#include "file-handle.h"
#include "filename.h"
#include "format.h"
-#include "getline.h"
+#include "getl.h"
#include "hash.h"
#include "magic.h"
#include "misc.h"
#include "str.h"
#include "var.h"
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+
#include "debug-print.h"
/* System file reader. */
/* Variables. */
struct sfm_var *vars; /* Variables. */
- size_t var_cnt; /* Number of variables. */
/* File's special constants. */
flt64 sysmis;
/* Swap bytes *A and *B. */
static inline void
-bswap (unsigned char *a, unsigned char *b)
+bswap (char *a, char *b)
{
- unsigned char t = *a;
+ char t = *a;
*a = *b;
*b = t;
}
-/* bswap_int32(): Reverse the byte order of 32-bit integer *X. */
+/* Reverse the byte order of 32-bit integer *X. */
static inline void
bswap_int32 (int32 *x_)
{
- unsigned char *x = (unsigned char *) x_;
+ char *x = (char *) x_;
bswap (x + 0, x + 3);
bswap (x + 1, x + 2);
}
static inline void
bswap_flt64 (flt64 *x_)
{
- unsigned char *x = (unsigned char *) x_;
+ char *x = (char *) x_;
bswap (x + 0, x + 7);
bswap (x + 1, x + 6);
bswap (x + 2, x + 5);
r->weight_idx = -1;
r->vars = NULL;
- r->var_cnt = 0;
r->sysmis = -FLT64_MAX;
r->highest = FLT64_MAX;
if (!read_header (r, *dict, info) || !read_variables (r, *dict, &var_by_idx))
goto error;
+
/* Handle weighting. */
if (r->weight_idx != -1)
{
{
const int n_vars = data.count / 3 ;
int i;
- if ( data.count % 3 )
+ if ( data.count % 3 || n_vars > dict_get_var_cnt(*dict) )
{
msg (MW, _("%s: Invalid subrecord length. "
"Record: 7; Subrecord: 11"),
skip = 1;
}
- for ( i = 0 ; i < n_vars ; ++i )
+ for ( i = 0 ; i < min(n_vars, dict_get_var_cnt(*dict)) ; ++i )
{
struct
{
break;
}
+ /* Identify any duplicates. */
+ if ( compare_var_names(short_name, long_name, 0) &&
+ NULL != dict_lookup_var (*dict, long_name))
+ {
+ lose ((ME, _("%s: Duplicate long variable name `%s' "
+ "within system file."),
+ handle_get_filename (r->fh), long_name));
+ break;
+ }
+
/* Set long name.
Renaming a variable may clear the short
name, but we want to retain it, so
int long_string_count = 0; /* # of long string continuation
records still expected. */
int next_value = 0; /* Index to next `value' structure. */
- size_t var_cap = 0;
assert(r);
*var_by_idx = 0;
/* Pre-allocate variables. */
- if ( r->value_cnt != -1 )
- *var_by_idx = xmalloc(r->value_cnt * sizeof (**var_by_idx));
+ if (r->value_cnt != -1)
+ {
+ *var_by_idx = xnmalloc (r->value_cnt, sizeof **var_by_idx);
+ r->vars = xnmalloc (r->value_cnt, sizeof *r->vars);
+ }
/* Read in the entry for each variable and use the info to
for (i = 0; ; ++i)
{
struct variable *vv;
- char name[9];
+ char name[SHORT_NAME_LEN + 1];
int nv;
int j;
if (sv.rec_type != 2)
{
buf_unread(r, sizeof sv);
+ r->value_cnt = i;
break;
}
if ( -1 == r->value_cnt )
- *var_by_idx = xrealloc (*var_by_idx, sizeof **var_by_idx * (i+1) );
+ {
+ *var_by_idx = xnrealloc (*var_by_idx, i + 1, sizeof **var_by_idx);
+ r->vars = xnrealloc (r->vars, i + 1, sizeof *r->vars);
+ }
/* If there was a long string previously, make sure that the
continuations are present; otherwise make sure there aren't
"proper number of continuation records."),
handle_get_filename (r->fh), i));
+
+ r->vars[i].width = -1;
(*var_by_idx)[i] = NULL;
long_string_count--;
continue;
}
name[j] = 0;
+ if ( ! var_is_valid_name(name, false) )
+ lose ((ME, _("%s: Invalid variable name `%s' within system file."),
+ handle_get_filename (r->fh), name));
+
/* Create variable. */
+
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. */
if (sv.n_missing_values != 0)
{
flt64 mv[3];
+ int mv_cnt = abs (sv.n_missing_values);
if (vv->width > MAX_SHORT_STRING)
lose ((ME, _("%s: Long string variable %s may not have missing "
"values."),
handle_get_filename (r->fh), vv->name));
- assertive_buf_read (r, mv, sizeof *mv * abs (sv.n_missing_values), 0);
+ assertive_buf_read (r, mv, sizeof *mv * mv_cnt, 0);
if (r->reverse_endian && vv->type == NUMERIC)
- for (j = 0; j < abs (sv.n_missing_values); j++)
+ for (j = 0; j < mv_cnt; j++)
bswap_flt64 (&mv[j]);
if (sv.n_missing_values > 0)
{
- vv->miss_type = sv.n_missing_values;
- if (vv->type == NUMERIC)
- for (j = 0; j < sv.n_missing_values; j++)
- vv->missing[j].f = mv[j];
- else
- for (j = 0; j < sv.n_missing_values; j++)
- memcpy (vv->missing[j].s, &mv[j], vv->width);
+ for (j = 0; j < sv.n_missing_values; j++)
+ if (vv->type == NUMERIC)
+ mv_add_num (&vv->miss, mv[j]);
+ else
+ mv_add_str (&vv->miss, (char *) &mv[j]);
}
else
{
- int x = 0;
-
if (vv->type == ALPHA)
lose ((ME, _("%s: String variable %s may not have missing "
"values specified as a range."),
handle_get_filename (r->fh), vv->name));
if (mv[0] == r->lowest)
- {
- vv->miss_type = MISSING_LOW;
- vv->missing[x++].f = mv[1];
- }
+ mv_add_num_range (&vv->miss, LOWEST, mv[1]);
else if (mv[1] == r->highest)
- {
- vv->miss_type = MISSING_HIGH;
- vv->missing[x++].f = mv[0];
- }
+ mv_add_num_range (&vv->miss, mv[0], HIGHEST);
else
- {
- vv->miss_type = MISSING_RANGE;
- vv->missing[x++].f = mv[0];
- vv->missing[x++].f = mv[1];
- }
+ mv_add_num_range (&vv->miss, mv[0], mv[1]);
if (sv.n_missing_values == -3)
- {
- vv->miss_type += 3;
- vv->missing[x++].f = mv[2];
- }
+ mv_add_num (&vv->miss, mv[2]);
}
}
- else
- vv->miss_type = MISSING_NONE;
if (!parse_format_spec (r, sv.print, &vv->print, vv)
|| !parse_format_spec (r, sv.write, &vv->write, vv))
goto error;
- /* Add variable to list. */
- if (var_cap >= r->var_cnt)
- {
- var_cap = 2 + r->var_cnt * 2;
- r->vars = xrealloc (r->vars, var_cap * sizeof *r->vars);
- }
- r->vars[r->var_cnt].width = vv->width;
- r->vars[r->var_cnt].fv = vv->fv;
- r->var_cnt++;
+ r->vars[i].width = vv->width;
+ r->vars[i].fv = vv->fv;
+
}
/* Some consistency checks. */
"%d were read from file."),
handle_get_filename (r->fh), r->value_cnt, next_value);
+
return 1;
error:
{
struct label
{
- unsigned char raw_value[8]; /* Value as uninterpreted bytes. */
+ char raw_value[8]; /* Value as uninterpreted bytes. */
union value value; /* Value. */
char *label; /* Null-terminated label string. */
};
if (r->reverse_endian)
bswap_int32 (&n_labels);
+ if ( n_labels >= ((int32) ~0) / sizeof *labels)
+ {
+ corrupt_msg(MW, _("%s: Invalid number of labels: %d. Ignoring labels."),
+ handle_get_filename (r->fh), n_labels);
+ n_labels = 0;
+ }
+
/* Allocate memory. */
- labels = xmalloc (n_labels * sizeof *labels);
+ labels = xcalloc (n_labels, sizeof *labels);
for (i = 0; i < n_labels; i++)
labels[i].label = NULL;
handle_get_filename (r->fh), n_vars, dict_get_var_cnt (dict)));
/* Read the list of variables. */
- var = xmalloc (n_vars * sizeof *var);
+ var = xnmalloc (n_vars, sizeof *var);
for (i = 0; i < n_vars; i++)
{
int32 var_idx;
if (var[0]->type == ALPHA)
{
- const int copy_len = min (sizeof (label->raw_value),
- sizeof (label->label));
+ const int copy_len = min (sizeof label->raw_value,
+ sizeof label->label);
memcpy (label->value.s, label->raw_value, copy_len);
} else {
flt64 f;
size_t amt;
if (r->buf == NULL)
- r->buf = xmalloc (sizeof *r->buf * 128);
+ r->buf = xnmalloc (128, sizeof *r->buf);
amt = fread (r->buf, sizeof *r->buf, 128, r->file);
if (ferror (r->file))
{
for (;;)
{
- for (; p < p_end; p++)
+ for (; p < p_end; p++){
switch (*p)
{
case 0:
goto success;
break;
}
-
+ }
/* We have reached the end of this instruction octet. Read
another. */
if (r->ptr == NULL || r->ptr >= r->end)
{
int i;
- for (i = 0; i < r->var_cnt; i++)
+ for (i = 0; i < r->value_cnt; i++)
if (r->vars[i].width == 0)
bswap_flt64 (&case_data_rw (c, r->vars[i].fv)->f);
}
{
int i;
- for (i = 0; i < r->var_cnt; i++)
+ for (i = 0; i < r->value_cnt; i++)
if (r->vars[i].width == 0 && case_num (c, i) == r->sysmis)
case_data_rw (c, r->vars[i].fv)->f = SYSMIS;
}
return 0;
}
- for (i = 0; i < r->var_cnt; i++)
+ for (i = 0; i < r->value_cnt; i++)
{
struct sfm_var *v = &r->vars[i];
flt64 f = *bounce_cur++;
if (r->reverse_endian)
bswap_flt64 (&f);
- case_data_rw (c, i)->f = f == r->sysmis ? SYSMIS : f;
+ case_data_rw (c, v->fv)->f = f == r->sysmis ? SYSMIS : f;
}
- else
+ else if (v->width != -1)
{
memcpy (case_data_rw (c, v->fv)->s, bounce_cur, v->width);
bounce_cur += DIV_RND_UP (v->width, sizeof (flt64));