803b5398888dec3c739c748afa8c13059d272ec3
[pspp-builds.git] / src / language / command.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 1997-9, 2000, 2009 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 #include <unistd.h>
26 #if HAVE_SYS_WAIT_H
27 #include <sys/wait.h>
28 #endif
29 #if HAVE_READLINE
30 #include <readline/readline.h>
31 #endif
32
33 #include <data/casereader.h>
34 #include <data/dictionary.h>
35 #include <data/procedure.h>
36 #include <data/settings.h>
37 #include <data/variable.h>
38 #include <language/lexer/lexer.h>
39 #include <language/prompt.h>
40 #include <libpspp/assertion.h>
41 #include <libpspp/compiler.h>
42 #include <libpspp/message.h>
43 #include <libpspp/message.h>
44 #include <libpspp/str.h>
45 #include <libpspp/getl.h>
46 #include <output/text-item.h>
47
48 #include "xalloc.h"
49 #include "xmalloca.h"
50
51 #include "gettext.h"
52 #define _(msgid) gettext (msgid)
53 #define N_(msgid) msgid
54 \f
55 /* Returns true if RESULT is a valid "enum cmd_result",
56    false otherwise. */
57 static inline bool
58 cmd_result_is_valid (enum cmd_result result)
59 {
60   return (result == CMD_SUCCESS || result == CMD_EOF || result == CMD_FINISH
61           || (result >= CMD_PRIVATE_FIRST && result <= CMD_PRIVATE_LAST)
62           || result == CMD_FAILURE || result == CMD_NOT_IMPLEMENTED
63           || result == CMD_CASCADING_FAILURE);
64 }
65
66 /* Returns true if RESULT indicates success,
67    false otherwise. */
68 bool
69 cmd_result_is_success (enum cmd_result result)
70 {
71   assert (cmd_result_is_valid (result));
72   return result > 0;
73 }
74
75 /* Returns true if RESULT indicates failure,
76    false otherwise. */
77 bool
78 cmd_result_is_failure (enum cmd_result result)
79 {
80   assert (cmd_result_is_valid (result));
81   return result < 0;
82 }
83 \f
84 /* Command processing states. */
85 enum states
86   {
87     S_INITIAL = 0x01,         /* Allowed before active file defined. */
88     S_DATA = 0x02,            /* Allowed after active file defined. */
89     S_INPUT_PROGRAM = 0x04,   /* Allowed in INPUT PROGRAM. */
90     S_FILE_TYPE = 0x08,       /* Allowed in FILE TYPE. */
91     S_ANY = 0x0f              /* Allowed anywhere. */
92   };
93
94 /* Other command requirements. */
95 enum flags
96   {
97     F_ENHANCED = 0x10,        /* Allowed only in enhanced syntax mode. */
98     F_TESTING = 0x20,         /* Allowed only in testing mode. */
99     F_KEEP_FINAL_TOKEN = 0x40,/* Don't skip final token in command name. */
100     F_ABBREV = 0x80           /* Not a candidate for name completion. */
101   };
102
103 /* A single command. */
104 struct command
105   {
106     enum states states;         /* States in which command is allowed. */
107     enum flags flags;           /* Other command requirements. */
108     const char *name;           /* Command name. */
109     int (*function) (struct lexer *, struct dataset *); /* Function to call. */
110   };
111
112 /* Define the command array. */
113 #define DEF_CMD(STATES, FLAGS, NAME, FUNCTION) {STATES, FLAGS, NAME, FUNCTION},
114 #define UNIMPL_CMD(NAME, DESCRIPTION) {S_ANY, 0, NAME, NULL},
115 static const struct command commands[] =
116   {
117 #include "command.def"
118   };
119 #undef DEF_CMD
120 #undef UNIMPL_CMD
121
122 static const size_t command_cnt = sizeof commands / sizeof *commands;
123
124 static bool in_correct_state (const struct command *, enum cmd_state);
125 static bool report_state_mismatch (const struct command *, enum cmd_state);
126 static const struct command *find_command (const char *name);
127 static void set_completion_state (enum cmd_state);
128 \f
129 /* Command parser. */
130
131 static const struct command *parse_command_name (struct lexer *lexer);
132 static enum cmd_result do_parse_command (struct lexer *, struct dataset *, enum cmd_state);
133
134 /* Parses an entire command, from command name to terminating
135    dot.  On failure, skips to the terminating dot.
136    Returns the command's success or failure result. */
137 enum cmd_result
138 cmd_parse_in_state (struct lexer *lexer, struct dataset *ds,
139                     enum cmd_state state)
140 {
141   int result;
142
143   result = do_parse_command (lexer, ds, state);
144
145   assert (!proc_is_open (ds));
146   unset_cmd_algorithm ();
147   dict_clear_aux (dataset_dict (ds));
148   if (!dataset_end_of_command (ds))
149     result = CMD_CASCADING_FAILURE;
150
151   return result;
152 }
153
154 enum cmd_result
155 cmd_parse (struct lexer *lexer, struct dataset *ds)
156 {
157   const struct dictionary *dict = dataset_dict (ds);
158   return cmd_parse_in_state (lexer, ds,
159                              proc_has_active_file (ds) &&
160                              dict_get_var_cnt (dict) > 0 ?
161                              CMD_STATE_DATA : CMD_STATE_INITIAL);
162 }
163
164
165 /* Parses an entire command, from command name to terminating
166    dot. */
167 static enum cmd_result
168 do_parse_command (struct lexer *lexer,
169                   struct dataset *ds, enum cmd_state state)
170 {
171   const struct command *command = NULL;
172   enum cmd_result result;
173   bool opened = false;
174
175   /* Read the command's first token. */
176   prompt_set_style (PROMPT_FIRST);
177   set_completion_state (state);
178   lex_get (lexer);
179   if (lex_token (lexer) == T_STOP)
180     {
181       result = CMD_EOF;
182       goto finish;
183     }
184   else if (lex_token (lexer) == '.')
185     {
186       /* Null commands can result from extra empty lines. */
187       result = CMD_SUCCESS;
188       goto finish;
189     }
190
191   prompt_set_style (PROMPT_LATER);
192
193   /* Parse the command name. */
194   command = parse_command_name (lexer);
195   if (command == NULL)
196     {
197       result = CMD_FAILURE;
198       goto finish;
199     }
200   text_item_submit (text_item_create (TEXT_ITEM_COMMAND_OPEN, command->name));
201   opened = true;
202
203   if (command->function == NULL)
204     {
205       msg (SE, _("%s is not yet implemented."), command->name);
206       result = CMD_NOT_IMPLEMENTED;
207     }
208   else if ((command->flags & F_TESTING) && !settings_get_testing_mode ())
209     {
210       msg (SE, _("%s may be used only in testing mode."), command->name);
211       result = CMD_FAILURE;
212     }
213   else if ((command->flags & F_ENHANCED) && settings_get_syntax () != ENHANCED)
214     {
215       msg (SE, _("%s may be used only in enhanced syntax mode."),
216            command->name);
217       result = CMD_FAILURE;
218     }
219   else if (!in_correct_state (command, state))
220     {
221       report_state_mismatch (command, state);
222       result = CMD_FAILURE;
223     }
224   else
225     {
226       /* Execute command. */
227       msg_set_command_name (command->name);
228       result = command->function (lexer, ds);
229       msg_set_command_name (NULL);
230     }
231
232   assert (cmd_result_is_valid (result));
233
234  finish:
235   if (cmd_result_is_failure (result))
236     {
237       lex_discard_rest_of_command (lexer);
238       if (source_stream_current_error_mode (
239             lex_get_source_stream (lexer)) == ERRMODE_STOP )
240         {
241           msg (MW, _("Error encountered while ERROR=STOP is effective."));
242           result = CMD_CASCADING_FAILURE;
243         }
244     }
245
246   if (opened)
247     text_item_submit (text_item_create (TEXT_ITEM_COMMAND_CLOSE,
248                                         command->name));
249
250   return result;
251 }
252
253 static size_t
254 match_strings (const char *a, size_t a_len,
255                const char *b, size_t b_len)
256 {
257   size_t match_len = 0;
258
259   while (a_len > 0 && b_len > 0)
260     {
261       /* Mismatch always returns zero. */
262       if (toupper ((unsigned char) *a++) != toupper ((unsigned char) *b++))
263         return 0;
264
265       /* Advance. */
266       a_len--;
267       b_len--;
268       match_len++;
269     }
270
271   return match_len;
272 }
273
274 /* Returns the first character in the first word in STRING,
275    storing the word's length in *WORD_LEN.  If no words remain,
276    returns a null pointer and stores 0 in *WORD_LEN.  Words are
277    sequences of alphanumeric characters or single
278    non-alphanumeric characters.  Words are delimited by
279    spaces. */
280 static const char *
281 find_word (const char *string, size_t *word_len)
282 {
283   /* Skip whitespace and asterisks. */
284   while (isspace ((unsigned char) *string))
285     string++;
286
287   /* End of string? */
288   if (*string == '\0')
289     {
290       *word_len = 0;
291       return NULL;
292     }
293
294   /* Special one-character word? */
295   if (!isalnum ((unsigned char) *string))
296     {
297       *word_len = 1;
298       return string;
299     }
300
301   /* Alphanumeric word. */
302   *word_len = 1;
303   while (isalnum ((unsigned char) string[*word_len]))
304     (*word_len)++;
305
306   return string;
307 }
308
309 /* Returns true if strings A and B can be confused based on
310    their first three letters. */
311 static bool
312 conflicting_3char_prefixes (const char *a, const char *b)
313 {
314   size_t aw_len, bw_len;
315   const char *aw, *bw;
316
317   aw = find_word (a, &aw_len);
318   bw = find_word (b, &bw_len);
319   assert (aw != NULL && bw != NULL);
320
321   /* Words that are the same don't conflict. */
322   if (aw_len == bw_len && !buf_compare_case (aw, bw, aw_len))
323     return false;
324
325   /* Words that are otherwise the same in the first three letters
326      do conflict. */
327   return ((aw_len > 3 && bw_len > 3)
328           || (aw_len == 3 && bw_len > 3)
329           || (bw_len == 3 && aw_len > 3)) && !buf_compare_case (aw, bw, 3);
330 }
331
332 /* Returns true if CMD can be confused with another command
333    based on the first three letters of its first word. */
334 static bool
335 conflicting_3char_prefix_command (const struct command *cmd)
336 {
337   assert (cmd >= commands && cmd < commands + command_cnt);
338
339   return ((cmd > commands
340            && conflicting_3char_prefixes (cmd[-1].name, cmd[0].name))
341           || (cmd < commands + command_cnt
342               && conflicting_3char_prefixes (cmd[0].name, cmd[1].name)));
343 }
344
345 /* Ways that a set of words can match a command name. */
346 enum command_match
347   {
348     MISMATCH,           /* Not a match. */
349     PARTIAL_MATCH,      /* The words begin the command name. */
350     COMPLETE_MATCH      /* The words are the command name. */
351   };
352
353 /* Figures out how well the WORD_CNT words in WORDS match CMD,
354    and returns the appropriate enum value.  If WORDS are a
355    partial match for CMD and the next word in CMD is a dash, then
356    *DASH_POSSIBLE is set to 1 if DASH_POSSIBLE is non-null;
357    otherwise, *DASH_POSSIBLE is unchanged. */
358 static enum command_match
359 cmd_match_words (const struct command *cmd,
360                  char *const words[], size_t word_cnt,
361                  int *dash_possible)
362 {
363   const char *word;
364   size_t word_len;
365   size_t word_idx;
366
367   for (word = find_word (cmd->name, &word_len), word_idx = 0;
368        word != NULL && word_idx < word_cnt;
369        word = find_word (word + word_len, &word_len), word_idx++)
370     if (word_len != strlen (words[word_idx])
371         || buf_compare_case (word, words[word_idx], word_len))
372       {
373         size_t match_chars = match_strings (word, word_len,
374                                             words[word_idx],
375                                             strlen (words[word_idx]));
376         if (match_chars == 0)
377           {
378             /* Mismatch. */
379             return MISMATCH;
380           }
381         else if (match_chars == 1 || match_chars == 2)
382           {
383             /* One- and two-character abbreviations are not
384                acceptable. */
385             return MISMATCH;
386           }
387         else if (match_chars == 3)
388           {
389             /* Three-character abbreviations are acceptable
390                in the first word of a command if there are
391                no name conflicts.  They are always
392                acceptable after the first word. */
393             if (word_idx == 0 && conflicting_3char_prefix_command (cmd))
394               return MISMATCH;
395           }
396         else /* match_chars > 3 */
397           {
398             /* Four-character and longer abbreviations are
399                always acceptable.  */
400           }
401       }
402
403   if (word == NULL && word_idx == word_cnt)
404     {
405       /* cmd->name = "FOO BAR", words[] = {"FOO", "BAR"}. */
406       return COMPLETE_MATCH;
407     }
408   else if (word == NULL)
409     {
410       /* cmd->name = "FOO BAR", words[] = {"FOO", "BAR", "BAZ"}. */
411       return MISMATCH;
412     }
413   else
414     {
415       /* cmd->name = "FOO BAR BAZ", words[] = {"FOO", "BAR"}. */
416       if (word[0] == '-' && dash_possible != NULL)
417         *dash_possible = 1;
418       return PARTIAL_MATCH;
419     }
420 }
421
422 /* Returns the number of commands for which the WORD_CNT words in
423    WORDS are a partial or complete match.  If some partial match
424    has a dash as the next word, then *DASH_POSSIBLE is set to 1,
425    otherwise it is set to 0. */
426 static int
427 count_matching_commands (char *const words[], size_t word_cnt,
428                          int *dash_possible)
429 {
430   const struct command *cmd;
431   int cmd_match_count;
432
433   cmd_match_count = 0;
434   *dash_possible = 0;
435   for (cmd = commands; cmd < commands + command_cnt; cmd++)
436     if (cmd_match_words (cmd, words, word_cnt, dash_possible) != MISMATCH)
437       cmd_match_count++;
438
439   return cmd_match_count;
440 }
441
442 /* Returns the command for which the WORD_CNT words in WORDS are
443    a complete match.  Returns a null pointer if no such command
444    exists. */
445 static const struct command *
446 get_complete_match (char *const words[], size_t word_cnt)
447 {
448   const struct command *cmd;
449
450   for (cmd = commands; cmd < commands + command_cnt; cmd++)
451     if (cmd_match_words (cmd, words, word_cnt, NULL) == COMPLETE_MATCH)
452       return cmd;
453
454   return NULL;
455 }
456
457 /* Returns the command with the given exact NAME.
458    Aborts if no such command exists. */
459 static const struct command *
460 find_command (const char *name)
461 {
462   const struct command *cmd;
463
464   for (cmd = commands; cmd < commands + command_cnt; cmd++)
465     if (!strcmp (cmd->name, name))
466       return cmd;
467   NOT_REACHED ();
468 }
469
470 /* Frees the WORD_CNT words in WORDS. */
471 static void
472 free_words (char *words[], size_t word_cnt)
473 {
474   size_t idx;
475
476   for (idx = 0; idx < word_cnt; idx++)
477     free (words[idx]);
478 }
479
480 /* Flags an error that the command whose name is given by the
481    WORD_CNT words in WORDS is unknown. */
482 static void
483 unknown_command_error (struct lexer *lexer, char *const words[], size_t word_cnt)
484 {
485   if (word_cnt == 0)
486     lex_error (lexer, _("expecting command name"));
487   else
488     {
489       struct string s;
490       size_t i;
491
492       ds_init_empty (&s);
493       for (i = 0; i < word_cnt; i++)
494         {
495           if (i != 0)
496             ds_put_char (&s, ' ');
497           ds_put_cstr (&s, words[i]);
498         }
499
500       msg (SE, _("Unknown command %s."), ds_cstr (&s));
501
502       ds_destroy (&s);
503     }
504 }
505
506 /* Parse the command name and return a pointer to the corresponding
507    struct command if successful.
508    If not successful, return a null pointer. */
509 static const struct command *
510 parse_command_name (struct lexer *lexer)
511 {
512   char *words[16];
513   int word_cnt;
514   int complete_word_cnt;
515   int dash_possible;
516
517   if (lex_token (lexer) == T_EXP ||
518                   lex_token (lexer) == '*' || lex_token (lexer) == '[')
519     return find_command ("COMMENT");
520
521   dash_possible = 0;
522   word_cnt = complete_word_cnt = 0;
523   while (lex_token (lexer) == T_ID || (dash_possible && lex_token (lexer) == '-'))
524     {
525       int cmd_match_cnt;
526
527       assert (word_cnt < sizeof words / sizeof *words);
528       if (lex_token (lexer) == T_ID)
529         {
530           words[word_cnt] = ds_xstrdup (lex_tokstr (lexer));
531           str_uppercase (words[word_cnt]);
532         }
533       else if (lex_token (lexer) == '-')
534         words[word_cnt] = xstrdup ("-");
535       word_cnt++;
536
537       cmd_match_cnt = count_matching_commands (words, word_cnt,
538                                                &dash_possible);
539       if (cmd_match_cnt == 0)
540         break;
541       else if (cmd_match_cnt == 1)
542         {
543           const struct command *command = get_complete_match (words, word_cnt);
544           if (command != NULL)
545             {
546               if (!(command->flags & F_KEEP_FINAL_TOKEN))
547                 lex_get (lexer);
548               free_words (words, word_cnt);
549               return command;
550             }
551         }
552       else /* cmd_match_cnt > 1 */
553         {
554           /* Do we have a complete command name so far? */
555           if (get_complete_match (words, word_cnt) != NULL)
556             complete_word_cnt = word_cnt;
557         }
558       lex_get (lexer);
559     }
560
561   /* If we saw a complete command name earlier, drop back to
562      it. */
563   if (complete_word_cnt)
564     {
565       int pushback_word_cnt;
566       const struct command *command;
567
568       /* Get the command. */
569       command = get_complete_match (words, complete_word_cnt);
570       assert (command != NULL);
571
572       /* Figure out how many words we want to keep.
573          We normally want to swallow the entire command. */
574       pushback_word_cnt = complete_word_cnt + 1;
575       if (command->flags & F_KEEP_FINAL_TOKEN)
576         pushback_word_cnt--;
577
578       /* FIXME: We only support one-token pushback. */
579       assert (pushback_word_cnt + 1 >= word_cnt);
580
581       while (word_cnt > pushback_word_cnt)
582         {
583           word_cnt--;
584           if (strcmp (words[word_cnt], "-"))
585             lex_put_back_id (lexer, words[word_cnt]);
586           else
587             lex_put_back (lexer, '-');
588           free (words[word_cnt]);
589         }
590
591       free_words (words, word_cnt);
592       return command;
593     }
594
595   /* We didn't get a valid command name. */
596   unknown_command_error (lexer, words, word_cnt);
597   free_words (words, word_cnt);
598   return NULL;
599 }
600
601 /* Returns true if COMMAND is allowed in STATE,
602    false otherwise. */
603 static bool
604 in_correct_state (const struct command *command, enum cmd_state state)
605 {
606   return ((state == CMD_STATE_INITIAL && command->states & S_INITIAL)
607           || (state == CMD_STATE_DATA && command->states & S_DATA)
608           || (state == CMD_STATE_INPUT_PROGRAM
609               && command->states & S_INPUT_PROGRAM)
610           || (state == CMD_STATE_FILE_TYPE && command->states & S_FILE_TYPE));
611 }
612
613 /* Emits an appropriate error message for trying to invoke
614    COMMAND in STATE. */
615 static bool
616 report_state_mismatch (const struct command *command, enum cmd_state state)
617 {
618   assert (!in_correct_state (command, state));
619   if (state == CMD_STATE_INITIAL || state == CMD_STATE_DATA)
620     {
621       switch (command->states)
622         {
623           /* One allowed state. */
624         case S_INITIAL:
625           msg (SE, _("%s is allowed only before the active file has "
626                      "been defined."), command->name);
627           break;
628         case S_DATA:
629           msg (SE, _("%s is allowed only after the active file has "
630                      "been defined."), command->name);
631           break;
632         case S_INPUT_PROGRAM:
633           msg (SE, _("%s is allowed only inside INPUT PROGRAM."),
634                command->name);
635           break;
636         case S_FILE_TYPE:
637           msg (SE, _("%s is allowed only inside FILE TYPE."), command->name);
638           break;
639
640           /* Two allowed states. */
641         case S_INITIAL | S_DATA:
642           NOT_REACHED ();
643         case S_INITIAL | S_INPUT_PROGRAM:
644           msg (SE, _("%s is allowed only before the active file has "
645                      "been defined or inside INPUT PROGRAM."), command->name);
646           break;
647         case S_INITIAL | S_FILE_TYPE:
648           msg (SE, _("%s is allowed only before the active file has "
649                      "been defined or inside FILE TYPE."), command->name);
650           break;
651         case S_DATA | S_INPUT_PROGRAM:
652           msg (SE, _("%s is allowed only after the active file has "
653                      "been defined or inside INPUT PROGRAM."), command->name);
654           break;
655         case S_DATA | S_FILE_TYPE:
656           msg (SE, _("%s is allowed only after the active file has "
657                      "been defined or inside FILE TYPE."), command->name);
658           break;
659         case S_INPUT_PROGRAM | S_FILE_TYPE:
660           msg (SE, _("%s is allowed only inside INPUT PROGRAM "
661                      "or inside FILE TYPE."), command->name);
662           break;
663
664           /* Three allowed states. */
665         case S_DATA | S_INPUT_PROGRAM | S_FILE_TYPE:
666           msg (SE, _("%s is allowed only after the active file has "
667                      "been defined, inside INPUT PROGRAM, or inside "
668                      "FILE TYPE."), command->name);
669           break;
670         case S_INITIAL | S_INPUT_PROGRAM | S_FILE_TYPE:
671           msg (SE, _("%s is allowed only before the active file has "
672                      "been defined, inside INPUT PROGRAM, or inside "
673                      "FILE TYPE."), command->name);
674           break;
675         case S_INITIAL | S_DATA | S_FILE_TYPE:
676           NOT_REACHED ();
677         case S_INITIAL | S_DATA | S_INPUT_PROGRAM:
678           NOT_REACHED ();
679
680           /* Four allowed states. */
681         case S_INITIAL | S_DATA | S_INPUT_PROGRAM | S_FILE_TYPE:
682           NOT_REACHED ();
683
684         default:
685           NOT_REACHED ();
686         }
687     }
688   else if (state == CMD_STATE_INPUT_PROGRAM)
689     msg (SE, _("%s is not allowed inside %s."), command->name, "INPUT PROGRAM" );
690   else if (state == CMD_STATE_FILE_TYPE)
691     msg (SE, _("%s is not allowed inside %s."), command->name, "FILE TYPE");
692
693   return false;
694 }
695 \f
696 /* Command name completion. */
697
698 static enum cmd_state completion_state = CMD_STATE_INITIAL;
699
700 static void
701 set_completion_state (enum cmd_state state)
702 {
703   completion_state = state;
704 }
705
706 /* Returns the next possible completion of a command name that
707    begins with PREFIX, in the current command state, or a null
708    pointer if no completions remain.
709    Before calling the first time, set *CMD to a null pointer. */
710 const char *
711 cmd_complete (const char *prefix, const struct command **cmd)
712 {
713   if (*cmd == NULL)
714     *cmd = commands;
715
716   for (; *cmd < commands + command_cnt; (*cmd)++)
717     if (!memcasecmp ((*cmd)->name, prefix, strlen (prefix))
718         && (!((*cmd)->flags & F_TESTING) || settings_get_testing_mode ())
719         && (!((*cmd)->flags & F_ENHANCED) || settings_get_syntax () == ENHANCED)
720         && !((*cmd)->flags & F_ABBREV)
721         && ((*cmd)->function != NULL)
722         && in_correct_state (*cmd, completion_state))
723       return (*cmd)++->name;
724
725   return NULL;
726 }
727 \f
728 /* Simple commands. */
729
730 /* Parse and execute FINISH command. */
731 int
732 cmd_finish (struct lexer *lexer UNUSED, struct dataset *ds UNUSED)
733 {
734   return CMD_FINISH;
735 }
736
737 /* Parses the N command. */
738 int
739 cmd_n_of_cases (struct lexer *lexer, struct dataset *ds)
740 {
741   /* Value for N. */
742   int x;
743
744   if (!lex_force_int (lexer))
745     return CMD_FAILURE;
746   x = lex_integer (lexer);
747   lex_get (lexer);
748   if (!lex_match_id (lexer, "ESTIMATED"))
749     dict_set_case_limit (dataset_dict (ds), x);
750
751   return lex_end_of_command (lexer);
752 }
753
754 /* Parses, performs the EXECUTE procedure. */
755 int
756 cmd_execute (struct lexer *lexer, struct dataset *ds)
757 {
758   bool ok = casereader_destroy (proc_open (ds));
759   if (!proc_commit (ds) || !ok)
760     return CMD_CASCADING_FAILURE;
761   return lex_end_of_command (lexer);
762 }
763
764 /* Parses, performs the ERASE command. */
765 int
766 cmd_erase (struct lexer *lexer, struct dataset *ds UNUSED)
767 {
768   if (settings_get_safer_mode ())
769     {
770       msg (SE, _("This command not allowed when the SAFER option is set."));
771       return CMD_FAILURE;
772     }
773
774   if (!lex_force_match_id (lexer, "FILE"))
775     return CMD_FAILURE;
776   lex_match (lexer, '=');
777   if (!lex_force_string (lexer))
778     return CMD_FAILURE;
779
780   if (remove (ds_cstr (lex_tokstr (lexer))) == -1)
781     {
782       msg (SW, _("Error removing `%s': %s."),
783            ds_cstr (lex_tokstr (lexer)), strerror (errno));
784       return CMD_FAILURE;
785     }
786
787   return CMD_SUCCESS;
788 }
789
790 #if HAVE_FORK && HAVE_EXECL
791 /* Spawn an interactive shell process. */
792 static bool
793 shell (void)
794 {
795   int pid;
796
797   pid = fork ();
798   switch (pid)
799     {
800     case 0:
801       {
802         const char *shell_fn;
803         char *shell_process;
804
805         {
806           int i;
807
808           for (i = 3; i < 20; i++)
809             close (i);
810         }
811
812         shell_fn = getenv ("SHELL");
813         if (shell_fn == NULL)
814           shell_fn = "/bin/sh";
815
816         {
817           const char *cp = strrchr (shell_fn, '/');
818           cp = cp ? &cp[1] : shell_fn;
819           shell_process = xmalloca (strlen (cp) + 8);
820           strcpy (shell_process, "-");
821           strcat (shell_process, cp);
822           if (strcmp (cp, "sh"))
823             shell_process[0] = '+';
824         }
825
826         execl (shell_fn, shell_process, NULL);
827
828         _exit (1);
829       }
830
831     case -1:
832       msg (SE, _("Couldn't fork: %s."), strerror (errno));
833       return false;
834
835     default:
836       assert (pid > 0);
837       while (wait (NULL) != pid)
838         ;
839       return true;
840     }
841 }
842 #else /* !(HAVE_FORK && HAVE_EXECL) */
843 /* Don't know how to spawn an interactive shell. */
844 static bool
845 shell (void)
846 {
847   msg (SE, _("Interactive shell not supported on this platform."));
848   return false;
849 }
850 #endif
851
852 /* Executes the specified COMMAND in a subshell.  Returns true if
853    successful, false otherwise. */
854 static bool
855 run_command (const char *command)
856 {
857   if (system (NULL) == 0)
858     {
859       msg (SE, _("Command shell not supported on this platform."));
860       return false;
861     }
862
863   /* Execute the command. */
864   if (system (command) == -1)
865     msg (SE, _("Error executing command: %s."), strerror (errno));
866
867   return true;
868 }
869
870 /* Parses, performs the HOST command. */
871 int
872 cmd_host (struct lexer *lexer, struct dataset *ds UNUSED)
873 {
874   int look_ahead;
875
876   if (settings_get_safer_mode ())
877     {
878       msg (SE, _("This command not allowed when the SAFER option is set."));
879       return CMD_FAILURE;
880     }
881
882   look_ahead = lex_look_ahead (lexer);
883   if (look_ahead == '.')
884     {
885       lex_get (lexer);
886       return shell () ? CMD_SUCCESS : CMD_FAILURE;
887     }
888   else if (look_ahead == '\'' || look_ahead == '"')
889     {
890       bool ok;
891
892       lex_get (lexer);
893       if (!lex_force_string (lexer))
894         NOT_REACHED ();
895       ok = run_command (ds_cstr (lex_tokstr (lexer)));
896
897       lex_get (lexer);
898       return ok ? lex_end_of_command (lexer) : CMD_FAILURE;
899     }
900   else
901     {
902       bool ok = run_command (lex_rest_of_line (lexer));
903       lex_discard_line (lexer);
904       return ok ? CMD_SUCCESS : CMD_FAILURE;
905     }
906 }
907
908 /* Parses, performs the NEW FILE command. */
909 int
910 cmd_new_file (struct lexer *lexer, struct dataset *ds)
911 {
912   proc_discard_active_file (ds);
913
914   return lex_end_of_command (lexer);
915 }
916
917 /* Parses a comment. */
918 int
919 cmd_comment (struct lexer *lexer, struct dataset *ds UNUSED)
920 {
921   lex_skip_comment (lexer);
922   return CMD_SUCCESS;
923 }