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