Sat Dec 27 16:16:49 2003 Ben Pfaff <blp@gnu.org>
[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 /* AIX requires this to be the first thing in the file.  */
21 #include <config.h>
22 #if __GNUC__
23 #define alloca __builtin_alloca
24 #else
25 #if HAVE_ALLOCA_H
26 #include <alloca.h>
27 #else
28 #ifdef _AIX
29 #pragma alloca
30 #else
31 #ifndef alloca                  /* predefined by HP cc +Olibcalls */
32 char *alloca ();
33 #endif
34 #endif
35 #endif
36 #endif
37
38 #include <assert.h>
39 #include "command.h"
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <ctype.h>
43 #include <errno.h>
44 #include "alloc.h"
45 #include "error.h"
46 #include "getline.h"
47 #include "lexer.h"
48 #include "main.h"
49 #include "settings.h"
50 #include "som.h"
51 #include "str.h"
52 #include "tab.h"
53 #include "var.h"
54 #include "vfm.h"
55
56 #if HAVE_UNISTD_H
57 #include <unistd.h>
58 #endif
59
60 #if HAVE_SYS_WAIT_H
61 #include <sys/wait.h>
62 #endif
63
64 #include "debug-print.h"
65 \f
66 /* Global variables. */
67
68 /* A STATE_* constant giving the current program state. */
69 int pgm_state;
70
71 /* The name of the procedure currently executing, if any. */
72 const char *cur_proc;
73 \f
74 /* Static variables. */
75
76 /* A single command. */
77 struct command
78   {
79     /* Initialized statically. */
80     char cmd[22];               /* Command name. */
81     int transition[4];          /* Transitions to make from each state. */
82     int (*func) (void);         /* Function to call. */
83
84     /* Calculated at startup time. */
85     char *word[3];              /* cmd[], divided into individual words. */
86     struct command *next;       /* Next command with same word[0]. */
87   };
88
89 /* Define the command array. */
90 #define DEFCMD(NAME, T1, T2, T3, T4, FUNC)              \
91         {NAME, {T1, T2, T3, T4}, FUNC, {NULL, NULL, NULL}, NULL},
92 #define UNIMPL(NAME, T1, T2, T3, T4)                    \
93         {NAME, {T1, T2, T3, T4}, NULL, {NULL, NULL, NULL}, NULL},
94 static struct command cmd_table[] = 
95   {
96 #include "command.def"
97     {"", {ERRO, ERRO, ERRO, ERRO}, NULL, {NULL, NULL, NULL}, NULL},
98   };
99 #undef DEFCMD
100 #undef UNIMPL
101 \f
102 /* Command parser. */
103
104 static struct command *figure_out_command (void);
105
106 /* Breaks the `cmd' member of C into individual words and sets C's
107    word[] member appropriately. */
108 static void
109 split_words (struct command *c)
110 {
111   char *cmd, *save;
112   int i;
113
114   cmd = xstrdup (c->cmd);
115   for (i = 0; i < 3; i++)
116     cmd = c->word[i] = strtok_r (i == 0 ? cmd : NULL, " -", &save);
117 }
118
119 /* Initializes the command parser. */
120 void
121 cmd_init (void)
122 {
123   struct command *c;
124
125   /* Break up command names into words. */
126   for (c = cmd_table; c->cmd[0]; c++)
127     split_words (c);
128
129   /* Make chains of commands having the same first word. */
130   for (c = cmd_table; c->cmd[0]; c++)
131     {
132       struct command *first;
133       for (first = c; c[1].word[0] && !strcmp (c[0].word[0], c[1].word[0]); c++)
134         c->next = c + 1;
135
136       c->next = NULL;
137     }
138 }
139
140 /* Determines whether command C is appropriate to call in this
141    part of a FILE TYPE structure. */
142 static int
143 FILE_TYPE_okay (struct command *c)
144 {
145   int okay = 0;
146   
147   if (c->func != cmd_record_type
148       && c->func != cmd_data_list
149       && c->func != cmd_repeating_data
150       && c->func != cmd_end_file_type)
151     msg (SE, _("%s not allowed inside FILE TYPE/END FILE TYPE."), c->cmd);
152 #if 0
153   /* FIXME */
154   else if (c->func == cmd_repeating_data && fty.type == FTY_GROUPED)
155     msg (SE, _("%s not allowed inside FILE TYPE GROUPED/END FILE TYPE."),
156          c->cmd);
157   else if (!fty.had_rec_type && c->func != cmd_record_type)
158     msg (SE, _("RECORD TYPE must be the first command inside a "
159                       "FILE TYPE structure."));
160 #endif
161   else
162     okay = 1;
163
164 #if 0
165   if (c->func == cmd_record_type)
166     fty.had_rec_type = 1;
167 #endif
168
169   return okay;
170 }
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   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 && !strcmp (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       msg (SE, _("This line does not begin with a valid command name."));
204       return CMD_FAILURE;
205     }
206
207   /* Parse the command name. */
208   cp = figure_out_command ();
209   if (cp == NULL)
210     return CMD_FAILURE;
211   if (cp->func == NULL)
212     {
213       msg (SE, _("%s is not yet implemented."), cp->cmd);
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 && vfm_source == &file_type_source
222       && !FILE_TYPE_okay (cp))
223     return CMD_FAILURE;
224
225   /* Certain state transitions are not allowed.  Check for these. */
226   assert (pgm_state >= 0 && pgm_state < STATE_ERROR);
227   if (cp->transition[pgm_state] == STATE_ERROR)
228     {
229       static const char *state_name[4] =
230       {
231         N_("%s is not allowed (1) before a command to specify the "
232            "input program, such as DATA LIST, (2) between FILE TYPE "
233            "and END FILE TYPE, (3) between INPUT PROGRAM and END "
234            "INPUT PROGRAM."),
235         N_("%s is not allowed within an input program."),
236         N_("%s is only allowed within an input program."),
237         N_("%s is only allowed within an input program."),
238       };
239
240       msg (SE, gettext (state_name[pgm_state]), cp->cmd);
241       return CMD_FAILURE;
242     }
243
244 #if DEBUGGING
245   if (cp->func != cmd_remark)
246     printf (_("%s command beginning\n"), cp->cmd);
247 #endif
248
249   /* The structured output manager numbers all its tables.  Increment
250      the major table number for each separate procedure. */
251   som_new_series ();
252   
253   {
254     int result;
255     
256     /* Call the command dispatcher.  Save and restore the name of
257        the current command around this call. */
258     {
259       const char *prev_proc;
260       
261       prev_proc = cur_proc;
262       cur_proc = cp->cmd;
263       result = cp->func ();
264       cur_proc = prev_proc;
265     }
266     
267     /* Perform the state transition if the command completed
268        successfully (at least in part). */
269     if (result != 0)
270       {
271         pgm_state = cp->transition[pgm_state];
272
273         if (pgm_state == STATE_ERROR)
274           {
275             discard_variables ();
276             pgm_state = STATE_INIT;
277           }
278       }
279
280 #if DEBUGGING
281     if (cp->func != cmd_remark)
282       printf (_("%s command completed\n\n"), cp->cmd);
283 #endif
284
285     /* Pass the command's success value up to the caller. */
286     return result;
287   }
288 }
289
290 /* Parse the command name and return a pointer to the corresponding
291    struct command if successful.
292    If not successful, return a null pointer. */
293 static struct command *
294 figure_out_command (void)
295 {
296   static const char *unk =
297     N_("The identifier(s) specified do not form a valid command name:");
298
299   static const char *inc = 
300     N_("The identifier(s) specified do not form a complete command name:");
301
302   struct command *cp;
303
304   /* Parse the INCLUDE short form.
305      Note that `@' is a valid character in identifiers. */
306   if (tokid[0] == '@')
307     return &cmd_table[0];
308
309   /* Find a command whose first word matches this identifier.
310      If it is the only command that begins with this word, return
311      it. */
312   for (cp = cmd_table; cp->cmd[0]; cp++)
313     if (lex_id_match (cp->word[0], tokid))
314       break;
315
316   if (cp->cmd[0] == '\0')
317     {
318       msg (SE, "%s %s.", gettext (unk), ds_value (&tokstr));
319       return NULL;
320     }
321
322   if (cp->next == NULL)
323     return cp;
324   
325   /* We know that there is more than one command starting with this
326      word.  Read the next word in the command name. */
327   {
328     struct command *ocp = cp;
329     
330     /* Verify that the next token is an identifier, because we
331        must disambiguate this command name. */
332     lex_get ();
333     if (token != T_ID)
334       {
335         /* If there's a command whose name is the first word only,
336            return it.  This happens with, i.e., PRINT vs. PRINT
337            SPACE. */
338         if (ocp->word[1] == NULL)
339           return ocp;
340         
341         msg (SE, "%s %s.", gettext (inc), ds_value (&tokstr));
342         return NULL;
343       }
344
345     for (; cp; cp = cp->next)
346       if (cp->word[1] && lex_id_match (cp->word[1], tokid))
347         break;
348
349     if (cp == NULL)
350       {
351         /* No match.  If there's a command whose name is the first
352            word only, return it.  This happens with, i.e., PRINT
353            vs. PRINT SPACE. */
354         if (ocp->word[1] == NULL)
355           return ocp;
356         
357         msg (SE, "%s %s %s.", gettext (unk), ocp->word[0], tokid);
358         return NULL;
359       }
360   
361     /* Check whether the next token is an identifier.
362        If not, bail. */
363     if (!isalpha ((unsigned char) (lex_look_ahead ())))
364       {
365         /* Check whether there is an unambiguous interpretation.
366            If not, give an error. */
367         if (cp->word[2]
368             && cp->next
369             && !strcmp (cp->word[1], cp->next->word[1]))
370           {
371             msg (SE, "%s %s %s.", gettext (inc), ocp->word[0], ocp->word[1]);
372             return NULL;
373           }
374         else
375           return cp;
376       }
377   }
378   
379   /* If this command can have a third word, disambiguate based on it. */
380   if (cp->word[2]
381       || (cp->next
382           && cp->next->word[2]
383           && !strcmp (cp->word[1], cp->next->word[1])))
384     {
385       struct command *ocp = cp;
386       
387       lex_get ();
388       assert (token == T_ID);
389
390       /* Try to find a command with this third word.
391          If found, bail. */
392       for (; cp; cp = cp->next)
393         if (cp->word[2]
394             && !strcmp (cp->word[1], ocp->word[1])
395             && lex_id_match (cp->word[2], tokid))
396           break;
397
398       if (cp != NULL)
399         return cp;
400
401       /* If no command with this third word found, make sure that
402          there's a command with those first two words but without a
403          third word. */
404       cp = ocp;
405       if (cp->word[2])
406         {
407           msg (SE, "%s %s %s %s.",
408                gettext (unk), ocp->word[0], ocp->word[1], ds_value (&tokstr));
409           return 0;
410         }
411     }
412
413   return cp;
414 }
415 \f
416 /* Simple commands. */
417
418 /* Parse and execute EXIT command. */
419 int
420 cmd_exit (void)
421 {
422   if (getl_reading_script)
423     {
424       msg (SE, _("This command is not accepted in a syntax file.  "
425            "Instead, use FINISH to terminate a syntax file."));
426       lex_get ();
427     }
428   else
429     finished = 1;
430
431   return CMD_SUCCESS;
432 }
433
434 /* Parse and execute FINISH command. */
435 int
436 cmd_finish (void)
437 {
438   /* Do not check for `.'
439      Do not fetch any extra tokens. */
440   if (getl_interactive)
441     {
442       msg (SM, _("This command is not executed "
443            "in interactive mode.  Instead, PSPP drops "
444            "down to the command prompt.  Use EXIT if you really want "
445            "to quit."));
446       getl_close_all ();
447     }
448   else
449     finished = 1;
450
451   return CMD_SUCCESS;
452 }
453
454 /* Extracts a null-terminated 8-or-fewer-character PREFIX from STRING.
455    PREFIX is converted to lowercase.  Removes trailing spaces from
456    STRING as a side effect.  */
457 static void
458 extract_prefix (char *string, char *prefix)
459 {
460   /* Length of STRING. */
461   int len;
462
463   /* Points to the null terminator in STRING (`end pointer'). */
464   char *ep;
465
466   /* Strip spaces from end of STRING. */
467   len = strlen (string);
468   while (len && isspace ((unsigned char) string[len - 1]))
469     string[--len] = 0;
470
471   /* Find null terminator. */
472   ep = memchr (string, '\0', 8);
473   if (!ep)
474     ep = &string[8];
475
476   /* Copy prefix, converting to lowercase. */
477   while (string < ep)
478     *prefix++ = tolower ((unsigned char) (*string++));
479   *prefix = 0;
480 }
481
482 /* Prints STRING on the console and to the listing file, replacing \n
483    by newline. */
484 static void
485 output_line (char *string)
486 {
487   /* Location of \n in line read in. */
488   char *cp;
489
490   cp = strstr (string, "\\n");
491   while (cp)
492     {
493       *cp = 0;
494       tab_output_text (TAB_LEFT | TAT_NOWRAP, string);
495       string = &cp[2];
496       cp = strstr (string, "\\n");
497     }
498   tab_output_text (TAB_LEFT | TAT_NOWRAP, string);
499 }
500
501 /* Parse and execute REMARK command. */
502 int
503 cmd_remark ()
504 {
505   /* Points to the line read in. */
506   char *s;
507
508   /* Index into s. */
509   char *cp;
510
511   /* 8-character sentinel used to terminate remark. */
512   char sentinel[9];
513
514   /* Beginning of line used to compare with SENTINEL. */
515   char prefix[9];
516
517   som_blank_line ();
518   
519   s = lex_rest_of_line (NULL);
520   if (*s == '-')
521     {
522       output_line (&s[1]);
523       return CMD_SUCCESS;
524     }
525
526   /* Read in SENTINEL from end of current line. */
527   cp = s;
528   while (isspace ((unsigned char) *cp))
529     cp++;
530   extract_prefix (cp, sentinel);
531   if (sentinel[0] == 0)
532     {
533       msg (SE, _("The sentinel may not be the empty string."));
534       return CMD_FAILURE;
535     }
536
537   /* Read in other lines until we encounter the sentinel. */
538   while (getl_read_line ())
539     {
540       extract_prefix (ds_value (&getl_buf), prefix);
541       if (!strcmp (sentinel, prefix))
542         break;
543
544       /* Output the line. */
545       output_line (ds_value (&getl_buf));
546     }
547
548   /* Calling lex_entire_line() forces the sentinel line to be
549      discarded. */
550   getl_prompt = GETL_PRPT_STANDARD;
551   lex_entire_line ();
552
553   return CMD_SUCCESS;
554 }
555
556 /* Parses the N command. */
557 int
558 cmd_n_of_cases (void)
559 {
560   /* Value for N. */
561   int x;
562
563   lex_match_id ("N");
564   lex_match_id ("OF");
565   lex_match_id ("CASES");
566   if (!lex_force_int ())
567     return CMD_FAILURE;
568   x = lex_integer ();
569   lex_get ();
570   if (!lex_match_id ("ESTIMATED"))
571     dict_set_case_limit (default_dict, x);
572
573   return lex_end_of_command ();
574 }
575
576 /* Parses, performs the EXECUTE procedure. */
577 int
578 cmd_execute (void)
579 {
580   lex_match_id ("EXECUTE");
581   procedure (NULL, NULL, NULL);
582   return lex_end_of_command ();
583 }
584
585 /* Parses, performs the ERASE command. */
586 int
587 cmd_erase (void)
588 {
589   if (set_safer)
590     {
591       msg (SE, _("This command not allowed when the SAFER option is set."));
592       return CMD_FAILURE;
593     }
594   
595   lex_match_id ("ERASE");
596   if (!lex_force_match_id ("FILE"))
597     return CMD_FAILURE;
598   lex_match ('=');
599   if (!lex_force_string ())
600     return CMD_FAILURE;
601
602   if (remove (ds_value (&tokstr)) == -1)
603     {
604       msg (SW, _("Error removing `%s': %s."),
605            ds_value (&tokstr), strerror (errno));
606       return CMD_FAILURE;
607     }
608
609   return lex_end_of_command ();
610 }
611
612 #if unix
613 /* Spawn a shell process. */
614 static int
615 shell (void)
616 {
617   int pid;
618   
619   pid = fork ();
620   switch (pid)
621     {
622     case 0:
623       {
624         const char *shell_fn;
625         char *shell_process;
626         
627         {
628           int i;
629           
630           for (i = 3; i < 20; i++)
631             close (i);
632         }
633
634         shell_fn = getenv ("SHELL");
635         if (shell_fn == NULL)
636           shell_fn = "/bin/sh";
637         
638         {
639           const char *cp = strrchr (shell_fn, '/');
640           cp = cp ? &cp[1] : shell_fn;
641           shell_process = local_alloc (strlen (cp) + 8);
642           strcpy (shell_process, "-");
643           strcat (shell_process, cp);
644           if (strcmp (cp, "sh"))
645             shell_process[0] = '+';
646         }
647         
648         execl (shell_fn, shell_process, NULL);
649
650         err_hcf (1);
651       }
652
653     case -1:
654       msg (SE, _("Couldn't fork: %s."), strerror (errno));
655       return 0;
656
657     default:
658       assert (pid > 0);
659       while (wait (NULL) != pid)
660         ;
661       return 1;
662     }
663 }
664 #endif /* unix */
665
666 /* Parses the HOST command argument and executes the specified
667    command.  Returns a suitable command return code. */
668 static int
669 run_command (void)
670 {
671   char *cmd;
672   int string;
673
674   /* Handle either a string argument or a full-line argument. */
675   {
676     int c = lex_look_ahead ();
677
678     if (c == '\'' || c == '"')
679       {
680         lex_get ();
681         if (!lex_force_string ())
682           return CMD_FAILURE;
683         cmd = ds_value (&tokstr);
684         string = 1;
685       }
686     else
687       {
688         cmd = lex_rest_of_line (NULL);
689         string = 0;
690       }
691   }
692
693   /* Execute the command. */
694   if (system (cmd) == -1)
695     msg (SE, _("Error executing command: %s."), strerror (errno));
696
697   /* Finish parsing. */
698   if (string)
699     {
700       lex_get ();
701
702       if (token != '.')
703         {
704           lex_error (_("expecting end of command"));
705           return CMD_TRAILING_GARBAGE;
706         }
707     }
708   else
709     token = '.';
710
711   return CMD_SUCCESS;
712 }
713
714 /* Parses, performs the HOST command. */
715 int
716 cmd_host (void)
717 {
718   int code;
719
720   if (set_safer)
721     {
722       msg (SE, _("This command not allowed when the SAFER option is set."));
723       return CMD_FAILURE;
724     }
725   
726   lex_match_id ("HOST");
727
728 #if unix
729   /* Figure out whether to invoke an interactive shell or to execute a
730      single shell command. */
731   if (lex_look_ahead () == '.')
732     {
733       lex_get ();
734       code = shell () ? CMD_PART_SUCCESS_MAYBE : CMD_SUCCESS;
735     }
736   else
737     code = run_command ();
738 #else /* !unix */
739   /* Make sure that the system has a command interpreter, then run a
740      command. */
741   if (system (NULL) != 0)
742     success = run_command ();
743   else
744     {
745       msg (SE, _("No operating system support for this command."));
746       success = CMD_FAILURE;
747     }
748 #endif /* !unix */
749
750   return code ? CMD_FAILURE : CMD_SUCCESS;
751 }
752
753 /* Parses, performs the NEW FILE command. */
754 int
755 cmd_new_file (void)
756 {
757   lex_match_id ("NEW");
758   lex_match_id ("FILE");
759   
760   discard_variables ();
761
762   return lex_end_of_command ();
763 }
764
765 /* Parses, performs the CLEAR TRANSFORMATIONS command. */
766 int
767 cmd_clear_transformations (void)
768 {
769   lex_match_id ("CLEAR");
770   lex_match_id ("TRANSFORMATIONS");
771
772   if (getl_reading_script)
773     {
774       msg (SW, _("This command is not valid in a syntax file."));
775       return CMD_FAILURE;
776     }
777
778   cancel_transformations ();
779
780   return CMD_SUCCESS;
781 }