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 <config.h>
#include "data-list.h"
int fc, lc; /* Column numbers in record. */
/* Free format only. */
- char name[9]; /* Name of variable. */
+ char name[LONG_NAME_LEN + 1]; /* Name of variable. */
};
/* Constants for DATA LIST type. */
if (lex_match_id ("TAB"))
delim = '\t';
else if (token == T_STRING && tokstr.length == 1)
- delim = tokstr.string[0];
+ {
+ delim = tokstr.string[0];
+ lex_get();
+ }
else
{
lex_error (NULL);
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 (&dls->h);
}
else
- vfm_source = create_case_source (&data_list_source_class,
- default_dict, dls);
+ vfm_source = create_case_source (&data_list_source_class, dls);
return CMD_SUCCESS;
while (lex_match ('/'))
{
fx.recno++;
- if (lex_integer_p ())
+ if (lex_is_integer ())
{
if (lex_integer () < fx.recno)
{
if (!parse_DATA_LIST_vars (&fx.name, &fx.name_cnt, PV_NONE))
return 0;
- if (token == T_NUM)
+ if (lex_is_number ())
{
if (!fixed_parse_compatible (&fx, &dls->first, &dls->last))
goto fail;
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++)
else
input.type = FMT_F;
- if (lex_integer_p ())
+ if (lex_is_integer ())
{
if (lex_integer () < 1)
{
input.type = FMT_F;
input.d = 0;
}
- if (!check_input_specifier (&input))
+ if (!check_input_specifier (&input, 1))
return 0;
/* Start column for next specification. */
tail = new;
/* Parse count. */
- if (lex_integer_p ())
+ if (lex_is_integer ())
{
new->count = lex_integer ();
lex_get ();
}
else if (lex_match ('/'))
new->f.type = FMT_NEWREC;
- else if (!parse_format_specifier (&new->f, 1)
- || !check_input_specifier (&new->f))
+ else if (!parse_format_specifier (&new->f, FMTP_ALLOW_XT)
+ || !check_input_specifier (&new->f, 1))
goto fail;
lex_match (',');
if (!parse_DATA_LIST_vars (&name, &name_cnt, PV_NONE))
return 0;
+
if (lex_match ('('))
{
if (!parse_format_specifier (&input, 0)
- || !check_input_specifier (&input)
+ || !check_input_specifier (&input, 1)
|| !lex_force_match (')'))
{
for (i = 0; i < name_cnt; i++)
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)
struct variable *v;
v = dict_create_var (default_dict, name[i], width);
+
if (!v)
{
msg (SE, _("%s is a duplicate variable name."), name[i]);
spec->input = input;
spec->v = v;
spec->fv = v->fv;
- strcpy (spec->name, name[i]);
+ 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
a 1-based column number indicating the beginning of the field
on success. */
static int
-cut_field (const struct data_list_pgm *dls, struct len_string *field,
+cut_field (const struct data_list_pgm *dls, struct fixed_string *field,
int *end_blank)
{
- struct len_string line;
+ struct fixed_string line;
char *cp;
size_t column_start;
return -2;
for (i = 1; i <= dls->rec_cnt; i++)
{
- struct len_string line;
+ struct fixed_string line;
if (dfm_eof (dls->reader))
{
data_in_finite_line (&di, ls_c_str (&line), ls_length (&line),
var_spec->fc, var_spec->lc);
di.v = case_data_rw (c, var_spec->fv);
- di.flags = 0;
+ di.flags = DI_IMPLIED_DECIMALS;
di.f1 = var_spec->fc;
di.format = var_spec->input;
for (var_spec = dls->first; var_spec; var_spec = var_spec->next)
{
- struct len_string field;
+ struct fixed_string field;
int column;
/* Cut out a field and read in a new record if necessary. */
for (var_spec = dls->first; var_spec; var_spec = var_spec->next)
{
- struct len_string field;
+ struct fixed_string field;
int column;
/* Cut out a field and check for end-of-line. */
free (dls->delims);
destroy_dls_var_spec (dls->first);
dfm_close_reader (dls->reader);
- free (pgm);
}
/* Handle DATA LIST transformation T, parsing data into C. */
data_list_source_destroy (struct case_source *source)
{
data_list_trns_free (source->aux);
+ free (source->aux);
}
const struct case_source_class data_list_source_class =
{
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 |= 2;
if (!parse_num_or_var (&rpd->occurs, "OCCURS"))
goto error;
else if (lex_match_id ("LENGTH"))
{
lex_match ('=');
- if (seen & 4)
+ if (saw_length & 4)
{
msg (SE, _("%s subcommand given multiple times."),"LENGTH");
goto error;
}
- seen |= 4;
+ saw_length |= 4;
if (!parse_num_or_var (&rpd->length, "LENGTH"))
goto error;
else if (lex_match_id ("CONTINUED"))
{
lex_match ('=');
- if (seen & 8)
+ if (saw_continued & 8)
{
msg (SE, _("%s subcommand given multiple times."),"CONTINUED");
goto error;
}
- seen |= 8;
+ saw_continued |= 8;
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 & 16)
{
msg (SE, _("%s subcommand given multiple times."),"ID");
goto error;
}
- seen |= 16;
+ saw_id |= 16;
if (!lex_force_int ())
goto error;
}
/* 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);
- }
+ rpd->h.proc = repeating_data_trns_proc;
+ rpd->h.free = repeating_data_trns_free;
+ add_transformation (&rpd->h);
return lex_end_of_command ();
return 0;
}
}
- else if (lex_integer_p ())
+ else if (lex_is_integer ())
{
value->num = lex_integer ();
if (!parse_DATA_LIST_vars (&fx.name, &fx.name_cnt, PV_NONE))
return 0;
- if (token == T_NUM)
+ if (lex_is_number ())
{
if (!fixed_parse_compatible (&fx, first, last))
goto fail;
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(). */
{
struct repeating_data_trns *t = (struct repeating_data_trns *) trns;
- struct len_string line; /* Current record. */
+ struct fixed_string line; /* Current record. */
int starts_beg; /* Starting column. */
int starts_end; /* Ending column. */