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