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