0021985: Vista/WIndows 7 compatibility issues reported by the community
[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
4// Copyright (c) 1999-2012 OPEN CASCADE SAS
5//
6// The content of this file is subject to the Open CASCADE Technology Public
7// License Version 6.5 (the "License"). You may not use the content of this file
8// except in compliance with the License. Please obtain a copy of the License
9// at http://www.opencascade.org and read it completely before using this file.
10//
11// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13//
14// The Original Code and all software distributed under the License is
15// distributed on an "AS IS" basis, without warranty of any kind, and the
16// Initial Developer hereby disclaims all such warranties, including without
17// limitation, any warranties of merchantability, fitness for a particular
18// purpose or non-infringement. Please see the License for the specific terms
19// and conditions governing the rights and limitations under the License.
20
7fd59977 21
22#include <Standard_Macro.hxx>
23#include <Standard_Stream.hxx>
24#include <Standard_SStream.hxx>
25
26#include <Draw.ixx>
27#include <Draw_Appli.hxx>
28#include <Draw_Printer.hxx>
29
30#include <Message.hxx>
31#include <Message_Messenger.hxx>
f0430952 32#include <OSD_MemInfo.hxx>
7fd59977 33
34#ifdef HAVE_CONFIG_H
35# include <config.h>
36#endif
37
38#if defined(HAVE_TIME_H) || defined(WNT)
39# include <time.h>
40#endif
41
42#ifdef HAVE_SIGNAL_H
43# include <signal.h>
44#endif
45
46#ifndef WNT
47# include <sys/resource.h>
48# ifdef HAVE_STRINGS_H
49# include <strings.h>
50# endif
51#else
52//WNT
53extern Standard_Boolean Draw_Batch;
54#include <windows.h>
55#include <winbase.h>
56#include <process.h>
57#include <stdio.h>
58#include <stdlib.h>
59#ifdef HAVE_LIMITS
60# include <limits>
61#elif defined (HAVE_LIMITS_H)
62# include <limits.h>
63#endif
64
65#ifdef WNT
66# include <limits>
67#endif
68
69static clock_t MDTV_CPU_LIMIT; // Cpu_limit in Sec.
70static clock_t MDTV_CPU_CURRENT; // cpu time already used at last
71 // cpulimit call. (sec.)
72//#define strcasecmp strcmp Already defined
73#define RLIM_INFINITY 0x7fffffff
74#endif
75
76#include <Draw_Chronometer.hxx>
7af17f1e 77#include <OSD_MAllocHook.hxx>
47cbc555 78#include <OSD_Chronometer.hxx>
7fd59977 79
80#if defined (__hpux) || defined ( HPUX )
81#define RLIM_INFINITY 0x7fffffff
82#define RLIMIT_CPU 0
83#endif
84
85
86
87//=======================================================================
88// chronom
89//=======================================================================
90
91extern Standard_Boolean Draw_Chrono;
92
93static Standard_Integer chronom(Draw_Interpretor& di,
94 Standard_Integer n,const char** a)
95{
96 if ((n == 1) || (*a[1] == '0') || (*a[1] == '1')) {
97 if (n == 1)
98 Draw_Chrono = !Draw_Chrono;
99 else
100 Draw_Chrono = (*a[1] == '1');
101
102 if (Draw_Chrono) di << "Chronometers activated."<<"\n";
103 else di << "Chronometers desactivated."<<"\n";
104 }
105 else {
106 Handle(Draw_Drawable3D) D = Draw::Get(a[1]);
107 Handle(Draw_Chronometer) C;
108 if (!D.IsNull()) {
109 C = Handle(Draw_Chronometer)::DownCast(D);
110 }
111 if (C.IsNull()) {
112 C = new Draw_Chronometer();
113 Draw::Set(a[1],C,Standard_False);
114 }
115 if (n <= 2) {
116 C->Timer().Reset();
117 }
118 else {
119 if (!strcasecmp(a[2],"reset"))
120 C->Timer().Reset();
121 if (!strcasecmp(a[2],"start"))
122 C->Timer().Start();
123 if (!strcasecmp(a[2],"stop"))
124 C->Timer().Stop();
125 if (!strcasecmp(a[2],"show"))
126 C->Timer().Show();
127 }
128 }
129 return 0;
130}
131
132static Standard_Integer dchronom(Draw_Interpretor& I,
133 Standard_Integer n,const char** a)
134{
135 if ((n == 1) || (*a[1] == '0') || (*a[1] == '1')) {
136 if (n == 1)
137 Draw_Chrono = !Draw_Chrono;
138 else
139 Draw_Chrono = (*a[1] == '1');
140
141 if (Draw_Chrono) I << "Chronometers activated."<<"\n";
142 else I << "Chronometers desactivated."<<"\n";
143 }
144 else {
145 Handle(Draw_Drawable3D) D = Draw::Get(a[1]);
146 Handle(Draw_Chronometer) C;
147 if (!D.IsNull()) {
148 C = Handle(Draw_Chronometer)::DownCast(D);
149 }
150 if (C.IsNull()) {
151 C = new Draw_Chronometer();
152 Draw::Set(a[1],C,Standard_False);
153 }
154 if (n <= 2) {
155 C->Timer().Reset();
156 }
157 else {
158 if (!strcasecmp(a[2],"reset"))
159 C->Timer().Reset();
160 if (!strcasecmp(a[2],"start"))
161 C->Timer().Start();
162 if (!strcasecmp(a[2],"stop"))
163 C->Timer().Stop();
164 if (!strcasecmp(a[2],"show")) {
165 Standard_SStream ss;
166 C->Timer().Show(ss);
167 I << ss;
168 }
169 }
170 }
171 return 0;
172}
173
174
175
176//=======================================================================
177//function : ifbatch
178//purpose :
179//=======================================================================
180
181static Standard_Integer ifbatch(Draw_Interpretor& DI, Standard_Integer , const char** )
182{
183 if (Draw_Batch)
184 DI << "1";
185 else
186 DI << "0";
187
188 return 0;
189}
190
191//=======================================================================
192//function : spy
193//purpose :
194//=======================================================================
195
196extern Standard_Boolean Draw_Spying;
197extern filebuf Draw_Spyfile;
198
199static Standard_Integer spy(Draw_Interpretor& di, Standard_Integer n, const char** a)
200{
201 if (Draw_Spying)
202 Draw_Spyfile.close();
203 Draw_Spying = Standard_False;
204 if (n > 1) {
205 if (!Draw_Spyfile.open(a[1],ios::out)) {
206 di << "Cannot open "<<a[1]<<" for writing"<<"\n";
207 return 1;
208 }
209 Draw_Spying = Standard_True;
210 }
211 return 0;
212}
213
aa02980d 214static Standard_Integer dlog(Draw_Interpretor& di, Standard_Integer n, const char** a)
215{
216 if (n != 2 && n != 3)
217 {
218 cout << "Enable or disable logging: " << a[0] << " {on|off}" << endl;
219 cout << "Reset log: " << a[0] << " reset" << endl;
220 cout << "Get log content: " << a[0] << " get" << endl;
221 return 1;
222 }
223
224 if (! strcmp (a[1], "on") && n == 2)
225 {
226 di.SetDoLog (Standard_True);
227// di.Log() << "dlog on" << endl; // for symmetry
228 }
229 else if (! strcmp (a[1], "off") && n == 2)
230 {
231 di.SetDoLog (Standard_False);
232 }
233 else if (! strcmp (a[1], "reset") && n == 2)
234 {
235 di.Log().str("");
236 }
237 else if (! strcmp (a[1], "get") && n == 2)
238 {
239 di << di.Log().str().c_str();
240 }
241 else if (! strcmp (a[1], "add") && n == 3)
242 {
243 di.Log() << a[2] << "\n";
244 }
245 else {
246 cout << "Unrecognized option(s): " << a[1] << endl;
247 return 1;
248 }
249 return 0;
250}
251
252static Standard_Integer decho(Draw_Interpretor& di, Standard_Integer n, const char** a)
253{
254 if (n != 2)
255 {
256 cout << "Enable or disable echoing: " << a[0] << " {on|off}" << endl;
257 return 1;
258 }
259
260 if (! strcmp (a[1], "on"))
261 {
262 di.SetDoEcho (Standard_True);
263 }
264 else if (! strcmp (a[1], "off"))
265 {
266 di.SetDoEcho (Standard_False);
267 }
268 else {
269 cout << "Unrecognized option: " << a[1] << endl;
270 return 1;
271 }
272 return 0;
273}
274
7fd59977 275//=======================================================================
276//function : wait
277//purpose :
278//=======================================================================
279
280static Standard_Integer Draw_wait(Draw_Interpretor& , Standard_Integer n, const char** a)
281{
282 Standard_Integer w = 10;
283 if (n > 1)
284 w = atoi(a[1]);
285 time_t ct = time(NULL) + w;
286 while (time(NULL) < ct) {};
287 return 0;
288}
289
47cbc555
A
290//=======================================================================
291//function : cpulimit
292//purpose :
293//=======================================================================
294#ifdef WNT
295static unsigned int __stdcall CpuFunc (void * param)
296{
297 clock_t aCurrent;
298 while (1)
299 {
300 Sleep (5);
301 Standard_Real anUserSeconds, aSystemSeconds;
302 OSD_Chronometer::GetProcessCPU (anUserSeconds, aSystemSeconds);
303 aCurrent = clock_t(anUserSeconds + aSystemSeconds);
304
305 if ((aCurrent - MDTV_CPU_CURRENT) >= MDTV_CPU_LIMIT)
306 {
307 printf ("CpuFunc : Fin sur Cpu Limit \n");
308 ExitProcess (2);
309 return 0;
310 }
311 }
312 return 0;
313}
314#endif
7fd59977 315
316static Standard_Integer cpulimit(Draw_Interpretor& di, Standard_Integer n, const char** a)
317{
318#ifndef WNT
319 rlimit rlp;
320 rlp.rlim_max = RLIM_INFINITY;
321 if (n <= 1)
322 rlp.rlim_cur = RLIM_INFINITY;
323 else
324 rlp.rlim_cur = atoi(a[1]);
325
326 int status;
327 status=setrlimit(RLIMIT_CPU,&rlp);
328 if (status !=0)
329 di << "status cpulimit setrlimit : " << status << "\n";
330
331#else
332//WNT
47cbc555 333 static int aFirst = 1;
7fd59977 334
47cbc555
A
335 unsigned int __stdcall CpuFunc (void *);
336 unsigned aThreadID;
337
338 if (n <= 1)
339 MDTV_CPU_LIMIT = RLIM_INFINITY;
340 else
341 {
342 MDTV_CPU_LIMIT = atoi (a[1]);
343 Standard_Real anUserSeconds, aSystemSeconds;
344 OSD_Chronometer::GetProcessCPU (anUserSeconds, aSystemSeconds);
345 MDTV_CPU_CURRENT = clock_t(anUserSeconds + aSystemSeconds);
346
347 if (aFirst) // Launch the thread only at the 1st call.
348 {
349 aFirst = 0;
350 _beginthreadex (NULL, 0, CpuFunc, NULL, 0, &aThreadID);
351 }
7fd59977 352 }
353
7fd59977 354#endif
355
356 return 0;
357}
358
7af17f1e
MA
359//=======================================================================
360//function : mallochook
361//purpose :
362//=======================================================================
363
364static Standard_Integer mallochook(Draw_Interpretor& di, Standard_Integer n,
365 const char** a)
366{
367 if (n < 2)
368 {
369 di << "\
370usage: mallochook cmd\n\
371where cmd is one of:\n\
372 set [<op>] - set callback to malloc/free; op is one of the following:\n\
373 0 - set callback to NULL,\n\
374 1 - set callback OSD_MAllocHook::CollectBySize (default)\n\
375 2 - set callback OSD_MAllocHook::LogFileHandler\n\
376 reset - reset the CollectBySize handler\n\
377 report1 [<outfile>]\n\
378 - write report from CollectBySize handler in <outfile>\n\
379 open [<logfile>]\n\
380 - open file for writing the log with LogFileHandler\n\
381 close - close the log file with LogFileHandler\n\
382 report2 [<flag>] [<logfile>] [<outfile>]\n\
383 - scan <logfile> written with LogFileHandler\n\
384 and make synthesized report in <outfile>; <flag> can be:\n\
385 0 - simple stats by sizes (default),\n\
386 1 - with alive allocation numbers\n\
387By default <logfile> is \"mem-log.txt\", <outfile> is \"mem-stat.txt\""
388 << "\n";
389 return 0;
390 }
391 if (strcmp(a[1], "set") == 0)
392 {
393 int aType = (n > 2 ? atoi(a[2]) : 1);
394 if (aType < 0 || aType > 2)
395 {
396 di << "unknown op of the command set" << "\n";
397 return 1;
398 }
399 else if (aType == 0)
400 {
401 OSD_MAllocHook::SetCallback(NULL);
402 di << "callback is unset" << "\n";
403 }
404 else if (aType == 1)
405 {
406 OSD_MAllocHook::SetCallback(OSD_MAllocHook::GetCollectBySize());
407 di << "callback is set to CollectBySize" << "\n";
408 }
409 else //if (aType == 2)
410 {
411 OSD_MAllocHook::SetCallback(OSD_MAllocHook::GetLogFileHandler());
412 di << "callback is set to LogFileHandler" << "\n";
413 }
414 }
415 else if (strcmp(a[1], "reset") == 0)
416 {
417 OSD_MAllocHook::GetCollectBySize()->Reset();
418 di << "CollectBySize handler is reset" << "\n";
419 }
420 else if (strcmp(a[1], "open") == 0)
421 {
422 const char* aFileName = (n > 2 ? a[2] : "mem-log.txt");
423 if (!OSD_MAllocHook::GetLogFileHandler()->Open(aFileName))
424 {
425 di << "cannot create file " << aFileName << " for writing" << "\n";
426 return 1;
427 }
428 di << "log file " << aFileName << " is opened for writing" << "\n";
429 }
430 else if (strcmp(a[1], "close") == 0)
431 {
432 OSD_MAllocHook::GetLogFileHandler()->Close();
433 di << "log file is closed" << "\n";
434 }
435 else if (strcmp(a[1], "report1") == 0)
436 {
437 const char* aOutFile = "mem-stat.txt";
438 if (n > 2)
439 aOutFile = a[2];
440 if (OSD_MAllocHook::GetCollectBySize()->MakeReport(aOutFile))
441 {
442 di << "report " << aOutFile << " has been created" << "\n";
443 }
444 else
445 {
446 di << "cannot create report " << aOutFile << "\n";
447 return 1;
448 }
449 }
450 else if (strcmp(a[1], "report2") == 0)
451 {
452 Standard_Boolean includeAlive = Standard_False;
453 const char* aLogFile = "mem-log.txt";
454 const char* aOutFile = "mem-stat.txt";
455 if (n > 2)
456 {
457 includeAlive = (atoi(a[2]) != 0);
458 if (n > 3)
459 {
460 aLogFile = a[3];
461 if (n > 4)
462 aOutFile = a[4];
463 }
464 }
465 if (OSD_MAllocHook::LogFileHandler::MakeReport(aLogFile, aOutFile, includeAlive))
466 {
467 di << "report " << aOutFile << " has been created" << "\n";
468 }
469 else
470 {
471 di << "cannot create report " << aOutFile << " from the log file "
472 << aLogFile << "\n";
473 return 1;
474 }
475 }
476 else
477 {
478 di << "unrecognized command " << a[1] << "\n";
479 return 1;
480 }
481 return 0;
482}
483
f0430952 484//==============================================================================
485//function : dmeminfo
486//purpose :
487//==============================================================================
488
489static int dmeminfo (Draw_Interpretor& theDI,
490 Standard_Integer theArgNb,
491 const char** theArgVec)
492{
493 OSD_MemInfo aMemInfo;
494 if (theArgNb <= 1)
495 {
496 theDI << aMemInfo.ToString();
497 return 0;
498 }
499
500 for (Standard_Integer anIter = 1; anIter < theArgNb; ++anIter)
501 {
502 TCollection_AsciiString anArg (theArgVec[anIter]);
503 anArg.LowerCase();
504 if (anArg == "virt" || anArg == "v")
505 {
506 theDI << Standard_Real (aMemInfo.Value (OSD_MemInfo::MemVirtual)) << " ";
507 }
508 else if (anArg == "wset" || anArg == "w")
509 {
510 theDI << Standard_Real (aMemInfo.Value (OSD_MemInfo::MemWorkingSet)) << " ";
511 }
512 else if (anArg == "wsetpeak")
513 {
514 theDI << Standard_Real (aMemInfo.Value (OSD_MemInfo::MemWorkingSetPeak)) << " ";
515 }
516 else if (anArg == "swap")
517 {
518 theDI << Standard_Real (aMemInfo.Value (OSD_MemInfo::MemSwapUsage)) << " ";
519 }
520 else if (anArg == "swappeak")
521 {
522 theDI << Standard_Real (aMemInfo.Value (OSD_MemInfo::MemSwapUsagePeak)) << " ";
523 }
524 else if (anArg == "private")
525 {
526 theDI << Standard_Real (aMemInfo.Value (OSD_MemInfo::MemPrivate)) << " ";
527 }
528 else
529 {
530 std::cerr << "Unknown argument '" << theArgVec[anIter] << "'!\n";
531 }
532 }
533 theDI << "\n";
534 return 0;
535}
7fd59977 536
537void Draw::BasicCommands(Draw_Interpretor& theCommands)
538{
539 static Standard_Boolean Done = Standard_False;
540 if (Done) return;
541 Done = Standard_True;
542
aa02980d 543 ios::sync_with_stdio();
544
7fd59977 545 const char* g = "DRAW General Commands";
546
547 theCommands.Add("batch", "returns 1 in batch mode",
548 __FILE__,ifbatch,g);
549 theCommands.Add("spy","spy [file], Save commands in file. no file close",
550 __FILE__,spy,g);
551 theCommands.Add("wait","wait [time(10)], wait time seconds",
552 __FILE__,Draw_wait,g);
553 theCommands.Add("cpulimit","cpulimit [nbseconds], no args remove limits",
554 __FILE__,cpulimit,g);
555 theCommands.Add("chrono","chrono [ name start/stop/reset/show]",
556 __FILE__,chronom,g);
557 theCommands.Add("dchrono","dchrono [ name start/stop/reset/show]",
558 __FILE__,dchronom,g);
7af17f1e
MA
559 theCommands.Add("mallochook",
560 "debug memory allocation/deallocation, w/o args for help",
561 __FILE__, mallochook, g);
f0430952 562 theCommands.Add ("meminfo",
563 "meminfo [virt|v] [wset|w] [wsetpeak] [swap] [swappeak] [private]"
564 " : memory counters for this process",
565 __FILE__, dmeminfo, g);
aa02980d 566
567 // Logging commands; note that their names are hard-coded in the code
568 // of Draw_Interpretor, thus should not be changed without update of that code!
569 theCommands.Add("dlog", "manage logging of commands and output; run without args to get help",
570 __FILE__,dlog,g);
571 theCommands.Add("decho", "switch on / off echo of commands to cout; run without args to get help",
572 __FILE__,decho,g);
7fd59977 573}