X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdata-list.c;h=ab166f0d65585b9c876ed06333e46240240cbde0;hb=40271dcbfdecb01dfe808684741215eb2ddeb508;hp=2ed1f673fc5290d5f7c10e967c93eda2fc51aaab;hpb=2e02472cf15ddb64c33a1477cf4cfbf3be2d0c95;p=pspp diff --git a/src/data-list.c b/src/data-list.c index 2ed1f673fc..ab166f0d65 100644 --- a/src/data-list.c +++ b/src/data-list.c @@ -41,6 +41,9 @@ #include "tab.h" #include "var.h" #include "vfm.h" + +#include "gettext.h" +#define _(msgid) gettext (msgid) /* Utility function. */ @@ -80,8 +83,6 @@ enum /* DATA LIST private data structure. */ struct data_list_pgm { - struct trns_header h; - struct dls_var_spec *first, *last; /* Variable parsing specifications. */ struct dfm_reader *reader; /* Data file reader. */ @@ -267,20 +268,14 @@ cmd_data_list (void) goto error; if (vfm_source != NULL) - { - dls->h.proc = data_list_trns_proc; - dls->h.free = data_list_trns_free; - add_transformation (&dls->h); - } + add_transformation (data_list_trns_proc, data_list_trns_free, dls); else vfm_source = create_case_source (&data_list_source_class, dls); return CMD_SUCCESS; error: - destroy_dls_var_spec (dls->first); - free (dls->delims); - free (dls); + data_list_trns_free (dls); return CMD_FAILURE; } @@ -314,7 +309,7 @@ struct fmt_list struct fixed_parsing_state { char **name; /* Variable names. */ - int name_cnt; /* Number of names. */ + size_t name_cnt; /* Number of names. */ int recno; /* Index of current record. */ int sc; /* 1-based column number of starting column for @@ -334,7 +329,7 @@ static int parse_fixed (struct data_list_pgm *dls) { struct fixed_parsing_state fx; - int i; + size_t i; fx.recno = 0; fx.sc = 1; @@ -825,9 +820,9 @@ parse_free (struct dls_var_spec **first, struct dls_var_spec **last) { struct fmt_spec input, output; char **name; - int name_cnt; + size_t name_cnt; int width; - int i; + size_t i; if (!parse_DATA_LIST_vars (&name, &name_cnt, PV_NONE)) return 0; @@ -849,7 +844,7 @@ parse_free (struct dls_var_spec **first, struct dls_var_spec **last) { lex_match ('*'); input = make_input_format (FMT_F, 8, 0); - output = get_format (); + output = *get_format (); } if (input.type == FMT_A || input.type == FMT_AHEX) @@ -1230,22 +1225,22 @@ destroy_dls_var_spec (struct dls_var_spec *spec) } } -/* Destroys DATA LIST transformation PGM. */ +/* Destroys DATA LIST transformation DLS. */ static void -data_list_trns_free (struct trns_header *pgm) +data_list_trns_free (void *dls_) { - struct data_list_pgm *dls = (struct data_list_pgm *) pgm; + struct data_list_pgm *dls = dls_; free (dls->delims); destroy_dls_var_spec (dls->first); dfm_close_reader (dls->reader); + free (dls); } -/* Handle DATA LIST transformation T, parsing data into C. */ +/* Handle DATA LIST transformation DLS, parsing data into C. */ static int -data_list_trns_proc (struct trns_header *t, struct ccase *c, - int case_num UNUSED) +data_list_trns_proc (void *dls_, struct ccase *c, int case_num UNUSED) { - struct data_list_pgm *dls = (struct data_list_pgm *) t; + struct data_list_pgm *dls = dls_; data_list_read_func *read_func; int retval; @@ -1312,7 +1307,6 @@ static void data_list_source_destroy (struct case_source *source) { data_list_trns_free (source->aux); - free (source->aux); } const struct case_source_class data_list_source_class = @@ -1335,7 +1329,6 @@ struct rpd_num_or_var /* REPEATING DATA private data structure. */ struct repeating_data_trns { - struct trns_header h; struct dls_var_spec *first, *last; /* Variable parsing specifications. */ struct dfm_reader *reader; /* Input file, never NULL. */ @@ -1426,11 +1419,10 @@ cmd_repeating_data (void) if (!parse_num_or_var (&rpd->starts_end, "STARTS ending column")) goto error; } else { - /* Otherwise, rpd->starts_end is left uninitialized. - This is okay. We will initialize it later from the - record length of the file. We can't do this now - because we can't be sure that the user has specified - the file handle yet. */ + /* Otherwise, rpd->starts_end is uninitialized. We + will initialize it later from the record length + of the file. We can't do so now because the + file handle may not be specified yet. */ } if (rpd->starts_beg.num != 0 && rpd->starts_end.num != 0 @@ -1450,7 +1442,7 @@ cmd_repeating_data (void) msg (SE, _("%s subcommand given multiple times."),"OCCURS"); goto error; } - saw_occurs |= 2; + saw_occurs = true; if (!parse_num_or_var (&rpd->occurs, "OCCURS")) goto error; @@ -1458,12 +1450,12 @@ cmd_repeating_data (void) else if (lex_match_id ("LENGTH")) { lex_match ('='); - if (saw_length & 4) + if (saw_length) { msg (SE, _("%s subcommand given multiple times."),"LENGTH"); goto error; } - saw_length |= 4; + saw_length = true; if (!parse_num_or_var (&rpd->length, "LENGTH")) goto error; @@ -1471,16 +1463,17 @@ cmd_repeating_data (void) else if (lex_match_id ("CONTINUED")) { lex_match ('='); - if (saw_continued & 8) + if (saw_continued) { msg (SE, _("%s subcommand given multiple times."),"CONTINUED"); goto error; } - saw_continued |= 8; + saw_continued = true; if (!lex_match ('/')) { - if (!parse_num_or_var (&rpd->cont_beg, "CONTINUED beginning column")) + if (!parse_num_or_var (&rpd->cont_beg, + "CONTINUED beginning column")) goto error; lex_negative_to_dash (); @@ -1504,12 +1497,12 @@ cmd_repeating_data (void) else if (lex_match_id ("ID")) { lex_match ('='); - if (saw_id & 16) + if (saw_id) { msg (SE, _("%s subcommand given multiple times."),"ID"); goto error; } - saw_id |= 16; + saw_id = true; if (!lex_force_int ()) goto error; @@ -1554,7 +1547,7 @@ cmd_repeating_data (void) goto error; find_variable_input_spec (rpd->id_var, &rpd->id_spec); - rpd->id_value = xmalloc (sizeof *rpd->id_value * rpd->id_var->nv); + rpd->id_value = xnmalloc (rpd->id_var->nv, sizeof *rpd->id_value); } else if (lex_match_id ("TABLE")) table = 1; @@ -1589,13 +1582,32 @@ cmd_repeating_data (void) goto error; } - /* Calculate starts_end, cont_end if necessary and possible. */ - if (fh != NULL) + /* Calculate and check starts_end, cont_end if necessary. */ + if (rpd->starts_end.num == 0 && rpd->starts_end.var == NULL) { - if (rpd->starts_end.num == 0 && rpd->starts_end.var == NULL) - rpd->starts_end.num = handle_get_record_width (fh); - if (rpd->cont_end.num == 0 && rpd->cont_end.var == NULL) - rpd->cont_end.num = handle_get_record_width (fh); + rpd->starts_end.num = fh != NULL ? handle_get_record_width (fh) : 80; + if (rpd->starts_beg.num != 0 + && rpd->starts_beg.num > rpd->starts_end.num) + { + msg (SE, _("STARTS beginning column (%d) exceeds " + "default STARTS ending column taken from file's " + "record width (%d)."), + rpd->starts_beg.num, rpd->starts_end.num); + goto error; + } + } + if (rpd->cont_end.num == 0 && rpd->cont_end.var == NULL) + { + rpd->cont_end.num = fh != NULL ? handle_get_record_width (fh) : 80; + if (rpd->cont_beg.num != 0 + && rpd->cont_beg.num > rpd->cont_end.num) + { + msg (SE, _("CONTINUED beginning column (%d) exceeds " + "default CONTINUED ending column taken from file's " + "record width (%d)."), + rpd->cont_beg.num, rpd->cont_end.num); + goto error; + } } lex_match ('='); @@ -1616,15 +1628,12 @@ cmd_repeating_data (void) if (table) dump_fixed_table (rpd->first, fh, rpd->last->rec); - rpd->h.proc = repeating_data_trns_proc; - rpd->h.free = repeating_data_trns_free; - add_transformation (&rpd->h); + add_transformation (repeating_data_trns_proc, repeating_data_trns_free, rpd); return lex_end_of_command (); error: - destroy_dls_var_spec (rpd->first); - free (rpd->id_value); + repeating_data_trns_free (rpd); return CMD_FAILURE; } @@ -1634,14 +1643,15 @@ cmd_repeating_data (void) static void find_variable_input_spec (struct variable *v, struct fmt_spec *spec) { - int i; + size_t i; for (i = 0; i < n_trns; i++) { - struct data_list_pgm *pgm = (struct data_list_pgm *) t_trns[i]; + struct transformation *trns = &t_trns[i]; - if (pgm->h.proc == data_list_trns_proc) + if (trns->proc == data_list_trns_proc) { + struct data_list_pgm *pgm = trns->private; struct dls_var_spec *iter; for (iter = pgm->first; iter; iter = iter->next) @@ -1700,7 +1710,7 @@ static int parse_repeating_data (struct dls_var_spec **first, struct dls_var_spec **last) { struct fixed_parsing_state fx; - int i; + size_t i; fx.recno = 0; fx.sc = 1; @@ -1744,23 +1754,17 @@ parse_repeating_data (struct dls_var_spec **first, struct dls_var_spec **last) /* Obtains the real value for rpd_num_or_var N in case C and returns it. The valid range is nonnegative numbers, but numbers outside this range can be returned and should be handled by the caller as - invalid. If N does not have a value, returns DEFAULT_VALUE, - which must be nonzero if this is possible. */ + invalid. */ static int -realize_value (struct rpd_num_or_var *n, struct ccase *c, int default_value) +realize_value (struct rpd_num_or_var *n, struct ccase *c) { - if (n->num != 0) - return n->num; - else if (n->var != NULL) + if (n->var != NULL) { double v = case_num (c, n->var->fv); return v != SYSMIS && v >= INT_MIN && v <= INT_MAX ? v : -1; } - else - { - assert (default_value != 0); - return default_value; - } + else + return n->num; } /* Parameter record passed to rpd_parse_record(). */ @@ -1884,10 +1888,9 @@ rpd_parse_record (const struct rpd_parse_info *info) DATA structure. Returns -1 on success, -2 on end of file or on failure. */ int -repeating_data_trns_proc (struct trns_header *trns, struct ccase *c, - int case_num UNUSED) +repeating_data_trns_proc (void *trns_, struct ccase *c, int case_num UNUSED) { - struct repeating_data_trns *t = (struct repeating_data_trns *) trns; + struct repeating_data_trns *t = trns_; struct fixed_string line; /* Current record. */ @@ -1915,13 +1918,13 @@ repeating_data_trns_proc (struct trns_header *trns, struct ccase *c, dfm_forward_record (t->reader); /* Calculate occurs, length. */ - occurs_left = occurs = realize_value (&t->occurs, c, 0); + occurs_left = occurs = realize_value (&t->occurs, c); if (occurs <= 0) { tmsg (SE, RPD_ERR, _("Invalid value %d for OCCURS."), occurs); return -3; } - starts_beg = realize_value (&t->starts_beg, c, 0); + starts_beg = realize_value (&t->starts_beg, c); if (starts_beg <= 0) { tmsg (SE, RPD_ERR, _("Beginning column for STARTS (%d) must be " @@ -1929,7 +1932,7 @@ repeating_data_trns_proc (struct trns_header *trns, struct ccase *c, starts_beg); return -3; } - starts_end = realize_value (&t->starts_end, c, line.length + 1); + starts_end = realize_value (&t->starts_end, c); if (starts_end < starts_beg) { tmsg (SE, RPD_ERR, _("Ending column for STARTS (%d) is less than " @@ -1937,14 +1940,14 @@ repeating_data_trns_proc (struct trns_header *trns, struct ccase *c, starts_end, starts_beg); skip_first_record = 1; } - length = realize_value (&t->length, c, 0); + length = realize_value (&t->length, c); if (length < 0) { tmsg (SE, RPD_ERR, _("Invalid value %d for LENGTH."), length); length = 1; occurs = occurs_left = 1; } - cont_beg = realize_value (&t->cont_beg, c, 0); + cont_beg = realize_value (&t->cont_beg, c); if (cont_beg < 0) { tmsg (SE, RPD_ERR, _("Beginning column for CONTINUED (%d) must be " @@ -1952,7 +1955,7 @@ repeating_data_trns_proc (struct trns_header *trns, struct ccase *c, cont_beg); return -2; } - cont_end = realize_value (&t->cont_end, c, line.length + 1); + cont_end = realize_value (&t->cont_end, c); if (cont_end < cont_beg) { tmsg (SE, RPD_ERR, _("Ending column for CONTINUED (%d) is less than " @@ -2039,25 +2042,26 @@ repeating_data_trns_proc (struct trns_header *trns, struct ccase *c, /* Frees a REPEATING DATA transformation. */ void -repeating_data_trns_free (struct trns_header *rpd_) +repeating_data_trns_free (void *rpd_) { - struct repeating_data_trns *rpd = (struct repeating_data_trns *) rpd_; + struct repeating_data_trns *rpd = rpd_; destroy_dls_var_spec (rpd->first); dfm_close_reader (rpd->reader); free (rpd->id_value); + free (rpd); } /* Lets repeating_data_trns_proc() know how to write the cases that it composes. Not elegant. */ void -repeating_data_set_write_case (struct trns_header *trns, +repeating_data_set_write_case (struct transformation *trns_, write_case_func *write_case, write_case_data wc_data) { - struct repeating_data_trns *t = (struct repeating_data_trns *) trns; + struct repeating_data_trns *t = trns_->private; - assert (trns->proc == repeating_data_trns_proc); + assert (trns_->proc == repeating_data_trns_proc); t->write_case = write_case; t->wc_data = wc_data; }