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