X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Flanguage%2Fdata-io%2Finpt-pgm.c;h=72d5a2e7b88e302df07e4ca54e59c206cbdebae5;hb=9ade26c8349b4434008c46cf09bc7473ec743972;hp=e000a0fd3a2b95772aec8a80371379a38b17ed0c;hpb=a9afcdd223cc1c1b7889601e405cff0bd47300d7;p=pspp-builds.git diff --git a/src/language/data-io/inpt-pgm.c b/src/language/data-io/inpt-pgm.c index e000a0fd..72d5a2e7 100644 --- a/src/language/data-io/inpt-pgm.c +++ b/src/language/data-io/inpt-pgm.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, 2011 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,32 +16,29 @@ #include -#include - #include -#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "xalloc.h" +#include "data/case.h" +#include "data/caseinit.h" +#include "data/casereader-provider.h" +#include "data/dictionary.h" +#include "data/procedure.h" +#include "data/transformations.h" +#include "data/variable.h" +#include "language/command.h" +#include "language/data-io/data-reader.h" +#include "language/data-io/file-handle.h" +#include "language/data-io/inpt-pgm.h" +#include "language/expressions/public.h" +#include "language/lexer/lexer.h" +#include "libpspp/assertion.h" +#include "libpspp/compiler.h" +#include "libpspp/message.h" +#include "libpspp/misc.h" +#include "libpspp/str.h" + +#include "gl/xalloc.h" #include "gettext.h" #define _(msgid) gettext (msgid) @@ -49,20 +46,10 @@ /* Private result codes for use within INPUT PROGRAM. */ enum cmd_result_extensions { - CMD_END_INPUT_PROGRAM = CMD_PRIVATE_FIRST, - CMD_END_CASE + CMD_END_CASE = CMD_PRIVATE_FIRST }; /* Indicates how a `union value' should be initialized. */ -enum value_init_type - { - INP_NUMERIC = 01, /* Numeric. */ - INP_STRING = 0, /* String. */ - - INP_INIT_ONCE = 02, /* Initialize only once. */ - INP_REINIT = 0, /* Reinitialize for each iteration. */ - }; - struct input_program_pgm { struct trns_chain *trns_chain; @@ -71,7 +58,7 @@ struct input_program_pgm casenumber case_nr; /* Incremented by END CASE transformation. */ struct caseinit *init; - size_t value_cnt; + struct caseproto *proto; }; static void destroy_input_program (struct input_program_pgm *); @@ -106,20 +93,21 @@ cmd_input_program (struct lexer *lexer, struct dataset *ds) bool saw_END_CASE = false; proc_discard_active_file (ds); - if (lex_token (lexer) != '.') + if (!lex_match (lexer, T_ENDCMD)) return lex_end_of_command (lexer); inp = xmalloc (sizeof *inp); inp->trns_chain = NULL; inp->init = NULL; + inp->proto = NULL; inside_input_program = true; - for (;;) + while (!lex_match_phrase (lexer, "END 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) + enum cmd_result result; + + result = cmd_parse_in_state (lexer, ds, CMD_STATE_INPUT_PROGRAM); + if (result == CMD_END_CASE) { emit_END_CASE (ds, inp); saw_END_CASE = true; @@ -154,10 +142,10 @@ cmd_input_program (struct lexer *lexer, struct dataset *ds) /* Figure out how to initialize each input case. */ inp->init = caseinit_create (); caseinit_mark_for_init (inp->init, dataset_dict (ds)); - inp->value_cnt = dict_get_next_value_idx (dataset_dict (ds)); + inp->proto = caseproto_ref (dict_get_proto (dataset_dict (ds))); proc_set_active_file_data ( - ds, casereader_create_sequential (NULL, inp->value_cnt, CASENUMBER_MAX, + ds, casereader_create_sequential (NULL, inp->proto, CASENUMBER_MAX, &input_program_casereader_class, inp)); return CMD_SUCCESS; @@ -166,8 +154,12 @@ cmd_input_program (struct lexer *lexer, struct dataset *ds) int cmd_end_input_program (struct lexer *lexer UNUSED, struct dataset *ds UNUSED) { - assert (in_input_program ()); - return CMD_END_INPUT_PROGRAM; + /* Inside INPUT PROGRAM, this should get caught at the top of the loop in + cmd_input_program(). + + Outside of INPUT PROGRAM, the command parser should reject this + command. */ + NOT_REACHED (); } /* Returns true if STATE is valid given the transformations that @@ -181,35 +173,34 @@ is_valid_state (enum trns_result state) || state >= 0); } -/* Reads one case into C. - Returns true if successful, false at end of file or if an +/* Reads and returns one case. + Returns the case if successful, null at end of file or if an I/O error occurred. */ -static bool -input_program_casereader_read (struct casereader *reader UNUSED, void *inp_, - struct ccase *c) +static struct ccase * +input_program_casereader_read (struct casereader *reader UNUSED, void *inp_) { struct input_program_pgm *inp = inp_; - - case_create (c, inp->value_cnt); + struct ccase *c = case_create (inp->proto); do { assert (is_valid_state (inp->restart)); if (inp->restart == TRNS_ERROR || inp->restart == TRNS_END_FILE) { - case_destroy (c); - return false; + case_unref (c); + return NULL; } + c = case_unshare (c); caseinit_init_vars (inp->init, c); inp->restart = trns_chain_execute (inp->trns_chain, inp->restart, - c, inp->case_nr); + &c, inp->case_nr); assert (is_valid_state (inp->restart)); caseinit_update_left_vars (inp->init, c); } while (inp->restart < 0); - return true; + return c; } static void @@ -219,6 +210,7 @@ destroy_input_program (struct input_program_pgm *pgm) { trns_chain_destroy (pgm->trns_chain); caseinit_destroy (pgm->init); + caseproto_unref (pgm->proto); free (pgm); } } @@ -245,14 +237,14 @@ int cmd_end_case (struct lexer *lexer, struct dataset *ds UNUSED) { assert (in_input_program ()); - if (lex_token (lexer) == '.') + if (lex_token (lexer) == T_ENDCMD) return CMD_END_CASE; - return lex_end_of_command (lexer); + return CMD_SUCCESS; } /* Outputs the current case */ int -end_case_trns_proc (void *inp_, struct ccase *c UNUSED, +end_case_trns_proc (void *inp_, struct ccase **c UNUSED, casenumber case_nr UNUSED) { struct input_program_pgm *inp = inp_; @@ -277,15 +269,15 @@ cmd_reread (struct lexer *lexer, struct dataset *ds) fh = fh_get_default_handle (); e = NULL; - while (lex_token (lexer) != '.') + while (lex_token (lexer) != T_ENDCMD) { if (lex_match_id (lexer, "COLUMN")) { - lex_match (lexer, '='); + lex_match (lexer, T_EQUALS); if (e) { - msg (SE, _("COLUMN subcommand multiply specified.")); + msg (SE, _("%s subcommand may be given at most once."), "COLUMN"); expr_free (e); return CMD_CASCADING_FAILURE; } @@ -296,7 +288,7 @@ cmd_reread (struct lexer *lexer, struct dataset *ds) } else if (lex_match_id (lexer, "FILE")) { - lex_match (lexer, '='); + lex_match (lexer, T_EQUALS); fh_unref (fh); fh = fh_parse (lexer, FH_REF_FILE | FH_REF_INLINE); if (fh == NULL) @@ -324,7 +316,7 @@ cmd_reread (struct lexer *lexer, struct dataset *ds) /* Executes a REREAD transformation. */ static int -reread_trns_proc (void *t_, struct ccase *c, casenumber case_num) +reread_trns_proc (void *t_, struct ccase **c, casenumber case_num) { struct reread_trns *t = t_; @@ -332,8 +324,8 @@ reread_trns_proc (void *t_, struct ccase *c, casenumber case_num) dfm_reread_record (t->reader, 1); else { - double column = expr_evaluate_num (t->column, c, case_num); - if (!gsl_finite (column) || column < 1) + double column = expr_evaluate_num (t->column, *c, case_num); + if (!isfinite (column) || column < 1) { msg (SE, _("REREAD: Column numbers must be positive finite " "numbers. Column set to 1.")); @@ -358,18 +350,18 @@ reread_trns_free (void *t_) /* Parses END FILE command. */ int -cmd_end_file (struct lexer *lexer, struct dataset *ds) +cmd_end_file (struct lexer *lexer UNUSED, struct dataset *ds) { assert (in_input_program ()); add_transformation (ds, end_file_trns_proc, NULL, NULL); - return lex_end_of_command (lexer); + return CMD_SUCCESS; } /* Executes an END FILE transformation. */ static int -end_file_trns_proc (void *trns_ UNUSED, struct ccase *c UNUSED, +end_file_trns_proc (void *trns_ UNUSED, struct ccase **c UNUSED, casenumber case_num UNUSED) { return TRNS_END_FILE;