X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdata%2Fpor-file-reader.c;h=a463124274a20c6cd62e1071f15c51cd95edcb3a;hb=b5c82cc9aabe7e641011130240ae1b2e84348e23;hp=c8e492897f3c117bfbc86e6c6b38a5f68249928d;hpb=6b562f8a8263930b8d1ed1862efec76f2511ed08;p=pspp-builds.git diff --git a/src/data/por-file-reader.c b/src/data/por-file-reader.c index c8e49289..a4631242 100644 --- a/src/data/por-file-reader.c +++ b/src/data/por-file-reader.c @@ -43,6 +43,7 @@ #include #include +#include "minmax.h" #include "xalloc.h" #include "gettext.h" @@ -446,6 +447,28 @@ read_string (struct pfm_reader *r, char *buf) *buf = '\0'; } + +/* Reads a string into BUF, which must have room for 256 + characters. + Returns the number of bytes read. +*/ +static size_t +read_bytes (struct pfm_reader *r, uint8_t *buf) +{ + int n = read_int (r); + if (n < 0 || n > 255) + error (r, _("Bad string length %d."), n); + + while (n-- > 0) + { + *buf++ = r->cc; + advance (r); + } + return n; +} + + + /* Reads a string and returns a copy of it allocated from R's pool. */ static char * @@ -606,8 +629,7 @@ assign_default: return fmt_default_for_width (var_get_width (v)); } -static void parse_value (struct pfm_reader *, struct variable *, - union value *); +static void parse_value (struct pfm_reader *, int width, union value *); /* Read information on all the variables. */ static void @@ -686,7 +708,7 @@ read_variables (struct pfm_reader *r, struct dictionary *dict) var_set_write_format (v, &write); /* Range missing values. */ - mv_init (&miss, var_get_width (v)); + mv_init (&miss, width); if (match (r, 'B')) { double x = read_float (r); @@ -701,13 +723,17 @@ read_variables (struct pfm_reader *r, struct dictionary *dict) /* Single missing values. */ while (match (r, '8')) { + int mv_width = MIN (width, 8); union value value; - parse_value (r, v, &value); + + parse_value (r, mv_width, &value); + value_resize (&value, mv_width, width); mv_add_value (&miss, &value); - value_destroy (&value, var_get_width (v)); + value_destroy (&value, width); } var_set_missing_values (v, &miss); + mv_destroy (&miss); if (match (r, 'C')) { @@ -728,16 +754,16 @@ read_variables (struct pfm_reader *r, struct dictionary *dict) } } -/* Parse a value for variable VV into value V. */ +/* Parse a value of with WIDTH into value V. */ static void -parse_value (struct pfm_reader *r, struct variable *vv, union value *v) +parse_value (struct pfm_reader *r, int width, union value *v) { - value_init (v, var_get_width (vv)); - if (var_is_alpha (vv)) + value_init (v, width); + if (width > 0) { - char string[256]; - read_string (r, string); - buf_copy_str_rpad (value_str_rw (v, 8), 8, string, ' '); + uint8_t buf[256]; + size_t n_bytes = read_bytes (r, buf); + value_copy_buf_rpad (v, width, buf, n_bytes, ' '); } else v->f = read_float (r); @@ -780,7 +806,7 @@ read_value_label (struct pfm_reader *r, struct dictionary *dict) char label[256]; int j; - parse_value (r, v[0], &val); + parse_value (r, var_get_width (v[0]), &val); read_string (r, label); /* Assign the value label to each variable. */ @@ -815,7 +841,6 @@ por_file_casereader_read (struct casereader *reader, void *r_) struct pfm_reader *r = r_; struct ccase *volatile c; size_t i; - size_t idx; c = case_create (r->proto); setjmp (r->bail_out); @@ -833,22 +858,17 @@ por_file_casereader_read (struct casereader *reader, void *r_) return NULL; } - idx = 0; for (i = 0; i < r->var_cnt; i++) { int width = caseproto_get_width (r->proto, i); if (width == 0) - { - case_data_rw_idx (c, idx)->f = read_float (r); - idx++; - } + case_data_rw_idx (c, i)->f = read_float (r); else { - char string[256]; - read_string (r, string); - buf_copy_str_rpad (case_str_rw_idx (c, idx), width, string, ' '); - idx += DIV_RND_UP (width, MAX_SHORT_STRING); + uint8_t buf[256]; + size_t n_bytes = read_bytes (r, buf); + u8_buf_copy_rpad (case_str_rw_idx (c, i), width, buf, n_bytes, ' '); } } @@ -862,17 +882,30 @@ pfm_detect (FILE *file) { unsigned char header[464]; char trans[256]; - int cooked_cnt, raw_cnt; + int cooked_cnt, raw_cnt, line_len; int i; cooked_cnt = raw_cnt = 0; + line_len = 0; while (cooked_cnt < sizeof header) { int c = getc (file); if (c == EOF || raw_cnt++ > 512) return false; - else if (c != '\n' && c != '\r') - header[cooked_cnt++] = c; + else if (c == '\n') + { + while (line_len < 80 && cooked_cnt < sizeof header) + { + header[cooked_cnt++] = ' '; + line_len++; + } + line_len = 0; + } + else if (c != '\r') + { + header[cooked_cnt++] = c; + line_len++; + } } memset (trans, 0, 256);