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