37608055890abbc3533e30babcfa47615831b2dd
[pspp-builds.git] / src / 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., 59 Temple Place - Suite 330, Boston, MA
18    02111-1307, USA. */
19
20 #include <config.h>
21 #include "error.h"
22 #include "command.h"
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <ctype.h>
26 #include <errno.h>
27 #include "alloc.h"
28 #include "error.h"
29 #include "getline.h"
30 #include "lexer.h"
31 #include "main.h"
32 #include "settings.h"
33 #include "som.h"
34 #include "str.h"
35 #include "tab.h"
36 #include "var.h"
37 #include "vfm.h"
38
39 #if HAVE_UNISTD_H
40 #include <unistd.h>
41 #endif
42
43 #if HAVE_SYS_WAIT_H
44 #include <sys/wait.h>
45 #endif
46 \f
47 /* Global variables. */
48
49 /* A STATE_* constant giving the current program state. */
50 int pgm_state;
51
52 /* The name of the procedure currently executing, if any. */
53 const char *cur_proc;
54 \f
55 /* Static variables. */
56
57 /* A single command. */
58 struct command
59   {
60     const char *name;           /* Command name. */
61     int transition[4];          /* Transitions to make from each state. */
62     int (*func) (void);         /* Function to call. */
63     int skip_entire_name;       /* If zero, we don't skip the
64                                    final token in the command name. */
65   };
66
67 /* Define the command array. */
68 #define DEFCMD(NAME, T1, T2, T3, T4, FUNC)              \
69         {NAME, {T1, T2, T3, T4}, FUNC, 1},
70 #define SPCCMD(NAME, T1, T2, T3, T4, FUNC)              \
71         {NAME, {T1, T2, T3, T4}, FUNC, 0},
72 #define UNIMPL(NAME, T1, T2, T3, T4)                    \
73         {NAME, {T1, T2, T3, T4}, NULL, 1},
74 static const struct command commands[] = 
75   {
76 #include "command.def"
77   };
78 #undef DEFCMD
79 #undef UNIMPL
80
81 #define COMMAND_CNT (sizeof commands / sizeof *commands)
82 \f
83 /* Command parser. */
84
85 static const struct command *parse_command_name (void);
86
87 /* Determines whether command C is appropriate to call in this
88    part of a FILE TYPE structure. */
89 static int
90 FILE_TYPE_okay (const struct command *c)
91 {
92   int okay = 0;
93   
94   if (c->func != cmd_record_type
95       && c->func != cmd_data_list
96       && c->func != cmd_repeating_data
97       && c->func != cmd_end_file_type)
98     msg (SE, _("%s not allowed inside FILE TYPE/END FILE TYPE."), c->name);
99 #if 0
100   /* FIXME */
101   else if (c->func == cmd_repeating_data && fty.type == FTY_GROUPED)
102     msg (SE, _("%s not allowed inside FILE TYPE GROUPED/END FILE TYPE."),
103          c->name);
104   else if (!fty.had_rec_type && c->func != cmd_record_type)
105     msg (SE, _("RECORD TYPE must be the first command inside a "
106                       "FILE TYPE structure."));
107 #endif
108   else
109     okay = 1;
110
111 #if 0
112   if (c->func == cmd_record_type)
113     fty.had_rec_type = 1;
114 #endif
115
116   return okay;
117 }
118
119 /* Parses an entire PSPP command.  This includes everything from the
120    command name to the terminating dot.  Does most of its work by
121    passing it off to the respective command dispatchers.  Only called
122    by parse() in main.c. */
123 int
124 cmd_parse (void)
125 {
126   const struct command *cp;     /* Iterator used to find the proper command. */
127
128 #if C_ALLOCA
129   /* The generic alloca package performs garbage collection when it is
130      called with an argument of zero. */
131   alloca (0);
132 #endif /* C_ALLOCA */
133
134   /* Null commands can result from extra empty lines. */
135   if (token == '.')
136     return CMD_SUCCESS;
137
138   /* Parse comments. */
139   if ((token == T_ID && !strcmp (tokid, "COMMENT"))
140       || token == T_EXP || token == '*' || token == '[')
141     {
142       lex_skip_comment ();
143       return CMD_SUCCESS;
144     }
145
146   /* Otherwise the line must begin with a command name, which is
147      always an ID token. */
148   if (token != T_ID)
149     {
150       lex_error (_("expecting command name"));
151       return CMD_FAILURE;
152     }
153
154   /* Parse the command name. */
155   cp = parse_command_name ();
156   if (cp == NULL)
157     return CMD_FAILURE;
158   if (cp->func == NULL)
159     {
160       msg (SE, _("%s is not yet implemented."), cp->name);
161       while (token && token != '.')
162         lex_get ();
163       return CMD_SUCCESS;
164     }
165
166   /* If we're in a FILE TYPE structure, only certain commands can be
167      allowed. */
168   if (pgm_state == STATE_INPUT
169       && case_source_is_class (vfm_source, &file_type_source_class)
170       && !FILE_TYPE_okay (cp))
171     return CMD_FAILURE;
172
173   /* Certain state transitions are not allowed.  Check for these. */
174   assert (pgm_state >= 0 && pgm_state < STATE_ERROR);
175   if (cp->transition[pgm_state] == STATE_ERROR)
176     {
177       static const char *state_name[4] =
178       {
179         N_("%s is not allowed (1) before a command to specify the "
180            "input program, such as DATA LIST, (2) between FILE TYPE "
181            "and END FILE TYPE, (3) between INPUT PROGRAM and END "
182            "INPUT PROGRAM."),
183         N_("%s is not allowed within an input program."),
184         N_("%s is only allowed within an input program."),
185         N_("%s is only allowed within an input program."),
186       };
187
188       msg (SE, gettext (state_name[pgm_state]), cp->name);
189       return CMD_FAILURE;
190     }
191
192   /* The structured output manager numbers all its tables.  Increment
193      the major table number for each separate procedure. */
194   som_new_series ();
195   
196   {
197     int result;
198     
199     /* Call the command dispatcher.  Save and restore the name of
200        the current command around this call. */
201     {
202       const char *prev_proc;
203       
204       prev_proc = cur_proc;
205       cur_proc = cp->name;
206       result = cp->func ();
207       cur_proc = prev_proc;
208     }
209     
210     /* Perform the state transition if the command completed
211        successfully (at least in part). */
212     if (result != CMD_FAILURE)
213       {
214         pgm_state = cp->transition[pgm_state];
215
216         if (pgm_state == STATE_ERROR)
217           {
218             discard_variables ();
219             pgm_state = STATE_INIT;
220           }
221       }
222
223     /* Pass the command's success value up to the caller. */
224     return result;
225   }
226 }
227
228 static size_t
229 match_strings (const char *a, size_t a_len,
230                const char *b, size_t b_len) 
231 {
232   size_t match_len = 0;
233   
234   while (a_len > 0 && b_len > 0) 
235     {
236       /* Mismatch always returns zero. */
237       if (*a++ != *b++)
238         return 0;
239
240       /* Advance. */
241       a_len--;
242       b_len--;
243       match_len++;
244     }
245
246   return match_len;
247 }
248
249 /* Returns the first character in the first word in STRING,
250    storing the word's length in *WORD_LEN.  If no words remain,
251    returns a null pointer and stores 0 in *WORD_LEN.  Words are
252    sequences of alphanumeric characters or single
253    non-alphanumeric characters.  Words are delimited by
254    spaces. */
255 static const char *
256 find_word (const char *string, size_t *word_len) 
257 {
258   /* Skip whitespace and asterisks. */
259   while (isspace (*string))
260     string++;
261
262   /* End of string? */
263   if (*string == '\0') 
264     {
265       *word_len = 0;
266       return NULL;
267     }
268
269   /* Special one-character word? */
270   if (!isalnum ((unsigned char) *string)) 
271     {
272       *word_len = 1;
273       return string;
274     }
275
276   /* Alphanumeric word. */
277   *word_len = 1;
278   while (isalnum ((unsigned char) string[*word_len]))
279     (*word_len)++;
280
281   return string;
282 }
283
284 /* Returns nonzero if strings A and B can be confused based on
285    their first three letters. */
286 static int
287 conflicting_3char_prefixes (const char *a, const char *b) 
288 {
289   size_t aw_len, bw_len;
290   const char *aw, *bw;
291
292   aw = find_word (a, &aw_len);
293   bw = find_word (b, &bw_len);
294   assert (aw != NULL && bw != NULL);
295
296   return ((aw_len > 3 && bw_len > 3)
297           || (aw_len == 3 && bw_len > 3)
298           || (bw_len == 3 && aw_len > 3)) && !memcmp (aw, bw, 3);
299 }
300
301 /* Returns nonzero if CMD can be confused with another command
302    based on the first three letters of its first word. */
303 static int
304 conflicting_3char_prefix_command (const struct command *cmd) 
305 {
306   assert (cmd >= commands && cmd < commands + COMMAND_CNT);
307
308   return ((cmd > commands
309            && conflicting_3char_prefixes (cmd[-1].name, cmd[0].name))
310           || (cmd < commands + COMMAND_CNT
311               && conflicting_3char_prefixes (cmd[0].name, cmd[1].name)));
312 }
313
314 /* Ways that a set of words can match a command name. */
315 enum command_match
316   {
317     MISMATCH,           /* Not a match. */
318     PARTIAL_MATCH,      /* The words begin the command name. */
319     COMPLETE_MATCH      /* The words are the command name. */
320   };
321
322 /* Figures out how well the WORD_CNT words in WORDS match CMD,
323    and returns the appropriate enum value.  If WORDS are a
324    partial match for CMD and the next word in CMD is a dash, then
325    *DASH_POSSIBLE is set to 1 if DASH_POSSIBLE is non-null;
326    otherwise, *DASH_POSSIBLE is unchanged. */
327 static enum command_match
328 cmd_match_words (const struct command *cmd,
329                  char *const words[], size_t word_cnt,
330                  int *dash_possible)
331 {
332   const char *word;
333   size_t word_len;
334   size_t word_idx;
335
336   for (word = find_word (cmd->name, &word_len), word_idx = 0;
337        word != NULL && word_idx < word_cnt;
338        word = find_word (word + word_len, &word_len), word_idx++)
339     if (word_len != strlen (words[word_idx])
340         || memcmp (word, words[word_idx], word_len))
341       {
342         size_t match_chars = match_strings (word, word_len,
343                                             words[word_idx],
344                                             strlen (words[word_idx]));
345         if (match_chars == 0) 
346           {
347             /* Mismatch. */
348             return MISMATCH;
349           }
350         else if (match_chars == 1 || match_chars == 2) 
351           {
352             /* One- and two-character abbreviations are not
353                acceptable. */
354             return MISMATCH; 
355           }
356         else if (match_chars == 3) 
357           {
358             /* Three-character abbreviations are acceptable
359                in the first word of a command if there are
360                no name conflicts.  They are always
361                acceptable after the first word. */
362             if (word_idx == 0 && conflicting_3char_prefix_command (cmd))
363               return MISMATCH;
364           }
365         else /* match_chars > 3 */ 
366           {
367             /* Four-character and longer abbreviations are
368                always acceptable.  */
369           }
370       }
371
372   if (word == NULL && word_idx == word_cnt) 
373     {
374       /* cmd->name = "FOO BAR", words[] = {"FOO", "BAR"}. */
375       return COMPLETE_MATCH;
376     }
377   else if (word == NULL) 
378     {
379       /* cmd->name = "FOO BAR", words[] = {"FOO", "BAR", "BAZ"}. */
380       return MISMATCH; 
381     }
382   else 
383     {
384       /* cmd->name = "FOO BAR BAZ", words[] = {"FOO", "BAR"}. */
385       if (word[0] == '-' && dash_possible != NULL)
386         *dash_possible = 1;
387       return PARTIAL_MATCH; 
388     }
389 }
390
391 /* Returns the number of commands for which the WORD_CNT words in
392    WORDS are a partial or complete match.  If some partial match
393    has a dash as the next word, then *DASH_POSSIBLE is set to 1,
394    otherwise it is set to 0. */
395 static int
396 count_matching_commands (char *const words[], size_t word_cnt,
397                          int *dash_possible) 
398 {
399   const struct command *cmd;
400   int cmd_match_count;
401
402   cmd_match_count = 0;
403   *dash_possible = 0;
404   for (cmd = commands; cmd < commands + COMMAND_CNT; cmd++) 
405     if (cmd_match_words (cmd, words, word_cnt, dash_possible) != MISMATCH) 
406       cmd_match_count++; 
407
408   return cmd_match_count;
409 }
410
411 /* Returns the command for which the WORD_CNT words in WORDS are
412    a complete match.  Returns a null pointer if no such command
413    exists. */
414 static const struct command *
415 get_complete_match (char *const words[], size_t word_cnt) 
416 {
417   const struct command *cmd;
418   
419   for (cmd = commands; cmd < commands + COMMAND_CNT; cmd++) 
420     if (cmd_match_words (cmd, words, word_cnt, NULL) == COMPLETE_MATCH) 
421       return cmd; 
422   
423   return NULL;
424 }
425
426 /* Frees the WORD_CNT words in WORDS. */
427 static void
428 free_words (char *words[], size_t word_cnt) 
429 {
430   size_t idx;
431   
432   for (idx = 0; idx < word_cnt; idx++)
433     free (words[idx]);
434 }
435
436 /* Flags an error that the command whose name is given by the
437    WORD_CNT words in WORDS is unknown. */
438 static void
439 unknown_command_error (char *const words[], size_t word_cnt) 
440 {
441   size_t idx;
442   size_t words_len;
443   char *name, *cp;
444
445   words_len = 0;
446   for (idx = 0; idx < word_cnt; idx++)
447     words_len += strlen (words[idx]);
448
449   cp = name = xmalloc (words_len + word_cnt + 16);
450   for (idx = 0; idx < word_cnt; idx++) 
451     {
452       if (idx != 0)
453         *cp++ = ' ';
454       cp = stpcpy (cp, words[idx]);
455     }
456   *cp = '\0';
457
458   msg (SE, _("Unknown command %s."), name);
459
460   free (name);
461 }
462
463
464 /* Parse the command name and return a pointer to the corresponding
465    struct command if successful.
466    If not successful, return a null pointer. */
467 static const struct command *
468 parse_command_name (void)
469 {
470   char *words[16];
471   int word_cnt;
472   int complete_word_cnt;
473   int dash_possible;
474
475   dash_possible = 0;
476   word_cnt = complete_word_cnt = 0;
477   while (token == T_ID || (dash_possible && token == '-')) 
478     {
479       int cmd_match_cnt;
480       
481       assert (word_cnt < sizeof words / sizeof *words);
482       if (token == T_ID)
483         words[word_cnt++] = xstrdup (ds_value (&tokstr));
484       else
485         words[word_cnt++] = xstrdup ("-");
486
487       cmd_match_cnt = count_matching_commands (words, word_cnt,
488                                                &dash_possible);
489       if (cmd_match_cnt == 0) 
490         break;
491       else if (cmd_match_cnt == 1) 
492         {
493           const struct command *command = get_complete_match (words, word_cnt);
494           if (command != NULL) 
495             {
496               if (command->skip_entire_name)
497                 lex_get ();
498               free_words (words, word_cnt);
499               return command;
500             }
501         }
502       else /* cmd_match_cnt > 1 */
503         {
504           /* Do we have a complete command name so far? */
505           if (get_complete_match (words, word_cnt) != NULL)
506             complete_word_cnt = word_cnt;
507         }
508       lex_get ();
509     }
510
511   /* If we saw a complete command name earlier, drop back to
512      it. */
513   if (complete_word_cnt) 
514     {
515       int pushback_word_cnt;
516       const struct command *command;
517
518       /* Get the command. */
519       command = get_complete_match (words, complete_word_cnt);
520       assert (command != NULL);
521
522       /* Figure out how many words we want to keep.
523          We normally want to swallow the entire command. */
524       pushback_word_cnt = complete_word_cnt + 1;
525       if (!command->skip_entire_name)
526         pushback_word_cnt--;
527       
528       /* FIXME: We only support one-token pushback. */
529       assert (pushback_word_cnt + 1 >= word_cnt);
530
531       while (word_cnt > pushback_word_cnt) 
532         {
533           word_cnt--;
534           if (strcmp (words[word_cnt], "-")) 
535             lex_put_back_id (words[word_cnt]);
536           else
537             lex_put_back ('-');
538           free (words[word_cnt]);
539         }
540
541       free_words (words, word_cnt);
542       return command;
543     }
544
545   unknown_command_error (words, word_cnt);
546   free_words (words, word_cnt);
547   return NULL;
548 }
549 \f
550 /* Simple commands. */
551
552 /* Parse and execute EXIT command. */
553 int
554 cmd_exit (void)
555 {
556   if (getl_reading_script)
557     {
558       msg (SE, _("This command is not accepted in a syntax file.  "
559            "Instead, use FINISH to terminate a syntax file."));
560       lex_get ();
561     }
562   else
563     finished = 1;
564
565   return CMD_SUCCESS;
566 }
567
568 /* Parse and execute FINISH command. */
569 int
570 cmd_finish (void)
571 {
572   /* Do not check for `.'
573      Do not fetch any extra tokens. */
574   if (getl_interactive)
575     {
576       msg (SM, _("This command is not executed "
577            "in interactive mode.  Instead, PSPP drops "
578            "down to the command prompt.  Use EXIT if you really want "
579            "to quit."));
580       getl_close_all ();
581     }
582   else
583     finished = 1;
584
585   return CMD_SUCCESS;
586 }
587
588 /* Extracts a null-terminated 8-or-fewer-character PREFIX from STRING.
589    PREFIX is converted to lowercase.  Removes trailing spaces from
590    STRING as a side effect.  */
591 static void
592 extract_prefix (char *string, char *prefix)
593 {
594   /* Length of STRING. */
595   int len;
596
597   /* Points to the null terminator in STRING (`end pointer'). */
598   char *ep;
599
600   /* Strip spaces from end of STRING. */
601   len = strlen (string);
602   while (len && isspace ((unsigned char) string[len - 1]))
603     string[--len] = 0;
604
605   /* Find null terminator. */
606   ep = memchr (string, '\0', 8);
607   if (!ep)
608     ep = &string[8];
609
610   /* Copy prefix, converting to lowercase. */
611   while (string < ep)
612     *prefix++ = tolower ((unsigned char) (*string++));
613   *prefix = 0;
614 }
615
616 /* Prints STRING on the console and to the listing file, replacing \n
617    by newline. */
618 static void
619 output_line (char *string)
620 {
621   /* Location of \n in line read in. */
622   char *cp;
623
624   cp = strstr (string, "\\n");
625   while (cp)
626     {
627       *cp = 0;
628       tab_output_text (TAB_LEFT | TAT_NOWRAP, string);
629       string = &cp[2];
630       cp = strstr (string, "\\n");
631     }
632   tab_output_text (TAB_LEFT | TAT_NOWRAP, string);
633 }
634
635 /* Parse and execute REMARK command. */
636 int
637 cmd_remark ()
638 {
639   /* Points to the line read in. */
640   char *s;
641
642   /* Index into s. */
643   char *cp;
644
645   /* 8-character sentinel used to terminate remark. */
646   char sentinel[9];
647
648   /* Beginning of line used to compare with SENTINEL. */
649   char prefix[9];
650
651   som_blank_line ();
652   
653   s = lex_rest_of_line (NULL);
654   if (*s == '-')
655     {
656       output_line (&s[1]);
657       return CMD_SUCCESS;
658     }
659
660   /* Read in SENTINEL from end of current line. */
661   cp = s;
662   while (isspace ((unsigned char) *cp))
663     cp++;
664   extract_prefix (cp, sentinel);
665   if (sentinel[0] == 0)
666     {
667       msg (SE, _("The sentinel may not be the empty string."));
668       return CMD_FAILURE;
669     }
670
671   /* Read in other lines until we encounter the sentinel. */
672   while (getl_read_line ())
673     {
674       extract_prefix (ds_value (&getl_buf), prefix);
675       if (!strcmp (sentinel, prefix))
676         break;
677
678       /* Output the line. */
679       output_line (ds_value (&getl_buf));
680     }
681
682   /* Calling lex_entire_line() forces the sentinel line to be
683      discarded. */
684   getl_prompt = GETL_PRPT_STANDARD;
685   lex_entire_line ();
686
687   return CMD_SUCCESS;
688 }
689
690 /* Parses the N command. */
691 int
692 cmd_n_of_cases (void)
693 {
694   /* Value for N. */
695   int x;
696
697   if (!lex_force_int ())
698     return CMD_FAILURE;
699   x = lex_integer ();
700   lex_get ();
701   if (!lex_match_id ("ESTIMATED"))
702     dict_set_case_limit (default_dict, x);
703
704   return lex_end_of_command ();
705 }
706
707 /* Parses, performs the EXECUTE procedure. */
708 int
709 cmd_execute (void)
710 {
711   procedure (NULL, NULL);
712   return lex_end_of_command ();
713 }
714
715 /* Parses, performs the ERASE command. */
716 int
717 cmd_erase (void)
718 {
719   if ( safer_mode() ) 
720     { 
721       msg (SE, _("This command not allowed when the SAFER option is set.")); 
722       return CMD_FAILURE; 
723     } 
724   
725   if (!lex_force_match_id ("FILE"))
726     return CMD_FAILURE;
727   lex_match ('=');
728   if (!lex_force_string ())
729     return CMD_FAILURE;
730
731   if (remove (ds_value (&tokstr)) == -1)
732     {
733       msg (SW, _("Error removing `%s': %s."),
734            ds_value (&tokstr), strerror (errno));
735       return CMD_FAILURE;
736     }
737
738   return CMD_SUCCESS;
739 }
740
741 #ifdef unix
742 /* Spawn a shell process. */
743 static int
744 shell (void)
745 {
746   int pid;
747   
748   pid = fork ();
749   switch (pid)
750     {
751     case 0:
752       {
753         const char *shell_fn;
754         char *shell_process;
755         
756         {
757           int i;
758           
759           for (i = 3; i < 20; i++)
760             close (i);
761         }
762
763         shell_fn = getenv ("SHELL");
764         if (shell_fn == NULL)
765           shell_fn = "/bin/sh";
766         
767         {
768           const char *cp = strrchr (shell_fn, '/');
769           cp = cp ? &cp[1] : shell_fn;
770           shell_process = local_alloc (strlen (cp) + 8);
771           strcpy (shell_process, "-");
772           strcat (shell_process, cp);
773           if (strcmp (cp, "sh"))
774             shell_process[0] = '+';
775         }
776         
777         execl (shell_fn, shell_process, NULL);
778
779         err_hcf (1);
780       }
781
782     case -1:
783       msg (SE, _("Couldn't fork: %s."), strerror (errno));
784       return 0;
785
786     default:
787       assert (pid > 0);
788       while (wait (NULL) != pid)
789         ;
790       return 1;
791     }
792 }
793 #endif /* unix */
794
795 /* Parses the HOST command argument and executes the specified
796    command.  Returns a suitable command return code. */
797 static int
798 run_command (void)
799 {
800   char *cmd;
801   int string;
802
803   /* Handle either a string argument or a full-line argument. */
804   {
805     int c = lex_look_ahead ();
806
807     if (c == '\'' || c == '"')
808       {
809         lex_get ();
810         if (!lex_force_string ())
811           return CMD_FAILURE;
812         cmd = ds_value (&tokstr);
813         string = 1;
814       }
815     else
816       {
817         cmd = lex_rest_of_line (NULL);
818         string = 0;
819       }
820   }
821
822   /* Execute the command. */
823   if (system (cmd) == -1)
824     msg (SE, _("Error executing command: %s."), strerror (errno));
825
826   /* Finish parsing. */
827   if (string)
828     {
829       lex_get ();
830
831       if (token != '.')
832         {
833           lex_error (_("expecting end of command"));
834           return CMD_TRAILING_GARBAGE;
835         }
836     }
837   else
838     token = '.';
839
840   return CMD_SUCCESS;
841 }
842
843 /* Parses, performs the HOST command. */
844 int
845 cmd_host (void)
846 {
847   int code;
848
849   if ( safer_mode() ) 
850     { 
851       msg (SE, _("This command not allowed when the SAFER option is set.")); 
852       return CMD_FAILURE; 
853     } 
854
855 #ifdef unix
856   /* Figure out whether to invoke an interactive shell or to execute a
857      single shell command. */
858   if (lex_look_ahead () == '.')
859     {
860       lex_get ();
861       code = shell () ? CMD_PART_SUCCESS_MAYBE : CMD_SUCCESS;
862     }
863   else
864     code = run_command ();
865 #else /* !unix */
866   /* Make sure that the system has a command interpreter, then run a
867      command. */
868   if (system (NULL) != 0)
869     success = run_command ();
870   else
871     {
872       msg (SE, _("No operating system support for this command."));
873       success = CMD_FAILURE;
874     }
875 #endif /* !unix */
876
877   return code ? CMD_FAILURE : CMD_SUCCESS;
878 }
879
880 /* Parses, performs the NEW FILE command. */
881 int
882 cmd_new_file (void)
883 {
884   discard_variables ();
885
886   return lex_end_of_command ();
887 }
888
889 /* Parses, performs the CLEAR TRANSFORMATIONS command. */
890 int
891 cmd_clear_transformations (void)
892 {
893   if (getl_reading_script)
894     {
895       msg (SW, _("This command is not valid in a syntax file."));
896       return CMD_FAILURE;
897     }
898
899   cancel_transformations ();
900   /* FIXME: what about variables created by transformations?
901      They need to be properly initialized. */
902
903   return CMD_SUCCESS;
904 }