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