X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=src%2Flanguage%2Fdata-io%2Finpt-pgm.c;h=71860ebfaee9bd67f618d43e94471c91e62af4ed;hb=9491a8bd354152d3a228e1bf041c7ad6228750d7;hp=fbf1d3422d940c0667dda3f295cd3d6d690ef895;hpb=b0bf9b1b0f727fafac4296a048e3f45db5936f81;p=pspp-builds.git diff --git a/src/language/data-io/inpt-pgm.c b/src/language/data-io/inpt-pgm.c index fbf1d342..71860ebf 100644 --- a/src/language/data-io/inpt-pgm.c +++ b/src/language/data-io/inpt-pgm.c @@ -1,6 +1,5 @@ /* PSPP - computes sample statistics. Copyright (C) 1997-9, 2000 Free Software Foundation, Inc. - Written by Ben Pfaff . This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -28,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -36,12 +36,12 @@ #include #include #include +#include #include #include #include #include #include -#include #include "gettext.h" #define _(msgid) gettext (msgid) @@ -66,10 +66,10 @@ enum value_init_type struct input_program_pgm { struct trns_chain *trns_chain; + enum trns_result restart; + bool inited_case; /* Did one-time case initialization? */ 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. */ @@ -96,21 +96,21 @@ in_input_program (void) /* Emits an END CASE transformation for INP. */ static void -emit_END_CASE (struct input_program_pgm *inp) +emit_END_CASE (struct dataset *ds, struct input_program_pgm *inp) { - add_transformation (end_case_trns_proc, NULL, inp); + add_transformation (ds, end_case_trns_proc, NULL, inp); } int -cmd_input_program (void) +cmd_input_program (struct lexer *lexer, struct dataset *ds) { struct input_program_pgm *inp; size_t i; bool saw_END_CASE = false; - discard_variables (); - if (token != '.') - return lex_end_of_command (); + discard_variables (ds); + if (lex_token (lexer) != '.') + return lex_end_of_command (lexer); inp = xmalloc (sizeof *inp); inp->trns_chain = NULL; @@ -119,14 +119,12 @@ cmd_input_program (void) inside_input_program = true; for (;;) { - enum cmd_result result; - lex_get (); - result = cmd_parse (CMD_STATE_INPUT_PROGRAM); + enum cmd_result result = cmd_parse_in_state (lexer, ds, CMD_STATE_INPUT_PROGRAM); if (result == CMD_END_INPUT_PROGRAM) break; else if (result == CMD_END_CASE) { - emit_END_CASE (inp); + emit_END_CASE (ds, inp); saw_END_CASE = true; } else if (cmd_result_is_failure (result) && result != CMD_FAILURE) @@ -134,54 +132,60 @@ cmd_input_program (void) if (result == CMD_EOF) msg (SE, _("Unexpected end-of-file within INPUT PROGRAM.")); inside_input_program = false; - discard_variables (); + discard_variables (ds); destroy_input_program (inp); return result; } } if (!saw_END_CASE) - emit_END_CASE (inp); + emit_END_CASE (ds, inp); inside_input_program = false; - if (dict_get_next_value_idx (default_dict) == 0) + if (dict_get_next_value_idx (dataset_dict (ds)) == 0) { msg (SE, _("Input program did not create any variables.")); - discard_variables (); + discard_variables (ds); destroy_input_program (inp); return CMD_FAILURE; } - inp->trns_chain = proc_capture_transformations (); + inp->trns_chain = proc_capture_transformations (ds); trns_chain_finalize (inp->trns_chain); + inp->restart = TRNS_CONTINUE; + inp->inited_case = false; + inp->case_nr = 1; + /* Figure out how to initialize each input case. */ - inp->init_cnt = dict_get_next_value_idx (default_dict); + inp->init_cnt = dict_get_next_value_idx (dataset_dict (ds)); inp->init = xnmalloc (inp->init_cnt, sizeof *inp->init); for (i = 0; i < inp->init_cnt; i++) inp->init[i] = -1; - for (i = 0; i < dict_get_var_cnt (default_dict); i++) + for (i = 0; i < dict_get_var_cnt (dataset_dict (ds)); i++) { - struct variable *var = dict_get_var (default_dict, i); + struct variable *var = dict_get_var (dataset_dict (ds), i); + size_t value_cnt = var_get_value_cnt (var); enum value_init_type value_init; size_t j; - value_init = var->type == NUMERIC ? INP_NUMERIC : INP_STRING; - value_init |= var->leave ? INP_INIT_ONCE : INP_REINIT; + value_init = var_is_numeric (var) ? INP_NUMERIC : INP_STRING; + value_init |= var_get_leave (var) ? INP_INIT_ONCE : INP_REINIT; - for (j = 0; j < var->nv; j++) - inp->init[j + var->fv] = value_init; + for (j = 0; j < value_cnt; j++) + inp->init[j + var_get_case_index (var)] = value_init; } for (i = 0; i < inp->init_cnt; i++) assert (inp->init[i] != -1); - inp->case_size = dict_get_case_size (default_dict); + inp->case_size = dict_get_case_size (dataset_dict (ds)); - proc_set_source (create_case_source (&input_program_source_class, inp)); + proc_set_source (ds, + create_case_source (&input_program_source_class, inp)); return CMD_SUCCESS; } int -cmd_end_input_program (void) +cmd_end_input_program (struct lexer *lexer UNUSED, struct dataset *ds UNUSED) { assert (in_input_program ()); return CMD_END_INPUT_PROGRAM; @@ -197,17 +201,18 @@ init_case (const struct input_program_pgm *inp, struct ccase *c) switch (inp->init[i]) { case INP_NUMERIC | INP_INIT_ONCE: - case_data_rw (c, i)->f = 0.0; + case_data_rw_idx (c, i)->f = 0.0; break; case INP_NUMERIC | INP_REINIT: - case_data_rw (c, i)->f = SYSMIS; + case_data_rw_idx (c, i)->f = SYSMIS; break; case INP_STRING | INP_INIT_ONCE: case INP_STRING | INP_REINIT: - memset (case_data_rw (c, i)->s, ' ', sizeof case_data_rw (c, i)->s); + memset (case_data_rw_idx (c, i)->s, ' ', + sizeof case_data_rw_idx (c, i)->s); break; default: - assert (0); + NOT_REACHED (); } } @@ -223,40 +228,58 @@ clear_case (const struct input_program_pgm *inp, struct ccase *c) case INP_NUMERIC | INP_INIT_ONCE: break; case INP_NUMERIC | INP_REINIT: - case_data_rw (c, i)->f = SYSMIS; + case_data_rw_idx (c, i)->f = SYSMIS; break; case INP_STRING | INP_INIT_ONCE: break; case INP_STRING | INP_REINIT: - memset (case_data_rw (c, i)->s, ' ', sizeof case_data_rw (c, i)->s); + memset (case_data_rw_idx (c, i)->s, ' ', + sizeof case_data_rw_idx (c, i)->s); break; default: - assert (0); + NOT_REACHED (); } } -/* Executes each transformation in turn on a `blank' case. - Returns true if successful, false if an I/O error occurred. */ +/* Returns true if STATE is valid given the transformations that + are allowed within INPUT PROGRAM. */ +static bool +is_valid_state (enum trns_result state) +{ + return (state == TRNS_CONTINUE + || state == TRNS_ERROR + || state == TRNS_END_FILE + || state >= 0); +} + +/* Reads one case into C. + Returns true if successful, false at end of file or if an + I/O error occurred. */ static bool -input_program_source_read (struct case_source *source, - struct ccase *c, - write_case_func *write_case, - write_case_data wc_data) +input_program_source_read (struct case_source *source, struct ccase *c) { struct input_program_pgm *inp = source->aux; - inp->case_nr = 1; - inp->write_case = write_case; - inp->wc_data = wc_data; - for (init_case (inp, c); ; clear_case (inp, c)) + if (!inp->inited_case) + { + init_case (inp, c); + inp->inited_case = true; + } + + do { - enum trns_result result = trns_chain_execute (inp->trns_chain, c, - &inp->case_nr); - if (result == TRNS_ERROR) + assert (is_valid_state (inp->restart)); + if (inp->restart == TRNS_ERROR || inp->restart == TRNS_END_FILE) return false; - else if (result == TRNS_END_FILE) - return true; + + clear_case (inp, c); + inp->restart = trns_chain_execute (inp->trns_chain, inp->restart, + c, &inp->case_nr); + assert (is_valid_state (inp->restart)); } + while (inp->restart < 0); + + return true; } static void @@ -270,13 +293,16 @@ destroy_input_program (struct input_program_pgm *pgm) } } -/* Destroys an INPUT PROGRAM source. */ -static void +/* Destroys the source. + Returns true if successful read, false if an I/O occurred + during destruction or previously. */ +static bool input_program_source_destroy (struct case_source *source) { struct input_program_pgm *inp = source->aux; - + bool ok = inp->restart != TRNS_ERROR; destroy_input_program (inp); + return ok; } static const struct case_source_class input_program_source_class = @@ -288,26 +314,22 @@ static const struct case_source_class input_program_source_class = }; int -cmd_end_case (void) +cmd_end_case (struct lexer *lexer, struct dataset *ds UNUSED) { assert (in_input_program ()); - if (token == '.') + if (lex_token (lexer) == '.') return CMD_END_CASE; - return lex_end_of_command (); + return lex_end_of_command (lexer); } /* Sends the current case as the source's output. */ int -end_case_trns_proc (void *inp_, struct ccase *c, int case_nr UNUSED) +end_case_trns_proc (void *inp_, struct ccase *c UNUSED, + casenumber case_nr UNUSED) { 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; + return TRNS_END_CASE; } /* REREAD transformation. */ @@ -319,7 +341,7 @@ struct reread_trns /* Parses REREAD command. */ int -cmd_reread (void) +cmd_reread (struct lexer *lexer, struct dataset *ds) { struct file_handle *fh; /* File to be re-read. */ struct expression *e; /* Expression for column to set. */ @@ -327,11 +349,11 @@ cmd_reread (void) fh = fh_get_default_handle (); e = NULL; - while (token != '.') + while (lex_token (lexer) != '.') { - if (lex_match_id ("COLUMN")) + if (lex_match_id (lexer, "COLUMN")) { - lex_match ('='); + lex_match (lexer, '='); if (e) { @@ -340,39 +362,39 @@ cmd_reread (void) return CMD_CASCADING_FAILURE; } - e = expr_parse (default_dict, EXPR_NUMBER); + e = expr_parse (lexer, ds, EXPR_NUMBER); if (!e) return CMD_CASCADING_FAILURE; } - else if (lex_match_id ("FILE")) + else if (lex_match_id (lexer, "FILE")) { - lex_match ('='); - fh = fh_parse (FH_REF_FILE | FH_REF_INLINE); + lex_match (lexer, '='); + fh = fh_parse (lexer, FH_REF_FILE | FH_REF_INLINE); if (fh == NULL) { expr_free (e); return CMD_CASCADING_FAILURE; } - lex_get (); } else { - lex_error (NULL); + lex_error (lexer, NULL); expr_free (e); + return CMD_CASCADING_FAILURE; } } t = xmalloc (sizeof *t); - t->reader = dfm_open_reader (fh); + t->reader = dfm_open_reader (fh, lexer); t->column = e; - add_transformation (reread_trns_proc, reread_trns_free, t); + add_transformation (ds, reread_trns_proc, reread_trns_free, t); return CMD_SUCCESS; } /* Executes a REREAD transformation. */ static int -reread_trns_proc (void *t_, struct ccase *c, int case_num) +reread_trns_proc (void *t_, struct ccase *c, casenumber case_num) { struct reread_trns *t = t_; @@ -406,19 +428,19 @@ reread_trns_free (void *t_) /* Parses END FILE command. */ int -cmd_end_file (void) +cmd_end_file (struct lexer *lexer, struct dataset *ds) { assert (in_input_program ()); - add_transformation (end_file_trns_proc, NULL, NULL); + add_transformation (ds, end_file_trns_proc, NULL, NULL); - return lex_end_of_command (); + return lex_end_of_command (lexer); } /* Executes an END FILE transformation. */ static int end_file_trns_proc (void *trns_ UNUSED, struct ccase *c UNUSED, - int case_num UNUSED) + casenumber case_num UNUSED) { return TRNS_END_FILE; }