1 /* PSPP - computes sample statistics.
2 Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
3 Written by Ben Pfaff <blp@gnu.org>.
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.
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.
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
47 /* Global variables. */
49 /* A STATE_* constant giving the current program state. */
52 /* The name of the procedure currently executing, if any. */
55 /* Static variables. */
57 /* A single command. */
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. */
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[] =
76 #include "command.def"
81 #define COMMAND_CNT (sizeof commands / sizeof *commands)
85 static const struct command *parse_command_name (void);
87 /* Determines whether command C is appropriate to call in this
88 part of a FILE TYPE structure. */
90 FILE_TYPE_okay (const struct command *c)
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);
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."),
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."));
112 if (c->func == cmd_record_type)
113 fty.had_rec_type = 1;
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. */
126 const struct command *cp; /* Iterator used to find the proper command. */
129 /* The generic alloca package performs garbage collection when it is
130 called with an argument of zero. */
132 #endif /* C_ALLOCA */
134 /* Null commands can result from extra empty lines. */
138 /* Parse comments. */
139 if ((token == T_ID && !strcmp (tokid, "COMMENT"))
140 || token == T_EXP || token == '*' || token == '[')
146 /* Otherwise the line must begin with a command name, which is
147 always an ID token. */
150 lex_error (_("expecting command name"));
154 /* Parse the command name. */
155 cp = parse_command_name ();
158 if (cp->func == NULL)
160 msg (SE, _("%s is not yet implemented."), cp->name);
161 while (token && token != '.')
166 /* If we're in a FILE TYPE structure, only certain commands can be
168 if (pgm_state == STATE_INPUT
169 && case_source_is_class (vfm_source, &file_type_source_class)
170 && !FILE_TYPE_okay (cp))
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)
177 static const char *state_name[4] =
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 "
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."),
188 msg (SE, gettext (state_name[pgm_state]), cp->name);
192 /* The structured output manager numbers all its tables. Increment
193 the major table number for each separate procedure. */
199 /* Call the command dispatcher. Save and restore the name of
200 the current command around this call. */
202 const char *prev_proc;
204 prev_proc = cur_proc;
206 result = cp->func ();
207 cur_proc = prev_proc;
210 /* Perform the state transition if the command completed
211 successfully (at least in part). */
212 if (result != CMD_FAILURE)
214 pgm_state = cp->transition[pgm_state];
216 if (pgm_state == STATE_ERROR)
218 discard_variables ();
219 pgm_state = STATE_INIT;
223 /* Pass the command's success value up to the caller. */
229 match_strings (const char *a, size_t a_len,
230 const char *b, size_t b_len)
232 size_t match_len = 0;
234 while (a_len > 0 && b_len > 0)
236 /* Mismatch always returns zero. */
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
256 find_word (const char *string, size_t *word_len)
258 /* Skip whitespace and asterisks. */
259 while (isspace (*string))
269 /* Special one-character word? */
270 if (!isalnum ((unsigned char) *string))
276 /* Alphanumeric word. */
278 while (isalnum ((unsigned char) string[*word_len]))
284 /* Returns nonzero if strings A and B can be confused based on
285 their first three letters. */
287 conflicting_3char_prefixes (const char *a, const char *b)
289 size_t aw_len, bw_len;
292 aw = find_word (a, &aw_len);
293 bw = find_word (b, &bw_len);
294 assert (aw != NULL && bw != NULL);
296 /* Words that are the same don't conflict. */
297 if (aw_len == bw_len && !memcmp (aw, bw, aw_len))
300 /* Words that are otherwise the same in the first three letters
302 return ((aw_len > 3 && bw_len > 3)
303 || (aw_len == 3 && bw_len > 3)
304 || (bw_len == 3 && aw_len > 3)) && !memcmp (aw, bw, 3);
307 /* Returns nonzero if CMD can be confused with another command
308 based on the first three letters of its first word. */
310 conflicting_3char_prefix_command (const struct command *cmd)
312 assert (cmd >= commands && cmd < commands + COMMAND_CNT);
314 return ((cmd > commands
315 && conflicting_3char_prefixes (cmd[-1].name, cmd[0].name))
316 || (cmd < commands + COMMAND_CNT
317 && conflicting_3char_prefixes (cmd[0].name, cmd[1].name)));
320 /* Ways that a set of words can match a command name. */
323 MISMATCH, /* Not a match. */
324 PARTIAL_MATCH, /* The words begin the command name. */
325 COMPLETE_MATCH /* The words are the command name. */
328 /* Figures out how well the WORD_CNT words in WORDS match CMD,
329 and returns the appropriate enum value. If WORDS are a
330 partial match for CMD and the next word in CMD is a dash, then
331 *DASH_POSSIBLE is set to 1 if DASH_POSSIBLE is non-null;
332 otherwise, *DASH_POSSIBLE is unchanged. */
333 static enum command_match
334 cmd_match_words (const struct command *cmd,
335 char *const words[], size_t word_cnt,
342 for (word = find_word (cmd->name, &word_len), word_idx = 0;
343 word != NULL && word_idx < word_cnt;
344 word = find_word (word + word_len, &word_len), word_idx++)
345 if (word_len != strlen (words[word_idx])
346 || memcmp (word, words[word_idx], word_len))
348 size_t match_chars = match_strings (word, word_len,
350 strlen (words[word_idx]));
351 if (match_chars == 0)
356 else if (match_chars == 1 || match_chars == 2)
358 /* One- and two-character abbreviations are not
362 else if (match_chars == 3)
364 /* Three-character abbreviations are acceptable
365 in the first word of a command if there are
366 no name conflicts. They are always
367 acceptable after the first word. */
368 if (word_idx == 0 && conflicting_3char_prefix_command (cmd))
371 else /* match_chars > 3 */
373 /* Four-character and longer abbreviations are
374 always acceptable. */
378 if (word == NULL && word_idx == word_cnt)
380 /* cmd->name = "FOO BAR", words[] = {"FOO", "BAR"}. */
381 return COMPLETE_MATCH;
383 else if (word == NULL)
385 /* cmd->name = "FOO BAR", words[] = {"FOO", "BAR", "BAZ"}. */
390 /* cmd->name = "FOO BAR BAZ", words[] = {"FOO", "BAR"}. */
391 if (word[0] == '-' && dash_possible != NULL)
393 return PARTIAL_MATCH;
397 /* Returns the number of commands for which the WORD_CNT words in
398 WORDS are a partial or complete match. If some partial match
399 has a dash as the next word, then *DASH_POSSIBLE is set to 1,
400 otherwise it is set to 0. */
402 count_matching_commands (char *const words[], size_t word_cnt,
405 const struct command *cmd;
410 for (cmd = commands; cmd < commands + COMMAND_CNT; cmd++)
411 if (cmd_match_words (cmd, words, word_cnt, dash_possible) != MISMATCH)
414 return cmd_match_count;
417 /* Returns the command for which the WORD_CNT words in WORDS are
418 a complete match. Returns a null pointer if no such command
420 static const struct command *
421 get_complete_match (char *const words[], size_t word_cnt)
423 const struct command *cmd;
425 for (cmd = commands; cmd < commands + COMMAND_CNT; cmd++)
426 if (cmd_match_words (cmd, words, word_cnt, NULL) == COMPLETE_MATCH)
432 /* Frees the WORD_CNT words in WORDS. */
434 free_words (char *words[], size_t word_cnt)
438 for (idx = 0; idx < word_cnt; idx++)
442 /* Flags an error that the command whose name is given by the
443 WORD_CNT words in WORDS is unknown. */
445 unknown_command_error (char *const words[], size_t word_cnt)
452 for (idx = 0; idx < word_cnt; idx++)
453 words_len += strlen (words[idx]);
455 cp = name = xmalloc (words_len + word_cnt + 16);
456 for (idx = 0; idx < word_cnt; idx++)
460 cp = stpcpy (cp, words[idx]);
464 msg (SE, _("Unknown command %s."), name);
470 /* Parse the command name and return a pointer to the corresponding
471 struct command if successful.
472 If not successful, return a null pointer. */
473 static const struct command *
474 parse_command_name (void)
478 int complete_word_cnt;
482 word_cnt = complete_word_cnt = 0;
483 while (token == T_ID || (dash_possible && token == '-'))
487 assert (word_cnt < sizeof words / sizeof *words);
489 words[word_cnt++] = xstrdup (ds_c_str (&tokstr));
491 words[word_cnt++] = xstrdup ("-");
493 cmd_match_cnt = count_matching_commands (words, word_cnt,
495 if (cmd_match_cnt == 0)
497 else if (cmd_match_cnt == 1)
499 const struct command *command = get_complete_match (words, word_cnt);
502 if (command->skip_entire_name)
504 free_words (words, word_cnt);
508 else /* cmd_match_cnt > 1 */
510 /* Do we have a complete command name so far? */
511 if (get_complete_match (words, word_cnt) != NULL)
512 complete_word_cnt = word_cnt;
517 /* If we saw a complete command name earlier, drop back to
519 if (complete_word_cnt)
521 int pushback_word_cnt;
522 const struct command *command;
524 /* Get the command. */
525 command = get_complete_match (words, complete_word_cnt);
526 assert (command != NULL);
528 /* Figure out how many words we want to keep.
529 We normally want to swallow the entire command. */
530 pushback_word_cnt = complete_word_cnt + 1;
531 if (!command->skip_entire_name)
534 /* FIXME: We only support one-token pushback. */
535 assert (pushback_word_cnt + 1 >= word_cnt);
537 while (word_cnt > pushback_word_cnt)
540 if (strcmp (words[word_cnt], "-"))
541 lex_put_back_id (words[word_cnt]);
544 free (words[word_cnt]);
547 free_words (words, word_cnt);
551 unknown_command_error (words, word_cnt);
552 free_words (words, word_cnt);
556 /* Simple commands. */
558 /* Parse and execute EXIT command. */
562 if (getl_reading_script)
564 msg (SE, _("This command is not accepted in a syntax file. "
565 "Instead, use FINISH to terminate a syntax file."));
574 /* Parse and execute FINISH command. */
578 /* Do not check for `.'
579 Do not fetch any extra tokens. */
580 if (getl_interactive)
582 msg (SM, _("This command is not executed "
583 "in interactive mode. Instead, PSPP drops "
584 "down to the command prompt. Use EXIT if you really want "
594 /* Parses the N command. */
596 cmd_n_of_cases (void)
601 if (!lex_force_int ())
605 if (!lex_match_id ("ESTIMATED"))
606 dict_set_case_limit (default_dict, x);
608 return lex_end_of_command ();
611 /* Parses, performs the EXECUTE procedure. */
615 procedure (NULL, NULL);
616 return lex_end_of_command ();
619 /* Parses, performs the ERASE command. */
625 msg (SE, _("This command not allowed when the SAFER option is set."));
629 if (!lex_force_match_id ("FILE"))
632 if (!lex_force_string ())
635 if (remove (ds_c_str (&tokstr)) == -1)
637 msg (SW, _("Error removing `%s': %s."),
638 ds_c_str (&tokstr), strerror (errno));
646 /* Spawn a shell process. */
657 const char *shell_fn;
663 for (i = 3; i < 20; i++)
667 shell_fn = getenv ("SHELL");
668 if (shell_fn == NULL)
669 shell_fn = "/bin/sh";
672 const char *cp = strrchr (shell_fn, '/');
673 cp = cp ? &cp[1] : shell_fn;
674 shell_process = local_alloc (strlen (cp) + 8);
675 strcpy (shell_process, "-");
676 strcat (shell_process, cp);
677 if (strcmp (cp, "sh"))
678 shell_process[0] = '+';
681 execl (shell_fn, shell_process, NULL);
687 msg (SE, _("Couldn't fork: %s."), strerror (errno));
692 while (wait (NULL) != pid)
699 /* Parses the HOST command argument and executes the specified
700 command. Returns a suitable command return code. */
707 /* Handle either a string argument or a full-line argument. */
709 int c = lex_look_ahead ();
711 if (c == '\'' || c == '"')
714 if (!lex_force_string ())
716 cmd = ds_c_str (&tokstr);
721 cmd = lex_rest_of_line (NULL);
727 /* Execute the command. */
728 if (system (cmd) == -1)
729 msg (SE, _("Error executing command: %s."), strerror (errno));
731 /* Finish parsing. */
738 lex_error (_("expecting end of command"));
739 return CMD_TRAILING_GARBAGE;
748 /* Parses, performs the HOST command. */
756 msg (SE, _("This command not allowed when the SAFER option is set."));
761 /* Figure out whether to invoke an interactive shell or to execute a
762 single shell command. */
763 if (lex_look_ahead () == '.')
766 code = shell () ? CMD_PART_SUCCESS_MAYBE : CMD_SUCCESS;
769 code = run_command ();
771 /* Make sure that the system has a command interpreter, then run a
773 if (system (NULL) != 0)
774 code = run_command ();
777 msg (SE, _("No operating system support for this command."));
782 return code ? CMD_FAILURE : CMD_SUCCESS;
785 /* Parses, performs the NEW FILE command. */
789 discard_variables ();
791 return lex_end_of_command ();
794 /* Parses, performs the CLEAR TRANSFORMATIONS command. */
796 cmd_clear_transformations (void)
798 if (getl_reading_script)
800 msg (SW, _("This command is not valid in a syntax file."));
804 cancel_transformations ();
805 /* FIXME: what about variables created by transformations?
806 They need to be properly initialized. */