Scilab debugger updates
[scilab.git] / scilab / modules / core / src / cpp / InitScilab.cpp
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2013 - Scilab Enterprises - Antoine ELIAS
4  * Copyright (C) 2013 - Scilab Enterprises - Cedric DELAMARRE
5  *
6  * Copyright (C) 2012 - 2016 - Scilab Enterprises
7  *
8  * This file is hereby licensed under the terms of the GNU GPL v2.0,
9  * pursuant to article 5.3.4 of the CeCILL v.2.1.
10  * This file was originally licensed under the terms of the CeCILL v2.1,
11  * and continues to be available under such terms.
12  * For more information, see the COPYING file which you should have received
13  * along with this program.
14  *
15  */
16
17 #include <string>
18 #include <libxml/parser.h>
19
20 #include "inspector.hxx"
21 #include "double.hxx"
22 #include "polynom.hxx"
23 #include "string.hxx"
24 #include "bool.hxx"
25
26 #include "scilabWrite.hxx"
27 #include "tasks.hxx"
28 #include "parser.hxx"
29 #include "context.hxx"
30 #include "configvariable.hxx"
31 #include "filemanager.hxx"
32 #include "runner.hxx"
33 #include "visitor_common.hxx"
34 #include "operations.hxx"
35 #include "threadmanagement.hxx"
36 #include "numericconstants.hxx"
37 #include "expandPathVariable.h"
38 #include "execvisitor.hxx"
39 #include "printvisitor.hxx"
40 #include "debugmanager.hxx"
41 #include "consoledebugger.hxx"
42
43 extern "C"
44 {
45 #include <locale.h>
46 #include "machine.h"
47 #include "InitializeLocalization.h"
48 #include "elem_common.h"
49 #include "InitializeJVM.h"
50 #include "TerminateJVM.h"
51 #include "InitializeGUI.h"
52 #include "graphicModuleLoad.h"
53 #include "TerminateGraphics.h"
54 #include "loadBackGroundClassPath.h"
55 #include "sci_tmpdir.h"
56 #include "setgetlanguage.h"
57 #include "InitializeConsole.h"
58 #include "InitializeHistoryManager.h"
59 #include "TerminateHistoryManager.h"
60 #include "prompt.h"
61 #include "scilabRead.h"
62 #include "functions_manager.h"
63 #include "InitScilab.h"
64 #include "setenvvar.h"
65 #include "getScilabPreference.h"
66 #include "saveCWDInPreferences.h"
67 #include "h5_fileManagement.h"
68 #include "with_fftw.h"
69 #include "BrowseVarManager.h"
70 #include "scicurdir.h"
71 #include "FileBrowserChDir.h"
72 #include "InitializePreferences.h"
73
74 #ifdef _MSC_VER
75 #include "InitializeWindows_tools.h"
76 #include "TerminateWindows_tools.h"
77 #include "WndThread.h"
78 #include "console.h"
79 #include "InnosetupMutex.h"
80 #include "MutexClosingScilab.h"
81 #include "WinConsole.h"
82 #include "SignalManagement.h"
83 #include "splashScreen.h"
84 #else
85 #include "signal_mgmt.h"
86 #include "initConsoleMode.h"
87 #endif
88
89 #if defined(linux) && defined(__i386__)
90 #include "setPrecisionFPU.h"
91 #endif
92
93 #include "InitializeTclTk.h"
94 #include "dynamic_link.h"
95
96     /* Defined without include to avoid useless header dependency */
97     extern BOOL isItTheDisabledLib(void);
98 }
99
100 static void Add_i(void);
101 static void Add_pi(void);
102 static void Add_eps(void);
103 static void Add_e(void);
104 static void Add_s(void);
105 static void Add_z(void);
106 static void Add_gui(void);
107 static void Add_fftw(void);
108 static void Add_Nan(void);
109 static void Add_Inf(void);
110 static void Add_io(void);
111 static void Add_All_Variables(void);
112 static void Add_Double_Constant(const std::wstring& _szName, double _dblReal, double _dblImg, bool _bComplex);
113 static void Add_Poly_Constant(const std::wstring& _szName, const std::wstring& _szPolyVar, int _iRank, types::Double * _pdblReal);
114 static void Add_Boolean_Constant(const std::wstring& _szName, bool _bBool);
115 static void Add_String_Constant(const std::wstring& _szName, const char *_pstString);
116 static void checkForLinkerErrors(void);
117
118 static int batchMain(ScilabEngineInfo* _pSEI);
119 static int InitializeEnvironnement(void);
120 static int interactiveMain(ScilabEngineInfo* _pSEI);
121 static void processCommand(ScilabEngineInfo* _pSEI);
122 static void stateShow(Parser::ControlStatus status);
123
124 static void executeDebuggerCommand(std::string cmd);
125 static void splitOnSpaces(const std::string& command, std::vector<std::string>& vCommand, std::vector<size_t>& vPos);
126 static void printDebuggerHelp();
127
128 using namespace ast;
129
130 ScilabEngineInfo* InitScilabEngineInfo()
131 {
132     // Disable all startup flags.
133     ScilabEngineInfo* pSEI = (ScilabEngineInfo*)CALLOC(1, sizeof(ScilabEngineInfo));
134
135     //Active default flags
136     pSEI->iExecAst = 1;
137     pSEI->iNoBanner = 1;
138
139     pSEI->iMultiLine = 0;
140     pSEI->isInterruptible = 1;      // by default all thread are interruptible
141     pSEI->isPrioritary = 0;         // by default all thread are non-prioritary
142     pSEI->iStartConsoleThread = 1;  // used in call_scilab to avoid "prompt" thread execution
143     pSEI->iForceQuit = 0;           // management of -quit argument
144     pSEI->iTimeoutDelay = 0;        // watchdog delay to avoid deadlocking tests
145     pSEI->iCommandOrigin = NONE;
146
147     pSEI->iCodeAction = -1; //default value, no code action ( used on windows by file associations -O -X -P arguments)
148     return pSEI;
149 }
150
151 int StartScilabEngine(ScilabEngineInfo* _pSEI)
152 {
153     int iMainRet = 0;
154     ConfigVariable::setStartProcessing(true);
155
156     // Update scihome from command line
157     if (_pSEI->pstSciHome && strcmp(_pSEI->pstSciHome, "") != 0)
158     {
159         wchar_t* w = to_wide_string(_pSEI->pstSciHome);
160         ConfigVariable::setSCIHOME(w);
161         FREE(w);
162     }
163
164     // ignore -e argument if the command is empty
165     if (_pSEI->pstExec && strcmp(_pSEI->pstExec, "") == 0)
166     {
167         _pSEI->pstExec = NULL;
168     }
169
170     // ignore -quit if -e or -f are not given
171     _pSEI->iForceQuit = _pSEI->iForceQuit && (_pSEI->pstExec || _pSEI->pstFile);
172     ConfigVariable::setForceQuit(_pSEI->iForceQuit == 1);
173
174     // setup timeout delay
175     if (_pSEI->iTimeoutDelay != 0)
176     {
177         timeout_process_after(_pSEI->iTimeoutDelay);
178     }
179
180     /* This bug only occurs under Linux 32 bits
181      * See: http://wiki.scilab.org/Scilab_precision
182      */
183 #if defined(linux) && defined(__i386__)
184     setFPUToDouble();
185 #endif
186
187 #ifndef _MSC_VER
188     /* Management of the signals (seg fault, floating point exception, etc) */
189     if (getenv("SCI_DISABLE_EXCEPTION_CATCHING") == NULL)
190     {
191         base_error_init();
192     }
193 #endif
194
195 #if defined(netbsd) || defined(freebsd)
196     /* floating point exceptions */
197     fpsetmask(0);
198 #endif
199
200     ThreadManagement::initialize();
201     NumericConstants::Initialize();
202     checkForLinkerErrors();
203
204 #ifdef _MSC_VER
205
206     //get current console window and hide it
207     int scilabMode = getScilabMode();
208
209 #ifndef _DEBUG
210     if (scilabMode == SCILAB_STD && _pSEI->pstFile == NULL && _pSEI->pstExec == NULL)
211     {
212         splashScreen();
213     }
214 #endif
215
216     if (scilabMode == SCILAB_STD || scilabMode == SCILAB_NW || scilabMode == SCILAB_API)
217     {
218         CreateScilabHiddenWndThread();
219     }
220
221     if (scilabMode == SCILAB_STD)
222     {
223         //show banner in console window
224         CreateScilabConsole(_pSEI->iNoBanner);
225
226         if (_pSEI->iKeepConsole == 0)
227         {
228             HideScilex(); /* hide console window */
229         }
230         else
231         {
232             ShowScilex();
233         }
234     }
235     else
236     {
237         if (scilabMode == SCILAB_NW || scilabMode == SCILAB_NWNI)
238         {
239             SaveConsoleColors();
240             if (scilabMode == SCILAB_NW)
241             {
242                 RenameConsole();
243                 UpdateConsoleColors();
244             }
245         }
246     }
247
248     //create a thread for innosetup to allow reinstall during scilab running
249     createInnosetupMutex();
250 #endif
251
252     //open scope lvl 0 for gateway from modules and first variables ( SCI, HOME, TMPDIR, ...)
253     symbol::Context::getInstance()->scope_begin();
254
255     /* Scilab Startup */
256     xmlInitParser();
257     InitializeEnvironnement();
258
259     if (_pSEI->pstLang)
260     {
261         wchar_t *pwstLang = to_wide_string(_pSEI->pstLang);
262         setlanguage(pwstLang);
263         FREE(pwstLang);
264     }
265
266 #ifdef _MSC_VER
267     InitializeWindows_tools();
268 #endif
269
270     if (_pSEI->iNoJvm == 0) // With JVM
271     {
272         InitializeTclTk();
273         InitializeJVM();
274         InitializeGUI(_pSEI->iWebMode == 0 ? TRUE : FALSE);
275
276         /* create needed data structure if not already created */
277         loadGraphicModule();
278
279         loadBackGroundClassPath();
280
281         //update %gui to true
282         Add_Boolean_Constant(L"%gui", true);
283     }
284
285     // Make sure the default locale is applied at startup
286     setlocale(LC_NUMERIC, "C");
287
288     /* Standard mode -> init Java Console */
289     if (_pSEI->iConsoleMode == 0)
290     {
291         /* Initialize console: lines... */
292         InitializeConsole();
293     }
294     else
295     {
296 #ifndef _MSC_VER
297         initConsoleMode(RAW);
298 #endif
299     }
300
301     //set prompt value
302     setPreviousLevel(0);
303
304     //load gateways
305     if (LoadModules() == false)
306     {
307         //clear opened files
308         FileManager::destroy();
309         return 1;
310     }
311
312     //variables are needed by loadModules but must be in SCOPE_CONSOLE under protection
313     //remove (W)SCI/SCIHOME/HOME/TMPDIR
314     types::InternalType* sci = symbol::Context::getInstance()->get(symbol::Symbol(L"SCI"));
315     types::InternalType* wsci = symbol::Context::getInstance()->get(symbol::Symbol(L"WSCI"));
316     types::InternalType* scihome = symbol::Context::getInstance()->get(symbol::Symbol(L"SCIHOME"));
317     types::InternalType* home = symbol::Context::getInstance()->get(symbol::Symbol(L"home"));
318     types::InternalType* tmpdir = symbol::Context::getInstance()->get(symbol::Symbol(L"TMPDIR"));
319
320     sci->IncreaseRef();
321     if (wsci)
322     {
323         wsci->IncreaseRef();
324     }
325     scihome->IncreaseRef();
326     home->IncreaseRef();
327     tmpdir->IncreaseRef();
328
329     symbol::Context::getInstance()->remove(symbol::Symbol(L"SCI"));
330     symbol::Context::getInstance()->remove(symbol::Symbol(L"WSCI"));
331     symbol::Context::getInstance()->remove(symbol::Symbol(L"SCIHOME"));
332     symbol::Context::getInstance()->remove(symbol::Symbol(L"home"));
333     symbol::Context::getInstance()->remove(symbol::Symbol(L"TMPDIR"));
334
335     //open a scope for macros
336     symbol::Context::getInstance()->scope_begin();
337
338     //put var in good scope
339     Add_All_Variables();
340     symbol::Context::getInstance()->put(symbol::Symbol(L"SCI"), sci);
341     if (wsci)
342     {
343         symbol::Context::getInstance()->put(symbol::Symbol(L"WSCI"), wsci);
344     }
345
346     symbol::Context::getInstance()->put(symbol::Symbol(L"SCIHOME"), scihome);
347     symbol::Context::getInstance()->put(symbol::Symbol(L"home"), home);
348     symbol::Context::getInstance()->put(symbol::Symbol(L"TMPDIR"), tmpdir);
349
350     sci->DecreaseRef();
351     if (wsci)
352     {
353         wsci->DecreaseRef();
354     }
355     scihome->DecreaseRef();
356     home->DecreaseRef();
357     tmpdir->DecreaseRef();
358
359
360     symbol::Context::getInstance()->protect();
361     //execute scilab.start
362     if (_pSEI->iNoStart == 0)
363     {
364         int ierr = execScilabStartTask(_pSEI->iSerialize != 0);
365         if (ierr)
366         {
367             return ierr;
368         }
369     }
370
371     //open console scope
372     //symbol::Context::getInstance()->scope_begin();
373
374     ConfigVariable::setStartProcessing(false);
375
376     ConfigVariable::setPromptMode(0);
377     int iScript = 0;
378     if (_pSEI->pstExec)
379     {
380         //-e option
381         Parser parser;
382         parseCommandTask(&parser, _pSEI->iTimed != 0, _pSEI->pstExec);
383
384         if (parser.getExitStatus() == Parser::Failed)
385         {
386             scilabWriteW(parser.getErrorMessage());
387         }
388         else if (parser.getControlStatus() !=  Parser::AllControlClosed)
389         {
390             _pSEI->iMultiLine = 1;
391         }
392         else
393         {
394             StoreConsoleCommand(_pSEI->pstExec, 0);
395         }
396
397         if (parser.getTree())
398         {
399             delete parser.getTree();
400             parser.setTree(NULL);
401         }
402         iMainRet = ConfigVariable::getExitStatus();
403         iScript = 1;
404
405         if (_pSEI->iCodeAction != -1)
406         {
407             //alloc in main to manage shell interaction
408             FREE(_pSEI->pstExec);
409             _pSEI->pstExec = NULL;
410         }
411     }
412     else if (_pSEI->pstFile)
413     {
414         //-f option execute exec('%s',-1)
415         char *pstCommand = (char *)MALLOC(sizeof(char) * (strlen("exec(\"\",-1)") + strlen(_pSEI->pstFile) + 1));
416         sprintf(pstCommand, "exec(\"%s\",-1)", _pSEI->pstFile);
417
418         StoreConsoleCommand(pstCommand, 0);
419         FREE(pstCommand);
420         iMainRet = ConfigVariable::getExitStatus();
421         _pSEI->pstExec = NULL;
422         _pSEI->pstFile = NULL;
423         iScript = 1;
424     }
425
426     ConfigVariable::setPromptMode(2);
427     InitializePreferences(iScript);
428
429     return iMainRet;
430 }
431
432 int RunScilabEngine(ScilabEngineInfo* _pSEI)
433 {
434     if (_pSEI->pstParseFile)
435     {
436         // Only for parsing test, won't execute anything.
437         return batchMain(_pSEI);
438     }
439     else
440     {
441         //always run as interactiveMain even after -e or -f option
442         return interactiveMain(_pSEI);
443     }
444 }
445
446 int ExecExternalCommand(ScilabEngineInfo* _pSEI)
447 {
448     if (_pSEI->pstExec)
449     {
450         StoreConsoleCommand(_pSEI->pstExec, 1);
451         return ConfigVariable::getExitStatus();
452     }
453
454     return -1;
455 }
456
457 void StopScilabEngine(ScilabEngineInfo* _pSEI)
458 {
459     ConfigVariable::setEndProcessing(true);
460 #ifdef _MSC_VER
461     /* bug 3672 */
462     /* Create a Mutex (closing scilab)
463      * used by files association
464      */
465     createMutexClosingScilab();
466 #endif
467
468     clearScilabPreferences();
469
470     if (_pSEI->pstFile)
471     {
472         //-f option execute exec('%s',-1)
473         char *pstCommand = (char *)MALLOC(sizeof(char) * (strlen("exec(\"\",-1)") + strlen(_pSEI->pstFile) + 1));
474         sprintf(pstCommand, "exec(\"%s\",-1)", _pSEI->pstFile);
475
476         _pSEI->pstExec = pstCommand;
477         processCommand(_pSEI);
478         FREE(pstCommand);
479     }
480     else if (_pSEI->iNoStart == 0)
481     {
482         //execute scilab.quit
483         execScilabQuitTask(_pSEI->iSerialize != 0);
484         //call all modules.quit
485         EndModules();
486     }
487
488     // close macros scope
489     symbol::Context::getInstance()->scope_end();
490
491     //close gateways scope
492     symbol::Context::getInstance()->scope_end();
493
494     //clean context
495     symbol::Context::getInstance()->clearAll();
496     //destroy context
497     symbol::Context::destroyInstance();
498
499 #ifndef NDEBUG
500     //uncomment to print mem leak log
501     //types::Inspector::displayMemleak();
502 #endif
503
504     //close dynamic linked libraries
505     std::vector<ConfigVariable::DynamicLibraryStr*>* pDLLIst = ConfigVariable::getDynamicLibraryList();
506     int size = static_cast<int>(pDLLIst->size());
507     for (int i = 0; i < size; i++)
508     {
509         ConfigVariable::DynamicLibraryStr* pStr = ConfigVariable::getDynamicLibrary(i);
510         if (pStr)
511         {
512             DynLibHandle iLib = pStr->hLib;
513             ConfigVariable::removeDynamicLibrary(i);
514             Sci_dlclose(iLib);
515         }
516     }
517
518     // cleanup Java dependent features
519     saveCWDInPreferences();
520     clearScilabPreferences();
521     TerminateHistoryManager();
522
523     // stop the JVM
524     if (_pSEI->iNoJvm == 0)
525     {
526         TerminateGraphics();
527         TerminateJVM();
528     }
529
530     // reset struct to prevent the use of deleted objects
531     // when we start scilab again without kill process (ie: call_scilab)
532     resetVariableValueDefinedInScilab();
533
534     /* TerminateCorePart2 */
535
536     //clear opened files
537     FileManager::destroy();
538
539     /* Remove TMPDIR before exit */
540     clearTMPDIR();
541
542     //Unload dynamic modules
543     UnloadModules();
544
545     //destroy function manager
546     destroyfunctionManagerInstance();
547     /* TerminateCorePart2 end */
548
549     /*
550     * Cleanup function for the XML library.
551     */
552     xmlCleanupParser();
553
554     /* Cleanup the parser state */
555     Parser::cleanup();
556
557 #ifdef _MSC_VER
558     TerminateWindows_tools();
559 #endif
560
561     /* Reset terminal configuration */
562     if (_pSEI->iConsoleMode)
563     {
564 #ifndef _MSC_VER
565         initConsoleMode(ATTR_RESET);
566 #endif
567     }
568
569 #ifdef _MSC_VER
570     /* close mutex (closing scilab)
571      * used by files association
572      */
573     terminateMutexClosingScilab();
574 #endif
575
576     ConfigVariable::clearLastError();
577     ConfigVariable::setEndProcessing(false);
578 }
579
580 static void processCommand(ScilabEngineInfo* _pSEI)
581 {
582     /*
583      ** -*- DUMPING TREE -*-
584      */
585     if (_pSEI->iDumpAst)
586     {
587         dumpAstTask((ast::Exp*)_pSEI->pExpTree, _pSEI->iTimed != 0);
588     }
589
590     /*
591      ** -*- PRETTY PRINT TREE -*-
592      */
593     if (_pSEI->iPrintAst)
594     {
595         printAstTask((ast::Exp*)_pSEI->pExpTree, _pSEI->iTimed != 0);
596     }
597
598     /*
599      ** -*- EXECUTING TREE -*-
600      */
601     if (_pSEI->iExecAst)
602     {
603         execAstTask((ast::Exp*)_pSEI->pExpTree, _pSEI->iSerialize != 0,
604                     _pSEI->iTimed != 0, _pSEI->iAstTimed != 0,
605                     _pSEI->iExecVerbose != 0, _pSEI->isInterruptible != 0,
606                     _pSEI->isPrioritary != 0, _pSEI->iCommandOrigin);
607     }
608
609     /*
610      ** -*- DUMPING STACK AFTER EXECUTION -*-
611      */
612     if (_pSEI->iDumpStack)
613     {
614         dumpStackTask(_pSEI->iTimed != 0);
615     }
616 }
617
618 // Thread used to parse and execute Scilab command set in storeCommand
619 void* scilabReadAndExecCommand(void* param)
620 {
621     char* command           = NULL;
622     int iInterruptibleCmd   = 0;
623     int iPrioritaryCmd      = 0;
624
625     command_origin_t iCmdOrigin = NONE;
626
627     ScilabEngineInfo* _pSEI = (ScilabEngineInfo*)param;
628
629     do
630     {
631         if (GetCommand(&command, &iPrioritaryCmd, &iInterruptibleCmd, &iCmdOrigin) == 0)
632         {
633             ThreadManagement::WaitForCommandStoredSignal();
634             continue;
635         }
636
637         // empty command
638         if (command == NULL || strlen(command) == 0)
639         {
640             continue;
641         }
642
643         _pSEI->isInterruptible = iInterruptibleCmd;
644         _pSEI->isPrioritary = iPrioritaryCmd;
645         _pSEI->iCommandOrigin = iCmdOrigin;
646
647         ThreadManagement::LockParser();
648         Parser parser;
649         parser.setParseTrace(_pSEI->iParseTrace != 0);
650         parseCommandTask(&parser, _pSEI->iTimed != 0, command);
651
652         if (parser.getExitStatus() == Parser::Failed)
653         {
654             scilabWriteW(parser.getErrorMessage());
655             ThreadManagement::UnlockParser();
656             FREE(command);
657             continue;
658         }
659
660         _pSEI->pExpTree = parser.getTree();
661         ThreadManagement::UnlockParser();
662
663         processCommand(_pSEI);
664         FREE(command);
665     }
666     while (ConfigVariable::getForceQuit() == false);
667
668     return NULL;
669 }
670
671 //Thread used to parse and set console commands in storeCommand
672 void* scilabReadAndStore(void* param)
673 {
674     Parser::ControlStatus controlStatus = Parser::AllControlClosed;
675
676     char *command = NULL;
677     wchar_t* parserErrorMsg = NULL;
678
679     ScilabEngineInfo* _pSEI = (ScilabEngineInfo*)param;
680
681     if (_pSEI->iMultiLine)
682     {
683         command = _pSEI->pstExec;
684     }
685
686     if (isEmptyCommandQueue() == false)
687     {
688         // unlock main thread
689         ThreadManagement::SendStartPendingSignal();
690
691         // Command stored as console command by -f
692         // We have to wait this execution before
693         // callOnPrompt (ie: onPrompt perform a quit in test_run)
694         ThreadManagement::WaitForConsoleExecDoneSignal();
695     }
696
697     // unlock main thread
698     ThreadManagement::SendStartPendingSignal();
699
700     while (ConfigVariable::getForceQuit() == false)
701     {
702         callOnPrompt();
703
704         Parser parser;
705         parser.setParseTrace(_pSEI->iParseTrace != 0);
706
707         Parser::ParserStatus exitStatus = Parser::Failed;
708
709         if (ConfigVariable::isPrintCompact() == false)
710         {
711             scilabWriteW(L"\n");
712         }
713
714         do
715         {
716             // Show Parser Sate before prompt
717             stateShow(controlStatus);
718
719             int pause = ConfigVariable::getPauseLevel();
720
721             //set prompt value
722            setPreviousLevel(pause);
723
724             if (scilabRead() == 0)
725             {
726                 // happens when the return of scilabRead must not be interpreted by Scilab.
727                 // ie: mscanf, step by step execution (mode 4 or 7)
728                 ThreadManagement::WaitForConsoleExecDoneSignal();
729                 continue;
730             }
731
732             char* pstRead = ConfigVariable::getConsoleReadStr();
733             if (command == NULL)
734             {
735                 command = pstRead;
736                 if (strcmp(command, "") == 0)
737                 {
738                     FREE(command);
739                     command = NULL;
740                     break;
741                 }
742 #ifdef DEBUG_THREAD
743                 ThreadManagement::PrintDebugHead();
744 #endif // DEBUG_THREAD
745             }
746             else
747             {
748                 if (ConfigVariable::isExecutionBreak())
749                 {
750                     //clean parser state and close opened instruction.
751                     if (parser.getControlStatus() != Parser::AllControlClosed)
752                     {
753                         parser.cleanup();
754                         FREE(command);
755                         command = NULL;
756                         parser.setControlStatus(Parser::AllControlClosed);
757                         controlStatus = parser.getControlStatus();
758                     }
759
760                     ConfigVariable::resetExecutionBreak();
761                     break;
762                 }
763                 else
764                 {
765                     //+1 for null termination and +1 for '\n'
766                     size_t iLen = strlen(command) + strlen(pstRead) + 2;
767                     char *pstNewCommand = (char *)MALLOC(iLen * sizeof(char));
768
769 #ifdef _MSC_VER
770                     sprintf_s(pstNewCommand, iLen, "%s\n%s", command, pstRead);
771 #else
772                     sprintf(pstNewCommand, "%s\n%s", command, pstRead);
773 #endif
774                     FREE(pstRead);
775                     FREE(command);
776                     command = pstNewCommand;
777                 }
778             }
779
780             if (ConfigVariable::getEnableDebug())
781             {
782                 executeDebuggerCommand(command);
783                 FREE(command);
784                 command = NULL;
785                 continue;
786             }
787
788             ThreadManagement::LockParser();
789             parseCommandTask(&parser, _pSEI->iTimed != 0, command);
790             controlStatus = parser.getControlStatus();
791             exitStatus = parser.getExitStatus();
792             parserErrorMsg = parser.getErrorMessage();
793             if (parser.getTree())
794             {
795                 delete parser.getTree();
796                 parser.setTree(NULL);
797             }
798             ThreadManagement::UnlockParser();
799         }
800         while (controlStatus != Parser::AllControlClosed);
801
802         if (command == NULL)
803         {
804             continue;
805         }
806
807         if (exitStatus == Parser::Failed)
808         {
809             FREE(command);
810             command = NULL;
811             scilabForcedWriteW(parserErrorMsg);
812             continue;
813         }
814
815         // store the command and wait for this execution ends.
816         StoreConsoleCommand(command, 1);
817
818         FREE(command);
819         command = NULL;
820     }
821
822     // Awake scilabReadAndExecCommand thread in case of scilab exit
823     ThreadManagement::SendCommandStoredSignal();
824     return NULL;
825 }
826
827 /*
828 ** -*- Interactive Main -*-
829 */
830 static int interactiveMain(ScilabEngineInfo* _pSEI)
831 {
832 #ifndef WITH_GUI
833 #ifndef _MSC_VER
834     if (getScilabMode() != SCILAB_NWNI)
835     {
836         fprintf(stderr, "Scilab was compiled without its GUI and advanced features. Run scilab-cli or use the -nwni option.\n");
837         initConsoleMode(ATTR_RESET);
838         exit(1);
839     }
840 #endif
841 #endif
842
843     InitializeHistoryManager();
844
845     if (getScilabMode() != SCILAB_NWNI && getScilabMode() != SCILAB_API)
846     {
847
848         char *cwd = NULL;
849
850         int err = 0;
851
852         UpdateBrowseVar();
853         cwd = scigetcwd(&err);
854         if (cwd)
855         {
856             FileBrowserChDir(cwd);
857             FREE(cwd);
858         }
859     }
860
861     // -e -quit with parser error, command queue is empty
862     if (_pSEI->iForceQuit && isEmptyCommandQueue())
863     {
864         return 1;
865     }
866
867     __threadId threadIdConsole;
868     __threadKey threadKeyConsole;
869     __threadId threadIdCommand;
870     __threadKey threadKeyCommand;
871
872     if (_pSEI->iStartConsoleThread)
873     {
874         // thread to manage console command
875         __CreateThreadWithParams(&threadIdConsole, &threadKeyConsole, &scilabReadAndStore, _pSEI);
876
877         // scilabReadAndStore thread must be execute before scilabReadAndExecCommand
878         // to be such that the -f command stored is not removed
879         // from queue before scilabReadAndStore is waiting for.
880         ThreadManagement::WaitForStartPendingSignal();
881     }
882
883     // thread to manage command stored
884     __CreateThreadWithParams(&threadIdCommand, &threadKeyCommand, &scilabReadAndExecCommand, _pSEI);
885
886 #ifdef DEBUG_THREAD
887     ThreadManagement::SetThreadKey( __GetCurrentThreadKey(), threadKeyCommand, threadKeyConsole);
888 #endif // DEBUG_THREAD
889
890     int iRet = 0;
891     do
892     {
893         // wait for available runner
894         ThreadManagement::WaitForRunMeSignal();
895
896         try
897         {
898             iRet = StaticRunner::launch();
899         }
900         catch (const ast::InternalAbort& /*ia*/)
901         {
902             // go out when exit/quit is called
903             iRet = ConfigVariable::getExitStatus();
904         }
905         catch (const ast::RecursionException& /*re*/)
906         {
907             // go out when exit/quit is called
908             iRet = 1;
909         }
910
911         ThreadManagement::SendAwakeRunnerSignal();
912     }
913     while (ConfigVariable::getForceQuit() == false);
914
915     return iRet;
916 }
917
918 /*
919 ** -*- Batch Main -*-
920 */
921 static int batchMain(ScilabEngineInfo* _pSEI)
922 {
923     /*
924      ** -*- PARSING -*-
925      */
926     Parser *parser = new Parser();
927
928     parser->setParseTrace(_pSEI->iParseTrace != 0);
929
930     wchar_t *pwstFileName = to_wide_string(_pSEI->pstParseFile);
931
932     /*
933      ** -*- PARSING -*-
934      */
935     parseFileTask(parser, _pSEI->iTimed != 0, pwstFileName, L"scilab 6");
936
937     /*
938      ** -*- DUMPING TREE -*-
939      */
940     if (_pSEI->iDumpAst)
941     {
942         dumpAstTask(parser->getTree(), _pSEI->iTimed != 0);
943     }
944
945     if (parser->getExitStatus() == Parser::Succeded)
946     {
947         /*
948          ** -*- PRETTY PRINT TREE -*-
949          */
950         if (_pSEI->iPrintAst)
951         {
952             printAstTask(parser->getTree(), _pSEI->iTimed != 0);
953         }
954
955     }
956     else
957     {
958         scilabWriteW(parser->getErrorMessage());
959     }
960
961 #ifdef DEBUG
962     std::cerr << "To end program press [ENTER]" << std::endl;
963 #endif
964     int ret = parser->getExitStatus();
965     delete parser;
966     FREE(pwstFileName);
967     return ret;
968 }
969
970 /*
971 ** -*- stateView
972 */
973 static void stateShow(Parser::ControlStatus status)
974 {
975     if (status != Parser::AllControlClosed)
976     {
977         SetTemporaryPrompt("  > ");
978     }
979 }
980
981 static int InitializeEnvironnement(void)
982 {
983     SetScilabEnvironment();
984     InitializeLocalization();
985
986     ConfigVariable::setConsoleWidth(75);
987     ConfigVariable::setFormatSize(10);
988     ConfigVariable::setFormatMode(1);
989     //Add_All_Variables();
990     FileManager::initialize();
991     initOperationArray();
992     return 0;
993 }
994
995 /*
996  * Private function to check any linker errors
997  */
998
999 static void checkForLinkerErrors(void)
1000 {
1001 #ifndef _MSC_VER
1002     /*
1003        Depending on the linking order, sometimes, libs are not loaded the right way.
1004        This can cause painful debugging tasks for packager or developer, we are
1005        doing the check to help them.
1006     */
1007 #define LINKER_ERROR_1 "Scilab startup function detected that the function proposed to the engine is the wrong one. Usually, it comes from a linker problem in your distribution/OS.\n"
1008 #define LINKER_ERROR_2 "If you do not know what it means, please report a bug on http://bugzilla.scilab.org/. If you do, you probably know that you should change the link order in SCI/modules/Makefile.am\n"
1009
1010     if (getScilabMode() != SCILAB_NWNI && getScilabMode() != SCILAB_API)
1011     {
1012         if (isItTheDisabledLib())
1013         {
1014             fprintf(stderr, LINKER_ERROR_1);
1015             fprintf(stderr, "Here, Scilab should have 'libscijvm' defined but gets 'libscijvm-disable' instead.\n");
1016             fprintf(stderr, LINKER_ERROR_2);
1017             exit(1);
1018         }
1019     }
1020     else
1021     {
1022         /* NWNI mode */
1023         if (!isItTheDisabledLib())
1024         {
1025             fprintf(stderr, LINKER_ERROR_1);
1026             fprintf(stderr, "Here, Scilab should have 'libscijvm-disable' defined but gets 'libscijvm' instead.\n");
1027             fprintf(stderr, LINKER_ERROR_2);
1028             exit(1);
1029         }
1030     }
1031 #undef LINKER_ERROR_1
1032 #undef LINKER_ERROR_2
1033 #endif
1034 }
1035
1036 static void Add_All_Variables(void)
1037 {
1038     Add_pi();
1039     Add_eps();
1040     Add_e();
1041     Add_i();
1042     Add_s();
1043     Add_z();
1044     Add_gui();
1045     Add_fftw();
1046     Add_Nan();
1047     Add_Inf();
1048     Add_io();
1049 }
1050
1051 static void Add_Nan(void)
1052 {
1053     Add_Double_Constant(L"%nan", NumericConstants::nan, 0, false);
1054 }
1055
1056 static void Add_Inf(void)
1057 {
1058     Add_Double_Constant(L"%inf", NumericConstants::infinity, 0, false);
1059 }
1060
1061 static void Add_gui(void)
1062 {
1063     Add_Boolean_Constant(L"%gui", false);
1064 }
1065
1066 static void Add_fftw(void)
1067 {
1068     Add_Boolean_Constant(L"%fftw", withfftw() == 1);
1069 }
1070
1071 static void Add_pi(void)
1072 {
1073     Add_Double_Constant(L"%pi", M_PI, 0, false);
1074 }
1075
1076 static void Add_eps(void)
1077 {
1078     Add_Double_Constant(L"%eps", NumericConstants::eps_machine, 0, false);
1079 }
1080
1081 static void Add_e(void)
1082 {
1083     Add_Double_Constant(L"%e", 2.71828182845904530, 0, false);
1084 }
1085
1086 static void Add_i(void)
1087 {
1088     Add_Double_Constant(L"%i", 0, 1, true);
1089 }
1090
1091 static void Add_s(void)
1092 {
1093     types::Double dblCoef(1, 2);
1094
1095     dblCoef.set(0, 0, 0);
1096     dblCoef.set(0, 1, 1);
1097
1098     Add_Poly_Constant(L"%s", L"s", 1, &dblCoef);
1099 }
1100
1101 static void Add_z(void)
1102 {
1103     types::Double dblCoef(1, 2);
1104
1105     dblCoef.set(0, 0, 0);
1106     dblCoef.set(0, 1, 1);
1107
1108     Add_Poly_Constant(L"%z", L"z", 1, &dblCoef);
1109 }
1110
1111 static void Add_io(void)
1112 {
1113     types::Double * pVal = new types::Double(1, 2);
1114     pVal->set(0, 5);
1115     pVal->set(1, 6);
1116     symbol::Context::getInstance()->put(symbol::Symbol(L"%io"), pVal);
1117 }
1118
1119 static void Add_Poly_Constant(const std::wstring& _szName, const std::wstring& _szPolyVar, int _iRank, types::Double * _pdbl)
1120 {
1121     types::Polynom * pVar = new types::Polynom(_szPolyVar, 1, 1, &_iRank);
1122     types::SinglePoly *poPoly = pVar->get(0);
1123
1124     poPoly->setCoef(_pdbl);
1125     symbol::Context::getInstance()->put(symbol::Symbol(_szName), pVar);
1126 }
1127
1128 static void Add_Double_Constant(const std::wstring& _szName, double _dblReal, double _dblImg, bool _bComplex)
1129 {
1130     types::Double * pVal = new types::Double(1, 1, _bComplex);
1131     pVal->set(0, 0, _dblReal);
1132     pVal->setImg(0, 0, _dblImg);
1133     symbol::Context::getInstance()->put(symbol::Symbol(_szName), pVal);
1134 }
1135
1136 static void Add_Boolean_Constant(const std::wstring& _szName, bool _bBool)
1137 {
1138     types::Bool * pVal = new types::Bool(_bBool);
1139     symbol::Context::getInstance()->put(symbol::Symbol(_szName), pVal);
1140 }
1141
1142 static void Add_String_Constant(const std::wstring& _szName, const char *_pstString)
1143 {
1144     types::String * ps = new types::String(_pstString);
1145     symbol::Context::getInstance()->put(symbol::Symbol(_szName), ps);
1146 }
1147
1148 // manage debugger commands
1149 static void executeDebuggerCommand(std::string _command)
1150 {
1151     debugger::DebuggerManager* manager = debugger::DebuggerManager::getInstance();
1152     std::vector<std::string> vCommand;
1153     std::vector<size_t> vPos;
1154     splitOnSpaces(_command, vCommand, vPos);
1155
1156     std::string cmd = vCommand[0];
1157     int iSize = vCommand.size();
1158
1159     // check prefix
1160     if (cmd.compare("e")    == 0 ||
1161         cmd.compare("exec") == 0 ||
1162         cmd.compare("r")    == 0 ||
1163         cmd.compare("run")  == 0)
1164     {
1165         if (manager->isInterrupted())
1166         {
1167             // try to execute a command when execution is stopped on a breakpoint
1168             sciprint(_("Debugger is on a breakpoint\n"));
1169             sciprint(_("(c)ontinue or (a)bort current execution before execute a new command\n"));
1170             vCommand.clear();
1171             return;
1172         }
1173
1174         if(iSize == 1)
1175         {
1176             sciprint(_("%s: Command missing.\n"), "run");
1177             sciprint("use 'h' for more information\n\n");
1178             vCommand.clear();
1179             return;
1180         }
1181
1182         // execute a command
1183         char* error = manager->execute(_command.erase(0, _command.find(" ")).data());
1184         if(error)
1185         {
1186             sciprint("Debugger execution failed\n\n%s\n", error);
1187             vCommand.clear();
1188             return;
1189         }
1190     }
1191     else if(cmd.compare("d")     == 0 ||
1192             cmd.compare("disp")  == 0 ||
1193             cmd.compare("p")     == 0 ||
1194             cmd.compare("print") == 0)
1195     {
1196         if(iSize < 2)
1197         {
1198             sciprint(_("%s: Wrong number of input arguments: %d expected.\n"), "print", 2);
1199             sciprint("use 'h' for more information\n\n");
1200             vCommand.clear();
1201             return;
1202         }
1203
1204         manager->print(vCommand[1]);
1205     }
1206     else if(cmd.compare("a")      == 0 ||
1207             cmd.compare("abort")  == 0)
1208     {
1209         manager->abort();
1210     }
1211     else if(cmd.compare("c")         == 0 ||
1212             cmd.compare("continue")  == 0 ||
1213             cmd.compare("resume")    == 0)
1214     {
1215         if (manager->isInterrupted() == false)
1216         {
1217             // cannot execute this comment if the execution is not stopped
1218             sciprint("debugger is not on a breakpoint\n");
1219             vCommand.clear();
1220             return;
1221         }
1222
1223         manager->resume();
1224     }
1225     else if(cmd.compare("b")           == 0 ||
1226             cmd.compare("break")       == 0 ||
1227             cmd.compare("breakpoint")  == 0)
1228     {
1229         if(iSize < 2)
1230         {
1231             sciprint(_("%s: Wrong number of input arguments: %d to %d expected.\n"), "breakpoint", 1, 3);
1232             sciprint("use 'h' for more information\n\n");
1233             vCommand.clear();
1234             return;
1235         }
1236
1237         debugger::Breakpoint* bp = new debugger::Breakpoint();
1238
1239         // set file or function name
1240         bool isFile = vCommand[1].find_first_of("\\./") != std::string::npos;
1241         isFile ? bp->setFileName(vCommand[1]) : bp->setFunctionName(vCommand[1]);
1242
1243         // set file or function line
1244         if(iSize > 2)
1245         {
1246             try
1247             {
1248                 int iFileFuncLine = std::stoi(vCommand[2].data());
1249                 isFile ? bp->setFileLine(iFileFuncLine) : bp->setMacroLine(iFileFuncLine);
1250             }
1251             catch(std::invalid_argument e) // std::stoi
1252             {
1253                 sciprint(_("%s: Wrong type for input argument #%d: Integer expected.\n"), "breakpoint", 2);
1254                 sciprint("use 'h' for more information\n\n");
1255                 vCommand.clear();
1256                 return;
1257             }
1258         }
1259
1260         // set condition
1261         if(iSize > 3)
1262         {
1263             char* error = bp->setCondition(_command.substr(vPos[3], _command.length() - vPos[3]));
1264             if(error)
1265             {
1266                 delete bp;
1267                 bp = nullptr;
1268                 sciprint("parsing condition failed\n\n%s\n", error);
1269                 FREE(error);
1270                 vCommand.clear();
1271                 return;
1272             }
1273         }
1274
1275         manager->addBreakPoint(bp);
1276     }
1277     else if(cmd.compare("w")     == 0 ||
1278             cmd.compare("bt")    == 0 ||
1279             cmd.compare("where") == 0)
1280     {
1281         if (manager->isInterrupted() == false)
1282         {
1283             // cannot execute this comment if the execution is not stopped
1284             sciprint("debugger is not on a breakpoint\n");
1285             vCommand.clear();
1286             return;
1287         }
1288
1289         sciprint("%s\n", _("callstack:"));
1290         debugger::DebuggerManager::CallStack callstack = manager->getCallStack();
1291         int i = 0;
1292         sciprint("#%-5d%s\n", i++, callstack.exp.data());
1293         for (auto row : callstack.stack)
1294         {
1295             if(row.functionLine < 0)
1296             {
1297                 sciprint(_("#%-5d%s"), i++, row.functionName.data());
1298             }
1299             else
1300             {
1301                 sciprint(_("#%-5d%s (line %d)"), i++, row.functionName.data(), row.functionLine);
1302             }
1303
1304             if(row.hasFile)
1305             {
1306                 sciprint("  %s:%d", row.fileName.data(), row.fileLine);
1307             }
1308
1309             sciprint("\n");
1310         }
1311     }
1312     else if(cmd.compare("disable") == 0)
1313     {
1314         if(iSize == 1)
1315         {
1316             manager->disableAllBreakPoints();
1317         }
1318         else
1319         {
1320             try
1321             {
1322                 int bp = std::stoi(vCommand[1].data());
1323                 if (manager->getBreakPoint(bp) == NULL)
1324                 {
1325                     sciprint(_("%s: Unable to retrieve information about breakpoint %d.\n"), "disable", bp);
1326                     sciprint("use 'h' for more information\n\n");
1327                     vCommand.clear();
1328                     return;
1329                 }
1330                 manager->disableBreakPoint(bp);
1331             }
1332             catch(std::invalid_argument e) // std::stoi
1333             {
1334                 sciprint(_("%s: Wrong type for input argument #%d: Integer expected.\n"), "disable", 1);
1335                 sciprint("use 'h' for more information\n\n");
1336                 vCommand.clear();
1337                 return;
1338             }
1339         }
1340     }
1341     else if(cmd.compare("enable") == 0)
1342     {
1343         if(iSize == 1)
1344         {
1345             manager->enableAllBreakPoints();
1346         }
1347         else
1348         {
1349             try
1350             {
1351                 int bp = std::stoi(vCommand[1].data());
1352                 if (manager->getBreakPoint(bp) == NULL)
1353                 {
1354                     sciprint(_("%s: Unable to retrieve information about breakpoint %d.\n"), "enable", bp);
1355                     sciprint("use 'h' for more information\n\n");
1356                     vCommand.clear();
1357                     return;
1358                 }
1359                 manager->enableBreakPoint(bp);
1360             }
1361             catch(std::invalid_argument e) // std::stoi
1362             {
1363                 sciprint(_("%s: Wrong type for input argument #%d: Integer expected.\n"), "enable", 1);
1364                 sciprint("use 'h' for more information\n\n");
1365                 vCommand.clear();
1366                 return;
1367             }
1368         }
1369     }
1370     else if(cmd.compare("del")   == 0 ||
1371             cmd.compare("delete") == 0)
1372     {
1373         if(iSize == 1)
1374         {
1375             manager->removeAllBreakPoints();
1376         }
1377         else
1378         {
1379             try
1380             {
1381                 int bp = std::stoi(vCommand[1].data());
1382                 if (manager->getBreakPoint(bp) == NULL)
1383                 {
1384                     sciprint(_("%s: Unable to retrieve information about breakpoint %d.\n"), "delete", bp);
1385                     sciprint("use 'h' for more information\n\n");
1386                     vCommand.clear();
1387                     return;
1388                 }
1389                 manager->removeBreakPoint(bp);
1390             }
1391             catch(std::invalid_argument e) // std::stoi
1392             {
1393                 sciprint(_("%s: Wrong type for input argument #%d: Integer expected.\n"), "delete", 1);
1394                 sciprint("use 'h' for more information\n\n");
1395                 vCommand.clear();
1396                 return;
1397             }
1398         }
1399     }
1400     else if(cmd.compare("h")     == 0 ||
1401             cmd.compare("help")  == 0)
1402     {
1403         if(cmd.compare("help") == 0 &&
1404           (ConfigVariable::getScilabMode() == SCILAB_NW || ConfigVariable::getScilabMode() == SCILAB_STD))
1405         {
1406             StorePrioritaryCommand("help debug");
1407             vCommand.clear();
1408             return;
1409         }
1410
1411         printDebuggerHelp();
1412     }
1413     else if(cmd.compare("l")     == 0 ||
1414             cmd.compare("list")  == 0)
1415     {
1416         if (manager->isInterrupted() == false)
1417         {
1418             // cannot execute this comment if the execution is not stopped
1419             sciprint("debugger is not on a breakpoint\n");
1420             vCommand.clear();
1421             return;
1422         }
1423
1424         std::wostringstream ostr;
1425         ast::PrintVisitor pp(ostr, true, true, true);
1426         manager->getExp()->accept(pp);
1427         sciprint(_("%ls"), ostr.str().data());
1428     }
1429     else if(cmd.compare("i")      == 0 ||
1430             cmd.compare("in")     == 0 ||
1431             cmd.compare("stepin") == 0)
1432     {
1433         if (manager->isInterrupted() == false)
1434         {
1435             // cannot execute this comment if the execution is not stopped
1436             sciprint("debugger is not on a breakpoint\n");
1437             vCommand.clear();
1438             return;
1439         }
1440
1441         manager->setStepIn();
1442         manager->resume();
1443     }
1444     else if(cmd.compare("o")         == 0 ||
1445             cmd.compare("out")       == 0 ||
1446             cmd.compare("stepout")   == 0)
1447     {
1448         if (manager->isInterrupted() == false)
1449         {
1450             // cannot execute this comment if the execution is not stopped
1451             sciprint("debugger is not on a breakpoint\n");
1452             vCommand.clear();
1453             return;
1454         }
1455
1456         manager->setStepOut();
1457         manager->resume();
1458     }
1459     else if(cmd.compare("n")         == 0 ||
1460             cmd.compare("next")      == 0 ||
1461             cmd.compare("stepnext")  == 0)
1462     {
1463         if (manager->isInterrupted() == false)
1464         {
1465             // cannot execute this comment if the execution is not stopped
1466             sciprint("debugger is not on a breakpoint\n");
1467             vCommand.clear();
1468             return;
1469         }
1470
1471         manager->setStepNext();
1472         manager->resume();
1473     }
1474     else if(cmd.compare("q")     == 0 ||
1475             cmd.compare("exit")  == 0 ||
1476             cmd.compare("quit")  == 0)
1477     {
1478         // quit debugger
1479         manager->sendQuit();
1480         ConfigVariable::setEnableDebug(false);
1481         ConfigVariable::setDefaultVisitor(new ast::ExecVisitor());
1482         StoreConsoleCommand("abort", 1);
1483         manager->removeDebugger("console");
1484     }
1485     else if(cmd.compare("s")     == 0 ||
1486             cmd.compare("show")  == 0)
1487     {
1488         if(iSize == 1)
1489         {
1490             manager->show(-1);
1491         }
1492         else
1493         {
1494             try
1495             {
1496                 int bp = std::stoi(vCommand[1].data());
1497                 if (manager->getBreakPoint(bp) == NULL)
1498                 {
1499                     sciprint(_("%s: Unable to retrieve information about breakpoint %d.\n"), "show", bp);
1500                     sciprint("use 'h' for more information\n\n");
1501                     vCommand.clear();
1502                     return;
1503                 }
1504                 manager->show(bp);
1505             }
1506             catch(std::invalid_argument e) // std::stoi
1507             {
1508                 sciprint(_("%s: Wrong type for input argument #%d: Integer expected.\n"), "show", 1);
1509                 sciprint("use 'h' for more information\n\n");
1510                 vCommand.clear();
1511                 return;
1512             }
1513         }
1514     }
1515     else
1516     {
1517         // not a debugger command
1518         sciprint("Unknown command \"%s\".\n\n", _command.data());
1519         sciprint("use 'h' for more information\n\n");
1520     }
1521
1522     vCommand.clear();
1523 }
1524
1525 static void splitOnSpaces(const std::string& command, std::vector<std::string>& vCommand, std::vector<size_t>& vPos)
1526 {
1527     size_t pos = command.find(' ');
1528     size_t lastPos = 0;
1529
1530     while(pos != std::string::npos)
1531     {
1532         if(pos - lastPos)
1533         {
1534             vCommand.push_back(command.substr(lastPos, pos - lastPos));
1535             vPos.push_back(lastPos);
1536         }
1537
1538         lastPos = pos + 1;
1539         pos = command.find(' ', lastPos);
1540     }
1541
1542     if(lastPos != command.length())
1543     {
1544         vCommand.push_back(command.substr(lastPos, std::min(pos, command.size()) - lastPos + 1 ) );
1545         vPos.push_back(lastPos);
1546     }
1547 }
1548
1549 static void printDebuggerHelp()
1550 {
1551     sciprint(_("debug commands : \n"));
1552     sciprint("  h                            : %s.\n", _("show this help"));
1553     sciprint("  help                         : %s.\n", _("open debug documentation page"));
1554     sciprint("\n");
1555     sciprint("  (q)uit                       : %s.\n", _("stop debugging"));
1556     sciprint("  (w)here or bt                : %s.\n", _("show callstack"));
1557     sciprint("\n");
1558     sciprint("  (e)xec cmd                   : %s.\n", _("execute cmd"));
1559     sciprint("  (r)un cmd                    : %s.\n", _("execute cmd"));
1560     sciprint("\n");
1561     sciprint("  (d)isp var                   : %s.\n", _("display variable"));
1562     sciprint("  (p)rint var                  : %s.\n", _("display variable"));
1563     sciprint("\n");
1564     sciprint("  (c)ontinue                   : %s.\n", _("continue execution"));
1565     sciprint("  (a)bort                      : %s.\n", _("abort execution"));
1566     sciprint("  step(n)ext or next           : %s.\n", _("continue to next statement"));
1567     sciprint("  step(i)n or in               : %s.\n", _("step into function"));
1568     sciprint("  step(o)ut or out             : %s.\n", _("step outside function"));
1569     sciprint("\n");
1570     sciprint("  (b)reakpoint or break\n     func [line [\"condition\"]] : %s.\n", _("add a breakpoint"));
1571     sciprint("  (del)ete                     : %s.\n", _("delete all breakpoints"));
1572     sciprint("  (del)ete n                   : %s.\n", _("delete a specific breakpoint"));
1573     sciprint("  enable                       : %s.\n", _("enable all breakpoints"));
1574     sciprint("  enable n                     : %s.\n", _("enable a specific breakpoint"));
1575     sciprint("  disable                      : %s.\n", _("disable all breakpoints"));
1576     sciprint("  disable n                    : %s.\n", _("disable a specific breakpoint"));
1577     sciprint("  (s)how                       : %s.\n", _("show all breakpoints"));
1578     sciprint("  (s)how n                     : %s.\n", _("show a specific breakpoint"));
1579     sciprint("\n");
1580     sciprint(_("  for more details, show help page.\n"));
1581 }