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