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