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., 51 Franklin Street, Fifth Floor, Boston, MA
28 #include "dictionary.h"
49 /* Global variables. */
51 /* A STATE_* constant giving the current program state. */
54 /* The name of the procedure currently executing, if any. */
57 /* Static variables. */
59 /* A single command. */
62 const char *name; /* Command name. */
63 int transition[4]; /* Transitions to make from each state. */
64 int (*func) (void); /* Function to call. */
65 int skip_entire_name; /* If zero, we don't skip the
66 final token in the command name. */
67 short debug; /* Set if this cmd available only in test mode*/
70 /* Define the command array. */
71 #define DEFCMD(NAME, T1, T2, T3, T4, FUNC) \
72 {NAME, {T1, T2, T3, T4}, FUNC, 1, 0},
73 #define DBGCMD(NAME, T1, T2, T3, T4, FUNC) \
74 {NAME, {T1, T2, T3, T4}, FUNC, 1, 1},
75 #define SPCCMD(NAME, T1, T2, T3, T4, FUNC) \
76 {NAME, {T1, T2, T3, T4}, FUNC, 0, 0},
77 #define UNIMPL(NAME, T1, T2, T3, T4) \
78 {NAME, {T1, T2, T3, T4}, NULL, 1, 0},
79 static const struct command commands[] =
81 #include "command.def"
88 /* Complete the line using the name of a command,
89 * based upon the current prg_state
92 pspp_completion_function (const char *text, int state)
95 const struct command *cmd = 0;
99 if ( state + skip >= sizeof(commands)/ sizeof(struct command))
105 cmd = &commands[state + skip];
107 if ( cmd->transition[pgm_state] == STATE_ERROR || ( cmd->debug && ! test_mode ) )
113 if ( text == 0 || 0 == strncasecmp (cmd->name, text, strlen(text)))
122 return xstrdup(cmd->name);
128 #define COMMAND_CNT (sizeof commands / sizeof *commands)
130 /* Command parser. */
132 static const struct command *parse_command_name (void);
134 /* Determines whether command C is appropriate to call in this
135 part of a FILE TYPE structure. */
137 FILE_TYPE_okay (const struct command *c)
141 if (c->func != cmd_record_type
142 && c->func != cmd_data_list
143 && c->func != cmd_repeating_data
144 && c->func != cmd_end_file_type)
145 msg (SE, _("%s not allowed inside FILE TYPE/END FILE TYPE."), c->name);
148 else if (c->func == cmd_repeating_data && fty.type == FTY_GROUPED)
149 msg (SE, _("%s not allowed inside FILE TYPE GROUPED/END FILE TYPE."),
151 else if (!fty.had_rec_type && c->func != cmd_record_type)
152 msg (SE, _("RECORD TYPE must be the first command inside a "
153 "FILE TYPE structure."));
159 if (c->func == cmd_record_type)
160 fty.had_rec_type = 1;
166 /* Parses an entire PSPP command. This includes everything from the
167 command name to the terminating dot. Does most of its work by
168 passing it off to the respective command dispatchers. Only called
169 by parse() in main.c. */
173 const struct command *cp; /* Iterator used to find the proper command. */
176 /* The generic alloca package performs garbage collection when it is
177 called with an argument of zero. */
179 #endif /* C_ALLOCA */
181 /* Null commands can result from extra empty lines. */
185 /* Parse comments. */
186 if ((token == T_ID && !strcasecmp (tokid, "COMMENT"))
187 || token == T_EXP || token == '*' || token == '[')
193 /* Otherwise the line must begin with a command name, which is
194 always an ID token. */
197 lex_error (_("expecting command name"));
201 /* Parse the command name. */
202 cp = parse_command_name ();
205 if (cp->func == NULL)
207 msg (SE, _("%s is not yet implemented."), cp->name);
208 while (token && token != '.')
213 /* If we're in a FILE TYPE structure, only certain commands can be
215 if (pgm_state == STATE_INPUT
216 && case_source_is_class (vfm_source, &file_type_source_class)
217 && !FILE_TYPE_okay (cp))
220 /* Certain state transitions are not allowed. Check for these. */
221 assert (pgm_state >= 0 && pgm_state < STATE_ERROR);
222 if (cp->transition[pgm_state] == STATE_ERROR)
224 static const char *state_name[4] =
226 N_("%s is not allowed (1) before a command to specify the "
227 "input program, such as DATA LIST, (2) between FILE TYPE "
228 "and END FILE TYPE, (3) between INPUT PROGRAM and END "
230 N_("%s is not allowed within an input program."),
231 N_("%s is only allowed within an input program."),
232 N_("%s is only allowed within an input program."),
235 msg (SE, gettext (state_name[pgm_state]), cp->name);
239 /* The structured output manager numbers all its tables. Increment
240 the major table number for each separate procedure. */
246 /* Call the command dispatcher. Save and restore the name of
247 the current command around this call. */
249 const char *prev_proc;
251 prev_proc = cur_proc;
253 result = cp->func ();
254 cur_proc = prev_proc;
257 /* Perform the state transition if the command completed
258 successfully (at least in part). */
259 if (result != CMD_FAILURE)
261 pgm_state = cp->transition[pgm_state];
263 if (pgm_state == STATE_ERROR)
265 discard_variables ();
266 pgm_state = STATE_INIT;
270 /* Pass the command's success value up to the caller. */
276 match_strings (const char *a, size_t a_len,
277 const char *b, size_t b_len)
279 size_t match_len = 0;
281 while (a_len > 0 && b_len > 0)
283 /* Mismatch always returns zero. */
284 if (toupper ((unsigned char) *a++) != toupper ((unsigned char) *b++))
296 /* Returns the first character in the first word in STRING,
297 storing the word's length in *WORD_LEN. If no words remain,
298 returns a null pointer and stores 0 in *WORD_LEN. Words are
299 sequences of alphanumeric characters or single
300 non-alphanumeric characters. Words are delimited by
303 find_word (const char *string, size_t *word_len)
305 /* Skip whitespace and asterisks. */
306 while (isspace (*string))
316 /* Special one-character word? */
317 if (!isalnum ((unsigned char) *string))
323 /* Alphanumeric word. */
325 while (isalnum ((unsigned char) string[*word_len]))
331 /* Returns nonzero if strings A and B can be confused based on
332 their first three letters. */
334 conflicting_3char_prefixes (const char *a, const char *b)
336 size_t aw_len, bw_len;
339 aw = find_word (a, &aw_len);
340 bw = find_word (b, &bw_len);
341 assert (aw != NULL && bw != NULL);
343 /* Words that are the same don't conflict. */
344 if (aw_len == bw_len && !mm_case_compare (aw, bw, aw_len))
347 /* Words that are otherwise the same in the first three letters
349 return ((aw_len > 3 && bw_len > 3)
350 || (aw_len == 3 && bw_len > 3)
351 || (bw_len == 3 && aw_len > 3)) && !mm_case_compare (aw, bw, 3);
354 /* Returns nonzero if CMD can be confused with another command
355 based on the first three letters of its first word. */
357 conflicting_3char_prefix_command (const struct command *cmd)
359 assert (cmd >= commands && cmd < commands + COMMAND_CNT);
361 return ((cmd > commands
362 && conflicting_3char_prefixes (cmd[-1].name, cmd[0].name))
363 || (cmd < commands + COMMAND_CNT
364 && conflicting_3char_prefixes (cmd[0].name, cmd[1].name)));
367 /* Ways that a set of words can match a command name. */
370 MISMATCH, /* Not a match. */
371 PARTIAL_MATCH, /* The words begin the command name. */
372 COMPLETE_MATCH /* The words are the command name. */
375 /* Figures out how well the WORD_CNT words in WORDS match CMD,
376 and returns the appropriate enum value. If WORDS are a
377 partial match for CMD and the next word in CMD is a dash, then
378 *DASH_POSSIBLE is set to 1 if DASH_POSSIBLE is non-null;
379 otherwise, *DASH_POSSIBLE is unchanged. */
380 static enum command_match
381 cmd_match_words (const struct command *cmd,
382 char *const words[], size_t word_cnt,
389 for (word = find_word (cmd->name, &word_len), word_idx = 0;
390 word != NULL && word_idx < word_cnt;
391 word = find_word (word + word_len, &word_len), word_idx++)
392 if (word_len != strlen (words[word_idx])
393 || mm_case_compare (word, words[word_idx], word_len))
395 size_t match_chars = match_strings (word, word_len,
397 strlen (words[word_idx]));
398 if (match_chars == 0)
403 else if (match_chars == 1 || match_chars == 2)
405 /* One- and two-character abbreviations are not
409 else if (match_chars == 3)
411 /* Three-character abbreviations are acceptable
412 in the first word of a command if there are
413 no name conflicts. They are always
414 acceptable after the first word. */
415 if (word_idx == 0 && conflicting_3char_prefix_command (cmd))
418 else /* match_chars > 3 */
420 /* Four-character and longer abbreviations are
421 always acceptable. */
425 if (word == NULL && word_idx == word_cnt)
427 /* cmd->name = "FOO BAR", words[] = {"FOO", "BAR"}. */
428 return COMPLETE_MATCH;
430 else if (word == NULL)
432 /* cmd->name = "FOO BAR", words[] = {"FOO", "BAR", "BAZ"}. */
437 /* cmd->name = "FOO BAR BAZ", words[] = {"FOO", "BAR"}. */
438 if (word[0] == '-' && dash_possible != NULL)
440 return PARTIAL_MATCH;
444 /* Returns the number of commands for which the WORD_CNT words in
445 WORDS are a partial or complete match. If some partial match
446 has a dash as the next word, then *DASH_POSSIBLE is set to 1,
447 otherwise it is set to 0. */
449 count_matching_commands (char *const words[], size_t word_cnt,
452 const struct command *cmd;
457 for (cmd = commands; cmd < commands + COMMAND_CNT; cmd++)
458 if (cmd_match_words (cmd, words, word_cnt, dash_possible) != MISMATCH)
461 return cmd_match_count;
464 /* Returns the command for which the WORD_CNT words in WORDS are
465 a complete match. Returns a null pointer if no such command
467 static const struct command *
468 get_complete_match (char *const words[], size_t word_cnt)
470 const struct command *cmd;
472 for (cmd = commands; cmd < commands + COMMAND_CNT; cmd++)
473 if (cmd_match_words (cmd, words, word_cnt, NULL) == COMPLETE_MATCH)
479 /* Frees the WORD_CNT words in WORDS. */
481 free_words (char *words[], size_t word_cnt)
485 for (idx = 0; idx < word_cnt; idx++)
489 /* Flags an error that the command whose name is given by the
490 WORD_CNT words in WORDS is unknown. */
492 unknown_command_error (char *const words[], size_t word_cnt)
499 for (idx = 0; idx < word_cnt; idx++)
500 words_len += strlen (words[idx]);
502 cp = name = xmalloc (words_len + word_cnt + 16);
503 for (idx = 0; idx < word_cnt; idx++)
507 cp = stpcpy (cp, words[idx]);
511 msg (SE, _("Unknown command %s."), name);
517 /* Parse the command name and return a pointer to the corresponding
518 struct command if successful.
519 If not successful, return a null pointer. */
520 static const struct command *
521 parse_command_name (void)
525 int complete_word_cnt;
529 word_cnt = complete_word_cnt = 0;
530 while (token == T_ID || (dash_possible && token == '-'))
534 assert (word_cnt < sizeof words / sizeof *words);
536 words[word_cnt++] = xstrdup (ds_c_str (&tokstr));
538 words[word_cnt++] = xstrdup ("-");
540 cmd_match_cnt = count_matching_commands (words, word_cnt,
542 if (cmd_match_cnt == 0)
544 else if (cmd_match_cnt == 1)
546 const struct command *command = get_complete_match (words, word_cnt);
549 if (command->skip_entire_name)
551 if ( command->debug & !test_mode )
553 free_words (words, word_cnt);
557 else /* cmd_match_cnt > 1 */
559 /* Do we have a complete command name so far? */
560 if (get_complete_match (words, word_cnt) != NULL)
561 complete_word_cnt = word_cnt;
566 /* If we saw a complete command name earlier, drop back to
568 if (complete_word_cnt)
570 int pushback_word_cnt;
571 const struct command *command;
573 /* Get the command. */
574 command = get_complete_match (words, complete_word_cnt);
575 assert (command != NULL);
577 /* Figure out how many words we want to keep.
578 We normally want to swallow the entire command. */
579 pushback_word_cnt = complete_word_cnt + 1;
580 if (!command->skip_entire_name)
583 /* FIXME: We only support one-token pushback. */
584 assert (pushback_word_cnt + 1 >= word_cnt);
586 while (word_cnt > pushback_word_cnt)
589 if (strcmp (words[word_cnt], "-"))
590 lex_put_back_id (words[word_cnt]);
593 free (words[word_cnt]);
596 if ( command->debug && !test_mode )
599 free_words (words, word_cnt);
604 unknown_command_error (words, word_cnt);
605 free_words (words, word_cnt);
609 /* Simple commands. */
611 /* Parse and execute EXIT command. */
615 if (getl_reading_script)
617 msg (SE, _("This command is not accepted in a syntax file. "
618 "Instead, use FINISH to terminate a syntax file."));
627 /* Parse and execute FINISH command. */
631 /* Do not check for `.'
632 Do not fetch any extra tokens. */
633 if (getl_interactive)
635 msg (SM, _("This command is not executed "
636 "in interactive mode. Instead, PSPP drops "
637 "down to the command prompt. Use EXIT if you really want "
647 /* Parses the N command. */
649 cmd_n_of_cases (void)
654 if (!lex_force_int ())
658 if (!lex_match_id ("ESTIMATED"))
659 dict_set_case_limit (default_dict, x);
661 return lex_end_of_command ();
664 /* Parses, performs the EXECUTE procedure. */
668 procedure (NULL, NULL);
669 return lex_end_of_command ();
672 /* Parses, performs the ERASE command. */
678 msg (SE, _("This command not allowed when the SAFER option is set."));
682 if (!lex_force_match_id ("FILE"))
685 if (!lex_force_string ())
688 if (remove (ds_c_str (&tokstr)) == -1)
690 msg (SW, _("Error removing `%s': %s."),
691 ds_c_str (&tokstr), strerror (errno));
699 /* Spawn a shell process. */
710 const char *shell_fn;
716 for (i = 3; i < 20; i++)
720 shell_fn = getenv ("SHELL");
721 if (shell_fn == NULL)
722 shell_fn = "/bin/sh";
725 const char *cp = strrchr (shell_fn, '/');
726 cp = cp ? &cp[1] : shell_fn;
727 shell_process = local_alloc (strlen (cp) + 8);
728 strcpy (shell_process, "-");
729 strcat (shell_process, cp);
730 if (strcmp (cp, "sh"))
731 shell_process[0] = '+';
734 execl (shell_fn, shell_process, NULL);
740 msg (SE, _("Couldn't fork: %s."), strerror (errno));
745 while (wait (NULL) != pid)
752 /* Parses the HOST command argument and executes the specified
753 command. Returns a suitable command return code. */
760 /* Handle either a string argument or a full-line argument. */
762 int c = lex_look_ahead ();
764 if (c == '\'' || c == '"')
767 if (!lex_force_string ())
769 cmd = ds_c_str (&tokstr);
774 cmd = lex_rest_of_line (NULL);
780 /* Execute the command. */
781 if (system (cmd) == -1)
782 msg (SE, _("Error executing command: %s."), strerror (errno));
784 /* Finish parsing. */
791 lex_error (_("expecting end of command"));
792 return CMD_TRAILING_GARBAGE;
801 /* Parses, performs the HOST command. */
809 msg (SE, _("This command not allowed when the SAFER option is set."));
814 /* Figure out whether to invoke an interactive shell or to execute a
815 single shell command. */
816 if (lex_look_ahead () == '.')
819 code = shell () ? CMD_PART_SUCCESS_MAYBE : CMD_SUCCESS;
822 code = run_command ();
824 /* Make sure that the system has a command interpreter, then run a
826 if (system (NULL) != 0)
827 code = run_command ();
830 msg (SE, _("No operating system support for this command."));
835 return code ? CMD_FAILURE : CMD_SUCCESS;
838 /* Parses, performs the NEW FILE command. */
842 discard_variables ();
844 return lex_end_of_command ();
847 /* Parses, performs the CLEAR TRANSFORMATIONS command. */
849 cmd_clear_transformations (void)
851 if (getl_reading_script)
853 msg (SW, _("This command is not valid in a syntax file."));
857 cancel_transformations ();
858 /* FIXME: what about variables created by transformations?
859 They need to be properly initialized. */