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