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