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