X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=src%2Fdata-list.c;h=eb491d1d9dd72e0f50c19300b50a142e4550bc74;hb=e32e05bf60402d3229e45adcc9b4c8d5bb27d174;hp=c9203122134f87eac200e04b6fc984520c5486ec;hpb=92bfefccd465052e492f669ce561aa25b0110283;p=pspp-builds.git diff --git a/src/data-list.c b/src/data-list.c index c9203122..eb491d1d 100644 --- a/src/data-list.c +++ b/src/data-list.c @@ -25,10 +25,12 @@ #include #include #include "alloc.h" +#include "case.h" #include "command.h" #include "data-in.h" #include "debug-print.h" -#include "dfm.h" +#include "dfm-read.h" +#include "dictionary.h" #include "error.h" #include "file-handle.h" #include "format.h" @@ -81,12 +83,12 @@ struct data_list_pgm struct trns_header h; struct dls_var_spec *first, *last; /* Variable parsing specifications. */ - struct file_handle *handle; /* Input file, never NULL. */ + struct dfm_reader *reader; /* Data file reader. */ int type; /* A DLS_* constant. */ struct variable *end; /* Variable specified on END subcommand. */ int eof; /* End of file encountered. */ - int nrec; /* Number of records. */ + int rec_cnt; /* Number of records. */ size_t case_size; /* Case size in bytes. */ char *delims; /* Delimiters if any; not null-terminated. */ size_t delim_cnt; /* Number of delimiter, or 0 for spaces. */ @@ -94,9 +96,10 @@ struct data_list_pgm static int parse_fixed (struct data_list_pgm *); static int parse_free (struct dls_var_spec **, struct dls_var_spec **); -static void dump_fixed_table (const struct dls_var_spec *specs, - const struct file_handle *handle, int nrec); -static void dump_free_table (const struct data_list_pgm *); +static void dump_fixed_table (const struct dls_var_spec *, + const struct file_handle *, int rec_cnt); +static void dump_free_table (const struct data_list_pgm *, + const struct file_handle *); static void destroy_dls_var_spec (struct dls_var_spec *); static trns_free_func data_list_trns_free; static trns_proc_func data_list_trns_proc; @@ -107,21 +110,19 @@ static trns_proc_func data_list_trns_proc; int cmd_data_list (void) { - /* DATA LIST program under construction. */ - struct data_list_pgm *dls; - - /* 0=print no table, 1=print table. (TABLE subcommand.) */ - int table = -1; + struct data_list_pgm *dls; /* DATA LIST program under construction. */ + int table = -1; /* Print table if nonzero, -1=undecided. */ + struct file_handle *fh = NULL; /* File handle of source, NULL=inline file. */ if (!case_source_is_complex (vfm_source)) discard_variables (); dls = xmalloc (sizeof *dls); - dls->handle = default_handle; + dls->reader = NULL; dls->type = -1; dls->end = NULL; dls->eof = 0; - dls->nrec = 0; + dls->rec_cnt = 0; dls->delims = NULL; dls->delim_cnt = 0; dls->first = dls->last = NULL; @@ -131,11 +132,11 @@ cmd_data_list (void) if (lex_match_id ("FILE")) { lex_match ('='); - dls->handle = fh_parse_file_handle (); - if (!dls->handle) + fh = fh_parse (); + if (fh == NULL) goto error; if (case_source_is_class (vfm_source, &file_type_source_class) - && dls->handle != default_handle) + && fh != default_handle) { msg (SE, _("DATA LIST may not use a different file from " "that specified on its surrounding FILE TYPE.")); @@ -148,7 +149,7 @@ cmd_data_list (void) lex_match ('('); if (!lex_force_int ()) goto error; - dls->nrec = lex_integer (); + dls->rec_cnt = lex_integer (); lex_get (); lex_match (')'); } @@ -207,7 +208,10 @@ cmd_data_list (void) if (lex_match_id ("TAB")) delim = '\t'; else if (token == T_STRING && tokstr.length == 1) - delim = tokstr.string[0]; + { + delim = tokstr.string[0]; + lex_get(); + } else { lex_error (NULL); @@ -230,7 +234,7 @@ cmd_data_list (void) } dls->case_size = dict_get_case_size (default_dict); - default_handle = dls->handle; + default_handle = fh; if (dls->type == -1) dls->type = DLS_FIXED; @@ -248,17 +252,18 @@ cmd_data_list (void) if (!parse_fixed (dls)) goto error; if (table) - dump_fixed_table (dls->first, dls->handle, dls->nrec); + dump_fixed_table (dls->first, fh, dls->rec_cnt); } else { if (!parse_free (&dls->first, &dls->last)) goto error; if (table) - dump_free_table (dls); + dump_free_table (dls, fh); } - if (!dfm_open_for_reading (dls->handle)) + dls->reader = dfm_open_reader (fh); + if (dls->reader == NULL) goto error; if (vfm_source != NULL) @@ -280,6 +285,7 @@ cmd_data_list (void) error: destroy_dls_var_spec (dls->first); + free (dls->delims); free (dls); return CMD_FAILURE; } @@ -391,14 +397,14 @@ parse_fixed (struct data_list_pgm *dls) msg (SE, _("At least one variable must be specified.")); return 0; } - if (dls->nrec && dls->last->rec > dls->nrec) + if (dls->rec_cnt && dls->last->rec > dls->rec_cnt) { msg (SE, _("Variables are specified on records that " "should not exist according to RECORDS subcommand.")); return 0; } - else if (!dls->nrec) - dls->nrec = dls->last->rec; + else if (!dls->rec_cnt) + dls->rec_cnt = dls->last->rec; if (token != '.') { lex_error (_("expecting end of command")); @@ -529,7 +535,7 @@ fixed_parse_compatible (struct fixed_parsing_state *fx, input.type = FMT_F; input.d = 0; } - if (!check_input_specifier (&input)) + if (!check_input_specifier (&input, 1)) return 0; /* Start column for next specification. */ @@ -725,8 +731,8 @@ fixed_parse_fortran_internal (struct fixed_parsing_state *fx, } else if (lex_match ('/')) new->f.type = FMT_NEWREC; - else if (!parse_format_specifier (&new->f, 1) - || !check_input_specifier (&new->f)) + else if (!parse_format_specifier (&new->f, FMTP_ALLOW_XT) + || !check_input_specifier (&new->f, 1)) goto fail; lex_match (','); @@ -776,12 +782,10 @@ fixed_parse_fortran (struct fixed_parsing_state *fx, ending column. */ static void dump_fixed_table (const struct dls_var_spec *specs, - const struct file_handle *handle, int nrec) + const struct file_handle *fh, int rec_cnt) { const struct dls_var_spec *spec; struct tab_table *t; - char *buf; - const char *filename; int i; for (i = 0, spec = specs; spec; spec = spec->next) @@ -807,21 +811,16 @@ dump_fixed_table (const struct dls_var_spec *specs, fmt_to_string (&spec->input)); } - filename = handle_get_filename (handle); - if (filename == NULL) - filename = ""; - buf = local_alloc (strlen (filename) + INT_DIGITS + 80); - sprintf (buf, (handle != inline_file - ? ngettext ("Reading %d record from file %s.", - "Reading %d records from file %s.", nrec) - : ngettext ("Reading %d record from the command file.", - "Reading %d records from the command file.", - nrec)), - nrec, filename); - - tab_title (t, 0, buf); + if (fh != NULL) + tab_title (t, 1, ngettext ("Reading %d record from file %s.", + "Reading %d records from file %s.", rec_cnt), + rec_cnt, handle_get_filename (fh)); + else + tab_title (t, 1, ngettext ("Reading %d record from the command file.", + "Reading %d records from the command file.", + rec_cnt), + rec_cnt); tab_submit (t); - local_free (buf); } /* Free-format parsing. */ @@ -846,7 +845,7 @@ parse_free (struct dls_var_spec **first, struct dls_var_spec **last) if (lex_match ('(')) { if (!parse_format_specifier (&input, 0) - || !check_input_specifier (&input) + || !check_input_specifier (&input, 1) || !lex_force_match (')')) { for (i = 0; i < name_cnt; i++) @@ -905,7 +904,8 @@ parse_free (struct dls_var_spec **first, struct dls_var_spec **last) /* Displays a table giving information on free-format variable parsing on DATA LIST. */ static void -dump_free_table (const struct data_list_pgm *dls) +dump_free_table (const struct data_list_pgm *dls, + const struct file_handle *fh) { struct tab_table *t; int i; @@ -934,19 +934,12 @@ dump_free_table (const struct data_list_pgm *dls) tab_text (t, 1, i, TAB_LEFT | TAT_FIX, fmt_to_string (&spec->input)); } } - - { - const char *filename; - - filename = handle_get_filename (dls->handle); - if (filename == NULL) - filename = ""; - tab_title (t, 1, - (dls->handle != inline_file - ? _("Reading free-form data from file %s.") - : _("Reading free-form data from the command file.")), - filename); - } + + if (fh != NULL) + tab_title (t, 1, _("Reading free-form data from file %s."), + handle_get_filename (fh)); + else + tab_title (t, 1, _("Reading free-form data from the command file.")); tab_submit (t); } @@ -963,18 +956,18 @@ dump_free_table (const struct data_list_pgm *dls) a 1-based column number indicating the beginning of the field on success. */ static int -cut_field (const struct data_list_pgm *dls, struct len_string *field, +cut_field (const struct data_list_pgm *dls, struct fixed_string *field, int *end_blank) { - struct len_string line; + struct fixed_string line; char *cp; size_t column_start; - if (dfm_eof (dls->handle)) + if (dfm_eof (dls->reader)) return 0; if (dls->delim_cnt == 0) - dfm_expand_tabs (dls->handle); - dfm_get_record (dls->handle, &line); + dfm_expand_tabs (dls->reader); + dfm_get_record (dls->reader, &line); cp = ls_c_str (&line); if (dls->delim_cnt == 0) @@ -1018,7 +1011,7 @@ cut_field (const struct data_list_pgm *dls, struct len_string *field, { if (cp >= ls_end (&line)) { - int column = dfm_column_start (dls->handle); + int column = dfm_column_start (dls->reader); /* A blank line or a line that ends in \t has a trailing blank field. */ if (column == 1 || (column > 1 && cp[-1] == '\t')) @@ -1028,7 +1021,7 @@ cut_field (const struct data_list_pgm *dls, struct len_string *field, *end_blank = 1; field->string = ls_end (&line); field->length = 0; - dfm_forward_record (dls->handle); + dfm_forward_record (dls->reader); return column; } else @@ -1052,10 +1045,10 @@ cut_field (const struct data_list_pgm *dls, struct len_string *field, } } - dfm_forward_columns (dls->handle, field->string - line.string); - column_start = dfm_column_start (dls->handle); + dfm_forward_columns (dls->reader, field->string - line.string); + column_start = dfm_column_start (dls->reader); - dfm_forward_columns (dls->handle, cp - field->string); + dfm_forward_columns (dls->reader, cp - field->string); return column_start; } @@ -1097,21 +1090,21 @@ read_from_data_list_fixed (const struct data_list_pgm *dls, struct dls_var_spec *var_spec = dls->first; int i; - if (dfm_eof (dls->handle)) + if (dfm_eof (dls->reader)) return -2; - for (i = 1; i <= dls->nrec; i++) + for (i = 1; i <= dls->rec_cnt; i++) { - struct len_string line; + struct fixed_string line; - if (dfm_eof (dls->handle)) + if (dfm_eof (dls->reader)) { /* Note that this can't occur on the first record. */ msg (SW, _("Partial case of %d of %d records discarded."), - i - 1, dls->nrec); + i - 1, dls->rec_cnt); return -2; } - dfm_expand_tabs (dls->handle); - dfm_get_record (dls->handle, &line); + dfm_expand_tabs (dls->reader); + dfm_get_record (dls->reader, &line); for (; var_spec && i == var_spec->rec; var_spec = var_spec->next) { @@ -1119,7 +1112,7 @@ read_from_data_list_fixed (const struct data_list_pgm *dls, data_in_finite_line (&di, ls_c_str (&line), ls_length (&line), var_spec->fc, var_spec->lc); - di.v = &c->data[var_spec->fv]; + di.v = case_data_rw (c, var_spec->fv); di.flags = 0; di.f1 = var_spec->fc; di.format = var_spec->input; @@ -1127,7 +1120,7 @@ read_from_data_list_fixed (const struct data_list_pgm *dls, data_in (&di); } - dfm_forward_record (dls->handle); + dfm_forward_record (dls->reader); } return -1; @@ -1145,7 +1138,7 @@ read_from_data_list_free (const struct data_list_pgm *dls, for (var_spec = dls->first; var_spec; var_spec = var_spec->next) { - struct len_string field; + struct fixed_string field; int column; /* Cut out a field and read in a new record if necessary. */ @@ -1155,9 +1148,9 @@ read_from_data_list_free (const struct data_list_pgm *dls, if (column != 0) break; - if (!dfm_eof (dls->handle)) - dfm_forward_record (dls->handle); - if (dfm_eof (dls->handle)) + if (!dfm_eof (dls->reader)) + dfm_forward_record (dls->reader); + if (dfm_eof (dls->reader)) { if (var_spec != dls->first) msg (SW, _("Partial case discarded. The first variable " @@ -1171,7 +1164,7 @@ read_from_data_list_free (const struct data_list_pgm *dls, di.s = ls_c_str (&field); di.e = ls_end (&field); - di.v = &c->data[var_spec->fv]; + di.v = case_data_rw (c, var_spec->fv); di.flags = 0; di.f1 = column; di.format = var_spec->input; @@ -1191,12 +1184,12 @@ read_from_data_list_list (const struct data_list_pgm *dls, struct dls_var_spec *var_spec; int end_blank = 0; - if (dfm_eof (dls->handle)) + if (dfm_eof (dls->reader)) return -2; for (var_spec = dls->first; var_spec; var_spec = var_spec->next) { - struct len_string field; + struct fixed_string field; int column; /* Cut out a field and check for end-of-line. */ @@ -1212,9 +1205,9 @@ read_from_data_list_list (const struct data_list_pgm *dls, { int width = get_format_var_width (&var_spec->input); if (width == 0) - c->data[var_spec->fv].f = SYSMIS; + case_data_rw (c, var_spec->fv)->f = SYSMIS; else - memset (c->data[var_spec->fv].s, ' ', width); + memset (case_data_rw (c, var_spec->fv)->s, ' ', width); } break; } @@ -1224,7 +1217,7 @@ read_from_data_list_list (const struct data_list_pgm *dls, di.s = ls_c_str (&field); di.e = ls_end (&field); - di.v = &c->data[var_spec->fv]; + di.v = case_data_rw (c, var_spec->fv); di.flags = 0; di.f1 = column; di.format = var_spec->input; @@ -1232,7 +1225,7 @@ read_from_data_list_list (const struct data_list_pgm *dls, } } - dfm_forward_record (dls->handle); + dfm_forward_record (dls->reader); return -1; } @@ -1255,8 +1248,9 @@ static void data_list_trns_free (struct trns_header *pgm) { struct data_list_pgm *dls = (struct data_list_pgm *) pgm; + free (dls->delims); destroy_dls_var_spec (dls->first); - fh_close_handle (dls->handle); + dfm_close_reader (dls->reader); free (pgm); } @@ -1269,7 +1263,7 @@ data_list_trns_proc (struct trns_header *t, struct ccase *c, data_list_read_func *read_func; int retval; - dfm_push (dls->handle); + dfm_push (dls->reader); read_func = get_data_list_read_func (dls); retval = read_func (dls, c); @@ -1283,7 +1277,7 @@ data_list_trns_proc (struct trns_header *t, struct ccase *c, { msg (SE, _("Attempt to read past end of file.")); err_failure (); - dfm_pop (dls->handle); + dfm_pop (dls->reader); return -2; } @@ -1298,14 +1292,14 @@ data_list_trns_proc (struct trns_header *t, struct ccase *c, { if (retval == -2) { - c->data[dls->end->fv].f = 1.0; + case_data_rw (c, dls->end->fv)->f = 1.0; retval = -1; } else - c->data[dls->end->fv].f = 0.0; + case_data_rw (c, dls->end->fv)->f = 0.0; } - dfm_pop (dls->handle); + dfm_pop (dls->reader); return retval; } @@ -1320,13 +1314,11 @@ data_list_source_read (struct case_source *source, struct data_list_pgm *dls = source->aux; data_list_read_func *read_func = get_data_list_read_func (dls); - dfm_push (dls->handle); + dfm_push (dls->reader); while (read_func (dls, c) != -2) if (!write_case (wc_data)) break; - dfm_pop (dls->handle); - - fh_close_handle (dls->handle); + dfm_pop (dls->reader); } /* Destroys the source's internal data. */ @@ -1358,7 +1350,7 @@ struct repeating_data_trns { struct trns_header h; struct dls_var_spec *first, *last; /* Variable parsing specifications. */ - struct file_handle *handle; /* Input file, never NULL. */ + struct dfm_reader *reader; /* Input file, never NULL. */ struct rpd_num_or_var starts_beg; /* STARTS=, before the dash. */ struct rpd_num_or_var starts_end; /* STARTS=, after the dash. */ @@ -1389,17 +1381,14 @@ int cmd_repeating_data (void) { struct repeating_data_trns *rpd; - - /* 0=print no table, 1=print table. (TABLE subcommand.) */ - int table = 1; - - /* Bits are set when a particular subcommand has been seen. */ - unsigned seen = 0; + int table = 1; /* Print table? */ + unsigned seen = 0; /* Mark subcommands as already seen. */ + struct file_handle *const fh = default_handle; assert (case_source_is_complex (vfm_source)); rpd = xmalloc (sizeof *rpd); - rpd->handle = default_handle; + rpd->reader = dfm_open_reader (default_handle); rpd->first = rpd->last = NULL; rpd->starts_beg.num = 0; rpd->starts_beg.var = NULL; @@ -1415,11 +1404,12 @@ cmd_repeating_data (void) { if (lex_match_id ("FILE")) { + struct file_handle *file; lex_match ('='); - rpd->handle = fh_parse_file_handle (); - if (!rpd->handle) + file = fh_parse (); + if (file == NULL) goto error; - if (rpd->handle != default_handle) + if (file != fh) { msg (SE, _("REPEATING DATA must use the same file as its " "corresponding DATA LIST or FILE TYPE.")); @@ -1610,9 +1600,9 @@ cmd_repeating_data (void) /* Calculate starts_end, cont_end if necessary. */ if (rpd->starts_end.num == 0 && rpd->starts_end.var == NULL) - rpd->starts_end.num = handle_get_record_width (rpd->handle); + rpd->starts_end.num = handle_get_record_width (fh); if (rpd->cont_end.num == 0 && rpd->starts_end.var == NULL) - rpd->cont_end.num = handle_get_record_width (rpd->handle); + rpd->cont_end.num = handle_get_record_width (fh); /* Calculate length if possible. */ if ((seen & 4) == 0) @@ -1632,7 +1622,7 @@ cmd_repeating_data (void) goto error; if (table) - dump_fixed_table (rpd->first, rpd->handle, rpd->last->rec); + dump_fixed_table (rpd->first, fh, rpd->last->rec); { struct repeating_data_trns *new_trns; @@ -1784,7 +1774,7 @@ realize_value (struct rpd_num_or_var *n, struct ccase *c) assert (n->num == 0); if (n->var != NULL) { - double v = c->data[n->var->fv].f; + double v = case_num (c, n->var->fv); if (v == SYSMIS || v <= INT_MIN || v >= INT_MAX) return -1; @@ -1891,7 +1881,7 @@ rpd_parse_record (const struct rpd_parse_info *info) struct data_in di; data_in_finite_line (&di, info->line, info->len, fc, lc); - di.v = &info->c->data[var_spec->fv]; + di.v = case_data_rw (info->c, var_spec->fv); di.flags = 0; di.f1 = fc + 1; di.format = var_spec->input; @@ -1921,7 +1911,7 @@ repeating_data_trns_proc (struct trns_header *trns, struct ccase *c, { struct repeating_data_trns *t = (struct repeating_data_trns *) trns; - struct len_string line; /* Current record. */ + struct fixed_string line; /* Current record. */ int starts_beg; /* Starting column. */ int starts_end; /* Ending column. */ @@ -1936,15 +1926,15 @@ repeating_data_trns_proc (struct trns_header *trns, struct ccase *c, int skip_first_record = 0; - dfm_push (t->handle); + dfm_push (t->reader); /* Read the current record. */ - dfm_reread_record (t->handle, 1); - dfm_expand_tabs (t->handle); - if (dfm_eof (t->handle)) + dfm_reread_record (t->reader, 1); + dfm_expand_tabs (t->reader); + if (dfm_eof (t->reader)) return -2; - dfm_get_record (t->handle, &line); - dfm_forward_record (t->handle); + dfm_get_record (t->reader, &line); + dfm_forward_record (t->reader); /* Calculate occurs, length. */ occurs_left = occurs = realize_value (&t->occurs, c); @@ -2034,7 +2024,7 @@ repeating_data_trns_proc (struct trns_header *trns, struct ccase *c, assert (occurs_left >= 0); /* Read in another record. */ - if (dfm_eof (t->handle)) + if (dfm_eof (t->reader)) { tmsg (SE, RPD_ERR, _("Unexpected end of file with %d repetitions " @@ -2042,9 +2032,9 @@ repeating_data_trns_proc (struct trns_header *trns, struct ccase *c, occurs_left, occurs); return -2; } - dfm_expand_tabs (t->handle); - dfm_get_record (t->handle, &line); - dfm_forward_record (t->handle); + dfm_expand_tabs (t->reader); + dfm_get_record (t->reader, &line); + dfm_forward_record (t->reader); /* Parse this record. */ info.trns = t; @@ -2062,7 +2052,7 @@ repeating_data_trns_proc (struct trns_header *trns, struct ccase *c, occurs_left -= code; } - dfm_pop (t->handle); + dfm_pop (t->reader); /* FIXME: This is a kluge until we've implemented multiplexing of transformations. */ @@ -2076,7 +2066,7 @@ repeating_data_trns_free (struct trns_header *rpd_) struct repeating_data_trns *rpd = (struct repeating_data_trns *) rpd_; destroy_dls_var_spec (rpd->first); - fh_close_handle (rpd->handle); + dfm_close_reader (rpd->reader); free (rpd->id_value); }