X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fsfm-read.c;h=23abde90ff1e57c0e14a04d11a5fdbc72a47e463;hb=dbb0228a4c98cbf4756ba651fda158c1565b3b55;hp=d48291224ab0f4e0226da8082735640daa1b1e6f;hpb=d807ad29cc0d3caa4f0e04ee4b75c70a225cfeaf;p=pspp diff --git a/src/sfm-read.c b/src/sfm-read.c index d48291224a..23abde90ff 100644 --- a/src/sfm-read.c +++ b/src/sfm-read.c @@ -14,8 +14,8 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. */ + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ #include #include "sfm-read.h" @@ -296,6 +296,7 @@ sfm_open_reader (struct file_handle *fh, struct dictionary **dict, int32 count P; } data; + unsigned long bytes; int skip = 0; @@ -306,6 +307,10 @@ sfm_open_reader (struct file_handle *fh, struct dictionary **dict, bswap_int32 (&data.size); bswap_int32 (&data.count); } + bytes = data.size * data.count; + if (bytes < data.size || bytes < data.count) + lose ((ME, "%s: Record type %d subtype %d too large.", + handle_get_filename (r->fh), rec_type, data.subtype)); switch (data.subtype) { @@ -320,10 +325,113 @@ sfm_open_reader (struct file_handle *fh, struct dictionary **dict, break; case 5: - case 6: - case 11: /* ?? Used by SPSS 8.0. */ + case 6: /* ?? Used by SPSS 8.0. */ skip = 1; break; + + case 11: /* Variable display parameters */ + { + const int n_vars = data.count / 3 ; + int i; + if ( data.count % 3 ) + { + msg (MW, _("%s: Invalid subrecord length. " + "Record: 7; Subrecord: 11"), + handle_get_filename (r->fh)); + skip = 1; + } + + for ( i = 0 ; i < n_vars ; ++i ) + { + struct + { + int32 measure P; + int32 width P; + int32 align P; + } + params; + + struct variable *v; + + assertive_buf_read (r, ¶ms, sizeof(params), 0); + + v = dict_get_var(*dict, i); + + v->measure = params.measure; + v->display_width = params.width; + v->alignment = params.align; + } + } + break; + + case 13: /* SPSS 12.0 Long variable name map */ + { + char *buf, *short_name, *save_ptr; + int idx; + + /* Read data. */ + buf = xmalloc (bytes + 1); + if (!buf_read (r, buf, bytes, 0)) + { + free (buf); + goto error; + } + buf[bytes] = '\0'; + + /* Parse data. */ + for (short_name = strtok_r (buf, "=", &save_ptr), idx = 0; + short_name != NULL; + short_name = strtok_r (NULL, "=", &save_ptr), idx++) + { + char *long_name = strtok_r (NULL, "\t", &save_ptr); + struct variable *v; + + /* Validate long name. */ + if (long_name == NULL) + { + msg (MW, _("%s: Trailing garbage in long variable " + "name map."), + handle_get_filename (r->fh)); + break; + } + if (!var_is_valid_name (long_name, false)) + { + msg (MW, _("%s: Long variable mapping to invalid " + "variable name `%s'."), + handle_get_filename (r->fh), long_name); + break; + } + + /* Find variable using short name. */ + v = dict_lookup_var (*dict, short_name); + if (v == NULL) + { + msg (MW, _("%s: Long variable mapping for " + "nonexistent variable %s."), + handle_get_filename (r->fh), short_name); + break; + } + + /* Set long name. + Renaming a variable may clear the short + name, but we want to retain it, so + re-set it explicitly. */ + dict_rename_var (*dict, v, long_name); + var_set_short_name (v, short_name); + + /* For compatability, make sure dictionary + is in long variable name map order. In + the common case, this has no effect, + because the dictionary and the long + variable name map are already in the + same order. */ + dict_reorder_var (*dict, v, idx); + } + + /* Free data. */ + free (buf); + } + break; default: msg (MW, _("%s: Unrecognized record type 7, subtype %d " @@ -628,6 +736,8 @@ read_variables (struct sfm_reader *r, int next_value = 0; /* Index to next `value' structure. */ size_t var_cap = 0; + assert(r); + /* Allocate variables. */ *var_by_idx = xmalloc (sizeof **var_by_idx * r->value_cnt); @@ -706,7 +816,7 @@ read_variables (struct sfm_reader *r, name[0] = toupper ((unsigned char) (sv.name[0])); /* Copy remaining characters of variable name. */ - for (j = 1; j < 8; j++) + for (j = 1; j < SHORT_NAME_LEN; j++) { int c = (unsigned char) sv.name[j]; @@ -734,6 +844,7 @@ read_variables (struct sfm_reader *r, if (vv == NULL) lose ((ME, _("%s: Duplicate variable name `%s' within system file."), handle_get_filename (r->fh), name)); + var_set_short_name (vv, vv->name); /* Case reading data. */ nv = sv.type == 0 ? 1 : DIV_RND_UP (sv.type, sizeof (flt64)); @@ -757,11 +868,14 @@ read_variables (struct sfm_reader *r, "length %d."), handle_get_filename (r->fh), vv->name, len)); - /* Read label into variable structure. */ - vv->label = buf_read (r, NULL, ROUND_UP (len, sizeof (int32)), len + 1); - if (vv->label == NULL) - goto error; - vv->label[len] = '\0'; + if ( len != 0 ) + { + /* Read label into variable structure. */ + vv->label = buf_read (r, NULL, ROUND_UP (len, sizeof (int32)), len + 1); + if (vv->label == NULL) + goto error; + vv->label[len] = '\0'; + } } /* Set missing values. */ @@ -1079,8 +1193,15 @@ error: static void * buf_read (struct sfm_reader *r, void *buf, size_t byte_cnt, size_t min_alloc) { - if (buf == NULL) + assert (r); + + if (buf == NULL && byte_cnt > 0 ) buf = xmalloc (max (byte_cnt, min_alloc)); + + if ( byte_cnt == 0 ) + return buf; + + if (1 != fread (buf, byte_cnt, 1, r->file)) { if (ferror (r->file))