4c2f1a8eb6b4dd0425493ee77467a3d839ee03f0
[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
20 #include "inspector.hxx"
21 #include "double.hxx"
22 #include "polynom.hxx"
23 #include "string.hxx"
24 #include "bool.hxx"
25
26 #include "scilabWrite.hxx"
27 #include "tasks.hxx"
28 #include "parser.hxx"
29 #include "context.hxx"
30 #include "configvariable.hxx"
31 #include "filemanager.hxx"
32 #include "runner.hxx"
33 #include "visitor_common.hxx"
34 #include "operations.hxx"
35 #include "threadmanagement.hxx"
36 #include "numericconstants.hxx"
37 #include "expandPathVariable.h"
38 #include "execvisitor.hxx"
39 #include "debugmanager.hxx"
40 #include "consoledebugger.hxx"
41
42 extern "C"
43 {
44 #include <locale.h>
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     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                         FREE(tmpCommand);
755                         continue;
756                     }
757                 }
758                 else if (commandsize > 1 && command[0] == 'd' && command[1] == ' ')
759                 {
760                     std::string s("disp(");
761                     s += command + 2;
762                     s += ")";
763                     tmpCommand = os_strdup(s.data());
764                     disableDebug = true;
765                 }
766                 else if (commandsize > 5 && strncmp(command, "disp ", 5) == 0)
767                 {
768                     std::string s("disp(");
769                     s += command + 5;
770                     s += ")";
771                     tmpCommand = os_strdup(s.data());
772                     disableDebug = true;
773                 }
774                 else if (commandsize > 1 && command[0] == 'p' && command[1] == ' ')
775                 {
776                     std::string s("disp(");
777                     s += command + 2;
778                     s += ")";
779                     tmpCommand = os_strdup(s.data());
780                     disableDebug = true;
781                 }
782                 else if (commandsize > 6 && strncmp(command, "print ", 6) == 0)
783                 {
784                     std::string s("disp(");
785                     s += command + 6;
786                     s += ")";
787                     tmpCommand = os_strdup(s.data());
788                     disableDebug = true;
789                 }
790                 else
791                 {
792                     int iLen = (int)strlen(command) + (int)strlen("debug ") + 1;
793                     tmpCommand = (char*)MALLOC(sizeof(char) * iLen);
794 #ifdef _MSC_VER
795                     os_sprintf(tmpCommand, iLen, "%s %s", "debug", command);
796 #else
797                     os_sprintf(tmpCommand, "%s %s", "debug", command);
798 #endif
799                     disableDebug = true;
800                 }
801
802                 if (disableDebug)
803                 {
804                     //disable debugger time to exec debug command
805                     //it will be enable in debuggervisitor, after execution
806                     ConfigVariable::setEnableDebug(false);
807                 }
808
809                 FREE(command);
810                 command = tmpCommand;
811             }
812
813             ThreadManagement::LockParser();
814             parseCommandTask(&parser, _pSEI->iTimed != 0, command);
815             controlStatus = parser.getControlStatus();
816             exitStatus = parser.getExitStatus();
817             parserErrorMsg = parser.getErrorMessage();
818             if (parser.getTree())
819             {
820                 delete parser.getTree();
821                 parser.setTree(NULL);
822             }
823             ThreadManagement::UnlockParser();
824         }
825         while (controlStatus != Parser::AllControlClosed);
826
827         if (command == NULL)
828         {
829             continue;
830         }
831
832         if (exitStatus == Parser::Failed)
833         {
834             FREE(command);
835             command = NULL;
836             scilabForcedWriteW(parserErrorMsg);
837             continue;
838         }
839
840         // store the command and wait for this execution ends.
841         StoreConsoleCommand(command, 1);
842
843         FREE(command);
844         command = NULL;
845     }
846
847     // Awake scilabReadAndExecCommand thread in case of scilab exit
848     ThreadManagement::SendCommandStoredSignal();
849     return NULL;
850 }
851
852 /*
853 ** -*- Interactive Main -*-
854 */
855 static int interactiveMain(ScilabEngineInfo* _pSEI)
856 {
857 #ifndef WITH_GUI
858 #ifndef _MSC_VER
859     if (getScilabMode() != SCILAB_NWNI)
860     {
861         fprintf(stderr, "Scilab was compiled without its GUI and advanced features. Run scilab-cli or use the -nwni option.\n");
862         initConsoleMode(ATTR_RESET);
863         exit(1);
864     }
865 #endif
866 #endif
867
868     InitializeHistoryManager();
869
870     if (getScilabMode() != SCILAB_NWNI && getScilabMode() != SCILAB_API)
871     {
872
873         char *cwd = NULL;
874
875         int err = 0;
876
877         UpdateBrowseVar();
878         cwd = scigetcwd(&err);
879         if (cwd)
880         {
881             FileBrowserChDir(cwd);
882             FREE(cwd);
883         }
884     }
885
886     // -e -quit with parser error, command queue is empty
887     if (_pSEI->iForceQuit && isEmptyCommandQueue())
888     {
889         return 1;
890     }
891
892     __threadId threadIdConsole;
893     __threadKey threadKeyConsole;
894     __threadId threadIdCommand;
895     __threadKey threadKeyCommand;
896
897     if (_pSEI->iStartConsoleThread)
898     {
899         // thread to manage console command
900         __CreateThreadWithParams(&threadIdConsole, &threadKeyConsole, &scilabReadAndStore, _pSEI);
901
902         // scilabReadAndStore thread must be execute before scilabReadAndExecCommand
903         // to be such that the -f command stored is not removed
904         // from queue before scilabReadAndStore is waiting for.
905         ThreadManagement::WaitForStartPendingSignal();
906     }
907
908     // thread to manage command stored
909     __CreateThreadWithParams(&threadIdCommand, &threadKeyCommand, &scilabReadAndExecCommand, _pSEI);
910
911 #ifdef DEBUG_THREAD
912     ThreadManagement::SetThreadKey( __GetCurrentThreadKey(), threadKeyCommand, threadKeyConsole);
913 #endif // DEBUG_THREAD
914
915     int iRet = 0;
916     do
917     {
918         // wait for available runner
919         ThreadManagement::WaitForRunMeSignal();
920
921         try
922         {
923             iRet = StaticRunner::launch();
924         }
925         catch (const ast::InternalAbort& /*ia*/)
926         {
927             // go out when exit/quit is called
928             iRet = ConfigVariable::getExitStatus();
929         }
930         catch (const ast::RecursionException& /*re*/)
931         {
932             // go out when exit/quit is called
933             iRet = 1;
934         }
935
936         ThreadManagement::SendAwakeRunnerSignal();
937     }
938     while (ConfigVariable::getForceQuit() == false);
939
940     return iRet;
941 }
942
943 /*
944 ** -*- Batch Main -*-
945 */
946 static int batchMain(ScilabEngineInfo* _pSEI)
947 {
948     /*
949      ** -*- PARSING -*-
950      */
951     Parser *parser = new Parser();
952
953     parser->setParseTrace(_pSEI->iParseTrace != 0);
954
955     wchar_t *pwstFileName = to_wide_string(_pSEI->pstParseFile);
956
957     /*
958      ** -*- PARSING -*-
959      */
960     parseFileTask(parser, _pSEI->iTimed != 0, pwstFileName, L"scilab 6");
961
962     /*
963      ** -*- DUMPING TREE -*-
964      */
965     if (_pSEI->iDumpAst)
966     {
967         dumpAstTask(parser->getTree(), _pSEI->iTimed != 0);
968     }
969
970     if (parser->getExitStatus() == Parser::Succeded)
971     {
972         /*
973          ** -*- PRETTY PRINT TREE -*-
974          */
975         if (_pSEI->iPrintAst)
976         {
977             printAstTask(parser->getTree(), _pSEI->iTimed != 0);
978         }
979
980     }
981     else
982     {
983         scilabWriteW(parser->getErrorMessage());
984     }
985
986 #ifdef DEBUG
987     std::cerr << "To end program press [ENTER]" << std::endl;
988 #endif
989     int ret = parser->getExitStatus();
990     delete parser;
991     return ret;
992 }
993
994 /*
995 ** -*- stateView
996 */
997 static void stateShow(Parser::ControlStatus status)
998 {
999     if (status != Parser::AllControlClosed)
1000     {
1001         SetTemporaryPrompt("  > ");
1002     }
1003 }
1004
1005 static int InitializeEnvironnement(void)
1006 {
1007     SetScilabEnvironment();
1008     InitializeLocalization();
1009
1010     ConfigVariable::setConsoleWidth(75);
1011     ConfigVariable::setFormatSize(10);
1012     ConfigVariable::setFormatMode(1);
1013     //Add_All_Variables();
1014     FileManager::initialize();
1015     initOperationArray();
1016     return 0;
1017 }
1018
1019 /*
1020  * Private function to check any linker errors
1021  */
1022
1023 static void checkForLinkerErrors(void)
1024 {
1025 #ifndef _MSC_VER
1026     /*
1027        Depending on the linking order, sometime, libs are not loaded the right way.
1028        This can cause painful debugging tasks for packager or developer, we are
1029        doing the check to help them.
1030     */
1031 #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"
1032 #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"
1033
1034     if (getScilabMode() != SCILAB_NWNI && getScilabMode() != SCILAB_API)
1035     {
1036         if (isItTheDisabledLib())
1037         {
1038             fprintf(stderr, LINKER_ERROR_1);
1039             fprintf(stderr, "Here, Scilab should have 'libscijvm' defined but gets 'libscijvm-disable' instead.\n");
1040             fprintf(stderr, LINKER_ERROR_2);
1041             exit(1);
1042         }
1043     }
1044     else
1045     {
1046         /* NWNI mode */
1047         if (!isItTheDisabledLib())
1048         {
1049             fprintf(stderr, LINKER_ERROR_1);
1050             fprintf(stderr, "Here, Scilab should have 'libscijvm-disable' defined but gets 'libscijvm' instead.\n");
1051             fprintf(stderr, LINKER_ERROR_2);
1052             exit(1);
1053         }
1054     }
1055 #undef LINKER_ERROR_1
1056 #undef LINKER_ERROR_2
1057 #endif
1058 }
1059
1060 static void Add_All_Variables(void)
1061 {
1062     Add_pi();
1063     Add_eps();
1064     Add_e();
1065     Add_i();
1066     Add_s();
1067     Add_z();
1068     Add_gui();
1069     Add_fftw();
1070     Add_Nan();
1071     Add_Inf();
1072     Add_io();
1073 }
1074
1075 static void Add_Nan(void)
1076 {
1077     double dbl1 = -1.0;
1078     double dbl0 = fabs(dbl1 - dbl1);
1079
1080     Add_Double_Constant(L"%nan", dbl0 / dbl0, 0, false);
1081 }
1082
1083 static void Add_Inf(void)
1084 {
1085     double dbl1 = 1.0;
1086     double dbl0 = dbl1 - dbl1;
1087
1088     Add_Double_Constant(L"%inf", dbl1 / dbl0, 0, false);
1089 }
1090
1091 static void Add_gui(void)
1092 {
1093     Add_Boolean_Constant(L"%gui", false);
1094 }
1095
1096 static void Add_fftw(void)
1097 {
1098     Add_Boolean_Constant(L"%fftw", withfftw() == 1);
1099 }
1100
1101 static void Add_pi(void)
1102 {
1103     Add_Double_Constant(L"%pi", M_PI, 0, false);
1104 }
1105
1106 static void Add_eps(void)
1107 {
1108     Add_Double_Constant(L"%eps", NumericConstants::eps_machine, 0, false);
1109 }
1110
1111 static void Add_e(void)
1112 {
1113     Add_Double_Constant(L"%e", 2.71828182845904530, 0, false);
1114 }
1115
1116 static void Add_i(void)
1117 {
1118     Add_Double_Constant(L"%i", 0, 1, true);
1119 }
1120
1121 static void Add_s(void)
1122 {
1123     types::Double dblCoef(1, 2);
1124
1125     dblCoef.set(0, 0, 0);
1126     dblCoef.set(0, 1, 1);
1127
1128     Add_Poly_Constant(L"%s", L"s", 1, &dblCoef);
1129 }
1130
1131 static void Add_z(void)
1132 {
1133     types::Double dblCoef(1, 2);
1134
1135     dblCoef.set(0, 0, 0);
1136     dblCoef.set(0, 1, 1);
1137
1138     Add_Poly_Constant(L"%z", L"z", 1, &dblCoef);
1139 }
1140
1141 static void Add_io(void)
1142 {
1143     types::Double * pVal = new types::Double(1, 2);
1144     pVal->set(0, 5);
1145     pVal->set(1, 6);
1146     symbol::Context::getInstance()->put(symbol::Symbol(L"%io"), pVal);
1147 }
1148
1149 static void Add_Poly_Constant(const std::wstring& _szName, const std::wstring& _szPolyVar, int _iRank, types::Double * _pdbl)
1150 {
1151     types::Polynom * pVar = new types::Polynom(_szPolyVar, 1, 1, &_iRank);
1152     types::SinglePoly *poPoly = pVar->get(0);
1153
1154     poPoly->setCoef(_pdbl);
1155     symbol::Context::getInstance()->put(symbol::Symbol(_szName), pVar);
1156 }
1157
1158 static void Add_Double_Constant(const std::wstring& _szName, double _dblReal, double _dblImg, bool _bComplex)
1159 {
1160     types::Double * pVal = new types::Double(1, 1, _bComplex);
1161     pVal->set(0, 0, _dblReal);
1162     pVal->setImg(0, 0, _dblImg);
1163     symbol::Context::getInstance()->put(symbol::Symbol(_szName), pVal);
1164 }
1165
1166 static void Add_Boolean_Constant(const std::wstring& _szName, bool _bBool)
1167 {
1168     types::Bool * pVal = new types::Bool(_bBool);
1169     symbol::Context::getInstance()->put(symbol::Symbol(_szName), pVal);
1170 }
1171
1172 static void Add_String_Constant(const std::wstring& _szName, const char *_pstString)
1173 {
1174     types::String * ps = new types::String(_pstString);
1175     symbol::Context::getInstance()->put(symbol::Symbol(_szName), ps);
1176 }