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