X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Flanguage%2Fdata-io%2Finpt-pgm.c;h=71860ebfaee9bd67f618d43e94471c91e62af4ed;hb=9aac12c2130257396c9ee4ee7860f618dcb202b0;hp=24a2e22968f1eccc0a3a23f9f0275f898470c228;hpb=888d0f91d57e0c3c5a4206c30ac71eb87bf44227;p=pspp-builds.git diff --git a/src/language/data-io/inpt-pgm.c b/src/language/data-io/inpt-pgm.c index 24a2e229..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 @@ -67,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. */ @@ -120,7 +119,7 @@ cmd_input_program (struct lexer *lexer, struct dataset *ds) inside_input_program = true; for (;;) { - enum cmd_result result = cmd_parse (lexer, ds, 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) @@ -153,6 +152,10 @@ cmd_input_program (struct lexer *lexer, struct dataset *ds) 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 (dataset_dict (ds)); inp->init = xnmalloc (inp->init_cnt, sizeof *inp->init); @@ -169,14 +172,14 @@ cmd_input_program (struct lexer *lexer, struct dataset *ds) value_init |= var_get_leave (var) ? INP_INIT_ONCE : INP_REINIT; for (j = 0; j < value_cnt; j++) - inp->init[j + var->fv] = value_init; + 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 (dataset_dict (ds)); proc_set_source (ds, - create_case_source (&input_program_source_class, inp)); + create_case_source (&input_program_source_class, inp)); return CMD_SUCCESS; } @@ -198,14 +201,15 @@ 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: NOT_REACHED (); @@ -224,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: 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 @@ -271,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 = @@ -299,16 +324,12 @@ cmd_end_case (struct lexer *lexer, struct dataset *ds UNUSED) /* Sends the current case as the source's output. */ int -end_case_trns_proc (void *inp_, struct ccase *c, casenumber 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. */