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