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