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