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
6 // This file is part of Open CASCADE Technology software library.
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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
19 #include <Draw_Appli.hxx>
20 #include <Draw_Chronometer.hxx>
21 #include <Draw_Drawable3D.hxx>
22 #include <Draw_Printer.hxx>
23 #include <Draw_ProgressIndicator.hxx>
24 #include <Message.hxx>
25 #include <Message_Messenger.hxx>
27 #include <OSD_Chronometer.hxx>
28 #include <OSD_Environment.hxx>
29 #include <OSD_Exception_CTRL_BREAK.hxx>
30 #include <OSD_MAllocHook.hxx>
31 #include <OSD_MemInfo.hxx>
32 #include <Standard_Macro.hxx>
33 #include <Standard_SStream.hxx>
34 #include <Standard_Stream.hxx>
35 #include <Standard_Version.hxx>
36 #include <TCollection_AsciiString.hxx>
38 #include <OSD_PerfMeter.h>
49 #define RLIM_INFINITY 0x7fffffff
51 static clock_t CPU_CURRENT; // cpu time already used at last
52 // cpulimit call. (sec.)
55 #include <sys/resource.h>
59 #if defined (__hpux) || defined ( HPUX )
60 #define RLIM_INFINITY 0x7fffffff
66 extern Standard_Boolean Draw_Batch;
68 static clock_t CPU_LIMIT; // Cpu_limit in Sec.
69 static OSD_Timer aTimer;
71 //=======================================================================
73 //=======================================================================
75 extern Standard_Boolean Draw_Chrono;
77 static Standard_Integer chronom(Draw_Interpretor& di,
78 Standard_Integer n,const char** a)
80 if ((n == 1) || (*a[1] == '0') || (*a[1] == '1')) {
82 Draw_Chrono = !Draw_Chrono;
84 Draw_Chrono = (*a[1] == '1');
86 if (Draw_Chrono) di << "Chronometers activated.\n";
87 else di << "Chronometers desactivated.\n";
90 Handle(Draw_Drawable3D) D = Draw::Get(a[1]);
91 Handle(Draw_Chronometer) C;
93 C = Handle(Draw_Chronometer)::DownCast(D);
96 C = new Draw_Chronometer();
97 Draw::Set(a[1],C,Standard_False);
103 if (!strcasecmp(a[2],"reset"))
105 if (!strcasecmp(a[2],"start"))
107 if (!strcasecmp(a[2],"stop"))
109 if (!strcasecmp(a[2],"show"))
116 static Standard_Integer dchronom(Draw_Interpretor& I,
117 Standard_Integer n,const char** a)
119 if ((n == 1) || (*a[1] == '0') || (*a[1] == '1')) {
121 Draw_Chrono = !Draw_Chrono;
123 Draw_Chrono = (*a[1] == '1');
125 if (Draw_Chrono) I << "Chronometers activated.\n";
126 else I << "Chronometers desactivated.\n";
129 Handle(Draw_Drawable3D) D = Draw::Get(a[1]);
130 Handle(Draw_Chronometer) C;
132 C = Handle(Draw_Chronometer)::DownCast(D);
135 C = new Draw_Chronometer();
136 Draw::Set(a[1],C,Standard_False);
142 if (!strcasecmp(a[2],"reset"))
144 if (!strcasecmp(a[2],"start"))
146 if (!strcasecmp(a[2],"stop"))
148 if (!strcasecmp(a[2],"show")) {
160 //=======================================================================
163 //=======================================================================
165 static Standard_Integer ifbatch(Draw_Interpretor& DI, Standard_Integer , const char** )
175 //=======================================================================
178 //=======================================================================
180 extern Standard_Boolean Draw_Spying;
181 extern filebuf Draw_Spyfile;
183 static Standard_Integer spy(Draw_Interpretor& di, Standard_Integer n, const char** a)
186 Draw_Spyfile.close();
187 Draw_Spying = Standard_False;
189 if (!Draw_Spyfile.open(a[1],ios::out)) {
190 di << "Cannot open "<<a[1]<<" for writing\n";
193 Draw_Spying = Standard_True;
198 static Standard_Integer dlog(Draw_Interpretor& di, Standard_Integer n, const char** a)
200 if (n != 2 && n != 3)
202 cout << "Enable or disable logging: " << a[0] << " {on|off}" << endl;
203 cout << "Reset log: " << a[0] << " reset" << endl;
204 cout << "Get log content: " << a[0] << " get" << endl;
208 if (! strcmp (a[1], "on") && n == 2)
210 di.SetDoLog (Standard_True);
211 // di.Log() << "dlog on" << endl; // for symmetry
213 else if (! strcmp (a[1], "off") && n == 2)
215 di.SetDoLog (Standard_False);
217 else if (! strcmp (a[1], "reset") && n == 2)
221 else if (! strcmp (a[1], "get") && n == 2)
223 di << di.Log().str().c_str();
225 else if (! strcmp (a[1], "add") && n == 3)
227 di.Log() << a[2] << "\n";
230 cout << "Unrecognized option(s): " << a[1] << endl;
236 static Standard_Integer decho(Draw_Interpretor& di, Standard_Integer n, const char** a)
240 cout << "Enable or disable echoing: " << a[0] << " {on|off}" << endl;
244 if (! strcmp (a[1], "on"))
246 di.SetDoEcho (Standard_True);
248 else if (! strcmp (a[1], "off"))
250 di.SetDoEcho (Standard_False);
253 cout << "Unrecognized option: " << a[1] << endl;
259 static Standard_Integer dbreak(Draw_Interpretor& di, Standard_Integer, const char**)
264 catch (OSD_Exception_CTRL_BREAK) {
265 di << "User pressed Control-Break";
266 return 1; // Tcl exception
272 static Standard_Integer dversion(Draw_Interpretor& di, Standard_Integer, const char**)
274 // print OCCT version and OCCTY-specific macros used
275 di << "Open CASCADE Technology " << OCC_VERSION_STRING_EXT << "\n";
277 di << "Extended debug mode\n";
278 #elif defined(_DEBUG)
279 di << "Debug mode\n";
282 di << "TBB enabled (HAVE_TBB)\n";
284 di << "TBB disabled\n";
287 di << "GL2PS enabled (HAVE_GL2PS)\n";
289 di << "GL2PS disabled\n";
291 #ifdef HAVE_FREEIMAGE
292 di << "FreeImage enabled (HAVE_FREEIMAGE)\n";
294 di << "FreeImage disabled\n";
297 di << "OpenCL enabled (HAVE_OPENCL)\n";
299 di << "OpenCL disabled\n";
302 di << "VTK enabled (HAVE_VTK)\n";
304 di << "VTK disabled\n";
307 di << "Exceptions disabled (No_Exception)\n";
309 di << "Exceptions enabled\n";
312 // check compiler, OS, etc. using pre-processor macros provided by compiler
313 // see "Pre-defined C/C++ Compiler Macros" http://sourceforge.net/p/predef/wiki/
314 // note that only modern compilers that are known to be used for OCCT are recognized
316 // compiler; note that GCC and MSVC are last as other compilers (e.g. Intel) can also define __GNUC__ and _MSC_VER
317 #if defined(__INTEL_COMPILER)
318 di << "Compiler: Intel " << __INTEL_COMPILER << "\n";
319 #elif defined(__BORLANDC__)
320 di << "Compiler: Borland C++ (__BORLANDC__ = " << __BORLANDC__ << ")\n";
321 #elif defined(__clang__)
322 di << "Compiler: Clang " << __clang_major__ << "." << __clang_minor__ << "." << __clang_patchlevel__ << "\n";
323 #elif defined(__SUNPRO_C)
324 di << "Compiler: Sun Studio (__SUNPRO_C = " << __SUNPROC_C << ")\n";
325 #elif defined(_MSC_VER)
326 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";
327 #elif defined(__GNUC__)
328 di << "Compiler: GCC " << __GNUC__ << "." << __GNUC_MINOR__ << "." << __GNUC_PATCHLEVEL__ << "\n";
330 di << "Compiler: unrecognized\n";
333 // Cygwin and MinGW specifics
334 #if defined(__CYGWIN__)
337 #if defined(__MINGW64__)
338 di << "MinGW 64 " << __MINGW64_VERSION_MAJOR << "." << __MINGW64_VERSION_MINOR << "\n";
339 #elif defined(__MINGW32__)
340 di << "MinGW 32 " << __MINGW32_MAJOR_VERSION << "." << __MINGW32_MINOR_VERSION << "\n";
344 #if defined(__amd64) || defined(__x86_64) || defined(_M_AMD64)
345 di << "Architecture: AMD64\n";
346 #elif defined(__i386) || defined(_M_IX86) || defined(__X86__)|| defined(_X86_)
347 di << "Architecture: Intel x86\n";
348 #elif defined(_M_IA64) || defined(__ia64__)
349 di << "Architecture: Intel Itanium (IA 64)\n";
350 #elif defined(__sparc__) || defined(__sparc)
351 di << "Architecture: SPARC\n";
353 di << "Architecture: unrecognized\n";
357 #if defined(_WIN32) || defined(__WINDOWS__) || defined(__WIN32__)
358 di << "OS: Windows\n";
359 #elif defined(__APPLE__) || defined(__MACH__)
360 di << "OS: Mac OS X\n";
362 di << "OS: SUN Solaris\n";
363 #elif defined(__ANDROID__) /* must be before Linux */
364 #include <android/api-level.h>
365 di << "OS: Android (__ANDROID_API__ = " << __ANDROID_API__ << ")\n";
366 #elif defined(__QNXNTO__)
367 di << "OS: QNX Neutrino\n";
368 #elif defined(__QNX__)
370 #elif defined(__linux__)
372 #elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
373 #include <sys/param.h>
374 di << "OS: BSD (BSD = " << BSD << ")\n";
376 di << "OS: unrecognized\n";
382 //=======================================================================
385 //=======================================================================
387 static Standard_Integer Draw_wait(Draw_Interpretor& , Standard_Integer n, const char** a)
389 Standard_Integer w = 10;
391 w = Draw::Atoi(a[1]);
392 time_t ct = time(NULL) + w;
393 while (time(NULL) < ct) {};
397 //=======================================================================
398 //function : cpulimit
400 //=======================================================================
402 static unsigned int __stdcall CpuFunc (void * /*param*/)
404 clock_t anElapCurrent;
410 Standard_Real anUserSeconds, aSystemSeconds;
411 OSD_Chronometer::GetProcessCPU (anUserSeconds, aSystemSeconds);
412 aCurrent = clock_t(anUserSeconds + aSystemSeconds);
413 anElapCurrent = clock_t(aTimer.ElapsedTime());
415 if (CPU_LIMIT > 0 && (aCurrent - CPU_CURRENT) >= CPU_LIMIT)
417 cout << "Process killed by CPU limit (" << CPU_LIMIT << " sec)" << endl;
421 if (CPU_LIMIT > 0 && anElapCurrent >= CPU_LIMIT)
423 cout << "Process killed by elapsed limit (" << CPU_LIMIT << " sec)" << endl;
430 static void cpulimitSignalHandler (int)
432 cout << "Process killed by CPU limit (" << CPU_LIMIT << " sec)" << endl;
435 static void *CpuFunc(void* /*threadarg*/)
437 clock_t anElapCurrent;
441 anElapCurrent = clock_t(aTimer.ElapsedTime());
442 if (CPU_LIMIT >0 && (anElapCurrent) >= CPU_LIMIT) {
443 cout << "Process killed by elapsed limit (" << CPU_LIMIT << " sec)" << endl;
452 static Standard_Integer cpulimit(Draw_Interpretor&, Standard_Integer n, const char** a)
455 static Standard_Integer cpulimit(Draw_Interpretor& di, Standard_Integer n, const char** a)
458 static int aFirst = 1;
460 // Windows specific code
461 unsigned int __stdcall CpuFunc (void *);
465 CPU_LIMIT = RLIM_INFINITY;
467 CPU_LIMIT = Draw::Atoi (a[1]);
468 Standard_Real anUserSeconds, aSystemSeconds;
469 OSD_Chronometer::GetProcessCPU (anUserSeconds, aSystemSeconds);
470 CPU_CURRENT = clock_t(anUserSeconds + aSystemSeconds);
473 if (aFirst) // Launch the thread only at the 1st call.
476 _beginthreadex (NULL, 0, CpuFunc, NULL, 0, &aThreadID);
483 rlp.rlim_max = RLIM_INFINITY;
485 rlp.rlim_cur = RLIM_INFINITY;
487 rlp.rlim_cur = Draw::Atoi(a[1]);
488 CPU_LIMIT = rlp.rlim_cur;
491 status=setrlimit(RLIMIT_CPU,&rlp);
493 di << "status cpulimit setrlimit : " << status << "\n";
495 // set signal handler to print a message before death
496 struct sigaction act, oact;
497 memset (&act, 0, sizeof(act));
498 act.sa_handler = cpulimitSignalHandler;
499 sigaction (SIGXCPU, &act, &oact);
501 // cpulimit for elapsed time
504 pthread_t cpulimitThread;
505 if (aFirst) // Launch the thread only at the 1st call.
508 pthread_create(&cpulimitThread, NULL, CpuFunc, NULL);
515 //=======================================================================
516 //function : mallochook
518 //=======================================================================
520 static Standard_Integer mallochook(Draw_Interpretor& di, Standard_Integer n,
526 usage: mallochook cmd\n\
527 where cmd is one of:\n\
528 set [<op>] - set callback to malloc/free; op is one of the following:\n\
529 0 - set callback to NULL,\n\
530 1 - set callback OSD_MAllocHook::CollectBySize (default)\n\
531 2 - set callback OSD_MAllocHook::LogFileHandler\n\
532 reset - reset the CollectBySize handler\n\
533 report1 [<outfile>]\n\
534 - write report from CollectBySize handler in <outfile>\n\
536 - open file for writing the log with LogFileHandler\n\
537 close - close the log file with LogFileHandler\n\
538 report2 [<flag>] [<logfile>] [<outfile>]\n\
539 - scan <logfile> written with LogFileHandler\n\
540 and make synthesized report in <outfile>; <flag> can be:\n\
541 0 - simple stats by sizes (default),\n\
542 1 - with alive allocation numbers\n\
543 By default <logfile> is \"mem-log.txt\", <outfile> is \"mem-stat.txt\""
547 if (strcmp(a[1], "set") == 0)
549 int aType = (n > 2 ? Draw::Atoi(a[2]) : 1);
550 if (aType < 0 || aType > 2)
552 di << "unknown op of the command set\n";
557 OSD_MAllocHook::SetCallback(NULL);
558 di << "callback is unset\n";
562 OSD_MAllocHook::SetCallback(OSD_MAllocHook::GetCollectBySize());
563 di << "callback is set to CollectBySize\n";
565 else //if (aType == 2)
567 OSD_MAllocHook::SetCallback(OSD_MAllocHook::GetLogFileHandler());
568 di << "callback is set to LogFileHandler\n";
571 else if (strcmp(a[1], "reset") == 0)
573 OSD_MAllocHook::GetCollectBySize()->Reset();
574 di << "CollectBySize handler is reset\n";
576 else if (strcmp(a[1], "open") == 0)
578 const char* aFileName = (n > 2 ? a[2] : "mem-log.txt");
579 if (!OSD_MAllocHook::GetLogFileHandler()->Open(aFileName))
581 di << "cannot create file " << aFileName << " for writing\n";
584 di << "log file " << aFileName << " is opened for writing\n";
586 else if (strcmp(a[1], "close") == 0)
588 OSD_MAllocHook::GetLogFileHandler()->Close();
589 di << "log file is closed\n";
591 else if (strcmp(a[1], "report1") == 0)
593 const char* aOutFile = "mem-stat.txt";
596 if (OSD_MAllocHook::GetCollectBySize()->MakeReport(aOutFile))
598 di << "report " << aOutFile << " has been created\n";
602 di << "cannot create report " << aOutFile << "\n";
606 else if (strcmp(a[1], "report2") == 0)
608 Standard_Boolean includeAlive = Standard_False;
609 const char* aLogFile = "mem-log.txt";
610 const char* aOutFile = "mem-stat.txt";
613 includeAlive = (Draw::Atoi(a[2]) != 0);
621 if (OSD_MAllocHook::LogFileHandler::MakeReport(aLogFile, aOutFile, includeAlive))
623 di << "report " << aOutFile << " has been created\n";
627 di << "cannot create report " << aOutFile << " from the log file "
634 di << "unrecognized command " << a[1] << "\n";
640 //==============================================================================
643 //==============================================================================
645 static int dlocale (Draw_Interpretor& di, Standard_Integer n, const char** argv)
647 int category = LC_ALL;
650 const char *cat = argv[1];
651 if ( ! strcmp (cat, "LC_ALL") ) category = LC_ALL;
652 else if ( ! strcmp (cat, "LC_COLLATE") ) category = LC_COLLATE;
653 else if ( ! strcmp (cat, "LC_CTYPE") ) category = LC_CTYPE;
654 else if ( ! strcmp (cat, "LC_MONETARY") ) category = LC_MONETARY;
655 else if ( ! strcmp (cat, "LC_NUMERIC") ) category = LC_NUMERIC;
656 else if ( ! strcmp (cat, "LC_TIME") ) category = LC_TIME;
659 cout << "Error: cannot recognize argument " << cat << " as one of LC_ macros" << endl;
663 const char* locale = (n > 2 ? argv[2] : NULL);
664 const char* result = setlocale (category, locale);
668 cout << "Error: unsupported locale specification: " << locale << endl;
672 //==============================================================================
673 //function : dmeminfo
675 //==============================================================================
677 static int dmeminfo (Draw_Interpretor& theDI,
678 Standard_Integer theArgNb,
679 const char** theArgVec)
681 OSD_MemInfo aMemInfo;
684 theDI << aMemInfo.ToString();
688 for (Standard_Integer anIter = 1; anIter < theArgNb; ++anIter)
690 TCollection_AsciiString anArg (theArgVec[anIter]);
692 if (anArg == "virt" || anArg == "v")
694 theDI << Standard_Real (aMemInfo.Value (OSD_MemInfo::MemVirtual)) << " ";
696 else if (anArg == "heap" || anArg == "h")
698 theDI << Standard_Real (aMemInfo.Value (OSD_MemInfo::MemHeapUsage)) << " ";
700 else if (anArg == "wset" || anArg == "w")
702 theDI << Standard_Real (aMemInfo.Value (OSD_MemInfo::MemWorkingSet)) << " ";
704 else if (anArg == "wsetpeak")
706 theDI << Standard_Real (aMemInfo.Value (OSD_MemInfo::MemWorkingSetPeak)) << " ";
708 else if (anArg == "swap")
710 theDI << Standard_Real (aMemInfo.Value (OSD_MemInfo::MemSwapUsage)) << " ";
712 else if (anArg == "swappeak")
714 theDI << Standard_Real (aMemInfo.Value (OSD_MemInfo::MemSwapUsagePeak)) << " ";
716 else if (anArg == "private")
718 theDI << Standard_Real (aMemInfo.Value (OSD_MemInfo::MemPrivate)) << " ";
722 std::cerr << "Unknown argument '" << theArgVec[anIter] << "'!\n";
729 //==============================================================================
732 //==============================================================================
734 static int dperf (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
736 // reset if argument is provided and it is not '0'
737 int reset = (theArgNb > 1 ? theArgVec[1][0] != '0' && theArgVec[1][0] != '\0' : 0);
739 perf_sprint_all_meters (buffer, 25600 - 1, reset);
744 //==============================================================================
745 //function : dsetsignal
747 //==============================================================================
749 static int dsetsignal (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
751 // arm FPE handler if argument is provided and its first symbol is not '0'
752 // or if environment variable CSF_FPE is set and its first symbol is not '0'
756 setFPE = (theArgVec[1][0] == '1' || theArgVec[1][0] == 't');
760 OSD_Environment aEnv ("CSF_FPE");
761 TCollection_AsciiString aEnvStr = aEnv.Value();
762 setFPE = (! aEnvStr.IsEmpty() && aEnvStr.Value(1) != '0');
764 OSD::SetSignal (setFPE);
765 theDI << "Signal handlers are set, with FPE " << (setFPE ? "armed" : "disarmed");
769 //==============================================================================
770 //function : dtracelevel
772 //==============================================================================
774 static int dtracelevel (Draw_Interpretor& theDI,
775 Standard_Integer theArgNb,
776 const char** theArgVec)
778 Message_Gravity aLevel = Message_Info;
779 if (theArgNb < 1 || theArgNb > 2)
781 std::cout << "Error: wrong number of arguments! See usage:\n";
782 theDI.PrintHelp (theArgVec[0]);
785 else if (theArgNb == 2)
787 TCollection_AsciiString aVal (theArgVec[1]);
791 aLevel = Message_Trace;
793 else if (aVal == "info")
795 aLevel = Message_Info;
797 else if (aVal == "warn"
798 || aVal == "warning")
800 aLevel = Message_Warning;
802 else if (aVal == "alarm")
804 aLevel = Message_Alarm;
806 else if (aVal == "fail")
808 aLevel = Message_Fail;
812 std::cout << "Error: unknown gravity '" << theArgVec[1] << "'!\n";
817 Handle(Message_Messenger) aMessenger = Message::DefaultMessenger();
818 if (aMessenger.IsNull())
820 std::cout << "Error: default messenger is unavailable!\n";
824 Message_SequenceOfPrinters& aPrinters = aMessenger->ChangePrinters();
825 if (aPrinters.Length() < 1)
827 std::cout << "Error: no printers registered in default Messenger!\n";
831 for (Standard_Integer aPrinterIter = 1; aPrinterIter <= aPrinters.Length(); ++aPrinterIter)
833 Handle(Message_Printer)& aPrinter = aPrinters.ChangeValue (aPrinterIter);
836 if (aPrinterIter == 1)
838 aLevel = aPrinter->GetTraceLevel();
840 else if (aLevel == aPrinter->GetTraceLevel())
845 switch (aPrinter->GetTraceLevel())
847 case Message_Trace: theDI << "trace"; break;
848 case Message_Info: theDI << "info"; break;
849 case Message_Warning: theDI << "warn"; break;
850 case Message_Alarm: theDI << "alarm"; break;
851 case Message_Fail: theDI << "fail"; break;
856 aPrinter->SetTraceLevel (aLevel);
862 void Draw::BasicCommands(Draw_Interpretor& theCommands)
864 static Standard_Boolean Done = Standard_False;
866 Done = Standard_True;
868 ios::sync_with_stdio();
870 const char* g = "DRAW General Commands";
872 theCommands.Add("batch", "returns 1 in batch mode",
874 theCommands.Add("spy","spy [file], Save commands in file. no file close",
876 theCommands.Add("wait","wait [time(10)], wait time seconds",
877 __FILE__,Draw_wait,g);
878 theCommands.Add("cpulimit","cpulimit [nbseconds], no args remove limits",
879 __FILE__,cpulimit,g);
880 theCommands.Add("chrono","chrono [ name start/stop/reset/show]",
882 theCommands.Add("dchrono","dchrono [ name start/stop/reset/show]",
883 __FILE__,dchronom,g);
884 theCommands.Add("mallochook",
885 "debug memory allocation/deallocation, w/o args for help",
886 __FILE__, mallochook, g);
887 theCommands.Add ("meminfo",
888 "meminfo [virt|v] [heap|h] [wset|w] [wsetpeak] [swap] [swappeak] [private]"
889 " : memory counters for this process",
890 __FILE__, dmeminfo, g);
891 theCommands.Add("dperf","dperf [reset] -- show performance counters, reset if argument is provided",
893 theCommands.Add("dsetsignal","dsetsignal [fpe=0] -- set OSD signal handler, with FPE option if argument is given",
894 __FILE__,dsetsignal,g);
896 // Logging commands; note that their names are hard-coded in the code
897 // of Draw_Interpretor, thus should not be changed without update of that code!
898 theCommands.Add("dlog", "manage logging of commands and output; run without args to get help",
900 theCommands.Add("decho", "switch on / off echo of commands to cout; run without args to get help",
902 theCommands.Add("dtracelevel", "dtracelevel [trace|info|warn|alarm|fail]",
903 __FILE__, dtracelevel, g);
905 theCommands.Add("dbreak", "raises Tcl exception if user has pressed Control-Break key",
907 theCommands.Add("dversion", "provides information on OCCT build configuration (version, compiler, OS, C library, etc.)",
908 __FILE__,dversion,g);
909 theCommands.Add("dlocale", "set and / or query locate of C subsystem (function setlocale())",