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