X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Flanguage%2Fcommand.c;h=9f90db93a941af0762b20e4f02b3f6e4758d8732;hb=5933892c21c6166b5714be979116d3aa70219c57;hp=1688a10eb6e3472dc5fa7e3ae0a21134827fc006;hpb=68f08c4bb53fcde16035b622bdb6e9529f9cf3ae;p=pspp diff --git a/src/language/command.c b/src/language/command.c index 1688a10eb6..9f90db93a9 100644 --- a/src/language/command.c +++ b/src/language/command.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2009, 2010 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -16,38 +16,29 @@ #include -#include +#include "language/command.h" #include #include #include #include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if HAVE_SYS_WAIT_H -#include -#endif - -#if HAVE_READLINE -#include -#endif + +#include "data/casereader.h" +#include "data/dictionary.h" +#include "data/procedure.h" +#include "data/settings.h" +#include "data/variable.h" +#include "language/lexer/lexer.h" +#include "language/prompt.h" +#include "libpspp/assertion.h" +#include "libpspp/compiler.h" +#include "libpspp/message.h" +#include "libpspp/str.h" +#include "libpspp/getl.h" +#include "output/text-item.h" + +#include "xalloc.h" +#include "xmalloca.h" #include "gettext.h" #define _(msgid) gettext (msgid) @@ -141,11 +132,7 @@ cmd_parse_in_state (struct lexer *lexer, struct dataset *ds, { int result; - som_new_series (); - result = do_parse_command (lexer, ds, state); - if (cmd_result_is_failure (result)) - lex_discard_rest_of_command (lexer); assert (!proc_is_open (ds)); unset_cmd_algorithm (); @@ -173,8 +160,9 @@ static enum cmd_result do_parse_command (struct lexer *lexer, struct dataset *ds, enum cmd_state state) { - const struct command *command; + const struct command *command = NULL; enum cmd_result result; + bool opened = false; /* Read the command's first token. */ prompt_set_style (PROMPT_FIRST); @@ -201,53 +189,54 @@ do_parse_command (struct lexer *lexer, result = CMD_FAILURE; goto finish; } - else if (command->function == NULL) + text_item_submit (text_item_create (TEXT_ITEM_COMMAND_OPEN, command->name)); + opened = true; + + if (command->function == NULL) { - msg (SE, _("%s is unimplemented."), command->name); + msg (SE, _("%s is not yet implemented."), command->name); result = CMD_NOT_IMPLEMENTED; - goto finish; } - else if ((command->flags & F_TESTING) && !get_testing_mode ()) + else if ((command->flags & F_TESTING) && !settings_get_testing_mode ()) { msg (SE, _("%s may be used only in testing mode."), command->name); result = CMD_FAILURE; - goto finish; } - else if ((command->flags & F_ENHANCED) && get_syntax () != ENHANCED) + else if ((command->flags & F_ENHANCED) && settings_get_syntax () != ENHANCED) { msg (SE, _("%s may be used only in enhanced syntax mode."), command->name); result = CMD_FAILURE; - goto finish; } else if (!in_correct_state (command, state)) { report_state_mismatch (command, state); result = CMD_FAILURE; - goto finish; } - - /* Execute command. */ - msg_set_command_name (command->name); - tab_set_command_name (command->name); - result = command->function (lexer, ds); - tab_set_command_name (NULL); - msg_set_command_name (NULL); + else + { + /* Execute command. */ + result = command->function (lexer, ds); + } assert (cmd_result_is_valid (result)); finish: - if ( cmd_result_is_failure (result)) + if (cmd_result_is_failure (result)) { - const struct source_stream *cs = lex_get_source_stream (lexer); - - if ( source_stream_current_error_mode (cs) == ERRMODE_STOP ) + lex_discard_rest_of_command (lexer); + if (source_stream_current_error_mode ( + lex_get_source_stream (lexer)) == ERRMODE_STOP ) { msg (MW, _("Error encountered while ERROR=STOP is effective.")); result = CMD_CASCADING_FAILURE; } } + if (opened) + text_item_submit (text_item_create (TEXT_ITEM_COMMAND_CLOSE, + command->name)); + return result; } @@ -619,37 +608,77 @@ report_state_mismatch (const struct command *command, enum cmd_state state) assert (!in_correct_state (command, state)); if (state == CMD_STATE_INITIAL || state == CMD_STATE_DATA) { - const char *allowed[3]; - int allowed_cnt; - char *s; - - allowed_cnt = 0; - if (command->states & S_INITIAL) - allowed[allowed_cnt++] = _("before the active file has been defined"); - else if (command->states & S_DATA) - allowed[allowed_cnt++] = _("after the active file has been defined"); - if (command->states & S_INPUT_PROGRAM) - allowed[allowed_cnt++] = _("inside INPUT PROGRAM"); - if (command->states & S_FILE_TYPE) - allowed[allowed_cnt++] = _("inside FILE TYPE"); - - if (allowed_cnt == 1) - s = xstrdup (allowed[0]); - else if (allowed_cnt == 2) - s = xasprintf (_("%s or %s"), allowed[0], allowed[1]); - else if (allowed_cnt == 3) - s = xasprintf (_("%s, %s, or %s"), allowed[0], allowed[1], allowed[2]); - else - NOT_REACHED (); - - msg (SE, _("%s is allowed only %s."), command->name, s); - - free (s); + switch (command->states) + { + /* One allowed state. */ + case S_INITIAL: + msg (SE, _("%s is allowed only before the active file has " + "been defined."), command->name); + break; + case S_DATA: + msg (SE, _("%s is allowed only after the active file has " + "been defined."), command->name); + break; + case S_INPUT_PROGRAM: + msg (SE, _("%s is allowed only inside INPUT PROGRAM."), + command->name); + break; + case S_FILE_TYPE: + msg (SE, _("%s is allowed only inside FILE TYPE."), command->name); + break; + + /* Two allowed states. */ + case S_INITIAL | S_DATA: + NOT_REACHED (); + case S_INITIAL | S_INPUT_PROGRAM: + msg (SE, _("%s is allowed only before the active file has " + "been defined or inside INPUT PROGRAM."), command->name); + break; + case S_INITIAL | S_FILE_TYPE: + msg (SE, _("%s is allowed only before the active file has " + "been defined or inside FILE TYPE."), command->name); + break; + case S_DATA | S_INPUT_PROGRAM: + msg (SE, _("%s is allowed only after the active file has " + "been defined or inside INPUT PROGRAM."), command->name); + break; + case S_DATA | S_FILE_TYPE: + msg (SE, _("%s is allowed only after the active file has " + "been defined or inside FILE TYPE."), command->name); + break; + case S_INPUT_PROGRAM | S_FILE_TYPE: + msg (SE, _("%s is allowed only inside INPUT PROGRAM " + "or inside FILE TYPE."), command->name); + break; + + /* Three allowed states. */ + case S_DATA | S_INPUT_PROGRAM | S_FILE_TYPE: + msg (SE, _("%s is allowed only after the active file has " + "been defined, inside INPUT PROGRAM, or inside " + "FILE TYPE."), command->name); + break; + case S_INITIAL | S_INPUT_PROGRAM | S_FILE_TYPE: + msg (SE, _("%s is allowed only before the active file has " + "been defined, inside INPUT PROGRAM, or inside " + "FILE TYPE."), command->name); + break; + case S_INITIAL | S_DATA | S_FILE_TYPE: + NOT_REACHED (); + case S_INITIAL | S_DATA | S_INPUT_PROGRAM: + NOT_REACHED (); + + /* Four allowed states. */ + case S_INITIAL | S_DATA | S_INPUT_PROGRAM | S_FILE_TYPE: + NOT_REACHED (); + + default: + NOT_REACHED (); + } } else if (state == CMD_STATE_INPUT_PROGRAM) - msg (SE, _("%s is not allowed inside INPUT PROGRAM."), command->name); + msg (SE, _("%s is not allowed inside %s."), command->name, "INPUT PROGRAM" ); else if (state == CMD_STATE_FILE_TYPE) - msg (SE, _("%s is not allowed inside FILE TYPE."), command->name); + msg (SE, _("%s is not allowed inside %s."), command->name, "FILE TYPE"); return false; } @@ -676,8 +705,8 @@ cmd_complete (const char *prefix, const struct command **cmd) for (; *cmd < commands + command_cnt; (*cmd)++) if (!memcasecmp ((*cmd)->name, prefix, strlen (prefix)) - && (!((*cmd)->flags & F_TESTING) || get_testing_mode ()) - && (!((*cmd)->flags & F_ENHANCED) || get_syntax () == ENHANCED) + && (!((*cmd)->flags & F_TESTING) || settings_get_testing_mode ()) + && (!((*cmd)->flags & F_ENHANCED) || settings_get_syntax () == ENHANCED) && !((*cmd)->flags & F_ABBREV) && ((*cmd)->function != NULL) && in_correct_state (*cmd, completion_state)) @@ -726,7 +755,7 @@ cmd_execute (struct lexer *lexer, struct dataset *ds) int cmd_erase (struct lexer *lexer, struct dataset *ds UNUSED) { - if (get_safer_mode ()) + if (settings_get_safer_mode ()) { msg (SE, _("This command not allowed when the SAFER option is set.")); return CMD_FAILURE; @@ -748,124 +777,6 @@ cmd_erase (struct lexer *lexer, struct dataset *ds UNUSED) return CMD_SUCCESS; } -#if HAVE_FORK && HAVE_EXECL -/* Spawn an interactive shell process. */ -static bool -shell (void) -{ - int pid; - - pid = fork (); - switch (pid) - { - case 0: - { - const char *shell_fn; - char *shell_process; - - { - int i; - - for (i = 3; i < 20; i++) - close (i); - } - - shell_fn = getenv ("SHELL"); - if (shell_fn == NULL) - shell_fn = "/bin/sh"; - - { - const char *cp = strrchr (shell_fn, '/'); - cp = cp ? &cp[1] : shell_fn; - shell_process = local_alloc (strlen (cp) + 8); - strcpy (shell_process, "-"); - strcat (shell_process, cp); - if (strcmp (cp, "sh")) - shell_process[0] = '+'; - } - - execl (shell_fn, shell_process, NULL); - - _exit (1); - } - - case -1: - msg (SE, _("Couldn't fork: %s."), strerror (errno)); - return false; - - default: - assert (pid > 0); - while (wait (NULL) != pid) - ; - return true; - } -} -#else /* !(HAVE_FORK && HAVE_EXECL) */ -/* Don't know how to spawn an interactive shell. */ -static bool -shell (void) -{ - msg (SE, _("Interactive shell not supported on this platform.")); - return false; -} -#endif - -/* Executes the specified COMMAND in a subshell. Returns true if - successful, false otherwise. */ -static bool -run_command (const char *command) -{ - if (system (NULL) == 0) - { - msg (SE, _("Command shell not supported on this platform.")); - return false; - } - - /* Execute the command. */ - if (system (command) == -1) - msg (SE, _("Error executing command: %s."), strerror (errno)); - - return true; -} - -/* Parses, performs the HOST command. */ -int -cmd_host (struct lexer *lexer, struct dataset *ds UNUSED) -{ - int look_ahead; - - if (get_safer_mode ()) - { - msg (SE, _("This command not allowed when the SAFER option is set.")); - return CMD_FAILURE; - } - - look_ahead = lex_look_ahead (lexer); - if (look_ahead == '.') - { - lex_get (lexer); - return shell () ? CMD_SUCCESS : CMD_FAILURE; - } - else if (look_ahead == '\'' || look_ahead == '"') - { - bool ok; - - lex_get (lexer); - if (!lex_force_string (lexer)) - NOT_REACHED (); - ok = run_command (ds_cstr (lex_tokstr (lexer))); - - lex_get (lexer); - return ok ? lex_end_of_command (lexer) : CMD_FAILURE; - } - else - { - bool ok = run_command (lex_rest_of_line (lexer)); - lex_discard_line (lexer); - return ok ? CMD_SUCCESS : CMD_FAILURE; - } -} - /* Parses, performs the NEW FILE command. */ int cmd_new_file (struct lexer *lexer, struct dataset *ds)