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