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