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