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 <OSD_Parallel.hxx>
33 #include <OSD_ThreadPool.hxx>
34 #include <Standard_Macro.hxx>
35 #include <Standard_SStream.hxx>
36 #include <Standard_Stream.hxx>
37 #include <Standard_Version.hxx>
38 #include <TCollection_AsciiString.hxx>
40 #include <OSD_PerfMeter.h>
51 #define RLIM_INFINITY 0x7fffffff
53 static clock_t CPU_CURRENT; // cpu time already used at last
54 // cpulimit call. (sec.)
57 #include <sys/resource.h>
61 #if defined (__hpux) || defined ( HPUX )
62 #define RLIM_INFINITY 0x7fffffff
68 extern Standard_Boolean Draw_Batch;
70 static clock_t CPU_LIMIT; // Cpu_limit in Sec.
71 static OSD_Timer aTimer;
73 //=======================================================================
75 //=======================================================================
77 extern Standard_Boolean Draw_Chrono;
79 static Standard_Integer chronom(Draw_Interpretor& di,
80 Standard_Integer n,const char** a)
82 if ((n == 1) || (*a[1] == '0') || (*a[1] == '1')) {
84 Draw_Chrono = !Draw_Chrono;
86 Draw_Chrono = (*a[1] == '1');
88 if (Draw_Chrono) di << "Chronometers activated.\n";
89 else di << "Chronometers desactivated.\n";
92 Handle(Draw_Drawable3D) D = Draw::Get(a[1]);
93 Handle(Draw_Chronometer) C;
95 C = Handle(Draw_Chronometer)::DownCast(D);
98 C = new Draw_Chronometer();
99 Draw::Set(a[1],C,Standard_False);
105 for (Standard_Integer anIter = 2; anIter < n; ++anIter)
107 TCollection_AsciiString anArg (a[anIter]);
110 if (anArg == "reset")
114 else if (anArg == "restart")
116 C->Timer().Restart();
118 else if (anArg == "start")
122 else if (anArg == "stop")
126 else if (anArg == "show")
130 else if (anArg == "counter")
132 Standard_Real aSeconds,aCPUtime;
133 Standard_Integer aMinutes, aHours;
134 C->Timer().Show(aSeconds,aMinutes,aHours,aCPUtime);
135 std::cout << "COUNTER " << a[++anIter] << ": " << aCPUtime << "\n";
139 std::cerr << "Unknown argument '" << a[anIter] << "'!\n";
147 static Standard_Integer dchronom(Draw_Interpretor& theDI,
148 Standard_Integer n,const char** a)
150 if ((n == 1) || (*a[1] == '0') || (*a[1] == '1')) {
152 Draw_Chrono = !Draw_Chrono;
154 Draw_Chrono = (*a[1] == '1');
156 if (Draw_Chrono) theDI << "Chronometers activated.\n";
157 else theDI << "Chronometers desactivated.\n";
160 Handle(Draw_Drawable3D) D = Draw::Get(a[1]);
161 Handle(Draw_Chronometer) C;
163 C = Handle(Draw_Chronometer)::DownCast(D);
166 C = new Draw_Chronometer();
167 Draw::Set(a[1],C,Standard_False);
173 for (Standard_Integer anIter = 2; anIter < n; ++anIter)
175 TCollection_AsciiString anArg (a[anIter]);
178 if (anArg == "reset")
182 else if (anArg == "restart")
184 C->Timer().Restart();
186 else if (anArg == "start")
190 else if (anArg == "stop")
194 else if (anArg == "show")
200 else if (anArg == "counter")
202 Standard_Real aSeconds,aCPUtime;
203 Standard_Integer aMinutes, aHours;
204 C->Timer().Show(aSeconds,aMinutes,aHours,aCPUtime);
205 theDI << "COUNTER " << a[++anIter] << ": " << aCPUtime << "\n";
209 theDI << "Unknown argument '" << a[anIter] << "'!\n";
219 //=======================================================================
222 //=======================================================================
224 static Standard_Integer ifbatch(Draw_Interpretor& DI, Standard_Integer , const char** )
234 //=======================================================================
237 //=======================================================================
239 extern Standard_Boolean Draw_Spying;
240 extern std::filebuf Draw_Spyfile;
242 static Standard_Integer spy(Draw_Interpretor& di, Standard_Integer n, const char** a)
245 Draw_Spyfile.close();
246 Draw_Spying = Standard_False;
248 if (!Draw_Spyfile.open(a[1],std::ios::out)) {
249 di << "Cannot open "<<a[1]<<" for writing\n";
252 Draw_Spying = Standard_True;
257 static Standard_Integer dlog(Draw_Interpretor& di, Standard_Integer n, const char** a)
259 if (n != 2 && n != 3)
261 std::cout << "Enable or disable logging: " << a[0] << " {on|off}" << std::endl;
262 std::cout << "Reset log: " << a[0] << " reset" << std::endl;
263 std::cout << "Get log content: " << a[0] << " get" << std::endl;
267 if (! strcmp (a[1], "on") && n == 2)
269 di.SetDoLog (Standard_True);
270 // di.Log() << "dlog on" << std::endl; // for symmetry
272 else if (! strcmp (a[1], "off") && n == 2)
274 di.SetDoLog (Standard_False);
276 else if (! strcmp (a[1], "reset") && n == 2)
280 else if (! strcmp (a[1], "get") && n == 2)
284 else if (! strcmp (a[1], "add") && n == 3)
289 else if (! strcmp (a[1], "status") && n == 2)
291 di << (di.GetDoLog() ? "on" : "off");
294 std::cout << "Unrecognized option(s): " << a[1] << std::endl;
300 static Standard_Integer decho(Draw_Interpretor& di, Standard_Integer n, const char** a)
304 std::cout << "Enable or disable echoing: " << a[0] << " {on|off}" << std::endl;
308 if (! strcmp (a[1], "on"))
310 di.SetDoEcho (Standard_True);
312 else if (! strcmp (a[1], "off"))
314 di.SetDoEcho (Standard_False);
317 std::cout << "Unrecognized option: " << a[1] << std::endl;
323 static Standard_Integer dbreak(Draw_Interpretor& di, Standard_Integer, const char**)
328 catch (OSD_Exception_CTRL_BREAK const&) {
329 di << "User pressed Control-Break";
330 return 1; // Tcl exception
336 static Standard_Integer dversion(Draw_Interpretor& di, Standard_Integer, const char**)
338 // print OCCT version and OCCTY-specific macros used
339 di << "Open CASCADE Technology " << OCC_VERSION_STRING_EXT << "\n";
341 di << "Extended debug mode\n";
342 #elif defined(_DEBUG)
343 di << "Debug mode\n";
346 di << "TBB enabled (HAVE_TBB)\n";
348 di << "TBB disabled\n";
350 #ifdef HAVE_FREEIMAGE
351 di << "FreeImage enabled (HAVE_FREEIMAGE)\n";
353 di << "FreeImage disabled\n";
356 di << "FFmpeg enabled (HAVE_FFMPEG)\n";
358 di << "FFmpeg disabled\n";
361 di << "OpenGL: ES2\n";
363 di << "OpenGL: desktop\n";
366 di << "OpenVR enabled (HAVE_OPENVR)\n";
368 di << "OpenVR disabled\n";
370 #ifdef HAVE_RAPIDJSON
371 di << "RapidJSON enabled (HAVE_RAPIDJSON)\n";
373 di << "RapidJSON disabled\n";
376 di << "VTK enabled (HAVE_VTK)\n";
378 di << "VTK disabled\n";
381 di << "Exceptions disabled (No_Exception)\n";
383 di << "Exceptions enabled\n";
386 // check compiler, OS, etc. using pre-processor macros provided by compiler
387 // see "Pre-defined C/C++ Compiler Macros" http://sourceforge.net/p/predef/wiki/
388 // note that only modern compilers that are known to be used for OCCT are recognized
390 // compiler; note that GCC and MSVC are last as other compilers (e.g. Intel) can also define __GNUC__ and _MSC_VER
391 #if defined(__INTEL_COMPILER)
392 di << "Compiler: Intel " << __INTEL_COMPILER << "\n";
393 #elif defined(__BORLANDC__)
394 di << "Compiler: Borland C++ (__BORLANDC__ = " << __BORLANDC__ << ")\n";
395 #elif defined(__clang__)
396 di << "Compiler: Clang " << __clang_major__ << "." << __clang_minor__ << "." << __clang_patchlevel__ << "\n";
397 #elif defined(__SUNPRO_C)
398 di << "Compiler: Sun Studio (__SUNPRO_C = " << __SUNPROC_C << ")\n";
399 #elif defined(_MSC_VER)
401 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";
403 di << "Compiler: MS Visual C++ " << (int)(_MSC_VER/100-5) << "." << (int)((_MSC_VER/10)-50-10*(int)(_MSC_VER/100-5)) << " (_MSC_FULL_VER = " << _MSC_FULL_VER << ")\n";
405 #elif defined(__GNUC__)
406 di << "Compiler: GCC " << __GNUC__ << "." << __GNUC_MINOR__ << "." << __GNUC_PATCHLEVEL__ << "\n";
408 di << "Compiler: unrecognized\n";
411 // Cygwin and MinGW specifics
412 #if defined(__CYGWIN__)
415 #if defined(__MINGW64__)
416 di << "MinGW 64 " << __MINGW64_VERSION_MAJOR << "." << __MINGW64_VERSION_MINOR << "\n";
417 #elif defined(__MINGW32__)
418 di << "MinGW 32 " << __MINGW32_MAJOR_VERSION << "." << __MINGW32_MINOR_VERSION << "\n";
422 #if defined(__amd64) || defined(__x86_64) || defined(_M_AMD64)
423 di << "Architecture: AMD64\n";
424 #elif defined(__i386) || defined(_M_IX86) || defined(__X86__)|| defined(_X86_)
425 di << "Architecture: Intel x86\n";
426 #elif defined(_M_IA64) || defined(__ia64__)
427 di << "Architecture: Intel Itanium (IA 64)\n";
428 #elif defined(__sparc__) || defined(__sparc)
429 di << "Architecture: SPARC\n";
431 di << "Architecture: unrecognized\n";
435 #if defined(_WIN32) || defined(__WINDOWS__) || defined(__WIN32__)
436 di << "OS: Windows\n";
437 #elif defined(__APPLE__) || defined(__MACH__)
438 di << "OS: Mac OS X\n";
440 di << "OS: SUN Solaris\n";
441 #elif defined(__ANDROID__) /* must be before Linux */
442 #include <android/api-level.h>
443 di << "OS: Android (__ANDROID_API__ = " << __ANDROID_API__ << ")\n";
444 #elif defined(__QNXNTO__)
445 di << "OS: QNX Neutrino\n";
446 #elif defined(__QNX__)
448 #elif defined(__linux__)
450 #elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
451 #include <sys/param.h>
452 di << "OS: BSD (BSD = " << BSD << ")\n";
454 di << "OS: unrecognized\n";
460 //=======================================================================
463 //=======================================================================
465 static Standard_Integer Draw_wait(Draw_Interpretor& , Standard_Integer n, const char** a)
467 Standard_Integer w = 10;
469 w = Draw::Atoi(a[1]);
470 time_t ct = time(NULL) + w;
471 while (time(NULL) < ct) {};
475 //=======================================================================
476 //function : cpulimit
478 //=======================================================================
480 static unsigned int __stdcall CpuFunc (void * /*param*/)
482 clock_t anElapCurrent;
488 Standard_Real anUserSeconds, aSystemSeconds;
489 OSD_Chronometer::GetProcessCPU (anUserSeconds, aSystemSeconds);
490 aCurrent = clock_t(anUserSeconds + aSystemSeconds);
491 anElapCurrent = clock_t(aTimer.ElapsedTime());
493 if (CPU_LIMIT > 0 && (aCurrent - CPU_CURRENT) >= CPU_LIMIT)
496 if (IsDebuggerPresent())
498 std::cout << "Info: CPU limit (" << CPU_LIMIT << " sec) has been reached but ignored because of attached Debugger" << std::endl;
503 std::cout << "ERROR: Process killed by CPU limit (" << CPU_LIMIT << " sec)" << std::endl;
507 if (CPU_LIMIT > 0 && anElapCurrent >= CPU_LIMIT)
510 if (IsDebuggerPresent())
512 std::cout << "Info: Elapsed limit (" << CPU_LIMIT << " sec) has been reached but ignored because of attached Debugger" << std::endl;
517 std::cout << "ERROR: Process killed by elapsed limit (" << CPU_LIMIT << " sec)" << std::endl;
524 static void cpulimitSignalHandler (int)
526 std::cout << "Process killed by CPU limit (" << CPU_LIMIT << " sec)" << std::endl;
529 static void *CpuFunc(void* /*threadarg*/)
531 clock_t anElapCurrent;
535 anElapCurrent = clock_t(aTimer.ElapsedTime());
536 if (CPU_LIMIT >0 && (anElapCurrent) >= CPU_LIMIT) {
537 std::cout << "Process killed by elapsed limit (" << CPU_LIMIT << " sec)" << std::endl;
545 // Returns time in seconds defined by the argument string,
546 // multiplied by factor defined in environment variable
547 // CSF_CPULIMIT_FACTOR (if it exists, 1 otherwise)
548 static clock_t GetCpuLimit (const Standard_CString theParam)
550 clock_t aValue = Draw::Atoi (theParam);
552 OSD_Environment aEnv("CSF_CPULIMIT_FACTOR");
553 TCollection_AsciiString aEnvStr = aEnv.Value();
554 if (!aEnvStr.IsEmpty())
556 aValue *= Draw::Atoi (aEnvStr.ToCString());
561 static Standard_Integer cpulimit(Draw_Interpretor& di, Standard_Integer n, const char** a)
563 static int aFirst = 1;
565 // Windows specific code
566 unsigned int __stdcall CpuFunc (void *);
570 CPU_LIMIT = RLIM_INFINITY;
572 CPU_LIMIT = GetCpuLimit (a[1]);
573 Standard_Real anUserSeconds, aSystemSeconds;
574 OSD_Chronometer::GetProcessCPU (anUserSeconds, aSystemSeconds);
575 CPU_CURRENT = clock_t(anUserSeconds + aSystemSeconds);
578 if (aFirst) // Launch the thread only at the 1st call.
581 _beginthreadex (NULL, 0, CpuFunc, NULL, 0, &aThreadID);
588 rlp.rlim_max = RLIM_INFINITY;
590 rlp.rlim_cur = RLIM_INFINITY;
592 rlp.rlim_cur = GetCpuLimit (a[1]);
593 CPU_LIMIT = rlp.rlim_cur;
596 status=setrlimit(RLIMIT_CPU,&rlp);
598 di << "status cpulimit setrlimit : " << status << "\n";
600 // set signal handler to print a message before death
601 struct sigaction act, oact;
602 memset (&act, 0, sizeof(act));
603 act.sa_handler = cpulimitSignalHandler;
604 sigaction (SIGXCPU, &act, &oact);
606 // cpulimit for elapsed time
609 pthread_t cpulimitThread;
610 if (aFirst) // Launch the thread only at the 1st call.
613 pthread_create(&cpulimitThread, NULL, CpuFunc, NULL);
616 di << "CPU and elapsed time limit set to " << (double)CPU_LIMIT << " seconds";
620 //=======================================================================
621 //function : mallochook
623 //=======================================================================
625 static Standard_Integer mallochook(Draw_Interpretor& di, Standard_Integer n,
631 usage: mallochook cmd\n\
632 where cmd is one of:\n\
633 set [<op>] - set callback to malloc/free; op is one of the following:\n\
634 0 - set callback to NULL,\n\
635 1 - set callback OSD_MAllocHook::CollectBySize (default)\n\
636 2 - set callback OSD_MAllocHook::LogFileHandler\n\
637 reset - reset the CollectBySize handler\n\
638 report1 [<outfile>]\n\
639 - write report from CollectBySize handler in <outfile>\n\
641 - open file for writing the log with LogFileHandler\n\
642 close - close the log file with LogFileHandler\n\
643 report2 [<flag>] [<logfile>] [<outfile>]\n\
644 - scan <logfile> written with LogFileHandler\n\
645 and make synthesized report in <outfile>; <flag> can be:\n\
646 0 - simple stats by sizes (default),\n\
647 1 - with alive allocation numbers\n\
648 By default <logfile> is \"mem-log.txt\", <outfile> is \"mem-stat.txt\""
652 if (strcmp(a[1], "set") == 0)
654 int aType = (n > 2 ? Draw::Atoi(a[2]) : 1);
655 if (aType < 0 || aType > 2)
657 di << "unknown op of the command set\n";
662 OSD_MAllocHook::SetCallback(NULL);
663 di << "callback is unset\n";
667 OSD_MAllocHook::SetCallback(OSD_MAllocHook::GetCollectBySize());
668 di << "callback is set to CollectBySize\n";
670 else //if (aType == 2)
672 OSD_MAllocHook::SetCallback(OSD_MAllocHook::GetLogFileHandler());
673 di << "callback is set to LogFileHandler\n";
676 else if (strcmp(a[1], "reset") == 0)
678 OSD_MAllocHook::GetCollectBySize()->Reset();
679 di << "CollectBySize handler is reset\n";
681 else if (strcmp(a[1], "open") == 0)
683 const char* aFileName = (n > 2 ? a[2] : "mem-log.txt");
684 if (!OSD_MAllocHook::GetLogFileHandler()->Open(aFileName))
686 di << "cannot create file " << aFileName << " for writing\n";
689 di << "log file " << aFileName << " is opened for writing\n";
691 else if (strcmp(a[1], "close") == 0)
693 OSD_MAllocHook::GetLogFileHandler()->Close();
694 di << "log file is closed\n";
696 else if (strcmp(a[1], "report1") == 0)
698 const char* aOutFile = "mem-stat.txt";
701 if (OSD_MAllocHook::GetCollectBySize()->MakeReport(aOutFile))
703 di << "report " << aOutFile << " has been created\n";
707 di << "cannot create report " << aOutFile << "\n";
711 else if (strcmp(a[1], "report2") == 0)
713 Standard_Boolean includeAlive = Standard_False;
714 const char* aLogFile = "mem-log.txt";
715 const char* aOutFile = "mem-stat.txt";
718 includeAlive = (Draw::Atoi(a[2]) != 0);
726 if (OSD_MAllocHook::LogFileHandler::MakeReport(aLogFile, aOutFile, includeAlive))
728 di << "report " << aOutFile << " has been created\n";
732 di << "cannot create report " << aOutFile << " from the log file "
739 di << "unrecognized command " << a[1] << "\n";
745 //==============================================================================
748 //==============================================================================
750 static int dlocale (Draw_Interpretor& di, Standard_Integer n, const char** argv)
752 int category = LC_ALL;
755 const char *cat = argv[1];
756 if ( ! strcmp (cat, "LC_ALL") ) category = LC_ALL;
757 else if ( ! strcmp (cat, "LC_COLLATE") ) category = LC_COLLATE;
758 else if ( ! strcmp (cat, "LC_CTYPE") ) category = LC_CTYPE;
759 else if ( ! strcmp (cat, "LC_MONETARY") ) category = LC_MONETARY;
760 else if ( ! strcmp (cat, "LC_NUMERIC") ) category = LC_NUMERIC;
761 else if ( ! strcmp (cat, "LC_TIME") ) category = LC_TIME;
764 std::cout << "Error: cannot recognize argument " << cat << " as one of LC_ macros" << std::endl;
768 const char* locale = (n > 2 ? argv[2] : NULL);
769 const char* result = setlocale (category, locale);
773 std::cout << "Error: unsupported locale specification: " << locale << std::endl;
777 //==============================================================================
778 //function : dmeminfo
780 //==============================================================================
782 static int dmeminfo (Draw_Interpretor& theDI,
783 Standard_Integer theArgNb,
784 const char** theArgVec)
788 OSD_MemInfo aMemInfo;
789 theDI << aMemInfo.ToString();
793 NCollection_Map<OSD_MemInfo::Counter> aCounters;
794 for (Standard_Integer anIter = 1; anIter < theArgNb; ++anIter)
796 TCollection_AsciiString anArg (theArgVec[anIter]);
798 if (anArg == "virt" || anArg == "v")
800 aCounters.Add (OSD_MemInfo::MemVirtual);
802 else if (anArg == "heap" || anArg == "h")
804 aCounters.Add (OSD_MemInfo::MemHeapUsage);
806 else if (anArg == "wset" || anArg == "w")
808 aCounters.Add (OSD_MemInfo::MemWorkingSet);
810 else if (anArg == "wsetpeak")
812 aCounters.Add (OSD_MemInfo::MemWorkingSetPeak);
814 else if (anArg == "swap")
816 aCounters.Add (OSD_MemInfo::MemSwapUsage);
818 else if (anArg == "swappeak")
820 aCounters.Add (OSD_MemInfo::MemSwapUsagePeak);
822 else if (anArg == "private")
824 aCounters.Add (OSD_MemInfo::MemPrivate);
828 std::cerr << "Unknown argument '" << theArgVec[anIter] << "'!\n";
832 OSD_MemInfo aMemInfo (Standard_False);
833 aMemInfo.SetActive (Standard_False);
834 for (NCollection_Map<OSD_MemInfo::Counter>::Iterator aCountersIt (aCounters); aCountersIt.More(); aCountersIt.Next())
836 aMemInfo.SetActive (aCountersIt.Value(), Standard_True);
840 for (NCollection_Map<OSD_MemInfo::Counter>::Iterator aCountersIt (aCounters); aCountersIt.More(); aCountersIt.Next())
842 theDI << Standard_Real (aMemInfo.Value (aCountersIt.Value())) << " ";
848 //==============================================================================
849 //function : dparallel
851 //==============================================================================
852 static int dparallel (Draw_Interpretor& theDI,
853 Standard_Integer theArgNb,
854 const char** theArgVec)
856 const Handle(OSD_ThreadPool)& aDefPool = OSD_ThreadPool::DefaultPool();
859 theDI << "NbLogicalProcessors: " << OSD_Parallel::NbLogicalProcessors() << "\n"
860 << "NbThreads: " << aDefPool->NbThreads() << "\n"
861 << "NbDefThreads: " << aDefPool->NbDefaultThreadsToLaunch() << "\n"
862 << "UseOcct: " << (OSD_Parallel::ToUseOcctThreads() ? 1 : 0);
866 for (Standard_Integer anIter = 1; anIter < theArgNb; ++anIter)
868 TCollection_AsciiString anArg (theArgVec[anIter]);
870 if (anIter + 1 < theArgNb
871 && (anArg == "-nbthreads"
872 || anArg == "-threads"))
874 const Standard_Integer aVal = Draw::Atoi (theArgVec[++anIter]);
875 aDefPool->Init (aVal);
877 else if (anIter + 1 < theArgNb
878 && (anArg == "-nbdefthreads"
879 || anArg == "-defthreads"
880 || anArg == "-nbmaxdefthreads"
881 || anArg == "-maxdefthreads"))
883 const Standard_Integer aVal = Draw::Atoi (theArgVec[++anIter]);
884 if (aVal <= 0 || aVal > aDefPool->NbThreads())
886 std::cout << "Syntax error: maximum number of threads to use should be <= of threads in the pool\n";
889 aDefPool->SetNbDefaultThreadsToLaunch (aVal);
891 else if (anIter + 1 < theArgNb
892 && (anArg == "-useocct"
893 || anArg == "-touseocct"
894 || anArg == "-occt"))
896 const Standard_Integer aVal = Draw::Atoi (theArgVec[++anIter]);
897 OSD_Parallel::SetUseOcctThreads (aVal == 1);
898 if (OSD_Parallel::ToUseOcctThreads() != (aVal == 1))
900 std::cout << "Warning: unable to switch threads library - no options available\n";
903 else if (anIter + 1 < theArgNb
904 && (anArg == "-usetbb"
905 || anArg == "-tousetbb"
908 const Standard_Integer aVal = Draw::Atoi (theArgVec[++anIter]);
909 OSD_Parallel::SetUseOcctThreads (aVal == 0);
910 if (OSD_Parallel::ToUseOcctThreads() != (aVal == 0))
912 std::cout << "Warning: unable to switch threads library - no options available\n";
917 std::cout << "Syntax error: unknown argument '" << anArg << "'\n";
924 //==============================================================================
927 //==============================================================================
929 static int dperf (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
931 // reset if argument is provided and it is not '0'
932 int reset = (theArgNb > 1 ? theArgVec[1][0] != '0' && theArgVec[1][0] != '\0' : 0);
934 perf_sprint_all_meters (buffer, 25600 - 1, reset);
939 //==============================================================================
940 //function : dsetsignal
942 //==============================================================================
944 static int dsetsignal (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
946 OSD_SignalMode aMode = OSD_SignalMode_Set;
947 Standard_Boolean aSetFPE = OSD::ToCatchFloatingSignals();
949 // default for FPE signal is defined by CSF_FPE variable, if set
950 OSD_Environment aEnv("CSF_FPE");
951 TCollection_AsciiString aEnvStr = aEnv.Value();
952 if (!aEnvStr.IsEmpty())
954 aSetFPE = (aEnvStr.Value(1) != '0');
958 for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
960 TCollection_AsciiString anArg(theArgVec[anArgIter]);
964 aMode = OSD_SignalMode_AsIs;
966 else if (anArg == "set")
968 aMode = OSD_SignalMode_Set;
970 else if (anArg == "unhandled")
972 aMode = OSD_SignalMode_SetUnhandled;
974 else if (anArg == "unset")
976 aMode = OSD_SignalMode_Unset;
978 else if (anArg == "1" || anArg == "on")
980 aSetFPE = Standard_True;
982 else if (anArg == "0" || anArg == "off")
984 aSetFPE = Standard_False;
986 else if (anArg == "default")
991 std::cout << "Syntax error: unknown argument '" << anArg << "'\n";
996 OSD::SetSignal(aMode, aSetFPE);
998 // report actual status in the end
999 const char* aModeStr = 0;
1000 switch (OSD::SignalMode())
1003 case OSD_SignalMode_AsIs: aModeStr = "asis"; break;
1004 case OSD_SignalMode_Set: aModeStr = "set"; break;
1005 case OSD_SignalMode_SetUnhandled: aModeStr = "unhandled"; break;
1006 case OSD_SignalMode_Unset: aModeStr = "unset"; break;
1008 theDI << "Signal mode: " << aModeStr << "\n"
1009 << "Catch FPE: " << (OSD::ToCatchFloatingSignals() ? "1" : "0") << "\n";
1013 //==============================================================================
1014 //function : dtracelevel
1016 //==============================================================================
1018 static int dtracelevel (Draw_Interpretor& theDI,
1019 Standard_Integer theArgNb,
1020 const char** theArgVec)
1022 Message_Gravity aLevel = Message_Info;
1023 if (theArgNb < 1 || theArgNb > 2)
1025 std::cout << "Error: wrong number of arguments! See usage:\n";
1026 theDI.PrintHelp (theArgVec[0]);
1029 else if (theArgNb == 2)
1031 TCollection_AsciiString aVal (theArgVec[1]);
1033 if (aVal == "trace")
1035 aLevel = Message_Trace;
1037 else if (aVal == "info")
1039 aLevel = Message_Info;
1041 else if (aVal == "warn"
1042 || aVal == "warning")
1044 aLevel = Message_Warning;
1046 else if (aVal == "alarm")
1048 aLevel = Message_Alarm;
1050 else if (aVal == "fail")
1052 aLevel = Message_Fail;
1056 std::cout << "Error: unknown gravity '" << theArgVec[1] << "'!\n";
1061 Handle(Message_Messenger) aMessenger = Message::DefaultMessenger();
1062 if (aMessenger.IsNull())
1064 std::cout << "Error: default messenger is unavailable!\n";
1068 Message_SequenceOfPrinters& aPrinters = aMessenger->ChangePrinters();
1069 if (aPrinters.Length() < 1)
1071 std::cout << "Error: no printers registered in default Messenger!\n";
1075 for (Standard_Integer aPrinterIter = 1; aPrinterIter <= aPrinters.Length(); ++aPrinterIter)
1077 Handle(Message_Printer)& aPrinter = aPrinters.ChangeValue (aPrinterIter);
1080 if (aPrinterIter == 1)
1082 aLevel = aPrinter->GetTraceLevel();
1084 else if (aLevel == aPrinter->GetTraceLevel())
1089 switch (aPrinter->GetTraceLevel())
1091 case Message_Trace: theDI << "trace"; break;
1092 case Message_Info: theDI << "info"; break;
1093 case Message_Warning: theDI << "warn"; break;
1094 case Message_Alarm: theDI << "alarm"; break;
1095 case Message_Fail: theDI << "fail"; break;
1100 aPrinter->SetTraceLevel (aLevel);
1106 void Draw::BasicCommands(Draw_Interpretor& theCommands)
1108 static Standard_Boolean Done = Standard_False;
1110 Done = Standard_True;
1112 std::ios::sync_with_stdio();
1114 const char* g = "DRAW General Commands";
1116 theCommands.Add("batch", "returns 1 in batch mode",
1117 __FILE__,ifbatch,g);
1118 theCommands.Add("spy","spy [file], Save commands in file. no file close",
1120 theCommands.Add("wait","wait [time(10)], wait time seconds",
1121 __FILE__,Draw_wait,g);
1122 theCommands.Add("cpulimit","cpulimit [nbseconds], no args remove limits",
1123 __FILE__,cpulimit,g);
1124 theCommands.Add("chrono","chrono [name action [action...]] \n Operates named timer.\n"
1125 " Supported actions: reset, start, stop, restart, show, counter [text].\n"
1126 " Without arguments enables / disables global timer for all DRAW commands.",
1127 __FILE__,chronom,g);
1128 theCommands.Add("dchrono","see help of chrono command",
1129 __FILE__,dchronom,g);
1130 theCommands.Add("mallochook",
1131 "debug memory allocation/deallocation, w/o args for help",
1132 __FILE__, mallochook, g);
1133 theCommands.Add ("meminfo",
1134 "meminfo [virt|v] [heap|h] [wset|w] [wsetpeak] [swap] [swappeak] [private]"
1135 " : memory counters for this process",
1136 __FILE__, dmeminfo, g);
1137 theCommands.Add("dperf","dperf [reset] -- show performance counters, reset if argument is provided",
1139 theCommands.Add("dsetsignal","dsetsignal [{asis|set|unhandled|unset}=set] [{0|1|default=$CSF_FPE}]\n -- set OSD signal handler, with FPE option if argument is given",
1140 __FILE__,dsetsignal,g);
1142 theCommands.Add("dparallel",
1143 "dparallel [-occt {0|1}] [-nbThreads Count] [-nbDefThreads Count]"
1144 "\n\t\t: Manages global parallelization parameters:"
1145 "\n\t\t: -occt use OCCT implementation or external library (if available)"
1146 "\n\t\t: -nbThreads specify the number of threads in default thread pool"
1147 "\n\t\t: -nbDefThreads specify the upper limit of threads to be used for default thread pool"
1148 "\n\t\t: within single parallelization call (should be <= of overall number of threads),"
1149 "\n\t\t: so that nested algorithm can also use this pool",
1150 __FILE__,dparallel,g);
1152 // Logging commands; note that their names are hard-coded in the code
1153 // of Draw_Interpretor, thus should not be changed without update of that code!
1154 theCommands.Add("dlog", "manage logging of commands and output; run without args to get help",
1156 theCommands.Add("decho", "switch on / off echo of commands to cout; run without args to get help",
1158 theCommands.Add("dtracelevel", "dtracelevel [trace|info|warn|alarm|fail]",
1159 __FILE__, dtracelevel, g);
1161 theCommands.Add("dbreak", "raises Tcl exception if user has pressed Control-Break key",
1163 theCommands.Add("dversion", "provides information on OCCT build configuration (version, compiler, OS, C library, etc.)",
1164 __FILE__,dversion,g);
1165 theCommands.Add("dlocale", "set and / or query locate of C subsystem (function setlocale())",
1166 __FILE__,dlocale,g);