From: Ben Pfaff Date: Tue, 2 May 2006 01:29:06 +0000 (+0000) Subject: Further clean up the CMD_* command result codes. X-Git-Tag: v0.6.0~914 X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c646c399bf8c942a5e33abaa6c12336429c09f24;p=pspp-builds.git Further clean up the CMD_* command result codes. --- diff --git a/src/language/ChangeLog b/src/language/ChangeLog index 4e88e3e7..81997af6 100644 --- a/src/language/ChangeLog +++ b/src/language/ChangeLog @@ -1,3 +1,19 @@ +Mon May 1 18:17:52 2006 Ben Pfaff + + Further clean up the CMD_* command result codes. + + * command.c (cmd_result_is_valid): New function. + (cmd_result_is_success) Assert that argument is valid. Simplified + check to one for a positive result. + (cmd_result_is_failure) Assert that argument is valid. Simplified + check to one for a negative result. + (do_parse_command) Check that command's returned result is valid. + + * command.h: (enum cmd_result) Renamed CMD_QUIT to CMD_FINISH and + updated all users. Removed CMD_END_SUBLOOP in favor of new + CMD_PRIVATE_FIRST...CMD_PRIVATE_LAST range. Changed failure codes + to have negative values. + Mon May 1 15:56:56 2006 Ben Pfaff Remove vestiges of FILE TYPE support. diff --git a/src/language/command.c b/src/language/command.c index 5712ddbe..b5002cae 100644 --- a/src/language/command.c +++ b/src/language/command.c @@ -52,13 +52,24 @@ #define _(msgid) gettext (msgid) #define N_(msgid) msgid +/* Returns true if RESULT is a valid "enum cmd_result", + false otherwise. */ +static inline bool +cmd_result_is_valid (enum cmd_result result) +{ + return (result == CMD_SUCCESS || result == CMD_EOF || result == CMD_FINISH + || (result >= CMD_PRIVATE_FIRST && result <= CMD_PRIVATE_LAST) + || result == CMD_FAILURE || result == CMD_NOT_IMPLEMENTED + || result == CMD_CASCADING_FAILURE); +} + /* Returns true if RESULT indicates success, false otherwise. */ bool cmd_result_is_success (enum cmd_result result) { - return (result == CMD_SUCCESS || result == CMD_EOF - || result == CMD_QUIT || result == CMD_END_SUBLOOP); + assert (cmd_result_is_valid (result)); + return result > 0; } /* Returns true if RESULT indicates failure, @@ -66,7 +77,8 @@ cmd_result_is_success (enum cmd_result result) bool cmd_result_is_failure (enum cmd_result result) { - return !cmd_result_is_success (result); + assert (cmd_result_is_valid (result)); + return result < 0; } /* Command processing states. */ @@ -175,6 +187,7 @@ do_parse_command (enum cmd_state state) tab_set_command_name (NULL); msg_set_command_name (NULL); + assert (cmd_result_is_valid (result)); return result; } @@ -628,7 +641,7 @@ command_generator (const char *text, int state) int cmd_finish (void) { - return CMD_QUIT; + return CMD_FINISH; } /* Parses the N command. */ diff --git a/src/language/command.h b/src/language/command.h index 0c4a5eac..ec51f658 100644 --- a/src/language/command.h +++ b/src/language/command.h @@ -27,14 +27,19 @@ enum cmd_result { /* Successful return values. */ CMD_SUCCESS = 1, /* Successfully parsed and executed. */ - CMD_EOF, /* No commands left. */ - CMD_QUIT, /* Requested exit. */ - CMD_END_SUBLOOP, /* End of INPUT PROGRAM. */ + CMD_EOF = 2, /* End of input. */ + CMD_FINISH = 3, /* FINISH was executed. */ + + /* Range of successful return values available for use + by agreement between a command and the caller of + cmd_parse(). */ + CMD_PRIVATE_FIRST = 4, + CMD_PRIVATE_LAST = 127, /* Various kinds of failures. */ - CMD_FAILURE, /* Not executed at all. */ - CMD_NOT_IMPLEMENTED, /* Command not implemented. */ - CMD_CASCADING_FAILURE /* Serious error: don't continue. */ + CMD_FAILURE = -1, /* Not executed at all. */ + CMD_NOT_IMPLEMENTED = -2, /* Command not implemented. */ + CMD_CASCADING_FAILURE = -3 /* Serious error: don't continue. */ }; bool cmd_result_is_success (enum cmd_result); diff --git a/src/language/data-io/ChangeLog b/src/language/data-io/ChangeLog index 9333a05b..7c486bc3 100644 --- a/src/language/data-io/ChangeLog +++ b/src/language/data-io/ChangeLog @@ -1,3 +1,28 @@ +Mon May 1 18:21:19 2006 Ben Pfaff + + Further clean up the CMD_* command result codes. + + * (enum cmd_result_extensions) New. Add CMD_END_INPUT_PROGRAM and + CMD_END_CASE result codes. + (struct input_program_pgm) Added case_nr, write_case, wc_data + members for use by END CASE transformation. + (emit_END_CASE) New function. + (cmd_input_program) Interpret CMD_END_CASE by outputting an END + CASE transformation. If none is output by the input program + itself, add one automatically at the end. Change lack of + variables from warning to error. + (cmd_end_input_program) Return CMD_END_INPUT_PROGRAM instead of + CMD_END_SUBLOOP. + (input_program_source_read) No longer any need to special-case END + CASE. Handle TRNS_DROP_CASE properly. Initialize new members in + inp for use by END CASE transformation. + (destroy_input_program) New function. + (input_program_source_destroy) Just call destroy_input_program(). + (cmd_end_case) Just return CMD_END_CASE. + (end_case_trns_proc) No longer a stub handled by + input_program_source_read(). Actually output the case and + increment the case number. + Mon May 1 16:06:30 2006 Ben Pfaff Remove vestiges of REPEATING DATA support. diff --git a/src/language/data-io/inpt-pgm.c b/src/language/data-io/inpt-pgm.c index 90f22ec2..0581249a 100644 --- a/src/language/data-io/inpt-pgm.c +++ b/src/language/data-io/inpt-pgm.c @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -44,6 +45,13 @@ #include "gettext.h" #define _(msgid) gettext (msgid) +/* Private result codes for use within INPUT PROGRAM. */ +enum cmd_result_extensions + { + CMD_END_INPUT_PROGRAM = CMD_PRIVATE_FIRST, + CMD_END_CASE + }; + /* Indicates how a `union value' should be initialized. */ enum value_init_type { @@ -56,14 +64,23 @@ enum value_init_type struct input_program_pgm { + size_t case_nr; /* Incremented by END CASE transformation. */ + write_case_func *write_case;/* Called by END CASE. */ + write_case_data wc_data; /* Aux data used by END CASE. */ + enum value_init_type *init; /* How to initialize each `union value'. */ size_t init_cnt; /* Number of elements in inp_init. */ size_t case_size; /* Size of case in bytes. */ }; -static trns_proc_func end_case_trns_proc, reread_trns_proc, end_file_trns_proc; +static void destroy_input_program (struct input_program_pgm *); +static trns_proc_func end_case_trns_proc; +static trns_proc_func reread_trns_proc; +static trns_proc_func end_file_trns_proc; static trns_free_func reread_trns_free; + static const struct case_source_class input_program_source_class; + static bool inside_input_program; /* Returns true if we're parsing the inside of a INPUT @@ -74,45 +91,67 @@ in_input_program (void) return inside_input_program; } +/* Emits an END CASE transformation for INP. */ +static void +emit_END_CASE (struct input_program_pgm *inp) +{ + add_transformation (end_case_trns_proc, NULL, inp); +} + int cmd_input_program (void) { struct input_program_pgm *inp; size_t i; + bool saw_END_CASE = false; discard_variables (); if (token != '.') return lex_end_of_command (); + inp = xmalloc (sizeof *inp); + inp->init = NULL; + inside_input_program = true; for (;;) { enum cmd_result result; lex_get (); result = cmd_parse (CMD_STATE_INPUT_PROGRAM); - if (result == CMD_END_SUBLOOP) + if (result == CMD_END_INPUT_PROGRAM) break; - if (result == CMD_EOF || result == CMD_QUIT || result == CMD_CASCADING_FAILURE) + else if (result == CMD_END_CASE) + { + emit_END_CASE (inp); + saw_END_CASE = true; + } + else if (cmd_result_is_failure (result) && result != CMD_FAILURE) { if (result == CMD_EOF) msg (SE, _("Unexpected end-of-file within INPUT PROGRAM.")); - discard_variables (); inside_input_program = false; + discard_variables (); + destroy_input_program (inp); return result; } } + if (!saw_END_CASE) + emit_END_CASE (inp); inside_input_program = false; - if (dict_get_next_value_idx (default_dict) == 0) - msg (SW, _("No data-input or transformation commands specified " - "between INPUT PROGRAM and END INPUT PROGRAM.")); - + if (dict_get_next_value_idx (default_dict) == 0) + { + msg (SE, _("Input program did not create any variables.")); + discard_variables (); + destroy_input_program (inp); + return CMD_FAILURE; + } + /* Mark the boundary between INPUT PROGRAM transformations and ordinary transformations. */ f_trns = n_trns; /* Figure out how to initialize each input case. */ - inp = xmalloc (sizeof *inp); inp->init_cnt = dict_get_next_value_idx (default_dict); inp->init = xnmalloc (inp->init_cnt, sizeof *inp->init); for (i = 0; i < inp->init_cnt; i++) @@ -143,7 +182,7 @@ int cmd_end_input_program (void) { assert (in_input_program ()); - return CMD_END_SUBLOOP; + return CMD_END_INPUT_PROGRAM; } /* Initializes case C. Called before the first case is read. */ @@ -203,45 +242,20 @@ input_program_source_read (struct case_source *source, write_case_data wc_data) { struct input_program_pgm *inp = source->aux; - size_t i; - /* Nonzero if there were any END CASE commands in the set of - transformations. If so, we don't automatically write out - cases. */ - int end_case = 0; - - /* FIXME? This is the number of cases sent out of the input - program, not the number of cases written to the procedure. - The difference should only show up in $CASENUM in COMPUTE. - We should check behavior against SPSS. */ - int cases_written = 0; - - assert (inp != NULL); - - /* Figure end_case. */ - for (i = 0; i < f_trns; i++) - if (t_trns[i].proc == end_case_trns_proc) - end_case = 1; - - init_case (inp, c); - for (;;) + inp->case_nr = 1; + inp->write_case = write_case; + inp->wc_data = wc_data; + for (init_case (inp, c); ; clear_case (inp, c)) { + int i; + /* Perform transformations on `blank' case. */ for (i = 0; i < f_trns; ) { int code; - if (t_trns[i].proc == end_case_trns_proc) - { - cases_written++; - if (!write_case (wc_data)) - return false; - clear_case (inp, c); - i++; - continue; - } - - code = t_trns[i].proc (t_trns[i].private, c, cases_written + 1); + code = t_trns[i].proc (t_trns[i].private, c, inp->case_nr); switch (code) { case TRNS_CONTINUE: @@ -249,7 +263,7 @@ input_program_source_read (struct case_source *source, break; case TRNS_DROP_CASE: - abort (); + break; case TRNS_ERROR: return false; @@ -265,18 +279,17 @@ input_program_source_read (struct case_source *source, break; } } + next_case: ; + } +} - /* Write the case if appropriate. */ - if (!end_case) - { - cases_written++; - if (!write_case (wc_data)) - return false; - } - - /* Blank out the case for the next iteration. */ - next_case: - clear_case (inp, c); +static void +destroy_input_program (struct input_program_pgm *pgm) +{ + if (pgm != NULL) + { + free (pgm->init); + free (pgm); } } @@ -286,13 +299,7 @@ input_program_source_destroy (struct case_source *source) { struct input_program_pgm *inp = source->aux; - cancel_transformations (); - - if (inp != NULL) - { - free (inp->init); - free (inp); - } + destroy_input_program (inp); } static const struct case_source_class input_program_source_class = @@ -307,18 +314,23 @@ int cmd_end_case (void) { assert (in_input_program ()); - add_transformation (end_case_trns_proc, NULL, NULL); - + if (token == '.') + return CMD_END_CASE; return lex_end_of_command (); } -/* Should never be called, because this is handled in - input_program_source_read(). */ +/* Sends the current case as the source's output. */ int -end_case_trns_proc (void *trns_ UNUSED, struct ccase *c UNUSED, - int case_num UNUSED) +end_case_trns_proc (void *inp_, struct ccase *c, int case_nr UNUSED) { - abort (); + struct input_program_pgm *inp = inp_; + + if (!inp->write_case (inp->wc_data)) + return TRNS_ERROR; + + inp->case_nr++; + clear_case (inp, c); + return TRNS_CONTINUE; } /* REREAD transformation. */ diff --git a/src/ui/terminal/main.c b/src/ui/terminal/main.c index 018ba8aa..2600a048 100644 --- a/src/ui/terminal/main.c +++ b/src/ui/terminal/main.c @@ -104,7 +104,7 @@ main (int argc, char **argv) for (;;) { int result = execute_command (); - if (result == CMD_EOF || result == CMD_QUIT) + if (result == CMD_EOF || result == CMD_FINISH) break; if (result == CMD_CASCADING_FAILURE && !getl_is_interactive ()) {