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