-Sun May 15 23:38:10 2005 Ben Pfaff <blp@gnu.org>
+Mon May 16 22:34:06 2005 Ben Pfaff <blp@gnu.org>
Fix rest of PR 13054.
+
+ * format.def: Fix EDATE, SDATE, ADATE, JDATE, QYR, MOYR, WKYR,
+ DATETIME, TIME system/portable file values.
+
+Mon May 16 22:31:15 2005 Ben Pfaff <blp@gnu.org>
+
+ * data-list.c: (parse_free) Use make_input_format().
+
+ * data-out.c: (num_to_string) Use make_output_format().
+
+ * dictionary.c: (dict_create_var) Ditto.
+
+ * format.c: (global var f8_2) New var.
+ (make_input_format) New function.
+ (make_output_format) New function.
+
+ * get.c: (cmd_match_files) Use make_output_format().
+
+ * list.q: (cmd_list) Ditto.
+
+ * matrix-data.c: Ditto.
+
+ * sfm-read.c: (parse_format_spec) Check output specifier
+ thoroughly.
+
+ * tab.c: (tab_float) Use make_output_format().
+
+Sun May 15 23:38:10 2005 Ben Pfaff <blp@gnu.org>
+
+ Fix more of PR 13054.
* format.def: FMT_A should allow 255-character output. FMT_AHEX
should allow 510-character input and output.
/* Create the target variable in the aggregate
dictionary. */
{
- static const struct fmt_spec f8_2 = {FMT_F, 8, 2};
struct variable *destvar;
v->function = func_index;
else
{
lex_match ('*');
- input.type = FMT_F;
- input.w = 8;
- input.d = 0;
- output = get_format();
+ input = make_input_format (FMT_F, 8, 0);
+ output = get_format ();
}
if (input.type == FMT_A || input.type == FMT_AHEX)
void
num_to_string (double v, char *s, int w, int d)
{
- struct fmt_spec f;
- f.type = FMT_F;
- f.w = w;
- f.d = d;
+ struct fmt_spec f = make_output_format (FMT_F, w, d);
convert_F (s, &f, v);
}
\f
v->miss_type = MISSING_NONE;
if (v->type == NUMERIC)
{
- v->print.type = FMT_F;
- v->print.w = 8;
- v->print.d = 2;
-
+ v->print = f8_2;
v->alignment = ALIGN_RIGHT;
v->display_width = 8;
v->measure = MEASURE_SCALE;
}
else
{
- v->print.type = FMT_A;
- v->print.w = v->width;
- v->print.d = 0;
-
+ v->print = make_output_format (FMT_A, v->width, 0);
v->alignment = ALIGN_LEFT;
v->display_width = 8;
v->measure = MEASURE_NOMINAL;
{"", -1, -1, -1, -1, -1, 0000, -1, -1},
};
+/* Common formats. */
+const struct fmt_spec f8_2 = {FMT_F, 8, 2};
+
/* Parses the alphabetic prefix of the current token as a format
specifier name. Returns the corresponding format specifier
type if successful, or -1 on failure. If ALLOW_XT is zero,
return type;
return -1;
}
+
+/* Returns an input format specification with type TYPE, width W,
+ and D decimals. */
+struct fmt_spec
+make_input_format (int type, int w, int d)
+{
+ struct fmt_spec f;
+ f.type = type;
+ f.w = w;
+ f.d = d;
+ assert (check_input_specifier (&f, 0));
+ return f;
+}
+
+/* Returns an output format specification with type TYPE, width
+ W, and D decimals. */
+struct fmt_spec
+make_output_format (int type, int w, int d)
+{
+ struct fmt_spec f;
+ f.type = type;
+ f.w = w;
+ f.d = d;
+ assert (check_output_specifier (&f, 0));
+ return f;
+}
/* Date/time formats. */
DEFFMT (FMT_DATE, "DATE", 1, 9, 40, 9, 40, 0001, FMT_DATE, 20)
-DEFFMT (FMT_EDATE, "EDATE", 1, 8, 40, 8, 40, 0001, FMT_EDATE, 23)
-DEFFMT (FMT_SDATE, "SDATE", 1, 8, 40, 8, 40, 0001, FMT_SDATE, 24)
-DEFFMT (FMT_ADATE, "ADATE", 1, 8, 40, 8, 40, 0001, FMT_ADATE, 29)
-DEFFMT (FMT_JDATE, "JDATE", 1, 5, 40, 5, 40, 0001, FMT_JDATE, 28)
-DEFFMT (FMT_QYR, "QYR", 1, 4, 40, 6, 40, 0001, FMT_QYR, 30)
-DEFFMT (FMT_MOYR, "MOYR", 1, 6, 40, 6, 40, 0001, FMT_MOYR, 22)
-DEFFMT (FMT_WKYR, "WKYR", 1, 6, 40, 8, 40, 0001, FMT_WKYR, 21)
-DEFFMT (FMT_DATETIME, "DATETIME", 2, 17, 40, 17, 40, 0001, FMT_DATETIME, 38)
-DEFFMT (FMT_TIME, "TIME", 2, 5, 40, 5, 40, 0001, FMT_TIME, 39)
+DEFFMT (FMT_EDATE, "EDATE", 1, 8, 40, 8, 40, 0001, FMT_EDATE, 38)
+DEFFMT (FMT_SDATE, "SDATE", 1, 8, 40, 8, 40, 0001, FMT_SDATE, 39)
+DEFFMT (FMT_ADATE, "ADATE", 1, 8, 40, 8, 40, 0001, FMT_ADATE, 23)
+DEFFMT (FMT_JDATE, "JDATE", 1, 5, 40, 5, 40, 0001, FMT_JDATE, 24)
+DEFFMT (FMT_QYR, "QYR", 1, 4, 40, 6, 40, 0001, FMT_QYR, 29)
+DEFFMT (FMT_MOYR, "MOYR", 1, 6, 40, 6, 40, 0001, FMT_MOYR, 28)
+DEFFMT (FMT_WKYR, "WKYR", 1, 6, 40, 8, 40, 0001, FMT_WKYR, 30)
+DEFFMT (FMT_DATETIME, "DATETIME", 2, 17, 40, 17, 40, 0001, FMT_DATETIME, 22)
+DEFFMT (FMT_TIME, "TIME", 2, 5, 40, 5, 40, 0001, FMT_TIME, 21)
DEFFMT (FMT_DTIME, "DTIME", 2, 11, 40, 8, 40, 0001, FMT_DTIME, 25)
DEFFMT (FMT_WKDAY, "WKDAY", 1, 2, 40, 2, 40, 0001, FMT_WKDAY, 26)
DEFFMT (FMT_MONTH, "MONTH", 1, 3, 40, 3, 40, 0001, FMT_MONTH, 27)
FMTP_SUPPRESS_ERRORS = 002 /* 1=Do not emit error messages. */
};
+/* Common formats. */
+extern const struct fmt_spec f8_2; /* F8.2. */
+
int parse_format_specifier (struct fmt_spec *input, enum fmt_parse_flags);
int parse_format_specifier_name (const char **cp, enum fmt_parse_flags);
int check_input_specifier (const struct fmt_spec *spec, int emit_error);
void data_out (char *s, const struct fmt_spec *fp, const union value *v);
char *fmt_to_string (const struct fmt_spec *);
void num_to_string (double v, char *s, int w, int d);
+struct fmt_spec make_input_format (int type, int w, int d);
+struct fmt_spec make_output_format (int type, int w, int d);
#endif /* !format_h */
for (iter = mtf.head; iter != NULL; iter = iter->next)
if (iter->in_name != NULL)
{
- static const struct fmt_spec f1_0 = {FMT_F, 1, 0};
-
iter->in_var = dict_create_var (mtf.dict, iter->in_name, 0);
if (iter->in_var == NULL)
{
iter->in_var);
goto error;
}
- iter->in_var->print = iter->in_var->write = f1_0;
+ iter->in_var->print = iter->in_var->write
+ = make_output_format (FMT_F, 1, 0);
}
/* MATCH FILES performs an n-way merge on all its input files.
strcpy (casenum_var.name, "Case#");
casenum_var.type = NUMERIC;
casenum_var.fv = -1;
- casenum_var.print.type = FMT_F;
- casenum_var.print.w = (cmd.last == LONG_MAX ? 5 : intlog10 (cmd.last));
- casenum_var.print.d = 0;
+ casenum_var.print = make_output_format (FMT_F,
+ (cmd.last == LONG_MAX
+ ? 5 : intlog10 (cmd.last)), 0);
/* Add the weight variable at the beginning of the variable list. */
cmd.n_variables++;
di.e = token->string + token->length;
di.v = (union value *) &token->number;
di.f1 = first_column;
- di.format.type = FMT_F;
- di.format.w = token->length;
- di.format.d = 0;
+ di.format = make_output_format (FMT_F, token->length, 0);
if (!data_in (&di))
return 0;
/* Translates the format spec from sysfile format to internal
format. */
static int
-parse_format_spec (struct sfm_reader *r, int32 s, struct fmt_spec *v, struct variable *vv)
+parse_format_spec (struct sfm_reader *r, int32 s,
+ struct fmt_spec *f, struct variable *v)
{
- v->type = translate_fmt ((s >> 16) & 0xff);
- if (v->type == -1)
+ f->type = translate_fmt ((s >> 16) & 0xff);
+ if (f->type == -1)
lose ((ME, _("%s: Bad format specifier byte (%d)."),
handle_get_filename (r->fh), (s >> 16) & 0xff));
- v->w = (s >> 8) & 0xff;
- v->d = s & 0xff;
+ f->w = (s >> 8) & 0xff;
+ f->d = s & 0xff;
- /* FIXME? Should verify the resulting specifier more thoroughly. */
-
- if (v->type == -1)
- lose ((ME, _("%s: Bad format specifier byte (%d)."),
- handle_get_filename (r->fh), (s >> 16) & 0xff));
- if ((vv->type == ALPHA) ^ ((formats[v->type].cat & FCAT_STRING) != 0))
+ if ((v->type == ALPHA) ^ ((formats[f->type].cat & FCAT_STRING) != 0))
lose ((ME, _("%s: %s variable %s has %s format specifier %s."),
handle_get_filename (r->fh),
- vv->type == ALPHA ? _("String") : _("Numeric"),
- vv->name,
- formats[v->type].cat & FCAT_STRING ? _("string") : _("numeric"),
- formats[v->type].name));
+ v->type == ALPHA ? _("String") : _("Numeric"),
+ v->name,
+ formats[f->type].cat & FCAT_STRING ? _("string") : _("numeric"),
+ formats[f->type].name));
+
+ if (!check_output_specifier (f, false)
+ || !check_specifier_width (f, v->width, false))
+ {
+ msg (ME, _("%s variable %s has invalid format specifier %s."),
+ v->type == NUMERIC ? _("Numeric") : _("String"),
+ v->name, fmt_to_string (f));
+ *f = v->type == NUMERIC ? f8_2 : make_output_format (FMT_A, v->width, 0);
+ }
return 1;
error:
assert (r >= 0);
assert (r < table->nr);
- f.type = FMT_F;
- f.w = w;
- f.d = d;
+ f = make_output_format (FMT_F, w, d);
#if GLOBAL_DEBUGGING
if (c + table->col_ofs < 0 || r + table->row_ofs < 0