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