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