command: Fix delayed execution of FINISH.
[pspp] / src / language / command.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 1997-9, 2000, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc.
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
16
17 #include <config.h>
18
19 #include "language/command.h"
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <ctype.h>
24 #include <errno.h>
25
26 #include "data/casereader.h"
27 #include "data/dataset.h"
28 #include "data/dictionary.h"
29 #include "data/session.h"
30 #include "data/settings.h"
31 #include "data/variable.h"
32 #include "language/lexer/command-name.h"
33 #include "language/lexer/lexer.h"
34 #include "libpspp/assertion.h"
35 #include "libpspp/compiler.h"
36 #include "libpspp/i18n.h"
37 #include "libpspp/message.h"
38 #include "libpspp/str.h"
39 #include "output/text-item.h"
40
41 #include "xalloc.h"
42 #include "xmalloca.h"
43
44 #include "gettext.h"
45 #define _(msgid) gettext (msgid)
46 #define N_(msgid) msgid
47 \f
48 /* Returns true if RESULT is a valid "enum cmd_result",
49    false otherwise. */
50 static inline bool
51 cmd_result_is_valid (enum cmd_result result)
52 {
53   switch (result)
54     {
55     case CMD_SUCCESS:
56     case CMD_EOF:
57     case CMD_FINISH:
58     case CMD_DATA_LIST:
59     case CMD_END_CASE:
60     case CMD_END_FILE:
61     case CMD_FAILURE:
62     case CMD_NOT_IMPLEMENTED:
63     case CMD_CASCADING_FAILURE:
64       return true;
65
66     default:
67       return false;
68     }
69 }
70
71 /* Returns true if RESULT indicates success,
72    false otherwise. */
73 bool
74 cmd_result_is_success (enum cmd_result result)
75 {
76   assert (cmd_result_is_valid (result));
77   return result > 0;
78 }
79
80 /* Returns true if RESULT indicates failure,
81    false otherwise. */
82 bool
83 cmd_result_is_failure (enum cmd_result result)
84 {
85   assert (cmd_result_is_valid (result));
86   return result < 0;
87 }
88 \f
89 /* Command processing states. */
90 enum states
91   {
92     S_INITIAL = 0x01,         /* Allowed before active dataset defined. */
93     S_DATA = 0x02,            /* Allowed after active dataset defined. */
94     S_INPUT_PROGRAM = 0x04,   /* Allowed in INPUT PROGRAM. */
95     S_FILE_TYPE = 0x08,       /* Allowed in FILE TYPE. */
96     S_ANY = 0x0f              /* Allowed anywhere. */
97   };
98
99 /* Other command requirements. */
100 enum flags
101   {
102     F_ENHANCED = 0x10,        /* Allowed only in enhanced syntax mode. */
103     F_TESTING = 0x20,         /* Allowed only in testing mode. */
104     F_ABBREV = 0x80           /* Not a candidate for name completion. */
105   };
106
107 /* A single command. */
108 struct command
109   {
110     enum states states;         /* States in which command is allowed. */
111     enum flags flags;           /* Other command requirements. */
112     const char *name;           /* Command name. */
113     int (*function) (struct lexer *, struct dataset *); /* Function to call. */
114   };
115
116 /* Define the command array. */
117 #define DEF_CMD(STATES, FLAGS, NAME, FUNCTION) {STATES, FLAGS, NAME, FUNCTION},
118 #define UNIMPL_CMD(NAME, DESCRIPTION) {S_ANY, 0, NAME, NULL},
119 static const struct command commands[] =
120   {
121 #include "command.def"
122   };
123 #undef DEF_CMD
124 #undef UNIMPL_CMD
125
126 static const size_t command_cnt = sizeof commands / sizeof *commands;
127
128 static bool in_correct_state (const struct command *, enum cmd_state);
129 static bool report_state_mismatch (const struct command *, enum cmd_state);
130 static void set_completion_state (enum cmd_state);
131 \f
132 /* Command parser. */
133
134 static const struct command *parse_command_name (struct lexer *,
135                                                  int *n_tokens);
136 static enum cmd_result do_parse_command (struct lexer *, struct dataset *, enum cmd_state);
137
138 /* Parses an entire command, from command name to terminating
139    dot.  On failure, skips to the terminating dot.
140    Returns the command's success or failure result. */
141 enum cmd_result
142 cmd_parse_in_state (struct lexer *lexer, struct dataset *ds,
143                     enum cmd_state state)
144 {
145   struct session *session = dataset_session (ds);
146   int result;
147
148   result = do_parse_command (lexer, ds, state);
149
150   ds = session_active_dataset (session);
151   assert (!proc_is_open (ds));
152   unset_cmd_algorithm ();
153   if (!dataset_end_of_command (ds))
154     result = CMD_CASCADING_FAILURE;
155
156   return result;
157 }
158
159 enum cmd_result
160 cmd_parse (struct lexer *lexer, struct dataset *ds)
161 {
162   const struct dictionary *dict = dataset_dict (ds);
163   return cmd_parse_in_state (lexer, ds,
164                              dataset_has_source (ds) &&
165                              dict_get_var_cnt (dict) > 0 ?
166                              CMD_STATE_DATA : CMD_STATE_INITIAL);
167 }
168
169
170 /* Parses an entire command, from command name to terminating
171    dot. */
172 static enum cmd_result
173 do_parse_command (struct lexer *lexer,
174                   struct dataset *ds, enum cmd_state state)
175 {
176   const struct command *command = NULL;
177   enum cmd_result result;
178   bool opened = false;
179   int n_tokens;
180
181   /* Read the command's first token. */
182   set_completion_state (state);
183   if (lex_token (lexer) == T_STOP)
184     {
185       result = CMD_EOF;
186       goto finish;
187     }
188   else if (lex_token (lexer) == T_ENDCMD)
189     {
190       /* Null commands can result from extra empty lines. */
191       result = CMD_SUCCESS;
192       goto finish;
193     }
194
195   /* Parse the command name. */
196   command = parse_command_name (lexer, &n_tokens);
197   if (command == NULL)
198     {
199       result = CMD_FAILURE;
200       goto finish;
201     }
202   text_item_submit (text_item_create (TEXT_ITEM_COMMAND_OPEN, command->name));
203   opened = true;
204
205   if (command->function == NULL)
206     {
207       msg (SE, _("%s is not yet implemented."), command->name);
208       result = CMD_NOT_IMPLEMENTED;
209     }
210   else if ((command->flags & F_TESTING) && !settings_get_testing_mode ())
211     {
212       msg (SE, _("%s may be used only in testing mode."), command->name);
213       result = CMD_FAILURE;
214     }
215   else if ((command->flags & F_ENHANCED) && settings_get_syntax () != ENHANCED)
216     {
217       msg (SE, _("%s may be used only in enhanced syntax mode."),
218            command->name);
219       result = CMD_FAILURE;
220     }
221   else if (!in_correct_state (command, state))
222     {
223       report_state_mismatch (command, state);
224       result = CMD_FAILURE;
225     }
226   else
227     {
228       /* Execute command. */
229       int i;
230
231       for (i = 0; i < n_tokens; i++)
232         lex_get (lexer);
233       result = command->function (lexer, ds);
234     }
235
236   assert (cmd_result_is_valid (result));
237
238 finish:
239   if (cmd_result_is_failure (result))
240     lex_interactive_reset (lexer);
241   else if (result == CMD_SUCCESS)
242     result = lex_end_of_command (lexer);
243
244   lex_discard_rest_of_command (lexer);
245   if (result != CMD_EOF && result != CMD_FINISH)
246     while (lex_token (lexer) == T_ENDCMD)
247       lex_get (lexer);
248
249   if (opened)
250     text_item_submit (text_item_create (TEXT_ITEM_COMMAND_CLOSE,
251                                         command->name));
252
253   return result;
254 }
255
256 static int
257 find_best_match (struct substring s, const struct command **matchp)
258 {
259   const struct command *cmd;
260   struct command_matcher cm;
261   int missing_words;
262
263   command_matcher_init (&cm, s);
264   for (cmd = commands; cmd < &commands[command_cnt]; cmd++)
265     command_matcher_add (&cm, ss_cstr (cmd->name), CONST_CAST (void *, cmd));
266
267   *matchp = command_matcher_get_match (&cm);
268   missing_words = command_matcher_get_missing_words (&cm);
269
270   command_matcher_destroy (&cm);
271
272   return missing_words;
273 }
274
275 static bool
276 parse_command_word (struct lexer *lexer, struct string *s, int n)
277 {
278   bool need_space = ds_last (s) != EOF && ds_last (s) != '-';
279
280   switch (lex_next_token (lexer, n))
281     {
282     case T_DASH:
283       ds_put_byte (s, '-');
284       return true;
285
286     case T_ID:
287       if (need_space)
288         ds_put_byte (s, ' ');
289       ds_put_cstr (s, lex_next_tokcstr (lexer, n));
290       return true;
291
292     case T_POS_NUM:
293       if (lex_next_is_integer (lexer, n))
294         {
295           int integer = lex_next_integer (lexer, n);
296           if (integer >= 0)
297             {
298               if (need_space)
299                 ds_put_byte (s, ' ');
300               ds_put_format (s, "%ld", lex_next_integer (lexer, n));
301               return true;
302             }
303         }
304       return false;
305
306     default:
307       return false;
308     }
309 }
310
311 /* Parses the command name.  On success returns a pointer to the corresponding
312    struct command and stores the number of tokens in the command name into
313    *N_TOKENS.  On failure, returns a null pointer and stores the number of
314    tokens required to determine that no command name was present into
315    *N_TOKENS. */
316 static const struct command *
317 parse_command_name (struct lexer *lexer, int *n_tokens)
318 {
319   const struct command *command;
320   int missing_words;
321   struct string s;
322   int word;
323
324   command = NULL;
325   missing_words = 0;
326   ds_init_empty (&s);
327   word = 0;
328   while (parse_command_word (lexer, &s, word))
329     {
330       missing_words = find_best_match (ds_ss (&s), &command);
331       if (missing_words <= 0)
332         break;
333       word++;
334     }
335
336   if (command == NULL && missing_words > 0)
337     {
338       ds_put_cstr (&s, " .");
339       missing_words = find_best_match (ds_ss (&s), &command);
340       ds_truncate (&s, ds_length (&s) - 2);
341     }
342
343   if (command == NULL)
344     {
345       if (ds_is_empty (&s))
346         lex_error (lexer, _("expecting command name"));
347       else
348         msg (SE, _("Unknown command `%s'."), ds_cstr (&s));
349     }
350
351   ds_destroy (&s);
352
353   *n_tokens = (word + 1) + missing_words;
354   return command;
355 }
356
357 /* Returns true if COMMAND is allowed in STATE,
358    false otherwise. */
359 static bool
360 in_correct_state (const struct command *command, enum cmd_state state)
361 {
362   return ((state == CMD_STATE_INITIAL && command->states & S_INITIAL)
363           || (state == CMD_STATE_DATA && command->states & S_DATA)
364           || (state == CMD_STATE_INPUT_PROGRAM
365               && command->states & S_INPUT_PROGRAM)
366           || (state == CMD_STATE_FILE_TYPE && command->states & S_FILE_TYPE));
367 }
368
369 /* Emits an appropriate error message for trying to invoke
370    COMMAND in STATE. */
371 static bool
372 report_state_mismatch (const struct command *command, enum cmd_state state)
373 {
374   assert (!in_correct_state (command, state));
375   if (state == CMD_STATE_INITIAL || state == CMD_STATE_DATA)
376     {
377       switch ((int) command->states)
378         {
379           /* One allowed state. */
380         case S_INITIAL:
381           msg (SE, _("%s is allowed only before the active dataset has "
382                      "been defined."), command->name);
383           break;
384         case S_DATA:
385           msg (SE, _("%s is allowed only after the active dataset has "
386                      "been defined."), command->name);
387           break;
388         case S_INPUT_PROGRAM:
389           msg (SE, _("%s is allowed only inside %s."),
390                command->name, "INPUT PROGRAM");
391           break;
392         case S_FILE_TYPE:
393           msg (SE, _("%s is allowed only inside %s."), command->name, "FILE TYPE");
394           break;
395
396           /* Two allowed states. */
397         case S_INITIAL | S_DATA:
398           NOT_REACHED ();
399         case S_INITIAL | S_INPUT_PROGRAM:
400           msg (SE, _("%s is allowed only before the active dataset has been defined or inside %s."),
401                command->name, "INPUT PROGRAM");
402           break;
403         case S_INITIAL | S_FILE_TYPE:
404           msg (SE, _("%s is allowed only before the active dataset has been defined or inside %s."),
405                command->name, "FILE TYPE");
406           break;
407         case S_DATA | S_INPUT_PROGRAM:
408           msg (SE, _("%s is allowed only after the active dataset has been defined or inside %s."),
409                command->name, "INPUT PROGRAM");
410           break;
411         case S_DATA | S_FILE_TYPE:
412           msg (SE, _("%s is allowed only after the active dataset has been defined or inside %s."),
413                command->name, "FILE TYPE");
414           break;
415         case S_INPUT_PROGRAM | S_FILE_TYPE:
416           msg (SE, _("%s is allowed only inside %s or inside %s."), command->name, 
417                "INPUT PROGRAM", "FILE TYPE");
418           break;
419
420           /* Three allowed states. */
421         case S_DATA | S_INPUT_PROGRAM | S_FILE_TYPE:
422           msg (SE, _("%s is allowed only after the active dataset has "
423                      "been defined, inside INPUT PROGRAM, or inside "
424                      "FILE TYPE."), command->name);
425           break;
426         case S_INITIAL | S_INPUT_PROGRAM | S_FILE_TYPE:
427           msg (SE, _("%s is allowed only before the active dataset has "
428                      "been defined, inside INPUT PROGRAM, or inside "
429                      "FILE TYPE."), command->name);
430           break;
431         case S_INITIAL | S_DATA | S_FILE_TYPE:
432           NOT_REACHED ();
433         case S_INITIAL | S_DATA | S_INPUT_PROGRAM:
434           NOT_REACHED ();
435
436           /* Four allowed states. */
437         case S_INITIAL | S_DATA | S_INPUT_PROGRAM | S_FILE_TYPE:
438           NOT_REACHED ();
439
440         default:
441           NOT_REACHED ();
442         }
443     }
444   else if (state == CMD_STATE_INPUT_PROGRAM)
445     msg (SE, _("%s is not allowed inside %s."),
446          command->name, "INPUT PROGRAM" );
447   else if (state == CMD_STATE_FILE_TYPE)
448     msg (SE, _("%s is not allowed inside %s."), command->name, "FILE TYPE");
449
450   return false;
451 }
452 \f
453 /* Command name completion. */
454
455 static enum cmd_state completion_state = CMD_STATE_INITIAL;
456
457 static void
458 set_completion_state (enum cmd_state state)
459 {
460   completion_state = state;
461 }
462
463 /* Returns the next possible completion of a command name that
464    begins with PREFIX, in the current command state, or a null
465    pointer if no completions remain.
466    Before calling the first time, set *CMD to a null pointer. */
467 const char *
468 cmd_complete (const char *prefix, const struct command **cmd)
469 {
470   if (*cmd == NULL)
471     *cmd = commands;
472
473   for (; *cmd < commands + command_cnt; (*cmd)++)
474     if (!memcasecmp ((*cmd)->name, prefix, strlen (prefix))
475         && (!((*cmd)->flags & F_TESTING) || settings_get_testing_mode ())
476         && (!((*cmd)->flags & F_ENHANCED) || settings_get_syntax () == ENHANCED)
477         && !((*cmd)->flags & F_ABBREV)
478         && ((*cmd)->function != NULL)
479         && in_correct_state (*cmd, completion_state))
480       return (*cmd)++->name;
481
482   return NULL;
483 }
484 \f
485 /* Simple commands. */
486
487 /* Parse and execute FINISH command. */
488 int
489 cmd_finish (struct lexer *lexer UNUSED, struct dataset *ds UNUSED)
490 {
491   return CMD_FINISH;
492 }
493
494 /* Parses the N command. */
495 int
496 cmd_n_of_cases (struct lexer *lexer, struct dataset *ds)
497 {
498   /* Value for N. */
499   int x;
500
501   if (!lex_force_int (lexer))
502     return CMD_FAILURE;
503   x = lex_integer (lexer);
504   lex_get (lexer);
505   if (!lex_match_id (lexer, "ESTIMATED"))
506     dict_set_case_limit (dataset_dict (ds), x);
507
508   return CMD_SUCCESS;
509 }
510
511 /* Parses, performs the EXECUTE procedure. */
512 int
513 cmd_execute (struct lexer *lexer UNUSED, struct dataset *ds)
514 {
515   bool ok = casereader_destroy (proc_open (ds));
516   if (!proc_commit (ds) || !ok)
517     return CMD_CASCADING_FAILURE;
518   return CMD_SUCCESS;
519 }
520
521 /* Parses, performs the ERASE command. */
522 int
523 cmd_erase (struct lexer *lexer, struct dataset *ds UNUSED)
524 {
525   char *filename;
526   int retval;
527
528   if (settings_get_safer_mode ())
529     {
530       msg (SE, _("This command not allowed when the %s option is set."), "SAFER");
531       return CMD_FAILURE;
532     }
533
534   if (!lex_force_match_id (lexer, "FILE"))
535     return CMD_FAILURE;
536   lex_match (lexer, T_EQUALS);
537   if (!lex_force_string (lexer))
538     return CMD_FAILURE;
539
540   filename = utf8_to_filename (lex_tokcstr (lexer));
541   retval = remove (filename);
542   free (filename);
543
544   if (retval == -1)
545     {
546       msg (SW, _("Error removing `%s': %s."),
547            lex_tokcstr (lexer), strerror (errno));
548       return CMD_FAILURE;
549     }
550   lex_get (lexer);
551
552   return CMD_SUCCESS;
553 }
554
555 /* Parses, performs the NEW FILE command. */
556 int
557 cmd_new_file (struct lexer *lexer UNUSED, struct dataset *ds)
558 {
559   dataset_clear (ds);
560   return CMD_SUCCESS;
561 }