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