0030895: Coding Rules - specify std namespace explicitly for std::cout and streams
[occt.git] / src / Draw / Draw_BasicCommands.cxx
CommitLineData
b311480e 1// Created on: 1995-02-23
2// Created by: Remi LEQUETTE
3// Copyright (c) 1995-1999 Matra Datavision
973c2be1 4// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 5//
973c2be1 6// This file is part of Open CASCADE Technology software library.
b311480e 7//
d5f74e42 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
973c2be1 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.
b311480e 13//
973c2be1 14// Alternatively, this file may be used under the terms of Open CASCADE
15// commercial license or contractual agreement.
b311480e 16
7fd59977 17
42cf5bc1 18#include <Draw.hxx>
7fd59977 19#include <Draw_Appli.hxx>
a60b9727 20#include <Draw_Chronometer.hxx>
42cf5bc1 21#include <Draw_Drawable3D.hxx>
7fd59977 22#include <Draw_Printer.hxx>
42cf5bc1 23#include <Draw_ProgressIndicator.hxx>
7fd59977 24#include <Message.hxx>
25#include <Message_Messenger.hxx>
8a262fa1 26#include <OSD.hxx>
42cf5bc1 27#include <OSD_Chronometer.hxx>
f4dee9bb 28#include <OSD_Environment.hxx>
8a262fa1 29#include <OSD_Exception_CTRL_BREAK.hxx>
42cf5bc1 30#include <OSD_MAllocHook.hxx>
31#include <OSD_MemInfo.hxx>
fc867b96 32#include <OSD_Parallel.hxx>
33#include <OSD_ThreadPool.hxx>
42cf5bc1 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>
7fd59977 39
42cf5bc1 40#include <OSD_PerfMeter.h>
a60b9727 41#ifdef _WIN32
7fd59977 42
7fd59977 43#include <windows.h>
44#include <winbase.h>
45#include <process.h>
46#include <stdio.h>
47#include <stdlib.h>
a60b9727 48#include <time.h>
49#include <limits>
50
51#define RLIM_INFINITY 0x7fffffff
52
53static clock_t CPU_CURRENT; // cpu time already used at last
54 // cpulimit call. (sec.)
a60b9727 55#else /* _WIN32 */
56
57#include <sys/resource.h>
03155c18 58#include <signal.h>
0b309a75 59#include <unistd.h>
7fd59977 60
61#if defined (__hpux) || defined ( HPUX )
62#define RLIM_INFINITY 0x7fffffff
63#define RLIMIT_CPU 0
64#endif
65
a60b9727 66#endif /* _WIN32 */
7fd59977 67
a60b9727 68extern Standard_Boolean Draw_Batch;
69
70static clock_t CPU_LIMIT; // Cpu_limit in Sec.
0b309a75 71static OSD_Timer aTimer;
7fd59977 72
73//=======================================================================
74// chronom
75//=======================================================================
76
77extern Standard_Boolean Draw_Chrono;
78
79static Standard_Integer chronom(Draw_Interpretor& di,
80 Standard_Integer n,const char** a)
81{
82 if ((n == 1) || (*a[1] == '0') || (*a[1] == '1')) {
83 if (n == 1)
84 Draw_Chrono = !Draw_Chrono;
85 else
86 Draw_Chrono = (*a[1] == '1');
87
586db386 88 if (Draw_Chrono) di << "Chronometers activated.\n";
89 else di << "Chronometers desactivated.\n";
7fd59977 90 }
91 else {
92 Handle(Draw_Drawable3D) D = Draw::Get(a[1]);
93 Handle(Draw_Chronometer) C;
94 if (!D.IsNull()) {
95 C = Handle(Draw_Chronometer)::DownCast(D);
96 }
97 if (C.IsNull()) {
98 C = new Draw_Chronometer();
99 Draw::Set(a[1],C,Standard_False);
100 }
101 if (n <= 2) {
102 C->Timer().Reset();
103 }
104 else {
44fae8b1 105 for (Standard_Integer anIter = 2; anIter < n; ++anIter)
106 {
107 TCollection_AsciiString anArg (a[anIter]);
108 anArg.LowerCase();
109
110 if (anArg == "reset")
111 {
112 C->Timer().Reset();
113 }
114 else if (anArg == "restart")
115 {
116 C->Timer().Restart();
117 }
118 else if (anArg == "start")
119 {
120 C->Timer().Start();
121 }
122 else if (anArg == "stop")
123 {
124 C->Timer().Stop();
125 }
126 else if (anArg == "show")
127 {
128 C->Timer().Show();
129 }
130 else if (anArg == "counter")
131 {
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";
136 }
137 else
138 {
139 std::cerr << "Unknown argument '" << a[anIter] << "'!\n";
140 }
141 }
7fd59977 142 }
143 }
144 return 0;
145}
146
44fae8b1 147static Standard_Integer dchronom(Draw_Interpretor& theDI,
7fd59977 148 Standard_Integer n,const char** a)
149{
150 if ((n == 1) || (*a[1] == '0') || (*a[1] == '1')) {
151 if (n == 1)
152 Draw_Chrono = !Draw_Chrono;
153 else
154 Draw_Chrono = (*a[1] == '1');
155
44fae8b1 156 if (Draw_Chrono) theDI << "Chronometers activated.\n";
157 else theDI << "Chronometers desactivated.\n";
7fd59977 158 }
159 else {
160 Handle(Draw_Drawable3D) D = Draw::Get(a[1]);
161 Handle(Draw_Chronometer) C;
162 if (!D.IsNull()) {
163 C = Handle(Draw_Chronometer)::DownCast(D);
164 }
165 if (C.IsNull()) {
166 C = new Draw_Chronometer();
44fae8b1 167 Draw::Set(a[1],C,Standard_False);
7fd59977 168 }
169 if (n <= 2) {
170 C->Timer().Reset();
171 }
172 else {
44fae8b1 173 for (Standard_Integer anIter = 2; anIter < n; ++anIter)
174 {
175 TCollection_AsciiString anArg (a[anIter]);
176 anArg.LowerCase();
177
178 if (anArg == "reset")
179 {
180 C->Timer().Reset();
181 }
182 else if (anArg == "restart")
183 {
184 C->Timer().Restart();
185 }
186 else if (anArg == "start")
187 {
188 C->Timer().Start();
189 }
190 else if (anArg == "stop")
191 {
192 C->Timer().Stop();
193 }
194 else if (anArg == "show")
195 {
196 Standard_SStream ss;
197 C->Timer().Show(ss);
198 theDI << ss;
199 }
200 else if (anArg == "counter")
201 {
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";
206 }
207 else
208 {
209 theDI << "Unknown argument '" << a[anIter] << "'!\n";
210 }
7fd59977 211 }
212 }
213 }
214 return 0;
215}
216
217
218
219//=======================================================================
220//function : ifbatch
221//purpose :
222//=======================================================================
223
224static Standard_Integer ifbatch(Draw_Interpretor& DI, Standard_Integer , const char** )
225{
226 if (Draw_Batch)
227 DI << "1";
228 else
229 DI << "0";
230
231 return 0;
232}
233
234//=======================================================================
235//function : spy
236//purpose :
237//=======================================================================
238
239extern Standard_Boolean Draw_Spying;
04232180 240extern std::filebuf Draw_Spyfile;
7fd59977 241
242static Standard_Integer spy(Draw_Interpretor& di, Standard_Integer n, const char** a)
243{
244 if (Draw_Spying)
245 Draw_Spyfile.close();
246 Draw_Spying = Standard_False;
247 if (n > 1) {
04232180 248 if (!Draw_Spyfile.open(a[1],std::ios::out)) {
586db386 249 di << "Cannot open "<<a[1]<<" for writing\n";
7fd59977 250 return 1;
251 }
252 Draw_Spying = Standard_True;
253 }
254 return 0;
255}
256
aa02980d 257static Standard_Integer dlog(Draw_Interpretor& di, Standard_Integer n, const char** a)
258{
259 if (n != 2 && n != 3)
260 {
04232180 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;
aa02980d 264 return 1;
265 }
266
267 if (! strcmp (a[1], "on") && n == 2)
268 {
269 di.SetDoLog (Standard_True);
04232180 270// di.Log() << "dlog on" << std::endl; // for symmetry
aa02980d 271 }
272 else if (! strcmp (a[1], "off") && n == 2)
273 {
274 di.SetDoLog (Standard_False);
275 }
276 else if (! strcmp (a[1], "reset") && n == 2)
277 {
e05c25c1 278 di.ResetLog();
aa02980d 279 }
280 else if (! strcmp (a[1], "get") && n == 2)
281 {
e05c25c1 282 di << di.GetLog();
aa02980d 283 }
284 else if (! strcmp (a[1], "add") && n == 3)
285 {
e05c25c1 286 di.AddLog (a[2]);
287 di.AddLog ("\n");
288 }
289 else if (! strcmp (a[1], "status") && n == 2)
290 {
291 di << (di.GetDoLog() ? "on" : "off");
aa02980d 292 }
293 else {
04232180 294 std::cout << "Unrecognized option(s): " << a[1] << std::endl;
aa02980d 295 return 1;
296 }
297 return 0;
298}
299
300static Standard_Integer decho(Draw_Interpretor& di, Standard_Integer n, const char** a)
301{
302 if (n != 2)
303 {
04232180 304 std::cout << "Enable or disable echoing: " << a[0] << " {on|off}" << std::endl;
aa02980d 305 return 1;
306 }
307
308 if (! strcmp (a[1], "on"))
309 {
310 di.SetDoEcho (Standard_True);
311 }
312 else if (! strcmp (a[1], "off"))
313 {
314 di.SetDoEcho (Standard_False);
315 }
316 else {
04232180 317 std::cout << "Unrecognized option: " << a[1] << std::endl;
aa02980d 318 return 1;
319 }
320 return 0;
321}
322
8a262fa1 323static Standard_Integer dbreak(Draw_Interpretor& di, Standard_Integer, const char**)
324{
325 try {
326 OSD::ControlBreak();
327 }
a738b534 328 catch (OSD_Exception_CTRL_BREAK const&) {
8a262fa1 329 di << "User pressed Control-Break";
330 return 1; // Tcl exception
331 }
332
333 return 0;
334}
335
336static Standard_Integer dversion(Draw_Interpretor& di, Standard_Integer, const char**)
337{
338 // print OCCT version and OCCTY-specific macros used
339 di << "Open CASCADE Technology " << OCC_VERSION_STRING_EXT << "\n";
0797d9d3 340#ifdef OCCT_DEBUG
341 di << "Extended debug mode\n";
342#elif defined(_DEBUG)
8a262fa1 343 di << "Debug mode\n";
344#endif
345#ifdef HAVE_TBB
346 di << "TBB enabled (HAVE_TBB)\n";
347#else
348 di << "TBB disabled\n";
349#endif
8a262fa1 350#ifdef HAVE_FREEIMAGE
351 di << "FreeImage enabled (HAVE_FREEIMAGE)\n";
352#else
353 di << "FreeImage disabled\n";
354#endif
08f8a185 355#ifdef HAVE_FFMPEG
356 di << "FFmpeg enabled (HAVE_FFMPEG)\n";
357#else
358 di << "FFmpeg disabled\n";
359#endif
f9f740d6 360#ifdef HAVE_GLES2
361 di << "OpenGL: ES2\n";
7ae4a307 362#else
f9f740d6 363 di << "OpenGL: desktop\n";
7ae4a307 364#endif
0a419c51 365#ifdef HAVE_RAPIDJSON
366 di << "RapidJSON enabled (HAVE_RAPIDJSON)\n";
367#else
368 di << "RapidJSON disabled\n";
369#endif
476e84b1 370#ifdef HAVE_VTK
371 di << "VTK enabled (HAVE_VTK)\n";
372#else
373 di << "VTK disabled\n";
374#endif
8a262fa1 375#ifdef No_Exception
376 di << "Exceptions disabled (No_Exception)\n";
377#else
378 di << "Exceptions enabled\n";
379#endif
380
381 // check compiler, OS, etc. using pre-processor macros provided by compiler
382 // see "Pre-defined C/C++ Compiler Macros" http://sourceforge.net/p/predef/wiki/
383 // note that only modern compilers that are known to be used for OCCT are recognized
384
385 // compiler; note that GCC and MSVC are last as other compilers (e.g. Intel) can also define __GNUC__ and _MSC_VER
386#if defined(__INTEL_COMPILER)
387 di << "Compiler: Intel " << __INTEL_COMPILER << "\n";
388#elif defined(__BORLANDC__)
389 di << "Compiler: Borland C++ (__BORLANDC__ = " << __BORLANDC__ << ")\n";
390#elif defined(__clang__)
391 di << "Compiler: Clang " << __clang_major__ << "." << __clang_minor__ << "." << __clang_patchlevel__ << "\n";
392#elif defined(__SUNPRO_C)
393 di << "Compiler: Sun Studio (__SUNPRO_C = " << __SUNPROC_C << ")\n";
394#elif defined(_MSC_VER)
f9f740d6 395 #if _MSC_VER < 1900
396 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";
397 #else
398 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";
399 #endif
8a262fa1 400#elif defined(__GNUC__)
401 di << "Compiler: GCC " << __GNUC__ << "." << __GNUC_MINOR__ << "." << __GNUC_PATCHLEVEL__ << "\n";
402#else
403 di << "Compiler: unrecognized\n";
404#endif
405
406 // Cygwin and MinGW specifics
407#if defined(__CYGWIN__)
408 di << "Cygwin\n";
409#endif
410#if defined(__MINGW64__)
7c65581d 411 di << "MinGW 64 " << __MINGW64_VERSION_MAJOR << "." << __MINGW64_VERSION_MINOR << "\n";
8a262fa1 412#elif defined(__MINGW32__)
413 di << "MinGW 32 " << __MINGW32_MAJOR_VERSION << "." << __MINGW32_MINOR_VERSION << "\n";
414#endif
415
416 // architecture
417#if defined(__amd64) || defined(__x86_64) || defined(_M_AMD64)
418 di << "Architecture: AMD64\n";
419#elif defined(__i386) || defined(_M_IX86) || defined(__X86__)|| defined(_X86_)
420 di << "Architecture: Intel x86\n";
421#elif defined(_M_IA64) || defined(__ia64__)
422 di << "Architecture: Intel Itanium (IA 64)\n";
423#elif defined(__sparc__) || defined(__sparc)
424 di << "Architecture: SPARC\n";
425#else
426 di << "Architecture: unrecognized\n";
427#endif
428
429 // OS
430#if defined(_WIN32) || defined(__WINDOWS__) || defined(__WIN32__)
431 di << "OS: Windows\n";
432#elif defined(__APPLE__) || defined(__MACH__)
433 di << "OS: Mac OS X\n";
434#elif defined(__sun)
435 di << "OS: SUN Solaris\n";
436#elif defined(__ANDROID__) /* must be before Linux */
437 #include <android/api-level.h>
438 di << "OS: Android (__ANDROID_API__ = " << __ANDROID_API__ << ")\n";
d8d01f6e 439#elif defined(__QNXNTO__)
440 di << "OS: QNX Neutrino\n";
441#elif defined(__QNX__)
442 di << "OS: QNX\n";
8a262fa1 443#elif defined(__linux__)
444 di << "OS: Linux\n";
445#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
446 #include <sys/param.h>
447 di << "OS: BSD (BSD = " << BSD << ")\n";
448#else
449 di << "OS: unrecognized\n";
450#endif
451
452 return 0;
453}
454
7fd59977 455//=======================================================================
456//function : wait
457//purpose :
458//=======================================================================
459
460static Standard_Integer Draw_wait(Draw_Interpretor& , Standard_Integer n, const char** a)
461{
462 Standard_Integer w = 10;
463 if (n > 1)
91322f44 464 w = Draw::Atoi(a[1]);
7fd59977 465 time_t ct = time(NULL) + w;
466 while (time(NULL) < ct) {};
467 return 0;
468}
469
47cbc555
A
470//=======================================================================
471//function : cpulimit
472//purpose :
473//=======================================================================
a60b9727 474#ifdef _WIN32
35e08fe8 475static unsigned int __stdcall CpuFunc (void * /*param*/)
47cbc555 476{
0b309a75 477 clock_t anElapCurrent;
47cbc555 478 clock_t aCurrent;
0b309a75 479
302f96fb 480 for(;;)
47cbc555
A
481 {
482 Sleep (5);
483 Standard_Real anUserSeconds, aSystemSeconds;
484 OSD_Chronometer::GetProcessCPU (anUserSeconds, aSystemSeconds);
485 aCurrent = clock_t(anUserSeconds + aSystemSeconds);
0b309a75 486 anElapCurrent = clock_t(aTimer.ElapsedTime());
47cbc555 487
d48df25d 488 if (CPU_LIMIT > 0 && (aCurrent - CPU_CURRENT) >= CPU_LIMIT)
47cbc555 489 {
0b309a75 490 aTimer.Stop();
667b5eb8 491 if (IsDebuggerPresent())
492 {
493 std::cout << "ERROR: CPU limit (" << CPU_LIMIT << " sec) has been reached but ignored because of attached Debugger" << std::endl;
494 return 0;
495 }
496 else
497 {
498 std::cout << "ERROR: Process killed by CPU limit (" << CPU_LIMIT << " sec)" << std::endl;
499 ExitProcess (2);
500 }
0b309a75 501 }
d48df25d 502 if (CPU_LIMIT > 0 && anElapCurrent >= CPU_LIMIT)
0b309a75 503 {
0b309a75 504 aTimer.Stop();
667b5eb8 505 if (IsDebuggerPresent())
506 {
507 std::cout << "ERROR: Elapsed limit (" << CPU_LIMIT << " sec) has been reached but ignored because of attached Debugger" << std::endl;
508 return 0;
509 }
510 else
511 {
512 std::cout << "ERROR: Process killed by elapsed limit (" << CPU_LIMIT << " sec)" << std::endl;
513 ExitProcess (2);
514 }
47cbc555
A
515 }
516 }
47cbc555 517}
a60b9727 518#else
0b309a75 519static void cpulimitSignalHandler (int)
a60b9727 520{
04232180 521 std::cout << "Process killed by CPU limit (" << CPU_LIMIT << " sec)" << std::endl;
a60b9727 522 exit(2);
523}
0b309a75 524static void *CpuFunc(void* /*threadarg*/)
525{
526 clock_t anElapCurrent;
527 for(;;)
528 {
529 sleep (5);
530 anElapCurrent = clock_t(aTimer.ElapsedTime());
d48df25d 531 if (CPU_LIMIT >0 && (anElapCurrent) >= CPU_LIMIT) {
04232180 532 std::cout << "Process killed by elapsed limit (" << CPU_LIMIT << " sec)" << std::endl;
0b309a75 533 exit(2);
534 }
535 }
536 return NULL;
537}
47cbc555 538#endif
7fd59977 539
35e08fe8 540#ifdef _WIN32
541static Standard_Integer cpulimit(Draw_Interpretor&, Standard_Integer n, const char** a)
542{
543#else
7fd59977 544static Standard_Integer cpulimit(Draw_Interpretor& di, Standard_Integer n, const char** a)
545{
35e08fe8 546#endif
0b309a75 547 static int aFirst = 1;
a60b9727 548#ifdef _WIN32
549 // Windows specific code
47cbc555
A
550 unsigned int __stdcall CpuFunc (void *);
551 unsigned aThreadID;
552
0b309a75 553 if (n <= 1){
a60b9727 554 CPU_LIMIT = RLIM_INFINITY;
0b309a75 555 } else {
91322f44 556 CPU_LIMIT = Draw::Atoi (a[1]);
47cbc555
A
557 Standard_Real anUserSeconds, aSystemSeconds;
558 OSD_Chronometer::GetProcessCPU (anUserSeconds, aSystemSeconds);
a60b9727 559 CPU_CURRENT = clock_t(anUserSeconds + aSystemSeconds);
0b309a75 560 aTimer.Reset();
561 aTimer.Start();
47cbc555
A
562 if (aFirst) // Launch the thread only at the 1st call.
563 {
564 aFirst = 0;
565 _beginthreadex (NULL, 0, CpuFunc, NULL, 0, &aThreadID);
566 }
7fd59977 567 }
568
a60b9727 569#else
a60b9727 570 // Unix & Linux
a60b9727 571 rlimit rlp;
572 rlp.rlim_max = RLIM_INFINITY;
573 if (n <= 1)
574 rlp.rlim_cur = RLIM_INFINITY;
575 else
91322f44 576 rlp.rlim_cur = Draw::Atoi(a[1]);
a60b9727 577 CPU_LIMIT = rlp.rlim_cur;
578
579 int status;
580 status=setrlimit(RLIMIT_CPU,&rlp);
581 if (status !=0)
582 di << "status cpulimit setrlimit : " << status << "\n";
583
584 // set signal handler to print a message before death
585 struct sigaction act, oact;
586 memset (&act, 0, sizeof(act));
0b309a75 587 act.sa_handler = cpulimitSignalHandler;
a60b9727 588 sigaction (SIGXCPU, &act, &oact);
589
0b309a75 590 // cpulimit for elapsed time
591 aTimer.Reset();
592 aTimer.Start();
593 pthread_t cpulimitThread;
594 if (aFirst) // Launch the thread only at the 1st call.
595 {
596 aFirst = 0;
597 pthread_create(&cpulimitThread, NULL, CpuFunc, NULL);
598 }
7fd59977 599#endif
7fd59977 600 return 0;
601}
602
0b309a75 603
7af17f1e
MA
604//=======================================================================
605//function : mallochook
606//purpose :
607//=======================================================================
608
609static Standard_Integer mallochook(Draw_Interpretor& di, Standard_Integer n,
610 const char** a)
611{
612 if (n < 2)
613 {
614 di << "\
615usage: mallochook cmd\n\
616where cmd is one of:\n\
617 set [<op>] - set callback to malloc/free; op is one of the following:\n\
618 0 - set callback to NULL,\n\
619 1 - set callback OSD_MAllocHook::CollectBySize (default)\n\
620 2 - set callback OSD_MAllocHook::LogFileHandler\n\
621 reset - reset the CollectBySize handler\n\
622 report1 [<outfile>]\n\
623 - write report from CollectBySize handler in <outfile>\n\
624 open [<logfile>]\n\
625 - open file for writing the log with LogFileHandler\n\
626 close - close the log file with LogFileHandler\n\
627 report2 [<flag>] [<logfile>] [<outfile>]\n\
628 - scan <logfile> written with LogFileHandler\n\
629 and make synthesized report in <outfile>; <flag> can be:\n\
630 0 - simple stats by sizes (default),\n\
631 1 - with alive allocation numbers\n\
632By default <logfile> is \"mem-log.txt\", <outfile> is \"mem-stat.txt\""
633 << "\n";
634 return 0;
635 }
636 if (strcmp(a[1], "set") == 0)
637 {
91322f44 638 int aType = (n > 2 ? Draw::Atoi(a[2]) : 1);
7af17f1e
MA
639 if (aType < 0 || aType > 2)
640 {
586db386 641 di << "unknown op of the command set\n";
7af17f1e
MA
642 return 1;
643 }
644 else if (aType == 0)
645 {
646 OSD_MAllocHook::SetCallback(NULL);
586db386 647 di << "callback is unset\n";
7af17f1e
MA
648 }
649 else if (aType == 1)
650 {
651 OSD_MAllocHook::SetCallback(OSD_MAllocHook::GetCollectBySize());
586db386 652 di << "callback is set to CollectBySize\n";
7af17f1e
MA
653 }
654 else //if (aType == 2)
655 {
656 OSD_MAllocHook::SetCallback(OSD_MAllocHook::GetLogFileHandler());
586db386 657 di << "callback is set to LogFileHandler\n";
7af17f1e
MA
658 }
659 }
660 else if (strcmp(a[1], "reset") == 0)
661 {
662 OSD_MAllocHook::GetCollectBySize()->Reset();
586db386 663 di << "CollectBySize handler is reset\n";
7af17f1e
MA
664 }
665 else if (strcmp(a[1], "open") == 0)
666 {
667 const char* aFileName = (n > 2 ? a[2] : "mem-log.txt");
668 if (!OSD_MAllocHook::GetLogFileHandler()->Open(aFileName))
669 {
586db386 670 di << "cannot create file " << aFileName << " for writing\n";
7af17f1e
MA
671 return 1;
672 }
586db386 673 di << "log file " << aFileName << " is opened for writing\n";
7af17f1e
MA
674 }
675 else if (strcmp(a[1], "close") == 0)
676 {
677 OSD_MAllocHook::GetLogFileHandler()->Close();
586db386 678 di << "log file is closed\n";
7af17f1e
MA
679 }
680 else if (strcmp(a[1], "report1") == 0)
681 {
682 const char* aOutFile = "mem-stat.txt";
683 if (n > 2)
684 aOutFile = a[2];
685 if (OSD_MAllocHook::GetCollectBySize()->MakeReport(aOutFile))
686 {
586db386 687 di << "report " << aOutFile << " has been created\n";
7af17f1e
MA
688 }
689 else
690 {
691 di << "cannot create report " << aOutFile << "\n";
692 return 1;
693 }
694 }
695 else if (strcmp(a[1], "report2") == 0)
696 {
697 Standard_Boolean includeAlive = Standard_False;
698 const char* aLogFile = "mem-log.txt";
699 const char* aOutFile = "mem-stat.txt";
700 if (n > 2)
701 {
91322f44 702 includeAlive = (Draw::Atoi(a[2]) != 0);
7af17f1e
MA
703 if (n > 3)
704 {
705 aLogFile = a[3];
706 if (n > 4)
707 aOutFile = a[4];
708 }
709 }
710 if (OSD_MAllocHook::LogFileHandler::MakeReport(aLogFile, aOutFile, includeAlive))
711 {
586db386 712 di << "report " << aOutFile << " has been created\n";
7af17f1e
MA
713 }
714 else
715 {
716 di << "cannot create report " << aOutFile << " from the log file "
717 << aLogFile << "\n";
718 return 1;
719 }
720 }
721 else
722 {
723 di << "unrecognized command " << a[1] << "\n";
724 return 1;
725 }
726 return 0;
727}
728
91322f44 729//==============================================================================
730//function : dlocale
731//purpose :
732//==============================================================================
733
734static int dlocale (Draw_Interpretor& di, Standard_Integer n, const char** argv)
735{
736 int category = LC_ALL;
737 if (n > 1)
738 {
739 const char *cat = argv[1];
740 if ( ! strcmp (cat, "LC_ALL") ) category = LC_ALL;
741 else if ( ! strcmp (cat, "LC_COLLATE") ) category = LC_COLLATE;
742 else if ( ! strcmp (cat, "LC_CTYPE") ) category = LC_CTYPE;
743 else if ( ! strcmp (cat, "LC_MONETARY") ) category = LC_MONETARY;
744 else if ( ! strcmp (cat, "LC_NUMERIC") ) category = LC_NUMERIC;
745 else if ( ! strcmp (cat, "LC_TIME") ) category = LC_TIME;
746 else
747 {
04232180 748 std::cout << "Error: cannot recognize argument " << cat << " as one of LC_ macros" << std::endl;
91322f44 749 return 1;
750 }
751 }
752 const char* locale = (n > 2 ? argv[2] : NULL);
753 const char* result = setlocale (category, locale);
754 if (result)
755 di << result;
756 else
04232180 757 std::cout << "Error: unsupported locale specification: " << locale << std::endl;
91322f44 758 return 0;
759}
760
f0430952 761//==============================================================================
762//function : dmeminfo
763//purpose :
764//==============================================================================
765
766static int dmeminfo (Draw_Interpretor& theDI,
767 Standard_Integer theArgNb,
768 const char** theArgVec)
769{
770 OSD_MemInfo aMemInfo;
771 if (theArgNb <= 1)
772 {
773 theDI << aMemInfo.ToString();
774 return 0;
775 }
776
777 for (Standard_Integer anIter = 1; anIter < theArgNb; ++anIter)
778 {
779 TCollection_AsciiString anArg (theArgVec[anIter]);
780 anArg.LowerCase();
781 if (anArg == "virt" || anArg == "v")
782 {
783 theDI << Standard_Real (aMemInfo.Value (OSD_MemInfo::MemVirtual)) << " ";
784 }
67a1064e 785 else if (anArg == "heap" || anArg == "h")
786 {
787 theDI << Standard_Real (aMemInfo.Value (OSD_MemInfo::MemHeapUsage)) << " ";
788 }
f0430952 789 else if (anArg == "wset" || anArg == "w")
790 {
791 theDI << Standard_Real (aMemInfo.Value (OSD_MemInfo::MemWorkingSet)) << " ";
792 }
793 else if (anArg == "wsetpeak")
794 {
795 theDI << Standard_Real (aMemInfo.Value (OSD_MemInfo::MemWorkingSetPeak)) << " ";
796 }
797 else if (anArg == "swap")
798 {
799 theDI << Standard_Real (aMemInfo.Value (OSD_MemInfo::MemSwapUsage)) << " ";
800 }
801 else if (anArg == "swappeak")
802 {
803 theDI << Standard_Real (aMemInfo.Value (OSD_MemInfo::MemSwapUsagePeak)) << " ";
804 }
805 else if (anArg == "private")
806 {
807 theDI << Standard_Real (aMemInfo.Value (OSD_MemInfo::MemPrivate)) << " ";
808 }
809 else
810 {
811 std::cerr << "Unknown argument '" << theArgVec[anIter] << "'!\n";
812 }
813 }
814 theDI << "\n";
815 return 0;
816}
7fd59977 817
fc867b96 818//==============================================================================
819//function : dparallel
820//purpose :
821//==============================================================================
822static int dparallel (Draw_Interpretor& theDI,
823 Standard_Integer theArgNb,
824 const char** theArgVec)
825{
826 const Handle(OSD_ThreadPool)& aDefPool = OSD_ThreadPool::DefaultPool();
827 if (theArgNb <= 1)
828 {
829 theDI << "NbLogicalProcessors: " << OSD_Parallel::NbLogicalProcessors() << "\n"
830 << "NbThreads: " << aDefPool->NbThreads() << "\n"
831 << "NbDefThreads: " << aDefPool->NbDefaultThreadsToLaunch() << "\n"
832 << "UseOcct: " << (OSD_Parallel::ToUseOcctThreads() ? 1 : 0);
833 return 0;
834 }
835
836 for (Standard_Integer anIter = 1; anIter < theArgNb; ++anIter)
837 {
838 TCollection_AsciiString anArg (theArgVec[anIter]);
839 anArg.LowerCase();
840 if (anIter + 1 < theArgNb
841 && (anArg == "-nbthreads"
842 || anArg == "-threads"))
843 {
844 const Standard_Integer aVal = Draw::Atoi (theArgVec[++anIter]);
845 aDefPool->Init (aVal);
846 }
847 else if (anIter + 1 < theArgNb
848 && (anArg == "-nbdefthreads"
849 || anArg == "-defthreads"
850 || anArg == "-nbmaxdefthreads"
851 || anArg == "-maxdefthreads"))
852 {
853 const Standard_Integer aVal = Draw::Atoi (theArgVec[++anIter]);
854 if (aVal <= 0 || aVal > aDefPool->NbThreads())
855 {
856 std::cout << "Syntax error: maximum number of threads to use should be <= of threads in the pool\n";
857 return 1;
858 }
859 aDefPool->SetNbDefaultThreadsToLaunch (aVal);
860 }
861 else if (anIter + 1 < theArgNb
862 && (anArg == "-useocct"
863 || anArg == "-touseocct"
864 || anArg == "-occt"))
865 {
866 const Standard_Integer aVal = Draw::Atoi (theArgVec[++anIter]);
867 OSD_Parallel::SetUseOcctThreads (aVal == 1);
868 if (OSD_Parallel::ToUseOcctThreads() != (aVal == 1))
869 {
870 std::cout << "Warning: unable to switch threads library - no options available\n";
871 }
872 }
873 else if (anIter + 1 < theArgNb
874 && (anArg == "-usetbb"
875 || anArg == "-tousetbb"
876 || anArg == "-tbb"))
877 {
878 const Standard_Integer aVal = Draw::Atoi (theArgVec[++anIter]);
879 OSD_Parallel::SetUseOcctThreads (aVal == 0);
880 if (OSD_Parallel::ToUseOcctThreads() != (aVal == 0))
881 {
882 std::cout << "Warning: unable to switch threads library - no options available\n";
883 }
884 }
885 else
886 {
887 std::cout << "Syntax error: unknown argument '" << anArg << "'\n";
888 return 1;
889 }
890 }
891 return 0;
892}
893
618617fe 894//==============================================================================
895//function : dperf
896//purpose :
897//==============================================================================
898
899static int dperf (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
900{
901 // reset if argument is provided and it is not '0'
902 int reset = (theArgNb > 1 ? theArgVec[1][0] != '0' && theArgVec[1][0] != '\0' : 0);
903 char buffer[25600];
904 perf_sprint_all_meters (buffer, 25600 - 1, reset);
905 theDI << buffer;
906 return 0;
907}
908
f4dee9bb 909//==============================================================================
910//function : dsetsignal
911//purpose :
912//==============================================================================
913
914static int dsetsignal (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
915{
916 // arm FPE handler if argument is provided and its first symbol is not '0'
917 // or if environment variable CSF_FPE is set and its first symbol is not '0'
918 bool setFPE = false;
919 if (theArgNb > 1)
920 {
921 setFPE = (theArgVec[1][0] == '1' || theArgVec[1][0] == 't');
922 }
923 else
924 {
925 OSD_Environment aEnv ("CSF_FPE");
926 TCollection_AsciiString aEnvStr = aEnv.Value();
927 setFPE = (! aEnvStr.IsEmpty() && aEnvStr.Value(1) != '0');
928 }
929 OSD::SetSignal (setFPE);
930 theDI << "Signal handlers are set, with FPE " << (setFPE ? "armed" : "disarmed");
931 return 0;
932}
933
785a9540 934//==============================================================================
935//function : dtracelevel
936//purpose :
937//==============================================================================
938
939static int dtracelevel (Draw_Interpretor& theDI,
940 Standard_Integer theArgNb,
941 const char** theArgVec)
942{
943 Message_Gravity aLevel = Message_Info;
944 if (theArgNb < 1 || theArgNb > 2)
945 {
946 std::cout << "Error: wrong number of arguments! See usage:\n";
947 theDI.PrintHelp (theArgVec[0]);
948 return 1;
949 }
950 else if (theArgNb == 2)
951 {
952 TCollection_AsciiString aVal (theArgVec[1]);
953 aVal.LowerCase();
954 if (aVal == "trace")
955 {
956 aLevel = Message_Trace;
957 }
958 else if (aVal == "info")
959 {
960 aLevel = Message_Info;
961 }
962 else if (aVal == "warn"
963 || aVal == "warning")
964 {
965 aLevel = Message_Warning;
966 }
967 else if (aVal == "alarm")
968 {
969 aLevel = Message_Alarm;
970 }
971 else if (aVal == "fail")
972 {
973 aLevel = Message_Fail;
974 }
975 else
976 {
977 std::cout << "Error: unknown gravity '" << theArgVec[1] << "'!\n";
978 return 1;
979 }
980 }
981
982 Handle(Message_Messenger) aMessenger = Message::DefaultMessenger();
983 if (aMessenger.IsNull())
984 {
985 std::cout << "Error: default messenger is unavailable!\n";
986 return 1;
987 }
988
989 Message_SequenceOfPrinters& aPrinters = aMessenger->ChangePrinters();
990 if (aPrinters.Length() < 1)
991 {
992 std::cout << "Error: no printers registered in default Messenger!\n";
993 return 0;
994 }
995
996 for (Standard_Integer aPrinterIter = 1; aPrinterIter <= aPrinters.Length(); ++aPrinterIter)
997 {
998 Handle(Message_Printer)& aPrinter = aPrinters.ChangeValue (aPrinterIter);
999 if (theArgNb == 1)
1000 {
1001 if (aPrinterIter == 1)
1002 {
1003 aLevel = aPrinter->GetTraceLevel();
1004 }
1005 else if (aLevel == aPrinter->GetTraceLevel())
1006 {
1007 continue;
1008 }
1009
1010 switch (aPrinter->GetTraceLevel())
1011 {
1012 case Message_Trace: theDI << "trace"; break;
1013 case Message_Info: theDI << "info"; break;
1014 case Message_Warning: theDI << "warn"; break;
1015 case Message_Alarm: theDI << "alarm"; break;
1016 case Message_Fail: theDI << "fail"; break;
1017 }
1018 continue;
1019 }
1020
1021 aPrinter->SetTraceLevel (aLevel);
1022 }
1023
1024 return 0;
1025}
1026
7fd59977 1027void Draw::BasicCommands(Draw_Interpretor& theCommands)
1028{
1029 static Standard_Boolean Done = Standard_False;
1030 if (Done) return;
1031 Done = Standard_True;
1032
04232180 1033 std::ios::sync_with_stdio();
aa02980d 1034
7fd59977 1035 const char* g = "DRAW General Commands";
785a9540 1036
7fd59977 1037 theCommands.Add("batch", "returns 1 in batch mode",
1038 __FILE__,ifbatch,g);
1039 theCommands.Add("spy","spy [file], Save commands in file. no file close",
1040 __FILE__,spy,g);
1041 theCommands.Add("wait","wait [time(10)], wait time seconds",
1042 __FILE__,Draw_wait,g);
1043 theCommands.Add("cpulimit","cpulimit [nbseconds], no args remove limits",
1044 __FILE__,cpulimit,g);
7d3225b5 1045 theCommands.Add("chrono","chrono [name action [action...]] \n Operates named timer.\n"
1046 " Supported actions: reset, start, stop, restart, show, counter [text].\n"
1047 " Without arguments enables / disables global timer for all DRAW commands.",
7fd59977 1048 __FILE__,chronom,g);
7d3225b5 1049 theCommands.Add("dchrono","see help of chrono command",
7fd59977 1050 __FILE__,dchronom,g);
7af17f1e
MA
1051 theCommands.Add("mallochook",
1052 "debug memory allocation/deallocation, w/o args for help",
1053 __FILE__, mallochook, g);
f0430952 1054 theCommands.Add ("meminfo",
67a1064e 1055 "meminfo [virt|v] [heap|h] [wset|w] [wsetpeak] [swap] [swappeak] [private]"
f0430952 1056 " : memory counters for this process",
1057 __FILE__, dmeminfo, g);
618617fe 1058 theCommands.Add("dperf","dperf [reset] -- show performance counters, reset if argument is provided",
1059 __FILE__,dperf,g);
f4dee9bb 1060 theCommands.Add("dsetsignal","dsetsignal [fpe=0] -- set OSD signal handler, with FPE option if argument is given",
1061 __FILE__,dsetsignal,g);
aa02980d 1062
fc867b96 1063 theCommands.Add("dparallel",
1064 "dparallel [-occt {0|1}] [-nbThreads Count] [-nbDefThreads Count]"
1065 "\n\t\t: Manages global parallelization parameters:"
1066 "\n\t\t: -occt use OCCT implementation or external library (if available)"
1067 "\n\t\t: -nbThreads specify the number of threads in default thread pool"
1068 "\n\t\t: -nbDefThreads specify the upper limit of threads to be used for default thread pool"
1069 "\n\t\t: within single parallelization call (should be <= of overall number of threads),"
1070 "\n\t\t: so that nested algorithm can also use this pool",
1071 __FILE__,dparallel,g);
1072
785a9540 1073 // Logging commands; note that their names are hard-coded in the code
aa02980d 1074 // of Draw_Interpretor, thus should not be changed without update of that code!
1075 theCommands.Add("dlog", "manage logging of commands and output; run without args to get help",
1076 __FILE__,dlog,g);
1077 theCommands.Add("decho", "switch on / off echo of commands to cout; run without args to get help",
1078 __FILE__,decho,g);
785a9540 1079 theCommands.Add("dtracelevel", "dtracelevel [trace|info|warn|alarm|fail]",
1080 __FILE__, dtracelevel, g);
1081
8a262fa1 1082 theCommands.Add("dbreak", "raises Tcl exception if user has pressed Control-Break key",
1083 __FILE__,dbreak,g);
1084 theCommands.Add("dversion", "provides information on OCCT build configuration (version, compiler, OS, C library, etc.)",
1085 __FILE__,dversion,g);
91322f44 1086 theCommands.Add("dlocale", "set and / or query locate of C subsystem (function setlocale())",
1087 __FILE__,dlocale,g);
7fd59977 1088}