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