c151e4201c7e5979314da250492b95bec73e4abe
[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 "debugmanager.hxx"
40 #include "consoledebugger.hxx"
41
42 extern "C"
43 {
44 #include "machine.h"
45 #include "InitializeLocalization.h"
46 #include "elem_common.h"
47 #include "InitializeJVM.h"
48 #include "TerminateJVM.h"
49 #include "InitializeGUI.h"
50 #include "graphicModuleLoad.h"
51 #include "TerminateGraphics.h"
52 #include "loadBackGroundClassPath.h"
53 #include "sci_tmpdir.h"
54 #include "setgetlanguage.h"
55 #include "InitializeConsole.h"
56 #include "InitializeHistoryManager.h"
57 #include "TerminateHistoryManager.h"
58 #include "prompt.h"
59 #include "scilabRead.h"
60 #include "functions_manager.h"
61 #include "InitScilab.h"
62 #include "setenvvar.h"
63 #include "getScilabPreference.h"
64 #include "saveCWDInPreferences.h"
65 #include "h5_fileManagement.h"
66 #include "with_fftw.h"
67 #include "BrowseVarManager.h"
68 #include "scicurdir.h"
69 #include "FileBrowserChDir.h"
70 #include "InitializePreferences.h"
71
72 #ifdef _MSC_VER
73 #include "InitializeWindows_tools.h"
74 #include "TerminateWindows_tools.h"
75 #include "WndThread.h"
76 #include "console.h"
77 #include "InnosetupMutex.h"
78 #include "MutexClosingScilab.h"
79 #include "WinConsole.h"
80 #else
81 #include "signal_mgmt.h"
82 #include "initConsoleMode.h"
83 #endif
84
85 #if defined(linux) && defined(__i386__)
86 #include "setPrecisionFPU.h"
87 #endif
88
89 #include "InitializeTclTk.h"
90 #include "dynamic_link.h"
91
92     /* Defined without include to avoid useless header dependency */
93     extern BOOL isItTheDisabledLib(void);
94 }
95
96 static void Add_i(void);
97 static void Add_pi(void);
98 static void Add_eps(void);
99 static void Add_e(void);
100 static void Add_s(void);
101 static void Add_z(void);
102 static void Add_gui(void);
103 static void Add_fftw(void);
104 static void Add_Nan(void);
105 static void Add_Inf(void);
106 static void Add_io(void);
107 static void Add_All_Variables(void);
108 static void Add_Double_Constant(const std::wstring& _szName, double _dblReal, double _dblImg, bool _bComplex);
109 static void Add_Poly_Constant(const std::wstring& _szName, const std::wstring& _szPolyVar, int _iRank, types::Double * _pdblReal);
110 static void Add_Boolean_Constant(const std::wstring& _szName, bool _bBool);
111 static void Add_String_Constant(const std::wstring& _szName, const char *_pstString);
112 static void checkForLinkerErrors(void);
113
114 static int batchMain(ScilabEngineInfo* _pSEI);
115 static int InitializeEnvironnement(void);
116 static int interactiveMain(ScilabEngineInfo* _pSEI);
117 static void processCommand(ScilabEngineInfo* _pSEI);
118 static void stateShow(Parser::ControlStatus status);
119
120 using namespace ast;
121
122 ScilabEngineInfo* InitScilabEngineInfo()
123 {
124     // Disable all startup flags.
125     ScilabEngineInfo* pSEI = (ScilabEngineInfo*)CALLOC(1, sizeof(ScilabEngineInfo));
126
127     //Active default flags
128     pSEI->iExecAst = 1;
129     pSEI->iNoBanner = 1;
130
131     pSEI->iMultiLine = 0;
132     pSEI->isInterruptible = 1;      // by default all thread are interruptible
133     pSEI->isPrioritary = 0;         // by default all thread are non-prioritary
134     pSEI->iStartConsoleThread = 1;  // used in call_scilab to avoid "prompt" thread execution
135     pSEI->iForceQuit = 0;           // management of -quit argument
136     pSEI->iCommandOrigin = NONE;
137
138     pSEI->iCodeAction = -1; //default value, no code action ( used on windows by file associations -O -X -P arguments)
139     return pSEI;
140 }
141
142 int StartScilabEngine(ScilabEngineInfo* _pSEI)
143 {
144     int iMainRet = 0;
145     ConfigVariable::setStartProcessing(true);
146
147     // ignore -e argument if the command is empty
148     if (_pSEI->pstExec && strcmp(_pSEI->pstExec, "") == 0)
149     {
150         _pSEI->pstExec = NULL;
151     }
152
153     // ignore -quit if -e or -f are not given
154     _pSEI->iForceQuit = _pSEI->iForceQuit && (_pSEI->pstExec || _pSEI->pstFile);
155     ConfigVariable::setForceQuit(_pSEI->iForceQuit == 1);
156
157     /* This bug only occurs under Linux 32 bits
158      * See: http://wiki.scilab.org/Scilab_precision
159      */
160 #if defined(linux) && defined(__i386__)
161     setFPUToDouble();
162 #endif
163
164 #ifndef _MSC_VER
165     /* Management of the signals (seg fault, floating point exception, etc) */
166     if (getenv("SCI_DISABLE_EXCEPTION_CATCHING") == NULL)
167     {
168         base_error_init();
169     }
170 #endif
171
172 #if defined(netbsd) || defined(freebsd)
173     /* floating point exceptions */
174     fpsetmask(0);
175 #endif
176
177     ThreadManagement::initialize();
178     NumericConstants::Initialize();
179     checkForLinkerErrors();
180
181 #ifdef _MSC_VER
182     //get current console window and hide it
183     int scilabMode = getScilabMode();
184     if (scilabMode == SCILAB_STD || scilabMode == SCILAB_NW || scilabMode == SCILAB_API)
185     {
186         CreateScilabHiddenWndThread();
187     }
188
189     if (scilabMode == SCILAB_STD)
190     {
191         //show banner in console window
192         CreateScilabConsole(_pSEI->iNoBanner);
193
194         if (_pSEI->iKeepConsole == 0)
195         {
196             HideScilex(); /* hide console window */
197         }
198         else
199         {
200             ShowScilex();
201         }
202     }
203     else
204     {
205         if (scilabMode == SCILAB_NW || scilabMode == SCILAB_NWNI)
206         {
207             SaveConsoleColors();
208             if (scilabMode == SCILAB_NW)
209             {
210                 RenameConsole();
211                 UpdateConsoleColors();
212             }
213         }
214     }
215
216     //create a thread for innosetup to allow reinstall during scilab running
217     createInnosetupMutex();
218 #endif
219
220     //open scope lvl 0 for gateway from modules and first variables ( SCI, HOME, TMPDIR, ...)
221     symbol::Context::getInstance()->scope_begin();
222
223     /* Scilab Startup */
224     xmlInitParser();
225     InitializeEnvironnement();
226
227     if (_pSEI->pstLang)
228     {
229         wchar_t *pwstLang = to_wide_string(_pSEI->pstLang);
230         setlanguage(pwstLang);
231         FREE(pwstLang);
232     }
233
234 #ifdef _MSC_VER
235     InitializeWindows_tools();
236 #endif
237
238     if (_pSEI->iNoJvm == 0) // With JVM
239     {
240         InitializeTclTk();
241         InitializeJVM();
242         InitializeGUI();
243
244         /* create needed data structure if not already created */
245         loadGraphicModule();
246
247         loadBackGroundClassPath();
248
249         //update %gui to true
250         Add_Boolean_Constant(L"%gui", true);
251     }
252
253     /* Standard mode -> init Java Console */
254     if (_pSEI->iConsoleMode == 0)
255     {
256         /* Initialize console: lines... */
257         InitializeConsole();
258     }
259     else
260     {
261 #ifndef _MSC_VER
262         initConsoleMode(RAW);
263 #endif
264     }
265
266     //set prompt value
267     int pause = 0;
268     C2F(setprlev) (&pause);
269
270     //load gateways
271     if (LoadModules() == false)
272     {
273         //clear opened files
274         FileManager::destroy();
275         return 1;
276     }
277
278     //variables are needed by loadModules but must be in SCOPE_CONSOLE under protection
279     //remove (W)SCI/SCIHOME/HOME/TMPDIR
280     symbol::Context::getInstance()->remove(symbol::Symbol(L"SCI"));
281     symbol::Context::getInstance()->remove(symbol::Symbol(L"WSCI"));
282     symbol::Context::getInstance()->remove(symbol::Symbol(L"SCIHOME"));
283     symbol::Context::getInstance()->remove(symbol::Symbol(L"home"));
284     symbol::Context::getInstance()->remove(symbol::Symbol(L"TMPDIR"));
285
286     //open a scope for macros
287     symbol::Context::getInstance()->scope_begin();
288
289     Add_All_Variables();
290     SetScilabVariables();
291
292     symbol::Context::getInstance()->protect();
293     //execute scilab.start
294     if (_pSEI->iNoStart == 0)
295     {
296         int ierr = execScilabStartTask(_pSEI->iSerialize != 0);
297         if (ierr)
298         {
299             return ierr;
300         }
301     }
302
303     //open console scope
304     //symbol::Context::getInstance()->scope_begin();
305
306     ConfigVariable::setStartProcessing(false);
307
308     ConfigVariable::setPromptMode(0);
309     int iScript = 0;
310     if (_pSEI->pstExec)
311     {
312         //-e option
313         Parser parser;
314         parseCommandTask(&parser, _pSEI->iTimed != 0, _pSEI->pstExec);
315
316         if (parser.getExitStatus() == Parser::Failed)
317         {
318             scilabWriteW(parser.getErrorMessage());
319         }
320         else if (parser.getControlStatus() !=  Parser::AllControlClosed)
321         {
322             _pSEI->iMultiLine = 1;
323         }
324         else
325         {
326             StoreConsoleCommand(_pSEI->pstExec, 0);
327         }
328
329         if (parser.getTree())
330         {
331             delete parser.getTree();
332             parser.setTree(NULL);
333         }
334         iMainRet = ConfigVariable::getExitStatus();
335         iScript = 1;
336
337         if (_pSEI->iCodeAction != -1)
338         {
339             //alloc in main to manage shell interaction
340             FREE(_pSEI->pstExec);
341             _pSEI->pstExec = NULL;
342         }
343     }
344     else if (_pSEI->pstFile)
345     {
346         //-f option execute exec('%s',-1)
347         char *pstCommand = (char *)MALLOC(sizeof(char) * (strlen("exec(\"\",-1)") + strlen(_pSEI->pstFile) + 1));
348         sprintf(pstCommand, "exec(\"%s\",-1)", _pSEI->pstFile);
349
350         StoreConsoleCommand(pstCommand, 0);
351         FREE(pstCommand);
352         iMainRet = ConfigVariable::getExitStatus();
353         _pSEI->pstExec = NULL;
354         _pSEI->pstFile = NULL;
355         iScript = 1;
356     }
357
358     ConfigVariable::setPromptMode(2);
359
360     InitializePreferences(iScript);
361
362
363     //register console debugger as debugger
364     debugger::DebuggerMagager::getInstance()->addDebugger(new debugger::ConsoleDebugger());
365     return iMainRet;
366 }
367
368 int RunScilabEngine(ScilabEngineInfo* _pSEI)
369 {
370     if (_pSEI->pstParseFile)
371     {
372         // Only for parsing test, won't execute anything.
373         return batchMain(_pSEI);
374     }
375     else
376     {
377         //always run as interactiveMain even after -e or -f option
378         return interactiveMain(_pSEI);
379     }
380 }
381
382 int ExecExternalCommand(ScilabEngineInfo* _pSEI)
383 {
384     if (_pSEI->pstExec)
385     {
386         StoreConsoleCommand(_pSEI->pstExec, 1);
387         return ConfigVariable::getExitStatus();
388     }
389
390     return -1;
391 }
392
393 void StopScilabEngine(ScilabEngineInfo* _pSEI)
394 {
395     ConfigVariable::setEndProcessing(true);
396 #ifdef _MSC_VER
397     /* bug 3672 */
398     /* Create a Mutex (closing scilab)
399      * used by files association
400      */
401     createMutexClosingScilab();
402 #endif
403
404     clearScilabPreferences();
405
406     if (_pSEI->pstFile)
407     {
408         //-f option execute exec('%s',-1)
409         char *pstCommand = (char *)MALLOC(sizeof(char) * (strlen("exec(\"\",-1)") + strlen(_pSEI->pstFile) + 1));
410         sprintf(pstCommand, "exec(\"%s\",-1)", _pSEI->pstFile);
411
412         _pSEI->pstExec = pstCommand;
413         processCommand(_pSEI);
414         FREE(pstCommand);
415     }
416     else if (_pSEI->iNoStart == 0)
417     {
418         //execute scilab.quit
419         execScilabQuitTask(_pSEI->iSerialize != 0);
420         //call all modules.quit
421         EndModules();
422     }
423
424     // close macros scope
425     symbol::Context::getInstance()->scope_end();
426
427     //close gateways scope
428     symbol::Context::getInstance()->scope_end();
429
430     //clean context
431     symbol::Context::getInstance()->clearAll();
432     //destroy context
433     symbol::Context::destroyInstance();
434
435 #ifndef NDEBUG
436     //uncomment to print mem leak log
437     //types::Inspector::displayMemleak();
438 #endif
439
440     //close dynamic linked libraries
441     std::vector<ConfigVariable::DynamicLibraryStr*>* pDLLIst = ConfigVariable::getDynamicLibraryList();
442     int size = pDLLIst->size();
443     for (int i = 0; i < size; i++)
444     {
445         ConfigVariable::DynamicLibraryStr* pStr = ConfigVariable::getDynamicLibrary(i);
446         if (pStr)
447         {
448             DynLibHandle iLib = pStr->hLib;
449             ConfigVariable::removeDynamicLibrary(i);
450             Sci_dlclose(iLib);
451         }
452     }
453
454     // cleanup Java dependent features
455     saveCWDInPreferences();
456     clearScilabPreferences();
457     TerminateHistoryManager();
458
459     // stop the JVM
460     if (_pSEI->iNoJvm == 0)
461     {
462         TerminateGraphics();
463         TerminateJVM();
464     }
465
466     // reset struct to prevent the use of deleted objects
467     // when we start scilab again without kill process (ie: call_scilab)
468     resetVariableValueDefinedInScilab();
469
470     /* TerminateCorePart2 */
471
472     //clear opened files
473     FileManager::destroy();
474
475     /* Remove TMPDIR before exit */
476     clearTMPDIR();
477
478     //Unload dynamic modules
479     UnloadModules();
480
481     //destroy function manager
482     destroyfunctionManagerInstance();
483     /* TerminateCorePart2 end */
484
485     /*
486     * Cleanup function for the XML library.
487     */
488     xmlCleanupParser();
489
490     /* Cleanup the parser state */
491     Parser::cleanup();
492
493 #ifdef _MSC_VER
494     TerminateWindows_tools();
495 #endif
496
497     /* Reset terminal configuration */
498     if (_pSEI->iConsoleMode)
499     {
500 #ifndef _MSC_VER
501         initConsoleMode(ATTR_RESET);
502 #endif
503     }
504
505 #ifdef _MSC_VER
506     /* close mutex (closing scilab)
507      * used by files association
508      */
509     terminateMutexClosingScilab();
510 #endif
511
512     ConfigVariable::clearLastError();
513     ConfigVariable::setEndProcessing(false);
514 }
515
516 static void processCommand(ScilabEngineInfo* _pSEI)
517 {
518     /*
519      ** -*- DUMPING TREE -*-
520      */
521     if (_pSEI->iDumpAst)
522     {
523         dumpAstTask((ast::Exp*)_pSEI->pExpTree, _pSEI->iTimed != 0);
524     }
525
526     /*
527      ** -*- PRETTY PRINT TREE -*-
528      */
529     if (_pSEI->iPrintAst)
530     {
531         printAstTask((ast::Exp*)_pSEI->pExpTree, _pSEI->iTimed != 0);
532     }
533
534     /*
535      ** -*- EXECUTING TREE -*-
536      */
537     if (_pSEI->iExecAst)
538     {
539         execAstTask((ast::Exp*)_pSEI->pExpTree, _pSEI->iSerialize != 0,
540                     _pSEI->iTimed != 0, _pSEI->iAstTimed != 0,
541                     _pSEI->iExecVerbose != 0, _pSEI->isInterruptible != 0,
542                     _pSEI->isPrioritary != 0, _pSEI->iCommandOrigin);
543     }
544
545     /*
546      ** -*- DUMPING STACK AFTER EXECUTION -*-
547      */
548     if (_pSEI->iDumpStack)
549     {
550         dumpStackTask(_pSEI->iTimed != 0);
551     }
552 }
553
554 // Thread used to parse and execute Scilab command setted in storeCommand
555 void* scilabReadAndExecCommand(void* param)
556 {
557     char* command           = NULL;
558     int iInterruptibleCmd   = 0;
559     int iPrioritaryCmd      = 0;
560
561     command_origin_t iCmdOrigin = NONE;
562
563     ScilabEngineInfo* _pSEI = (ScilabEngineInfo*)param;
564
565     do
566     {
567         if (GetCommand(&command, &iPrioritaryCmd, &iInterruptibleCmd, &iCmdOrigin) == 0)
568         {
569             ThreadManagement::WaitForCommandStoredSignal();
570             continue;
571         }
572
573         // empty command
574         if (command == NULL || strlen(command) == 0)
575         {
576             continue;
577         }
578
579         _pSEI->isInterruptible = iInterruptibleCmd;
580         _pSEI->isPrioritary = iPrioritaryCmd;
581         _pSEI->iCommandOrigin = iCmdOrigin;
582
583         ThreadManagement::LockParser();
584         Parser parser;
585         parser.setParseTrace(_pSEI->iParseTrace != 0);
586         parseCommandTask(&parser, _pSEI->iTimed != 0, command);
587
588         if (parser.getExitStatus() == Parser::Failed)
589         {
590             scilabWriteW(parser.getErrorMessage());
591             ThreadManagement::UnlockParser();
592             continue;
593         }
594
595         _pSEI->pExpTree = parser.getTree();
596         ThreadManagement::UnlockParser();
597
598         processCommand(_pSEI);
599         FREE(command);
600     }
601     while (ConfigVariable::getForceQuit() == false);
602
603     return NULL;
604 }
605
606 //Thread used to parse and set console commands in storeCommand
607 void* scilabReadAndStore(void* param)
608 {
609     Parser::ControlStatus controlStatus = Parser::AllControlClosed;
610
611     char *command = NULL;
612     wchar_t* parserErrorMsg = NULL;
613
614     ScilabEngineInfo* _pSEI = (ScilabEngineInfo*)param;
615
616     if (_pSEI->iMultiLine)
617     {
618         command = _pSEI->pstExec;
619     }
620
621     if (isEmptyCommandQueue() == false)
622     {
623         // unlock main thread
624         ThreadManagement::SendStartPendingSignal();
625
626         // Command stored as console command by -f
627         // We have to wait this execution before
628         // callOnPrompt (ie: onPrompt perform a quit in test_run)
629         ThreadManagement::WaitForConsoleExecDoneSignal();
630     }
631
632     // unlock main thread
633     ThreadManagement::SendStartPendingSignal();
634
635     while (ConfigVariable::getForceQuit() == false)
636     {
637         callOnPrompt();
638
639         Parser parser;
640         parser.setParseTrace(_pSEI->iParseTrace != 0);
641
642         Parser::ParserStatus exitStatus = Parser::Failed;
643
644         if (ConfigVariable::isPrintCompact() == false)
645         {
646             scilabWriteW(L"\n");
647         }
648
649         do
650         {
651             // Show Parser Sate before prompt
652             stateShow(controlStatus);
653
654             int pause = ConfigVariable::getPauseLevel();
655
656             //set prompt value
657             C2F(setprlev) (&pause);
658
659             if (scilabRead() == 0)
660             {
661                 // happens when the return of scilabRead must not be interpreted by Scilab.
662                 // ie: mscanf, step by step execution (mode 4 or 7)
663                 ThreadManagement::WaitForConsoleExecDoneSignal();
664                 continue;
665             }
666
667             char* pstRead = ConfigVariable::getConsoleReadStr();
668             if (command == NULL)
669             {
670                 command = pstRead;
671                 if (strcmp(command, "") == 0)
672                 {
673                     FREE(command);
674                     command = NULL;
675                     break;
676                 }
677 #ifdef DEBUG_THREAD
678                 ThreadManagement::PrintDebugHead();
679 #endif // DEBUG_THREAD
680             }
681             else
682             {
683                 if (ConfigVariable::isExecutionBreak())
684                 {
685                     //clean parser state and close opened instruction.
686                     if (parser.getControlStatus() != Parser::AllControlClosed)
687                     {
688                         parser.cleanup();
689                         FREE(command);
690                         command = NULL;
691                         parser.setControlStatus(Parser::AllControlClosed);
692                         controlStatus = parser.getControlStatus();
693                     }
694
695                     ConfigVariable::resetExecutionBreak();
696                     break;
697                 }
698                 else
699                 {
700                     //+1 for null termination and +1 for '\n'
701                     size_t iLen = strlen(command) + strlen(pstRead) + 2;
702                     char *pstNewCommand = (char *)MALLOC(iLen * sizeof(char));
703
704 #ifdef _MSC_VER
705                     sprintf_s(pstNewCommand, iLen, "%s\n%s", command, pstRead);
706 #else
707                     sprintf(pstNewCommand, "%s\n%s", command, pstRead);
708 #endif
709                     FREE(pstRead);
710                     FREE(command);
711                     command = pstNewCommand;
712                 }
713             }
714
715             if (ConfigVariable::getEnableDebug())
716             {
717                 bool disableDebug = false;
718                 char* tmpCommand = NULL;
719                 int commandsize = strlen(command);
720
721                 //all commands must be prefixed by debug except e(xec) (r)un or p(rint) "something" that become "something" or disp("something")
722                 if (strncmp(command, "e ", 2) == 0 || strncmp(command, "r ", 2) == 0)
723                 {
724                     tmpCommand = os_strdup(command + 2);
725                 }
726                 else if (commandsize >= 5 && strncmp(command, "exec ", 5) == 0)
727                 {
728                     tmpCommand = os_strdup(command + 5);
729                 }
730                 else if (commandsize >= 4 && strncmp(command, "run ", 4) == 0)
731                 {
732                     tmpCommand = os_strdup(command + 5);
733                 }
734
735                 if (tmpCommand)
736                 {
737                     if (debugger::DebuggerMagager::getInstance()->isInterrupted())
738                     {
739                         sciprint(_("Debugger is on a breakpoint\n"));
740                         sciprint(_("(c)ontinue or (a)bort current execution before execute a new command\n"));
741                         continue;
742                     }
743                 }
744                 else if (commandsize > 1 && command[0] == 'd' && command[1] == ' ')
745                 {
746                     std::string s("disp(");
747                     s += command + 2;
748                     s += ")";
749                     tmpCommand = os_strdup(s.data());
750                     disableDebug = true;
751                 }
752                 else if (commandsize > 5 && strncmp(command, "disp ", 5) == 0)
753                 {
754                     std::string s("disp(");
755                     s += command + 5;
756                     s += ")";
757                     tmpCommand = os_strdup(s.data());
758                     disableDebug = true;
759                 }
760                 else if (commandsize > 1 && command[0] == 'p' && command[1] == ' ')
761                 {
762                     std::string s("disp(");
763                     s += command + 2;
764                     s += ")";
765                     tmpCommand = os_strdup(s.data());
766                     disableDebug = true;
767                 }
768                 else if (commandsize > 6 && strncmp(command, "print ", 6) == 0)
769                 {
770                     std::string s("disp(");
771                     s += command + 6;
772                     s += ")";
773                     tmpCommand = os_strdup(s.data());
774                     disableDebug = true;
775                 }
776                 else
777                 {
778                     int iLen = (int)strlen(command) + (int)strlen("debug ") + 1;
779                     tmpCommand = (char*)MALLOC(sizeof(char) * iLen);
780 #ifdef _MSC_VER
781                     os_sprintf(tmpCommand, iLen, "%s %s", "debug", command);
782 #else
783                     os_sprintf(tmpCommand, "%s %s", "debug", command);
784 #endif
785                     disableDebug = true;
786                 }
787
788                 if (disableDebug)
789                 {
790                     //disable debugger time to exec debug command
791                     //it will be enable in debuggervisitor, after execution
792                     ConfigVariable::setEnableDebug(false);
793                 }
794
795                 FREE(command);
796                 command = tmpCommand;
797             }
798
799             ThreadManagement::LockParser();
800             parseCommandTask(&parser, _pSEI->iTimed != 0, command);
801             controlStatus = parser.getControlStatus();
802             exitStatus = parser.getExitStatus();
803             parserErrorMsg = parser.getErrorMessage();
804             if (parser.getTree())
805             {
806                 delete parser.getTree();
807                 parser.setTree(NULL);
808             }
809             ThreadManagement::UnlockParser();
810         }
811         while (controlStatus != Parser::AllControlClosed);
812
813         if (command == NULL)
814         {
815             continue;
816         }
817
818         if (exitStatus == Parser::Failed)
819         {
820             FREE(command);
821             command = NULL;
822             scilabForcedWriteW(parserErrorMsg);
823             continue;
824         }
825
826         // store the command and wait for this execution ends.
827         StoreConsoleCommand(command, 1);
828
829         FREE(command);
830         command = NULL;
831     }
832
833     // Awake scilabReadAndExecCommand thread in case of scilab exit
834     ThreadManagement::SendCommandStoredSignal();
835     return NULL;
836 }
837
838 /*
839 ** -*- Interactive Main -*-
840 */
841 static int interactiveMain(ScilabEngineInfo* _pSEI)
842 {
843 #ifndef WITH_GUI
844 #ifndef _MSC_VER
845     if (getScilabMode() != SCILAB_NWNI)
846     {
847         fprintf(stderr, "Scilab was compiled without its GUI and advanced features. Run scilab-cli or use the -nwni option.\n");
848         initConsoleMode(ATTR_RESET);
849         exit(1);
850     }
851 #endif
852 #endif
853
854     InitializeHistoryManager();
855
856     if (getScilabMode() != SCILAB_NWNI && getScilabMode() != SCILAB_API)
857     {
858
859         char *cwd = NULL;
860
861         int err = 0;
862
863         UpdateBrowseVar();
864         cwd = scigetcwd(&err);
865         if (cwd)
866         {
867             FileBrowserChDir(cwd);
868             FREE(cwd);
869         }
870     }
871
872     // -e -quit with parser error, command queue is empty
873     if (_pSEI->iForceQuit && isEmptyCommandQueue())
874     {
875         return 1;
876     }
877
878     __threadId threadIdConsole;
879     __threadKey threadKeyConsole;
880     __threadId threadIdCommand;
881     __threadKey threadKeyCommand;
882
883     if (_pSEI->iStartConsoleThread)
884     {
885         // thread to manage console command
886         __CreateThreadWithParams(&threadIdConsole, &threadKeyConsole, &scilabReadAndStore, _pSEI);
887
888         // scilabReadAndStore thread must be execute before scilabReadAndExecCommand
889         // to be such that the -f command stored is not removed
890         // from queue before scilabReadAndStore is waiting for.
891         ThreadManagement::WaitForStartPendingSignal();
892     }
893
894     // thread to manage command stored
895     __CreateThreadWithParams(&threadIdCommand, &threadKeyCommand, &scilabReadAndExecCommand, _pSEI);
896
897 #ifdef DEBUG_THREAD
898     ThreadManagement::SetThreadKey( __GetCurrentThreadKey(), threadKeyCommand, threadKeyConsole);
899 #endif // DEBUG_THREAD
900
901     int iRet = 0;
902     do
903     {
904         // wait for available runner
905         ThreadManagement::WaitForRunMeSignal();
906
907         try
908         {
909             iRet = StaticRunner::launch();
910         }
911         catch (const ast::InternalAbort& /*ia*/)
912         {
913             // go out when exit/quit is called
914             iRet = ConfigVariable::getExitStatus();
915         }
916         catch (const ast::RecursionException& /*re*/)
917         {
918             // go out when exit/quit is called
919             iRet = 1;
920         }
921
922         ThreadManagement::SendAwakeRunnerSignal();
923     }
924     while (ConfigVariable::getForceQuit() == false);
925
926     return iRet;
927 }
928
929 /*
930 ** -*- Batch Main -*-
931 */
932 static int batchMain(ScilabEngineInfo* _pSEI)
933 {
934     /*
935      ** -*- PARSING -*-
936      */
937     Parser *parser = new Parser();
938
939     parser->setParseTrace(_pSEI->iParseTrace != 0);
940
941     wchar_t *pwstFileName = to_wide_string(_pSEI->pstParseFile);
942
943     /*
944      ** -*- PARSING -*-
945      */
946     parseFileTask(parser, _pSEI->iTimed != 0, pwstFileName, L"scilab 6");
947
948     /*
949      ** -*- DUMPING TREE -*-
950      */
951     if (_pSEI->iDumpAst)
952     {
953         dumpAstTask(parser->getTree(), _pSEI->iTimed != 0);
954     }
955
956     if (parser->getExitStatus() == Parser::Succeded)
957     {
958         /*
959          ** -*- PRETTY PRINT TREE -*-
960          */
961         if (_pSEI->iPrintAst)
962         {
963             printAstTask(parser->getTree(), _pSEI->iTimed != 0);
964         }
965
966     }
967     else
968     {
969         scilabWriteW(parser->getErrorMessage());
970     }
971
972 #ifdef DEBUG
973     std::cerr << "To end program press [ENTER]" << std::endl;
974 #endif
975     return parser->getExitStatus();
976 }
977
978 /*
979 ** -*- stateView
980 */
981 static void stateShow(Parser::ControlStatus status)
982 {
983     if (status != Parser::AllControlClosed)
984     {
985         SetTemporaryPrompt("  > ");
986     }
987 }
988
989 static int InitializeEnvironnement(void)
990 {
991     SetScilabEnvironment();
992     InitializeLocalization();
993
994     ConfigVariable::setConsoleWidth(75);
995     ConfigVariable::setFormatSize(10);
996     ConfigVariable::setFormatMode(1);
997     //Add_All_Variables();
998     FileManager::initialize();
999     initOperationArray();
1000     return 0;
1001 }
1002
1003 /*
1004  * Private function to check any linker errors
1005  */
1006
1007 static void checkForLinkerErrors(void)
1008 {
1009 #ifndef _MSC_VER
1010     /*
1011        Depending on the linking order, sometime, libs are not loaded the right way.
1012        This can cause painful debugging tasks for packager or developer, we are
1013        doing the check to help them.
1014     */
1015 #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"
1016 #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"
1017
1018     if (getScilabMode() != SCILAB_NWNI && getScilabMode() != SCILAB_API)
1019     {
1020         if (isItTheDisabledLib())
1021         {
1022             fprintf(stderr, LINKER_ERROR_1);
1023             fprintf(stderr, "Here, Scilab should have 'libscijvm' defined but gets 'libscijvm-disable' instead.\n");
1024             fprintf(stderr, LINKER_ERROR_2);
1025             exit(1);
1026         }
1027     }
1028     else
1029     {
1030         /* NWNI mode */
1031         if (!isItTheDisabledLib())
1032         {
1033             fprintf(stderr, LINKER_ERROR_1);
1034             fprintf(stderr, "Here, Scilab should have 'libscijvm-disable' defined but gets 'libscijvm' instead.\n");
1035             fprintf(stderr, LINKER_ERROR_2);
1036             exit(1);
1037         }
1038     }
1039 #undef LINKER_ERROR_1
1040 #undef LINKER_ERROR_2
1041 #endif
1042 }
1043
1044 static void Add_All_Variables(void)
1045 {
1046     Add_pi();
1047     Add_eps();
1048     Add_e();
1049     Add_i();
1050     Add_s();
1051     Add_z();
1052     Add_gui();
1053     Add_fftw();
1054     Add_Nan();
1055     Add_Inf();
1056     Add_io();
1057 }
1058
1059 static void Add_Nan(void)
1060 {
1061     double dbl1 = -1.0;
1062     double dbl0 = fabs(dbl1 - dbl1);
1063
1064     Add_Double_Constant(L"%nan", dbl0 / dbl0, 0, false);
1065 }
1066
1067 static void Add_Inf(void)
1068 {
1069     double dbl1 = 1.0;
1070     double dbl0 = dbl1 - dbl1;
1071
1072     Add_Double_Constant(L"%inf", dbl1 / dbl0, 0, false);
1073 }
1074
1075 static void Add_gui(void)
1076 {
1077     Add_Boolean_Constant(L"%gui", false);
1078 }
1079
1080 static void Add_fftw(void)
1081 {
1082     Add_Boolean_Constant(L"%fftw", withfftw() == 1);
1083 }
1084
1085 static void Add_pi(void)
1086 {
1087     Add_Double_Constant(L"%pi", M_PI, 0, false);
1088 }
1089
1090 static void Add_eps(void)
1091 {
1092     Add_Double_Constant(L"%eps", NumericConstants::eps_machine, 0, false);
1093 }
1094
1095 static void Add_e(void)
1096 {
1097     Add_Double_Constant(L"%e", 2.71828182845904530, 0, false);
1098 }
1099
1100 static void Add_i(void)
1101 {
1102     Add_Double_Constant(L"%i", 0, 1, true);
1103 }
1104
1105 static void Add_s(void)
1106 {
1107     types::Double dblCoef(1, 2);
1108
1109     dblCoef.set(0, 0, 0);
1110     dblCoef.set(0, 1, 1);
1111
1112     Add_Poly_Constant(L"%s", L"s", 1, &dblCoef);
1113 }
1114
1115 static void Add_z(void)
1116 {
1117     types::Double dblCoef(1, 2);
1118
1119     dblCoef.set(0, 0, 0);
1120     dblCoef.set(0, 1, 1);
1121
1122     Add_Poly_Constant(L"%z", L"z", 1, &dblCoef);
1123 }
1124
1125 static void Add_io(void)
1126 {
1127     types::Double * pVal = new types::Double(1, 2);
1128     pVal->set(0, 5);
1129     pVal->set(1, 6);
1130     symbol::Context::getInstance()->put(symbol::Symbol(L"%io"), pVal);
1131 }
1132
1133 static void Add_Poly_Constant(const std::wstring& _szName, const std::wstring& _szPolyVar, int _iRank, types::Double * _pdbl)
1134 {
1135     types::Polynom * pVar = new types::Polynom(_szPolyVar, 1, 1, &_iRank);
1136     types::SinglePoly *poPoly = pVar->get(0);
1137
1138     poPoly->setCoef(_pdbl);
1139     symbol::Context::getInstance()->put(symbol::Symbol(_szName), pVar);
1140 }
1141
1142 static void Add_Double_Constant(const std::wstring& _szName, double _dblReal, double _dblImg, bool _bComplex)
1143 {
1144     types::Double * pVal = new types::Double(1, 1, _bComplex);
1145     pVal->set(0, 0, _dblReal);
1146     pVal->setImg(0, 0, _dblImg);
1147     symbol::Context::getInstance()->put(symbol::Symbol(_szName), pVal);
1148 }
1149
1150 static void Add_Boolean_Constant(const std::wstring& _szName, bool _bBool)
1151 {
1152     types::Bool * pVal = new types::Bool(_bBool);
1153     symbol::Context::getInstance()->put(symbol::Symbol(_szName), pVal);
1154 }
1155
1156 static void Add_String_Constant(const std::wstring& _szName, const char *_pstString)
1157 {
1158     types::String * ps = new types::String(_pstString);
1159     symbol::Context::getInstance()->put(symbol::Symbol(_szName), ps);
1160 }