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