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