1 /* PSPP - computes sample statistics.
2 Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 #include <language/command.h>
29 #include <data/casereader.h>
30 #include <data/dictionary.h>
31 #include <data/procedure.h>
32 #include <data/settings.h>
33 #include <data/variable.h>
34 #include <language/lexer/lexer.h>
35 #include <language/prompt.h>
36 #include <libpspp/alloc.h>
37 #include <libpspp/assertion.h>
38 #include <libpspp/compiler.h>
39 #include <libpspp/message.h>
40 #include <libpspp/message.h>
41 #include <libpspp/str.h>
42 #include <output/manager.h>
43 #include <output/table.h>
50 #include <readline/readline.h>
54 #define _(msgid) gettext (msgid)
55 #define N_(msgid) msgid
57 /* Returns true if RESULT is a valid "enum cmd_result",
60 cmd_result_is_valid (enum cmd_result result)
62 return (result == CMD_SUCCESS || result == CMD_EOF || result == CMD_FINISH
63 || (result >= CMD_PRIVATE_FIRST && result <= CMD_PRIVATE_LAST)
64 || result == CMD_FAILURE || result == CMD_NOT_IMPLEMENTED
65 || result == CMD_CASCADING_FAILURE);
68 /* Returns true if RESULT indicates success,
71 cmd_result_is_success (enum cmd_result result)
73 assert (cmd_result_is_valid (result));
77 /* Returns true if RESULT indicates failure,
80 cmd_result_is_failure (enum cmd_result result)
82 assert (cmd_result_is_valid (result));
86 /* Command processing states. */
89 S_INITIAL = 0x01, /* Allowed before active file defined. */
90 S_DATA = 0x02, /* Allowed after active file defined. */
91 S_INPUT_PROGRAM = 0x04, /* Allowed in INPUT PROGRAM. */
92 S_FILE_TYPE = 0x08, /* Allowed in FILE TYPE. */
93 S_ANY = 0x0f /* Allowed anywhere. */
96 /* Other command requirements. */
99 F_ENHANCED = 0x10, /* Allowed only in enhanced syntax mode. */
100 F_TESTING = 0x20, /* Allowed only in testing mode. */
101 F_KEEP_FINAL_TOKEN = 0x40,/* Don't skip final token in command name. */
102 F_ABBREV = 0x80 /* Not a candidate for name completion. */
105 /* A single command. */
108 enum states states; /* States in which command is allowed. */
109 enum flags flags; /* Other command requirements. */
110 const char *name; /* Command name. */
111 int (*function) (struct lexer *, struct dataset *); /* Function to call. */
114 /* Define the command array. */
115 #define DEF_CMD(STATES, FLAGS, NAME, FUNCTION) {STATES, FLAGS, NAME, FUNCTION},
116 #define UNIMPL_CMD(NAME, DESCRIPTION) {S_ANY, 0, NAME, NULL},
117 static const struct command commands[] =
119 #include "command.def"
124 static const size_t command_cnt = sizeof commands / sizeof *commands;
126 static bool in_correct_state (const struct command *, enum cmd_state);
127 static bool report_state_mismatch (const struct command *, enum cmd_state);
128 static const struct command *find_command (const char *name);
129 static void set_completion_state (enum cmd_state);
131 /* Command parser. */
133 static const struct command *parse_command_name (struct lexer *lexer);
134 static enum cmd_result do_parse_command (struct lexer *, struct dataset *, enum cmd_state);
136 /* Parses an entire command, from command name to terminating
137 dot. On failure, skips to the terminating dot.
138 Returns the command's success or failure result. */
140 cmd_parse_in_state (struct lexer *lexer, struct dataset *ds,
141 enum cmd_state state)
147 result = do_parse_command (lexer, ds, state);
148 if (cmd_result_is_failure (result))
149 lex_discard_rest_of_command (lexer);
151 assert (!proc_is_open (ds));
152 unset_cmd_algorithm ();
153 dict_clear_aux (dataset_dict (ds));
154 if (!dataset_end_of_command (ds))
155 result = CMD_CASCADING_FAILURE;
161 cmd_parse (struct lexer *lexer, struct dataset *ds)
163 const struct dictionary *dict = dataset_dict (ds);
164 return cmd_parse_in_state (lexer, ds,
165 proc_has_active_file (ds) &&
166 dict_get_var_cnt (dict) > 0 ?
167 CMD_STATE_DATA : CMD_STATE_INITIAL);
171 /* Parses an entire command, from command name to terminating
173 static enum cmd_result
174 do_parse_command (struct lexer *lexer, struct dataset *ds, enum cmd_state state)
176 const struct command *command;
177 enum cmd_result result;
179 /* Read the command's first token. */
180 prompt_set_style (PROMPT_FIRST);
181 set_completion_state (state);
183 if (lex_token (lexer) == T_STOP)
185 else if (lex_token (lexer) == '.')
187 /* Null commands can result from extra empty lines. */
190 prompt_set_style (PROMPT_LATER);
192 /* Parse the command name. */
193 command = parse_command_name (lexer);
196 else if (command->function == NULL)
198 msg (SE, _("%s is unimplemented."), command->name);
199 return CMD_NOT_IMPLEMENTED;
201 else if ((command->flags & F_TESTING) && !get_testing_mode ())
203 msg (SE, _("%s may be used only in testing mode."), command->name);
206 else if ((command->flags & F_ENHANCED) && get_syntax () != ENHANCED)
208 msg (SE, _("%s may be used only in enhanced syntax mode."),
212 else if (!in_correct_state (command, state))
214 report_state_mismatch (command, state);
218 /* Execute command. */
219 msg_set_command_name (command->name);
220 tab_set_command_name (command->name);
221 result = command->function (lexer, ds);
222 tab_set_command_name (NULL);
223 msg_set_command_name (NULL);
225 assert (cmd_result_is_valid (result));
230 match_strings (const char *a, size_t a_len,
231 const char *b, size_t b_len)
233 size_t match_len = 0;
235 while (a_len > 0 && b_len > 0)
237 /* Mismatch always returns zero. */
238 if (toupper ((unsigned char) *a++) != toupper ((unsigned char) *b++))
250 /* Returns the first character in the first word in STRING,
251 storing the word's length in *WORD_LEN. If no words remain,
252 returns a null pointer and stores 0 in *WORD_LEN. Words are
253 sequences of alphanumeric characters or single
254 non-alphanumeric characters. Words are delimited by
257 find_word (const char *string, size_t *word_len)
259 /* Skip whitespace and asterisks. */
260 while (isspace ((unsigned char) *string))
270 /* Special one-character word? */
271 if (!isalnum ((unsigned char) *string))
277 /* Alphanumeric word. */
279 while (isalnum ((unsigned char) string[*word_len]))
285 /* Returns true if strings A and B can be confused based on
286 their first three letters. */
288 conflicting_3char_prefixes (const char *a, const char *b)
290 size_t aw_len, bw_len;
293 aw = find_word (a, &aw_len);
294 bw = find_word (b, &bw_len);
295 assert (aw != NULL && bw != NULL);
297 /* Words that are the same don't conflict. */
298 if (aw_len == bw_len && !buf_compare_case (aw, bw, aw_len))
301 /* Words that are otherwise the same in the first three letters
303 return ((aw_len > 3 && bw_len > 3)
304 || (aw_len == 3 && bw_len > 3)
305 || (bw_len == 3 && aw_len > 3)) && !buf_compare_case (aw, bw, 3);
308 /* Returns true if CMD can be confused with another command
309 based on the first three letters of its first word. */
311 conflicting_3char_prefix_command (const struct command *cmd)
313 assert (cmd >= commands && cmd < commands + command_cnt);
315 return ((cmd > commands
316 && conflicting_3char_prefixes (cmd[-1].name, cmd[0].name))
317 || (cmd < commands + command_cnt
318 && conflicting_3char_prefixes (cmd[0].name, cmd[1].name)));
321 /* Ways that a set of words can match a command name. */
324 MISMATCH, /* Not a match. */
325 PARTIAL_MATCH, /* The words begin the command name. */
326 COMPLETE_MATCH /* The words are the command name. */
329 /* Figures out how well the WORD_CNT words in WORDS match CMD,
330 and returns the appropriate enum value. If WORDS are a
331 partial match for CMD and the next word in CMD is a dash, then
332 *DASH_POSSIBLE is set to 1 if DASH_POSSIBLE is non-null;
333 otherwise, *DASH_POSSIBLE is unchanged. */
334 static enum command_match
335 cmd_match_words (const struct command *cmd,
336 char *const words[], size_t word_cnt,
343 for (word = find_word (cmd->name, &word_len), word_idx = 0;
344 word != NULL && word_idx < word_cnt;
345 word = find_word (word + word_len, &word_len), word_idx++)
346 if (word_len != strlen (words[word_idx])
347 || buf_compare_case (word, words[word_idx], word_len))
349 size_t match_chars = match_strings (word, word_len,
351 strlen (words[word_idx]));
352 if (match_chars == 0)
357 else if (match_chars == 1 || match_chars == 2)
359 /* One- and two-character abbreviations are not
363 else if (match_chars == 3)
365 /* Three-character abbreviations are acceptable
366 in the first word of a command if there are
367 no name conflicts. They are always
368 acceptable after the first word. */
369 if (word_idx == 0 && conflicting_3char_prefix_command (cmd))
372 else /* match_chars > 3 */
374 /* Four-character and longer abbreviations are
375 always acceptable. */
379 if (word == NULL && word_idx == word_cnt)
381 /* cmd->name = "FOO BAR", words[] = {"FOO", "BAR"}. */
382 return COMPLETE_MATCH;
384 else if (word == NULL)
386 /* cmd->name = "FOO BAR", words[] = {"FOO", "BAR", "BAZ"}. */
391 /* cmd->name = "FOO BAR BAZ", words[] = {"FOO", "BAR"}. */
392 if (word[0] == '-' && dash_possible != NULL)
394 return PARTIAL_MATCH;
398 /* Returns the number of commands for which the WORD_CNT words in
399 WORDS are a partial or complete match. If some partial match
400 has a dash as the next word, then *DASH_POSSIBLE is set to 1,
401 otherwise it is set to 0. */
403 count_matching_commands (char *const words[], size_t word_cnt,
406 const struct command *cmd;
411 for (cmd = commands; cmd < commands + command_cnt; cmd++)
412 if (cmd_match_words (cmd, words, word_cnt, dash_possible) != MISMATCH)
415 return cmd_match_count;
418 /* Returns the command for which the WORD_CNT words in WORDS are
419 a complete match. Returns a null pointer if no such command
421 static const struct command *
422 get_complete_match (char *const words[], size_t word_cnt)
424 const struct command *cmd;
426 for (cmd = commands; cmd < commands + command_cnt; cmd++)
427 if (cmd_match_words (cmd, words, word_cnt, NULL) == COMPLETE_MATCH)
433 /* Returns the command with the given exact NAME.
434 Aborts if no such command exists. */
435 static const struct command *
436 find_command (const char *name)
438 const struct command *cmd;
440 for (cmd = commands; cmd < commands + command_cnt; cmd++)
441 if (!strcmp (cmd->name, name))
446 /* Frees the WORD_CNT words in WORDS. */
448 free_words (char *words[], size_t word_cnt)
452 for (idx = 0; idx < word_cnt; idx++)
456 /* Flags an error that the command whose name is given by the
457 WORD_CNT words in WORDS is unknown. */
459 unknown_command_error (struct lexer *lexer, char *const words[], size_t word_cnt)
462 lex_error (lexer, _("expecting command name"));
469 for (i = 0; i < word_cnt; i++)
472 ds_put_char (&s, ' ');
473 ds_put_cstr (&s, words[i]);
476 msg (SE, _("Unknown command %s."), ds_cstr (&s));
482 /* Parse the command name and return a pointer to the corresponding
483 struct command if successful.
484 If not successful, return a null pointer. */
485 static const struct command *
486 parse_command_name (struct lexer *lexer)
490 int complete_word_cnt;
493 if (lex_token (lexer) == T_EXP ||
494 lex_token (lexer) == '*' || lex_token (lexer) == '[')
495 return find_command ("COMMENT");
498 word_cnt = complete_word_cnt = 0;
499 while (lex_token (lexer) == T_ID || (dash_possible && lex_token (lexer) == '-'))
503 assert (word_cnt < sizeof words / sizeof *words);
504 if (lex_token (lexer) == T_ID)
506 words[word_cnt] = ds_xstrdup (lex_tokstr (lexer));
507 str_uppercase (words[word_cnt]);
509 else if (lex_token (lexer) == '-')
510 words[word_cnt] = xstrdup ("-");
513 cmd_match_cnt = count_matching_commands (words, word_cnt,
515 if (cmd_match_cnt == 0)
517 else if (cmd_match_cnt == 1)
519 const struct command *command = get_complete_match (words, word_cnt);
522 if (!(command->flags & F_KEEP_FINAL_TOKEN))
524 free_words (words, word_cnt);
528 else /* cmd_match_cnt > 1 */
530 /* Do we have a complete command name so far? */
531 if (get_complete_match (words, word_cnt) != NULL)
532 complete_word_cnt = word_cnt;
537 /* If we saw a complete command name earlier, drop back to
539 if (complete_word_cnt)
541 int pushback_word_cnt;
542 const struct command *command;
544 /* Get the command. */
545 command = get_complete_match (words, complete_word_cnt);
546 assert (command != NULL);
548 /* Figure out how many words we want to keep.
549 We normally want to swallow the entire command. */
550 pushback_word_cnt = complete_word_cnt + 1;
551 if (command->flags & F_KEEP_FINAL_TOKEN)
554 /* FIXME: We only support one-token pushback. */
555 assert (pushback_word_cnt + 1 >= word_cnt);
557 while (word_cnt > pushback_word_cnt)
560 if (strcmp (words[word_cnt], "-"))
561 lex_put_back_id (lexer, words[word_cnt]);
563 lex_put_back (lexer, '-');
564 free (words[word_cnt]);
567 free_words (words, word_cnt);
571 /* We didn't get a valid command name. */
572 unknown_command_error (lexer, words, word_cnt);
573 free_words (words, word_cnt);
577 /* Returns true if COMMAND is allowed in STATE,
580 in_correct_state (const struct command *command, enum cmd_state state)
582 return ((state == CMD_STATE_INITIAL && command->states & S_INITIAL)
583 || (state == CMD_STATE_DATA && command->states & S_DATA)
584 || (state == CMD_STATE_INPUT_PROGRAM
585 && command->states & S_INPUT_PROGRAM)
586 || (state == CMD_STATE_FILE_TYPE && command->states & S_FILE_TYPE));
589 /* Emits an appropriate error message for trying to invoke
592 report_state_mismatch (const struct command *command, enum cmd_state state)
594 assert (!in_correct_state (command, state));
595 if (state == CMD_STATE_INITIAL || state == CMD_STATE_DATA)
597 const char *allowed[3];
602 if (command->states & S_INITIAL)
603 allowed[allowed_cnt++] = _("before the active file has been defined");
604 else if (command->states & S_DATA)
605 allowed[allowed_cnt++] = _("after the active file has been defined");
606 if (command->states & S_INPUT_PROGRAM)
607 allowed[allowed_cnt++] = _("inside INPUT PROGRAM");
608 if (command->states & S_FILE_TYPE)
609 allowed[allowed_cnt++] = _("inside FILE TYPE");
611 if (allowed_cnt == 1)
612 s = xstrdup (allowed[0]);
613 else if (allowed_cnt == 2)
614 s = xasprintf (_("%s or %s"), allowed[0], allowed[1]);
615 else if (allowed_cnt == 3)
616 s = xasprintf (_("%s, %s, or %s"), allowed[0], allowed[1], allowed[2]);
620 msg (SE, _("%s is allowed only %s."), command->name, s);
624 else if (state == CMD_STATE_INPUT_PROGRAM)
625 msg (SE, _("%s is not allowed inside INPUT PROGRAM."), command->name);
626 else if (state == CMD_STATE_FILE_TYPE)
627 msg (SE, _("%s is not allowed inside FILE TYPE."), command->name);
632 /* Command name completion. */
634 static enum cmd_state completion_state = CMD_STATE_INITIAL;
637 set_completion_state (enum cmd_state state)
639 completion_state = state;
642 /* Returns the next possible completion of a command name that
643 begins with PREFIX, in the current command state, or a null
644 pointer if no completions remain.
645 Before calling the first time, set *CMD to a null pointer. */
647 cmd_complete (const char *prefix, const struct command **cmd)
652 for (; *cmd < commands + command_cnt; (*cmd)++)
653 if (!memcasecmp ((*cmd)->name, prefix, strlen (prefix))
654 && (!((*cmd)->flags & F_TESTING) || get_testing_mode ())
655 && (!((*cmd)->flags & F_ENHANCED) || get_syntax () == ENHANCED)
656 && !((*cmd)->flags & F_ABBREV)
657 && ((*cmd)->function != NULL)
658 && in_correct_state (*cmd, completion_state))
659 return (*cmd)++->name;
664 /* Simple commands. */
666 /* Parse and execute FINISH command. */
668 cmd_finish (struct lexer *lexer UNUSED, struct dataset *ds UNUSED)
673 /* Parses the N command. */
675 cmd_n_of_cases (struct lexer *lexer, struct dataset *ds)
680 if (!lex_force_int (lexer))
682 x = lex_integer (lexer);
684 if (!lex_match_id (lexer, "ESTIMATED"))
685 dict_set_case_limit (dataset_dict (ds), x);
687 return lex_end_of_command (lexer);
690 /* Parses, performs the EXECUTE procedure. */
692 cmd_execute (struct lexer *lexer, struct dataset *ds)
694 bool ok = casereader_destroy (proc_open (ds));
695 if (!proc_commit (ds) || !ok)
696 return CMD_CASCADING_FAILURE;
697 return lex_end_of_command (lexer);
700 /* Parses, performs the ERASE command. */
702 cmd_erase (struct lexer *lexer, struct dataset *ds UNUSED)
704 if (get_safer_mode ())
706 msg (SE, _("This command not allowed when the SAFER option is set."));
710 if (!lex_force_match_id (lexer, "FILE"))
712 lex_match (lexer, '=');
713 if (!lex_force_string (lexer))
716 if (remove (ds_cstr (lex_tokstr (lexer))) == -1)
718 msg (SW, _("Error removing `%s': %s."),
719 ds_cstr (lex_tokstr (lexer)), strerror (errno));
726 #if HAVE_FORK && HAVE_EXECL
727 /* Spawn an interactive shell process. */
738 const char *shell_fn;
744 for (i = 3; i < 20; i++)
748 shell_fn = getenv ("SHELL");
749 if (shell_fn == NULL)
750 shell_fn = "/bin/sh";
753 const char *cp = strrchr (shell_fn, '/');
754 cp = cp ? &cp[1] : shell_fn;
755 shell_process = local_alloc (strlen (cp) + 8);
756 strcpy (shell_process, "-");
757 strcat (shell_process, cp);
758 if (strcmp (cp, "sh"))
759 shell_process[0] = '+';
762 execl (shell_fn, shell_process, NULL);
768 msg (SE, _("Couldn't fork: %s."), strerror (errno));
773 while (wait (NULL) != pid)
778 #else /* !(HAVE_FORK && HAVE_EXECL) */
779 /* Don't know how to spawn an interactive shell. */
783 msg (SE, _("Interactive shell not supported on this platform."));
788 /* Executes the specified COMMAND in a subshell. Returns true if
789 successful, false otherwise. */
791 run_command (const char *command)
793 if (system (NULL) == 0)
795 msg (SE, _("Command shell not supported on this platform."));
799 /* Execute the command. */
800 if (system (command) == -1)
801 msg (SE, _("Error executing command: %s."), strerror (errno));
806 /* Parses, performs the HOST command. */
808 cmd_host (struct lexer *lexer, struct dataset *ds UNUSED)
812 if (get_safer_mode ())
814 msg (SE, _("This command not allowed when the SAFER option is set."));
818 look_ahead = lex_look_ahead (lexer);
819 if (look_ahead == '.')
822 return shell () ? CMD_SUCCESS : CMD_FAILURE;
824 else if (look_ahead == '\'' || look_ahead == '"')
829 if (!lex_force_string (lexer))
831 ok = run_command (ds_cstr (lex_tokstr (lexer)));
834 return ok ? lex_end_of_command (lexer) : CMD_FAILURE;
838 bool ok = run_command (lex_rest_of_line (lexer));
839 lex_discard_line (lexer);
840 return ok ? CMD_SUCCESS : CMD_FAILURE;
844 /* Parses, performs the NEW FILE command. */
846 cmd_new_file (struct lexer *lexer, struct dataset *ds)
848 proc_discard_active_file (ds);
850 return lex_end_of_command (lexer);
853 /* Parses a comment. */
855 cmd_comment (struct lexer *lexer, struct dataset *ds UNUSED)
857 lex_skip_comment (lexer);