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
28 #include "dictionary.h"
48 /* Global variables. */
50 /* A STATE_* constant giving the current program state. */
53 /* The name of the procedure currently executing, if any. */
56 /* Static variables. */
58 /* A single command. */
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. */
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[] =
77 #include "command.def"
83 /* Complete the line using the name of a command,
84 * based upon the current prg_state
87 pspp_completion_function (const char *text, int state)
90 const struct command *cmd = 0;
94 if ( state + skip >= sizeof(commands)/ sizeof(struct command))
100 cmd = &commands[state + skip];
102 if ( cmd->transition[pgm_state] == STATE_ERROR )
108 if ( text == 0 || 0 == strncasecmp (cmd->name, text, strlen(text)))
117 return xstrdup(cmd->name);
123 #define COMMAND_CNT (sizeof commands / sizeof *commands)
125 /* Command parser. */
127 static const struct command *parse_command_name (void);
129 /* Determines whether command C is appropriate to call in this
130 part of a FILE TYPE structure. */
132 FILE_TYPE_okay (const struct command *c)
136 if (c->func != cmd_record_type
137 && c->func != cmd_data_list
138 && c->func != cmd_repeating_data
139 && c->func != cmd_end_file_type)
140 msg (SE, _("%s not allowed inside FILE TYPE/END FILE TYPE."), c->name);
143 else if (c->func == cmd_repeating_data && fty.type == FTY_GROUPED)
144 msg (SE, _("%s not allowed inside FILE TYPE GROUPED/END FILE TYPE."),
146 else if (!fty.had_rec_type && c->func != cmd_record_type)
147 msg (SE, _("RECORD TYPE must be the first command inside a "
148 "FILE TYPE structure."));
154 if (c->func == cmd_record_type)
155 fty.had_rec_type = 1;
161 /* Parses an entire PSPP command. This includes everything from the
162 command name to the terminating dot. Does most of its work by
163 passing it off to the respective command dispatchers. Only called
164 by parse() in main.c. */
168 const struct command *cp; /* Iterator used to find the proper command. */
171 /* The generic alloca package performs garbage collection when it is
172 called with an argument of zero. */
174 #endif /* C_ALLOCA */
176 /* Null commands can result from extra empty lines. */
180 /* Parse comments. */
181 if ((token == T_ID && !strcmp (tokid, "COMMENT"))
182 || token == T_EXP || token == '*' || token == '[')
188 /* Otherwise the line must begin with a command name, which is
189 always an ID token. */
192 lex_error (_("expecting command name"));
196 /* Parse the command name. */
197 cp = parse_command_name ();
200 if (cp->func == NULL)
202 msg (SE, _("%s is not yet implemented."), cp->name);
203 while (token && token != '.')
208 /* If we're in a FILE TYPE structure, only certain commands can be
210 if (pgm_state == STATE_INPUT
211 && case_source_is_class (vfm_source, &file_type_source_class)
212 && !FILE_TYPE_okay (cp))
215 /* Certain state transitions are not allowed. Check for these. */
216 assert (pgm_state >= 0 && pgm_state < STATE_ERROR);
217 if (cp->transition[pgm_state] == STATE_ERROR)
219 static const char *state_name[4] =
221 N_("%s is not allowed (1) before a command to specify the "
222 "input program, such as DATA LIST, (2) between FILE TYPE "
223 "and END FILE TYPE, (3) between INPUT PROGRAM and END "
225 N_("%s is not allowed within an input program."),
226 N_("%s is only allowed within an input program."),
227 N_("%s is only allowed within an input program."),
230 msg (SE, gettext (state_name[pgm_state]), cp->name);
234 /* The structured output manager numbers all its tables. Increment
235 the major table number for each separate procedure. */
241 /* Call the command dispatcher. Save and restore the name of
242 the current command around this call. */
244 const char *prev_proc;
246 prev_proc = cur_proc;
248 result = cp->func ();
249 cur_proc = prev_proc;
252 /* Perform the state transition if the command completed
253 successfully (at least in part). */
254 if (result != CMD_FAILURE)
256 pgm_state = cp->transition[pgm_state];
258 if (pgm_state == STATE_ERROR)
260 discard_variables ();
261 pgm_state = STATE_INIT;
265 /* Pass the command's success value up to the caller. */
271 match_strings (const char *a, size_t a_len,
272 const char *b, size_t b_len)
274 size_t match_len = 0;
276 while (a_len > 0 && b_len > 0)
278 /* Mismatch always returns zero. */
291 /* Returns the first character in the first word in STRING,
292 storing the word's length in *WORD_LEN. If no words remain,
293 returns a null pointer and stores 0 in *WORD_LEN. Words are
294 sequences of alphanumeric characters or single
295 non-alphanumeric characters. Words are delimited by
298 find_word (const char *string, size_t *word_len)
300 /* Skip whitespace and asterisks. */
301 while (isspace (*string))
311 /* Special one-character word? */
312 if (!isalnum ((unsigned char) *string))
318 /* Alphanumeric word. */
320 while (isalnum ((unsigned char) string[*word_len]))
326 /* Returns nonzero if strings A and B can be confused based on
327 their first three letters. */
329 conflicting_3char_prefixes (const char *a, const char *b)
331 size_t aw_len, bw_len;
334 aw = find_word (a, &aw_len);
335 bw = find_word (b, &bw_len);
336 assert (aw != NULL && bw != NULL);
338 /* Words that are the same don't conflict. */
339 if (aw_len == bw_len && !memcmp (aw, bw, aw_len))
342 /* Words that are otherwise the same in the first three letters
344 return ((aw_len > 3 && bw_len > 3)
345 || (aw_len == 3 && bw_len > 3)
346 || (bw_len == 3 && aw_len > 3)) && !memcmp (aw, bw, 3);
349 /* Returns nonzero if CMD can be confused with another command
350 based on the first three letters of its first word. */
352 conflicting_3char_prefix_command (const struct command *cmd)
354 assert (cmd >= commands && cmd < commands + COMMAND_CNT);
356 return ((cmd > commands
357 && conflicting_3char_prefixes (cmd[-1].name, cmd[0].name))
358 || (cmd < commands + COMMAND_CNT
359 && conflicting_3char_prefixes (cmd[0].name, cmd[1].name)));
362 /* Ways that a set of words can match a command name. */
365 MISMATCH, /* Not a match. */
366 PARTIAL_MATCH, /* The words begin the command name. */
367 COMPLETE_MATCH /* The words are the command name. */
370 /* Figures out how well the WORD_CNT words in WORDS match CMD,
371 and returns the appropriate enum value. If WORDS are a
372 partial match for CMD and the next word in CMD is a dash, then
373 *DASH_POSSIBLE is set to 1 if DASH_POSSIBLE is non-null;
374 otherwise, *DASH_POSSIBLE is unchanged. */
375 static enum command_match
376 cmd_match_words (const struct command *cmd,
377 char *const words[], size_t word_cnt,
384 for (word = find_word (cmd->name, &word_len), word_idx = 0;
385 word != NULL && word_idx < word_cnt;
386 word = find_word (word + word_len, &word_len), word_idx++)
387 if (word_len != strlen (words[word_idx])
388 || memcmp (word, words[word_idx], word_len))
390 size_t match_chars = match_strings (word, word_len,
392 strlen (words[word_idx]));
393 if (match_chars == 0)
398 else if (match_chars == 1 || match_chars == 2)
400 /* One- and two-character abbreviations are not
404 else if (match_chars == 3)
406 /* Three-character abbreviations are acceptable
407 in the first word of a command if there are
408 no name conflicts. They are always
409 acceptable after the first word. */
410 if (word_idx == 0 && conflicting_3char_prefix_command (cmd))
413 else /* match_chars > 3 */
415 /* Four-character and longer abbreviations are
416 always acceptable. */
420 if (word == NULL && word_idx == word_cnt)
422 /* cmd->name = "FOO BAR", words[] = {"FOO", "BAR"}. */
423 return COMPLETE_MATCH;
425 else if (word == NULL)
427 /* cmd->name = "FOO BAR", words[] = {"FOO", "BAR", "BAZ"}. */
432 /* cmd->name = "FOO BAR BAZ", words[] = {"FOO", "BAR"}. */
433 if (word[0] == '-' && dash_possible != NULL)
435 return PARTIAL_MATCH;
439 /* Returns the number of commands for which the WORD_CNT words in
440 WORDS are a partial or complete match. If some partial match
441 has a dash as the next word, then *DASH_POSSIBLE is set to 1,
442 otherwise it is set to 0. */
444 count_matching_commands (char *const words[], size_t word_cnt,
447 const struct command *cmd;
452 for (cmd = commands; cmd < commands + COMMAND_CNT; cmd++)
453 if (cmd_match_words (cmd, words, word_cnt, dash_possible) != MISMATCH)
456 return cmd_match_count;
459 /* Returns the command for which the WORD_CNT words in WORDS are
460 a complete match. Returns a null pointer if no such command
462 static const struct command *
463 get_complete_match (char *const words[], size_t word_cnt)
465 const struct command *cmd;
467 for (cmd = commands; cmd < commands + COMMAND_CNT; cmd++)
468 if (cmd_match_words (cmd, words, word_cnt, NULL) == COMPLETE_MATCH)
474 /* Frees the WORD_CNT words in WORDS. */
476 free_words (char *words[], size_t word_cnt)
480 for (idx = 0; idx < word_cnt; idx++)
484 /* Flags an error that the command whose name is given by the
485 WORD_CNT words in WORDS is unknown. */
487 unknown_command_error (char *const words[], size_t word_cnt)
494 for (idx = 0; idx < word_cnt; idx++)
495 words_len += strlen (words[idx]);
497 cp = name = xmalloc (words_len + word_cnt + 16);
498 for (idx = 0; idx < word_cnt; idx++)
502 cp = stpcpy (cp, words[idx]);
506 msg (SE, _("Unknown command %s."), name);
512 /* Parse the command name and return a pointer to the corresponding
513 struct command if successful.
514 If not successful, return a null pointer. */
515 static const struct command *
516 parse_command_name (void)
520 int complete_word_cnt;
524 word_cnt = complete_word_cnt = 0;
525 while (token == T_ID || (dash_possible && token == '-'))
529 assert (word_cnt < sizeof words / sizeof *words);
531 words[word_cnt++] = xstrdup (ds_c_str (&tokstr));
533 words[word_cnt++] = xstrdup ("-");
535 cmd_match_cnt = count_matching_commands (words, word_cnt,
537 if (cmd_match_cnt == 0)
539 else if (cmd_match_cnt == 1)
541 const struct command *command = get_complete_match (words, word_cnt);
544 if (command->skip_entire_name)
546 free_words (words, word_cnt);
550 else /* cmd_match_cnt > 1 */
552 /* Do we have a complete command name so far? */
553 if (get_complete_match (words, word_cnt) != NULL)
554 complete_word_cnt = word_cnt;
559 /* If we saw a complete command name earlier, drop back to
561 if (complete_word_cnt)
563 int pushback_word_cnt;
564 const struct command *command;
566 /* Get the command. */
567 command = get_complete_match (words, complete_word_cnt);
568 assert (command != NULL);
570 /* Figure out how many words we want to keep.
571 We normally want to swallow the entire command. */
572 pushback_word_cnt = complete_word_cnt + 1;
573 if (!command->skip_entire_name)
576 /* FIXME: We only support one-token pushback. */
577 assert (pushback_word_cnt + 1 >= word_cnt);
579 while (word_cnt > pushback_word_cnt)
582 if (strcmp (words[word_cnt], "-"))
583 lex_put_back_id (words[word_cnt]);
586 free (words[word_cnt]);
589 free_words (words, word_cnt);
593 unknown_command_error (words, word_cnt);
594 free_words (words, word_cnt);
598 /* Simple commands. */
600 /* Parse and execute EXIT command. */
604 if (getl_reading_script)
606 msg (SE, _("This command is not accepted in a syntax file. "
607 "Instead, use FINISH to terminate a syntax file."));
616 /* Parse and execute FINISH command. */
620 /* Do not check for `.'
621 Do not fetch any extra tokens. */
622 if (getl_interactive)
624 msg (SM, _("This command is not executed "
625 "in interactive mode. Instead, PSPP drops "
626 "down to the command prompt. Use EXIT if you really want "
636 /* Parses the N command. */
638 cmd_n_of_cases (void)
643 if (!lex_force_int ())
647 if (!lex_match_id ("ESTIMATED"))
648 dict_set_case_limit (default_dict, x);
650 return lex_end_of_command ();
653 /* Parses, performs the EXECUTE procedure. */
657 procedure (NULL, NULL);
658 return lex_end_of_command ();
661 /* Parses, performs the ERASE command. */
667 msg (SE, _("This command not allowed when the SAFER option is set."));
671 if (!lex_force_match_id ("FILE"))
674 if (!lex_force_string ())
677 if (remove (ds_c_str (&tokstr)) == -1)
679 msg (SW, _("Error removing `%s': %s."),
680 ds_c_str (&tokstr), strerror (errno));
688 /* Spawn a shell process. */
699 const char *shell_fn;
705 for (i = 3; i < 20; i++)
709 shell_fn = getenv ("SHELL");
710 if (shell_fn == NULL)
711 shell_fn = "/bin/sh";
714 const char *cp = strrchr (shell_fn, '/');
715 cp = cp ? &cp[1] : shell_fn;
716 shell_process = local_alloc (strlen (cp) + 8);
717 strcpy (shell_process, "-");
718 strcat (shell_process, cp);
719 if (strcmp (cp, "sh"))
720 shell_process[0] = '+';
723 execl (shell_fn, shell_process, NULL);
729 msg (SE, _("Couldn't fork: %s."), strerror (errno));
734 while (wait (NULL) != pid)
741 /* Parses the HOST command argument and executes the specified
742 command. Returns a suitable command return code. */
749 /* Handle either a string argument or a full-line argument. */
751 int c = lex_look_ahead ();
753 if (c == '\'' || c == '"')
756 if (!lex_force_string ())
758 cmd = ds_c_str (&tokstr);
763 cmd = lex_rest_of_line (NULL);
769 /* Execute the command. */
770 if (system (cmd) == -1)
771 msg (SE, _("Error executing command: %s."), strerror (errno));
773 /* Finish parsing. */
780 lex_error (_("expecting end of command"));
781 return CMD_TRAILING_GARBAGE;
790 /* Parses, performs the HOST command. */
798 msg (SE, _("This command not allowed when the SAFER option is set."));
803 /* Figure out whether to invoke an interactive shell or to execute a
804 single shell command. */
805 if (lex_look_ahead () == '.')
808 code = shell () ? CMD_PART_SUCCESS_MAYBE : CMD_SUCCESS;
811 code = run_command ();
813 /* Make sure that the system has a command interpreter, then run a
815 if (system (NULL) != 0)
816 code = run_command ();
819 msg (SE, _("No operating system support for this command."));
824 return code ? CMD_FAILURE : CMD_SUCCESS;
827 /* Parses, performs the NEW FILE command. */
831 discard_variables ();
833 return lex_end_of_command ();
836 /* Parses, performs the CLEAR TRANSFORMATIONS command. */
838 cmd_clear_transformations (void)
840 if (getl_reading_script)
842 msg (SW, _("This command is not valid in a syntax file."));
846 cancel_transformations ();
847 /* FIXME: what about variables created by transformations?
848 They need to be properly initialized. */