546d4dade062855491276ee3febb15b89f271696
[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 bool parseFile = false;
112
113 using symbol::Context;
114 using std::string;
115
116 void Add_i(void);
117 void Add_pi(void);
118 void Add_s(void);
119 void Add_z(void);
120 void Add_true(void);
121 void Add_false(void);
122 void Add_Nan(void);
123 void Add_Inf(void);
124 void Add_WITH_DEMOS(void); //temporary variable
125 void Add_All_Variables(void);
126
127 void Add_Double_Constant(wstring _szName, double _dblReal, double _dblImg, bool _bComplex);
128 void Add_Poly_Constant(wstring _szName, wstring _szPolyVar, int _iRank, Double *_pdblReal);
129 void Add_Boolean_Constant(wstring _szName, bool _bBool);
130 void Add_String_Constant(wstring _szName, const char* _pstString);
131
132 int InitializeEnvironnement(void);
133 bool execScilabStart(void);
134
135 int StartScilabEngine(int argc, char*argv[], int iFileIndex);
136 static Parser::ControlStatus processCommand(char* _pstCommand);
137
138 /*
139 ** Usage
140 **
141 ** Display usage : options available in YaSp
142 */
143 static void usage (void)
144 {
145     std::cerr << "Usage: "<< prog_name << " <options>" << std::endl;
146     std::cerr << "      -f file          : Batch mode on the given file." << std::endl;
147     std::cerr << "      -l lang          : Change the language of scilab ( default : en_US )." << std::endl;
148     std::cerr << "      -nw              : Enable console mode." << std::endl;
149     std::cerr << "      -nwni            : Enable terminal mode." << std::endl;
150     std::cerr << "      -ns              : Don't execute etc/scilab.start." << std::endl;
151     std::cerr << "      --help           : Display this help." << std::endl;
152     std::cerr << "Developer Trace arguments:" << std::endl;
153     std::cerr << "      --parse-trace    : Display bison state machine evolution." << std::endl;
154     std::cerr << "      --AST-trace      : Display ASCII-art AST to be human readable." << std::endl;
155     std::cerr << "      --pretty-print   : Display pretty-printed code, standard Scilab syntax." << std::endl;
156     std::cerr << " " << std::endl;
157     std::cerr << "Developer Timer arguments:" << std::endl;
158     std::cerr << "      --AST-timed      : Time each AST node." << std::endl;
159     std::cerr << "      --timed          : Time global execution." << std::endl;
160     std::cerr << " " << std::endl;
161     std::cerr << "Developer Debug arguments:" << std::endl;
162     std::cerr << "      --no-exec        : Only do Lexing/parsing do not execute instructions." << std::endl;
163     std::cerr << "      --context-dump   : Display context status." << std::endl;
164 }
165
166
167 /*
168 ** Get Options
169 **
170 **
171 */
172 static int get_option (const int argc, char *argv[], int *_piFileIndex, int *_piLangIndex)
173 {
174     int i = 0;
175
176 #ifdef DEBUG
177     std::cerr << "-*- Getting Options -*-"<< std::endl;
178 #endif
179
180     for (i = 1; i < argc; ++i) {
181         if (!strcmp("--parse-trace", argv[i])) {
182             parseTrace = true;
183         }
184         else if (!strcmp("--pretty-print", argv[i])) {
185             printAst = true;
186         }
187         else if (!strcmp("--help", argv[i])) {
188             usage ();
189             exit (WELL_DONE);
190         }
191         else if (!strcmp("--AST-trace", argv[i])) {
192             dumpAst = true;
193         }
194         else if (!strcmp("--no-exec", argv[i])) {
195             execAst = false;
196         }
197         else if (!strcmp("--context-dump", argv[i])) {
198             dumpStack = true;
199         }
200         else if (!strcmp("--timed", argv[i])) {
201             timed = true;
202         }
203         else if (!strcmp("--AST-timed", argv[i])) {
204             std::cout << "Timed execution" << std::endl;
205             ASTtimed = true;
206         }
207         else if (!strcmp("--parse-file", argv[i])) {
208             i++;
209             parseFile = true;
210             *_piFileIndex = i;
211         }
212         else if (!strcmp("-f", argv[i])) {
213             i++;
214             execFile = true;
215             *_piFileIndex = i;
216         }
217         else if (!strcmp("-e", argv[i])) {
218             i++;
219             execCommand = true;
220             *_piFileIndex = i;
221         }
222         else if (!strcmp("-l", argv[i])) {
223             i++;
224             *_piLangIndex = i;
225         }
226         else if (!strcmp("-nw", argv[i])) {
227             consoleMode = true;
228             setScilabMode(SCILAB_NW);
229         }
230         else if (!strcmp("-nwni", argv[i])) {
231             consoleMode = true;
232             noJvm = true;
233             setScilabMode(SCILAB_NWNI);
234         }
235         else if (!strcmp("-ns", argv[i])) {
236             noStart = true;
237         }
238         else if (!strcmp("-nb", argv[i])) {
239             noBanner = true;
240         }
241     }
242
243 #ifdef DEBUG
244     std::cerr << "File : " << argv[ *_piFileIndex] << std::endl;
245 #endif
246
247     return 0;
248 }
249
250 /*
251 ** HACK HACK HACK
252 */
253
254 extern "C"
255 {
256 #include <stdio.h>
257
258 #ifndef _MSC_VER
259 #include <unistd.h>
260 #endif
261     extern char *TermReadAndProcess(void);
262     extern void ConsolePrintf(char*);
263 }
264
265 /*
266 ** -*- stateView
267 ** Used to show parser state.
268 ** Find if we are stuck within some control structure.
269 */
270
271 static void stateShow(Parser::ControlStatus status)
272 {
273     switch (status)
274     {
275     case Parser::WithinFor :            SetTemporaryPrompt("-for       ->"); break;
276     case Parser::WithinWhile :          SetTemporaryPrompt("-while     ->"); break;
277     case Parser::WithinIf :             SetTemporaryPrompt("-if        ->"); break;
278     case Parser::WithinElse :           SetTemporaryPrompt("-else      ->"); break;
279     case Parser::WithinElseIf :         SetTemporaryPrompt("-elseif    ->"); break;
280     case Parser::WithinTry :            SetTemporaryPrompt("-try       ->"); break;
281     case Parser::WithinCatch :          SetTemporaryPrompt("-catch     ->"); break;
282     case Parser::WithinFunction :       SetTemporaryPrompt("-function  ->"); break;
283     case Parser::WithinSelect :         SetTemporaryPrompt("-select    ->"); break;
284     case Parser::WithinCase :           SetTemporaryPrompt("-case      ->"); break;
285     case Parser::WithinSwitch :         SetTemporaryPrompt("-switch    ->"); break;
286     case Parser::WithinOtherwise :      SetTemporaryPrompt("-otherwise ->"); break;
287     case Parser::WithinMatrix :         SetTemporaryPrompt("- [        ->"); break;
288     case Parser::WithinCell :           SetTemporaryPrompt("- {        ->"); break;
289     case Parser::WithinBlockComment :   SetTemporaryPrompt("- /*       ->"); break;
290     case Parser::WithinDots :           SetTemporaryPrompt("- ...      ->"); break;
291     case Parser::AllControlClosed :     break;
292     }
293 }
294
295 /*
296 ** -*- Interactive Main -*-
297 */
298 static int interactiveMain (void)
299 {
300     int pause = 0;
301     char *command = NULL;
302     Parser::ControlStatus controlStatus = Parser::AllControlClosed;
303
304     if(noBanner == false)
305     {
306         banner();
307     }
308
309     InitializeHistoryManager();
310     /* add date & time @ begin session */
311     char *commentbeginsession = getCommentDateSession();
312     if (commentbeginsession)
313     {
314         appendLineToScilabHistory(commentbeginsession);
315         FREE(commentbeginsession);
316         commentbeginsession=NULL;
317     }
318
319     //before calling reader, try to call %onprompt function
320     callOnPrompt();
321
322     while (!ConfigVariable::getForceQuit())
323     {
324         // Show Parser Sate before prompt
325         stateShow(controlStatus);
326
327         pause = ConfigVariable::getPauseLevel();
328
329         //set prompt value
330         C2F(setprlev)(&pause);
331
332         if (controlStatus == Parser::AllControlClosed)
333         {
334             if(command)
335             {
336                 FREE(command);
337                 command = NULL;
338             }
339             //before calling YaspReader, try to call %onprompt function
340             callOnPrompt();
341
342             command = YaspRead();
343         }
344         else
345         {
346             char* pstRead = YaspRead();
347             //+1 for null termination and +1 for '\n'
348             size_t iLen = strlen(command) + strlen(pstRead) + 2;
349             char* pstNewCommand = (char*)MALLOC(iLen * sizeof(char));
350 #ifdef _MSC_VER
351             sprintf_s(pstNewCommand, iLen, "%s\n%s", command, pstRead);
352 #else
353             sprintf(pstNewCommand, "%s\n%s", command, pstRead);
354 #endif
355             FREE(pstRead);
356             FREE(command);
357             command = pstNewCommand;
358         }
359
360         controlStatus = processCommand(command);
361     }
362 #ifdef DEBUG
363     std::cerr << "To end program press [ENTER]" << std::endl;
364 #endif
365     return ConfigVariable::getExitStatus();
366 }
367
368 static Parser::ControlStatus processCommand(char* _pstCommand)
369 {
370     Parser *parser = new Parser();
371     parser->setParseTrace(parseTrace);
372     if (strcmp(_pstCommand, "") != 0)
373     {
374         wchar_t* pwstCommand = to_wide_string(_pstCommand);
375         /*
376         ** -*- PARSING -*-
377         */
378         parseCommandTask(parser, timed, pwstCommand);
379
380         /*
381         ** -*- DUMPING TREE -*-
382         */
383         if(dumpAst == true)
384         {
385             dumpAstTask(parser->getTree(), timed);
386         }
387
388         if(parser->getExitStatus() == Parser::Succeded)
389         {
390             /*
391             ** -*- PRETTY PRINT TREE -*-
392             */
393             if(printAst == true)
394             {
395                 printAstTask(parser->getTree(), timed);
396             }
397
398             /*
399             ** -*- EXECUTING TREE -*-
400             */
401             if(execAst == true)
402             {
403                 execAstTask(parser->getTree(), timed, ASTtimed);
404             }
405
406             /*
407             ** -*- DUMPING STACK AFTER EXECUTION -*-
408             */
409             if(dumpStack == true)
410             {
411                 dumpStackTask(timed);
412             }
413         }
414         else if(parser->getExitStatus() == Parser::Failed && parser->getControlStatus() == Parser::AllControlClosed)
415         {
416             YaspWriteW(parser->getErrorMessage());
417         }
418
419         FREE(pwstCommand);
420     }
421     return parser->getControlStatus();
422 }
423
424 static void TermPrintf(char *text)
425 {
426     //std::cout << text;
427     printf("%s", text);
428 }
429
430 /*
431 ** -*- MAIN -*-
432 */
433 int main(int argc, char *argv[])
434 {
435     int iFileIndex = INTERACTIVE;
436     int iLangIndex = 0;
437
438     prog_name = to_wide_string(argv[0]);
439
440     setScilabMode(SCILAB_STD);
441     get_option(argc, argv, &iFileIndex, &iLangIndex);
442
443     if (iFileIndex >= argc || iLangIndex >= argc)
444     {
445         // we used -l, -e or -f without another argument
446         usage();
447         return -1;
448     }
449
450 // if WITHOUT_GUI is defined
451 // force Terminal IO -> Terminal IO + StartScilabEngine
452
453 // WITHOUT_GUI (All Platform) => Terminal IO + StartScilabEngine
454 // GUI (MacOSX) =>      [no option]     -> Console IO + InitMacOSXEnv
455 //                      | [-nwni]       -> Terminal IO + StartScilabEngine
456 //                      | [-nw]         -> Terminal IO + InitMacOSXEnv
457 #ifndef WITHOUT_GUI
458     if (consoleMode)
459     {
460         setYaspInputMethod(&TermReadAndProcess);
461         setYaspOutputMethod(&TermPrintf);
462   #if defined(__APPLE__)
463         if(!noJvm)
464         {
465             return initMacOSXEnv(argc, argv, iFileIndex);
466         }
467   #endif // !defined(__APPLE__)
468         return StartScilabEngine(argc, argv, iFileIndex);
469     }
470     else
471     {
472         setYaspInputMethod(&ConsoleRead);
473         setYaspOutputMethod(&ConsolePrintf);
474   #if defined(__APPLE__)
475         return initMacOSXEnv(argc, argv, iFileIndex);
476   #else
477         return StartScilabEngine(argc, argv, iFileIndex);
478   #endif // !defined(__APPLE__)
479     }
480 #else
481         setYaspInputMethod(&TermReadAndProcess);
482         setYaspOutputMethod(&TermPrintf);
483         return StartScilabEngine(argc, argv, iFileIndex);
484 #endif // defined(WITHOUT_GUI)
485 }
486
487 /*
488 ** -*- Batch Main -*-
489 */
490 static int batchMain(char *pstFileName)
491 {
492     /*
493     ** -*- PARSING -*-
494     */
495     Parser *parser = new Parser();
496     parser->setParseTrace(parseTrace);
497
498
499     wchar_t* pwstFileName = to_wide_string(pstFileName);
500     /*
501     ** -*- PARSING -*-
502     */
503     parseFileTask(parser, timed, pwstFileName, L"YaSp");
504
505     /*
506     ** -*- DUMPING TREE -*-
507     */
508     if (dumpAst == true)
509     {
510         dumpAstTask(parser->getTree(), timed);
511     }
512
513     if (parser->getExitStatus() == Parser::Succeded)
514     {
515         /*
516         ** -*- PRETTY PRINT TREE -*-
517         */
518         if (printAst == true)
519         {
520             printAstTask(parser->getTree(), timed);
521         }
522
523     }
524     else
525     {
526         YaspWriteW(parser->getErrorMessage());
527     }
528
529 #ifdef DEBUG
530     std::cerr << "To end program press [ENTER]" << std::endl;
531 #endif
532     return parser->getExitStatus();
533 }
534
535
536 int StartScilabEngine(int argc, char*argv[], int iFileIndex)
537 {
538     int iMainRet = 0;
539     Runner::init();
540
541     /* Scilab Startup */
542     InitializeEnvironnement();
543
544     InitializeString();
545
546 #ifdef _MSC_VER
547     InitializeWindows_tools();
548 #endif
549
550     //InitializeCore();
551
552     InitializeShell();
553
554     if (!noJvm)
555     {
556         /* bug 3702 */
557         /* tclsci creates a TK window on Windows */
558         /* it changes focus on previous windows */
559         /* we put InitializeTclTk before InitializeGUI */
560
561         //InitializeTclTk();
562         InitializeJVM();
563         InitializeGUI();
564
565         /* create needed data structure if not already created */
566         loadGraphicModule() ;
567
568         /* Standard mode -> init Java Console */
569         if ( !consoleMode )
570         {
571             /* Initialize console: lines... */
572             InitializeConsole();
573         }
574
575         loadBackGroundClassPath();
576     }
577
578     /* set current language of scilab */
579     FuncManager *pFM = new FuncManager();
580     pFM->LoadModules(noStart);
581
582     //execute scilab.start
583     if(noStart == false)
584     {
585         execScilabStartTask();
586     }
587
588     int pause = 0;
589     //set prompt value
590     C2F(setprlev)(&pause);
591
592     try
593     {
594         if(execCommand)
595         {//-e option
596             processCommand(argv[iFileIndex]);
597         }
598         else if(execFile)
599         {//-f option execute exec('%s',-1)
600             char* pstCommand = (char*)MALLOC(sizeof(char) * (strlen("exec(\"\",-1)") + strlen(argv[iFileIndex]) + 1));
601             sprintf(pstCommand, "exec(\"%s\",-1)", argv[iFileIndex]);
602             processCommand(pstCommand);
603             FREE(pstCommand);
604         }
605     }
606     catch(ScilabException se)
607     {
608         YaspErrorW(se.GetErrorMessage().c_str());
609     }
610
611     ConfigVariable::setPromptMode(2);
612
613     if (!parseFile)
614     {
615         //always run as interactiveMain even after -e or -f option
616         file_name = L"prompt";
617         iMainRet = interactiveMain();
618     }
619     else
620     {
621         // Only for parsing test, won't execute anything.
622         iMainRet = batchMain(argv[iFileIndex]);
623     }
624
625     //close main scope
626     symbol::Context::getInstance()->scope_end();
627     delete pFM;
628
629     /* Remove TMPDIR before exit */
630     clearTMPDIR();
631
632     return iMainRet;
633 }
634
635 int InitializeEnvironnement(void)
636 {
637     SetScilabEnvironment();
638     InitializeLocalization();
639
640     ConfigVariable::setConsoleWidth(75);
641     ConfigVariable::setFormat(16);
642     Add_All_Variables();
643     FileManager::initialize();
644     return 0;
645 }
646
647 void Add_All_Variables(void)
648 {
649     Add_pi();
650     Add_i();
651     Add_s();
652     Add_z();
653     Add_true();
654     Add_false();
655     Add_Nan();
656     Add_Inf();
657     Add_WITH_DEMOS();
658 }
659
660 void Add_WITH_DEMOS(void)
661 {
662     Add_Boolean_Constant(L"WITH_DEMOS", false);
663 }
664
665 void Add_Nan(void)
666 {
667     double dbl1 = 1.0;
668     double dbl0 = dbl1 - dbl1;
669     Add_Double_Constant(L"%nan", dbl0/dbl0, 0, false);
670 }
671
672 void Add_Inf(void)
673 {
674     double dbl1 = 1.0;
675     double dbl0 = dbl1 - dbl1;
676     Add_Double_Constant(L"%inf", dbl1/dbl0, 0, false);
677 }
678
679 void Add_false(void)
680 {
681     Add_Boolean_Constant(L"%f", false);
682 }
683
684 void Add_true(void)
685 {
686     Add_Boolean_Constant(L"%t", true);
687 }
688
689 void Add_pi(void)
690 {
691     Add_Double_Constant(L"%pi", 3.1415926535897931159980, 0, false);
692 }
693
694 void Add_i(void)
695 {
696     Add_Double_Constant(L"%i", 0, 1, true);
697 }
698
699 void Add_s(void)
700 {
701     Double dblCoef(1,2);
702     dblCoef.set(0, 0, 0);
703     dblCoef.set(0, 1, 1);
704
705     Add_Poly_Constant(L"%s",L"s", 2, &dblCoef);
706 }
707
708 void Add_z(void)
709 {
710     Double dblCoef(1,2);
711     dblCoef.set(0, 0, 0);
712     dblCoef.set(0, 1, 1);
713
714     Add_Poly_Constant(L"%z",L"z", 2, &dblCoef);
715 }
716
717 void Add_Poly_Constant(wstring _szName, wstring _szPolyVar, int _iRank, Double *_pdbl)
718 {
719     types::Polynom *pVar = new types::Polynom(_szPolyVar, 1, 1, &_iRank);
720     SinglePoly *poPoly = pVar->get(0,0);
721     poPoly->setCoef(_pdbl);
722     Context::getInstance()->put(symbol::Symbol(_szName), *pVar);
723 }
724
725 void Add_Double_Constant(wstring _szName, double _dblReal, double _dblImg, bool _bComplex)
726 {
727     types::Double* pVal = new types::Double(1,1,_bComplex);
728     pVal->set(0, 0, _dblReal);
729     pVal->setImg(0, 0, _dblImg);
730     symbol::Context::getInstance()->put(symbol::Symbol(_szName), *pVal);
731 }
732
733 void Add_Boolean_Constant(wstring _szName, bool _bBool)
734 {
735     types::Bool* pVal = new types::Bool(_bBool);
736     symbol::Context::getInstance()->put(symbol::Symbol(_szName), *pVal);
737 }
738
739 void Add_String_Constant(wstring _szName, const char* _pstString)
740 {
741     types::String* ps = new types::String(_pstString);
742     symbol::Context::getInstance()->put(symbol::Symbol(_szName), *ps);
743 }
744