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"
36 #include "procedure.h"
47 #define _(msgid) gettext (msgid)
48 #define N_(msgid) msgid
50 /* Global variables. */
52 /* A STATE_* constant giving the current program state. */
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. */
65 short debug; /* Set if this cmd available only in test mode*/
68 /* Define the command array. */
69 #define DEFCMD(NAME, T1, T2, T3, T4, FUNC) \
70 {NAME, {T1, T2, T3, T4}, FUNC, 1, 0},
71 #define DBGCMD(NAME, T1, T2, T3, T4, FUNC) \
72 {NAME, {T1, T2, T3, T4}, FUNC, 1, 1},
73 #define SPCCMD(NAME, T1, T2, T3, T4, FUNC) \
74 {NAME, {T1, T2, T3, T4}, FUNC, 0, 0},
75 #define UNIMPL(NAME, T1, T2, T3, T4, DESC) \
76 {NAME, {T1, T2, T3, T4}, NULL, 1, 0},
77 static const struct command commands[] =
79 #include "command.def"
86 /* Complete the line using the name of a command,
87 * based upon the current prg_state
90 pspp_completion_function (const char *text, int state)
93 const struct command *cmd = 0;
97 if ( state + skip >= sizeof(commands)/ sizeof(struct command))
103 cmd = &commands[state + skip];
105 if ( cmd->transition[pgm_state] == STATE_ERROR || ( cmd->debug && ! get_testing_mode () ) )
111 if ( text == 0 || 0 == strncasecmp (cmd->name, text, strlen(text)))
120 return xstrdup(cmd->name);
125 #define COMMAND_CNT (sizeof commands / sizeof *commands)
127 /* Command parser. */
129 static const struct command *parse_command_name (void);
131 /* Determines whether command C is appropriate to call in this
132 part of a FILE TYPE structure. */
134 FILE_TYPE_okay (const struct command *c UNUSED)
139 if (c->func != cmd_record_type
140 && c->func != cmd_data_list
141 && c->func != cmd_repeating_data
142 && c->func != cmd_end_file_type)
143 msg (SE, _("%s not allowed inside FILE TYPE/END FILE TYPE."), c->name);
145 else if (c->func == cmd_repeating_data && fty.type == FTY_GROUPED)
146 msg (SE, _("%s not allowed inside FILE TYPE GROUPED/END FILE TYPE."),
148 else if (!fty.had_rec_type && c->func != cmd_record_type)
149 msg (SE, _("RECORD TYPE must be the first command inside a "
150 "FILE TYPE structure."));
154 if (c->func == cmd_record_type)
155 fty.had_rec_type = 1;
165 /* Parses an entire PSPP command. This includes everything from the
166 command name to the terminating dot. Does most of its work by
167 passing it off to the respective command dispatchers. Only called
168 by parse() in main.c. */
172 const struct command *cp; /* Iterator used to find the proper command. */
175 /* The generic alloca package performs garbage collection when it is
176 called with an argument of zero. */
178 #endif /* C_ALLOCA */
180 /* Null commands can result from extra empty lines. */
184 /* Parse comments. */
185 if ((token == T_ID && !strcasecmp (tokid, "COMMENT"))
186 || token == T_EXP || token == '*' || token == '[')
192 /* Otherwise the line must begin with a command name, which is
193 always an ID token. */
196 lex_error (_("expecting command name"));
200 /* Parse the command name. */
201 cp = parse_command_name ();
204 if (cp->func == NULL)
206 msg (SE, _("%s is not yet implemented."), cp->name);
207 while (token && token != '.')
212 /* If we're in a FILE TYPE structure, only certain commands can be
214 if (pgm_state == STATE_INPUT
215 && case_source_is_class (vfm_source, &file_type_source_class)
216 && !FILE_TYPE_okay (cp))
219 /* Certain state transitions are not allowed. Check for these. */
220 assert (pgm_state >= 0 && pgm_state < STATE_ERROR);
221 if (cp->transition[pgm_state] == STATE_ERROR)
223 static const char *state_name[4] =
225 N_("%s is not allowed (1) before a command to specify the "
226 "input program, such as DATA LIST, (2) between FILE TYPE "
227 "and END FILE TYPE, (3) between INPUT PROGRAM and END "
229 N_("%s is not allowed within an input program."),
230 N_("%s is only allowed within an input program."),
231 N_("%s is only allowed within an input program."),
234 msg (SE, gettext (state_name[pgm_state]), cp->name);
238 /* The structured output manager numbers all its tables. Increment
239 the major table number for each separate procedure. */
245 /* Call the command dispatcher. */
246 err_set_command_name (cp->name);
247 tab_set_command_name (cp->name);
248 result = cp->func ();
249 err_set_command_name (NULL);
250 tab_set_command_name (NULL);
252 /* Perform the state transition if the command completed
253 successfully (at least in part). */
254 if (result != CMD_FAILURE && result != CMD_CASCADING_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. */
279 if (toupper ((unsigned char) *a++) != toupper ((unsigned char) *b++))
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 ((unsigned char) *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 && !buf_compare_case (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)) && !buf_compare_case (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 || buf_compare_case (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 ("-");
534 str_uppercase (words[word_cnt]);
537 cmd_match_cnt = count_matching_commands (words, word_cnt,
539 if (cmd_match_cnt == 0)
541 else if (cmd_match_cnt == 1)
543 const struct command *command = get_complete_match (words, word_cnt);
546 if (command->skip_entire_name)
548 if ( command->debug & !get_testing_mode () )
550 free_words (words, word_cnt);
554 else /* cmd_match_cnt > 1 */
556 /* Do we have a complete command name so far? */
557 if (get_complete_match (words, word_cnt) != NULL)
558 complete_word_cnt = word_cnt;
563 /* If we saw a complete command name earlier, drop back to
565 if (complete_word_cnt)
567 int pushback_word_cnt;
568 const struct command *command;
570 /* Get the command. */
571 command = get_complete_match (words, complete_word_cnt);
572 assert (command != NULL);
574 /* Figure out how many words we want to keep.
575 We normally want to swallow the entire command. */
576 pushback_word_cnt = complete_word_cnt + 1;
577 if (!command->skip_entire_name)
580 /* FIXME: We only support one-token pushback. */
581 assert (pushback_word_cnt + 1 >= word_cnt);
583 while (word_cnt > pushback_word_cnt)
586 if (strcmp (words[word_cnt], "-"))
587 lex_put_back_id (words[word_cnt]);
590 free (words[word_cnt]);
593 if ( command->debug && !get_testing_mode () )
596 free_words (words, word_cnt);
601 unknown_command_error (words, word_cnt);
602 free_words (words, word_cnt);
606 /* Simple commands. */
608 /* Parse and execute FINISH command. */
615 /* Parses the N command. */
617 cmd_n_of_cases (void)
622 if (!lex_force_int ())
626 if (!lex_match_id ("ESTIMATED"))
627 dict_set_case_limit (default_dict, x);
629 return lex_end_of_command ();
632 /* Parses, performs the EXECUTE procedure. */
636 if (!procedure (NULL, NULL))
637 return CMD_CASCADING_FAILURE;
638 return lex_end_of_command ();
641 /* Parses, performs the ERASE command. */
645 if (get_safer_mode ())
647 msg (SE, _("This command not allowed when the SAFER option is set."));
651 if (!lex_force_match_id ("FILE"))
654 if (!lex_force_string ())
657 if (remove (ds_c_str (&tokstr)) == -1)
659 msg (SW, _("Error removing `%s': %s."),
660 ds_c_str (&tokstr), strerror (errno));
668 /* Spawn a shell process. */
679 const char *shell_fn;
685 for (i = 3; i < 20; i++)
689 shell_fn = getenv ("SHELL");
690 if (shell_fn == NULL)
691 shell_fn = "/bin/sh";
694 const char *cp = strrchr (shell_fn, '/');
695 cp = cp ? &cp[1] : shell_fn;
696 shell_process = local_alloc (strlen (cp) + 8);
697 strcpy (shell_process, "-");
698 strcat (shell_process, cp);
699 if (strcmp (cp, "sh"))
700 shell_process[0] = '+';
703 execl (shell_fn, shell_process, NULL);
709 msg (SE, _("Couldn't fork: %s."), strerror (errno));
714 while (wait (NULL) != pid)
721 /* Parses the HOST command argument and executes the specified
722 command. Returns a suitable command return code. */
729 /* Handle either a string argument or a full-line argument. */
731 int c = lex_look_ahead ();
733 if (c == '\'' || c == '"')
736 if (!lex_force_string ())
738 cmd = ds_c_str (&tokstr);
743 cmd = lex_rest_of_line (NULL);
749 /* Execute the command. */
750 if (system (cmd) == -1)
751 msg (SE, _("Error executing command: %s."), strerror (errno));
753 /* Finish parsing. */
760 lex_error (_("expecting end of command"));
761 return CMD_TRAILING_GARBAGE;
770 /* Parses, performs the HOST command. */
776 if (get_safer_mode ())
778 msg (SE, _("This command not allowed when the SAFER option is set."));
783 /* Figure out whether to invoke an interactive shell or to execute a
784 single shell command. */
785 if (lex_look_ahead () == '.')
788 code = shell () ? CMD_PART_SUCCESS_MAYBE : CMD_SUCCESS;
791 code = run_command ();
793 /* Make sure that the system has a command interpreter, then run a
795 if (system (NULL) != 0)
796 code = run_command ();
799 msg (SE, _("No operating system support for this command."));
807 /* Parses, performs the NEW FILE command. */
811 discard_variables ();
813 return lex_end_of_command ();
816 /* Parses, performs the CLEAR TRANSFORMATIONS command. */
818 cmd_clear_transformations (void)
820 cancel_transformations ();
821 /* FIXME: what about variables created by transformations?
822 They need to be properly initialized. */