1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 1997-9, 2000, 2009, 2010 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU 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, see <http://www.gnu.org/licenses/>. */
19 #include "language/command.h"
26 #include "data/casereader.h"
27 #include "data/dictionary.h"
28 #include "data/procedure.h"
29 #include "data/settings.h"
30 #include "data/variable.h"
31 #include "language/lexer/lexer.h"
32 #include "language/prompt.h"
33 #include "libpspp/assertion.h"
34 #include "libpspp/compiler.h"
35 #include "libpspp/message.h"
36 #include "libpspp/str.h"
37 #include "libpspp/getl.h"
38 #include "output/text-item.h"
44 #define _(msgid) gettext (msgid)
45 #define N_(msgid) msgid
47 /* Returns true if RESULT is a valid "enum cmd_result",
50 cmd_result_is_valid (enum cmd_result result)
52 return (result == CMD_SUCCESS || result == CMD_EOF || result == CMD_FINISH
53 || (result >= CMD_PRIVATE_FIRST && result <= CMD_PRIVATE_LAST)
54 || result == CMD_FAILURE || result == CMD_NOT_IMPLEMENTED
55 || result == CMD_CASCADING_FAILURE);
58 /* Returns true if RESULT indicates success,
61 cmd_result_is_success (enum cmd_result result)
63 assert (cmd_result_is_valid (result));
67 /* Returns true if RESULT indicates failure,
70 cmd_result_is_failure (enum cmd_result result)
72 assert (cmd_result_is_valid (result));
76 /* Command processing states. */
79 S_INITIAL = 0x01, /* Allowed before active file defined. */
80 S_DATA = 0x02, /* Allowed after active file defined. */
81 S_INPUT_PROGRAM = 0x04, /* Allowed in INPUT PROGRAM. */
82 S_FILE_TYPE = 0x08, /* Allowed in FILE TYPE. */
83 S_ANY = 0x0f /* Allowed anywhere. */
86 /* Other command requirements. */
89 F_ENHANCED = 0x10, /* Allowed only in enhanced syntax mode. */
90 F_TESTING = 0x20, /* Allowed only in testing mode. */
91 F_KEEP_FINAL_TOKEN = 0x40,/* Don't skip final token in command name. */
92 F_ABBREV = 0x80 /* Not a candidate for name completion. */
95 /* A single command. */
98 enum states states; /* States in which command is allowed. */
99 enum flags flags; /* Other command requirements. */
100 const char *name; /* Command name. */
101 int (*function) (struct lexer *, struct dataset *); /* Function to call. */
104 /* Define the command array. */
105 #define DEF_CMD(STATES, FLAGS, NAME, FUNCTION) {STATES, FLAGS, NAME, FUNCTION},
106 #define UNIMPL_CMD(NAME, DESCRIPTION) {S_ANY, 0, NAME, NULL},
107 static const struct command commands[] =
109 #include "command.def"
114 static const size_t command_cnt = sizeof commands / sizeof *commands;
116 static bool in_correct_state (const struct command *, enum cmd_state);
117 static bool report_state_mismatch (const struct command *, enum cmd_state);
118 static const struct command *find_command (const char *name);
119 static void set_completion_state (enum cmd_state);
121 /* Command parser. */
123 static const struct command *parse_command_name (struct lexer *lexer);
124 static enum cmd_result do_parse_command (struct lexer *, struct dataset *, enum cmd_state);
126 /* Parses an entire command, from command name to terminating
127 dot. On failure, skips to the terminating dot.
128 Returns the command's success or failure result. */
130 cmd_parse_in_state (struct lexer *lexer, struct dataset *ds,
131 enum cmd_state state)
135 result = do_parse_command (lexer, ds, state);
137 assert (!proc_is_open (ds));
138 unset_cmd_algorithm ();
139 dict_clear_aux (dataset_dict (ds));
140 if (!dataset_end_of_command (ds))
141 result = CMD_CASCADING_FAILURE;
147 cmd_parse (struct lexer *lexer, struct dataset *ds)
149 const struct dictionary *dict = dataset_dict (ds);
150 return cmd_parse_in_state (lexer, ds,
151 proc_has_active_file (ds) &&
152 dict_get_var_cnt (dict) > 0 ?
153 CMD_STATE_DATA : CMD_STATE_INITIAL);
157 /* Parses an entire command, from command name to terminating
159 static enum cmd_result
160 do_parse_command (struct lexer *lexer,
161 struct dataset *ds, enum cmd_state state)
163 const struct command *command = NULL;
164 enum cmd_result result;
167 /* Read the command's first token. */
168 prompt_set_style (PROMPT_FIRST);
169 set_completion_state (state);
171 if (lex_token (lexer) == T_STOP)
176 else if (lex_token (lexer) == '.')
178 /* Null commands can result from extra empty lines. */
179 result = CMD_SUCCESS;
183 prompt_set_style (PROMPT_LATER);
185 /* Parse the command name. */
186 command = parse_command_name (lexer);
189 result = CMD_FAILURE;
192 text_item_submit (text_item_create (TEXT_ITEM_COMMAND_OPEN, command->name));
195 if (command->function == NULL)
197 msg (SE, _("%s is not yet implemented."), command->name);
198 result = CMD_NOT_IMPLEMENTED;
200 else if ((command->flags & F_TESTING) && !settings_get_testing_mode ())
202 msg (SE, _("%s may be used only in testing mode."), command->name);
203 result = CMD_FAILURE;
205 else if ((command->flags & F_ENHANCED) && settings_get_syntax () != ENHANCED)
207 msg (SE, _("%s may be used only in enhanced syntax mode."),
209 result = CMD_FAILURE;
211 else if (!in_correct_state (command, state))
213 report_state_mismatch (command, state);
214 result = CMD_FAILURE;
218 /* Execute command. */
219 result = command->function (lexer, ds);
222 assert (cmd_result_is_valid (result));
225 if (cmd_result_is_failure (result))
227 lex_discard_rest_of_command (lexer);
228 if (source_stream_current_error_mode (
229 lex_get_source_stream (lexer)) == ERRMODE_STOP )
231 msg (MW, _("Error encountered while ERROR=STOP is effective."));
232 result = CMD_CASCADING_FAILURE;
237 text_item_submit (text_item_create (TEXT_ITEM_COMMAND_CLOSE,
244 match_strings (const char *a, size_t a_len,
245 const char *b, size_t b_len)
247 size_t match_len = 0;
249 while (a_len > 0 && b_len > 0)
251 /* Mismatch always returns zero. */
252 if (toupper ((unsigned char) *a++) != toupper ((unsigned char) *b++))
264 /* Returns the first character in the first word in STRING,
265 storing the word's length in *WORD_LEN. If no words remain,
266 returns a null pointer and stores 0 in *WORD_LEN. Words are
267 sequences of alphanumeric characters or single
268 non-alphanumeric characters. Words are delimited by
271 find_word (const char *string, size_t *word_len)
273 /* Skip whitespace and asterisks. */
274 while (isspace ((unsigned char) *string))
284 /* Special one-character word? */
285 if (!isalnum ((unsigned char) *string))
291 /* Alphanumeric word. */
293 while (isalnum ((unsigned char) string[*word_len]))
299 /* Returns true if strings A and B can be confused based on
300 their first three letters. */
302 conflicting_3char_prefixes (const char *a, const char *b)
304 size_t aw_len, bw_len;
307 aw = find_word (a, &aw_len);
308 bw = find_word (b, &bw_len);
309 assert (aw != NULL && bw != NULL);
311 /* Words that are the same don't conflict. */
312 if (aw_len == bw_len && !buf_compare_case (aw, bw, aw_len))
315 /* Words that are otherwise the same in the first three letters
317 return ((aw_len > 3 && bw_len > 3)
318 || (aw_len == 3 && bw_len > 3)
319 || (bw_len == 3 && aw_len > 3)) && !buf_compare_case (aw, bw, 3);
322 /* Returns true if CMD can be confused with another command
323 based on the first three letters of its first word. */
325 conflicting_3char_prefix_command (const struct command *cmd)
327 assert (cmd >= commands && cmd < commands + command_cnt);
329 return ((cmd > commands
330 && conflicting_3char_prefixes (cmd[-1].name, cmd[0].name))
331 || (cmd < commands + command_cnt
332 && conflicting_3char_prefixes (cmd[0].name, cmd[1].name)));
335 /* Ways that a set of words can match a command name. */
338 MISMATCH, /* Not a match. */
339 PARTIAL_MATCH, /* The words begin the command name. */
340 COMPLETE_MATCH /* The words are the command name. */
343 /* Figures out how well the WORD_CNT words in WORDS match CMD,
344 and returns the appropriate enum value. If WORDS are a
345 partial match for CMD and the next word in CMD is a dash, then
346 *DASH_POSSIBLE is set to 1 if DASH_POSSIBLE is non-null;
347 otherwise, *DASH_POSSIBLE is unchanged. */
348 static enum command_match
349 cmd_match_words (const struct command *cmd,
350 char *const words[], size_t word_cnt,
357 for (word = find_word (cmd->name, &word_len), word_idx = 0;
358 word != NULL && word_idx < word_cnt;
359 word = find_word (word + word_len, &word_len), word_idx++)
360 if (word_len != strlen (words[word_idx])
361 || buf_compare_case (word, words[word_idx], word_len))
363 size_t match_chars = match_strings (word, word_len,
365 strlen (words[word_idx]));
366 if (match_chars == 0)
371 else if (match_chars == 1 || match_chars == 2)
373 /* One- and two-character abbreviations are not
377 else if (match_chars == 3)
379 /* Three-character abbreviations are acceptable
380 in the first word of a command if there are
381 no name conflicts. They are always
382 acceptable after the first word. */
383 if (word_idx == 0 && conflicting_3char_prefix_command (cmd))
386 else /* match_chars > 3 */
388 /* Four-character and longer abbreviations are
389 always acceptable. */
393 if (word == NULL && word_idx == word_cnt)
395 /* cmd->name = "FOO BAR", words[] = {"FOO", "BAR"}. */
396 return COMPLETE_MATCH;
398 else if (word == NULL)
400 /* cmd->name = "FOO BAR", words[] = {"FOO", "BAR", "BAZ"}. */
405 /* cmd->name = "FOO BAR BAZ", words[] = {"FOO", "BAR"}. */
406 if (word[0] == '-' && dash_possible != NULL)
408 return PARTIAL_MATCH;
412 /* Returns the number of commands for which the WORD_CNT words in
413 WORDS are a partial or complete match. If some partial match
414 has a dash as the next word, then *DASH_POSSIBLE is set to 1,
415 otherwise it is set to 0. */
417 count_matching_commands (char *const words[], size_t word_cnt,
420 const struct command *cmd;
425 for (cmd = commands; cmd < commands + command_cnt; cmd++)
426 if (cmd_match_words (cmd, words, word_cnt, dash_possible) != MISMATCH)
429 return cmd_match_count;
432 /* Returns the command for which the WORD_CNT words in WORDS are
433 a complete match. Returns a null pointer if no such command
435 static const struct command *
436 get_complete_match (char *const words[], size_t word_cnt)
438 const struct command *cmd;
440 for (cmd = commands; cmd < commands + command_cnt; cmd++)
441 if (cmd_match_words (cmd, words, word_cnt, NULL) == COMPLETE_MATCH)
447 /* Returns the command with the given exact NAME.
448 Aborts if no such command exists. */
449 static const struct command *
450 find_command (const char *name)
452 const struct command *cmd;
454 for (cmd = commands; cmd < commands + command_cnt; cmd++)
455 if (!strcmp (cmd->name, name))
460 /* Frees the WORD_CNT words in WORDS. */
462 free_words (char *words[], size_t word_cnt)
466 for (idx = 0; idx < word_cnt; idx++)
470 /* Flags an error that the command whose name is given by the
471 WORD_CNT words in WORDS is unknown. */
473 unknown_command_error (struct lexer *lexer, char *const words[], size_t word_cnt)
476 lex_error (lexer, _("expecting command name"));
483 for (i = 0; i < word_cnt; i++)
486 ds_put_char (&s, ' ');
487 ds_put_cstr (&s, words[i]);
490 msg (SE, _("Unknown command %s."), ds_cstr (&s));
496 /* Parse the command name and return a pointer to the corresponding
497 struct command if successful.
498 If not successful, return a null pointer. */
499 static const struct command *
500 parse_command_name (struct lexer *lexer)
504 int complete_word_cnt;
507 if (lex_token (lexer) == T_EXP ||
508 lex_token (lexer) == '*' || lex_token (lexer) == '[')
509 return find_command ("COMMENT");
512 word_cnt = complete_word_cnt = 0;
513 while (lex_token (lexer) == T_ID || (dash_possible && lex_token (lexer) == '-'))
517 assert (word_cnt < sizeof words / sizeof *words);
518 if (lex_token (lexer) == T_ID)
520 words[word_cnt] = ds_xstrdup (lex_tokstr (lexer));
521 str_uppercase (words[word_cnt]);
523 else if (lex_token (lexer) == '-')
524 words[word_cnt] = xstrdup ("-");
527 cmd_match_cnt = count_matching_commands (words, word_cnt,
529 if (cmd_match_cnt == 0)
531 else if (cmd_match_cnt == 1)
533 const struct command *command = get_complete_match (words, word_cnt);
536 if (!(command->flags & F_KEEP_FINAL_TOKEN))
538 free_words (words, word_cnt);
542 else /* cmd_match_cnt > 1 */
544 /* Do we have a complete command name so far? */
545 if (get_complete_match (words, word_cnt) != NULL)
546 complete_word_cnt = word_cnt;
551 /* If we saw a complete command name earlier, drop back to
553 if (complete_word_cnt)
555 int pushback_word_cnt;
556 const struct command *command;
558 /* Get the command. */
559 command = get_complete_match (words, complete_word_cnt);
560 assert (command != NULL);
562 /* Figure out how many words we want to keep.
563 We normally want to swallow the entire command. */
564 pushback_word_cnt = complete_word_cnt + 1;
565 if (command->flags & F_KEEP_FINAL_TOKEN)
568 /* FIXME: We only support one-token pushback. */
569 assert (pushback_word_cnt + 1 >= word_cnt);
571 while (word_cnt > pushback_word_cnt)
574 if (strcmp (words[word_cnt], "-"))
575 lex_put_back_id (lexer, words[word_cnt]);
577 lex_put_back (lexer, '-');
578 free (words[word_cnt]);
581 free_words (words, word_cnt);
585 /* We didn't get a valid command name. */
586 unknown_command_error (lexer, words, word_cnt);
587 free_words (words, word_cnt);
591 /* Returns true if COMMAND is allowed in STATE,
594 in_correct_state (const struct command *command, enum cmd_state state)
596 return ((state == CMD_STATE_INITIAL && command->states & S_INITIAL)
597 || (state == CMD_STATE_DATA && command->states & S_DATA)
598 || (state == CMD_STATE_INPUT_PROGRAM
599 && command->states & S_INPUT_PROGRAM)
600 || (state == CMD_STATE_FILE_TYPE && command->states & S_FILE_TYPE));
603 /* Emits an appropriate error message for trying to invoke
606 report_state_mismatch (const struct command *command, enum cmd_state state)
608 assert (!in_correct_state (command, state));
609 if (state == CMD_STATE_INITIAL || state == CMD_STATE_DATA)
611 switch (command->states)
613 /* One allowed state. */
615 msg (SE, _("%s is allowed only before the active file has "
616 "been defined."), command->name);
619 msg (SE, _("%s is allowed only after the active file has "
620 "been defined."), command->name);
622 case S_INPUT_PROGRAM:
623 msg (SE, _("%s is allowed only inside INPUT PROGRAM."),
627 msg (SE, _("%s is allowed only inside FILE TYPE."), command->name);
630 /* Two allowed states. */
631 case S_INITIAL | S_DATA:
633 case S_INITIAL | S_INPUT_PROGRAM:
634 msg (SE, _("%s is allowed only before the active file has "
635 "been defined or inside INPUT PROGRAM."), command->name);
637 case S_INITIAL | S_FILE_TYPE:
638 msg (SE, _("%s is allowed only before the active file has "
639 "been defined or inside FILE TYPE."), command->name);
641 case S_DATA | S_INPUT_PROGRAM:
642 msg (SE, _("%s is allowed only after the active file has "
643 "been defined or inside INPUT PROGRAM."), command->name);
645 case S_DATA | S_FILE_TYPE:
646 msg (SE, _("%s is allowed only after the active file has "
647 "been defined or inside FILE TYPE."), command->name);
649 case S_INPUT_PROGRAM | S_FILE_TYPE:
650 msg (SE, _("%s is allowed only inside INPUT PROGRAM "
651 "or inside FILE TYPE."), command->name);
654 /* Three allowed states. */
655 case S_DATA | S_INPUT_PROGRAM | S_FILE_TYPE:
656 msg (SE, _("%s is allowed only after the active file has "
657 "been defined, inside INPUT PROGRAM, or inside "
658 "FILE TYPE."), command->name);
660 case S_INITIAL | S_INPUT_PROGRAM | S_FILE_TYPE:
661 msg (SE, _("%s is allowed only before the active file has "
662 "been defined, inside INPUT PROGRAM, or inside "
663 "FILE TYPE."), command->name);
665 case S_INITIAL | S_DATA | S_FILE_TYPE:
667 case S_INITIAL | S_DATA | S_INPUT_PROGRAM:
670 /* Four allowed states. */
671 case S_INITIAL | S_DATA | S_INPUT_PROGRAM | S_FILE_TYPE:
678 else if (state == CMD_STATE_INPUT_PROGRAM)
679 msg (SE, _("%s is not allowed inside %s."), command->name, "INPUT PROGRAM" );
680 else if (state == CMD_STATE_FILE_TYPE)
681 msg (SE, _("%s is not allowed inside %s."), command->name, "FILE TYPE");
686 /* Command name completion. */
688 static enum cmd_state completion_state = CMD_STATE_INITIAL;
691 set_completion_state (enum cmd_state state)
693 completion_state = state;
696 /* Returns the next possible completion of a command name that
697 begins with PREFIX, in the current command state, or a null
698 pointer if no completions remain.
699 Before calling the first time, set *CMD to a null pointer. */
701 cmd_complete (const char *prefix, const struct command **cmd)
706 for (; *cmd < commands + command_cnt; (*cmd)++)
707 if (!memcasecmp ((*cmd)->name, prefix, strlen (prefix))
708 && (!((*cmd)->flags & F_TESTING) || settings_get_testing_mode ())
709 && (!((*cmd)->flags & F_ENHANCED) || settings_get_syntax () == ENHANCED)
710 && !((*cmd)->flags & F_ABBREV)
711 && ((*cmd)->function != NULL)
712 && in_correct_state (*cmd, completion_state))
713 return (*cmd)++->name;
718 /* Simple commands. */
720 /* Parse and execute FINISH command. */
722 cmd_finish (struct lexer *lexer UNUSED, struct dataset *ds UNUSED)
727 /* Parses the N command. */
729 cmd_n_of_cases (struct lexer *lexer, struct dataset *ds)
734 if (!lex_force_int (lexer))
736 x = lex_integer (lexer);
738 if (!lex_match_id (lexer, "ESTIMATED"))
739 dict_set_case_limit (dataset_dict (ds), x);
741 return lex_end_of_command (lexer);
744 /* Parses, performs the EXECUTE procedure. */
746 cmd_execute (struct lexer *lexer, struct dataset *ds)
748 bool ok = casereader_destroy (proc_open (ds));
749 if (!proc_commit (ds) || !ok)
750 return CMD_CASCADING_FAILURE;
751 return lex_end_of_command (lexer);
754 /* Parses, performs the ERASE command. */
756 cmd_erase (struct lexer *lexer, struct dataset *ds UNUSED)
758 if (settings_get_safer_mode ())
760 msg (SE, _("This command not allowed when the SAFER option is set."));
764 if (!lex_force_match_id (lexer, "FILE"))
766 lex_match (lexer, '=');
767 if (!lex_force_string (lexer))
770 if (remove (ds_cstr (lex_tokstr (lexer))) == -1)
772 msg (SW, _("Error removing `%s': %s."),
773 ds_cstr (lex_tokstr (lexer)), strerror (errno));
780 /* Parses, performs the NEW FILE command. */
782 cmd_new_file (struct lexer *lexer, struct dataset *ds)
784 proc_discard_active_file (ds);
786 return lex_end_of_command (lexer);
789 /* Parses a comment. */
791 cmd_comment (struct lexer *lexer, struct dataset *ds UNUSED)
793 lex_skip_comment (lexer);