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