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