X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=src%2Fsfm-read.c;h=23abde90ff1e57c0e14a04d11a5fdbc72a47e463;hb=dbb0228a4c98cbf4756ba651fda158c1565b3b55;hp=e854e1bad651a85a50bc0bfab437920bdfe1ea0c;hpb=05e356b2a3087e819ef3b5388e29c822f41502e1;p=pspp diff --git a/src/sfm-read.c b/src/sfm-read.c index e854e1bad6..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) { @@ -361,25 +366,69 @@ sfm_open_reader (struct file_handle *fh, struct dictionary **dict, case 13: /* SPSS 12.0 Long variable name map */ { - - char *s; - char *buf = xmalloc(data.size * data.count + 1); - char *tbuf ; - assertive_buf_read (r, buf, data.size * data.count, 0); - buf[data.size * data.count]='\0'; - - s = strtok_r(buf, "\t", &tbuf); - while ( s ) + 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 *shortname, *longname; - shortname = strsep(&s,"="); - longname = strsep(&s,"="); - - dict_add_longvar_entry(*dict, shortname, longname); - - s = strtok_r(0,"\t", &tbuf); + 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; @@ -791,10 +840,11 @@ read_variables (struct sfm_reader *r, name[j] = 0; /* Create variable. */ - vv = (*var_by_idx)[i] = dict_create_var_from_short (dict, name, sv.type); + vv = (*var_by_idx)[i] = dict_create_var (dict, name, sv.type); 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));