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>
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"
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"
61 #include "InitializeWindows_tools.h"
62 #include "TerminateWindows_tools.h"
63 #include "WndThread.h"
65 #include "InnosetupMutex.h"
66 #include "MutexClosingScilab.h"
67 #include "WinConsole.h"
69 #include "signal_mgmt.h"
70 #include "initConsoleMode.h"
73 #if defined(linux) && defined(__i386__)
74 #include "setPrecisionFPU.h"
77 /* Defined without include to avoid useless header dependency */
78 extern BOOL isItTheDisabledLib(void);
81 static void Add_i(void);
82 static void Add_pi(void);
83 static void Add_eps(void);
84 static void Add_e(void);
85 static void Add_s(void);
86 static void Add_z(void);
87 static void Add_true(void);
88 static void Add_false(void);
89 static void Add_Nan(void);
90 static void Add_Inf(void);
91 static void Add_All_Variables(void);
92 static void Add_Double_Constant(std::wstring _szName, double _dblReal, double _dblImg, bool _bComplex);
93 static void Add_Poly_Constant(std::wstring _szName, std::wstring _szPolyVar, int _iRank, types::Double * _pdblReal);
94 static void Add_Boolean_Constant(std::wstring _szName, bool _bBool);
95 static void Add_String_Constant(std::wstring _szName, const char *_pstString);
96 static void checkForLinkerErrors(void);
98 static int batchMain(ScilabEngineInfo* _pSEI);
99 static int InitializeEnvironnement(void);
100 static int interactiveMain(ScilabEngineInfo* _pSEI);
101 static Parser::ControlStatus processCommand(ScilabEngineInfo* _pSEI);
102 static void stateShow(Parser::ControlStatus status);
106 ScilabEngineInfo* InitScilabEngineInfo()
108 // Disable all startup flags.
109 ScilabEngineInfo* pSEI = (ScilabEngineInfo*)CALLOC(1, sizeof(ScilabEngineInfo));
111 //Active default flags
118 int StartScilabEngine(ScilabEngineInfo* _pSEI)
122 /* This bug only occurs under Linux 32 bits
123 * See: http://wiki.scilab.org/Scilab_precision
125 #if defined(linux) && defined(__i386__)
130 /* Management of the signals (seg fault, floating point exception, etc) */
131 if (getenv("SCI_DISABLE_EXCEPTION_CATCHING") == NULL)
137 #if defined(netbsd) || defined(freebsd)
138 /* floating point exceptions */
144 checkForLinkerErrors();
147 //get current console window and hide it
148 int scilabMode = getScilabMode();
149 if (scilabMode == SCILAB_STD)
151 CreateScilabHiddenWndThread();
152 //show banner in console window
153 CreateScilabConsole(_pSEI->iNoBanner);
155 if (_pSEI->iKeepConsole == 0)
157 HideScilex(); /* hide console window */
166 if (scilabMode == SCILAB_NW || scilabMode == SCILAB_NWNI)
169 if (scilabMode == SCILAB_NW)
172 UpdateConsoleColors();
177 //create a thread for innosetup to allow reinstall during scilab running
178 createInnosetupMutex();
181 InitializeLaunchScilabSignal();
185 InitializeEnvironnement();
189 wchar_t *pwstLang = to_wide_string(_pSEI->pstLang);
190 setlanguage(pwstLang);
195 InitializeWindows_tools();
198 if (_pSEI->iNoJvm == 0) // With JVM
201 /* tclsci creates a TK window on Windows */
202 /* it changes focus on previous windows */
203 /* we put InitializeTclTk before InitializeGUI */
209 /* create needed data structure if not already created */
212 loadBackGroundClassPath();
215 /* Standard mode -> init Java Console */
216 if (_pSEI->iConsoleMode == 0)
218 /* Initialize console: lines... */
224 initConsoleMode(RAW);
228 //open "protection" scope to protect all variables after scilab start
229 symbol::Context::getInstance()->scope_begin();
233 //execute scilab.start
234 if (_pSEI->iNoStart == 0)
237 execScilabStartTask(_pSEI->iSerialize != 0);
243 C2F(setprlev) (&pause);
245 ConfigVariable::setPromptMode(0);
252 processCommand(_pSEI);
253 iMainRet = ConfigVariable::getExitStatus();
255 else if (_pSEI->pstFile)
257 //-f option execute exec('%s',-1)
258 char *pstCommand = (char *)MALLOC(sizeof(char) * (strlen("exec(\"\",-1)") + strlen(_pSEI->pstFile) + 1));
259 sprintf(pstCommand, "exec(\"%s\",-1)", _pSEI->pstFile);
261 _pSEI->pstExec = pstCommand;
262 processCommand(_pSEI);
264 iMainRet = ConfigVariable::getExitStatus();
265 _pSEI->pstExec = NULL;
266 _pSEI->pstFile = NULL;
269 catch (const ast::ScilabException& se)
271 scilabErrorW(se.GetErrorMessage().c_str());
274 ConfigVariable::setStartFinished(true);
275 ConfigVariable::setPromptMode(2);
279 int RunScilabEngine(ScilabEngineInfo* _pSEI)
281 if (_pSEI->pstParseFile)
283 // Only for parsing test, won't execute anything.
284 return batchMain(_pSEI);
288 //always run as interactiveMain even after -e or -f option
289 return interactiveMain(_pSEI);
293 int ExecExternalCommand(ScilabEngineInfo* _pSEI)
297 processCommand(_pSEI);
298 return ConfigVariable::getExitStatus();
304 void StopScilabEngine(ScilabEngineInfo* _pSEI)
308 /* Create a Mutex (closing scilab)
309 * used by files association
311 createMutexClosingScilab();
314 clearScilabPreferences();
316 //execute scilab.quit
319 //-f option execute exec('%s',-1)
320 char *pstCommand = (char *)MALLOC(sizeof(char) * (strlen("exec(\"\",-1)") + strlen(_pSEI->pstFile) + 1));
321 sprintf(pstCommand, "exec(\"%s\",-1)", _pSEI->pstFile);
323 _pSEI->pstExec = pstCommand;
324 processCommand(_pSEI);
327 else if (_pSEI->iNoStart == 0)
329 execScilabQuitTask(_pSEI->iSerialize != 0);
330 //call all modules.quit
334 //close "protection" scope
335 symbol::Context::getInstance()->scope_end();
338 symbol::Context::getInstance()->clearAll();
340 symbol::Context::destroyInstance();
343 saveCWDInPreferences();
344 clearScilabPreferences();
346 if (_pSEI->iNoJvm == 0)
348 //dynamic_TerminateTclTk();
353 /* TerminateCorePart2 */
356 FileManager::destroy();
358 /* Remove TMPDIR before exit */
361 //Unload dynamic modules
364 //destroy function manager
365 destroyfunctionManagerInstance();
366 /* TerminateCorePart2 end */
369 * History manager cleanup
371 TerminateHistoryManager();
374 * Cleanup function for the XML library.
378 /* Cleanup the parser state */
382 TerminateWindows_tools();
385 /* Reset terminal configuration */
386 if (_pSEI->iConsoleMode)
389 initConsoleMode(ATTR_RESET);
394 /* close mutex (closing scilab)
395 * used by files association
397 terminateMutexClosingScilab();
401 static Parser::ControlStatus processCommand(ScilabEngineInfo* _pSEI)
403 Parser *parser = new Parser();
405 parser->setParseTrace(_pSEI->iParseTrace != 0);
406 if (strcmp(_pSEI->pstExec, "") != 0)
408 wchar_t *pwstCommand = to_wide_string(_pSEI->pstExec);
413 parseCommandTask(parser, _pSEI->iTimed != 0, pwstCommand);
416 ** -*- DUMPING TREE -*-
420 dumpAstTask(parser->getTree(), _pSEI->iTimed != 0);
423 if (parser->getExitStatus() == Parser::Succeded)
426 ** -*- PRETTY PRINT TREE -*-
428 if (_pSEI->iPrintAst)
430 printAstTask(parser->getTree(), _pSEI->iTimed != 0);
434 ** -*- EXECUTING TREE -*-
438 //before calling YaspReader, try to call %onprompt function
440 execAstTask(parser->getTree(), _pSEI->iSerialize != 0, _pSEI->iTimed != 0, _pSEI->iAstTimed != 0, _pSEI->iExecVerbose != 0);
444 ** -*- DUMPING STACK AFTER EXECUTION -*-
446 if (_pSEI->iDumpStack)
448 dumpStackTask(_pSEI->iTimed != 0);
451 else if (parser->getExitStatus() == Parser::Failed && parser->getControlStatus() == Parser::AllControlClosed)
455 //before calling YaspReader, try to call %onprompt function
459 scilabWriteW(parser->getErrorMessage());
468 //before calling YaspReader, try to call %onprompt function
473 Parser::ControlStatus ret = parser->getControlStatus();
479 ** -*- Interactive Main -*-
481 static int interactiveMain(ScilabEngineInfo* _pSEI)
484 char *command = NULL;
486 Parser::ControlStatus controlStatus = Parser::AllControlClosed;
490 if (getScilabMode() != SCILAB_NWNI)
492 fprintf(stderr, "Scilab was compiled without its GUI and advanced features. Run scilab-cli or us the -nwni option.\n");
493 initConsoleMode(ATTR_RESET);
499 InitializeHistoryManager();
501 //before calling reader, try to call %onprompt function
504 while (!ConfigVariable::getForceQuit())
506 // Show Parser Sate before prompt
507 stateShow(controlStatus);
509 pause = ConfigVariable::getPauseLevel();
512 C2F(setprlev) (&pause);
514 if (controlStatus == Parser::AllControlClosed)
522 command = scilabRead();
526 char *pstRead = scilabRead();
528 //+1 for null termination and +1 for '\n'
529 size_t iLen = strlen(command) + strlen(pstRead) + 2;
530 char *pstNewCommand = (char *)MALLOC(iLen * sizeof(char));
533 sprintf_s(pstNewCommand, iLen, "%s\n%s", command, pstRead);
535 sprintf(pstNewCommand, "%s\n%s", command, pstRead);
539 command = pstNewCommand;
542 _pSEI->pstExec = command;
543 controlStatus = processCommand(_pSEI);
544 _pSEI->pstExec = NULL;
547 std::cerr << "To end program press [ENTER]" << std::endl;
551 return ConfigVariable::getExitStatus();
555 ** -*- Batch Main -*-
557 static int batchMain(ScilabEngineInfo* _pSEI)
562 Parser *parser = new Parser();
564 parser->setParseTrace(_pSEI->iParseTrace != 0);
566 wchar_t *pwstFileName = to_wide_string(_pSEI->pstParseFile);
571 parseFileTask(parser, _pSEI->iTimed != 0, pwstFileName, L"YaSp");
574 ** -*- DUMPING TREE -*-
578 dumpAstTask(parser->getTree(), _pSEI->iTimed != 0);
581 if (parser->getExitStatus() == Parser::Succeded)
584 ** -*- PRETTY PRINT TREE -*-
586 if (_pSEI->iPrintAst)
588 printAstTask(parser->getTree(), _pSEI->iTimed != 0);
594 scilabWriteW(parser->getErrorMessage());
598 std::cerr << "To end program press [ENTER]" << std::endl;
600 return parser->getExitStatus();
605 ** Used to show parser state.
606 ** Find if we are stuck within some control structure.
608 static void stateShow(Parser::ControlStatus status)
612 case Parser::WithinFor:
613 SetTemporaryPrompt("-for ->");
615 case Parser::WithinWhile:
616 SetTemporaryPrompt("-while ->");
618 case Parser::WithinIf:
619 SetTemporaryPrompt("-if ->");
621 case Parser::WithinElse:
622 SetTemporaryPrompt("-else ->");
624 case Parser::WithinElseIf:
625 SetTemporaryPrompt("-elseif ->");
627 case Parser::WithinTry:
628 SetTemporaryPrompt("-try ->");
630 case Parser::WithinCatch:
631 SetTemporaryPrompt("-catch ->");
633 case Parser::WithinFunction:
634 SetTemporaryPrompt("-function ->");
636 case Parser::WithinSelect:
637 SetTemporaryPrompt("-select ->");
639 case Parser::WithinCase:
640 SetTemporaryPrompt("-case ->");
642 case Parser::WithinSwitch:
643 SetTemporaryPrompt("-switch ->");
645 case Parser::WithinOtherwise:
646 SetTemporaryPrompt("-otherwise ->");
648 case Parser::WithinMatrix:
649 SetTemporaryPrompt("- [ ->");
651 case Parser::WithinCell:
652 SetTemporaryPrompt("- { ->");
654 case Parser::WithinBlockComment:
655 SetTemporaryPrompt("- /* ->");
657 case Parser::WithinDots:
658 SetTemporaryPrompt("- ... ->");
660 case Parser::AllControlClosed:
661 //ClearTemporaryPrompt();
666 static int InitializeEnvironnement(void)
668 SetScilabEnvironment();
669 InitializeLocalization();
671 ConfigVariable::setConsoleWidth(75);
672 ConfigVariable::setFormatSize(10);
673 ConfigVariable::setFormatMode(1);
675 FileManager::initialize();
676 initOperationArray();
681 * Private function to check any linker errors
684 static void checkForLinkerErrors(void)
688 Depending on the linking order, sometime, libs are not loaded the right way.
689 This can cause painful debugging tasks for packager or developer, we are
690 doing the check to help them.
692 #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"
693 #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"
695 if (getScilabMode() != SCILAB_NWNI)
697 if (isItTheDisabledLib())
699 fprintf(stderr, LINKER_ERROR_1);
700 fprintf(stderr, "Here, Scilab should have 'libscijvm' defined but gets 'libscijvm-disable' instead.\n");
701 fprintf(stderr, LINKER_ERROR_2);
709 if (!isItTheDisabledLib())
711 fprintf(stderr, LINKER_ERROR_1);
712 fprintf(stderr, "Here, Scilab should have 'libscijvm-disable' defined but gets 'libscijvm' instead.\n");
713 fprintf(stderr, LINKER_ERROR_2);
717 #undef LINKER_ERROR_1
718 #undef LINKER_ERROR_2
722 static void Add_All_Variables(void)
736 static void Add_Nan(void)
739 double dbl0 = dbl1 - dbl1;
741 Add_Double_Constant(L"%nan", dbl0 / dbl0, 0, false);
744 static void Add_Inf(void)
747 double dbl0 = dbl1 - dbl1;
749 Add_Double_Constant(L"%inf", dbl1 / dbl0, 0, false);
752 static void Add_false(void)
754 Add_Boolean_Constant(L"%f", false);
757 static void Add_true(void)
759 Add_Boolean_Constant(L"%t", true);
762 static void Add_pi(void)
764 Add_Double_Constant(L"%pi", 3.1415926535897931159980, 0, false);
767 static void Add_eps(void)
769 Add_Double_Constant(L"%eps", C2F(dlamch) ("p", 1L), 0, false);
772 static void Add_e(void)
774 Add_Double_Constant(L"%e", 2.71828182845904530, 0, false);
777 static void Add_i(void)
779 Add_Double_Constant(L"%i", 0, 1, true);
782 static void Add_s(void)
784 Double dblCoef(1, 2);
786 dblCoef.set(0, 0, 0);
787 dblCoef.set(0, 1, 1);
789 Add_Poly_Constant(L"%s", L"s", 1, &dblCoef);
792 static void Add_z(void)
794 Double dblCoef(1, 2);
796 dblCoef.set(0, 0, 0);
797 dblCoef.set(0, 1, 1);
799 Add_Poly_Constant(L"%z", L"z", 1, &dblCoef);
802 static void Add_Poly_Constant(wstring _szName, wstring _szPolyVar, int _iRank, Double * _pdbl)
804 types::Polynom * pVar = new types::Polynom(_szPolyVar, 1, 1, &_iRank);
805 SinglePoly *poPoly = pVar->get(0);
807 poPoly->setCoef(_pdbl);
808 symbol::Context::getInstance()->put(symbol::Symbol(_szName), pVar);
811 static void Add_Double_Constant(wstring _szName, double _dblReal, double _dblImg, bool _bComplex)
813 types::Double * pVal = new types::Double(1, 1, _bComplex);
814 pVal->set(0, 0, _dblReal);
815 pVal->setImg(0, 0, _dblImg);
816 symbol::Context::getInstance()->put(symbol::Symbol(_szName), pVal);
819 static void Add_Boolean_Constant(wstring _szName, bool _bBool)
821 types::Bool * pVal = new types::Bool(_bBool);
822 symbol::Context::getInstance()->put(symbol::Symbol(_szName), pVal);
825 static void Add_String_Constant(wstring _szName, const char *_pstString)
827 types::String * ps = new types::String(_pstString);
828 symbol::Context::getInstance()->put(symbol::Symbol(_szName), ps);