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
6 * This file must be used under the terms of the CeCILL.
7 * This source file is licensed as described in the file COPYING, which
8 * you should have received as part of this distribution. The terms
9 * are also available at
10 * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
15 #include <libxml/parser.h>
17 #include "inspector.hxx"
19 #include "polynom.hxx"
23 #include "scilabWrite.hxx"
26 #include "context.hxx"
27 #include "configvariable.hxx"
28 #include "filemanager.hxx"
30 #include "visitor_common.hxx"
31 #include "operations.hxx"
36 #include "InitializeLocalization.h"
37 #include "elem_common.h"
38 #include "LaunchScilabSignal.h"
39 #include "InitializeJVM.h"
40 #include "TerminateJVM.h"
41 #include "InitializeGUI.h"
42 #include "graphicModuleLoad.h"
43 #include "TerminateGraphics.h"
44 #include "loadBackGroundClassPath.h"
45 #include "sci_tmpdir.h"
46 #include "configvariable_interface.h"
47 #include "setgetlanguage.h"
48 #include "InitializeConsole.h"
49 #include "InitializeHistoryManager.h"
50 #include "TerminateHistoryManager.h"
52 #include "scilabRead.h"
53 #include "functions_manager.h"
54 #include "InitScilab.h"
55 #include "setenvvar.h"
56 #include "getScilabPreference.h"
57 #include "saveCWDInPreferences.h"
58 #include "h5_fileManagement.h"
59 #include "with_fftw.h"
63 #include "InitializeWindows_tools.h"
64 #include "TerminateWindows_tools.h"
65 #include "WndThread.h"
67 #include "InnosetupMutex.h"
68 #include "MutexClosingScilab.h"
69 #include "WinConsole.h"
71 #include "signal_mgmt.h"
72 #include "initConsoleMode.h"
75 #if defined(linux) && defined(__i386__)
76 #include "setPrecisionFPU.h"
79 /* Defined without include to avoid useless header dependency */
80 extern BOOL isItTheDisabledLib(void);
83 static void Add_i(void);
84 static void Add_pi(void);
85 static void Add_eps(void);
86 static void Add_e(void);
87 static void Add_s(void);
88 static void Add_z(void);
89 static void Add_gui(void);
90 static void Add_fftw(void);
91 static void Add_Nan(void);
92 static void Add_Inf(void);
93 static void Add_io(void);
94 static void Add_All_Variables(void);
95 static void Add_Double_Constant(std::wstring _szName, double _dblReal, double _dblImg, bool _bComplex);
96 static void Add_Poly_Constant(std::wstring _szName, std::wstring _szPolyVar, int _iRank, types::Double * _pdblReal);
97 static void Add_Boolean_Constant(std::wstring _szName, bool _bBool);
98 static void Add_String_Constant(std::wstring _szName, const char *_pstString);
99 static void checkForLinkerErrors(void);
101 static int batchMain(ScilabEngineInfo* _pSEI);
102 static int InitializeEnvironnement(void);
103 static int interactiveMain(ScilabEngineInfo* _pSEI);
104 static Parser::ControlStatus processCommand(ScilabEngineInfo* _pSEI);
105 static void stateShow(Parser::ControlStatus status);
109 ScilabEngineInfo* InitScilabEngineInfo()
111 // Disable all startup flags.
112 ScilabEngineInfo* pSEI = (ScilabEngineInfo*)CALLOC(1, sizeof(ScilabEngineInfo));
114 //Active default flags
121 int StartScilabEngine(ScilabEngineInfo* _pSEI)
124 ConfigVariable::setStartProcessing(true);
126 /* This bug only occurs under Linux 32 bits
127 * See: http://wiki.scilab.org/Scilab_precision
129 #if defined(linux) && defined(__i386__)
134 /* Management of the signals (seg fault, floating point exception, etc) */
135 if (getenv("SCI_DISABLE_EXCEPTION_CATCHING") == NULL)
141 #if defined(netbsd) || defined(freebsd)
142 /* floating point exceptions */
148 checkForLinkerErrors();
151 //get current console window and hide it
152 int scilabMode = getScilabMode();
153 if (scilabMode == SCILAB_STD || scilabMode == SCILAB_NW)
155 CreateScilabHiddenWndThread();
158 if (scilabMode == SCILAB_STD)
160 //show banner in console window
161 CreateScilabConsole(_pSEI->iNoBanner);
163 if (_pSEI->iKeepConsole == 0)
165 HideScilex(); /* hide console window */
174 if (scilabMode == SCILAB_NW || scilabMode == SCILAB_NWNI)
177 if (scilabMode == SCILAB_NW)
180 UpdateConsoleColors();
185 //create a thread for innosetup to allow reinstall during scilab running
186 createInnosetupMutex();
189 InitializeLaunchScilabSignal();
193 InitializeEnvironnement();
197 wchar_t *pwstLang = to_wide_string(_pSEI->pstLang);
198 setlanguage(pwstLang);
203 InitializeWindows_tools();
206 if (_pSEI->iNoJvm == 0) // With JVM
209 /* tclsci creates a TK window on Windows */
210 /* it changes focus on previous windows */
211 /* we put InitializeTclTk before InitializeGUI */
217 /* create needed data structure if not already created */
220 loadBackGroundClassPath();
222 //update %gui to true
223 Add_Boolean_Constant(L"%gui", true);
226 /* Standard mode -> init Java Console */
227 if (_pSEI->iConsoleMode == 0)
229 /* Initialize console: lines... */
235 initConsoleMode(RAW);
239 //open "protection" scope to protect all variables after scilab start
240 symbol::Context::getInstance()->scope_begin();
244 //execute scilab.start
245 if (_pSEI->iNoStart == 0)
248 execScilabStartTask(_pSEI->iSerialize != 0);
251 ConfigVariable::setStartProcessing(false);
255 C2F(setprlev) (&pause);
257 ConfigVariable::setPromptMode(0);
264 processCommand(_pSEI);
265 iMainRet = ConfigVariable::getExitStatus();
267 else if (_pSEI->pstFile)
269 //-f option execute exec('%s',-1)
270 char *pstCommand = (char *)MALLOC(sizeof(char) * (strlen("exec(\"\",-1)") + strlen(_pSEI->pstFile) + 1));
271 sprintf(pstCommand, "exec(\"%s\",-1)", _pSEI->pstFile);
273 _pSEI->pstExec = pstCommand;
274 processCommand(_pSEI);
276 iMainRet = ConfigVariable::getExitStatus();
277 _pSEI->pstExec = NULL;
278 _pSEI->pstFile = NULL;
281 catch (const ast::ScilabException& se)
283 scilabErrorW(se.GetErrorMessage().c_str());
286 ConfigVariable::setPromptMode(2);
290 int RunScilabEngine(ScilabEngineInfo* _pSEI)
292 if (_pSEI->pstParseFile)
294 // Only for parsing test, won't execute anything.
295 return batchMain(_pSEI);
299 //always run as interactiveMain even after -e or -f option
300 return interactiveMain(_pSEI);
304 int ExecExternalCommand(ScilabEngineInfo* _pSEI)
308 processCommand(_pSEI);
309 return ConfigVariable::getExitStatus();
315 void StopScilabEngine(ScilabEngineInfo* _pSEI)
317 ConfigVariable::setEndProcessing(true);
320 /* Create a Mutex (closing scilab)
321 * used by files association
323 createMutexClosingScilab();
326 clearScilabPreferences();
328 //close "protection" scope
329 symbol::Context::getInstance()->scope_end();
331 //execute scilab.quit
334 //-f option execute exec('%s',-1)
335 char *pstCommand = (char *)MALLOC(sizeof(char) * (strlen("exec(\"\",-1)") + strlen(_pSEI->pstFile) + 1));
336 sprintf(pstCommand, "exec(\"%s\",-1)", _pSEI->pstFile);
338 _pSEI->pstExec = pstCommand;
339 processCommand(_pSEI);
342 else if (_pSEI->iNoStart == 0)
344 execScilabQuitTask(_pSEI->iSerialize != 0);
345 //call all modules.quit
350 symbol::Context::getInstance()->clearAll();
352 symbol::Context::destroyInstance();
355 //uncomment to print mem leak log
356 //types::Inspector::displayMemleak();
359 // cleanup Java dependent features
360 saveCWDInPreferences();
361 clearScilabPreferences();
362 TerminateHistoryManager();
365 if (_pSEI->iNoJvm == 0)
367 //dynamic_TerminateTclTk();
371 /* TerminateCorePart2 */
374 FileManager::destroy();
376 /* Remove TMPDIR before exit */
379 //Unload dynamic modules
382 //destroy function manager
383 destroyfunctionManagerInstance();
384 /* TerminateCorePart2 end */
387 * Cleanup function for the XML library.
391 /* Cleanup the parser state */
395 TerminateWindows_tools();
398 /* Reset terminal configuration */
399 if (_pSEI->iConsoleMode)
402 initConsoleMode(ATTR_RESET);
407 /* close mutex (closing scilab)
408 * used by files association
410 terminateMutexClosingScilab();
412 ConfigVariable::setEndProcessing(false);
415 static Parser::ControlStatus processCommand(ScilabEngineInfo* _pSEI)
417 Parser *parser = new Parser();
419 parser->setParseTrace(_pSEI->iParseTrace != 0);
420 if (strcmp(_pSEI->pstExec, "") != 0)
422 wchar_t *pwstCommand = to_wide_string(_pSEI->pstExec);
427 parseCommandTask(parser, _pSEI->iTimed != 0, pwstCommand);
430 ** -*- DUMPING TREE -*-
434 dumpAstTask(parser->getTree(), _pSEI->iTimed != 0);
437 if (parser->getExitStatus() == Parser::Succeded)
440 ** -*- PRETTY PRINT TREE -*-
442 if (_pSEI->iPrintAst)
444 printAstTask(parser->getTree(), _pSEI->iTimed != 0);
448 ** -*- EXECUTING TREE -*-
452 //before calling YaspReader, try to call %onprompt function
454 execAstTask(parser->getTree(), _pSEI->iSerialize != 0, _pSEI->iTimed != 0, _pSEI->iAstTimed != 0, _pSEI->iExecVerbose != 0);
458 ** -*- DUMPING STACK AFTER EXECUTION -*-
460 if (_pSEI->iDumpStack)
462 dumpStackTask(_pSEI->iTimed != 0);
465 else if (parser->getExitStatus() == Parser::Failed && parser->getControlStatus() == Parser::AllControlClosed)
469 //before calling YaspReader, try to call %onprompt function
473 scilabWriteW(parser->getErrorMessage());
482 //before calling YaspReader, try to call %onprompt function
487 Parser::ControlStatus ret = parser->getControlStatus();
493 ** -*- Interactive Main -*-
495 static int interactiveMain(ScilabEngineInfo* _pSEI)
498 char *command = NULL;
500 Parser::ControlStatus controlStatus = Parser::AllControlClosed;
504 if (getScilabMode() != SCILAB_NWNI)
506 fprintf(stderr, "Scilab was compiled without its GUI and advanced features. Run scilab-cli or us the -nwni option.\n");
507 initConsoleMode(ATTR_RESET);
513 InitializeHistoryManager();
515 //before calling reader, try to call %onprompt function
518 while (!ConfigVariable::getForceQuit())
520 // Show Parser Sate before prompt
521 stateShow(controlStatus);
523 pause = ConfigVariable::getPauseLevel();
526 C2F(setprlev) (&pause);
528 if (controlStatus == Parser::AllControlClosed)
536 if (ConfigVariable::isEmptyLineShow())
541 command = scilabRead();
545 char *pstRead = scilabRead();
547 //+1 for null termination and +1 for '\n'
548 size_t iLen = strlen(command) + strlen(pstRead) + 2;
549 char *pstNewCommand = (char *)MALLOC(iLen * sizeof(char));
552 sprintf_s(pstNewCommand, iLen, "%s\n%s", command, pstRead);
554 sprintf(pstNewCommand, "%s\n%s", command, pstRead);
558 command = pstNewCommand;
561 _pSEI->pstExec = command;
562 controlStatus = processCommand(_pSEI);
563 _pSEI->pstExec = NULL;
566 std::cerr << "To end program press [ENTER]" << std::endl;
570 return ConfigVariable::getExitStatus();
574 ** -*- Batch Main -*-
576 static int batchMain(ScilabEngineInfo* _pSEI)
581 Parser *parser = new Parser();
583 parser->setParseTrace(_pSEI->iParseTrace != 0);
585 wchar_t *pwstFileName = to_wide_string(_pSEI->pstParseFile);
590 parseFileTask(parser, _pSEI->iTimed != 0, pwstFileName, L"YaSp");
593 ** -*- DUMPING TREE -*-
597 dumpAstTask(parser->getTree(), _pSEI->iTimed != 0);
600 if (parser->getExitStatus() == Parser::Succeded)
603 ** -*- PRETTY PRINT TREE -*-
605 if (_pSEI->iPrintAst)
607 printAstTask(parser->getTree(), _pSEI->iTimed != 0);
613 scilabWriteW(parser->getErrorMessage());
617 std::cerr << "To end program press [ENTER]" << std::endl;
619 return parser->getExitStatus();
624 ** Used to show parser state.
625 ** Find if we are stuck within some control structure.
627 static void stateShow(Parser::ControlStatus status)
631 case Parser::WithinFor:
632 SetTemporaryPrompt("-for ->");
634 case Parser::WithinWhile:
635 SetTemporaryPrompt("-while ->");
637 case Parser::WithinIf:
638 SetTemporaryPrompt("-if ->");
640 case Parser::WithinElse:
641 SetTemporaryPrompt("-else ->");
643 case Parser::WithinElseIf:
644 SetTemporaryPrompt("-elseif ->");
646 case Parser::WithinTry:
647 SetTemporaryPrompt("-try ->");
649 case Parser::WithinCatch:
650 SetTemporaryPrompt("-catch ->");
652 case Parser::WithinFunction:
653 SetTemporaryPrompt("-function ->");
655 case Parser::WithinSelect:
656 SetTemporaryPrompt("-select ->");
658 case Parser::WithinCase:
659 SetTemporaryPrompt("-case ->");
661 case Parser::WithinSwitch:
662 SetTemporaryPrompt("-switch ->");
664 case Parser::WithinOtherwise:
665 SetTemporaryPrompt("-otherwise ->");
667 case Parser::WithinMatrix:
668 SetTemporaryPrompt("- [ ->");
670 case Parser::WithinCell:
671 SetTemporaryPrompt("- { ->");
673 case Parser::WithinBlockComment:
674 SetTemporaryPrompt("- /* ->");
676 case Parser::WithinDots:
677 SetTemporaryPrompt("- ... ->");
679 case Parser::AllControlClosed:
680 //ClearTemporaryPrompt();
685 static int InitializeEnvironnement(void)
687 SetScilabEnvironment();
688 InitializeLocalization();
690 ConfigVariable::setConsoleWidth(75);
691 ConfigVariable::setFormatSize(10);
692 ConfigVariable::setFormatMode(1);
694 FileManager::initialize();
695 initOperationArray();
700 * Private function to check any linker errors
703 static void checkForLinkerErrors(void)
707 Depending on the linking order, sometime, libs are not loaded the right way.
708 This can cause painful debugging tasks for packager or developer, we are
709 doing the check to help them.
711 #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"
712 #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"
714 if (getScilabMode() != SCILAB_NWNI)
716 if (isItTheDisabledLib())
718 fprintf(stderr, LINKER_ERROR_1);
719 fprintf(stderr, "Here, Scilab should have 'libscijvm' defined but gets 'libscijvm-disable' instead.\n");
720 fprintf(stderr, LINKER_ERROR_2);
728 if (!isItTheDisabledLib())
730 fprintf(stderr, LINKER_ERROR_1);
731 fprintf(stderr, "Here, Scilab should have 'libscijvm-disable' defined but gets 'libscijvm' instead.\n");
732 fprintf(stderr, LINKER_ERROR_2);
736 #undef LINKER_ERROR_1
737 #undef LINKER_ERROR_2
741 static void Add_All_Variables(void)
756 static void Add_Nan(void)
759 double dbl0 = fabs(dbl1 - dbl1);
761 Add_Double_Constant(L"%nan", dbl0 / dbl0, 0, false);
764 static void Add_Inf(void)
767 double dbl0 = dbl1 - dbl1;
769 Add_Double_Constant(L"%inf", dbl1 / dbl0, 0, false);
772 static void Add_gui(void)
774 Add_Boolean_Constant(L"%gui", false);
777 static void Add_fftw(void)
779 Add_Boolean_Constant(L"%fftw", withfftw() == 1);
782 static void Add_pi(void)
784 Add_Double_Constant(L"%pi", 3.1415926535897931159980, 0, false);
787 static void Add_eps(void)
789 Add_Double_Constant(L"%eps", C2F(dlamch) ("p", 1L), 0, false);
792 static void Add_e(void)
794 Add_Double_Constant(L"%e", 2.71828182845904530, 0, false);
797 static void Add_i(void)
799 Add_Double_Constant(L"%i", 0, 1, true);
802 static void Add_s(void)
804 Double dblCoef(1, 2);
806 dblCoef.set(0, 0, 0);
807 dblCoef.set(0, 1, 1);
809 Add_Poly_Constant(L"%s", L"s", 1, &dblCoef);
812 static void Add_z(void)
814 Double dblCoef(1, 2);
816 dblCoef.set(0, 0, 0);
817 dblCoef.set(0, 1, 1);
819 Add_Poly_Constant(L"%z", L"z", 1, &dblCoef);
822 static void Add_io(void)
824 types::Double * pVal = new types::Double(1, 2);
827 symbol::Context::getInstance()->put(symbol::Symbol(L"%io"), pVal);
830 static void Add_Poly_Constant(wstring _szName, wstring _szPolyVar, int _iRank, Double * _pdbl)
832 types::Polynom * pVar = new types::Polynom(_szPolyVar, 1, 1, &_iRank);
833 SinglePoly *poPoly = pVar->get(0);
835 poPoly->setCoef(_pdbl);
836 symbol::Context::getInstance()->put(symbol::Symbol(_szName), pVar);
839 static void Add_Double_Constant(wstring _szName, double _dblReal, double _dblImg, bool _bComplex)
841 types::Double * pVal = new types::Double(1, 1, _bComplex);
842 pVal->set(0, 0, _dblReal);
843 pVal->setImg(0, 0, _dblImg);
844 symbol::Context::getInstance()->put(symbol::Symbol(_szName), pVal);
847 static void Add_Boolean_Constant(wstring _szName, bool _bBool)
849 types::Bool * pVal = new types::Bool(_bBool);
850 symbol::Context::getInstance()->put(symbol::Symbol(_szName), pVal);
853 static void Add_String_Constant(wstring _szName, const char *_pstString)
855 types::String * ps = new types::String(_pstString);
856 symbol::Context::getInstance()->put(symbol::Symbol(_szName), ps);