0023880: Integration of grid "ncl" into the new testing system
[occt.git] / src / Draw / Draw_BasicCommands.cxx
1 // Created on: 1995-02-23
2 // Created by: Remi LEQUETTE
3 // Copyright (c) 1995-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <Standard_Macro.hxx>
18 #include <Standard_Stream.hxx>
19 #include <Standard_SStream.hxx>
20 #include <Standard_Version.hxx>
21
22 #include <Draw.ixx>
23 #include <Draw_Appli.hxx>
24 #include <Draw_Chronometer.hxx>
25 #include <Draw_Printer.hxx>
26
27 #include <Message.hxx>
28 #include <Message_Messenger.hxx>
29
30 #include <OSD_MemInfo.hxx>
31 #include <OSD_MAllocHook.hxx>
32 #include <OSD_Chronometer.hxx>
33 #include <OSD.hxx>
34 #include <OSD_Exception_CTRL_BREAK.hxx>
35 #include <OSD_PerfMeter.h>
36
37 #ifdef _WIN32
38
39 #include <windows.h>
40 #include <winbase.h>
41 #include <process.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <time.h>
45 #include <limits>
46
47 #define RLIM_INFINITY   0x7fffffff
48
49 static clock_t CPU_CURRENT; // cpu time already used at last
50                             // cpulimit call. (sec.) 
51 #else /* _WIN32 */
52
53 #include <sys/resource.h>
54 #include <signal.h>
55 #include <unistd.h>
56
57 #if defined (__hpux) || defined ( HPUX )
58 #define RLIM_INFINITY   0x7fffffff
59 #define RLIMIT_CPU      0
60 #endif
61
62 #endif /* _WIN32 */
63
64 extern Standard_Boolean Draw_Batch;
65
66 static clock_t CPU_LIMIT;   // Cpu_limit in Sec.
67 static OSD_Timer aTimer;
68
69 //=======================================================================
70 // chronom
71 //=======================================================================
72
73 extern Standard_Boolean Draw_Chrono;
74
75 static Standard_Integer chronom(Draw_Interpretor& di,
76                                 Standard_Integer n,const char** a)
77 {
78   if ((n == 1) || (*a[1] == '0') || (*a[1] == '1')) {
79     if (n == 1)
80       Draw_Chrono = !Draw_Chrono;
81     else
82       Draw_Chrono = (*a[1] == '1');
83
84     if (Draw_Chrono) di << "Chronometers activated."<<"\n";
85     else di << "Chronometers desactivated."<<"\n";
86   }
87   else {
88     Handle(Draw_Drawable3D) D = Draw::Get(a[1]);
89     Handle(Draw_Chronometer) C;
90     if (!D.IsNull()) {
91       C = Handle(Draw_Chronometer)::DownCast(D);
92     }
93     if (C.IsNull()) {
94       C = new Draw_Chronometer();
95     Draw::Set(a[1],C,Standard_False);
96     }
97     if (n <= 2) {
98       C->Timer().Reset();
99     }
100     else {
101       if (!strcasecmp(a[2],"reset"))
102         C->Timer().Reset();
103       if (!strcasecmp(a[2],"start"))
104         C->Timer().Start();
105       if (!strcasecmp(a[2],"stop"))
106         C->Timer().Stop();
107       if (!strcasecmp(a[2],"show"))
108         C->Timer().Show();
109     }
110   }
111   return 0;
112 }
113
114 static Standard_Integer dchronom(Draw_Interpretor& I,
115                                  Standard_Integer n,const char** a)
116 {
117   if ((n == 1) || (*a[1] == '0') || (*a[1] == '1')) {
118     if (n == 1)
119       Draw_Chrono = !Draw_Chrono;
120     else
121       Draw_Chrono = (*a[1] == '1');
122
123     if (Draw_Chrono) I << "Chronometers activated."<<"\n";
124     else I << "Chronometers desactivated."<<"\n";
125   }
126   else {
127     Handle(Draw_Drawable3D) D = Draw::Get(a[1]);
128     Handle(Draw_Chronometer) C;
129     if (!D.IsNull()) {
130       C = Handle(Draw_Chronometer)::DownCast(D);
131     }
132     if (C.IsNull()) {
133       C = new Draw_Chronometer();
134     Draw::Set(a[1],C,Standard_False);
135     }
136     if (n <= 2) {
137       C->Timer().Reset();
138     }
139     else {
140       if (!strcasecmp(a[2],"reset"))
141         C->Timer().Reset();
142       if (!strcasecmp(a[2],"start"))
143         C->Timer().Start();
144       if (!strcasecmp(a[2],"stop"))
145         C->Timer().Stop();
146       if (!strcasecmp(a[2],"show")) {
147         Standard_SStream ss;
148         C->Timer().Show(ss);
149         I << ss;
150       }
151     }
152   }
153   return 0;
154 }
155
156
157
158 //=======================================================================
159 //function : ifbatch
160 //purpose  : 
161 //=======================================================================
162
163 static Standard_Integer ifbatch(Draw_Interpretor& DI, Standard_Integer , const char** )
164 {
165   if (Draw_Batch)
166     DI << "1";
167   else
168     DI << "0";
169   
170   return 0;
171 }
172
173 //=======================================================================
174 //function : spy
175 //purpose  : 
176 //=======================================================================
177
178 extern Standard_Boolean Draw_Spying;
179 extern filebuf Draw_Spyfile;
180
181 static Standard_Integer spy(Draw_Interpretor& di, Standard_Integer n, const char** a)
182 {
183   if (Draw_Spying) 
184     Draw_Spyfile.close();
185   Draw_Spying = Standard_False;
186   if (n > 1) {
187     if (!Draw_Spyfile.open(a[1],ios::out)) {
188       di << "Cannot open "<<a[1]<<" for writing"<<"\n";
189       return 1;
190     }
191     Draw_Spying = Standard_True;
192   }
193   return 0;
194 }
195
196 static Standard_Integer dlog(Draw_Interpretor& di, Standard_Integer n, const char** a)
197 {
198   if (n != 2 && n != 3)
199   {
200     cout << "Enable or disable logging: " << a[0] << " {on|off}" << endl;
201     cout << "Reset log: " << a[0] << " reset" << endl;
202     cout << "Get log content: " << a[0] << " get" << endl;
203     return 1;
204   }
205
206   if (! strcmp (a[1], "on") && n == 2)
207   {
208     di.SetDoLog (Standard_True);
209 //    di.Log() << "dlog on" << endl; // for symmetry
210   }
211   else if (! strcmp (a[1], "off") && n == 2)
212   {
213     di.SetDoLog (Standard_False);
214   }
215   else if (! strcmp (a[1], "reset") && n == 2)
216   {
217     di.Log().str("");
218   }
219   else if (! strcmp (a[1], "get") && n == 2)
220   {
221     di << di.Log().str().c_str();
222   }
223   else if (! strcmp (a[1], "add") && n == 3)
224   {
225     di.Log() << a[2] << "\n";
226   }
227   else {
228     cout << "Unrecognized option(s): " << a[1] << endl;
229     return 1;
230   }
231   return 0;
232 }
233
234 static Standard_Integer decho(Draw_Interpretor& di, Standard_Integer n, const char** a)
235 {
236   if (n != 2)
237   {
238     cout << "Enable or disable echoing: " << a[0] << " {on|off}" << endl;
239     return 1;
240   }
241
242   if (! strcmp (a[1], "on"))
243   {
244     di.SetDoEcho (Standard_True);
245   }
246   else if (! strcmp (a[1], "off"))
247   {
248     di.SetDoEcho (Standard_False);
249   }
250   else {
251     cout << "Unrecognized option: " << a[1] << endl;
252     return 1;
253   }
254   return 0;
255 }
256
257 static Standard_Integer dbreak(Draw_Interpretor& di, Standard_Integer, const char**)
258 {
259   try {
260     OSD::ControlBreak();
261   }
262   catch (OSD_Exception_CTRL_BREAK) {
263     di << "User pressed Control-Break";
264     return 1; // Tcl exception
265   }
266
267   return 0;
268 }
269
270 static Standard_Integer dversion(Draw_Interpretor& di, Standard_Integer, const char**)
271 {
272   // print OCCT version and OCCTY-specific macros used
273   di << "Open CASCADE Technology " << OCC_VERSION_STRING_EXT << "\n";
274 #ifdef OCCT_DEBUG
275   di << "Extended debug mode\n";
276 #elif defined(_DEBUG)
277   di << "Debug mode\n";
278 #endif
279 #ifdef HAVE_TBB
280   di << "TBB enabled (HAVE_TBB)\n";
281 #else 
282   di << "TBB disabled\n";
283 #endif
284 #ifdef HAVE_GL2PS
285   di << "GL2PS enabled (HAVE_GL2PS)\n";
286 #else
287   di << "GL2PS disabled\n";
288 #endif
289 #ifdef HAVE_FREEIMAGE
290   di << "FreeImage enabled (HAVE_FREEIMAGE)\n";
291 #else
292   di << "FreeImage disabled\n";
293 #endif
294 #ifdef HAVE_OPENCL
295   di << "OpenCL enabled (HAVE_OPENCL)\n";
296 #else
297   di << "OpenCL disabled\n";
298 #endif
299 #ifdef HAVE_VTK
300   di << "VTK enabled (HAVE_VTK)\n";
301 #else
302   di << "VTK disabled\n";
303 #endif
304 #ifdef No_Exception
305   di << "Exceptions disabled (No_Exception)\n";
306 #else
307   di << "Exceptions enabled\n";
308 #endif
309
310   // check compiler, OS, etc. using pre-processor macros provided by compiler
311   // see "Pre-defined C/C++ Compiler Macros" http://sourceforge.net/p/predef/wiki/
312   // note that only modern compilers that are known to be used for OCCT are recognized
313
314   // compiler; note that GCC and MSVC are last as other compilers (e.g. Intel) can also define __GNUC__ and _MSC_VER
315 #if defined(__INTEL_COMPILER)
316   di << "Compiler: Intel " << __INTEL_COMPILER << "\n";
317 #elif defined(__BORLANDC__)
318   di << "Compiler: Borland C++ (__BORLANDC__ = " << __BORLANDC__ << ")\n";
319 #elif defined(__clang__)
320   di << "Compiler: Clang " << __clang_major__ << "." << __clang_minor__ << "." << __clang_patchlevel__ << "\n";
321 #elif defined(__SUNPRO_C)
322   di << "Compiler: Sun Studio (__SUNPRO_C = " << __SUNPROC_C << ")\n";
323 #elif defined(_MSC_VER)
324   di << "Compiler: MS Visual C++ " << (int)(_MSC_VER/100-6) << "." << (int)((_MSC_VER/10)-60-10*(int)(_MSC_VER/100-6)) << " (_MSC_FULL_VER = " << _MSC_FULL_VER << ")\n";
325 #elif defined(__GNUC__)
326   di << "Compiler: GCC " << __GNUC__ << "." << __GNUC_MINOR__ << "." << __GNUC_PATCHLEVEL__ << "\n";
327 #else
328   di << "Compiler: unrecognized\n";
329 #endif
330
331   // Cygwin and MinGW specifics
332 #if defined(__CYGWIN__)
333   di << "Cygwin\n";
334 #endif
335 #if defined(__MINGW64__)
336   di << "MinGW 64 " << __MINGW64_MAJOR_VERSION << "." << __MINGW64_MINOR_VERSION << "\n";
337 #elif defined(__MINGW32__)
338   di << "MinGW 32 " << __MINGW32_MAJOR_VERSION << "." << __MINGW32_MINOR_VERSION << "\n";
339 #endif 
340
341   // architecture
342 #if defined(__amd64) || defined(__x86_64) || defined(_M_AMD64)
343   di << "Architecture: AMD64\n";
344 #elif defined(__i386) || defined(_M_IX86) || defined(__X86__)|| defined(_X86_)
345   di << "Architecture: Intel x86\n";
346 #elif defined(_M_IA64) || defined(__ia64__)
347   di << "Architecture: Intel Itanium (IA 64)\n";
348 #elif defined(__sparc__) || defined(__sparc)
349   di << "Architecture: SPARC\n";
350 #else
351   di << "Architecture: unrecognized\n";
352 #endif
353
354   // OS
355 #if defined(_WIN32) || defined(__WINDOWS__) || defined(__WIN32__)
356   di << "OS: Windows\n";
357 #elif defined(__APPLE__) || defined(__MACH__)
358   di << "OS: Mac OS X\n";
359 #elif defined(__sun) 
360   di << "OS: SUN Solaris\n";
361 #elif defined(__ANDROID__) /* must be before Linux */
362   #include <android/api-level.h>
363   di << "OS: Android (__ANDROID_API__ = " << __ANDROID_API__ << ")\n";
364 #elif defined(__linux__)
365   di << "OS: Linux\n";
366 #elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
367   #include <sys/param.h>
368   di << "OS: BSD (BSD = " << BSD << ")\n";
369 #else
370   di << "OS: unrecognized\n";
371 #endif
372
373   return 0;
374 }
375
376 //=======================================================================
377 //function : wait
378 //purpose  : 
379 //=======================================================================
380
381 static Standard_Integer Draw_wait(Draw_Interpretor& , Standard_Integer n, const char** a)
382 {
383   Standard_Integer w = 10;
384   if (n > 1)
385     w = Draw::Atoi(a[1]);
386   time_t ct = time(NULL) + w;
387   while (time(NULL) < ct) {};
388   return 0;
389 }
390
391 //=======================================================================
392 //function : cpulimit
393 //purpose  : 
394 //=======================================================================
395 #ifdef _WIN32
396 static unsigned int __stdcall CpuFunc (void * /*param*/)
397 {
398   clock_t anElapCurrent;
399   clock_t aCurrent;
400
401   for(;;)
402   {
403     Sleep (5);
404     Standard_Real anUserSeconds, aSystemSeconds;
405     OSD_Chronometer::GetProcessCPU (anUserSeconds, aSystemSeconds);
406     aCurrent = clock_t(anUserSeconds + aSystemSeconds);
407     anElapCurrent = clock_t(aTimer.ElapsedTime());
408     
409     if ((aCurrent - CPU_CURRENT) >= CPU_LIMIT)
410     {
411       cout << "Process killed by CPU limit (" << CPU_LIMIT << " sec)" << endl;
412       aTimer.Stop();
413       ExitProcess (2);
414     }
415     if ((anElapCurrent) >= CPU_LIMIT)
416     {
417       cout << "Process killed by elapsed limit (" << CPU_LIMIT << " sec)" << endl;
418       aTimer.Stop();
419       ExitProcess (2);
420     }
421   }
422 }
423 #else
424 static void cpulimitSignalHandler (int)
425 {
426   cout << "Process killed by CPU limit  (" << CPU_LIMIT << " sec)" << endl;
427   exit(2);
428 }
429 static void *CpuFunc(void* /*threadarg*/)
430 {
431   clock_t anElapCurrent;
432   for(;;)
433   {
434     sleep (5);
435     anElapCurrent = clock_t(aTimer.ElapsedTime());
436     if ( CPU_LIMIT < 0 )
437       return NULL;
438     if ((anElapCurrent) >= CPU_LIMIT) {
439       cout << "Process killed by elapsed limit  (" << CPU_LIMIT << " sec)" << endl;
440       exit(2);
441     }
442   }
443   return NULL;
444 }
445 #endif
446
447 #ifdef _WIN32
448 static Standard_Integer cpulimit(Draw_Interpretor&, Standard_Integer n, const char** a)
449 {
450 #else
451 static Standard_Integer cpulimit(Draw_Interpretor& di, Standard_Integer n, const char** a)
452 {
453 #endif
454   static int aFirst = 1;
455 #ifdef _WIN32
456   // Windows specific code
457   unsigned int __stdcall CpuFunc (void *);
458   unsigned aThreadID;
459
460   if (n <= 1){
461     CPU_LIMIT = RLIM_INFINITY;
462   } else {
463     CPU_LIMIT = Draw::Atoi (a[1]);
464     Standard_Real anUserSeconds, aSystemSeconds;
465     OSD_Chronometer::GetProcessCPU (anUserSeconds, aSystemSeconds);
466     CPU_CURRENT = clock_t(anUserSeconds + aSystemSeconds);
467     aTimer.Reset();
468     aTimer.Start();
469     if (aFirst) // Launch the thread only at the 1st call.
470     {
471       aFirst = 0;
472       _beginthreadex (NULL, 0, CpuFunc, NULL, 0, &aThreadID);
473     }
474   }
475
476 #else 
477   // Unix & Linux
478   rlimit rlp;
479   rlp.rlim_max = RLIM_INFINITY;
480   if (n <= 1)
481     rlp.rlim_cur = RLIM_INFINITY;
482   else
483     rlp.rlim_cur = Draw::Atoi(a[1]);
484   CPU_LIMIT = rlp.rlim_cur;
485
486   int status;
487   status=setrlimit(RLIMIT_CPU,&rlp);
488   if (status !=0)
489     di << "status cpulimit setrlimit : " << status << "\n";
490
491   // set signal handler to print a message before death
492   struct sigaction act, oact;
493   memset (&act, 0, sizeof(act));
494   act.sa_handler = cpulimitSignalHandler;
495   sigaction (SIGXCPU, &act, &oact);
496
497   // cpulimit for elapsed time
498   aTimer.Reset();
499   aTimer.Start();
500   pthread_t cpulimitThread;
501   if (aFirst) // Launch the thread only at the 1st call.
502   {
503     aFirst = 0;
504     pthread_create(&cpulimitThread, NULL, CpuFunc, NULL);
505   }
506 #endif
507   return 0;
508 }
509
510
511 //=======================================================================
512 //function : mallochook
513 //purpose  : 
514 //=======================================================================
515
516 static Standard_Integer mallochook(Draw_Interpretor& di, Standard_Integer n,
517                                    const char** a)
518 {
519   if (n < 2)
520   {
521     di << "\
522 usage: mallochook cmd\n\
523 where cmd is one of:\n\
524   set [<op>]      - set callback to malloc/free; op is one of the following:\n\
525                     0 - set callback to NULL,\n\
526                     1 - set callback OSD_MAllocHook::CollectBySize (default)\n\
527                     2 - set callback OSD_MAllocHook::LogFileHandler\n\
528   reset           - reset the CollectBySize handler\n\
529   report1 [<outfile>]\n\
530                   - write report from CollectBySize handler in <outfile>\n\
531   open [<logfile>]\n\
532                   - open file for writing the log with LogFileHandler\n\
533   close           - close the log file with LogFileHandler\n\
534   report2 [<flag>] [<logfile>] [<outfile>]\n\
535                   - scan <logfile> written with LogFileHandler\n\
536                     and make synthesized report in <outfile>; <flag> can be:\n\
537                     0 - simple stats by sizes (default),\n\
538                     1 - with alive allocation numbers\n\
539 By default <logfile> is \"mem-log.txt\", <outfile> is \"mem-stat.txt\""
540       << "\n";
541     return 0;
542   }
543   if (strcmp(a[1], "set") == 0)
544   {
545     int aType = (n > 2 ? Draw::Atoi(a[2]) : 1);
546     if (aType < 0 || aType > 2)
547     {
548       di << "unknown op of the command set" << "\n";
549       return 1;
550     }
551     else if (aType == 0)
552     {
553       OSD_MAllocHook::SetCallback(NULL);
554       di << "callback is unset" << "\n";
555     }
556     else if (aType == 1)
557     {
558       OSD_MAllocHook::SetCallback(OSD_MAllocHook::GetCollectBySize());
559       di << "callback is set to CollectBySize" << "\n";
560     }
561     else //if (aType == 2)
562     {
563       OSD_MAllocHook::SetCallback(OSD_MAllocHook::GetLogFileHandler());
564       di << "callback is set to LogFileHandler" << "\n";
565     }
566   }
567   else if (strcmp(a[1], "reset") == 0)
568   {
569     OSD_MAllocHook::GetCollectBySize()->Reset();
570     di << "CollectBySize handler is reset" << "\n";
571   }
572   else if (strcmp(a[1], "open") == 0)
573   {
574     const char* aFileName = (n > 2 ? a[2] : "mem-log.txt");
575     if (!OSD_MAllocHook::GetLogFileHandler()->Open(aFileName))
576     {
577       di << "cannot create file " << aFileName << " for writing" << "\n";
578       return 1;
579     }
580     di << "log file " << aFileName << " is opened for writing" << "\n";
581   }
582   else if (strcmp(a[1], "close") == 0)
583   {
584     OSD_MAllocHook::GetLogFileHandler()->Close();
585     di << "log file is closed" << "\n";
586   }
587   else if (strcmp(a[1], "report1") == 0)
588   {
589     const char* aOutFile = "mem-stat.txt";
590     if (n > 2)
591       aOutFile = a[2];
592     if (OSD_MAllocHook::GetCollectBySize()->MakeReport(aOutFile))
593     {
594       di << "report " << aOutFile << " has been created" << "\n";
595     }
596     else
597     {
598       di << "cannot create report " << aOutFile << "\n";
599       return 1;
600     }
601   }
602   else if (strcmp(a[1], "report2") == 0)
603   {
604     Standard_Boolean includeAlive = Standard_False;
605     const char* aLogFile = "mem-log.txt";
606     const char* aOutFile = "mem-stat.txt";
607     if (n > 2)
608     {
609       includeAlive = (Draw::Atoi(a[2]) != 0);
610       if (n > 3)
611       {
612         aLogFile = a[3];
613         if (n > 4)
614           aOutFile = a[4];
615       }
616     }
617     if (OSD_MAllocHook::LogFileHandler::MakeReport(aLogFile, aOutFile, includeAlive))
618     {
619       di << "report " << aOutFile << " has been created" << "\n";
620     }
621     else
622     {
623       di << "cannot create report " << aOutFile << " from the log file "
624         << aLogFile << "\n";
625       return 1;
626     }
627   }
628   else
629   {
630     di << "unrecognized command " << a[1] << "\n";
631     return 1;
632   }
633   return 0;
634 }
635
636 //==============================================================================
637 //function : dlocale
638 //purpose  :
639 //==============================================================================
640
641 static int dlocale (Draw_Interpretor& di, Standard_Integer n, const char** argv)
642 {
643   int category = LC_ALL;
644   if (n > 1)
645   {
646     const char *cat = argv[1];
647     if ( ! strcmp (cat, "LC_ALL") ) category = LC_ALL;
648     else if ( ! strcmp (cat, "LC_COLLATE") ) category = LC_COLLATE;
649     else if ( ! strcmp (cat, "LC_CTYPE") ) category = LC_CTYPE;
650     else if ( ! strcmp (cat, "LC_MONETARY") ) category = LC_MONETARY;
651     else if ( ! strcmp (cat, "LC_NUMERIC") ) category = LC_NUMERIC;
652     else if ( ! strcmp (cat, "LC_TIME") ) category = LC_TIME;
653     else 
654     {
655       cout << "Error: cannot recognize argument " << cat << " as one of LC_ macros" << endl;
656       return 1;
657     }
658   }
659   const char* locale = (n > 2 ? argv[2] : NULL);
660   const char* result = setlocale (category, locale);
661   if (result)
662     di << result;
663   else 
664     cout << "Error: unsupported locale specification: " << locale << endl;
665   return 0;
666 }
667
668 //==============================================================================
669 //function : dmeminfo
670 //purpose  :
671 //==============================================================================
672
673 static int dmeminfo (Draw_Interpretor& theDI,
674                      Standard_Integer  theArgNb,
675                      const char**      theArgVec)
676 {
677   OSD_MemInfo aMemInfo;
678   if (theArgNb <= 1)
679   {
680     theDI << aMemInfo.ToString();
681     return 0;
682   }
683
684   for (Standard_Integer anIter = 1; anIter < theArgNb; ++anIter)
685   {
686     TCollection_AsciiString anArg (theArgVec[anIter]);
687     anArg.LowerCase();
688     if (anArg == "virt" || anArg == "v")
689     {
690       theDI << Standard_Real (aMemInfo.Value (OSD_MemInfo::MemVirtual)) << " ";
691     }
692     else if (anArg == "heap" || anArg == "h")
693     {
694       theDI << Standard_Real (aMemInfo.Value (OSD_MemInfo::MemHeapUsage)) << " ";
695     }
696     else if (anArg == "wset" || anArg == "w")
697     {
698       theDI << Standard_Real (aMemInfo.Value (OSD_MemInfo::MemWorkingSet)) << " ";
699     }
700     else if (anArg == "wsetpeak")
701     {
702       theDI << Standard_Real (aMemInfo.Value (OSD_MemInfo::MemWorkingSetPeak)) << " ";
703     }
704     else if (anArg == "swap")
705     {
706       theDI << Standard_Real (aMemInfo.Value (OSD_MemInfo::MemSwapUsage)) << " ";
707     }
708     else if (anArg == "swappeak")
709     {
710       theDI << Standard_Real (aMemInfo.Value (OSD_MemInfo::MemSwapUsagePeak)) << " ";
711     }
712     else if (anArg == "private")
713     {
714       theDI << Standard_Real (aMemInfo.Value (OSD_MemInfo::MemPrivate)) << " ";
715     }
716     else
717     {
718       std::cerr << "Unknown argument '" << theArgVec[anIter] << "'!\n";
719     }
720   }
721   theDI << "\n";
722   return 0;
723 }
724
725 //==============================================================================
726 //function : dperf
727 //purpose  :
728 //==============================================================================
729
730 static int dperf (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
731 {
732   // reset if argument is provided and it is not '0'
733   int reset = (theArgNb > 1 ? theArgVec[1][0] != '0' && theArgVec[1][0] != '\0' : 0);
734   char buffer[25600];
735   perf_sprint_all_meters (buffer, 25600 - 1, reset);
736   theDI << buffer;
737   return 0;
738 }
739
740 //==============================================================================
741 //function : dtracelevel
742 //purpose  :
743 //==============================================================================
744
745 static int dtracelevel (Draw_Interpretor& theDI,
746                         Standard_Integer  theArgNb,
747                         const char**      theArgVec)
748 {
749   Message_Gravity aLevel = Message_Info;
750   if (theArgNb < 1 || theArgNb > 2)
751   {
752     std::cout << "Error: wrong number of arguments! See usage:\n";
753     theDI.PrintHelp (theArgVec[0]);
754     return 1;
755   }
756   else if (theArgNb == 2)
757   {
758     TCollection_AsciiString aVal (theArgVec[1]);
759     aVal.LowerCase();
760     if (aVal == "trace")
761     {
762       aLevel = Message_Trace;
763     }
764     else if (aVal == "info")
765     {
766       aLevel = Message_Info;
767     }
768     else if (aVal == "warn"
769           || aVal == "warning")
770     {
771       aLevel = Message_Warning;
772     }
773     else if (aVal == "alarm")
774     {
775       aLevel = Message_Alarm;
776     }
777     else if (aVal == "fail")
778     {
779       aLevel = Message_Fail;
780     }
781     else
782     {
783       std::cout << "Error: unknown gravity '" << theArgVec[1] << "'!\n";
784       return 1;
785     }
786   }
787
788   Handle(Message_Messenger) aMessenger = Message::DefaultMessenger();
789   if (aMessenger.IsNull())
790   {
791     std::cout << "Error: default messenger is unavailable!\n";
792     return 1;
793   }
794
795   Message_SequenceOfPrinters& aPrinters = aMessenger->ChangePrinters();
796   if (aPrinters.Length() < 1)
797   {
798     std::cout << "Error: no printers registered in default Messenger!\n";
799     return 0;
800   }
801
802   for (Standard_Integer aPrinterIter = 1; aPrinterIter <= aPrinters.Length(); ++aPrinterIter)
803   {
804     Handle(Message_Printer)& aPrinter = aPrinters.ChangeValue (aPrinterIter);
805     if (theArgNb == 1)
806     {
807       if (aPrinterIter == 1)
808       {
809         aLevel = aPrinter->GetTraceLevel();
810       }
811       else if (aLevel == aPrinter->GetTraceLevel())
812       {
813         continue;
814       }
815
816       switch (aPrinter->GetTraceLevel())
817       {
818         case Message_Trace:   theDI << "trace"; break;
819         case Message_Info:    theDI << "info";  break;
820         case Message_Warning: theDI << "warn";  break;
821         case Message_Alarm:   theDI << "alarm"; break;
822         case Message_Fail:    theDI << "fail";  break;
823       }
824       continue;
825     }
826
827     aPrinter->SetTraceLevel (aLevel);
828   }
829
830   return 0;
831 }
832
833 void Draw::BasicCommands(Draw_Interpretor& theCommands)
834 {
835   static Standard_Boolean Done = Standard_False;
836   if (Done) return;
837   Done = Standard_True;
838
839   ios::sync_with_stdio();
840
841   const char* g = "DRAW General Commands";
842
843   theCommands.Add("batch", "returns 1 in batch mode",
844                   __FILE__,ifbatch,g);
845   theCommands.Add("spy","spy [file], Save commands in file. no file close",
846                   __FILE__,spy,g);
847   theCommands.Add("wait","wait [time(10)], wait time seconds",
848                   __FILE__,Draw_wait,g);
849   theCommands.Add("cpulimit","cpulimit [nbseconds], no args remove limits",
850                   __FILE__,cpulimit,g);
851   theCommands.Add("chrono","chrono [ name start/stop/reset/show]",
852                   __FILE__,chronom,g);
853   theCommands.Add("dchrono","dchrono [ name start/stop/reset/show]",
854                   __FILE__,dchronom,g);
855   theCommands.Add("mallochook",
856                   "debug memory allocation/deallocation, w/o args for help",
857                   __FILE__, mallochook, g);
858   theCommands.Add ("meminfo",
859     "meminfo [virt|v] [heap|h] [wset|w] [wsetpeak] [swap] [swappeak] [private]"
860     " : memory counters for this process",
861           __FILE__, dmeminfo, g);
862   theCommands.Add("dperf","dperf [reset] -- show performance counters, reset if argument is provided",
863                   __FILE__,dperf,g);
864
865   // Logging commands; note that their names are hard-coded in the code
866   // of Draw_Interpretor, thus should not be changed without update of that code!
867   theCommands.Add("dlog", "manage logging of commands and output; run without args to get help",
868                   __FILE__,dlog,g);
869   theCommands.Add("decho", "switch on / off echo of commands to cout; run without args to get help",
870                   __FILE__,decho,g);
871   theCommands.Add("dtracelevel", "dtracelevel [trace|info|warn|alarm|fail]",
872                   __FILE__, dtracelevel, g);
873
874   theCommands.Add("dbreak", "raises Tcl exception if user has pressed Control-Break key",
875                   __FILE__,dbreak,g);
876   theCommands.Add("dversion", "provides information on OCCT build configuration (version, compiler, OS, C library, etc.)",
877                   __FILE__,dversion,g);
878   theCommands.Add("dlocale", "set and / or query locate of C subsystem (function setlocale())",
879                   __FILE__,dlocale,g);
880 }