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
22 #include <language/command.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/line-buffer.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 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 (void);
134 static enum cmd_result do_parse_command (struct dataset *ds, 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 (struct dataset *ds, enum cmd_state state)
146 result = do_parse_command (ds, state);
147 if (cmd_result_is_failure (result))
148 lex_discard_rest_of_command ();
150 unset_cmd_algorithm ();
151 dict_clear_aux (dataset_dict (ds));
156 /* Parses an entire command, from command name to terminating
158 static enum cmd_result
159 do_parse_command (struct dataset *ds, enum cmd_state state)
161 const struct command *command;
162 enum cmd_result result;
164 /* Read the command's first token. */
165 getl_set_prompt_style (GETL_PROMPT_FIRST);
166 set_completion_state (state);
170 else if (token == '.')
172 /* Null commands can result from extra empty lines. */
175 getl_set_prompt_style (GETL_PROMPT_LATER);
177 /* Parse the command name. */
178 command = parse_command_name ();
181 else if (command->function == NULL)
183 msg (SE, _("%s is unimplemented."), command->name);
184 return CMD_NOT_IMPLEMENTED;
186 else if ((command->flags & F_TESTING) && !get_testing_mode ())
188 msg (SE, _("%s may be used only in testing mode."), command->name);
191 else if ((command->flags & F_ENHANCED) && get_syntax () != ENHANCED)
193 msg (SE, _("%s may be used only in enhanced syntax mode."),
197 else if (!in_correct_state (command, state))
199 report_state_mismatch (command, state);
203 /* Execute command. */
204 msg_set_command_name (command->name);
205 tab_set_command_name (command->name);
206 result = command->function (ds);
207 tab_set_command_name (NULL);
208 msg_set_command_name (NULL);
210 assert (cmd_result_is_valid (result));
215 match_strings (const char *a, size_t a_len,
216 const char *b, size_t b_len)
218 size_t match_len = 0;
220 while (a_len > 0 && b_len > 0)
222 /* Mismatch always returns zero. */
223 if (toupper ((unsigned char) *a++) != toupper ((unsigned char) *b++))
235 /* Returns the first character in the first word in STRING,
236 storing the word's length in *WORD_LEN. If no words remain,
237 returns a null pointer and stores 0 in *WORD_LEN. Words are
238 sequences of alphanumeric characters or single
239 non-alphanumeric characters. Words are delimited by
242 find_word (const char *string, size_t *word_len)
244 /* Skip whitespace and asterisks. */
245 while (isspace ((unsigned char) *string))
255 /* Special one-character word? */
256 if (!isalnum ((unsigned char) *string))
262 /* Alphanumeric word. */
264 while (isalnum ((unsigned char) string[*word_len]))
270 /* Returns true if strings A and B can be confused based on
271 their first three letters. */
273 conflicting_3char_prefixes (const char *a, const char *b)
275 size_t aw_len, bw_len;
278 aw = find_word (a, &aw_len);
279 bw = find_word (b, &bw_len);
280 assert (aw != NULL && bw != NULL);
282 /* Words that are the same don't conflict. */
283 if (aw_len == bw_len && !buf_compare_case (aw, bw, aw_len))
286 /* Words that are otherwise the same in the first three letters
288 return ((aw_len > 3 && bw_len > 3)
289 || (aw_len == 3 && bw_len > 3)
290 || (bw_len == 3 && aw_len > 3)) && !buf_compare_case (aw, bw, 3);
293 /* Returns true if CMD can be confused with another command
294 based on the first three letters of its first word. */
296 conflicting_3char_prefix_command (const struct command *cmd)
298 assert (cmd >= commands && cmd < commands + command_cnt);
300 return ((cmd > commands
301 && conflicting_3char_prefixes (cmd[-1].name, cmd[0].name))
302 || (cmd < commands + command_cnt
303 && conflicting_3char_prefixes (cmd[0].name, cmd[1].name)));
306 /* Ways that a set of words can match a command name. */
309 MISMATCH, /* Not a match. */
310 PARTIAL_MATCH, /* The words begin the command name. */
311 COMPLETE_MATCH /* The words are the command name. */
314 /* Figures out how well the WORD_CNT words in WORDS match CMD,
315 and returns the appropriate enum value. If WORDS are a
316 partial match for CMD and the next word in CMD is a dash, then
317 *DASH_POSSIBLE is set to 1 if DASH_POSSIBLE is non-null;
318 otherwise, *DASH_POSSIBLE is unchanged. */
319 static enum command_match
320 cmd_match_words (const struct command *cmd,
321 char *const words[], size_t word_cnt,
328 for (word = find_word (cmd->name, &word_len), word_idx = 0;
329 word != NULL && word_idx < word_cnt;
330 word = find_word (word + word_len, &word_len), word_idx++)
331 if (word_len != strlen (words[word_idx])
332 || buf_compare_case (word, words[word_idx], word_len))
334 size_t match_chars = match_strings (word, word_len,
336 strlen (words[word_idx]));
337 if (match_chars == 0)
342 else if (match_chars == 1 || match_chars == 2)
344 /* One- and two-character abbreviations are not
348 else if (match_chars == 3)
350 /* Three-character abbreviations are acceptable
351 in the first word of a command if there are
352 no name conflicts. They are always
353 acceptable after the first word. */
354 if (word_idx == 0 && conflicting_3char_prefix_command (cmd))
357 else /* match_chars > 3 */
359 /* Four-character and longer abbreviations are
360 always acceptable. */
364 if (word == NULL && word_idx == word_cnt)
366 /* cmd->name = "FOO BAR", words[] = {"FOO", "BAR"}. */
367 return COMPLETE_MATCH;
369 else if (word == NULL)
371 /* cmd->name = "FOO BAR", words[] = {"FOO", "BAR", "BAZ"}. */
376 /* cmd->name = "FOO BAR BAZ", words[] = {"FOO", "BAR"}. */
377 if (word[0] == '-' && dash_possible != NULL)
379 return PARTIAL_MATCH;
383 /* Returns the number of commands for which the WORD_CNT words in
384 WORDS are a partial or complete match. If some partial match
385 has a dash as the next word, then *DASH_POSSIBLE is set to 1,
386 otherwise it is set to 0. */
388 count_matching_commands (char *const words[], size_t word_cnt,
391 const struct command *cmd;
396 for (cmd = commands; cmd < commands + command_cnt; cmd++)
397 if (cmd_match_words (cmd, words, word_cnt, dash_possible) != MISMATCH)
400 return cmd_match_count;
403 /* Returns the command for which the WORD_CNT words in WORDS are
404 a complete match. Returns a null pointer if no such command
406 static const struct command *
407 get_complete_match (char *const words[], size_t word_cnt)
409 const struct command *cmd;
411 for (cmd = commands; cmd < commands + command_cnt; cmd++)
412 if (cmd_match_words (cmd, words, word_cnt, NULL) == COMPLETE_MATCH)
418 /* Returns the command with the given exact NAME.
419 Aborts if no such command exists. */
420 static const struct command *
421 find_command (const char *name)
423 const struct command *cmd;
425 for (cmd = commands; cmd < commands + command_cnt; cmd++)
426 if (!strcmp (cmd->name, name))
431 /* Frees the WORD_CNT words in WORDS. */
433 free_words (char *words[], size_t word_cnt)
437 for (idx = 0; idx < word_cnt; idx++)
441 /* Flags an error that the command whose name is given by the
442 WORD_CNT words in WORDS is unknown. */
444 unknown_command_error (char *const words[], size_t word_cnt)
447 lex_error (_("expecting command name"));
454 for (i = 0; i < word_cnt; i++)
457 ds_put_char (&s, ' ');
458 ds_put_cstr (&s, words[i]);
461 msg (SE, _("Unknown command %s."), ds_cstr (&s));
467 /* Parse the command name and return a pointer to the corresponding
468 struct command if successful.
469 If not successful, return a null pointer. */
470 static const struct command *
471 parse_command_name (void)
475 int complete_word_cnt;
478 if (token == T_EXP || token == '*' || token == '[')
479 return find_command ("COMMENT");
482 word_cnt = complete_word_cnt = 0;
483 while (token == T_ID || (dash_possible && token == '-'))
487 assert (word_cnt < sizeof words / sizeof *words);
490 words[word_cnt] = ds_xstrdup (&tokstr);
491 str_uppercase (words[word_cnt]);
493 else if (token == '-')
494 words[word_cnt] = xstrdup ("-");
497 cmd_match_cnt = count_matching_commands (words, word_cnt,
499 if (cmd_match_cnt == 0)
501 else if (cmd_match_cnt == 1)
503 const struct command *command = get_complete_match (words, word_cnt);
506 if (!(command->flags & F_KEEP_FINAL_TOKEN))
508 free_words (words, word_cnt);
512 else /* cmd_match_cnt > 1 */
514 /* Do we have a complete command name so far? */
515 if (get_complete_match (words, word_cnt) != NULL)
516 complete_word_cnt = word_cnt;
521 /* If we saw a complete command name earlier, drop back to
523 if (complete_word_cnt)
525 int pushback_word_cnt;
526 const struct command *command;
528 /* Get the command. */
529 command = get_complete_match (words, complete_word_cnt);
530 assert (command != NULL);
532 /* Figure out how many words we want to keep.
533 We normally want to swallow the entire command. */
534 pushback_word_cnt = complete_word_cnt + 1;
535 if (command->flags & F_KEEP_FINAL_TOKEN)
538 /* FIXME: We only support one-token pushback. */
539 assert (pushback_word_cnt + 1 >= word_cnt);
541 while (word_cnt > pushback_word_cnt)
544 if (strcmp (words[word_cnt], "-"))
545 lex_put_back_id (words[word_cnt]);
548 free (words[word_cnt]);
551 free_words (words, word_cnt);
555 /* We didn't get a valid command name. */
556 unknown_command_error (words, word_cnt);
557 free_words (words, word_cnt);
561 /* Returns true if COMMAND is allowed in STATE,
564 in_correct_state (const struct command *command, enum cmd_state state)
566 return ((state == CMD_STATE_INITIAL && command->states & S_INITIAL)
567 || (state == CMD_STATE_DATA && command->states & S_DATA)
568 || (state == CMD_STATE_INPUT_PROGRAM
569 && command->states & S_INPUT_PROGRAM)
570 || (state == CMD_STATE_FILE_TYPE && command->states & S_FILE_TYPE));
573 /* Emits an appropriate error message for trying to invoke
576 report_state_mismatch (const struct command *command, enum cmd_state state)
578 assert (!in_correct_state (command, state));
579 if (state == CMD_STATE_INITIAL || state == CMD_STATE_DATA)
581 const char *allowed[3];
586 if (command->states & S_INITIAL)
587 allowed[allowed_cnt++] = _("before the active file has been defined");
588 else if (command->states & S_DATA)
589 allowed[allowed_cnt++] = _("after the active file has been defined");
590 if (command->states & S_INPUT_PROGRAM)
591 allowed[allowed_cnt++] = _("inside INPUT PROGRAM");
592 if (command->states & S_FILE_TYPE)
593 allowed[allowed_cnt++] = _("inside FILE TYPE");
595 if (allowed_cnt == 1)
596 s = xstrdup (allowed[0]);
597 else if (allowed_cnt == 2)
598 s = xasprintf (_("%s or %s"), allowed[0], allowed[1]);
599 else if (allowed_cnt == 3)
600 s = xasprintf (_("%s, %s, or %s"), allowed[0], allowed[1], allowed[2]);
604 msg (SE, _("%s is allowed only %s."), command->name, s);
608 else if (state == CMD_STATE_INPUT_PROGRAM)
609 msg (SE, _("%s is not allowed inside INPUT PROGRAM."), command->name);
610 else if (state == CMD_STATE_FILE_TYPE)
611 msg (SE, _("%s is not allowed inside FILE TYPE."), command->name);
616 /* Command name completion. */
618 static enum cmd_state completion_state = CMD_STATE_INITIAL;
621 set_completion_state (enum cmd_state state)
623 completion_state = state;
626 /* Returns the next possible completion of a command name that
627 begins with PREFIX, in the current command state, or a null
628 pointer if no completions remain.
629 Before calling the first time, set *CMD to a null pointer. */
631 cmd_complete (const char *prefix, const struct command **cmd)
636 for (; *cmd < commands + command_cnt; (*cmd)++)
637 if (!memcasecmp ((*cmd)->name, prefix, strlen (prefix))
638 && (!((*cmd)->flags & F_TESTING) || get_testing_mode ())
639 && (!((*cmd)->flags & F_ENHANCED) || get_syntax () == ENHANCED)
640 && !((*cmd)->flags & F_ABBREV)
641 && ((*cmd)->function != NULL)
642 && in_correct_state (*cmd, completion_state))
643 return (*cmd)++->name;
648 /* Simple commands. */
650 /* Parse and execute FINISH command. */
652 cmd_finish (struct dataset *ds UNUSED)
657 /* Parses the N command. */
659 cmd_n_of_cases (struct dataset *ds)
664 if (!lex_force_int ())
668 if (!lex_match_id ("ESTIMATED"))
669 dict_set_case_limit (dataset_dict (ds), x);
671 return lex_end_of_command ();
674 /* Parses, performs the EXECUTE procedure. */
676 cmd_execute (struct dataset *ds)
678 if (!procedure (ds, NULL, NULL))
679 return CMD_CASCADING_FAILURE;
680 return lex_end_of_command ();
683 /* Parses, performs the ERASE command. */
685 cmd_erase (struct dataset *ds UNUSED)
687 if (get_safer_mode ())
689 msg (SE, _("This command not allowed when the SAFER option is set."));
693 if (!lex_force_match_id ("FILE"))
696 if (!lex_force_string ())
699 if (remove (ds_cstr (&tokstr)) == -1)
701 msg (SW, _("Error removing `%s': %s."),
702 ds_cstr (&tokstr), strerror (errno));
710 /* Spawn a shell process. */
721 const char *shell_fn;
727 for (i = 3; i < 20; i++)
731 shell_fn = getenv ("SHELL");
732 if (shell_fn == NULL)
733 shell_fn = "/bin/sh";
736 const char *cp = strrchr (shell_fn, '/');
737 cp = cp ? &cp[1] : shell_fn;
738 shell_process = local_alloc (strlen (cp) + 8);
739 strcpy (shell_process, "-");
740 strcat (shell_process, cp);
741 if (strcmp (cp, "sh"))
742 shell_process[0] = '+';
745 execl (shell_fn, shell_process, NULL);
751 msg (SE, _("Couldn't fork: %s."), strerror (errno));
756 while (wait (NULL) != pid)
763 /* Parses the HOST command argument and executes the specified
764 command. Returns a suitable command return code. */
771 /* Handle either a string argument or a full-line argument. */
773 int c = lex_look_ahead ();
775 if (c == '\'' || c == '"')
778 if (!lex_force_string ())
780 cmd = ds_cstr (&tokstr);
785 cmd = lex_rest_of_line (NULL);
791 /* Execute the command. */
792 if (system (cmd) == -1)
793 msg (SE, _("Error executing command: %s."), strerror (errno));
795 /* Finish parsing. */
802 lex_error (_("expecting end of command"));
812 /* Parses, performs the HOST command. */
814 cmd_host (struct dataset *ds UNUSED)
818 if (get_safer_mode ())
820 msg (SE, _("This command not allowed when the SAFER option is set."));
825 /* Figure out whether to invoke an interactive shell or to execute a
826 single shell command. */
827 if (lex_look_ahead () == '.')
830 code = shell () ? CMD_FAILURE : CMD_SUCCESS;
833 code = run_command ();
835 /* Make sure that the system has a command interpreter, then run a
837 if (system (NULL) != 0)
838 code = run_command ();
841 msg (SE, _("No operating system support for this command."));
849 /* Parses, performs the NEW FILE command. */
851 cmd_new_file (struct dataset *ds)
853 discard_variables (ds);
855 return lex_end_of_command ();
858 /* Parses a comment. */
860 cmd_comment (struct dataset *ds UNUSED)