Refactoring of ScilabException in AST, exec, execstr.
[scilab.git] / scilab / modules / core / src / cpp / scilab.cpp
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2006-2008 - DIGITEO - Bruno JOFRET
4  *
5  *  This file must be used under the terms of the CeCILL.
6  *  This source file is licensed as described in the file COPYING, which
7  *  you should have received as part of this distribution.  The terms
8  *  are also available at
9  *  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
10  *
11  */
12
13 #pragma comment(lib,"../../bin/libintl.lib")
14
15 #include <cstdio>
16 #include <iostream>
17 #include <string.h>
18
19 extern "C"
20 {
21 #ifndef _MSC_VER
22 #include <unistd.h>
23 #endif
24
25 //#include "SetScilabEnvironment.h"
26 #include "prompt.h"
27 #include "InitializeLocalization.h"
28 #include "MALLOC.h"
29 #include "sci_path.h"
30 #include "inisci-c.h"
31 #include "sci_mode.h"
32 #ifdef _MSC_VER
33 #include "../src/c/scilab_windows/getScilabDirectory.h"
34 #endif
35 #include "ConsoleRead.h"
36 #include "../../../console/includes/InitializeConsole.h"
37 #include "../../../jvm/includes/InitializeJVM.h"
38 #include "InitializeCore.h"
39 #include "../../../shell/includes/InitializeShell.h"
40 #include "../../../console/includes/InitializeConsole.h"
41 #include "../../../tclsci/includes/InitializeTclTk.h"
42 #include "../../../localization/includes/InitializeLocalization.h"
43 #include "../../../graphics/includes/graphicModuleLoad.h"
44 #include "../../../jvm/includes/InitializeJVM.h"
45 #ifdef _MSC_VER
46 #include "../../../windows_tools/includes/InitializeWindows_tools.h"
47 #endif
48 #include "../../../gui/includes/InitializeGUI.h"
49 #include "../../../string/includes/InitializeString.h"
50 #include "../../../jvm/includes/loadBackGroundClassPath.h"
51
52 #include "HistoryManager.h"
53 #include "InitializeHistoryManager.h"
54 #include "TerminateHistoryManager.h"
55 #include "getCommentDateSession.h"
56 #include "os_swprintf.h"
57 #include "os_strdup.h"
58 #include "localization.h"
59 #include "diary.h"
60 #include "PATH_MAX.h"
61 #include "sci_tmpdir.h"
62 #include "deleteafile.h"
63
64 #ifdef __APPLE__
65 #include "initMacOSXEnv.h"
66 #endif
67 /*
68 ** HACK HACK HACK
69 */
70     extern char *TermReadAndProcess(void);
71 }
72
73 #include "yaspio.hxx"
74 #include "tasks.hxx"
75 #include "exit_status.hxx"
76 #include "parser.hxx"
77 #include "context.hxx"
78 #include "configvariable.hxx"
79 #include "context.hxx"
80 #include "setenvvar.hxx"
81 #include "funcmanager.hxx"
82 #include "configvariable.hxx"
83 #include "filemanager.hxx"
84 #include "scilabexception.hxx"
85
86 #include "runner.hxx"
87
88 #include "banner.hxx"
89
90 #include "string.hxx"
91 #include "polynom.hxx"
92
93 #define INTERACTIVE     -1
94
95 const wchar_t* prog_name;
96 const wchar_t* file_name;
97
98 bool parseTrace = false;
99 bool printAst = false;
100 bool execAst = true;
101 bool dumpAst = false;
102 bool dumpStack = false;
103 bool timed = false;
104 bool ASTtimed = false;
105 bool consoleMode = false;
106 bool noJvm = false;
107 bool noStart = false;
108 bool noBanner = false;
109 bool execCommand = false;
110 bool execFile = false;
111
112 using symbol::Context;
113 using std::string;
114
115 void Add_i(void);
116 void Add_pi(void);
117 void Add_s(void);
118 void Add_z(void);
119 void Add_true(void);
120 void Add_false(void);
121 void Add_Nan(void);
122 void Add_Inf(void);
123 void Add_WITH_DEMOS(void); //temporary variable
124 void Add_All_Variables(void);
125
126 void Add_Double_Constant(wstring _szName, double _dblReal, double _dblImg, bool _bComplex);
127 void Add_Poly_Constant(wstring _szName, wstring _szPolyVar, int _iRank, Double *_pdblReal);
128 void Add_Boolean_Constant(wstring _szName, bool _bBool);
129 void Add_String_Constant(wstring _szName, const char* _pstString);
130
131 int InitializeEnvironnement(void);
132 bool execScilabStart(void);
133
134 int StartScilabEngine(int argc, char*argv[], int iFileIndex);
135 static Parser::ControlStatus processCommand(char* _pstCommand);
136
137 /*
138 ** Usage
139 **
140 ** Display usage : options available in YaSp
141 */
142 static void usage (void)
143 {
144     std::cerr << "Usage: "<< prog_name << " <options>" << std::endl;
145     std::cerr << "      -f file          : Batch mode on the given file." << std::endl;
146     std::cerr << "      -l lang          : Change the language of scilab ( default : en_US )." << std::endl;
147     std::cerr << "      -nw              : Enable console mode." << std::endl;
148     std::cerr << "      -nwni            : Enable terminal mode." << std::endl;
149     std::cerr << "      -ns              : Don't execute etc/scilab.start." << std::endl;
150     std::cerr << "      --help           : Display this help." << std::endl;
151     std::cerr << "Developer Trace arguments:" << std::endl;
152     std::cerr << "      --parse-trace    : Display bison state machine evolution." << std::endl;
153     std::cerr << "      --AST-trace      : Display ASCII-art AST to be human readable." << std::endl;
154     std::cerr << "      --pretty-print   : Display pretty-printed code, standard Scilab syntax." << std::endl;
155     std::cerr << " " << std::endl;
156     std::cerr << "Developer Timer arguments:" << std::endl;
157     std::cerr << "      --AST-timed      : Time each AST node." << std::endl;
158     std::cerr << "      --timed          : Time global execution." << std::endl;
159     std::cerr << " " << std::endl;
160     std::cerr << "Developer Debug arguments:" << std::endl;
161     std::cerr << "      --no-exec        : Only do Lexing/parsing do not execute instructions." << std::endl;
162     std::cerr << "      --context-dump   : Display context status." << std::endl;
163 }
164
165
166 /*
167 ** Get Options
168 **
169 **
170 */
171 static int get_option (const int argc, char *argv[], int *_piFileIndex, int *_piLangIndex)
172 {
173     int i = 0;
174
175 #ifdef DEBUG
176     std::cerr << "-*- Getting Options -*-"<< std::endl;
177 #endif
178
179     for (i = 1; i < argc; ++i) {
180         if (!strcmp("--parse-trace", argv[i])) {
181             parseTrace = true;
182         }
183         else if (!strcmp("--pretty-print", argv[i])) {
184             printAst = true;
185         }
186         else if (!strcmp("--help", argv[i])) {
187             usage ();
188             exit (WELL_DONE);
189         }
190         else if (!strcmp("--AST-trace", argv[i])) {
191             dumpAst = true;
192         }
193         else if (!strcmp("--no-exec", argv[i])) {
194             execAst = false;
195         }
196         else if (!strcmp("--context-dump", argv[i])) {
197             dumpStack = true;
198         }
199         else if (!strcmp("--timed", argv[i])) {
200             timed = true;
201         }
202         else if (!strcmp("--AST-timed", argv[i])) {
203             std::cout << "Timed execution" << std::endl;
204             ASTtimed = true;
205         }
206         else if (!strcmp("-f", argv[i])) {
207             i++;
208             execFile = true;
209             *_piFileIndex = i;
210         }
211         else if (!strcmp("-e", argv[i])) {
212             i++;
213             execCommand = true;
214             *_piFileIndex = i;
215         }
216         else if (!strcmp("-l", argv[i])) {
217             i++;
218             *_piLangIndex = i;
219         }
220         else if (!strcmp("-nw", argv[i])) {
221             consoleMode = true;
222             setScilabMode(SCILAB_NW);
223         }
224         else if (!strcmp("-nwni", argv[i])) {
225             consoleMode = true;
226             noJvm = true;
227             setScilabMode(SCILAB_NWNI);
228         }
229         else if (!strcmp("-ns", argv[i])) {
230             noStart = true;
231         }
232         else if (!strcmp("-nb", argv[i])) {
233             noBanner = true;
234         }
235     }
236
237 #ifdef DEBUG
238     std::cerr << "File : " << argv[good] << std::endl;
239 #endif
240
241     return 0;
242 }
243
244 /*
245 ** HACK HACK HACK
246 */
247
248 extern "C"
249 {
250 #include <stdio.h>
251
252 #ifndef _MSC_VER
253 #include <unistd.h>
254 #endif
255     extern char *TermReadAndProcess(void);
256     extern void ConsolePrintf(char*);
257 }
258
259 /*
260 ** -*- stateView
261 ** Used to show parser state.
262 ** Find if we are stuck within some control structure.
263 */
264
265 static void stateShow(Parser::ControlStatus status)
266 {
267     switch (status)
268     {
269     case Parser::WithinFor :            SetTemporaryPrompt("-for       ->"); break;
270     case Parser::WithinWhile :          SetTemporaryPrompt("-while     ->"); break;
271     case Parser::WithinIf :             SetTemporaryPrompt("-if        ->"); break;
272     case Parser::WithinElse :           SetTemporaryPrompt("-else      ->"); break;
273     case Parser::WithinElseIf :         SetTemporaryPrompt("-elseif    ->"); break;
274     case Parser::WithinTry :            SetTemporaryPrompt("-try       ->"); break;
275     case Parser::WithinCatch :          SetTemporaryPrompt("-catch     ->"); break;
276     case Parser::WithinFunction :       SetTemporaryPrompt("-function  ->"); break;
277     case Parser::WithinSelect :         SetTemporaryPrompt("-select    ->"); break;
278     case Parser::WithinCase :           SetTemporaryPrompt("-case      ->"); break;
279     case Parser::WithinSwitch :         SetTemporaryPrompt("-switch    ->"); break;
280     case Parser::WithinOtherwise :      SetTemporaryPrompt("-otherwise ->"); break;
281     case Parser::WithinMatrix :         SetTemporaryPrompt("- [        ->"); break;
282     case Parser::WithinCell :           SetTemporaryPrompt("- {        ->"); break;
283     case Parser::WithinBlockComment :   SetTemporaryPrompt("- /*       ->"); break;
284     case Parser::WithinDots :           SetTemporaryPrompt("- ...      ->"); break;
285     case Parser::AllControlClosed :     break;
286     }
287 }
288
289 /*
290 ** -*- Interactive Main -*-
291 */
292 static int interactiveMain (void)
293 {
294     int pause = 0;
295     char *command = NULL;
296     Parser::ControlStatus controlStatus = Parser::AllControlClosed;
297
298     if(noBanner == false)
299     {
300         banner();
301     }
302
303     InitializeHistoryManager();
304     /* add date & time @ begin session */
305     char *commentbeginsession = getCommentDateSession();
306     if (commentbeginsession)
307     {
308         appendLineToScilabHistory(commentbeginsession);
309         FREE(commentbeginsession);
310         commentbeginsession=NULL;
311     }
312
313     //before calling reader, try to call %onprompt function
314     callOnPrompt();
315
316     while (!ConfigVariable::getForceQuit())
317     {
318         // Show Parser Sate before prompt
319         stateShow(controlStatus);
320
321         pause = ConfigVariable::getPauseLevel();
322
323         //set prompt value
324         C2F(setprlev)(&pause);
325
326         if (controlStatus == Parser::AllControlClosed)
327         {
328             if(command)
329             {
330                 FREE(command);
331                 command = NULL;
332             }
333             //before calling YaspReader, try to call %onprompt function
334             callOnPrompt();
335
336             command = YaspRead();
337         }
338         else
339         {
340             char* pstRead = YaspRead();
341             //+1 for null termination and +1 for '\n'
342             size_t iLen = strlen(command) + strlen(pstRead) + 2;
343             char* pstNewCommand = (char*)MALLOC(iLen * sizeof(char));
344 #ifdef _MSC_VER
345             sprintf_s(pstNewCommand, iLen, "%s\n%s", command, pstRead);
346 #else
347             sprintf(pstNewCommand, "%s\n%s", command, pstRead);
348 #endif
349             FREE(pstRead);
350             FREE(command);
351             command = pstNewCommand;
352         }
353
354         controlStatus = processCommand(command);
355     }
356 #ifdef DEBUG
357     std::cerr << "To end program press [ENTER]" << std::endl;
358 #endif
359     return ConfigVariable::getExitStatus();
360 }
361
362 static Parser::ControlStatus processCommand(char* _pstCommand)
363 {
364     Parser *parser = new Parser();
365     parser->setParseTrace(parseTrace);
366     if (strcmp(_pstCommand, "") != 0)
367     {
368         wchar_t* pwstCommand = to_wide_string(_pstCommand);
369         /*
370         ** -*- PARSING -*-
371         */
372         parseCommandTask(parser, timed, pwstCommand);
373
374         /*
375         ** -*- DUMPING TREE -*-
376         */
377         if(dumpAst == true)
378         {
379             dumpAstTask(parser->getTree(), timed);
380         }
381
382         if(parser->getExitStatus() == Parser::Succeded)
383         {
384             /*
385             ** -*- PRETTY PRINT TREE -*-
386             */
387             if(printAst == true)
388             {
389                 printAstTask(parser->getTree(), timed);
390             }
391
392             /*
393             ** -*- EXECUTING TREE -*-
394             */
395             if(execAst == true)
396             {
397                 execAstTask(parser->getTree(), timed, ASTtimed);
398             }
399
400             /*
401             ** -*- DUMPING STACK AFTER EXECUTION -*-
402             */
403             if(dumpStack == true)
404             {
405                 dumpStackTask(timed);
406             }
407         }
408         else if(parser->getExitStatus() == Parser::Failed && parser->getControlStatus() == Parser::AllControlClosed)
409         {
410             YaspWriteW(parser->getErrorMessage());
411         }
412
413         FREE(pwstCommand);
414     }
415     return parser->getControlStatus();
416 }
417
418 static void TermPrintf(char *text)
419 {
420     //std::cout << text;
421     printf("%s", text);
422 }
423
424 /*
425 ** -*- MAIN -*-
426 */
427 int main(int argc, char *argv[])
428 {
429     int iFileIndex = INTERACTIVE;
430     int iLangIndex = 0;
431
432     prog_name = to_wide_string(argv[0]);
433
434     setScilabMode(SCILAB_STD);
435     get_option(argc, argv, &iFileIndex, &iLangIndex);
436
437 // if WITHOUT_GUI is defined
438 // force Terminal IO -> Terminal IO + StartScilabEngine
439
440 // WITHOUT_GUI (All Platform) => Terminal IO + StartScilabEngine
441 // GUI (MacOSX) =>      [no option]     -> Console IO + InitMacOSXEnv
442 //                      | [-nwni]       -> Terminal IO + StartScilabEngine
443 //                      | [-nw]         -> Terminal IO + InitMacOSXEnv
444 #ifndef WITHOUT_GUI
445     if (consoleMode)
446     {
447         setYaspInputMethod(&TermReadAndProcess);
448         setYaspOutputMethod(&TermPrintf);
449   #if defined(__APPLE__)
450         if(!noJvm)
451         {
452             return initMacOSXEnv(argc, argv, iFileIndex);
453         }
454   #endif // !defined(__APPLE__)
455         return StartScilabEngine(argc, argv, iFileIndex);
456     }
457     else
458     {
459         setYaspInputMethod(&ConsoleRead);
460         setYaspOutputMethod(&ConsolePrintf);
461   #if defined(__APPLE__)
462         return initMacOSXEnv(argc, argv, iFileIndex);
463   #else
464         return StartScilabEngine(argc, argv, iFileIndex);
465   #endif // !defined(__APPLE__)
466     }
467 #else
468         setYaspInputMethod(&TermReadAndProcess);
469         setYaspOutputMethod(&TermPrintf);
470         return StartScilabEngine(argc, argv, iFileIndex);
471 #endif // defined(WITHOUT_GUI)
472 }
473
474 int StartScilabEngine(int argc, char*argv[], int iFileIndex)
475 {
476     int iMainRet = 0;
477     Runner::init();
478     
479     /* Scilab Startup */
480     InitializeEnvironnement();
481
482     InitializeString();
483
484 #ifdef _MSC_VER
485     InitializeWindows_tools();
486 #endif
487
488     //InitializeCore();
489
490     InitializeShell();
491
492     if (!noJvm)
493     {
494         /* bug 3702 */
495         /* tclsci creates a TK window on Windows */
496         /* it changes focus on previous windows */
497         /* we put InitializeTclTk before InitializeGUI */
498
499         //InitializeTclTk();
500         InitializeJVM();
501         InitializeGUI();
502
503         /* create needed data structure if not already created */
504         loadGraphicModule() ;
505
506         /* Standard mode -> init Java Console */
507         if ( !consoleMode )
508         {
509             /* Initialize console: lines... */
510             InitializeConsole();
511         }
512
513         loadBackGroundClassPath();
514     }
515
516     /* set current language of scilab */
517     FuncManager *pFM = new FuncManager();
518     pFM->LoadModules(noStart);
519
520     //execute scilab.start
521     if(noStart == false)
522     {
523         execScilabStartTask();
524     }
525
526     int pause = 0;
527     //set prompt value
528     C2F(setprlev)(&pause);
529
530     try
531     {
532         if(execCommand)
533         {//-e option
534             processCommand(argv[iFileIndex]);
535         }
536         else if(execFile)
537         {//-f option execute exec('%s',-1)
538             char* pstCommand = (char*)MALLOC(sizeof(char) * (strlen("exec(\"\",-1)") + strlen(argv[iFileIndex]) + 1));
539             sprintf(pstCommand, "exec(\"%s\",-1)", argv[iFileIndex]);
540             processCommand(pstCommand);
541             FREE(pstCommand);
542         }
543     }
544     catch(ScilabException se)
545     {
546         YaspErrorW(se.GetErrorMessage().c_str());
547     }
548
549     ConfigVariable::setPromptMode(2);
550
551     //always run as interactiveMain even after -e or -f option
552     file_name = L"prompt";
553     iMainRet = interactiveMain();
554
555     //close main scope
556     symbol::Context::getInstance()->scope_end();
557     delete pFM;
558     return iMainRet;
559 }
560
561 int InitializeEnvironnement(void)
562 {
563     SetScilabEnvironment();
564     InitializeLocalization();
565
566     ConfigVariable::setConsoleWidth(75);
567     ConfigVariable::setFormat(16);
568     Add_All_Variables();
569     FileManager::initialize();
570     return 0;
571 }
572
573 void Add_All_Variables(void)
574 {
575     Add_pi();
576     Add_i();
577     Add_s();
578     Add_z();
579     Add_true();
580     Add_false();
581     Add_Nan();
582     Add_Inf();
583     Add_WITH_DEMOS();
584 }
585
586 void Add_WITH_DEMOS(void)
587 {
588     Add_Boolean_Constant(L"WITH_DEMOS", false);
589 }
590
591 void Add_Nan(void)
592 {
593     double dbl1 = 1.0;
594     double dbl0 = dbl1 - dbl1;
595     Add_Double_Constant(L"%nan", dbl0/dbl0, 0, false);
596 }
597
598 void Add_Inf(void)
599 {
600     double dbl1 = 1.0;
601     double dbl0 = dbl1 - dbl1;
602     Add_Double_Constant(L"%inf", dbl1/dbl0, 0, false);
603 }
604
605 void Add_false(void)
606 {
607     Add_Boolean_Constant(L"%f", false);
608 }
609
610 void Add_true(void)
611 {
612     Add_Boolean_Constant(L"%t", true);
613 }
614
615 void Add_pi(void)
616 {
617     Add_Double_Constant(L"%pi", 3.1415926535897931159980, 0, false);
618 }
619
620 void Add_i(void)
621 {
622     Add_Double_Constant(L"%i", 0, 1, true);
623 }
624
625 void Add_s(void)
626 {
627     Double dblCoef(1,2);
628     dblCoef.set(0, 0, 0);
629     dblCoef.set(0, 1, 1);
630
631     Add_Poly_Constant(L"%s",L"s", 2, &dblCoef);
632 }
633
634 void Add_z(void)
635 {
636     Double dblCoef(1,2);
637     dblCoef.set(0, 0, 0);
638     dblCoef.set(0, 1, 1);
639
640     Add_Poly_Constant(L"%z",L"z", 2, &dblCoef);
641 }
642
643 void Add_Poly_Constant(wstring _szName, wstring _szPolyVar, int _iRank, Double *_pdbl)
644 {
645     types::Polynom *pVar = new types::Polynom(_szPolyVar, 1, 1, &_iRank);
646     SinglePoly *poPoly = pVar->get(0,0);
647     poPoly->setCoef(_pdbl);
648     Context::getInstance()->put(symbol::Symbol(_szName), *pVar);
649 }
650
651 void Add_Double_Constant(wstring _szName, double _dblReal, double _dblImg, bool _bComplex)
652 {
653     types::Double* pVal = new types::Double(1,1,_bComplex);
654     pVal->set(0, 0, _dblReal);
655     pVal->setImg(0, 0, _dblImg);
656     symbol::Context::getInstance()->put(symbol::Symbol(_szName), *pVal);
657 }
658
659 void Add_Boolean_Constant(wstring _szName, bool _bBool)
660 {
661     types::Bool* pVal = new types::Bool(_bBool);
662     symbol::Context::getInstance()->put(symbol::Symbol(_szName), *pVal);
663 }
664
665 void Add_String_Constant(wstring _szName, const char* _pstString)
666 {
667     types::String* ps = new types::String(_pstString);
668     symbol::Context::getInstance()->put(symbol::Symbol(_szName), *ps);
669 }
670