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