0eeb98b898f225eabb197d78e91bdd62faedd680
[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 #ifdef _MSC_VER
234 #if WITH_CONSOLE_JAVA
235             MessageBoxA(NULL, "Argument \"-nw\" is no longer supported.\nSee help page: https://help.scilab.org/scilab \n", "Error", MB_OK | MB_ICONERROR);
236 #else
237             printf("Argument \"-nw\" is no longer supported.\nSee help page: https://help.scilab.org/scilab \n");
238 #endif
239             exit(-1);
240 #endif
241         }
242         else if (!strcmp("-nwni", argv[i]))
243         {
244             _pSEI->iConsoleMode = 1;
245             _pSEI->iNoJvm = 1;
246 #ifdef _MSC_VER
247 #if WITH_CONSOLE_JAVA
248             MessageBoxA(NULL, "Argument \"-nwni\" is no longer supported.\nSee help page: https://help.scilab.org/scilab \n", "Error", MB_OK | MB_ICONERROR);
249 #else
250             printf("Argument \"-nwni\" is no longer supported.\nSee help page: https://help.scilab.org/scilab \n");
251 #endif
252             exit(-1);
253 #endif
254         }
255         else if (!strcmp("-ns", argv[i]))
256         {
257             _pSEI->iNoStart = 1;
258         }
259         else if (!strcmp("-nb", argv[i]))
260         {
261             _pSEI->iNoBanner = 0;
262         }
263         else if (!strcmp("--exec-verbose", argv[i]))
264         {
265             _pSEI->iExecVerbose = 1;
266         }
267         else if (!strcmp("-nocolor", argv[i]))
268         {
269 #ifndef _MSC_VER
270             setCLIColor(FALSE);
271 #endif
272         }
273         else if (!strcmp("--timeout", argv[i]))
274         {
275             i++;
276             if (argc > i)
277             {
278                 char* timeout = argv[i];
279
280                 char* str_end = NULL;
281                 int iTimeoutDelay = strtol(timeout, &str_end, 0);
282
283                 int modifier;
284                 switch (*str_end)
285                 {
286                     case 'd':
287                         modifier = 86400;
288                         break;
289                     case 'h':
290                         modifier = 3600;
291                         break;
292                     case 'm':
293                         modifier = 60;
294                         break;
295                     case 's':
296                     case '\0': // no modifiers
297                         modifier = 1;
298                         break;
299                     default:
300                         std::cerr << "Invalid timeout delay unit: s (for seconds, default), m (for minutes), h (for hours), d (for days) are supported" << std::endl;
301                         exit(EXIT_FAILURE);
302                         break;
303                 }
304
305                 _pSEI->iTimeoutDelay = iTimeoutDelay * modifier;
306             }
307             else
308             {
309                 std::cerr << "Unspecified timeout delay" << std::endl;
310                 exit(EXIT_FAILURE);
311             }
312
313         }
314         else if (!strcmp("-keepconsole", argv[i]))
315         {
316             _pSEI->iKeepConsole = 1;
317         }
318         else if (!strcmp("--webmode", argv[i]))
319         {
320             _pSEI->iWebMode = 1;
321         }
322         else if (!strcmp("-scihome", argv[i]))
323         {
324             i++;
325             if (argc >= i)
326             {
327                 _pSEI->pstSciHome = argv[i];
328             }
329         }
330     }
331
332     ConfigVariable::setCommandLineArgs(argc, argv);
333     return 0;
334 }
335
336 extern "C"
337 {
338 #include <stdio.h>
339
340 #ifndef _MSC_VER
341 #include <unistd.h>
342 #endif
343     extern char *getCmdLine(void);
344     extern void ConsolePrintf(const char *);
345 }
346
347 static void TermError(const char *text)
348 {
349     fprintf(stderr, "%s", text);
350 }
351
352 static void TermOutput(const char *text)
353 {
354     fprintf(stdout, "%s", text);
355 }
356
357 /*
358 ** -*- MAIN -*-
359 */
360 #if defined(_WIN32) && !defined(WITHOUT_GUI) && defined(WITH_CONSOLE_JAVA)
361 int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLine, int iCmdShow)
362 {
363     LPWSTR *szArglist = NULL;
364     int argc = 0;
365     szArglist = CommandLineToArgvW(GetCommandLineW(), &argc);
366     char** argv = new char*[argc];
367     for (int i = 0; i < argc; ++i)
368     {
369         argv[i] = wide_string_to_UTF8(szArglist[i]);
370     }
371
372     setWindowShowMode(iCmdShow);
373
374 #else
375 int main(int argc, char *argv[])
376 {
377 #endif
378     int iRet = 0;
379
380 #ifdef ENABLE_MPI
381     initScilabMPI();
382 #endif
383
384     ScilabEngineInfo* pSEI = InitScilabEngineInfo();
385 #ifdef WITHOUT_GUI
386     /* Building Scilab-cli-bin. We won't ever had the gui nor the jvm */
387     pSEI->iConsoleMode = 1;
388     pSEI->iNoJvm = 1;
389     setScilabMode(SCILAB_NWNI);
390 #else
391     setScilabMode(SCILAB_STD);
392 #endif
393
394     //#if defined(_WIN32) && !defined(WITHOUT_GUI)
395     //    {
396     //        LPSTR my_argv[256];
397     //        int nArgs = 0;
398     //        LPWSTR *szArglist = CommandLineToArgvW(GetCommandLineW(), &nArgs);
399     //        if (szArglist)
400     //        {
401     //            for (int i = 0; i < nArgs; i++)
402     //            {
403     //                my_argv[i] = wide_string_to_UTF8(szArglist[i]);
404     //            }
405     //            LocalFree(szArglist);
406     //        }
407     //        get_option(nArgs, my_argv, pSEI);
408     //    }
409     //#else
410     get_option(argc, argv, pSEI);
411     //#endif
412
413     // if WITHOUT_GUI is defined
414     // force Terminal IO -> Terminal IO + StartScilabEngine
415
416     // WITHOUT_GUI (All Platform) => Terminal IO + StartScilabEngine
417     // GUI (MacOSX) =>      [no option]     -> Console IO + InitMacOSXEnv
418     //                      | [-nwni]       -> Terminal IO + StartScilabEngine
419     //                      | [-nw]         -> Terminal IO + InitMacOSXEnv
420 #ifndef WITHOUT_GUI
421 #ifdef _MSC_VER
422 #ifndef WITH_CONSOLE_JAVA
423     pSEI->iConsoleMode = SCILAB_NW;
424 #endif
425 #endif
426     if (pSEI->iConsoleMode)
427     {
428         setScilabMode(SCILAB_NW);
429         setScilabInputMethod(&getCmdLine);
430         setScilabErrorStreamMethod(&TermError);
431         setScilabOutputStreamMethod(&TermOutput);
432 #if defined(__APPLE__)
433         if (pSEI->iNoJvm == 0)
434         {
435             return initMacOSXEnv(pSEI);
436         }
437 #endif // !defined(__APPLE__)
438     }
439     else
440     {
441         setScilabMode(SCILAB_STD);
442         setScilabInputMethod(&ConsoleRead);
443         setScilabOutputMethod(&ConsolePrintf);
444
445 #ifdef _MSC_VER
446         if (pSEI->iCodeAction != -1)
447         {
448             //manage calls from explorer ( double click on sce file , ... )
449             char* Cmd = (char*)MALLOC(((PATH_MAX * 2) + 1) * sizeof(char));
450             strcpy(Cmd, "");
451             int ret = CommandByFileExtension(pSEI->pstExec, pSEI->iCodeAction, Cmd);
452
453             if (ret && Cmd[0] != '\0')
454             {
455                 pSEI->pstExec = Cmd; //Cmd must be freed in StartScilabEngine after process.
456             }
457             else
458             {
459                 pSEI->iCodeAction = -1;
460             }
461         }
462 #endif
463
464 #if defined(__APPLE__)
465         return initMacOSXEnv(pSEI);
466 #endif // !defined(__APPLE__)
467     }
468 #else
469     setScilabMode(SCILAB_NWNI);
470     setScilabInputMethod(&getCmdLine);
471     setScilabErrorStreamMethod(&TermError);
472     setScilabOutputStreamMethod(&TermOutput);
473 #endif // defined(WITHOUT_GUI)
474
475 #ifdef _MSC_VER
476     /* if file descriptor returned is -2 stdin is not associated with an input stream */
477     /* example : echo plot3d | scilex -e */
478
479     if (!isatty(_fileno(stdin)) && (_fileno(stdin) != -2) && getScilabMode() != SCILAB_STD)
480 #else
481     if (!isatty(fileno(stdin)) && getScilabMode() != SCILAB_STD)
482 #endif
483     {
484         // We are in a pipe
485         setScilabInputMethod(&getPipeLine);
486     }
487
488     if (pSEI->iShowVersion == 1)
489     {
490         disp_scilab_version();
491         exit(0);
492     }
493
494     int val = setjmp(ScilabJmpEnv);
495     if (!val)
496     {
497         iRet = StartScilabEngine(pSEI);
498         if (iRet == 0)
499         {
500             iRet = RunScilabEngine(pSEI);
501         }
502
503         StopScilabEngine(pSEI);
504         FREE(pSEI);
505         return iRet;
506     }
507     else
508     {
509         // We probably had a segfault so print error
510         std::wcerr << getLastErrorMessage() << std::endl;
511         return val;
512     }
513
514 #if defined(_WIN32) && !defined(WITHOUT_GUI) && defined(WITH_CONSOLE_JAVA)
515     LocalFree(szArglist);
516 #endif
517 }
518