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