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"
50 #define _(msgid) gettext (msgid)
51 #define N_(msgid) msgid
53 /* Global variables. */
55 /* A STATE_* constant giving the current program state. */
58 /* The name of the procedure currently executing, if any. */
61 /* Static variables. */
63 /* A single command. */
66 const char *name; /* Command name. */
67 int transition[4]; /* Transitions to make from each state. */
68 int (*func) (void); /* Function to call. */
69 int skip_entire_name; /* If zero, we don't skip the
70 final token in the command name. */
71 short debug; /* Set if this cmd available only in test mode*/
74 /* Define the command array. */
75 #define DEFCMD(NAME, T1, T2, T3, T4, FUNC) \
76 {NAME, {T1, T2, T3, T4}, FUNC, 1, 0},
77 #define DBGCMD(NAME, T1, T2, T3, T4, FUNC) \
78 {NAME, {T1, T2, T3, T4}, FUNC, 1, 1},
79 #define SPCCMD(NAME, T1, T2, T3, T4, FUNC) \
80 {NAME, {T1, T2, T3, T4}, FUNC, 0, 0},
81 #define UNIMPL(NAME, T1, T2, T3, T4, DESC) \
82 {NAME, {T1, T2, T3, T4}, NULL, 1, 0},
83 static const struct command commands[] =
85 #include "command.def"
92 /* Complete the line using the name of a command,
93 * based upon the current prg_state
96 pspp_completion_function (const char *text, int state)
99 const struct command *cmd = 0;
103 if ( state + skip >= sizeof(commands)/ sizeof(struct command))
109 cmd = &commands[state + skip];
111 if ( cmd->transition[pgm_state] == STATE_ERROR || ( cmd->debug && ! get_testing_mode () ) )
117 if ( text == 0 || 0 == strncasecmp (cmd->name, text, strlen(text)))
126 return xstrdup(cmd->name);
132 #define COMMAND_CNT (sizeof commands / sizeof *commands)
134 /* Command parser. */
136 static const struct command *parse_command_name (void);
138 /* Determines whether command C is appropriate to call in this
139 part of a FILE TYPE structure. */
141 FILE_TYPE_okay (const struct command *c UNUSED)
146 if (c->func != cmd_record_type
147 && c->func != cmd_data_list
148 && c->func != cmd_repeating_data
149 && c->func != cmd_end_file_type)
150 msg (SE, _("%s not allowed inside FILE TYPE/END FILE TYPE."), c->name);
152 else if (c->func == cmd_repeating_data && fty.type == FTY_GROUPED)
153 msg (SE, _("%s not allowed inside FILE TYPE GROUPED/END FILE TYPE."),
155 else if (!fty.had_rec_type && c->func != cmd_record_type)
156 msg (SE, _("RECORD TYPE must be the first command inside a "
157 "FILE TYPE structure."));
161 if (c->func == cmd_record_type)
162 fty.had_rec_type = 1;
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. */
179 const struct command *cp; /* Iterator used to find the proper command. */
182 /* The generic alloca package performs garbage collection when it is
183 called with an argument of zero. */
185 #endif /* C_ALLOCA */
187 /* Null commands can result from extra empty lines. */
191 /* Parse comments. */
192 if ((token == T_ID && !strcasecmp (tokid, "COMMENT"))
193 || token == T_EXP || token == '*' || token == '[')
199 /* Otherwise the line must begin with a command name, which is
200 always an ID token. */
203 lex_error (_("expecting command name"));
207 /* Parse the command name. */
208 cp = parse_command_name ();
211 if (cp->func == NULL)
213 msg (SE, _("%s is not yet implemented."), cp->name);
214 while (token && token != '.')
219 /* If we're in a FILE TYPE structure, only certain commands can be
221 if (pgm_state == STATE_INPUT
222 && case_source_is_class (vfm_source, &file_type_source_class)
223 && !FILE_TYPE_okay (cp))
226 /* Certain state transitions are not allowed. Check for these. */
227 assert (pgm_state >= 0 && pgm_state < STATE_ERROR);
228 if (cp->transition[pgm_state] == STATE_ERROR)
230 static const char *state_name[4] =
232 N_("%s is not allowed (1) before a command to specify the "
233 "input program, such as DATA LIST, (2) between FILE TYPE "
234 "and END FILE TYPE, (3) between INPUT PROGRAM and END "
236 N_("%s is not allowed within an input program."),
237 N_("%s is only allowed within an input program."),
238 N_("%s is only allowed within an input program."),
241 msg (SE, gettext (state_name[pgm_state]), cp->name);
245 /* The structured output manager numbers all its tables. Increment
246 the major table number for each separate procedure. */
252 /* Call the command dispatcher. Save and restore the name of
253 the current command around this call. */
255 const char *prev_proc;
257 prev_proc = cur_proc;
259 result = cp->func ();
260 cur_proc = prev_proc;
263 /* Perform the state transition if the command completed
264 successfully (at least in part). */
265 if (result != CMD_FAILURE)
267 pgm_state = cp->transition[pgm_state];
269 if (pgm_state == STATE_ERROR)
271 discard_variables ();
272 pgm_state = STATE_INIT;
276 /* Pass the command's success value up to the caller. */
282 match_strings (const char *a, size_t a_len,
283 const char *b, size_t b_len)
285 size_t match_len = 0;
287 while (a_len > 0 && b_len > 0)
289 /* Mismatch always returns zero. */
290 if (toupper ((unsigned char) *a++) != toupper ((unsigned char) *b++))
302 /* Returns the first character in the first word in STRING,
303 storing the word's length in *WORD_LEN. If no words remain,
304 returns a null pointer and stores 0 in *WORD_LEN. Words are
305 sequences of alphanumeric characters or single
306 non-alphanumeric characters. Words are delimited by
309 find_word (const char *string, size_t *word_len)
311 /* Skip whitespace and asterisks. */
312 while (isspace ((unsigned char) *string))
322 /* Special one-character word? */
323 if (!isalnum ((unsigned char) *string))
329 /* Alphanumeric word. */
331 while (isalnum ((unsigned char) string[*word_len]))
337 /* Returns nonzero if strings A and B can be confused based on
338 their first three letters. */
340 conflicting_3char_prefixes (const char *a, const char *b)
342 size_t aw_len, bw_len;
345 aw = find_word (a, &aw_len);
346 bw = find_word (b, &bw_len);
347 assert (aw != NULL && bw != NULL);
349 /* Words that are the same don't conflict. */
350 if (aw_len == bw_len && !buf_compare_case (aw, bw, aw_len))
353 /* Words that are otherwise the same in the first three letters
355 return ((aw_len > 3 && bw_len > 3)
356 || (aw_len == 3 && bw_len > 3)
357 || (bw_len == 3 && aw_len > 3)) && !buf_compare_case (aw, bw, 3);
360 /* Returns nonzero if CMD can be confused with another command
361 based on the first three letters of its first word. */
363 conflicting_3char_prefix_command (const struct command *cmd)
365 assert (cmd >= commands && cmd < commands + COMMAND_CNT);
367 return ((cmd > commands
368 && conflicting_3char_prefixes (cmd[-1].name, cmd[0].name))
369 || (cmd < commands + COMMAND_CNT
370 && conflicting_3char_prefixes (cmd[0].name, cmd[1].name)));
373 /* Ways that a set of words can match a command name. */
376 MISMATCH, /* Not a match. */
377 PARTIAL_MATCH, /* The words begin the command name. */
378 COMPLETE_MATCH /* The words are the command name. */
381 /* Figures out how well the WORD_CNT words in WORDS match CMD,
382 and returns the appropriate enum value. If WORDS are a
383 partial match for CMD and the next word in CMD is a dash, then
384 *DASH_POSSIBLE is set to 1 if DASH_POSSIBLE is non-null;
385 otherwise, *DASH_POSSIBLE is unchanged. */
386 static enum command_match
387 cmd_match_words (const struct command *cmd,
388 char *const words[], size_t word_cnt,
395 for (word = find_word (cmd->name, &word_len), word_idx = 0;
396 word != NULL && word_idx < word_cnt;
397 word = find_word (word + word_len, &word_len), word_idx++)
398 if (word_len != strlen (words[word_idx])
399 || buf_compare_case (word, words[word_idx], word_len))
401 size_t match_chars = match_strings (word, word_len,
403 strlen (words[word_idx]));
404 if (match_chars == 0)
409 else if (match_chars == 1 || match_chars == 2)
411 /* One- and two-character abbreviations are not
415 else if (match_chars == 3)
417 /* Three-character abbreviations are acceptable
418 in the first word of a command if there are
419 no name conflicts. They are always
420 acceptable after the first word. */
421 if (word_idx == 0 && conflicting_3char_prefix_command (cmd))
424 else /* match_chars > 3 */
426 /* Four-character and longer abbreviations are
427 always acceptable. */
431 if (word == NULL && word_idx == word_cnt)
433 /* cmd->name = "FOO BAR", words[] = {"FOO", "BAR"}. */
434 return COMPLETE_MATCH;
436 else if (word == NULL)
438 /* cmd->name = "FOO BAR", words[] = {"FOO", "BAR", "BAZ"}. */
443 /* cmd->name = "FOO BAR BAZ", words[] = {"FOO", "BAR"}. */
444 if (word[0] == '-' && dash_possible != NULL)
446 return PARTIAL_MATCH;
450 /* Returns the number of commands for which the WORD_CNT words in
451 WORDS are a partial or complete match. If some partial match
452 has a dash as the next word, then *DASH_POSSIBLE is set to 1,
453 otherwise it is set to 0. */
455 count_matching_commands (char *const words[], size_t word_cnt,
458 const struct command *cmd;
463 for (cmd = commands; cmd < commands + COMMAND_CNT; cmd++)
464 if (cmd_match_words (cmd, words, word_cnt, dash_possible) != MISMATCH)
467 return cmd_match_count;
470 /* Returns the command for which the WORD_CNT words in WORDS are
471 a complete match. Returns a null pointer if no such command
473 static const struct command *
474 get_complete_match (char *const words[], size_t word_cnt)
476 const struct command *cmd;
478 for (cmd = commands; cmd < commands + COMMAND_CNT; cmd++)
479 if (cmd_match_words (cmd, words, word_cnt, NULL) == COMPLETE_MATCH)
485 /* Frees the WORD_CNT words in WORDS. */
487 free_words (char *words[], size_t word_cnt)
491 for (idx = 0; idx < word_cnt; idx++)
495 /* Flags an error that the command whose name is given by the
496 WORD_CNT words in WORDS is unknown. */
498 unknown_command_error (char *const words[], size_t word_cnt)
505 for (idx = 0; idx < word_cnt; idx++)
506 words_len += strlen (words[idx]);
508 cp = name = xmalloc (words_len + word_cnt + 16);
509 for (idx = 0; idx < word_cnt; idx++)
513 cp = stpcpy (cp, words[idx]);
517 msg (SE, _("Unknown command %s."), name);
523 /* Parse the command name and return a pointer to the corresponding
524 struct command if successful.
525 If not successful, return a null pointer. */
526 static const struct command *
527 parse_command_name (void)
531 int complete_word_cnt;
535 word_cnt = complete_word_cnt = 0;
536 while (token == T_ID || (dash_possible && token == '-'))
540 assert (word_cnt < sizeof words / sizeof *words);
542 words[word_cnt++] = xstrdup (ds_c_str (&tokstr));
544 words[word_cnt++] = xstrdup ("-");
546 cmd_match_cnt = count_matching_commands (words, word_cnt,
548 if (cmd_match_cnt == 0)
550 else if (cmd_match_cnt == 1)
552 const struct command *command = get_complete_match (words, word_cnt);
555 if (command->skip_entire_name)
557 if ( command->debug & !get_testing_mode () )
559 free_words (words, word_cnt);
563 else /* cmd_match_cnt > 1 */
565 /* Do we have a complete command name so far? */
566 if (get_complete_match (words, word_cnt) != NULL)
567 complete_word_cnt = word_cnt;
572 /* If we saw a complete command name earlier, drop back to
574 if (complete_word_cnt)
576 int pushback_word_cnt;
577 const struct command *command;
579 /* Get the command. */
580 command = get_complete_match (words, complete_word_cnt);
581 assert (command != NULL);
583 /* Figure out how many words we want to keep.
584 We normally want to swallow the entire command. */
585 pushback_word_cnt = complete_word_cnt + 1;
586 if (!command->skip_entire_name)
589 /* FIXME: We only support one-token pushback. */
590 assert (pushback_word_cnt + 1 >= word_cnt);
592 while (word_cnt > pushback_word_cnt)
595 if (strcmp (words[word_cnt], "-"))
596 lex_put_back_id (words[word_cnt]);
599 free (words[word_cnt]);
602 if ( command->debug && !get_testing_mode () )
605 free_words (words, word_cnt);
610 unknown_command_error (words, word_cnt);
611 free_words (words, word_cnt);
615 /* Simple commands. */
617 /* Parse and execute EXIT command. */
621 if (getl_reading_script)
623 msg (SE, _("This command is not accepted in a syntax file. "
624 "Instead, use FINISH to terminate a syntax file."));
633 /* Parse and execute FINISH command. */
637 /* Do not check for `.'
638 Do not fetch any extra tokens. */
639 if (getl_interactive)
641 msg (SM, _("This command is not executed "
642 "in interactive mode. Instead, PSPP drops "
643 "down to the command prompt. Use EXIT if you really want "
653 /* Parses the N command. */
655 cmd_n_of_cases (void)
660 if (!lex_force_int ())
664 if (!lex_match_id ("ESTIMATED"))
665 dict_set_case_limit (default_dict, x);
667 return lex_end_of_command ();
670 /* Parses, performs the EXECUTE procedure. */
674 procedure (NULL, NULL);
675 return lex_end_of_command ();
678 /* Parses, performs the ERASE command. */
682 if (get_safer_mode ())
684 msg (SE, _("This command not allowed when the SAFER option is set."));
688 if (!lex_force_match_id ("FILE"))
691 if (!lex_force_string ())
694 if (remove (ds_c_str (&tokstr)) == -1)
696 msg (SW, _("Error removing `%s': %s."),
697 ds_c_str (&tokstr), strerror (errno));
705 /* Spawn a shell process. */
716 const char *shell_fn;
722 for (i = 3; i < 20; i++)
726 shell_fn = getenv ("SHELL");
727 if (shell_fn == NULL)
728 shell_fn = "/bin/sh";
731 const char *cp = strrchr (shell_fn, '/');
732 cp = cp ? &cp[1] : shell_fn;
733 shell_process = local_alloc (strlen (cp) + 8);
734 strcpy (shell_process, "-");
735 strcat (shell_process, cp);
736 if (strcmp (cp, "sh"))
737 shell_process[0] = '+';
740 execl (shell_fn, shell_process, NULL);
746 msg (SE, _("Couldn't fork: %s."), strerror (errno));
751 while (wait (NULL) != pid)
758 /* Parses the HOST command argument and executes the specified
759 command. Returns a suitable command return code. */
766 /* Handle either a string argument or a full-line argument. */
768 int c = lex_look_ahead ();
770 if (c == '\'' || c == '"')
773 if (!lex_force_string ())
775 cmd = ds_c_str (&tokstr);
780 cmd = lex_rest_of_line (NULL);
786 /* Execute the command. */
787 if (system (cmd) == -1)
788 msg (SE, _("Error executing command: %s."), strerror (errno));
790 /* Finish parsing. */
797 lex_error (_("expecting end of command"));
798 return CMD_TRAILING_GARBAGE;
807 /* Parses, performs the HOST command. */
813 if (get_safer_mode ())
815 msg (SE, _("This command not allowed when the SAFER option is set."));
820 /* Figure out whether to invoke an interactive shell or to execute a
821 single shell command. */
822 if (lex_look_ahead () == '.')
825 code = shell () ? CMD_PART_SUCCESS_MAYBE : CMD_SUCCESS;
828 code = run_command ();
830 /* Make sure that the system has a command interpreter, then run a
832 if (system (NULL) != 0)
833 code = run_command ();
836 msg (SE, _("No operating system support for this command."));
841 return code ? CMD_FAILURE : CMD_SUCCESS;
844 /* Parses, performs the NEW FILE command. */
848 discard_variables ();
850 return lex_end_of_command ();
853 /* Parses, performs the CLEAR TRANSFORMATIONS command. */
855 cmd_clear_transformations (void)
857 if (getl_reading_script)
859 msg (SW, _("This command is not valid in a syntax file."));
863 cancel_transformations ();
864 /* FIXME: what about variables created by transformations?
865 They need to be properly initialized. */