1 /*
2  *  gretl -- Gnu Regression, Econometrics and Time-series Library
3  *  Copyright (C) 2001 Allin Cottrell and Riccardo "Jack" Lucchetti
4  *
5  *  This program is free software: you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation, either version 3 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  *
18  */
19 
20 /* command-line client program for libgretl */
21 
22 #include "libgretl.h"
23 #include "version.h"
24 #include "monte_carlo.h"
25 #include "var.h"
26 #include "system.h"
27 #include "gretl_restrict.h"
28 #include "gretl_func.h"
29 #include "gretl_help.h"
30 #include "libset.h"
31 #include "cmd_private.h"
32 #include "flow_control.h"
33 #include "objstack.h"
34 #include "gretl_xml.h"
35 #include "gretl_string_table.h"
36 #include "dbread.h"
37 #include "uservar.h"
38 #include "csvdata.h"
39 #ifdef USE_CURL
40 # include "gretl_www.h"
41 #endif
42 
43 #include <dirent.h>
44 
45 #ifdef WIN32
46 # include "gretl_win32.h"
47 #else
48 # include <sys/stat.h>
49 # include <sys/types.h>
50 # include <fcntl.h>
51 # include <unistd.h>
52 #endif
53 
54 #ifdef HAVE_READLINE
55 # include <readline/readline.h>
56 /* readline functions from complete.c */
57 extern char *rl_gets (char **line_read, const char *prompt);
58 extern void initialize_readline (void);
59 #endif /* HAVE_READLINE */
60 
61 #define ENDRUN (NC + 1)
62 #define RUNLOOP (NC + 2)
63 
64 char datafile[MAXLEN];
65 char cmdfile[MAXLEN];
66 FILE *fb;
67 int batch;
68 int runit;
69 int indent0;
70 int batch_stdin;
71 int data_status;
72 char linebak[MAXLINE];      /* for storing comments */
73 char *line_read;
74 
75 static int cli_exec_line (ExecState *s, DATASET *dset, PRN *cmdprn);
76 static int push_input_file (FILE *fp);
77 static FILE *pop_input_file (void);
78 static int cli_saved_object_action (const char *line,
79                                     DATASET *dset,
80                                     PRN *prn);
81 
parse_options(int * pargc,char *** pargv,gretlopt * popt,double * scriptval,char * fname)82 static int parse_options (int *pargc, char ***pargv, gretlopt *popt,
83                           double *scriptval, char *fname)
84 {
85     char **argv;
86     int argc, gotfile = 0;
87     gretlopt opt = OPT_NONE;
88     int err = 0;
89 
90     *fname = '\0';
91 
92     if (pargv == NULL) {
93         return 0;
94     }
95 
96     argc = *pargc;
97     argv = *pargv;
98 
99     while (*++argv) {
100         const char *s = *argv;
101 
102         if (!strcmp(s, "-e") || !strncmp(s, "--english", 9)) {
103             opt |= OPT_ENGLISH;
104         } else if (!strcmp(s, "-b") || !strncmp(s, "--batch", 7)) {
105             opt |= OPT_BATCH;
106         } else if (!strcmp(s, "-h") || !strcmp(s, "--help")) {
107             opt |= OPT_HELP;
108         } else if (!strcmp(s, "-v") || !strcmp(s, "--version")) {
109             opt |= OPT_VERSION;
110         } else if (!strcmp(s, "-r") || !strncmp(s, "--run", 5)) {
111             opt |= OPT_RUNIT;
112         } else if (!strcmp(s, "-c") || !strncmp(s, "--dump", 6)) {
113             opt |= OPT_DUMP;
114         } else if (!strcmp(s, "-q") || !strcmp(s, "--quiet")) {
115             opt |= OPT_QUIET;
116         } else if (!strcmp(s, "-m") || !strcmp(s, "--makepkg")) {
117             opt |= OPT_MAKEPKG;
118         } else if (!strcmp(s, "-i") || !strcmp(s, "--instpkg")) {
119             opt |= OPT_INSTPKG;
120         } else if (!strcmp(s, "-t") || !strcmp(s, "--tool")) {
121             opt |= (OPT_TOOL | OPT_BATCH);
122         } else if (!strncmp(s, "--scriptopt=", 12)) {
123             *scriptval = atof(s + 12);
124         } else if (*s == '-' && *(s+1) != '\0') {
125             /* spurious option? */
126             fprintf(stderr, "Bad option: %s\n", s);
127             err = E_DATA;
128             break;
129         } else if (!gotfile) {
130             strncat(fname, s, MAXLEN - 1);
131             gotfile = 1;
132         }
133 
134         argc--;
135     }
136 
137     if (!err) {
138         err = incompatible_options(opt, OPT_BATCH | OPT_RUNIT |
139                                    OPT_DBOPEN | OPT_WEBDB | OPT_MAKEPKG);
140         if (!err) {
141             err = incompatible_options(opt, OPT_ENGLISH | OPT_BASQUE);
142         }
143         if (!err) {
144             err = incompatible_options(opt, OPT_MAKEPKG | OPT_INSTPKG);
145         }
146     }
147 
148     *pargc = argc;
149     *pargv = argv;
150     *popt = opt;
151 
152     return err;
153 }
154 
usage(int err)155 static void usage (int err)
156 {
157     logo(0);
158 
159     printf(_("\nYou may supply the name of a data file on the command line.\n"
160              "Options:\n"
161              " -b or --batch     Process a command script and exit.\n"
162              " -r or --run       Run a script then hand control to command line.\n"
163              " -m or --makepkg   Run a script and create a package from it.\n"
164              " -i or --instpkg   Install a specified function package.\n"
165              " -h or --help      Print this info and exit.\n"
166              " -v or --version   Print version info and exit.\n"
167              " -e or --english   Force use of English rather than translation.\n"
168              " -q or --quiet     Print less verbose program information.\n"
169              " -t or --tool      Operate silently.\n"
170              "Example of batch mode usage:\n"
171              " gretlcli -b myfile.inp > myfile.out\n"
172              "Example of run mode usage:\n"
173              " gretlcli -r myfile.inp\n"));
174 
175     printf(_("\nSpecial batch-mode option:\n"
176              " --scriptopt=<value> sets a scalar value, accessible to a script\n"
177              " under the name \"scriptopt\"\n\n"));
178 
179     if (err) {
180         exit(EXIT_FAILURE);
181     } else {
182         exit(EXIT_SUCCESS);
183     }
184 }
185 
186 #if defined(OPENMP_BUILD) && !defined(WIN32) && !defined(OS_OSX)
187 
check_blas_threading(int tool,int quiet)188 static void check_blas_threading (int tool, int quiet)
189 {
190     char *s1, *s2;
191 
192     if (get_openblas_details(&s1, &s2) && !strcmp(s2, "pthreads")) {
193         if (tool || quiet) {
194             fprintf(stderr, "Disabling OpenBLAS multi-threading "
195                     "(OpenMP/pthreads collision)\n");
196         } else {
197             puts("\n*** Warning ***\n*\n"
198                  "* gretl is built using OpenMP, but is linked against\n"
199                  "* OpenBLAS parallelized via pthreads. This combination\n"
200                  "* of threading mechanisms is not recommended. Ideally,\n"
201                  "* OpenBLAS should also use OpenMP.");
202         }
203         /* do we really need this? */
204         gretl_setenv("OPENBLAS_NUM_THREADS", "1");
205     }
206 }
207 
208 #endif
209 
gretl_abort(char * line)210 static void gretl_abort (char *line)
211 {
212     const char *tokline = get_parser_errline();
213 
214     fprintf(stderr, _("\ngretlcli: error executing script: halting\n"));
215 
216     if (tokline != NULL && *tokline != '\0' && strcmp(tokline, line)) {
217         fprintf(stderr, "> %s\n", tokline);
218     }
219 
220     if (*line != '\0') {
221         fprintf(stderr, "> %s\n", line);
222     }
223 
224     exit(EXIT_FAILURE);
225 }
226 
noalloc(void)227 static void noalloc (void)
228 {
229     fputs(_("Out of memory!\n"), stderr);
230     exit(EXIT_FAILURE);
231 }
232 
file_get_line(ExecState * s)233 static int file_get_line (ExecState *s)
234 {
235     char *line = s->line;
236     int len = 0;
237 
238     memset(line, 0, MAXLINE);
239 
240     if (fgets(line, MAXLINE, fb) == NULL) {
241         /* no more input from current source */
242         gretl_exec_state_uncomment(s);
243     } else {
244         len = strlen(line);
245     }
246 
247     if (*line == '\0') {
248         strcpy(line, "quit");
249         s->cmd->ci = QUIT;
250     } else if (len == MAXLINE - 1 && line[len-1] != '\n') {
251         return E_TOOLONG;
252     } else {
253         *linebak = '\0';
254         strncat(linebak, line, MAXLINE-1);
255         tailstrip(linebak);
256     }
257 
258     if (gretl_echo_on() && s->cmd->ci == RUN && batch && *line == '(') {
259         printf("%s", line);
260         *linebak = '\0';
261     }
262 
263     return 0;
264 }
265 
266 #ifdef ENABLE_NLS
267 
nls_init(void)268 static void nls_init (void)
269 {
270 # if defined(WIN32) && defined(PKGBUILD)
271     char localedir[MAXLEN];
272 
273     gretl_build_path(localedir, gretl_home(), "locale", NULL);
274 # else
275     const char *localedir = LOCALEDIR;
276 # endif /* WIN32 package or not */
277     setlocale(LC_ALL, "");
278     bindtextdomain(PACKAGE, localedir);
279     textdomain(PACKAGE);
280     bind_textdomain_codeset(PACKAGE, "UTF-8");
281 
282     gretl_setenv("LC_NUMERIC", "");
283     setlocale(LC_NUMERIC, "");
284     reset_local_decpoint();
285 # ifdef WIN32
286     if (getenv("CLI_DEBUG")) {
287         set_windebug(2);
288     }
289     if (try_for_CP_65001() != 0) {
290 	/* FIXME issue a warning */
291 	;
292     }
293 # endif
294 }
295 
296 #endif /* ENABLE_NLS */
297 
cli_clear_data(ExecState * s,DATASET * dset)298 static int cli_clear_data (ExecState *s, DATASET *dset)
299 {
300     CMD *cmd = s->cmd;
301     gretlopt clearopt = 0;
302     int err = 0;
303 
304     if (cmd->ci == CLEAR) {
305         clearopt = cmd->opt;
306     } else if (cmd->opt & OPT_P) {
307         /* --preserve: clear dataset only */
308         clearopt = OPT_D;
309     } else if (csv_open_needs_matrix(cmd->opt)) {
310         clearopt = OPT_D;
311     }
312 
313     if (dset->Z != NULL) {
314         err = restore_full_sample(dset, NULL);
315         free_Z(dset);
316     }
317 
318     clear_datainfo(dset, CLEAR_FULL);
319     data_status = 0;
320     *datafile = '\0';
321 
322     clear_model(s->model);
323 
324     if (clearopt & OPT_D) {
325         libgretl_session_cleanup(SESSION_CLEAR_DATASET);
326     } else {
327         libgretl_session_cleanup(SESSION_CLEAR_ALL);
328     }
329 
330     set_model_count(0);
331     gretl_cmd_destroy_context(cmd);
332 
333     return err;
334 }
335 
get_prompt(ExecState * s)336 static const char *get_prompt (ExecState *s)
337 {
338     if (s->flags & DEBUG_EXEC) {
339         return "$ ";
340     } else if (gretl_compiling_function() ||
341                gretl_compiling_loop()) {
342         return "> ";
343     } else {
344         return "? ";
345     }
346 }
347 
348 /* this function is set up as it is to make it available for debugging
349    purposes */
350 
get_interactive_line(void * p)351 static int get_interactive_line (void *p)
352 {
353     ExecState *s = (ExecState *) p;
354     const char *prompt = get_prompt(s);
355     int err = 0;
356 
357 #ifdef HAVE_READLINE
358     rl_gets(&line_read, prompt);
359 
360     if (line_read == NULL) {
361         strcpy(s->line, "quit");
362     } else if (strlen(line_read) > MAXLINE - 2) {
363         err = E_TOOLONG;
364     } else {
365         *s->line = '\0';
366         strncat(s->line, line_read, MAXLINE - 2);
367         strcat(s->line, "\n");
368     }
369 #else
370     printf("%s", prompt);
371     fflush(stdout);
372     file_get_line(s); /* note: "file" = stdin here */
373 #endif
374 
375     return err;
376 }
377 
cli_get_input_line(ExecState * s)378 static int cli_get_input_line (ExecState *s)
379 {
380     int err = 0;
381 
382     if (s->more != NULL) {
383         /* pick up next concatented statement */
384         memmove(s->line, s->more, strlen(s->more) + 1);
385     } else if (runit || batch) {
386         /* reading from script file */
387         err = file_get_line(s);
388     } else {
389         /* interactive use */
390         err = get_interactive_line(s);
391     }
392 
393     return err;
394 }
395 
396 /* allow for continuation of lines */
397 
maybe_get_input_line_continuation(char * line)398 static int maybe_get_input_line_continuation (char *line)
399 {
400     char tmp[MAXLINE];
401     int contd, err = 0;
402 
403     if (!strncmp(line, "quit", 4)) {
404         return 0;
405     }
406 
407     contd = top_n_tail(line, MAXLINE, &err);
408 
409     while (contd && !err) {
410         *tmp = '\0';
411 
412         if (batch || runit) {
413             char *test = fgets(tmp, MAXLINE, fb);
414 
415             if (test == NULL) {
416                 break;
417             }
418         } else {
419 #ifdef HAVE_READLINE
420             rl_gets(&line_read, "> ");
421             strcpy(tmp, line_read);
422 #else
423             fgets(tmp, MAXLINE, stdin);
424 #endif
425         }
426 
427         if (*tmp != '\0') {
428             if (strlen(line) + strlen(tmp) > MAXLINE - 1) {
429                 err = E_TOOLONG;
430                 break;
431             } else {
432                 strcat(line, tmp);
433                 compress_spaces(line);
434             }
435         }
436         contd = top_n_tail(line, MAXLINE, &err);
437     }
438 
439     return err;
440 }
441 
442 #ifdef G_OS_WIN32
443 
444 /* We're looking at an input line here, either in interactive
445    mode or from file, with line-continuation already applied
446    if required.
447 */
448 
line_ensure_utf8(char * s)449 static int line_ensure_utf8 (char *s)
450 {
451     int err = 0;
452 
453     if (!g_utf8_validate(s, -1, NULL)) {
454         gsize bytes;
455         gchar *tmp = g_locale_to_utf8(s, -1, NULL, &bytes, NULL);
456 
457         if (tmp == NULL) {
458             gretl_errmsg_set("Couldn't convert input to UTF-8");
459             err = E_DATA;
460         } else {
461             *s = '\0';
462             if (strlen(tmp) > MAXLINE - 1) {
463                 err = E_TOOLONG;
464             } else {
465                 strcpy(s, tmp);
466             }
467             g_free(tmp);
468         }
469     }
470 
471     return err;
472 }
473 
win32_get_args(int * pargc,char *** pargv)474 static int win32_get_args (int *pargc, char ***pargv)
475 {
476     int argc_w = 0;
477     LPWSTR *argv_w;
478     int err = 0;
479 
480     /* get command-line arguments as UTF-16 */
481     argv_w = CommandLineToArgvW(GetCommandLineW(), &argc_w);
482 
483     if (argv_w == NULL) {
484         err = 1;
485     } else {
486         /* convert args to UTF-8 */
487         char **argv_u8 = calloc((argc_w + 1), sizeof *argv_u8);
488         int i;
489 
490         for (i=0; i<argc_w && !err; i++) {
491             argv_u8[i] = g_utf16_to_utf8(argv_w[i], -1, NULL, NULL, NULL);
492             if (argv_u8[i] == NULL) {
493                 err = 1;
494             }
495         }
496         *pargc = argc_w;
497         *pargv = argv_u8;
498         /* we're done with this */
499         LocalFree(argv_w);
500     }
501 
502     if (err) {
503         fprintf(stderr, "Failed to get command-line arguments\n");
504         exit(EXIT_FAILURE);
505     }
506 
507     return err;
508 }
509 
console_use_utf8(void)510 static int console_use_utf8 (void)
511 {
512     if (IsValidCodePage(65001)) {
513 	SetConsoleOutputCP(65001);
514     }
515 }
516 
517 #endif
518 
519 static int xout;
520 
521 #ifdef HAVE_RL_DONE
ctrl_x(int count,int key)522 static int ctrl_x (int count, int key)
523 {
524     xout = 1;
525     rl_done = 1;
526     puts("exit");
527     return 0;
528 }
529 #endif
530 
handle_datafile(char * filearg,char * runfile,DATASET * dset,PRN * prn,PRN * cmdprn)531 static void handle_datafile (char *filearg, char *runfile,
532                              DATASET *dset, PRN *prn,
533                              PRN *cmdprn)
534 {
535     char given_file[MAXLEN];
536     int load_datafile = 1;
537     int ftype, err = 0;
538 
539     strcpy(given_file, filearg);
540     strcpy(datafile, filearg);
541 
542     ftype = detect_filetype(datafile, OPT_P);
543 
544     switch (ftype) {
545     case GRETL_UNRECOGNIZED:
546     case GRETL_NATIVE_DB:
547     case GRETL_RATS_DB:
548         exit(EXIT_FAILURE);
549         break;
550     case GRETL_XML_DATA:
551     case GRETL_BINARY_DATA:
552         err = gretl_read_gdt(datafile, dset, OPT_NONE, prn);
553         break;
554     case GRETL_CSV:
555         err = import_csv(datafile, dset, OPT_NONE, prn);
556         break;
557     case GRETL_XLS:
558     case GRETL_GNUMERIC:
559     case GRETL_ODS:
560         err = import_spreadsheet(datafile, ftype, NULL, NULL,
561                                  dset, OPT_NONE, prn);
562         break;
563     case GRETL_DTA:
564     case GRETL_SAV:
565     case GRETL_SAS:
566     case GRETL_JMULTI:
567     case GRETL_OCTAVE:
568     case GRETL_WF1:
569         err = import_other(datafile, ftype, dset,
570                            OPT_NONE, prn);
571         break;
572     case GRETL_SCRIPT:
573         runit = 1;
574         strcpy(runfile, datafile);
575         memset(datafile, 0, sizeof datafile);
576         load_datafile = 0;
577         break;
578     default:
579         break;
580     }
581 
582     if (load_datafile) {
583         if (err) {
584             errmsg(err, prn);
585             if (err == E_FOPEN) {
586                 show_paths();
587             }
588             exit(EXIT_FAILURE);
589         }
590         data_status = 1;
591         if (!batch) {
592             pprintf(cmdprn, "open %s\n", given_file);
593         }
594     }
595 }
596 
check_help_file(void)597 static void check_help_file (void)
598 {
599     const char *hpath = helpfile_path(GRETL_CMDREF, 1, 0);
600     FILE *fp = gretl_fopen(hpath, "r");
601 
602     if (fp != NULL) {
603         printf(_("\n\"help\" gives a list of commands\n"));
604         fclose(fp);
605     } else {
606         printf(_("help file %s is not accessible\n"), hpath);
607         show_paths();
608     }
609 }
610 
main(int argc,char * argv[])611 int main (int argc, char *argv[])
612 {
613     char linecopy[MAXLINE];
614     DATASET *dset = NULL;
615     MODEL *model = NULL;
616     ExecState state;
617     char *line = NULL;
618     int quiet = 0;
619     int tool = 0;
620     int pkgmode = 0;
621     int load_datafile = 1;
622     char filearg[MAXLEN];
623     char runfile[MAXLEN];
624     double scriptval = NADBL;
625     CMD cmd;
626     PRN *prn = NULL;
627     PRN *cmdprn = NULL;
628     int err = 0;
629 
630 #if defined(G_OS_WIN32)
631     win32_get_args(&argc, &argv);
632     console_use_utf8();
633     win32_set_gretldir();
634 #endif
635 
636 #ifdef ENABLE_NLS
637     nls_init();
638 #endif
639 
640 #ifdef HAVE_RL_DONE
641     rl_bind_key(0x18, ctrl_x);
642 #endif
643 
644     dset = datainfo_new();
645     if (dset == NULL) {
646         noalloc();
647     }
648 
649     runfile[0] = filearg[0] = '\0';
650 
651     if (argc < 2) {
652         force_language(LANG_AUTO);
653         load_datafile = 0;
654     } else {
655         gretlopt opt = 0;
656 
657         err = parse_options(&argc, &argv, &opt, &scriptval, filearg);
658 
659         if (err) {
660             /* bad option */
661             usage(1);
662         } else if (opt & (OPT_HELP | OPT_VERSION)) {
663             /* we'll exit in these cases */
664             if (opt & OPT_HELP) {
665                 usage(0);
666             } else {
667                 logo(0);
668                 exit(EXIT_SUCCESS);
669             }
670         }
671 
672         if (opt & (OPT_BATCH | OPT_RUNIT | OPT_MAKEPKG | OPT_INSTPKG)) {
673             if (*filearg == '\0') {
674                 /* we're missing a filename argument */
675                 fprintf(stdout, "No filename given\n");
676                 usage(1);
677             } else if ((opt & OPT_BATCH) && !strcmp(filearg, "-")) {
678                 /* batch mode, but read from stdin */
679                 quiet = batch_stdin = batch = 1;
680                 *runfile = '\0';
681                 load_datafile = 0;
682             } else {
683                 /* record argument (not a datafile) */
684                 strcpy(runfile, filearg);
685                 load_datafile = 0;
686                 if (opt & OPT_BATCH) {
687                     batch = 1;
688                 } else if (opt & OPT_MAKEPKG) {
689                     tool = quiet = batch = 1;
690                     pkgmode = OPT_MAKEPKG;
691                 } else if (opt & OPT_INSTPKG) {
692                     tool = quiet = batch = 1;
693                     pkgmode = OPT_INSTPKG;
694                 } else {
695                     runit = 1;
696                 }
697             }
698         } else if (*filearg == '\0') {
699             load_datafile = 0;
700         }
701 
702         if (opt & OPT_TOOL) {
703             tool = quiet = 1;
704             gretl_set_tool_mode();
705         } else if (opt & OPT_QUIET) {
706             quiet = 1;
707         }
708 
709         if (opt & OPT_ENGLISH) {
710             force_language(LANG_C);
711         } else {
712             force_language(LANG_AUTO);
713         }
714     }
715 
716     libgretl_init();
717 
718     if (!tool) {
719         logo(quiet);
720         if (!quiet) {
721             session_time(NULL);
722         }
723     }
724 
725 #if defined(OPENMP_BUILD) && !defined(WIN32) && !defined(OS_OSX)
726     check_blas_threading(tool, quiet);
727 #endif
728 
729     prn = gretl_print_new(GRETL_PRINT_STDOUT, &err);
730     if (err) {
731         noalloc();
732     }
733 
734     line = malloc(MAXLINE);
735     if (line == NULL) {
736         noalloc();
737     }
738 
739 #ifdef WIN32
740     win32_cli_read_rc();
741 #else
742     cli_read_rc();
743 #endif /* WIN32 */
744 
745     if (!batch && !tool) {
746         strcpy(cmdfile, gretl_workdir());
747         strcat(cmdfile, "session.inp");
748         cmdprn = gretl_print_new_with_filename(cmdfile, &err);
749         if (err) {
750             errmsg(err, prn);
751             return EXIT_FAILURE;
752         }
753     }
754 
755     if (load_datafile) {
756         handle_datafile(filearg, runfile, dset, prn, cmdprn);
757     }
758 
759     /* allocate memory for model */
760     model = allocate_working_model();
761     if (model == NULL) {
762         noalloc();
763     }
764 
765     gretl_cmd_init(&cmd);
766     gretl_exec_state_init(&state, 0, line, &cmd, model, prn);
767     set_debug_read_func(get_interactive_line);
768 
769     /* print list of variables */
770     if (data_status) {
771         list_series(dset, OPT_NONE, prn);
772     }
773 
774     if (!na(scriptval)) {
775         /* define "scriptopt" */
776         gretl_scalar_add("scriptopt", scriptval);
777     }
778 
779     /* misc. interactive-mode setup */
780     if (!batch) {
781         check_help_file();
782         fb = stdin;
783         push_input_file(fb);
784         if (!runit && !data_status) {
785             fputs(_("Type \"open filename\" to open a data set\n"), stdout);
786         }
787     } else if (batch_stdin) {
788         fb = stdin;
789         push_input_file(fb);
790     }
791 
792 #ifdef HAVE_READLINE
793     initialize_readline();
794 #endif
795 
796     if (batch || runit) {
797         /* re-initialize: will be incremented by "run" cmd */
798         runit = 0;
799         if (tool) {
800             set_gretl_echo(0);
801         }
802         if (*runfile != '\0' && pkgmode != OPT_INSTPKG) {
803             if (strchr(runfile, ' ')) {
804                 sprintf(line, "run \"%s\"", runfile);
805             } else {
806                 sprintf(line, "run %s", runfile);
807             }
808             err = cli_exec_line(&state, dset, cmdprn);
809             if (err && fb == NULL) {
810                 exit(EXIT_FAILURE);
811             }
812         }
813     }
814 
815     *linecopy = '\0';
816 
817     /* enter main command loop */
818 
819     while (cmd.ci != QUIT && fb != NULL) {
820         if (err && gretl_error_is_fatal()) {
821             gretl_abort(linecopy);
822         }
823 
824         if (gretl_execute_loop()) {
825             state.cmd->ci = RUNLOOP;
826             err = cli_exec_line(&state, dset, cmdprn);
827             state.cmd->ci = 0;
828         } else {
829             err = cli_get_input_line(&state);
830             if (err) {
831                 errmsg(err, prn);
832                 break;
833             } else if (cmd.ci == QUIT) {
834                 /* no more input available */
835                 cli_exec_line(&state, dset, cmdprn);
836                 if (runit == 0) {
837                     err = gretl_if_state_check(0);
838                     if (err) {
839                         errmsg(err, prn);
840                     }
841                 }
842                 continue;
843             }
844         }
845 
846         if (xout) {
847             /* readline Ctrl-X: get out without saving
848                input or output */
849             gretl_print_destroy(cmdprn);
850             gretl_remove(cmdfile);
851             break;
852         }
853 
854         if (!state.in_comment) {
855             if (cmd.context == FOREIGN || cmd.context == MPI ||
856                 gretl_compiling_python(line)) {
857                 tailstrip(line);
858             } else {
859                 err = maybe_get_input_line_continuation(line);
860                 if (err) {
861                     errmsg(err, prn);
862                     break;
863                 }
864             }
865         }
866 
867 #ifdef G_OS_WIN32
868         line_ensure_utf8(line);
869 #endif
870         strcpy(linecopy, line);
871         tailstrip(linecopy);
872         err = cli_exec_line(&state, dset, cmdprn);
873     }
874 
875     /* finished main command loop */
876 
877     if (!err) {
878         err = gretl_if_state_check(0);
879         if (err) {
880             errmsg(err, prn);
881         }
882     }
883 
884     if (!err && pkgmode) {
885         if (pkgmode == OPT_MAKEPKG) {
886             switch_ext(filearg, runfile, "gfn");
887             sprintf(line, "makepkg %s\n", filearg);
888         } else {
889             if (!isalpha(filearg[0]) || filearg[1] == ':') {
890                 /* some sort of path: install local file */
891                 sprintf(line, "pkg install %s --local\n", filearg);
892             } else {
893                 /* plain filename or http: install from server */
894                 sprintf(line, "pkg install %s\n", filearg);
895             }
896         }
897         cli_exec_line(&state, dset, cmdprn);
898     }
899 
900     /* leak check -- try explicitly freeing all memory allocated */
901 
902     destroy_working_model(model);
903     destroy_dataset(dset);
904 
905     if (fb != stdin && fb != NULL) {
906         fclose(fb);
907     }
908 
909     free(line);
910     gretl_print_destroy(prn);
911     gretl_cmd_free(&cmd);
912     libgretl_cleanup();
913 
914     exit(err ? EXIT_FAILURE : EXIT_SUCCESS);
915 }
916 
printline(const char * s)917 static void printline (const char *s)
918 {
919     if (*s != '\0') {
920         if (gretl_compiling_loop()) {
921             printf("> %s\n", s);
922         } else {
923             printf("%s\n", s);
924         }
925     }
926 }
927 
maybe_abort_open(ExecState * s)928 static int maybe_abort_open (ExecState *s)
929 {
930     if (data_status && !batch) {
931         char response[3];
932 
933         fprintf(stderr, _("Opening a new data file closes the "
934                           "present one.  Proceed? (y/n) "));
935         if (fgets(response, sizeof response, stdin) != NULL &&
936             *response != 'y' && *response != 'Y') {
937             pprintf(s->prn, _("OK, staying with current data set\n"));
938             return 1;
939         }
940     }
941 
942     return 0;
943 }
944 
cli_exec_callback(ExecState * s,void * ptr,GretlObjType type)945 static int cli_exec_callback (ExecState *s, void *ptr,
946                               GretlObjType type)
947 {
948     if (s->cmd->ci == MODELTAB || s->cmd->ci == GRAPHPG) {
949         pprintf(s->prn, _("%s: command not available\n"),
950                 gretl_command_word(s->cmd->ci));
951     } else if (s->cmd->ci == OPEN) {
952         if (type == GRETL_OBJ_DSET) {
953             /* check that "open" is really OK */
954             if (maybe_abort_open(s)) {
955                 return 1;
956             } else {
957 		if (gretl_looping()) {
958 		    s->cmd->opt |= OPT_P;
959 		}
960                 cli_clear_data(s, (DATASET *) ptr);
961             }
962         } else if (type == GRETL_OBJ_ANY) {
963             /* handle successful "open" */
964             OpenOp *op = (OpenOp *) ptr;
965 
966             if (op->fname[0] != '\0') {
967                 strncpy(datafile, op->fname, MAXLEN - 1);
968             }
969             data_status = 1;
970         }
971     }
972 
973     return 0;
974 }
975 
cli_renumber_series(const int * list,const char * parm,DATASET * dset,PRN * prn)976 static int cli_renumber_series (const int *list,
977                                 const char *parm,
978                                 DATASET *dset,
979                                 PRN *prn)
980 {
981     int err, fixmax = highest_numbered_var_in_saved_object(dset);
982 
983     err = renumber_series_with_checks(list, parm, fixmax, dset, prn);
984     if (err) {
985         errmsg(err, prn);
986     }
987 
988     return err;
989 }
990 
maybe_save_session_output(const char * cmdfile)991 static void maybe_save_session_output (const char *cmdfile)
992 {
993     char outfile[FILENAME_MAX];
994 
995     printf(_("type a filename to store output (enter to quit): "));
996 
997     *outfile = '\0';
998 
999     if (fgets(outfile, sizeof outfile, stdin) != NULL) {
1000         top_n_tail(outfile, 0, NULL);
1001     }
1002 
1003     if (*outfile != '\0' && *outfile != '\n' && *outfile != '\r'
1004         && strcmp(outfile, "q")) {
1005         const char *udir = gretl_workdir();
1006         char *syscmd;
1007         int err;
1008 
1009         printf(_("writing session output to %s%s\n"), udir, outfile);
1010 #ifdef WIN32
1011         syscmd = gretl_strdup_printf("\"%sgretlcli\" -b \"%s\" > \"%s%s\"",
1012                                      gretl_home(), cmdfile, udir, outfile);
1013         err = system(syscmd);
1014 #else
1015         syscmd = gretl_strdup_printf("gretlcli -b \"%s\" > \"%s%s\"",
1016                                      cmdfile, udir, outfile);
1017         err = system(syscmd);
1018 #endif
1019         if (!err) {
1020             printf("%s\n", syscmd);
1021         }
1022         free(syscmd);
1023     }
1024 }
1025 
run_include_error(ExecState * s,const char * param,int err,PRN * prn)1026 static int run_include_error (ExecState *s, const char *param,
1027                               int err, PRN *prn)
1028 {
1029     const char *msg = gretl_errmsg_get();
1030 
1031     pprintf(prn, _("Error reading %s\n"), param);
1032     if (*msg != '\0') {
1033         pprintf(prn, "%s\n", msg);
1034     }
1035 
1036     return process_command_error(s, err);
1037 }
1038 
do_quit_message(ExecState * s,int err)1039 static void do_quit_message (ExecState *s, int err)
1040 {
1041     if (gretl_messages_on() && s != NULL && s->prn != NULL) {
1042 	if (err) {
1043 	    pputs(s->prn, _("Terminated on error\n"));
1044 	} else {
1045 	    pputs(s->prn, _("Done\n"));
1046 	}
1047     }
1048 }
1049 
cli_quit(ExecState * s,PRN * cmdprn,int err)1050 static void cli_quit (ExecState *s, PRN *cmdprn, int err)
1051 {
1052     if (runit || batch_stdin) {
1053         *s->runfile = '\0';
1054         runit--;
1055         fclose(fb);
1056         fb = pop_input_file();
1057         if (fb == NULL) {
1058 	    do_quit_message(s, err);
1059         } else {
1060 	    gretl_if_state_reset(indent0);
1061             s->cmd->ci = ENDRUN;
1062         }
1063     } else if (batch && fb == NULL) {
1064 	do_quit_message(s, err);
1065     } else {
1066         gretl_print_destroy(cmdprn);
1067         if (s->cmd->opt & OPT_X) {
1068             gretl_remove(cmdfile);
1069         } else {
1070             printf(_("commands saved as %s\n"), cmdfile);
1071             maybe_save_session_output(cmdfile);
1072         }
1073     }
1074 }
1075 
1076 /* cli_exec_line: this is called to execute both interactive and
1077    script commands.  Note that most commands get passed on to the
1078    libgretl function gretl_cmd_exec(), but some commands that require
1079    special action are dealt with here.
1080 
1081    see also gui_exec_line() in gui2/library.c
1082 */
1083 
cli_exec_line(ExecState * s,DATASET * dset,PRN * cmdprn)1084 static int cli_exec_line (ExecState *s, DATASET *dset, PRN *cmdprn)
1085 {
1086     char *line = s->line;
1087     CMD *cmd = s->cmd;
1088     PRN *prn = s->prn;
1089     int old_runit = runit;
1090     char runfile[MAXLEN];
1091     int renumber = 0;
1092     int err = 0;
1093 
1094     if (cmd->ci == RUNLOOP) {
1095         goto cmd_proceed;
1096     }
1097 
1098 #if 0
1099     fprintf(stderr, "cli_exec_line: '%s'\n", line);
1100 #endif
1101 
1102     if (gretl_compiling_function()) {
1103         err = gretl_function_append_line(s);
1104         if (err) {
1105             errmsg(err, prn);
1106             goto cmd_finish;
1107         } else {
1108             pprintf(cmdprn, "%s\n", line);
1109             return 0;
1110         }
1111     }
1112 
1113     if (string_is_blank(line)) {
1114         return 0;
1115     }
1116 
1117     if (!gretl_compiling_loop() && !s->in_comment &&
1118         !cmd->context && !gretl_if_state_false()) {
1119         /* catch requests relating to saved objects, which are not
1120            really "commands" as such */
1121         int action = cli_saved_object_action(line, dset, prn);
1122 
1123         if (action == OBJ_ACTION_INVALID) {
1124             /* action was faulty */
1125             err = 1;
1126             goto cmd_finish;
1127         } else if (action != OBJ_ACTION_NONE) {
1128             return 0; /* action was OK (and handled), or ignored */
1129         }
1130     }
1131 
1132     /* tell libgretl if we're in batch mode */
1133     gretl_set_batch_mode(batch);
1134 
1135     if (gretl_compiling_loop()) {
1136         /* if we're stacking commands for a loop, parse "lightly" */
1137         err = get_command_index(s, LOOP);
1138     } else {
1139         err = parse_command_line(s, dset, NULL);
1140     }
1141 
1142     if (err) {
1143         int catch = 0;
1144 
1145         gretl_exec_state_uncomment(s);
1146         if (err != E_ALLOC && (cmd->flags & CMD_CATCH)) {
1147             set_gretl_errno(err);
1148             catch = 1;
1149         }
1150         gretl_echo_command(cmd, line, prn);
1151         errmsg(err, prn);
1152         err = catch ? 0 : err;
1153         goto cmd_finish;
1154     }
1155 
1156     gretl_exec_state_transcribe_flags(s, cmd);
1157 
1158     /* if in batch mode, echo comments from input */
1159     if (batch && runit < 2 && cmd->ci == CMD_COMMENT &&
1160         !gretl_if_state_false()) {
1161         if (gretl_echo_on() || gretl_comments_on()) {
1162             printline(linebak);
1163         }
1164     }
1165 
1166     if (cmd->ci < 0) {
1167         /* nothing there, comment, or masked by "if" */
1168         return 0;
1169     }
1170 
1171     if (s->sys != NULL && cmd->ci != END && cmd->ci != EQUATION &&
1172         cmd->ci != SYSTEM) {
1173         printf(_("Command '%s' ignored; not valid within equation system\n"),
1174                line);
1175         equation_system_destroy(s->sys);
1176         s->sys = NULL;
1177         err = 1;
1178         goto cmd_finish;
1179     }
1180 
1181     if (cmd->ci == LOOP && !batch && !runit) {
1182         pputs(prn, _("Enter commands for loop.  "
1183                      "Type 'endloop' to get out\n"));
1184     }
1185 
1186     if (cmd->ci == LOOP || gretl_compiling_loop()) {
1187         /* accumulating loop commands */
1188         if (gretl_echo_on() && (!gretl_compiling_loop() || batch || runit)) {
1189             /* straight visual echo */
1190             gretl_echo_command(cmd, line, prn);
1191         }
1192         err = gretl_loop_append_line(s, dset);
1193         if (err) {
1194             errmsg(err, prn);
1195         } else if (!batch && !runit) {
1196             gretl_record_command(cmd, line, cmdprn);
1197         }
1198         goto cmd_finish;
1199     }
1200 
1201     if (gretl_echo_on()) {
1202         /* visual feedback, not recording */
1203         if (cmd->ci == FUNC && runit > 1) {
1204             ; /* don't echo */
1205         } else if (batch || runit) {
1206             gretl_echo_command(cmd, line, prn);
1207         }
1208     }
1209 
1210     check_for_loop_only_options(cmd->ci, cmd->opt, prn);
1211 
1212  cmd_proceed:
1213 
1214     gretl_exec_state_set_callback(s, cli_exec_callback, OPT_NONE);
1215 
1216     switch (cmd->ci) {
1217 
1218     case DELEET:
1219         err = gretl_delete_variables(cmd->list, cmd->param,
1220                                      cmd->opt, dset, &renumber,
1221                                      prn);
1222         if (err) {
1223             errmsg(err, prn);
1224         } else if (renumber && !batch) {
1225             pputs(prn, _("Take note: variables have been renumbered"));
1226             pputc(prn, '\n');
1227             maybe_list_series(dset, prn);
1228         }
1229         if (err && cmd->flags & CMD_CATCH) {
1230             cmd->flags ^= CMD_CATCH;
1231             err = 0;
1232         }
1233         break;
1234 
1235     case HELP:
1236         cli_help(cmd->param, cmd->parm2, cmd->opt, NULL, prn);
1237         break;
1238 
1239     case NULLDATA:
1240         if (cmd->order < 1) {
1241             err = 1;
1242             pputs(prn, _("Data series length count missing or invalid\n"));
1243         } else {
1244             cli_clear_data(s, dset);
1245             err = open_nulldata(dset, data_status, cmd->order,
1246                                 cmd->opt, prn);
1247             if (err) {
1248                 errmsg(err, prn);
1249             } else {
1250                 data_status = 1;
1251             }
1252         }
1253         break;
1254 
1255     case RUNLOOP:
1256         err = gretl_loop_exec(s, dset, NULL);
1257         break;
1258 
1259     case QUIT:
1260 	gretl_if_state_clear();
1261         cli_quit(s, cmdprn, err);
1262         break;
1263 
1264     case RUN:
1265     case INCLUDE:
1266         if (cmd->ci == INCLUDE) {
1267             err = get_full_filename(cmd->param, runfile, OPT_I);
1268         } else {
1269             err = get_full_filename(cmd->param, runfile, OPT_S);
1270         }
1271         if (err) {
1272             err = run_include_error(s, cmd->param, err, prn);
1273             break;
1274         }
1275         if (gretl_messages_on()) {
1276             pprintf(prn, " %s\n", runfile);
1277         }
1278         if (cmd->ci == INCLUDE && gretl_is_xml_file(runfile)) {
1279             err = load_XML_functions_file(runfile, cmd->opt, prn);
1280             if (err) {
1281                 err = run_include_error(s, runfile, err, prn);
1282             } else {
1283                 pprintf(cmdprn, "include \"%s\"\n", runfile);
1284             }
1285             break;
1286         } else if (cmd->ci == INCLUDE && gfn_is_loaded(runfile)) {
1287             break;
1288         }
1289         if (!strcmp(runfile, s->runfile)) {
1290             pprintf(prn, _("Infinite loop detected in script\n"));
1291             err = 1;
1292             break;
1293         }
1294         if (fb != NULL) {
1295             push_input_file(fb);
1296         }
1297         if ((fb = gretl_fopen(runfile, "r")) == NULL) {
1298             pprintf(prn, _("Error reading %s\n"), runfile);
1299             err = process_command_error(s, E_FOPEN);
1300             fb = pop_input_file();
1301         } else {
1302             strcpy(s->runfile, runfile);
1303             gretl_set_script_dir(runfile);
1304             if (cmd->ci == INCLUDE) {
1305                 pprintf(cmdprn, "include \"%s\"\n", runfile);
1306             } else {
1307                 pprintf(cmdprn, "run \"%s\"\n", runfile);
1308             }
1309             runit++;
1310 	    indent0 = gretl_if_state_record();
1311         }
1312         break;
1313 
1314     case CLEAR:
1315 	err = incompatible_options(cmd->opt, OPT_D | OPT_F);
1316 	if (!err) {
1317 	    if (cmd->opt & OPT_F) {
1318 		gretl_functions_cleanup();
1319 	    } else {
1320 		err = cli_clear_data(s, dset);
1321 	    }
1322 	}
1323         break;
1324 
1325     case DATAMOD:
1326         if (cmd->auxint == DS_CLEAR) {
1327             err = cli_clear_data(s, dset);
1328             pputs(prn, _("Dataset cleared\n"));
1329             break;
1330         } else if (cmd->auxint == DS_RENUMBER) {
1331             err = cli_renumber_series(cmd->list, cmd->parm2, dset, prn);
1332             break;
1333         } else {
1334            err = gretl_cmd_exec(s, dset);
1335         }
1336         break;
1337 
1338     default:
1339         err = gretl_cmd_exec(s, dset);
1340         break;
1341     }
1342 
1343     if (!err && cmd->ci != QUIT && gretl_echo_on() && !batch && !old_runit) {
1344         /* record a successful interactive command */
1345         gretl_record_command(cmd, line, cmdprn);
1346     }
1347 
1348  cmd_finish:
1349 
1350     if (err) {
1351         gretl_exec_state_uncomment(s);
1352         if ((runit || batch) && cmd->ci != QUIT) {
1353             cli_quit(s, cmdprn, err);
1354         }
1355     }
1356 
1357     return err;
1358 }
1359 
1360 /* apparatus for keeping track of input stream */
1361 
1362 #define N_STACKED_FILES 8
1363 
1364 static int nfiles;
1365 static FILE *fstack[N_STACKED_FILES];
1366 
push_input_file(FILE * fp)1367 static int push_input_file (FILE *fp)
1368 {
1369     int err = 0;
1370 
1371     if (nfiles >= N_STACKED_FILES) {
1372         err = 1;
1373     } else {
1374         fstack[nfiles++] = fp;
1375     }
1376 
1377     return err;
1378 }
1379 
pop_input_file(void)1380 static FILE *pop_input_file (void)
1381 {
1382     FILE *ret = NULL;
1383 
1384     if (nfiles > 0) {
1385         ret = fstack[--nfiles];
1386     }
1387 
1388     return ret;
1389 }
1390 
1391 #include "cli_object.c"
1392