1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 1997-9, 2000, 2009, 2010, 2011, 2012, 2013 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/dataset.h"
28 #include "data/dictionary.h"
29 #include "data/session.h"
30 #include "data/settings.h"
31 #include "data/variable.h"
32 #include "language/lexer/command-name.h"
33 #include "language/lexer/lexer.h"
34 #include "libpspp/assertion.h"
35 #include "libpspp/compiler.h"
36 #include "libpspp/i18n.h"
37 #include "libpspp/message.h"
38 #include "libpspp/str.h"
39 #include "output/text-item.h"
45 #define _(msgid) gettext (msgid)
46 #define N_(msgid) msgid
48 /* Returns true if RESULT is a valid "enum cmd_result",
51 cmd_result_is_valid (enum cmd_result result)
62 case CMD_NOT_IMPLEMENTED:
63 case CMD_CASCADING_FAILURE:
71 /* Returns true if RESULT indicates success,
74 cmd_result_is_success (enum cmd_result result)
76 assert (cmd_result_is_valid (result));
80 /* Returns true if RESULT indicates failure,
83 cmd_result_is_failure (enum cmd_result result)
85 assert (cmd_result_is_valid (result));
89 /* Command processing states. */
92 S_INITIAL = 0x01, /* Allowed before active dataset defined. */
93 S_DATA = 0x02, /* Allowed after active dataset defined. */
94 S_INPUT_PROGRAM = 0x04, /* Allowed in INPUT PROGRAM. */
95 S_FILE_TYPE = 0x08, /* Allowed in FILE TYPE. */
96 S_ANY = 0x0f /* Allowed anywhere. */
99 /* Other command requirements. */
102 F_ENHANCED = 0x10, /* Allowed only in enhanced syntax mode. */
103 F_TESTING = 0x20, /* Allowed only in testing mode. */
104 F_ABBREV = 0x80 /* Not a candidate for name completion. */
107 /* A single command. */
110 enum states states; /* States in which command is allowed. */
111 enum flags flags; /* Other command requirements. */
112 const char *name; /* Command name. */
113 int (*function) (struct lexer *, struct dataset *); /* Function to call. */
116 /* Define the command array. */
117 #define DEF_CMD(STATES, FLAGS, NAME, FUNCTION) {STATES, FLAGS, NAME, FUNCTION},
118 #define UNIMPL_CMD(NAME, DESCRIPTION) {S_ANY, 0, NAME, NULL},
119 static const struct command commands[] =
121 #include "command.def"
126 static const size_t command_cnt = sizeof commands / sizeof *commands;
128 static bool in_correct_state (const struct command *, enum cmd_state);
129 static bool report_state_mismatch (const struct command *, enum cmd_state);
130 static void set_completion_state (enum cmd_state);
132 /* Command parser. */
134 static const struct command *parse_command_name (struct lexer *,
136 static enum cmd_result do_parse_command (struct lexer *, struct dataset *, enum cmd_state);
138 /* Parses an entire command, from command name to terminating
139 dot. On failure, skips to the terminating dot.
140 Returns the command's success or failure result. */
142 cmd_parse_in_state (struct lexer *lexer, struct dataset *ds,
143 enum cmd_state state)
145 struct session *session = dataset_session (ds);
148 result = do_parse_command (lexer, ds, state);
150 ds = session_active_dataset (session);
151 assert (!proc_is_open (ds));
152 unset_cmd_algorithm ();
153 if (!dataset_end_of_command (ds))
154 result = CMD_CASCADING_FAILURE;
160 cmd_parse (struct lexer *lexer, struct dataset *ds)
162 const struct dictionary *dict = dataset_dict (ds);
163 return cmd_parse_in_state (lexer, ds,
164 dataset_has_source (ds) &&
165 dict_get_var_cnt (dict) > 0 ?
166 CMD_STATE_DATA : CMD_STATE_INITIAL);
170 /* Parses an entire command, from command name to terminating
172 static enum cmd_result
173 do_parse_command (struct lexer *lexer,
174 struct dataset *ds, enum cmd_state state)
176 const struct command *command = NULL;
177 enum cmd_result result;
181 /* Read the command's first token. */
182 set_completion_state (state);
183 if (lex_token (lexer) == T_STOP)
188 else if (lex_token (lexer) == T_ENDCMD)
190 /* Null commands can result from extra empty lines. */
191 result = CMD_SUCCESS;
195 /* Parse the command name. */
196 command = parse_command_name (lexer, &n_tokens);
199 result = CMD_FAILURE;
202 text_item_submit (text_item_create (TEXT_ITEM_COMMAND_OPEN, command->name));
205 if (command->function == NULL)
207 msg (SE, _("%s is not yet implemented."), command->name);
208 result = CMD_NOT_IMPLEMENTED;
210 else if ((command->flags & F_TESTING) && !settings_get_testing_mode ())
212 msg (SE, _("%s may be used only in testing mode."), command->name);
213 result = CMD_FAILURE;
215 else if ((command->flags & F_ENHANCED) && settings_get_syntax () != ENHANCED)
217 msg (SE, _("%s may be used only in enhanced syntax mode."),
219 result = CMD_FAILURE;
221 else if (!in_correct_state (command, state))
223 report_state_mismatch (command, state);
224 result = CMD_FAILURE;
228 /* Execute command. */
231 for (i = 0; i < n_tokens; i++)
233 result = command->function (lexer, ds);
236 assert (cmd_result_is_valid (result));
239 if (cmd_result_is_failure (result))
240 lex_interactive_reset (lexer);
241 else if (result == CMD_SUCCESS)
242 result = lex_end_of_command (lexer);
244 lex_discard_rest_of_command (lexer);
245 while (lex_token (lexer) == T_ENDCMD)
249 text_item_submit (text_item_create (TEXT_ITEM_COMMAND_CLOSE,
256 find_best_match (struct substring s, const struct command **matchp)
258 const struct command *cmd;
259 struct command_matcher cm;
262 command_matcher_init (&cm, s);
263 for (cmd = commands; cmd < &commands[command_cnt]; cmd++)
264 command_matcher_add (&cm, ss_cstr (cmd->name), CONST_CAST (void *, cmd));
266 *matchp = command_matcher_get_match (&cm);
267 missing_words = command_matcher_get_missing_words (&cm);
269 command_matcher_destroy (&cm);
271 return missing_words;
275 parse_command_word (struct lexer *lexer, struct string *s, int n)
277 bool need_space = ds_last (s) != EOF && ds_last (s) != '-';
279 switch (lex_next_token (lexer, n))
282 ds_put_byte (s, '-');
287 ds_put_byte (s, ' ');
288 ds_put_cstr (s, lex_next_tokcstr (lexer, n));
292 if (lex_next_is_integer (lexer, n))
294 int integer = lex_next_integer (lexer, n);
298 ds_put_byte (s, ' ');
299 ds_put_format (s, "%ld", lex_next_integer (lexer, n));
310 /* Parses the command name. On success returns a pointer to the corresponding
311 struct command and stores the number of tokens in the command name into
312 *N_TOKENS. On failure, returns a null pointer and stores the number of
313 tokens required to determine that no command name was present into
315 static const struct command *
316 parse_command_name (struct lexer *lexer, int *n_tokens)
318 const struct command *command;
327 while (parse_command_word (lexer, &s, word))
329 missing_words = find_best_match (ds_ss (&s), &command);
330 if (missing_words <= 0)
335 if (command == NULL && missing_words > 0)
337 ds_put_cstr (&s, " .");
338 missing_words = find_best_match (ds_ss (&s), &command);
339 ds_truncate (&s, ds_length (&s) - 2);
344 if (ds_is_empty (&s))
345 lex_error (lexer, _("expecting command name"));
347 msg (SE, _("Unknown command `%s'."), ds_cstr (&s));
352 *n_tokens = (word + 1) + missing_words;
356 /* Returns true if COMMAND is allowed in STATE,
359 in_correct_state (const struct command *command, enum cmd_state state)
361 return ((state == CMD_STATE_INITIAL && command->states & S_INITIAL)
362 || (state == CMD_STATE_DATA && command->states & S_DATA)
363 || (state == CMD_STATE_INPUT_PROGRAM
364 && command->states & S_INPUT_PROGRAM)
365 || (state == CMD_STATE_FILE_TYPE && command->states & S_FILE_TYPE));
368 /* Emits an appropriate error message for trying to invoke
371 report_state_mismatch (const struct command *command, enum cmd_state state)
373 assert (!in_correct_state (command, state));
374 if (state == CMD_STATE_INITIAL || state == CMD_STATE_DATA)
376 switch ((int) command->states)
378 /* One allowed state. */
380 msg (SE, _("%s is allowed only before the active dataset has "
381 "been defined."), command->name);
384 msg (SE, _("%s is allowed only after the active dataset has "
385 "been defined."), command->name);
387 case S_INPUT_PROGRAM:
388 msg (SE, _("%s is allowed only inside INPUT PROGRAM."),
392 msg (SE, _("%s is allowed only inside FILE TYPE."), command->name);
395 /* Two allowed states. */
396 case S_INITIAL | S_DATA:
398 case S_INITIAL | S_INPUT_PROGRAM:
399 msg (SE, _("%s is allowed only before the active dataset has been defined or inside %s."),
400 command->name, "INPUT PROGRAM");
402 case S_INITIAL | S_FILE_TYPE:
403 msg (SE, _("%s is allowed only before the active dataset has been defined or inside %s."),
404 command->name, "FILE TYPE");
406 case S_DATA | S_INPUT_PROGRAM:
407 msg (SE, _("%s is allowed only after the active dataset has been defined or inside %s."),
408 command->name, "INPUT PROGRAM");
410 case S_DATA | S_FILE_TYPE:
411 msg (SE, _("%s is allowed only after the active dataset has been defined or inside %s."),
412 command->name, "FILE TYPE");
414 case S_INPUT_PROGRAM | S_FILE_TYPE:
415 msg (SE, _("%s is allowed only inside INPUT PROGRAM or inside FILE TYPE."), command->name);
418 /* Three allowed states. */
419 case S_DATA | S_INPUT_PROGRAM | S_FILE_TYPE:
420 msg (SE, _("%s is allowed only after the active dataset has "
421 "been defined, inside INPUT PROGRAM, or inside "
422 "FILE TYPE."), command->name);
424 case S_INITIAL | S_INPUT_PROGRAM | S_FILE_TYPE:
425 msg (SE, _("%s is allowed only before the active dataset has "
426 "been defined, inside INPUT PROGRAM, or inside "
427 "FILE TYPE."), command->name);
429 case S_INITIAL | S_DATA | S_FILE_TYPE:
431 case S_INITIAL | S_DATA | S_INPUT_PROGRAM:
434 /* Four allowed states. */
435 case S_INITIAL | S_DATA | S_INPUT_PROGRAM | S_FILE_TYPE:
442 else if (state == CMD_STATE_INPUT_PROGRAM)
443 msg (SE, _("%s is not allowed inside %s."),
444 command->name, "INPUT PROGRAM" );
445 else if (state == CMD_STATE_FILE_TYPE)
446 msg (SE, _("%s is not allowed inside %s."), command->name, "FILE TYPE");
451 /* Command name completion. */
453 static enum cmd_state completion_state = CMD_STATE_INITIAL;
456 set_completion_state (enum cmd_state state)
458 completion_state = state;
461 /* Returns the next possible completion of a command name that
462 begins with PREFIX, in the current command state, or a null
463 pointer if no completions remain.
464 Before calling the first time, set *CMD to a null pointer. */
466 cmd_complete (const char *prefix, const struct command **cmd)
471 for (; *cmd < commands + command_cnt; (*cmd)++)
472 if (!memcasecmp ((*cmd)->name, prefix, strlen (prefix))
473 && (!((*cmd)->flags & F_TESTING) || settings_get_testing_mode ())
474 && (!((*cmd)->flags & F_ENHANCED) || settings_get_syntax () == ENHANCED)
475 && !((*cmd)->flags & F_ABBREV)
476 && ((*cmd)->function != NULL)
477 && in_correct_state (*cmd, completion_state))
478 return (*cmd)++->name;
483 /* Simple commands. */
485 /* Parse and execute FINISH command. */
487 cmd_finish (struct lexer *lexer UNUSED, struct dataset *ds UNUSED)
492 /* Parses the N command. */
494 cmd_n_of_cases (struct lexer *lexer, struct dataset *ds)
499 if (!lex_force_int (lexer))
501 x = lex_integer (lexer);
503 if (!lex_match_id (lexer, "ESTIMATED"))
504 dict_set_case_limit (dataset_dict (ds), x);
509 /* Parses, performs the EXECUTE procedure. */
511 cmd_execute (struct lexer *lexer UNUSED, struct dataset *ds)
513 bool ok = casereader_destroy (proc_open (ds));
514 if (!proc_commit (ds) || !ok)
515 return CMD_CASCADING_FAILURE;
519 /* Parses, performs the ERASE command. */
521 cmd_erase (struct lexer *lexer, struct dataset *ds UNUSED)
526 if (settings_get_safer_mode ())
528 msg (SE, _("This command not allowed when the SAFER option is set."));
532 if (!lex_force_match_id (lexer, "FILE"))
534 lex_match (lexer, T_EQUALS);
535 if (!lex_force_string (lexer))
538 filename = utf8_to_filename (lex_tokcstr (lexer));
539 retval = remove (filename);
544 msg (SW, _("Error removing `%s': %s."),
545 lex_tokcstr (lexer), strerror (errno));
553 /* Parses, performs the NEW FILE command. */
555 cmd_new_file (struct lexer *lexer UNUSED, struct dataset *ds)