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