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