02110-1301, USA. */
#include <config.h>
-#include <libpspp/message.h>
+
#include <stdlib.h>
-#include <libpspp/alloc.h>
+
#include <data/any-reader.h>
#include <data/any-writer.h>
+#include <data/case-sink.h>
+#include <data/case-source.h>
#include <data/case.h>
-#include <language/command.h>
-#include <libpspp/compiler.h>
+#include <data/casefile.h>
+#include <data/fastfile.h>
#include <data/dictionary.h>
-#include <libpspp/message.h>
-#include <language/data-io/file-handle.h>
-#include <libpspp/hash.h>
-#include <language/lexer/lexer.h>
-#include <libpspp/misc.h>
#include <data/por-file-writer.h>
+#include <data/procedure.h>
#include <data/settings.h>
+#include <data/storage-stream.h>
#include <data/sys-file-writer.h>
-#include <libpspp/str.h>
+#include <data/transformations.h>
#include <data/value-labels.h>
#include <data/variable.h>
-#include <procedure.h>
+#include <language/command.h>
+#include <language/data-io/file-handle.h>
+#include <language/lexer/lexer.h>
+#include <language/lexer/variable-parser.h>
+#include <libpspp/alloc.h>
+#include <libpspp/assertion.h>
+#include <libpspp/compiler.h>
+#include <libpspp/hash.h>
+#include <libpspp/message.h>
+#include <libpspp/message.h>
+#include <libpspp/misc.h>
+#include <libpspp/str.h>
#include "gettext.h"
#define _(msgid) gettext (msgid)
const struct ccase *, struct ccase *);
static void destroy_case_map (struct case_map *);
-static bool parse_dict_trim (struct dictionary *);
+static bool parse_dict_trim (struct lexer *, struct dictionary *);
\f
/* Reading system and portable files. */
/* Parses a GET or IMPORT command. */
static int
-parse_read_command (enum reader_command type)
+parse_read_command (struct lexer *lexer, struct dataset *ds, enum reader_command type)
{
struct case_reader_pgm *pgm = NULL;
struct file_handle *fh = NULL;
for (;;)
{
- lex_match ('/');
+ lex_match (lexer, '/');
- if (lex_match_id ("FILE") || token == T_STRING)
+ if (lex_match_id (lexer, "FILE") || lex_token (lexer) == T_STRING)
{
- lex_match ('=');
+ lex_match (lexer, '=');
- fh = fh_parse (FH_REF_FILE | FH_REF_SCRATCH);
+ fh = fh_parse (lexer, FH_REF_FILE | FH_REF_SCRATCH);
if (fh == NULL)
goto error;
}
- else if (type == IMPORT_CMD && lex_match_id ("TYPE"))
+ else if (type == IMPORT_CMD && lex_match_id (lexer, "TYPE"))
{
- lex_match ('=');
+ lex_match (lexer, '=');
- if (lex_match_id ("COMM"))
+ if (lex_match_id (lexer, "COMM"))
type = PFM_COMM;
- else if (lex_match_id ("TAPE"))
+ else if (lex_match_id (lexer, "TAPE"))
type = PFM_TAPE;
else
{
- lex_error (_("expecting COMM or TAPE"));
+ lex_error (lexer, _("expecting COMM or TAPE"));
goto error;
}
}
if (fh == NULL)
{
- lex_sbc_missing ("FILE");
+ lex_sbc_missing (lexer, "FILE");
goto error;
}
- discard_variables ();
+ discard_variables (ds);
pgm = xmalloc (sizeof *pgm);
pgm->reader = any_reader_open (fh, &dict);
start_case_map (dict);
- while (token != '.')
+ while (lex_token (lexer) != '.')
{
- lex_match ('/');
- if (!parse_dict_trim (dict))
+ lex_match (lexer, '/');
+ if (!parse_dict_trim (lexer, dict))
goto error;
}
pgm->map = finish_case_map (dict);
- dict_destroy (default_dict);
- default_dict = dict;
+ dict_destroy (dataset_dict (ds));
+ dataset_set_dict (ds, dict);
- vfm_source = create_case_source (&case_reader_source_class, pgm);
+ proc_set_source (ds,
+ create_case_source (&case_reader_source_class, pgm));
return CMD_SUCCESS;
\f
/* GET. */
int
-cmd_get (void)
+cmd_get (struct lexer *lexer, struct dataset *ds)
{
- return parse_read_command (GET_CMD);
+ return parse_read_command (lexer, ds, GET_CMD);
}
/* IMPORT. */
int
-cmd_import (void)
+cmd_import (struct lexer *lexer, struct dataset *ds)
{
- return parse_read_command (IMPORT_CMD);
+ return parse_read_command (lexer, ds, IMPORT_CMD);
}
\f
/* Writing system and portable files. */
On failure, returns a null pointer. */
static struct case_writer *
-parse_write_command (enum writer_type writer_type,
+parse_write_command (struct lexer *lexer, struct dataset *ds,
+ enum writer_type writer_type,
enum command_type command_type,
bool *retain_unselected)
{
*retain_unselected = true;
handle = NULL;
- dict = dict_clone (default_dict);
+ dict = dict_clone (dataset_dict (ds));
aw = xmalloc (sizeof *aw);
aw->writer = NULL;
aw->map = NULL;
start_case_map (dict);
dict_delete_scratch_vars (dict);
- lex_match ('/');
+ lex_match (lexer, '/');
for (;;)
{
- if (lex_match_id ("OUTFILE"))
+ if (lex_match_id (lexer, "OUTFILE"))
{
if (handle != NULL)
{
goto error;
}
- lex_match ('=');
+ lex_match (lexer, '=');
- handle = fh_parse (FH_REF_FILE | FH_REF_SCRATCH);
+ handle = fh_parse (lexer, FH_REF_FILE | FH_REF_SCRATCH);
if (handle == NULL)
goto error;
}
- else if (lex_match_id ("NAMES"))
+ else if (lex_match_id (lexer, "NAMES"))
print_short_names = true;
- else if (lex_match_id ("PERMISSIONS"))
+ else if (lex_match_id (lexer, "PERMISSIONS"))
{
bool cw;
- lex_match ('=');
- if (lex_match_id ("READONLY"))
+ lex_match (lexer, '=');
+ if (lex_match_id (lexer, "READONLY"))
cw = false;
- else if (lex_match_id ("WRITEABLE"))
+ else if (lex_match_id (lexer, "WRITEABLE"))
cw = true;
else
{
- lex_error (_("expecting %s or %s"), "READONLY", "WRITEABLE");
+ lex_error (lexer, _("expecting %s or %s"), "READONLY", "WRITEABLE");
goto error;
}
sysfile_opts.create_writeable = porfile_opts.create_writeable = cw;
}
- else if (command_type == PROC_CMD && lex_match_id ("UNSELECTED"))
+ else if (command_type == PROC_CMD && lex_match_id (lexer, "UNSELECTED"))
{
- lex_match ('=');
- if (lex_match_id ("RETAIN"))
+ lex_match (lexer, '=');
+ if (lex_match_id (lexer, "RETAIN"))
*retain_unselected = true;
- else if (lex_match_id ("DELETE"))
+ else if (lex_match_id (lexer, "DELETE"))
*retain_unselected = false;
else
{
- lex_error (_("expecting %s or %s"), "RETAIN", "DELETE");
+ lex_error (lexer, _("expecting %s or %s"), "RETAIN", "DELETE");
goto error;
}
}
- else if (writer_type == SYSFILE_WRITER && lex_match_id ("COMPRESSED"))
+ else if (writer_type == SYSFILE_WRITER && lex_match_id (lexer, "COMPRESSED"))
sysfile_opts.compress = true;
- else if (writer_type == SYSFILE_WRITER && lex_match_id ("UNCOMPRESSED"))
+ else if (writer_type == SYSFILE_WRITER && lex_match_id (lexer, "UNCOMPRESSED"))
sysfile_opts.compress = false;
- else if (writer_type == SYSFILE_WRITER && lex_match_id ("VERSION"))
+ else if (writer_type == SYSFILE_WRITER && lex_match_id (lexer, "VERSION"))
{
- lex_match ('=');
- if (!lex_force_int ())
+ lex_match (lexer, '=');
+ if (!lex_force_int (lexer))
goto error;
- sysfile_opts.version = lex_integer ();
- lex_get ();
+ sysfile_opts.version = lex_integer (lexer);
+ lex_get (lexer);
}
- else if (writer_type == PORFILE_WRITER && lex_match_id ("TYPE"))
+ else if (writer_type == PORFILE_WRITER && lex_match_id (lexer, "TYPE"))
{
- lex_match ('=');
- if (lex_match_id ("COMMUNICATIONS"))
+ lex_match (lexer, '=');
+ if (lex_match_id (lexer, "COMMUNICATIONS"))
porfile_opts.type = PFM_COMM;
- else if (lex_match_id ("TAPE"))
+ else if (lex_match_id (lexer, "TAPE"))
porfile_opts.type = PFM_TAPE;
else
{
- lex_error (_("expecting %s or %s"), "COMM", "TAPE");
+ lex_error (lexer, _("expecting %s or %s"), "COMM", "TAPE");
goto error;
}
}
- else if (writer_type == PORFILE_WRITER && lex_match_id ("DIGITS"))
+ else if (writer_type == PORFILE_WRITER && lex_match_id (lexer, "DIGITS"))
{
- lex_match ('=');
- if (!lex_force_int ())
+ lex_match (lexer, '=');
+ if (!lex_force_int (lexer))
goto error;
- porfile_opts.digits = lex_integer ();
- lex_get ();
+ porfile_opts.digits = lex_integer (lexer);
+ lex_get (lexer);
}
- else if (!parse_dict_trim (dict))
+ else if (!parse_dict_trim (lexer, dict))
goto error;
- if (!lex_match ('/'))
+ if (!lex_match (lexer, '/'))
break;
}
- if (lex_end_of_command () != CMD_SUCCESS)
+ if (lex_end_of_command (lexer) != CMD_SUCCESS)
goto error;
if (handle == NULL)
{
- lex_sbc_missing ("OUTFILE");
+ lex_sbc_missing (lexer, "OUTFILE");
goto error;
}
}
else
aw->writer = any_writer_open (handle, dict);
+ if (aw->writer == NULL)
+ goto error;
dict_destroy (dict);
return aw;
/* Writes case C to writer AW. */
static bool
-case_writer_write_case (struct case_writer *aw, struct ccase *c)
+case_writer_write_case (struct case_writer *aw, const struct ccase *c)
{
if (aw->map != NULL)
{
\f
/* SAVE and EXPORT. */
-static bool output_proc (struct ccase *, void *);
+static bool output_proc (const struct ccase *, void *, const struct dataset *);
/* Parses and performs the SAVE or EXPORT procedure. */
static int
-parse_output_proc (enum writer_type writer_type)
+parse_output_proc (struct lexer *lexer, struct dataset *ds, enum writer_type writer_type)
{
bool retain_unselected;
struct variable *saved_filter_variable;
struct case_writer *aw;
bool ok;
- aw = parse_write_command (writer_type, PROC_CMD, &retain_unselected);
+ aw = parse_write_command (lexer, ds, writer_type, PROC_CMD, &retain_unselected);
if (aw == NULL)
return CMD_CASCADING_FAILURE;
- saved_filter_variable = dict_get_filter (default_dict);
+ saved_filter_variable = dict_get_filter (dataset_dict (ds));
if (retain_unselected)
- dict_set_filter (default_dict, NULL);
- ok = procedure (output_proc, aw);
- dict_set_filter (default_dict, saved_filter_variable);
+ dict_set_filter (dataset_dict (ds), NULL);
+ ok = procedure (ds, output_proc, aw);
+ dict_set_filter (dataset_dict (ds), saved_filter_variable);
case_writer_destroy (aw);
return ok ? CMD_SUCCESS : CMD_CASCADING_FAILURE;
/* Writes case C to file. */
static bool
-output_proc (struct ccase *c, void *aw_)
+output_proc (const struct ccase *c, void *aw_, const struct dataset *ds UNUSED)
{
struct case_writer *aw = aw_;
return case_writer_write_case (aw, c);
}
int
-cmd_save (void)
+cmd_save (struct lexer *lexer, struct dataset *ds)
{
- return parse_output_proc (SYSFILE_WRITER);
+ return parse_output_proc (lexer, ds, SYSFILE_WRITER);
}
int
-cmd_export (void)
+cmd_export (struct lexer *lexer, struct dataset *ds)
{
- return parse_output_proc (PORFILE_WRITER);
+ return parse_output_proc (lexer, ds, PORFILE_WRITER);
}
\f
/* XSAVE and XEXPORT. */
/* Parses the XSAVE or XEXPORT transformation command. */
static int
-parse_output_trns (enum writer_type writer_type)
+parse_output_trns (struct lexer *lexer, struct dataset *ds, enum writer_type writer_type)
{
struct output_trns *t = xmalloc (sizeof *t);
- t->aw = parse_write_command (writer_type, XFORM_CMD, NULL);
+ t->aw = parse_write_command (lexer, ds, writer_type, XFORM_CMD, NULL);
if (t->aw == NULL)
{
free (t);
return CMD_CASCADING_FAILURE;
}
- add_transformation (output_trns_proc, output_trns_free, t);
+ add_transformation (ds, output_trns_proc, output_trns_free, t);
return CMD_SUCCESS;
}
/* Writes case C to the system file specified on XSAVE or XEXPORT. */
static int
-output_trns_proc (void *trns_, struct ccase *c, int case_num UNUSED)
+output_trns_proc (void *trns_, struct ccase *c, casenumber case_num UNUSED)
{
struct output_trns *t = trns_;
case_writer_write_case (t->aw, c);
/* XSAVE command. */
int
-cmd_xsave (void)
+cmd_xsave (struct lexer *lexer, struct dataset *ds)
{
- return parse_output_trns (SYSFILE_WRITER);
+ return parse_output_trns (lexer, ds, SYSFILE_WRITER);
}
/* XEXPORT command. */
int
-cmd_xexport (void)
+cmd_xexport (struct lexer *lexer, struct dataset *ds)
{
- return parse_output_trns (PORFILE_WRITER);
+ return parse_output_trns (lexer, ds, PORFILE_WRITER);
}
\f
-static bool rename_variables (struct dictionary *dict);
-static bool drop_variables (struct dictionary *dict);
-static bool keep_variables (struct dictionary *dict);
+static bool rename_variables (struct lexer *lexer, struct dictionary *dict);
+static bool drop_variables (struct lexer *, struct dictionary *dict);
+static bool keep_variables (struct lexer *, struct dictionary *dict);
/* Commands that read and write system files share a great deal
of common syntactic structure for rearranging and dropping
variables. This function parses this syntax and modifies DICT
appropriately. Returns true on success, false on failure. */
static bool
-parse_dict_trim (struct dictionary *dict)
+parse_dict_trim (struct lexer *lexer, struct dictionary *dict)
{
- if (lex_match_id ("MAP"))
+ if (lex_match_id (lexer, "MAP"))
{
/* FIXME. */
return true;
}
- else if (lex_match_id ("DROP"))
- return drop_variables (dict);
- else if (lex_match_id ("KEEP"))
- return keep_variables (dict);
- else if (lex_match_id ("RENAME"))
- return rename_variables (dict);
+ else if (lex_match_id (lexer, "DROP"))
+ return drop_variables (lexer, dict);
+ else if (lex_match_id (lexer, "KEEP"))
+ return keep_variables (lexer, dict);
+ else if (lex_match_id (lexer, "RENAME"))
+ return rename_variables (lexer, dict);
else
{
- lex_error (_("expecting a valid subcommand"));
+ lex_error (lexer, _("expecting a valid subcommand"));
return false;
}
}
/* Parses and performs the RENAME subcommand of GET and SAVE. */
static bool
-rename_variables (struct dictionary *dict)
+rename_variables (struct lexer *lexer, struct dictionary *dict)
{
size_t i;
int group;
- lex_match ('=');
- if (token != '(')
+ lex_match (lexer, '=');
+ if (lex_token (lexer) != '(')
{
struct variable *v;
- v = parse_dict_variable (dict);
+ v = parse_variable (lexer, dict);
if (v == NULL)
return 0;
- if (!lex_force_match ('=')
- || !lex_force_id ())
+ if (!lex_force_match (lexer, '=')
+ || !lex_force_id (lexer))
return 0;
- if (dict_lookup_var (dict, tokid) != NULL)
+ if (dict_lookup_var (dict, lex_tokid (lexer)) != NULL)
{
msg (SE, _("Cannot rename %s as %s because there already exists "
"a variable named %s. To rename variables with "
"overlapping names, use a single RENAME subcommand "
"such as \"/RENAME (A=B)(B=C)(C=A)\", or equivalently, "
- "\"/RENAME (A B C=B C A)\"."), v->name, tokid, tokid);
+ "\"/RENAME (A B C=B C A)\"."),
+ var_get_name (v), lex_tokid (lexer), lex_tokid (lexer));
return 0;
}
- dict_rename_var (dict, v, tokid);
- lex_get ();
+ dict_rename_var (dict, v, lex_tokid (lexer));
+ lex_get (lexer);
return 1;
}
v = NULL;
new_names = 0;
group = 1;
- while (lex_match ('('))
+ while (lex_match (lexer, '('))
{
size_t old_nv = nv;
- if (!parse_variables (dict, &v, &nv, PV_NO_DUPLICATE | PV_APPEND))
+ if (!parse_variables (lexer, dict, &v, &nv, PV_NO_DUPLICATE | PV_APPEND))
goto done;
- if (!lex_match ('='))
+ if (!lex_match (lexer, '='))
{
msg (SE, _("`=' expected after variable list."));
goto done;
}
- if (!parse_DATA_LIST_vars (&new_names, &nn, PV_APPEND | PV_NO_SCRATCH))
+ if (!parse_DATA_LIST_vars (lexer, &new_names, &nn, PV_APPEND | PV_NO_SCRATCH))
goto done;
if (nn != nv)
{
(unsigned) (nv - old_nv), (unsigned) (nn - old_nv), group);
goto done;
}
- if (!lex_force_match (')'))
+ if (!lex_force_match (lexer, ')'))
goto done;
group++;
}
/* Parses and performs the DROP subcommand of GET and SAVE.
Returns true if successful, false on failure.*/
static bool
-drop_variables (struct dictionary *dict)
+drop_variables (struct lexer *lexer, struct dictionary *dict)
{
struct variable **v;
size_t nv;
- lex_match ('=');
- if (!parse_variables (dict, &v, &nv, PV_NONE))
+ lex_match (lexer, '=');
+ if (!parse_variables (lexer, dict, &v, &nv, PV_NONE))
return false;
dict_delete_vars (dict, v, nv);
free (v);
/* Parses and performs the KEEP subcommand of GET and SAVE.
Returns true if successful, false on failure.*/
static bool
-keep_variables (struct dictionary *dict)
+keep_variables (struct lexer *lexer, struct dictionary *dict)
{
struct variable **v;
size_t nv;
size_t i;
- lex_match ('=');
- if (!parse_variables (dict, &v, &nv, PV_NONE))
+ lex_match (lexer, '=');
+ if (!parse_variables (lexer, dict, &v, &nv, PV_NONE))
return false;
/* Move the specified variables to the beginning. */
char first[LONG_NAME_LEN + 1], last[LONG_NAME_LEN + 1];
struct dictionary *dict; /* Dictionary of output file. */
- struct case_sink *sink; /* Sink to receive output. */
+ struct casefile *output; /* MATCH FILES output. */
struct ccase mtf_case; /* Case used for output. */
unsigned seq_num; /* Have we initialized this variable? */
static bool mtf_delete_file_in_place (struct mtf_proc *, struct mtf_file **);
static bool mtf_read_nonactive_records (void *);
-static bool mtf_processing_finish (void *);
-static bool mtf_processing (struct ccase *, void *);
+static bool mtf_processing_finish (void *, const struct dataset *);
+static bool mtf_processing (const struct ccase *, void *, const struct dataset *);
static char *var_type_description (struct variable *);
/* Parse and execute the MATCH FILES command. */
int
-cmd_match_files (void)
+cmd_match_files (struct lexer *lexer, struct dataset *ds)
{
struct mtf_proc mtf;
struct mtf_file *first_table = NULL;
mtf.first[0] = '\0';
mtf.last[0] = '\0';
mtf.dict = dict_create ();
- mtf.sink = NULL;
+ mtf.output = NULL;
case_nullify (&mtf.mtf_case);
mtf.seq_num = 0;
mtf.seq_nums = NULL;
- dict_set_case_limit (mtf.dict, dict_get_case_limit (default_dict));
+ dict_set_case_limit (mtf.dict, dict_get_case_limit (dataset_dict (ds)));
- lex_match ('/');
- while (token == T_ID
- && (lex_id_match ("FILE", tokid) || lex_id_match ("TABLE", tokid)))
+ lex_match (lexer, '/');
+ while (lex_token (lexer) == T_ID
+ && (lex_id_match (ss_cstr ("FILE"), ss_cstr (lex_tokid (lexer)))
+ || lex_id_match (ss_cstr ("TABLE"), ss_cstr (lex_tokid (lexer)))))
{
struct mtf_file *file = xmalloc (sizeof *file);
- if (lex_match_id ("FILE"))
+ if (lex_match_id (lexer, "FILE"))
file->type = MTF_FILE;
- else if (lex_match_id ("TABLE"))
+ else if (lex_match_id (lexer, "TABLE"))
{
file->type = MTF_TABLE;
saw_table = true;
}
else
- assert (0);
- lex_match ('=');
+ NOT_REACHED ();
+ lex_match (lexer, '=');
file->by = NULL;
file->handle = NULL;
first_table->prev = file;
}
- if (lex_match ('*'))
+ if (lex_match (lexer, '*'))
{
file->handle = NULL;
file->reader = NULL;
}
used_active_file = true;
- assert (pgm_state != STATE_INPUT);
- if (pgm_state == STATE_INIT)
+ if (!proc_has_source (ds))
{
msg (SE, _("Cannot specify the active file since no active "
"file has been defined."));
goto error;
}
- if (temporary != 0)
- {
- msg (SE,
- _("MATCH FILES may not be used after TEMPORARY when "
- "the active file is an input source. "
- "Temporary transformations will be made permanent."));
- cancel_temporary ();
- }
+ if (proc_make_temporary_transformations_permanent (ds))
+ msg (SE,
+ _("MATCH FILES may not be used after TEMPORARY when "
+ "the active file is an input source. "
+ "Temporary transformations will be made permanent."));
- file->dict = default_dict;
+ file->dict = dataset_dict (ds);
}
else
{
- file->handle = fh_parse (FH_REF_FILE | FH_REF_SCRATCH);
+ file->handle = fh_parse (lexer, FH_REF_FILE | FH_REF_SCRATCH);
if (file->handle == NULL)
goto error;
case_create (&file->input, dict_get_next_value_idx (file->dict));
}
- while (lex_match ('/'))
- if (lex_match_id ("RENAME"))
+ while (lex_match (lexer, '/'))
+ if (lex_match_id (lexer, "RENAME"))
{
- if (!rename_variables (file->dict))
+ if (!rename_variables (lexer, file->dict))
goto error;
}
- else if (lex_match_id ("IN"))
+ else if (lex_match_id (lexer, "IN"))
{
- lex_match ('=');
- if (token != T_ID)
+ lex_match (lexer, '=');
+ if (lex_token (lexer) != T_ID)
{
- lex_error (NULL);
+ lex_error (lexer, NULL);
goto error;
}
"TABLE."));
goto error;
}
- file->in_name = xstrdup (tokid);
- lex_get ();
+ file->in_name = xstrdup (lex_tokid (lexer));
+ lex_get (lexer);
saw_in = true;
}
mtf_merge_dictionary (mtf.dict, file);
}
- while (token != '.')
+ while (lex_token (lexer) != '.')
{
- if (lex_match (T_BY))
+ if (lex_match (lexer, T_BY))
{
struct variable **by;
goto error;
}
- lex_match ('=');
- if (!parse_variables (mtf.dict, &by, &mtf.by_cnt,
+ lex_match (lexer, '=');
+ if (!parse_variables (lexer, mtf.dict, &by, &mtf.by_cnt,
PV_NO_DUPLICATE | PV_NO_SCRATCH))
goto error;
for (i = 0; i < mtf.by_cnt; i++)
{
- iter->by[i] = dict_lookup_var (iter->dict, by[i]->name);
+ iter->by[i] = dict_lookup_var (iter->dict,
+ var_get_name (by[i]));
if (iter->by[i] == NULL)
{
msg (SE, _("File %s lacks BY variable %s."),
iter->handle ? fh_get_name (iter->handle) : "*",
- by[i]->name);
+ var_get_name (by[i]));
free (by);
goto error;
}
}
free (by);
}
- else if (lex_match_id ("FIRST"))
+ else if (lex_match_id (lexer, "FIRST"))
{
if (mtf.first[0] != '\0')
{
goto error;
}
- lex_match ('=');
- if (!lex_force_id ())
+ lex_match (lexer, '=');
+ if (!lex_force_id (lexer))
goto error;
- strcpy (mtf.first, tokid);
- lex_get ();
+ strcpy (mtf.first, lex_tokid (lexer));
+ lex_get (lexer);
}
- else if (lex_match_id ("LAST"))
+ else if (lex_match_id (lexer, "LAST"))
{
if (mtf.last[0] != '\0')
{
goto error;
}
- lex_match ('=');
- if (!lex_force_id ())
+ lex_match (lexer, '=');
+ if (!lex_force_id (lexer))
goto error;
- strcpy (mtf.last, tokid);
- lex_get ();
+ strcpy (mtf.last, lex_tokid (lexer));
+ lex_get (lexer);
}
- else if (lex_match_id ("MAP"))
+ else if (lex_match_id (lexer, "MAP"))
{
/* FIXME. */
}
- else if (lex_match_id ("DROP"))
+ else if (lex_match_id (lexer, "DROP"))
{
- if (!drop_variables (mtf.dict))
+ if (!drop_variables (lexer, mtf.dict))
goto error;
}
- else if (lex_match_id ("KEEP"))
+ else if (lex_match_id (lexer, "KEEP"))
{
- if (!keep_variables (mtf.dict))
+ if (!keep_variables (lexer, mtf.dict))
goto error;
}
else
{
- lex_error (NULL);
+ lex_error (lexer, NULL);
goto error;
}
- if (!lex_match ('/') && token != '.')
+ if (!lex_match (lexer, '/') && lex_token (lexer) != '.')
{
- lex_end_of_command ();
+ lex_end_of_command (lexer);
goto error;
}
}
for (i = 0; i < dict_get_var_cnt (d); i++)
{
struct variable *v = dict_get_var (d, i);
- struct variable *mv = dict_lookup_var (mtf.dict, v->name);
+ struct variable *mv = dict_lookup_var (mtf.dict, var_get_name (v));
if (mv != NULL)
set_master (v, mv);
}
for (iter = mtf.head; iter != NULL; iter = iter->next)
if (iter->in_name != NULL)
{
+ struct fmt_spec format = fmt_for_output (FMT_F, 1, 0);
iter->in_var = dict_create_var (mtf.dict, iter->in_name, 0);
if (iter->in_var == NULL)
{
msg (SE, _("IN variable name %s duplicates an "
"existing variable name."),
- iter->in_var->name);
+ var_get_name (iter->in_var));
goto error;
}
- iter->in_var->print = iter->in_var->write
- = make_output_format (FMT_F, 1, 0);
+ var_set_both_formats (iter->in_var, &format);
}
/* MATCH FILES performs an n-way merge on all its input files.
values. */
if (!used_active_file)
- discard_variables ();
+ discard_variables (ds);
dict_compact_values (mtf.dict);
- mtf.sink = create_case_sink (&storage_sink_class, mtf.dict, NULL);
- if (mtf.sink->class->open != NULL)
- mtf.sink->class->open (mtf.sink);
-
+ mtf.output = fastfile_create (dict_get_next_value_idx (mtf.dict));
mtf.seq_nums = xcalloc (dict_get_var_cnt (mtf.dict), sizeof *mtf.seq_nums);
case_create (&mtf.mtf_case, dict_get_next_value_idx (mtf.dict));
goto error;
if (used_active_file)
- ok = procedure (mtf_processing, &mtf) && mtf_processing_finish (&mtf);
+ {
+ proc_set_sink (ds,
+ create_case_sink (&null_sink_class,
+ dataset_dict (ds), NULL));
+ ok =
+ ( procedure (ds, mtf_processing, &mtf) &&
+ mtf_processing_finish (&mtf, ds) );
+ }
else
- ok = mtf_processing_finish (&mtf);
+ ok = mtf_processing_finish (&mtf, ds);
- free_case_source (vfm_source);
- vfm_source = NULL;
+ discard_variables (ds);
- dict_destroy (default_dict);
- default_dict = mtf.dict;
+ dict_destroy (dataset_dict (ds));
+ dataset_set_dict (ds, mtf.dict);
mtf.dict = NULL;
- vfm_source = mtf.sink->class->make_source (mtf.sink);
- free_case_sink (mtf.sink);
+ proc_set_source (ds, storage_source_create (mtf.output));
+ mtf.output = NULL;
if (!mtf_free (&mtf))
ok = false;
/* Repeats 2...7 an arbitrary number of times. */
static bool
-mtf_processing_finish (void *mtf_)
+mtf_processing_finish (void *mtf_, const struct dataset *ds)
{
struct mtf_proc *mtf = mtf_;
struct mtf_file *iter;
if (iter->handle == NULL)
{
if (!mtf_delete_file_in_place (mtf, &iter))
- abort ();
+ NOT_REACHED ();
break;
}
while (mtf->head && mtf->head->type == MTF_FILE)
- if (!mtf_processing (NULL, mtf))
+ if (!mtf_processing (NULL, mtf, ds))
return false;
return true;
x ^= 1;
s = buf[x];
- if (v->type == NUMERIC)
+ if (var_is_numeric (v))
strcpy (s, "numeric");
else
- {
- assert (v->type == ALPHA);
- sprintf (s, "string with width %d", v->width);
- }
+ sprintf (s, "string with width %d", var_get_width (v));
return s;
}
{
union value *out = case_data_rw (&mtf->mtf_case, mv->fv);
- if (v->type == NUMERIC)
+ if (var_is_numeric (v))
out->f = SYSMIS;
else
- memset (out->s, ' ', v->width);
+ memset (out->s, ' ', var_get_width (v));
}
}
static inline int
mtf_compare_BY_values (struct mtf_proc *mtf,
struct mtf_file *a, struct mtf_file *b,
- struct ccase *c)
+ const struct ccase *c)
{
- struct ccase *ca = case_is_null (&a->input) ? c : &a->input;
- struct ccase *cb = case_is_null (&b->input) ? c : &b->input;
+ const struct ccase *ca = case_is_null (&a->input) ? c : &a->input;
+ const struct ccase *cb = case_is_null (&b->input) ? c : &b->input;
assert ((a == NULL) + (b == NULL) + (c == NULL) <= 1);
return case_compare_2dict (ca, cb, a->by, b->by, mtf->by_cnt);
}
/* Perform one iteration of steps 3...7 above.
Returns true if successful, false if an I/O error occurred. */
static bool
-mtf_processing (struct ccase *c, void *mtf_)
+mtf_processing (const struct ccase *c, void *mtf_, const struct dataset *ds UNUSED)
{
struct mtf_proc *mtf = mtf_;
if (mv != NULL && mtf->seq_nums[mv->index] != mtf->seq_num)
{
- struct ccase *record
+ const struct ccase *record
= case_is_null (&iter->input) ? c : &iter->input;
union value *out = case_data_rw (&mtf->mtf_case, mv->fv);
mtf->seq_nums[mv->index] = mtf->seq_num;
- if (v->type == NUMERIC)
+ if (var_is_numeric (v))
out->f = case_num (record, v->fv);
else
- memcpy (out->s, case_str (record, v->fv), v->width);
+ memcpy (out->s, case_str (record, v->fv),
+ var_get_width (v));
}
}
if (iter->in_var != NULL)
union value *out = case_data_rw (&mtf->mtf_case, mv->fv);
mtf->seq_nums[mv->index] = mtf->seq_num;
- if (v->type == NUMERIC)
+ if (var_is_numeric (v))
out->f = SYSMIS;
else
- memset (out->s, ' ', v->width);
+ memset (out->s, ' ', var_get_width (v));
}
}
if (iter->in_var != NULL)
}
/* 5. Write the output record. */
- mtf->sink->class->write (mtf->sink, &mtf->mtf_case);
+ casefile_append (mtf->output, &mtf->mtf_case);
/* 6. Read another record from each input file FILE and TABLE
that we stored values from above. If we come to the end of
for (i = 0; i < dict_get_var_cnt (d); i++)
{
struct variable *dv = dict_get_var (d, i);
- struct variable *mv = dict_lookup_var (m, dv->name);
+ struct variable *mv = dict_lookup_var (m, var_get_name (dv));
- if (dict_class_from_id (dv->name) == DC_SCRATCH)
+ if (dict_class_from_id (var_get_name (dv)) == DC_SCRATCH)
continue;
if (mv != NULL)
{
- if (mv->width != dv->width)
+ if (var_get_width (mv) != var_get_width (dv))
{
msg (SE, _("Variable %s in file %s (%s) has different "
"type or width from the same variable in "
"earlier file (%s)."),
- dv->name, fh_get_name (f->handle),
+ var_get_name (dv), fh_get_name (f->handle),
var_type_description (dv), var_type_description (mv));
return 0;
}
- if (dv->width == mv->width)
+ if (var_get_width (dv) == var_get_width (mv))
{
if (val_labs_count (dv->val_labs)
- && !val_labs_count (mv->val_labs))
- mv->val_labs = val_labs_copy (dv->val_labs);
- if (!mv_is_empty (&dv->miss) && mv_is_empty (&mv->miss))
- mv_copy (&mv->miss, &dv->miss);
+ && !val_labs_count (mv->val_labs))
+ {
+ val_labs_destroy (mv->val_labs);
+ mv->val_labs = val_labs_copy (dv->val_labs);
+ }
+ if (var_has_missing_values (dv) && !var_has_missing_values (mv))
+ var_set_missing_values (mv, var_get_missing_values (dv));
}
- if (dv->label && !mv->label)
- mv->label = xstrdup (dv->label);
+ if (var_get_label (dv) && !var_get_label (mv))
+ var_set_label (mv, var_get_label (dv));
}
else
- mv = dict_clone_var_assert (m, dv, dv->name);
+ mv = dict_clone_var_assert (m, dv, var_get_name (dv));
}
return 1;
for (i = 0; i < var_cnt; i++)
{
struct variable *v = dict_get_var (d, i);
+ size_t value_cnt = var_get_value_cnt (v);
int *src_fv = (int *) var_detach_aux (v);
size_t idx;
if (v->fv != *src_fv)
identity_map = 0;
- for (idx = 0; idx < v->nv; idx++)
+ for (idx = 0; idx < value_cnt; idx++)
{
int src_idx = *src_fv + idx;
int dst_idx = v->fv + idx;