Fixed a few typos
[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             FREE(command);
606             continue;
607         }
608
609         _pSEI->pExpTree = parser.getTree();
610         ThreadManagement::UnlockParser();
611
612         processCommand(_pSEI);
613         FREE(command);
614     }
615     while (ConfigVariable::getForceQuit() == false);
616
617     return NULL;
618 }
619
620 //Thread used to parse and set console commands in storeCommand
621 void* scilabReadAndStore(void* param)
622 {
623     Parser::ControlStatus controlStatus = Parser::AllControlClosed;
624
625     char *command = NULL;
626     wchar_t* parserErrorMsg = NULL;
627
628     ScilabEngineInfo* _pSEI = (ScilabEngineInfo*)param;
629
630     if (_pSEI->iMultiLine)
631     {
632         command = _pSEI->pstExec;
633     }
634
635     if (isEmptyCommandQueue() == false)
636     {
637         // unlock main thread
638         ThreadManagement::SendStartPendingSignal();
639
640         // Command stored as console command by -f
641         // We have to wait this execution before
642         // callOnPrompt (ie: onPrompt perform a quit in test_run)
643         ThreadManagement::WaitForConsoleExecDoneSignal();
644     }
645
646     // unlock main thread
647     ThreadManagement::SendStartPendingSignal();
648
649     while (ConfigVariable::getForceQuit() == false)
650     {
651         callOnPrompt();
652
653         Parser parser;
654         parser.setParseTrace(_pSEI->iParseTrace != 0);
655
656         Parser::ParserStatus exitStatus = Parser::Failed;
657
658         if (ConfigVariable::isPrintCompact() == false)
659         {
660             scilabWriteW(L"\n");
661         }
662
663         do
664         {
665             // Show Parser Sate before prompt
666             stateShow(controlStatus);
667
668             int pause = ConfigVariable::getPauseLevel();
669
670             //set prompt value
671             C2F(setprlev) (&pause);
672
673             if (scilabRead() == 0)
674             {
675                 // happens when the return of scilabRead must not be interpreted by Scilab.
676                 // ie: mscanf, step by step execution (mode 4 or 7)
677                 ThreadManagement::WaitForConsoleExecDoneSignal();
678                 continue;
679             }
680
681             char* pstRead = ConfigVariable::getConsoleReadStr();
682             if (command == NULL)
683             {
684                 command = pstRead;
685                 if (strcmp(command, "") == 0)
686                 {
687                     FREE(command);
688                     command = NULL;
689                     break;
690                 }
691 #ifdef DEBUG_THREAD
692                 ThreadManagement::PrintDebugHead();
693 #endif // DEBUG_THREAD
694             }
695             else
696             {
697                 if (ConfigVariable::isExecutionBreak())
698                 {
699                     //clean parser state and close opened instruction.
700                     if (parser.getControlStatus() != Parser::AllControlClosed)
701                     {
702                         parser.cleanup();
703                         FREE(command);
704                         command = NULL;
705                         parser.setControlStatus(Parser::AllControlClosed);
706                         controlStatus = parser.getControlStatus();
707                     }
708
709                     ConfigVariable::resetExecutionBreak();
710                     break;
711                 }
712                 else
713                 {
714                     //+1 for null termination and +1 for '\n'
715                     size_t iLen = strlen(command) + strlen(pstRead) + 2;
716                     char *pstNewCommand = (char *)MALLOC(iLen * sizeof(char));
717
718 #ifdef _MSC_VER
719                     sprintf_s(pstNewCommand, iLen, "%s\n%s", command, pstRead);
720 #else
721                     sprintf(pstNewCommand, "%s\n%s", command, pstRead);
722 #endif
723                     FREE(pstRead);
724                     FREE(command);
725                     command = pstNewCommand;
726                 }
727             }
728
729             if (ConfigVariable::getEnableDebug())
730             {
731                 bool disableDebug = false;
732                 char* tmpCommand = NULL;
733                 int commandsize = strlen(command);
734
735                 //all commands must be prefixed by debug except e(xec) (r)un or p(rint) "something" that become "something" or disp("something")
736                 if (strncmp(command, "e ", 2) == 0 || strncmp(command, "r ", 2) == 0)
737                 {
738                     tmpCommand = os_strdup(command + 2);
739                 }
740                 else if (commandsize >= 5 && strncmp(command, "exec ", 5) == 0)
741                 {
742                     tmpCommand = os_strdup(command + 5);
743                 }
744                 else if (commandsize >= 4 && strncmp(command, "run ", 4) == 0)
745                 {
746                     tmpCommand = os_strdup(command + 5);
747                 }
748
749                 if (tmpCommand)
750                 {
751                     if (debugger::DebuggerMagager::getInstance()->isInterrupted())
752                     {
753                         sciprint(_("Debugger is on a breakpoint\n"));
754                         sciprint(_("(c)ontinue or (a)bort current execution before execute a new command\n"));
755                         FREE(tmpCommand);
756                         continue;
757                     }
758                 }
759                 else if (commandsize > 1 && command[0] == 'd' && command[1] == ' ')
760                 {
761                     std::string s("disp(");
762                     s += command + 2;
763                     s += ")";
764                     tmpCommand = os_strdup(s.data());
765                     disableDebug = true;
766                 }
767                 else if (commandsize > 5 && strncmp(command, "disp ", 5) == 0)
768                 {
769                     std::string s("disp(");
770                     s += command + 5;
771                     s += ")";
772                     tmpCommand = os_strdup(s.data());
773                     disableDebug = true;
774                 }
775                 else if (commandsize > 1 && command[0] == 'p' && command[1] == ' ')
776                 {
777                     std::string s("disp(");
778                     s += command + 2;
779                     s += ")";
780                     tmpCommand = os_strdup(s.data());
781                     disableDebug = true;
782                 }
783                 else if (commandsize > 6 && strncmp(command, "print ", 6) == 0)
784                 {
785                     std::string s("disp(");
786                     s += command + 6;
787                     s += ")";
788                     tmpCommand = os_strdup(s.data());
789                     disableDebug = true;
790                 }
791                 else
792                 {
793                     int iLen = (int)strlen(command) + (int)strlen("debug ") + 1;
794                     tmpCommand = (char*)MALLOC(sizeof(char) * iLen);
795 #ifdef _MSC_VER
796                     os_sprintf(tmpCommand, iLen, "%s %s", "debug", command);
797 #else
798                     os_sprintf(tmpCommand, "%s %s", "debug", command);
799 #endif
800                     disableDebug = true;
801                 }
802
803                 if (disableDebug)
804                 {
805                     //disable debugger time to exec debug command
806                     //it will be enable in debuggervisitor, after execution
807                     ConfigVariable::setEnableDebug(false);
808                 }
809
810                 FREE(command);
811                 command = tmpCommand;
812             }
813
814             ThreadManagement::LockParser();
815             parseCommandTask(&parser, _pSEI->iTimed != 0, command);
816             controlStatus = parser.getControlStatus();
817             exitStatus = parser.getExitStatus();
818             parserErrorMsg = parser.getErrorMessage();
819             if (parser.getTree())
820             {
821                 delete parser.getTree();
822                 parser.setTree(NULL);
823             }
824             ThreadManagement::UnlockParser();
825         }
826         while (controlStatus != Parser::AllControlClosed);
827
828         if (command == NULL)
829         {
830             continue;
831         }
832
833         if (exitStatus == Parser::Failed)
834         {
835             FREE(command);
836             command = NULL;
837             scilabForcedWriteW(parserErrorMsg);
838             continue;
839         }
840
841         // store the command and wait for this execution ends.
842         StoreConsoleCommand(command, 1);
843
844         FREE(command);
845         command = NULL;
846     }
847
848     // Awake scilabReadAndExecCommand thread in case of scilab exit
849     ThreadManagement::SendCommandStoredSignal();
850     return NULL;
851 }
852
853 /*
854 ** -*- Interactive Main -*-
855 */
856 static int interactiveMain(ScilabEngineInfo* _pSEI)
857 {
858 #ifndef WITH_GUI
859 #ifndef _MSC_VER
860     if (getScilabMode() != SCILAB_NWNI)
861     {
862         fprintf(stderr, "Scilab was compiled without its GUI and advanced features. Run scilab-cli or use the -nwni option.\n");
863         initConsoleMode(ATTR_RESET);
864         exit(1);
865     }
866 #endif
867 #endif
868
869     InitializeHistoryManager();
870
871     if (getScilabMode() != SCILAB_NWNI && getScilabMode() != SCILAB_API)
872     {
873
874         char *cwd = NULL;
875
876         int err = 0;
877
878         UpdateBrowseVar();
879         cwd = scigetcwd(&err);
880         if (cwd)
881         {
882             FileBrowserChDir(cwd);
883             FREE(cwd);
884         }
885     }
886
887     // -e -quit with parser error, command queue is empty
888     if (_pSEI->iForceQuit && isEmptyCommandQueue())
889     {
890         return 1;
891     }
892
893     __threadId threadIdConsole;
894     __threadKey threadKeyConsole;
895     __threadId threadIdCommand;
896     __threadKey threadKeyCommand;
897
898     if (_pSEI->iStartConsoleThread)
899     {
900         // thread to manage console command
901         __CreateThreadWithParams(&threadIdConsole, &threadKeyConsole, &scilabReadAndStore, _pSEI);
902
903         // scilabReadAndStore thread must be execute before scilabReadAndExecCommand
904         // to be such that the -f command stored is not removed
905         // from queue before scilabReadAndStore is waiting for.
906         ThreadManagement::WaitForStartPendingSignal();
907     }
908
909     // thread to manage command stored
910     __CreateThreadWithParams(&threadIdCommand, &threadKeyCommand, &scilabReadAndExecCommand, _pSEI);
911
912 #ifdef DEBUG_THREAD
913     ThreadManagement::SetThreadKey( __GetCurrentThreadKey(), threadKeyCommand, threadKeyConsole);
914 #endif // DEBUG_THREAD
915
916     int iRet = 0;
917     do
918     {
919         // wait for available runner
920         ThreadManagement::WaitForRunMeSignal();
921
922         try
923         {
924             iRet = StaticRunner::launch();
925         }
926         catch (const ast::InternalAbort& /*ia*/)
927         {
928             // go out when exit/quit is called
929             iRet = ConfigVariable::getExitStatus();
930         }
931         catch (const ast::RecursionException& /*re*/)
932         {
933             // go out when exit/quit is called
934             iRet = 1;
935         }
936
937         ThreadManagement::SendAwakeRunnerSignal();
938     }
939     while (ConfigVariable::getForceQuit() == false);
940
941     return iRet;
942 }
943
944 /*
945 ** -*- Batch Main -*-
946 */
947 static int batchMain(ScilabEngineInfo* _pSEI)
948 {
949     /*
950      ** -*- PARSING -*-
951      */
952     Parser *parser = new Parser();
953
954     parser->setParseTrace(_pSEI->iParseTrace != 0);
955
956     wchar_t *pwstFileName = to_wide_string(_pSEI->pstParseFile);
957
958     /*
959      ** -*- PARSING -*-
960      */
961     parseFileTask(parser, _pSEI->iTimed != 0, pwstFileName, L"scilab 6");
962
963     /*
964      ** -*- DUMPING TREE -*-
965      */
966     if (_pSEI->iDumpAst)
967     {
968         dumpAstTask(parser->getTree(), _pSEI->iTimed != 0);
969     }
970
971     if (parser->getExitStatus() == Parser::Succeded)
972     {
973         /*
974          ** -*- PRETTY PRINT TREE -*-
975          */
976         if (_pSEI->iPrintAst)
977         {
978             printAstTask(parser->getTree(), _pSEI->iTimed != 0);
979         }
980
981     }
982     else
983     {
984         scilabWriteW(parser->getErrorMessage());
985     }
986
987 #ifdef DEBUG
988     std::cerr << "To end program press [ENTER]" << std::endl;
989 #endif
990     int ret = parser->getExitStatus();
991     delete parser;
992     FREE(pwstFileName);
993     return ret;
994 }
995
996 /*
997 ** -*- stateView
998 */
999 static void stateShow(Parser::ControlStatus status)
1000 {
1001     if (status != Parser::AllControlClosed)
1002     {
1003         SetTemporaryPrompt("  > ");
1004     }
1005 }
1006
1007 static int InitializeEnvironnement(void)
1008 {
1009     SetScilabEnvironment();
1010     InitializeLocalization();
1011
1012     ConfigVariable::setConsoleWidth(75);
1013     ConfigVariable::setFormatSize(10);
1014     ConfigVariable::setFormatMode(1);
1015     //Add_All_Variables();
1016     FileManager::initialize();
1017     initOperationArray();
1018     return 0;
1019 }
1020
1021 /*
1022  * Private function to check any linker errors
1023  */
1024
1025 static void checkForLinkerErrors(void)
1026 {
1027 #ifndef _MSC_VER
1028     /*
1029        Depending on the linking order, sometimes, libs are not loaded the right way.
1030        This can cause painful debugging tasks for packager or developer, we are
1031        doing the check to help them.
1032     */
1033 #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"
1034 #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"
1035
1036     if (getScilabMode() != SCILAB_NWNI && getScilabMode() != SCILAB_API)
1037     {
1038         if (isItTheDisabledLib())
1039         {
1040             fprintf(stderr, LINKER_ERROR_1);
1041             fprintf(stderr, "Here, Scilab should have 'libscijvm' defined but gets 'libscijvm-disable' instead.\n");
1042             fprintf(stderr, LINKER_ERROR_2);
1043             exit(1);
1044         }
1045     }
1046     else
1047     {
1048         /* NWNI mode */
1049         if (!isItTheDisabledLib())
1050         {
1051             fprintf(stderr, LINKER_ERROR_1);
1052             fprintf(stderr, "Here, Scilab should have 'libscijvm-disable' defined but gets 'libscijvm' instead.\n");
1053             fprintf(stderr, LINKER_ERROR_2);
1054             exit(1);
1055         }
1056     }
1057 #undef LINKER_ERROR_1
1058 #undef LINKER_ERROR_2
1059 #endif
1060 }
1061
1062 static void Add_All_Variables(void)
1063 {
1064     Add_pi();
1065     Add_eps();
1066     Add_e();
1067     Add_i();
1068     Add_s();
1069     Add_z();
1070     Add_gui();
1071     Add_fftw();
1072     Add_Nan();
1073     Add_Inf();
1074     Add_io();
1075 }
1076
1077 static void Add_Nan(void)
1078 {
1079     double dbl1 = -1.0;
1080     double dbl0 = fabs(dbl1 - dbl1);
1081
1082     Add_Double_Constant(L"%nan", dbl0 / dbl0, 0, false);
1083 }
1084
1085 static void Add_Inf(void)
1086 {
1087     double dbl1 = 1.0;
1088     double dbl0 = dbl1 - dbl1;
1089
1090     Add_Double_Constant(L"%inf", dbl1 / dbl0, 0, false);
1091 }
1092
1093 static void Add_gui(void)
1094 {
1095     Add_Boolean_Constant(L"%gui", false);
1096 }
1097
1098 static void Add_fftw(void)
1099 {
1100     Add_Boolean_Constant(L"%fftw", withfftw() == 1);
1101 }
1102
1103 static void Add_pi(void)
1104 {
1105     Add_Double_Constant(L"%pi", M_PI, 0, false);
1106 }
1107
1108 static void Add_eps(void)
1109 {
1110     Add_Double_Constant(L"%eps", NumericConstants::eps_machine, 0, false);
1111 }
1112
1113 static void Add_e(void)
1114 {
1115     Add_Double_Constant(L"%e", 2.71828182845904530, 0, false);
1116 }
1117
1118 static void Add_i(void)
1119 {
1120     Add_Double_Constant(L"%i", 0, 1, true);
1121 }
1122
1123 static void Add_s(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"%s", L"s", 1, &dblCoef);
1131 }
1132
1133 static void Add_z(void)
1134 {
1135     types::Double dblCoef(1, 2);
1136
1137     dblCoef.set(0, 0, 0);
1138     dblCoef.set(0, 1, 1);
1139
1140     Add_Poly_Constant(L"%z", L"z", 1, &dblCoef);
1141 }
1142
1143 static void Add_io(void)
1144 {
1145     types::Double * pVal = new types::Double(1, 2);
1146     pVal->set(0, 5);
1147     pVal->set(1, 6);
1148     symbol::Context::getInstance()->put(symbol::Symbol(L"%io"), pVal);
1149 }
1150
1151 static void Add_Poly_Constant(const std::wstring& _szName, const std::wstring& _szPolyVar, int _iRank, types::Double * _pdbl)
1152 {
1153     types::Polynom * pVar = new types::Polynom(_szPolyVar, 1, 1, &_iRank);
1154     types::SinglePoly *poPoly = pVar->get(0);
1155
1156     poPoly->setCoef(_pdbl);
1157     symbol::Context::getInstance()->put(symbol::Symbol(_szName), pVar);
1158 }
1159
1160 static void Add_Double_Constant(const std::wstring& _szName, double _dblReal, double _dblImg, bool _bComplex)
1161 {
1162     types::Double * pVal = new types::Double(1, 1, _bComplex);
1163     pVal->set(0, 0, _dblReal);
1164     pVal->setImg(0, 0, _dblImg);
1165     symbol::Context::getInstance()->put(symbol::Symbol(_szName), pVal);
1166 }
1167
1168 static void Add_Boolean_Constant(const std::wstring& _szName, bool _bBool)
1169 {
1170     types::Bool * pVal = new types::Bool(_bBool);
1171     symbol::Context::getInstance()->put(symbol::Symbol(_szName), pVal);
1172 }
1173
1174 static void Add_String_Constant(const std::wstring& _szName, const char *_pstString)
1175 {
1176     types::String * ps = new types::String(_pstString);
1177     symbol::Context::getInstance()->put(symbol::Symbol(_szName), ps);
1178 }