#include "tab.h"
#include "var.h"
#include "vfm.h"
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
\f
/* Utility function. */
int fc, lc; /* Column numbers in record. */
/* Free format only. */
- char name[SHORT_NAME_LEN + 1]; /* Name of variable. */
+ char name[LONG_NAME_LEN + 1]; /* Name of variable. */
};
/* Constants for DATA LIST type. */
/* DATA LIST private data structure. */
struct data_list_pgm
{
- struct trns_header h;
-
struct dls_var_spec *first, *last; /* Variable parsing specifications. */
struct dfm_reader *reader; /* Data file reader. */
goto error;
if (vfm_source != NULL)
- {
- struct data_list_pgm *new_pgm;
-
- dls->h.proc = data_list_trns_proc;
- dls->h.free = data_list_trns_free;
-
- new_pgm = xmalloc (sizeof *new_pgm);
- memcpy (new_pgm, &dls, sizeof *new_pgm);
- add_transformation (&new_pgm->h);
- }
+ add_transformation (data_list_trns_proc, data_list_trns_free, dls);
else
vfm_source = create_case_source (&data_list_source_class, dls);
return CMD_SUCCESS;
error:
- destroy_dls_var_spec (dls->first);
- free (dls->delims);
- free (dls);
+ data_list_trns_free (dls);
return CMD_FAILURE;
}
struct fixed_parsing_state
{
char **name; /* Variable names. */
- int name_cnt; /* Number of names. */
+ size_t name_cnt; /* Number of names. */
int recno; /* Index of current record. */
int sc; /* 1-based column number of starting column for
parse_fixed (struct data_list_pgm *dls)
{
struct fixed_parsing_state fx;
- int i;
+ size_t i;
fx.recno = 0;
fx.sc = 1;
else
{
msg (SE, _("SPSS-like or FORTRAN-like format "
- "specification expected after variable names."));
+ "specification expected after variable names."));
goto fail;
}
}
else if (!dls->rec_cnt)
dls->rec_cnt = dls->last->rec;
- if (token != '.')
- {
- lex_error (_("expecting end of command"));
- return 0;
- }
- return 1;
+ return lex_end_of_command () == CMD_SUCCESS;
fail:
for (i = 0; i < fx.name_cnt; i++)
{
struct fmt_spec input, output;
char **name;
- int name_cnt;
+ size_t name_cnt;
int width;
- int i;
+ size_t i;
if (!parse_DATA_LIST_vars (&name, &name_cnt, PV_NONE))
return 0;
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)
spec->input = input;
spec->v = v;
spec->fv = v->fv;
- strcpy (spec->name, v->name);
+ str_copy_trunc (spec->name, sizeof spec->name, v->name);
append_var_spec (first, last, spec);
}
for (i = 0; i < name_cnt; i++)
free (name);
}
- if (token != '.')
- lex_error (_("expecting end of command"));
- return 1;
+ return lex_end_of_command () == CMD_SUCCESS;
}
/* Displays a table giving information on free-format variable parsing
}
}
-/* Destroys DATA LIST transformation PGM. */
+/* Destroys DATA LIST transformation DLS. */
static void
-data_list_trns_free (struct trns_header *pgm)
+data_list_trns_free (void *dls_)
{
- struct data_list_pgm *dls = (struct data_list_pgm *) pgm;
+ struct data_list_pgm *dls = dls_;
free (dls->delims);
destroy_dls_var_spec (dls->first);
dfm_close_reader (dls->reader);
- free (pgm);
+ free (dls);
}
-/* Handle DATA LIST transformation T, parsing data into C. */
+/* Handle DATA LIST transformation DLS, parsing data into C. */
static int
-data_list_trns_proc (struct trns_header *t, struct ccase *c,
- int case_num UNUSED)
+data_list_trns_proc (void *dls_, struct ccase *c, int case_num UNUSED)
{
- struct data_list_pgm *dls = (struct data_list_pgm *) t;
+ struct data_list_pgm *dls = dls_;
data_list_read_func *read_func;
int retval;
/* REPEATING DATA private data structure. */
struct repeating_data_trns
{
- struct trns_header h;
struct dls_var_spec *first, *last; /* Variable parsing specifications. */
struct dfm_reader *reader; /* Input file, never NULL. */
{
struct repeating_data_trns *rpd;
int table = 1; /* Print table? */
- unsigned seen = 0; /* Mark subcommands as already seen. */
+ bool saw_starts = false; /* Saw STARTS subcommand? */
+ bool saw_occurs = false; /* Saw OCCURS subcommand? */
+ bool saw_length = false; /* Saw LENGTH subcommand? */
+ bool saw_continued = false; /* Saw CONTINUED subcommand? */
+ bool saw_id = false; /* Saw ID subcommand? */
struct file_handle *const fh = default_handle;
assert (case_source_is_complex (vfm_source));
else if (lex_match_id ("STARTS"))
{
lex_match ('=');
- if (seen & 1)
+ if (saw_starts)
{
msg (SE, _("%s subcommand given multiple times."),"STARTS");
goto error;
}
- seen |= 1;
-
+ saw_starts = true;
+
if (!parse_num_or_var (&rpd->starts_beg, "STARTS beginning column"))
goto error;
if (!parse_num_or_var (&rpd->starts_end, "STARTS ending column"))
goto error;
} else {
- /* Otherwise, rpd->starts_end is left uninitialized.
- This is okay. We will initialize it later from the
- record length of the file. We can't do this now
- because we can't be sure that the user has specified
- the file handle yet. */
+ /* Otherwise, rpd->starts_end is uninitialized. We
+ will initialize it later from the record length
+ of the file. We can't do so now because the
+ file handle may not be specified yet. */
}
if (rpd->starts_beg.num != 0 && rpd->starts_end.num != 0
else if (lex_match_id ("OCCURS"))
{
lex_match ('=');
- if (seen & 2)
+ if (saw_occurs)
{
msg (SE, _("%s subcommand given multiple times."),"OCCURS");
goto error;
}
- seen |= 2;
+ saw_occurs = true;
if (!parse_num_or_var (&rpd->occurs, "OCCURS"))
goto error;
else if (lex_match_id ("LENGTH"))
{
lex_match ('=');
- if (seen & 4)
+ if (saw_length)
{
msg (SE, _("%s subcommand given multiple times."),"LENGTH");
goto error;
}
- seen |= 4;
+ saw_length = true;
if (!parse_num_or_var (&rpd->length, "LENGTH"))
goto error;
else if (lex_match_id ("CONTINUED"))
{
lex_match ('=');
- if (seen & 8)
+ if (saw_continued)
{
msg (SE, _("%s subcommand given multiple times."),"CONTINUED");
goto error;
}
- seen |= 8;
+ saw_continued = true;
if (!lex_match ('/'))
{
- if (!parse_num_or_var (&rpd->cont_beg, "CONTINUED beginning column"))
+ if (!parse_num_or_var (&rpd->cont_beg,
+ "CONTINUED beginning column"))
goto error;
lex_negative_to_dash ();
else if (lex_match_id ("ID"))
{
lex_match ('=');
- if (seen & 16)
+ if (saw_id)
{
msg (SE, _("%s subcommand given multiple times."),"ID");
goto error;
}
- seen |= 16;
+ saw_id = true;
if (!lex_force_int ())
goto error;
goto error;
find_variable_input_spec (rpd->id_var, &rpd->id_spec);
- rpd->id_value = xmalloc (sizeof *rpd->id_value * rpd->id_var->nv);
+ rpd->id_value = xnmalloc (rpd->id_var->nv, sizeof *rpd->id_value);
}
else if (lex_match_id ("TABLE"))
table = 1;
}
/* Comes here when DATA specification encountered. */
- if ((seen & (1 | 2)) != (1 | 2))
+ if (!saw_starts || !saw_occurs)
{
- if ((seen & 1) == 0)
+ if (!saw_starts)
msg (SE, _("Missing required specification STARTS."));
- if ((seen & 2) == 0)
+ if (!saw_occurs)
msg (SE, _("Missing required specification OCCURS."));
goto error;
}
/* Enforce ID restriction. */
- if ((seen & 16) && !(seen & 8))
+ if (saw_id && !saw_continued)
{
msg (SE, _("ID specified without CONTINUED."));
goto error;
}
- /* Calculate starts_end, cont_end if necessary. */
- if (rpd->starts_end.num == 0 && rpd->starts_end.var == NULL)
- rpd->starts_end.num = handle_get_record_width (fh);
- if (rpd->cont_end.num == 0 && rpd->starts_end.var == NULL)
- rpd->cont_end.num = handle_get_record_width (fh);
-
- /* Calculate length if possible. */
- if ((seen & 4) == 0)
+ /* Calculate and check starts_end, cont_end if necessary. */
+ if (rpd->starts_end.num == 0 && rpd->starts_end.var == NULL)
{
- struct dls_var_spec *iter;
-
- for (iter = rpd->first; iter; iter = iter->next)
- {
- if (iter->lc > rpd->length.num)
- rpd->length.num = iter->lc;
- }
- assert (rpd->length.num != 0);
+ rpd->starts_end.num = fh != NULL ? handle_get_record_width (fh) : 80;
+ if (rpd->starts_beg.num != 0
+ && rpd->starts_beg.num > rpd->starts_end.num)
+ {
+ msg (SE, _("STARTS beginning column (%d) exceeds "
+ "default STARTS ending column taken from file's "
+ "record width (%d)."),
+ rpd->starts_beg.num, rpd->starts_end.num);
+ goto error;
+ }
+ }
+ if (rpd->cont_end.num == 0 && rpd->cont_end.var == NULL)
+ {
+ rpd->cont_end.num = fh != NULL ? handle_get_record_width (fh) : 80;
+ if (rpd->cont_beg.num != 0
+ && rpd->cont_beg.num > rpd->cont_end.num)
+ {
+ msg (SE, _("CONTINUED beginning column (%d) exceeds "
+ "default CONTINUED ending column taken from file's "
+ "record width (%d)."),
+ rpd->cont_beg.num, rpd->cont_end.num);
+ goto error;
+ }
}
lex_match ('=');
if (!parse_repeating_data (&rpd->first, &rpd->last))
goto error;
+ /* Calculate length if necessary. */
+ if (!saw_length)
+ {
+ struct dls_var_spec *iter;
+
+ for (iter = rpd->first; iter; iter = iter->next)
+ if (iter->lc > rpd->length.num)
+ rpd->length.num = iter->lc;
+ assert (rpd->length.num != 0);
+ }
+
if (table)
dump_fixed_table (rpd->first, fh, rpd->last->rec);
- {
- struct repeating_data_trns *new_trns;
-
- rpd->h.proc = repeating_data_trns_proc;
- rpd->h.free = repeating_data_trns_free;
-
- new_trns = xmalloc (sizeof *new_trns);
- memcpy (new_trns, &rpd, sizeof *new_trns);
- add_transformation ((struct trns_header *) new_trns);
- }
+ add_transformation (repeating_data_trns_proc, repeating_data_trns_free, rpd);
return lex_end_of_command ();
error:
- destroy_dls_var_spec (rpd->first);
- free (rpd->id_value);
+ repeating_data_trns_free (rpd);
return CMD_FAILURE;
}
static void
find_variable_input_spec (struct variable *v, struct fmt_spec *spec)
{
- int i;
+ size_t i;
for (i = 0; i < n_trns; i++)
{
- struct data_list_pgm *pgm = (struct data_list_pgm *) t_trns[i];
+ struct transformation *trns = &t_trns[i];
- if (pgm->h.proc == data_list_trns_proc)
+ if (trns->proc == data_list_trns_proc)
{
+ struct data_list_pgm *pgm = trns->private;
struct dls_var_spec *iter;
for (iter = pgm->first; iter; iter = iter->next)
parse_repeating_data (struct dls_var_spec **first, struct dls_var_spec **last)
{
struct fixed_parsing_state fx;
- int i;
+ size_t i;
fx.recno = 0;
fx.sc = 1;
else
{
msg (SE, _("SPSS-like or FORTRAN-like format "
- "specification expected after variable names."));
+ "specification expected after variable names."));
goto fail;
}
free (fx.name[i]);
free (fx.name);
}
- if (token != '.')
- {
- lex_error (_("expecting end of command"));
- return 0;
- }
return 1;
static int
realize_value (struct rpd_num_or_var *n, struct ccase *c)
{
- if (n->num > 0)
- return n->num;
-
- assert (n->num == 0);
if (n->var != NULL)
{
double v = case_num (c, n->var->fv);
-
- if (v == SYSMIS || v <= INT_MIN || v >= INT_MAX)
- return -1;
- else
- return v;
+ return v != SYSMIS && v >= INT_MIN && v <= INT_MAX ? v : -1;
}
else
- return 0;
+ return n->num;
}
/* Parameter record passed to rpd_parse_record(). */
DATA structure. Returns -1 on success, -2 on end of file or
on failure. */
int
-repeating_data_trns_proc (struct trns_header *trns, struct ccase *c,
- int case_num UNUSED)
+repeating_data_trns_proc (void *trns_, struct ccase *c, int case_num UNUSED)
{
- struct repeating_data_trns *t = (struct repeating_data_trns *) trns;
+ struct repeating_data_trns *t = trns_;
struct fixed_string line; /* Current record. */
/* Frees a REPEATING DATA transformation. */
void
-repeating_data_trns_free (struct trns_header *rpd_)
+repeating_data_trns_free (void *rpd_)
{
- struct repeating_data_trns *rpd = (struct repeating_data_trns *) rpd_;
+ struct repeating_data_trns *rpd = rpd_;
destroy_dls_var_spec (rpd->first);
dfm_close_reader (rpd->reader);
free (rpd->id_value);
+ free (rpd);
}
/* Lets repeating_data_trns_proc() know how to write the cases
that it composes. Not elegant. */
void
-repeating_data_set_write_case (struct trns_header *trns,
+repeating_data_set_write_case (struct transformation *trns_,
write_case_func *write_case,
write_case_data wc_data)
{
- struct repeating_data_trns *t = (struct repeating_data_trns *) trns;
+ struct repeating_data_trns *t = trns_->private;
- assert (trns->proc == repeating_data_trns_proc);
+ assert (trns_->proc == repeating_data_trns_proc);
t->write_case = write_case;
t->wc_data = wc_data;
}