struct variable *end; /* Variable specified on END subcommand. */
int record_cnt; /* Number of records. */
struct string delims; /* Field delimiters. */
+ int skip_records; /* Records to skip before first case. */
};
static const struct case_source_class data_list_source_class;
-static bool parse_fixed (struct pool *tmp_pool, struct data_list_pgm *);
-static bool parse_free (struct pool *tmp_pool, struct data_list_pgm *);
+static bool parse_fixed (struct lexer *, struct dictionary *dict,
+ struct pool *tmp_pool, struct data_list_pgm *);
+static bool parse_free (struct lexer *, struct dictionary *dict,
+ struct pool *tmp_pool, struct data_list_pgm *);
static void dump_fixed_table (const struct ll_list *,
const struct file_handle *, int record_cnt);
static void dump_free_table (const struct data_list_pgm *,
static trns_proc_func data_list_trns_proc;
int
-cmd_data_list (void)
+cmd_data_list (struct lexer *lexer, struct dataset *ds)
{
+ struct dictionary *dict = dataset_dict (ds);
struct data_list_pgm *dls;
int table = -1; /* Print table if nonzero, -1=undecided. */
struct file_handle *fh = fh_inline_file ();
bool ok;
if (!in_input_program ())
- discard_variables (current_dataset);
+ discard_variables (ds);
dls = pool_create_container (struct data_list_pgm, pool);
ll_init (&dls->specs);
dls->type = -1;
dls->end = NULL;
dls->record_cnt = 0;
+ dls->skip_records = 0;
ds_init_empty (&dls->delims);
ds_register_pool (&dls->delims, dls->pool);
tmp_pool = pool_create_subpool (dls->pool);
- while (token != '/')
+ while (lex_token (lexer) != '/')
{
- if (lex_match_id ("FILE"))
+ if (lex_match_id (lexer, "FILE"))
{
- lex_match ('=');
- fh = fh_parse (FH_REF_FILE | FH_REF_INLINE);
+ lex_match (lexer, '=');
+ fh = fh_parse (lexer, FH_REF_FILE | FH_REF_INLINE);
if (fh == NULL)
goto error;
}
- else if (lex_match_id ("RECORDS"))
+ else if (lex_match_id (lexer, "RECORDS"))
{
- lex_match ('=');
- lex_match ('(');
- if (!lex_force_int ())
+ lex_match (lexer, '=');
+ lex_match (lexer, '(');
+ if (!lex_force_int (lexer))
goto error;
- dls->record_cnt = lex_integer ();
- lex_get ();
- lex_match (')');
+ dls->record_cnt = lex_integer (lexer);
+ lex_get (lexer);
+ lex_match (lexer, ')');
}
- else if (lex_match_id ("END"))
+ else if (lex_match_id (lexer, "SKIP"))
+ {
+ lex_match (lexer, '=');
+ if (!lex_force_int (lexer))
+ goto error;
+ dls->skip_records = lex_integer (lexer);
+ lex_get (lexer);
+ }
+ else if (lex_match_id (lexer, "END"))
{
if (dls->end)
{
goto error;
}
- lex_match ('=');
- if (!lex_force_id ())
+ lex_match (lexer, '=');
+ if (!lex_force_id (lexer))
goto error;
- dls->end = dict_lookup_var (dataset_dict (current_dataset), tokid);
+ dls->end = dict_lookup_var (dataset_dict (ds), lex_tokid (lexer));
if (!dls->end)
- dls->end = dict_create_var_assert (dataset_dict (current_dataset), tokid, 0);
- lex_get ();
+ dls->end = dict_create_var_assert (dataset_dict (ds), lex_tokid (lexer), 0);
+ lex_get (lexer);
}
- else if (token == T_ID)
+ else if (lex_token (lexer) == T_ID)
{
- if (lex_match_id ("NOTABLE"))
+ if (lex_match_id (lexer, "NOTABLE"))
table = 0;
- else if (lex_match_id ("TABLE"))
+ else if (lex_match_id (lexer, "TABLE"))
table = 1;
else
{
int type;
- if (lex_match_id ("FIXED"))
+ if (lex_match_id (lexer, "FIXED"))
type = DLS_FIXED;
- else if (lex_match_id ("FREE"))
+ else if (lex_match_id (lexer, "FREE"))
type = DLS_FREE;
- else if (lex_match_id ("LIST"))
+ else if (lex_match_id (lexer, "LIST"))
type = DLS_LIST;
else
{
- lex_error (NULL);
+ lex_error (lexer, NULL);
goto error;
}
dls->type = type;
if ((dls->type == DLS_FREE || dls->type == DLS_LIST)
- && lex_match ('('))
+ && lex_match (lexer, '('))
{
- while (!lex_match (')'))
+ while (!lex_match (lexer, ')'))
{
int delim;
- if (lex_match_id ("TAB"))
+ if (lex_match_id (lexer, "TAB"))
delim = '\t';
- else if (token == T_STRING && ds_length (&tokstr) == 1)
+ else if (lex_token (lexer) == T_STRING && ds_length (lex_tokstr (lexer)) == 1)
{
- delim = ds_first (&tokstr);
- lex_get ();
+ delim = ds_first (lex_tokstr (lexer));
+ lex_get (lexer);
}
else
{
- lex_error (NULL);
+ lex_error (lexer, NULL);
goto error;
}
ds_put_char (&dls->delims, delim);
- lex_match (',');
+ lex_match (lexer, ',');
}
}
}
}
else
{
- lex_error (NULL);
+ lex_error (lexer, NULL);
goto error;
}
}
if (table == -1)
table = dls->type != DLS_FREE;
- ok = (dls->type == DLS_FIXED ? parse_fixed : parse_free) (tmp_pool, dls);
+ ok = (dls->type == DLS_FIXED ? parse_fixed : parse_free) (lexer, dict, tmp_pool, dls);
if (!ok)
goto error;
- if (lex_end_of_command () != CMD_SUCCESS)
+ if (lex_end_of_command (lexer) != CMD_SUCCESS)
goto error;
if (table)
dump_free_table (dls, fh);
}
- dls->reader = dfm_open_reader (fh);
+ dls->reader = dfm_open_reader (fh, lexer);
if (dls->reader == NULL)
goto error;
if (in_input_program ())
- add_transformation (current_dataset, data_list_trns_proc, data_list_trns_free, dls);
+ add_transformation (ds, data_list_trns_proc, data_list_trns_free, dls);
else
- proc_set_source (current_dataset,
- create_case_source (&data_list_source_class, dls));
+ proc_set_source (ds, create_case_source (&data_list_source_class, dls));
pool_destroy (tmp_pool);
needed once parsing is complete. Returns true only if
successful. */
static bool
-parse_fixed (struct pool *tmp_pool, struct data_list_pgm *dls)
+parse_fixed (struct lexer *lexer, struct dictionary *dict,
+ struct pool *tmp_pool, struct data_list_pgm *dls)
{
int last_nonempty_record;
int record = 0;
int column = 1;
- while (token != '.')
+ while (lex_token (lexer) != '.')
{
char **names;
size_t name_cnt, name_idx;
size_t format_cnt;
/* Parse everything. */
- if (!parse_record_placement (&record, &column)
- || !parse_DATA_LIST_vars_pool (tmp_pool, &names, &name_cnt, PV_NONE)
- || !parse_var_placements (tmp_pool, name_cnt, &formats, &format_cnt))
+ if (!parse_record_placement (lexer, &record, &column)
+ || !parse_DATA_LIST_vars_pool (lexer, tmp_pool,
+ &names, &name_cnt, PV_NONE)
+ || !parse_var_placements (lexer, tmp_pool, name_cnt, true,
+ &formats, &format_cnt))
return false;
/* Create variables and var specs. */
name = names[name_idx++];
/* Create variable. */
- width = get_format_var_width (f);
- v = dict_create_var (dataset_dict (current_dataset), name, width);
+ width = fmt_var_width (f);
+ v = dict_create_var (dict, name, width);
if (v != NULL)
{
/* Success. */
- struct fmt_spec output;
- convert_fmt_ItoO (f, &output);
- v->print = output;
- v->write = output;
+ struct fmt_spec output = fmt_for_output_from_input (f);
+ var_set_both_formats (v, &output);
}
else
{
return false;
}
- v = dict_lookup_var_assert (dataset_dict (current_dataset), name);
- if ((width != 0) != (v->width != 0))
+ v = dict_lookup_var_assert (dict, name);
+ if ((width != 0) != (var_get_width (v) != 0))
{
msg (SE, _("There is already a variable %s of a "
"different type."),
name);
return false;
}
- if (width != 0 && width != v->width)
+ if (width != 0 && width != var_get_width (v))
{
msg (SE, _("There is already a string variable %s of a "
"different width."), name);
spec->fv = v->fv;
spec->record = record;
spec->first_column = column;
- strcpy (spec->name, v->name);
+ strcpy (spec->name, var_get_name (v));
ll_push_tail (&dls->specs, &spec->ll);
column += f->w;
row = 1;
ll_for_each (spec, struct dls_var_spec, ll, specs)
{
+ char fmt_string[FMT_STRING_LEN_MAX + 1];
tab_text (t, 0, row, TAB_LEFT, spec->name);
tab_text (t, 1, row, TAT_PRINTF, "%d", spec->record);
tab_text (t, 2, row, TAT_PRINTF, "%3d-%3d",
spec->first_column, spec->first_column + spec->input.w - 1);
- tab_text (t, 3, row, TAB_LEFT | TAB_FIX, fmt_to_string (&spec->input));
+ tab_text (t, 3, row, TAB_LEFT | TAB_FIX,
+ fmt_to_string (&spec->input, fmt_string));
row++;
}
them to DLS. Uses TMP_POOL for data that is not needed once
parsing is complete. Returns true only if successful. */
static bool
-parse_free (struct pool *tmp_pool, struct data_list_pgm *dls)
+parse_free (struct lexer *lexer, struct dictionary *dict, struct pool *tmp_pool,
+ struct data_list_pgm *dls)
{
- lex_get ();
- while (token != '.')
+ lex_get (lexer);
+ while (lex_token (lexer) != '.')
{
struct fmt_spec input, output;
char **name;
size_t name_cnt;
size_t i;
- if (!parse_DATA_LIST_vars_pool (tmp_pool, &name, &name_cnt, PV_NONE))
+ if (!parse_DATA_LIST_vars_pool (lexer, tmp_pool,
+ &name, &name_cnt, PV_NONE))
return 0;
- if (lex_match ('('))
+ if (lex_match (lexer, '('))
{
- if (!parse_format_specifier (&input)
- || !check_input_specifier (&input, 1)
- || !lex_force_match (')'))
+ if (!parse_format_specifier (lexer, &input)
+ || !fmt_check_input (&input)
+ || !lex_force_match (lexer, ')'))
return NULL;
- convert_fmt_ItoO (&input, &output);
+
+ /* As a special case, N format is treated as F format
+ for free-field input. */
+ if (input.type == FMT_N)
+ input.type = FMT_F;
+
+ output = fmt_for_output_from_input (&input);
}
else
{
- lex_match ('*');
- input = make_input_format (FMT_F, 8, 0);
+ lex_match (lexer, '*');
+ input = fmt_for_input (FMT_F, 8, 0);
output = *get_format ();
}
struct dls_var_spec *spec;
struct variable *v;
- v = dict_create_var (dataset_dict (current_dataset), name[i],
- get_format_var_width (&input));
+ v = dict_create_var (dict, name[i], fmt_var_width (&input));
if (v == NULL)
{
msg (SE, _("%s is a duplicate variable name."), name[i]);
return 0;
}
- v->print = v->write = output;
+ var_set_both_formats (v, &output);
spec = pool_alloc (dls->pool, sizeof *spec);
spec->input = input;
spec->fv = v->fv;
- strcpy (spec->name, v->name);
+ strcpy (spec->name, var_get_name (v));
ll_push_tail (&dls->specs, &spec->ll);
}
}
tab_box (t, TAL_1, TAL_1, TAL_0, TAL_1, 0, 0, 1, spec_cnt);
tab_hline (t, TAL_2, 0, 1, 1);
tab_dim (t, tab_natural_dimensions);
-
row = 1;
ll_for_each (spec, struct dls_var_spec, ll, &dls->specs)
{
+ char str[FMT_STRING_LEN_MAX + 1];
tab_text (t, 0, row, TAB_LEFT, spec->name);
- tab_text (t, 1, row, TAB_LEFT | TAB_FIX, fmt_to_string (&spec->input));
+ tab_text (t, 1, row, TAB_LEFT | TAB_FIX,
+ fmt_to_string (&spec->input, str));
row++;
}
line = dfm_get_record (dls->reader);
ll_for_each_continue (spec, struct dls_var_spec, ll, &dls->specs)
- {
- struct data_in di;
-
- data_in_finite_line (&di, ss_data (line), ss_length (line),
- spec->first_column,
- spec->first_column + spec->input.w - 1);
- di.v = case_data_rw (c, spec->fv);
- di.flags = DI_IMPLIED_DECIMALS;
- di.f1 = spec->first_column;
- di.format = spec->input;
-
- data_in (&di);
- }
+ data_in (ss_substr (line, spec->first_column - 1, spec->input.w),
+ spec->input.type, spec->input.d, spec->first_column,
+ case_data_rw (c, spec->fv), fmt_var_width (&spec->input));
dfm_forward_record (dls->reader);
}
ll_for_each (spec, struct dls_var_spec, ll, &dls->specs)
{
struct substring field;
- struct data_in di;
/* Cut out a field and read in a new record if necessary. */
while (!cut_field (dls, &field))
}
}
- di.s = ss_data (field);
- di.e = ss_end (field);
- di.v = case_data_rw (c, spec->fv);
- di.flags = 0;
- di.f1 = dfm_get_column (dls->reader, ss_data (field));
- di.format = spec->input;
- data_in (&di);
+ data_in (field, spec->input.type, 0,
+ dfm_get_column (dls->reader, ss_data (field)),
+ case_data_rw (c, spec->fv), fmt_var_width (&spec->input));
}
return true;
}
ll_for_each (spec, struct dls_var_spec, ll, &dls->specs)
{
struct substring field;
- struct data_in di;
if (!cut_field (dls, &field))
{
spec->name);
ll_for_each_continue (spec, struct dls_var_spec, ll, &dls->specs)
{
- int width = get_format_var_width (&spec->input);
+ int width = fmt_var_width (&spec->input);
if (width == 0)
case_data_rw (c, spec->fv)->f = SYSMIS;
else
break;
}
- di.s = ss_data (field);
- di.e = ss_end (field);
- di.v = case_data_rw (c, spec->fv);
- di.flags = 0;
- di.f1 = dfm_get_column (dls->reader, ss_data (field));
- di.format = spec->input;
- data_in (&di);
+ data_in (field, spec->input.type, 0,
+ dfm_get_column (dls->reader, ss_data (field)),
+ case_data_rw (c, spec->fv), fmt_var_width (&spec->input));
}
dfm_forward_record (dls->reader);
/* Handle DATA LIST transformation DLS, parsing data into C. */
static int
-data_list_trns_proc (void *dls_, struct ccase *c, casenum_t case_num UNUSED)
+data_list_trns_proc (void *dls_, struct ccase *c, casenumber case_num UNUSED)
{
struct data_list_pgm *dls = dls_;
int retval;
{
struct data_list_pgm *dls = source->aux;
+ /* Skip the requested number of records before reading the
+ first case. */
+ while (dls->skip_records > 0)
+ {
+ if (dfm_eof (dls->reader))
+ return false;
+ dfm_forward_record (dls->reader);
+ dls->skip_records--;
+ }
+
for (;;)
{
bool ok;