bug #13983: who_user returns wrong values
[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 "configvariable_interface.h"
52 #include "setgetlanguage.h"
53 #include "InitializeConsole.h"
54 #include "InitializeHistoryManager.h"
55 #include "TerminateHistoryManager.h"
56 #include "prompt.h"
57 #include "scilabRead.h"
58 #include "functions_manager.h"
59 #include "InitScilab.h"
60 #include "setenvvar.h"
61 #include "getScilabPreference.h"
62 #include "saveCWDInPreferences.h"
63 #include "h5_fileManagement.h"
64 #include "with_fftw.h"
65 #include "BrowseVarManager.h"
66 #include "scicurdir.h"
67 #include "FileBrowserChDir.h"
68 #include "InitializePreferences.h"
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 "storeCommand.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
133     return pSEI;
134 }
135
136 int StartScilabEngine(ScilabEngineInfo* _pSEI)
137 {
138     int iMainRet = 0;
139     ConfigVariable::setStartProcessing(true);
140
141     // ignore -e argument if the command is empty
142     if (_pSEI->pstExec && strcmp(_pSEI->pstExec, "") == 0)
143     {
144         _pSEI->pstExec = NULL;
145     }
146
147     // ignore -quit if -e or -f are not given
148     _pSEI->iForceQuit = _pSEI->iForceQuit && (_pSEI->pstExec || _pSEI->pstFile);
149     ConfigVariable::setForceQuit(_pSEI->iForceQuit == 1);
150
151     /* This bug only occurs under Linux 32 bits
152      * See: http://wiki.scilab.org/Scilab_precision
153      */
154 #if defined(linux) && defined(__i386__)
155     setFPUToDouble();
156 #endif
157
158 #ifndef _MSC_VER
159     /* Management of the signals (seg fault, floating point exception, etc) */
160     if (getenv("SCI_DISABLE_EXCEPTION_CATCHING") == NULL)
161     {
162         base_error_init();
163     }
164 #endif
165
166 #if defined(netbsd) || defined(freebsd)
167     /* floating point exceptions */
168     fpsetmask(0);
169 #endif
170
171     ThreadManagement::initialize();
172     NumericConstants::Initialize();
173     checkForLinkerErrors();
174
175 #ifdef _MSC_VER
176     //get current console window and hide it
177     int scilabMode = getScilabMode();
178     if (scilabMode == SCILAB_STD || scilabMode == SCILAB_NW || scilabMode == SCILAB_API)
179     {
180         CreateScilabHiddenWndThread();
181     }
182
183     if (scilabMode == SCILAB_STD)
184     {
185         //show banner in console window
186         CreateScilabConsole(_pSEI->iNoBanner);
187
188         if (_pSEI->iKeepConsole == 0)
189         {
190             HideScilex(); /* hide console window */
191         }
192         else
193         {
194             ShowScilex();
195         }
196     }
197     else
198     {
199         if (scilabMode == SCILAB_NW || scilabMode == SCILAB_NWNI)
200         {
201             SaveConsoleColors();
202             if (scilabMode == SCILAB_NW)
203             {
204                 RenameConsole();
205                 UpdateConsoleColors();
206             }
207         }
208     }
209
210     //create a thread for innosetup to allow reinstall during scilab running
211     createInnosetupMutex();
212 #endif
213
214     //open scope lvl 0 for gateway from modules and first variables ( SCI, HOME, TMPDIR, ...)
215     symbol::Context::getInstance()->scope_begin();
216
217     /* Scilab Startup */
218     xmlInitParser();
219     InitializeEnvironnement();
220
221     if (_pSEI->pstLang)
222     {
223         wchar_t *pwstLang = to_wide_string(_pSEI->pstLang);
224         setlanguage(pwstLang);
225         FREE(pwstLang);
226     }
227
228 #ifdef _MSC_VER
229     InitializeWindows_tools();
230 #endif
231
232     if (_pSEI->iNoJvm == 0) // With JVM
233     {
234         /* bug 3702 */
235         /* tclsci creates a TK window on Windows */
236         /* it changes focus on previous windows */
237         /* we put InitializeTclTk before InitializeGUI */
238
239         //InitializeTclTk();
240         InitializeJVM();
241         InitializeGUI();
242
243         /* create needed data structure if not already created */
244         loadGraphicModule();
245
246         loadBackGroundClassPath();
247
248         //update %gui to true
249         Add_Boolean_Constant(L"%gui", true);
250     }
251
252     /* Standard mode -> init Java Console */
253     if (_pSEI->iConsoleMode == 0)
254     {
255         /* Initialize console: lines... */
256         InitializeConsole();
257     }
258     else
259     {
260 #ifndef _MSC_VER
261         initConsoleMode(RAW);
262 #endif
263     }
264
265     //set prompt value
266     int pause = 0;
267     C2F(setprlev) (&pause);
268
269     //load gateways
270     LoadModules();
271
272     //variables are needed by loadModules but must be in SCOPE_CONSOLE under protection
273     //remove (W)SCI/SCIHOME/HOME/TMPDIR
274     symbol::Context::getInstance()->remove(symbol::Symbol(L"SCI"));
275     symbol::Context::getInstance()->remove(symbol::Symbol(L"WSCI"));
276     symbol::Context::getInstance()->remove(symbol::Symbol(L"SCIHOME"));
277     symbol::Context::getInstance()->remove(symbol::Symbol(L"home"));
278     symbol::Context::getInstance()->remove(symbol::Symbol(L"TMPDIR"));
279
280     //open a scope for macros
281     symbol::Context::getInstance()->scope_begin();
282
283     Add_All_Variables();
284     SetScilabVariables();
285
286     symbol::Context::getInstance()->protect();
287     //execute scilab.start
288     if (_pSEI->iNoStart == 0)
289     {
290         execScilabStartTask(_pSEI->iSerialize != 0);
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     //execute scilab.quit
393     if (_pSEI->pstFile)
394     {
395         //-f option execute exec('%s',-1)
396         char *pstCommand = (char *)MALLOC(sizeof(char) * (strlen("exec(\"\",-1)") + strlen(_pSEI->pstFile) + 1));
397         sprintf(pstCommand, "exec(\"%s\",-1)", _pSEI->pstFile);
398
399         _pSEI->pstExec = pstCommand;
400         processCommand(_pSEI);
401         FREE(pstCommand);
402     }
403     else if (_pSEI->iNoStart == 0)
404     {
405         execScilabQuitTask(_pSEI->iSerialize != 0);
406         //call all modules.quit
407         EndModules();
408     }
409
410     //close macros scope
411     symbol::Context::getInstance()->scope_end();
412
413     //close gateways scope
414     symbol::Context::getInstance()->scope_end();
415
416     //clean context
417     symbol::Context::getInstance()->clearAll();
418     //destroy context
419     symbol::Context::destroyInstance();
420 #ifndef NDEBUG
421     //uncomment to print mem leak log
422     //types::Inspector::displayMemleak();
423 #endif
424
425     // cleanup Java dependent features
426     saveCWDInPreferences();
427     clearScilabPreferences();
428     TerminateHistoryManager();
429
430     // stop the JVM
431     if (_pSEI->iNoJvm == 0)
432     {
433         //dynamic_TerminateTclTk();
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->isConsoleCommand != 0);
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     int iInterruptibleCmd   = 0;
530     int iPrioritaryCmd      = 0;
531     int iConsoleCmd         = 0;
532     char* command           = NULL;
533
534     ScilabEngineInfo* _pSEI = (ScilabEngineInfo*)param;
535
536     do
537     {
538         if (GetCommand(&command, &iInterruptibleCmd, &iPrioritaryCmd, &iConsoleCmd) == 0)
539         {
540             // command queue is empty
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->isConsoleCommand = iConsoleCmd;
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     do
833     {
834         // Some times, the signal "SendRunMeSignal" can be sent before the main thread is waiting for.
835         // If a Runner is available do not perform this wait.
836         if (StaticRunner::isRunnerAvailable() == false)
837         {
838             ThreadManagement::WaitForRunMeSignal();
839         }
840
841         try
842         {
843             StaticRunner::launch();
844         }
845         catch (const ast::InternalAbort& /*ia*/)
846         {
847             // go out when exit/quit is called
848         }
849         ThreadManagement::SendAwakeRunnerSignal();
850     }
851     while (ConfigVariable::getForceQuit() == false);
852
853     return ConfigVariable::getExitStatus();
854 }
855
856 /*
857 ** -*- Batch Main -*-
858 */
859 static int batchMain(ScilabEngineInfo* _pSEI)
860 {
861     /*
862      ** -*- PARSING -*-
863      */
864     Parser *parser = new Parser();
865
866     parser->setParseTrace(_pSEI->iParseTrace != 0);
867
868     wchar_t *pwstFileName = to_wide_string(_pSEI->pstParseFile);
869
870     /*
871      ** -*- PARSING -*-
872      */
873     parseFileTask(parser, _pSEI->iTimed != 0, pwstFileName, L"scilab 6");
874
875     /*
876      ** -*- DUMPING TREE -*-
877      */
878     if (_pSEI->iDumpAst)
879     {
880         dumpAstTask(parser->getTree(), _pSEI->iTimed != 0);
881     }
882
883     if (parser->getExitStatus() == Parser::Succeded)
884     {
885         /*
886          ** -*- PRETTY PRINT TREE -*-
887          */
888         if (_pSEI->iPrintAst)
889         {
890             printAstTask(parser->getTree(), _pSEI->iTimed != 0);
891         }
892
893     }
894     else
895     {
896         scilabWriteW(parser->getErrorMessage());
897     }
898
899 #ifdef DEBUG
900     std::cerr << "To end program press [ENTER]" << std::endl;
901 #endif
902     return parser->getExitStatus();
903 }
904
905 /*
906 ** -*- stateView
907 ** Used to show parser state.
908 ** Find if we are stuck within some control structure.
909 */
910 static void stateShow(Parser::ControlStatus status)
911 {
912     switch (status)
913     {
914         //case Parser::WithinFor:
915         //    SetTemporaryPrompt("-for       ->");
916         //    break;
917         //case Parser::WithinWhile:
918         //    SetTemporaryPrompt("-while     ->");
919         //    break;
920         //case Parser::WithinIf:
921         //    SetTemporaryPrompt("-if        ->");
922         //    break;
923         //case Parser::WithinElse:
924         //    SetTemporaryPrompt("-else      ->");
925         //    break;
926         //case Parser::WithinElseIf:
927         //    SetTemporaryPrompt("-elseif    ->");
928         //    break;
929         //case Parser::WithinTry:
930         //    SetTemporaryPrompt("-try       ->");
931         //    break;
932         //case Parser::WithinCatch:
933         //    SetTemporaryPrompt("-catch     ->");
934         //    break;
935         //case Parser::WithinFunction:
936         //    SetTemporaryPrompt("-function  ->");
937         //    break;
938         //case Parser::WithinSelect:
939         //    SetTemporaryPrompt("-select    ->");
940         //    break;
941         //case Parser::WithinCase:
942         //    SetTemporaryPrompt("-case      ->");
943         //    break;
944         //case Parser::WithinSwitch:
945         //    SetTemporaryPrompt("-switch    ->");
946         //    break;
947         //case Parser::WithinOtherwise:
948         //    SetTemporaryPrompt("-otherwise ->");
949         //    break;
950         //case Parser::WithinMatrix:
951         //    SetTemporaryPrompt("- [        ->");
952         //    break;
953         //case Parser::WithinCell:
954         //    SetTemporaryPrompt("- {        ->");
955         //    break;
956         //case Parser::WithinBlockComment:
957         //    SetTemporaryPrompt("- /*       ->");
958         //    break;
959         //case Parser::WithinDots:
960         //    SetTemporaryPrompt("- ...      ->");
961         //    break;
962         default :
963             SetTemporaryPrompt("  > ");
964             break;
965         case Parser::AllControlClosed:
966             //ClearTemporaryPrompt();
967             break;
968     }
969 }
970
971 static int InitializeEnvironnement(void)
972 {
973     SetScilabEnvironment();
974     InitializeLocalization();
975
976     ConfigVariable::setConsoleWidth(75);
977     ConfigVariable::setFormatSize(10);
978     ConfigVariable::setFormatMode(1);
979     //Add_All_Variables();
980     FileManager::initialize();
981     initOperationArray();
982     return 0;
983 }
984
985 /*
986  * Private function to check any linker errors
987  */
988
989 static void checkForLinkerErrors(void)
990 {
991 #ifndef _MSC_VER
992     /*
993        Depending on the linking order, sometime, libs are not loaded the right way.
994        This can cause painful debugging tasks for packager or developer, we are
995        doing the check to help them.
996     */
997 #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"
998 #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"
999
1000     if (getScilabMode() != SCILAB_NWNI && getScilabMode() != SCILAB_API)
1001     {
1002         if (isItTheDisabledLib())
1003         {
1004             fprintf(stderr, LINKER_ERROR_1);
1005             fprintf(stderr, "Here, Scilab should have 'libscijvm' defined but gets 'libscijvm-disable' instead.\n");
1006             fprintf(stderr, LINKER_ERROR_2);
1007             exit(1);
1008         }
1009     }
1010     else
1011     {
1012         /* NWNI mode */
1013         if (!isItTheDisabledLib())
1014         {
1015             fprintf(stderr, LINKER_ERROR_1);
1016             fprintf(stderr, "Here, Scilab should have 'libscijvm-disable' defined but gets 'libscijvm' instead.\n");
1017             fprintf(stderr, LINKER_ERROR_2);
1018             exit(1);
1019         }
1020     }
1021 #undef LINKER_ERROR_1
1022 #undef LINKER_ERROR_2
1023 #endif
1024 }
1025
1026 static void Add_All_Variables(void)
1027 {
1028     Add_pi();
1029     Add_eps();
1030     Add_e();
1031     Add_i();
1032     Add_s();
1033     Add_z();
1034     Add_gui();
1035     Add_fftw();
1036     Add_Nan();
1037     Add_Inf();
1038     Add_io();
1039 }
1040
1041 static void Add_Nan(void)
1042 {
1043     double dbl1 = -1.0;
1044     double dbl0 = fabs(dbl1 - dbl1);
1045
1046     Add_Double_Constant(L"%nan", dbl0 / dbl0, 0, false);
1047 }
1048
1049 static void Add_Inf(void)
1050 {
1051     double dbl1 = 1.0;
1052     double dbl0 = dbl1 - dbl1;
1053
1054     Add_Double_Constant(L"%inf", dbl1 / dbl0, 0, false);
1055 }
1056
1057 static void Add_gui(void)
1058 {
1059     Add_Boolean_Constant(L"%gui", false);
1060 }
1061
1062 static void Add_fftw(void)
1063 {
1064     Add_Boolean_Constant(L"%fftw", withfftw() == 1);
1065 }
1066
1067 static void Add_pi(void)
1068 {
1069     Add_Double_Constant(L"%pi", M_PI, 0, false);
1070 }
1071
1072 static void Add_eps(void)
1073 {
1074     Add_Double_Constant(L"%eps", NumericConstants::eps_machine, 0, false);
1075 }
1076
1077 static void Add_e(void)
1078 {
1079     Add_Double_Constant(L"%e", 2.71828182845904530, 0, false);
1080 }
1081
1082 static void Add_i(void)
1083 {
1084     Add_Double_Constant(L"%i", 0, 1, true);
1085 }
1086
1087 static void Add_s(void)
1088 {
1089     types::Double dblCoef(1, 2);
1090
1091     dblCoef.set(0, 0, 0);
1092     dblCoef.set(0, 1, 1);
1093
1094     Add_Poly_Constant(L"%s", L"s", 1, &dblCoef);
1095 }
1096
1097 static void Add_z(void)
1098 {
1099     types::Double dblCoef(1, 2);
1100
1101     dblCoef.set(0, 0, 0);
1102     dblCoef.set(0, 1, 1);
1103
1104     Add_Poly_Constant(L"%z", L"z", 1, &dblCoef);
1105 }
1106
1107 static void Add_io(void)
1108 {
1109     types::Double * pVal = new types::Double(1, 2);
1110     pVal->set(0, 5);
1111     pVal->set(1, 6);
1112     symbol::Context::getInstance()->put(symbol::Symbol(L"%io"), pVal);
1113 }
1114
1115 static void Add_Poly_Constant(const std::wstring& _szName, const std::wstring& _szPolyVar, int _iRank, types::Double * _pdbl)
1116 {
1117     types::Polynom * pVar = new types::Polynom(_szPolyVar, 1, 1, &_iRank);
1118     types::SinglePoly *poPoly = pVar->get(0);
1119
1120     poPoly->setCoef(_pdbl);
1121     symbol::Context::getInstance()->put(symbol::Symbol(_szName), pVar);
1122 }
1123
1124 static void Add_Double_Constant(const std::wstring& _szName, double _dblReal, double _dblImg, bool _bComplex)
1125 {
1126     types::Double * pVal = new types::Double(1, 1, _bComplex);
1127     pVal->set(0, 0, _dblReal);
1128     pVal->setImg(0, 0, _dblImg);
1129     symbol::Context::getInstance()->put(symbol::Symbol(_szName), pVal);
1130 }
1131
1132 static void Add_Boolean_Constant(const std::wstring& _szName, bool _bBool)
1133 {
1134     types::Bool * pVal = new types::Bool(_bBool);
1135     symbol::Context::getInstance()->put(symbol::Symbol(_szName), pVal);
1136 }
1137
1138 static void Add_String_Constant(const std::wstring& _szName, const char *_pstString)
1139 {
1140     types::String * ps = new types::String(_pstString);
1141     symbol::Context::getInstance()->put(symbol::Symbol(_szName), ps);
1142 }