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