18145dc4025c7bafc92e5bfa0bc7865718e52461
[scilab.git] / scilab / modules / startup / 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  *  Copyright (C) 2013 - Scilab Enterprises - Antoine ELIAS
5  *
6  * Copyright (C) 2012 - 2016 - Scilab Enterprises
7  *
8  * This file is hereby licensed under the terms of the GNU GPL v2.0,
9  * pursuant to article 5.3.4 of the CeCILL v.2.1.
10  * This file was originally licensed under the terms of the CeCILL v2.1,
11  * and continues to be available under such terms.
12  * For more information, see the COPYING file which you should have received
13  * along with this program.
14  *
15  */
16
17
18 #ifdef _MSC_VER
19 #pragma comment(lib,"../../../../../bin/libintl.lib")
20 #endif
21
22 #include <cstdio>
23 #include <iostream>
24 #include <string.h>
25 #include <setjmp.h>
26
27 extern "C"
28 {
29 #ifdef __APPLE__
30 #include "initMacOSXEnv.h"
31 #endif
32 #include "InitScilab.h"
33 #include "configvariable_interface.h"
34 #include "scilabRead.h"
35 #include "ConsoleRead.h"
36 #include "version.h"
37 #include "sci_malloc.h"
38 #include "lasterror.h"
39 #include "getpipeline.h"
40
41     extern char *getCmdLine(void);
42
43 #ifdef _MSC_VER
44 #include "FilesAssociations.h"
45 #include "PATH_MAX.h"
46     jmp_buf ScilabJmpEnv;
47 #else
48     extern jmp_buf ScilabJmpEnv;
49 #endif
50 #include "isatty.hxx"
51 }
52
53 #include "configvariable.hxx"
54 #include "exit_status.hxx"
55 #include "scilabWrite.hxx"
56
57 #define INTERACTIVE     -1
58
59 extern "C"
60 {
61 #ifdef ENABLE_MPI
62 #include "initMPI.h"
63 #endif
64 }
65
66 /*
67 ** Usage
68 **
69 ** Display usage : options available
70 */
71 static void usage(void)
72 {
73     std::cerr << "Usage: Scilab <options>" << std::endl;
74     std::cerr << "      -e Instruction   : execute the scilab instruction given in Instruction argument.";
75     std::cerr << "                         -e and -f arguments are mutually exclusive.";
76     std::cerr << "      -f File          : execute the scilab script given in File argument.";
77     std::cerr << "                         -e and -f arguments are mutually exclusive.";
78     std::cerr << "      -quit            : force scilab exit after execution of script from -e or -f argument.";
79     std::cerr << "                         this flag is ignored if it is not used with -e or -f argument.";
80     std::cerr << "      -l lang          : Change the language of scilab ( default : en_US )." << std::endl;
81     std::cerr << "      -nw              : Enable console mode." << std::endl;
82     std::cerr << "      -nwni            : Enable terminal mode." << std::endl;
83     std::cerr << "      -ns              : Don't execute etc/scilab.start." << std::endl;
84     std::cerr << "      --help           : Display this help." << std::endl;
85     std::cerr << "Developer Trace arguments:" << std::endl;
86     std::cerr << "      --parse-trace    : Display bison state machine evolution." << std::endl;
87     std::cerr << "      --AST-trace      : Display ASCII-art AST to be human readable." << std::endl;
88     std::cerr << "      --pretty-print   : Display pretty-printed code, standard Scilab syntax." << std::endl;
89     std::cerr << " " << std::endl;
90     std::cerr << "Developer Timer arguments:" << std::endl;
91     std::cerr << "      --AST-timed      : Time each AST node." << std::endl;
92     std::cerr << "      --timed          : Time global execution." << std::endl;
93     std::cerr << " " << std::endl;
94     std::cerr << "Developer Debug arguments:" << std::endl;
95     std::cerr << "      --no-exec        : Only do Lexing/parsing do not execute instructions." << std::endl;
96     std::cerr << "      --context-dump   : Display context status." << std::endl;
97     std::cerr << "      --exec-verbose   : Display command before running it." << std::endl;
98     std::cerr << "      --timeout delay  : Kill the Scilab process after a delay." << std::endl;
99 }
100
101 /*
102 ** Get Options
103 **
104 */
105 static int get_option(const int argc, char *argv[], ScilabEngineInfo* _pSEI)
106 {
107     int i = 0;
108
109 #ifdef DEBUG
110     std::cerr << "-*- Getting Options -*-" << std::endl;
111 #endif
112
113     for (i = 1; i < argc; ++i)
114     {
115         if (!strcmp("--parse-trace", argv[i]))
116         {
117             _pSEI->iParseTrace = 1;
118         }
119         else if (!strcmp("--pretty-print", argv[i]))
120         {
121             _pSEI->iPrintAst = 1;
122         }
123         else if (!strcmp("--help", argv[i]))
124         {
125             usage();
126             exit(WELL_DONE);
127         }
128         else if (!strcmp("--AST-trace", argv[i]))
129         {
130             _pSEI->iDumpAst = 1;
131         }
132         else if (!strcmp("--no-exec", argv[i]))
133         {
134             _pSEI->iExecAst = 0;
135         }
136         else if (!strcmp("--context-dump", argv[i]))
137         {
138             _pSEI->iDumpStack = 1;
139         }
140         else if (!strcmp("--timed", argv[i]))
141         {
142             _pSEI->iTimed = 1;
143             ConfigVariable::setTimed(true);
144         }
145         else if (!strcmp("--serialize", argv[i]))
146         {
147             _pSEI->iSerialize = 1;
148             ConfigVariable::setSerialize(true);
149         }
150         else if (!strcmp("--AST-timed", argv[i]))
151         {
152             std::cout << "Timed execution" << std::endl;
153             _pSEI->iAstTimed = 1;
154         }
155         else if (!strcmp("--parse-file", argv[i]))
156         {
157             i++;
158             if (argc >= i)
159             {
160                 _pSEI->pstParseFile = argv[i];
161             }
162         }
163         else if (!strcmp("-quit", argv[i]))
164         {
165             _pSEI->iForceQuit = 1;
166         }
167         else if (!strcmp("-version", argv[i]))
168         {
169             i++;
170             if (argc >= i)
171             {
172                 _pSEI->iShowVersion = 1;
173             }
174         }
175         else if (!strcmp("-f", argv[i]))
176         {
177             i++;
178             if (argc >= i)
179             {
180                 _pSEI->pstFile = argv[i];
181             }
182         }
183         else if (!strcmp("-e", argv[i]))
184         {
185             i++;
186             if (argc >= i)
187             {
188                 _pSEI->pstExec = argv[i];
189             }
190         }
191         else if (!strcmp("-O", argv[i]))
192         {
193             i++;
194             if (argc >= i)
195             {
196                 _pSEI->pstExec = argv[i];
197                 _pSEI->iCodeAction = 0;
198             }
199         }
200         else if (!strcmp("-X", argv[i]))
201         {
202             i++;
203             if (argc >= i)
204             {
205                 _pSEI->pstExec = argv[i];
206                 _pSEI->iCodeAction = 1;
207             }
208         }
209         else if (!strcmp("-P", argv[i]))
210         {
211             i++;
212             if (argc >= i)
213             {
214                 _pSEI->pstExec = argv[i];
215                 _pSEI->iCodeAction = 2;
216             }
217         }
218         else if (!strcmp("-l", argv[i]))
219         {
220             i++;
221             if (argc >= i)
222             {
223                 _pSEI->pstLang = argv[i];
224             }
225         }
226         else if (!strcmp("-nw", argv[i]))
227         {
228             _pSEI->iConsoleMode = 1;
229         }
230         else if (!strcmp("-nwni", argv[i]))
231         {
232             _pSEI->iConsoleMode = 1;
233             _pSEI->iNoJvm = 1;
234         }
235         else if (!strcmp("-ns", argv[i]))
236         {
237             _pSEI->iNoStart = 1;
238         }
239         else if (!strcmp("-nb", argv[i]))
240         {
241             _pSEI->iNoBanner = 0;
242         }
243         else if (!strcmp("--exec-verbose", argv[i]))
244         {
245             _pSEI->iExecVerbose = 1;
246         }
247         else if (!strcmp("--timeout", argv[i]))
248         {
249             i++;
250             if (argc > i)
251             {
252                 char* timeout = argv[i];
253
254                 char* str_end = NULL;
255                 int iTimeoutDelay = strtol(timeout, &str_end, 0);
256
257                 int modifier = 1;
258                 if (str_end != '\0')
259                 {
260                     switch (*str_end)
261                     {
262                         case 'd':
263                             modifier = 86400;
264                             break;
265                         case 'h':
266                             modifier = 3600;
267                             break;
268                         case 'm':
269                             modifier = 60;
270                             break;
271                         case 's':
272                             modifier = 1;
273                             break;
274                         default:
275                             std::cerr << "Invalid timeout delay unit: s (for seconds), m (for minutes), h (for hours), d (for days) are supported" << std::endl;
276                             exit(EXIT_FAILURE);
277                             break;
278                     }
279                 }
280
281                 _pSEI->iTimeoutDelay = iTimeoutDelay * modifier;
282             }
283             else
284             {
285                 std::cerr << "Unspecified timeout delay" << std::endl;
286                 exit(EXIT_FAILURE);
287             }
288
289         }
290         else if (!strcmp("-keepconsole", argv[i]))
291         {
292             _pSEI->iKeepConsole = 1;
293         }
294     }
295
296     ConfigVariable::setCommandLineArgs(argc, argv);
297     return 0;
298 }
299
300 extern "C"
301 {
302 #include <stdio.h>
303
304 #ifndef _MSC_VER
305 #include <unistd.h>
306 #endif
307     extern char *getCmdLine(void);
308     extern void ConsolePrintf(const char *);
309 }
310
311 static void TermPrintf(const char *text)
312 {
313     //std::cout << text;
314     printf("%s", text);
315 }
316
317 /*
318 ** -*- MAIN -*-
319 */
320 //#if defined(_WIN32) && !defined(WITHOUT_GUI)
321 //int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLine, int iCmdShow)
322 //#else
323 int main(int argc, char *argv[])
324 //#endif
325 {
326     int iRet = 0;
327
328 #ifdef ENABLE_MPI
329     initScilabMPI();
330 #endif
331
332     ScilabEngineInfo* pSEI = InitScilabEngineInfo();
333 #ifdef WITHOUT_GUI
334     /* Building Scilab-cli-bin. We won't ever had the gui nor the jvm */
335     pSEI->iConsoleMode = 1;
336     pSEI->iNoJvm = 1;
337     setScilabMode(SCILAB_NWNI);
338 #else
339     setScilabMode(SCILAB_STD);
340 #endif
341
342     //#if defined(_WIN32) && !defined(WITHOUT_GUI)
343     //    {
344     //        LPSTR my_argv[256];
345     //        int nArgs = 0;
346     //        LPWSTR *szArglist = CommandLineToArgvW(GetCommandLineW(), &nArgs);
347     //        if (szArglist)
348     //        {
349     //            for (int i = 0; i < nArgs; i++)
350     //            {
351     //                my_argv[i] = wide_string_to_UTF8(szArglist[i]);
352     //            }
353     //            LocalFree(szArglist);
354     //        }
355     //        get_option(nArgs, my_argv, pSEI);
356     //    }
357     //#else
358     get_option(argc, argv, pSEI);
359     //#endif
360
361     // if WITHOUT_GUI is defined
362     // force Terminal IO -> Terminal IO + StartScilabEngine
363
364     // WITHOUT_GUI (All Platform) => Terminal IO + StartScilabEngine
365     // GUI (MacOSX) =>      [no option]     -> Console IO + InitMacOSXEnv
366     //                      | [-nwni]       -> Terminal IO + StartScilabEngine
367     //                      | [-nw]         -> Terminal IO + InitMacOSXEnv
368 #ifndef WITHOUT_GUI
369     if (pSEI->iConsoleMode)
370     {
371         setScilabMode(SCILAB_NW);
372         setScilabInputMethod(&getCmdLine);
373         setScilabOutputMethod(&TermPrintf);
374 #if defined(__APPLE__)
375         if (pSEI->iNoJvm == 0)
376         {
377             return initMacOSXEnv(pSEI);
378         }
379 #endif // !defined(__APPLE__)
380     }
381     else
382     {
383         setScilabMode(SCILAB_STD);
384         setScilabInputMethod(&ConsoleRead);
385         setScilabOutputMethod(&ConsolePrintf);
386
387 #ifdef _MSC_VER
388         if (pSEI->iCodeAction != -1)
389         {
390             //manage calls from explorer ( double click on sce file , ... )
391             char* Cmd = (char*)MALLOC(((PATH_MAX * 2) + 1) * sizeof(char));
392             strcpy(Cmd, "");
393             int ret = CommandByFileExtension(pSEI->pstExec, pSEI->iCodeAction, Cmd);
394
395             if (ret && Cmd[0] != '\0')
396             {
397                 pSEI->pstExec = Cmd; //Cmd must be freed in StartScilabEngine after process.
398             }
399             else
400             {
401                 pSEI->iCodeAction = -1;
402             }
403         }
404 #endif
405
406 #if defined(__APPLE__)
407         return initMacOSXEnv(pSEI);
408 #endif // !defined(__APPLE__)
409     }
410 #else
411     setScilabMode(SCILAB_NWNI);
412     setScilabInputMethod(&getCmdLine);
413     setScilabOutputMethod(&TermPrintf);
414 #endif // defined(WITHOUT_GUI)
415
416 #ifdef _MSC_VER
417     /* if file descriptor returned is -2 stdin is not associated with an input stream */
418     /* example : echo plot3d | scilex -nw -e */
419     if (!isatty(_fileno(stdin)) && (_fileno(stdin) != -2))
420 #else
421     if (!isatty(fileno(stdin)))
422 #endif
423     {
424         // We are in a pipe
425         setScilabInputMethod(&getPipeLine);
426     }
427
428     if (pSEI->iShowVersion == 1)
429     {
430         disp_scilab_version();
431         exit(0);
432     }
433
434     int val = setjmp(ScilabJmpEnv);
435     if (!val)
436     {
437         iRet = StartScilabEngine(pSEI);
438         if (iRet == 0)
439         {
440             iRet = RunScilabEngine(pSEI);
441         }
442
443         StopScilabEngine(pSEI);
444         FREE(pSEI);
445         return iRet;
446     }
447     else
448     {
449         // We probably had a segfault so print error
450         std::wcerr << getLastErrorMessage() << std::endl;
451         return val;
452     }
453 }
454