/* PSPP - computes sample statistics.
- Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
Written by Ben Pfaff <blp@gnu.org>.
This program is free software; you can redistribute it and/or
02110-1301, USA. */
#include <config.h>
-#include "message.h"
+
#include <stdlib.h>
-#include "alloc.h"
-#include "any-writer.h"
-#include "case.h"
-#include "casefile.h"
-#include "command.h"
-#include "dictionary.h"
-#include "message.h"
-#include "file-handle-def.h"
-#include "lexer.h"
-#include "misc.h"
-#include "moments.h"
-#include "pool.h"
-#include "settings.h"
-#include "sys-file-writer.h"
-#include "sort.h"
-#include "str.h"
-#include "variable.h"
-#include "procedure.h"
+
+#include <data/any-writer.h>
+#include <data/case-sink.h>
+#include <data/case.h>
+#include <data/casefile.h>
+#include <data/dictionary.h>
+#include <data/file-handle-def.h>
+#include <data/procedure.h>
+#include <data/settings.h>
+#include <data/storage-stream.h>
+#include <data/sys-file-writer.h>
+#include <data/variable.h>
+#include <language/command.h>
+#include <language/data-io/file-handle.h>
+#include <language/lexer/lexer.h>
+#include <language/lexer/variable-parser.h>
+#include <language/stats/sort-criteria.h>
+#include <libpspp/alloc.h>
+#include <libpspp/assertion.h>
+#include <libpspp/message.h>
+#include <libpspp/misc.h>
+#include <libpspp/pool.h>
+#include <libpspp/str.h>
+#include <math/moments.h>
+#include <math/sort.h>
#include "gettext.h"
#define _(msgid) gettext (msgid)
+/* Argument for AGGREGATE function. */
+union agr_argument
+ {
+ double f; /* Numeric. */
+ char *c; /* Short or long string. */
+ };
+
/* Specifies how to make an aggregate variable. */
struct agr_var
{
struct variable *dest; /* Target variable. */
int function; /* Function. */
int include_missing; /* 1=Include user-missing values. */
- union value arg[2]; /* Arguments. */
+ union agr_argument arg[2]; /* Arguments. */
/* Accumulated during AGGREGATE execution. */
double dbl[3];
enum missing_treatment missing; /* How to treat missing values. */
struct agr_var *agr_vars; /* First aggregate variable. */
struct dictionary *dict; /* Aggregate dictionary. */
+ const struct dictionary *src_dict; /* Dict of the source */
int case_cnt; /* Counts aggregated cases. */
struct ccase agr_case; /* Aggregate case for output. */
};
const struct ccase *);
/* Prototypes. */
-static int parse_aggregate_functions (struct agr_proc *);
+static bool parse_aggregate_functions (const struct dictionary *,
+ struct agr_proc *);
static void agr_destroy (struct agr_proc *);
-static int aggregate_single_case (struct agr_proc *agr,
- const struct ccase *input,
- struct ccase *output);
+static bool aggregate_single_case (struct agr_proc *agr,
+ const struct ccase *input,
+ struct ccase *output);
static void dump_aggregate_info (struct agr_proc *agr, struct ccase *output);
/* Aggregating to the active file. */
-static bool agr_to_active_file (struct ccase *, void *aux);
+static bool agr_to_active_file (const struct ccase *, void *aux, const struct dataset *);
/* Aggregating to a system file. */
-static bool presorted_agr_to_sysfile (struct ccase *, void *aux);
+static bool presorted_agr_to_sysfile (const struct ccase *, void *aux, const struct dataset *);
\f
/* Parsing. */
/* Parses and executes the AGGREGATE procedure. */
int
-cmd_aggregate (void)
+cmd_aggregate (struct dataset *ds)
{
+ struct dictionary *dict = dataset_dict (ds);
struct agr_proc agr;
struct file_handle *out_file = NULL;
case_nullify (&agr.break_case);
agr.dict = dict_create ();
- dict_set_label (agr.dict, dict_get_label (default_dict));
- dict_set_documents (agr.dict, dict_get_documents (default_dict));
+ agr.src_dict = dict;
+ dict_set_label (agr.dict, dict_get_label (dict));
+ dict_set_documents (agr.dict, dict_get_documents (dict));
/* OUTFILE subcommand must be first. */
if (!lex_force_match_id ("OUTFILE"))
int i;
lex_match ('=');
- agr.sort = sort_parse_criteria (default_dict,
+ agr.sort = sort_parse_criteria (dict,
&agr.break_vars, &agr.break_var_cnt,
&saw_direction, NULL);
if (agr.sort == NULL)
/* Read in the aggregate functions. */
lex_match ('/');
- if (!parse_aggregate_functions (&agr))
+ if (!parse_aggregate_functions (dict, &agr))
goto error;
/* Delete documents. */
{
/* The active file will be replaced by the aggregated data,
so TEMPORARY is moot. */
- cancel_temporary ();
+ proc_cancel_temporary_transformations (ds);
if (agr.sort != NULL && !presorted)
{
- if (!sort_active_file_in_place (agr.sort))
+ if (!sort_active_file_in_place (ds, agr.sort))
goto error;
}
agr.sink = create_case_sink (&storage_sink_class, agr.dict, NULL);
if (agr.sink->class->open != NULL)
agr.sink->class->open (agr.sink);
- vfm_sink = create_case_sink (&null_sink_class, default_dict, NULL);
- if (!procedure (agr_to_active_file, &agr))
+ proc_set_sink (ds,
+ create_case_sink (&null_sink_class,
+ dict, NULL));
+ if (!procedure (ds, agr_to_active_file, &agr))
goto error;
if (agr.case_cnt > 0)
{
if (!agr.sink->class->write (agr.sink, &agr.agr_case))
goto error;
}
- dict_destroy (default_dict);
- default_dict = agr.dict;
+ discard_variables (ds);
+ dict_destroy (dict);
+ dataset_set_dict (ds, agr.dict);
agr.dict = NULL;
- vfm_source = agr.sink->class->make_source (agr.sink);
+ proc_set_source (ds,
+ agr.sink->class->make_source (agr.sink));
free_case_sink (agr.sink);
}
else
struct ccase c;
bool ok = true;
- dst = sort_active_file_to_casefile (agr.sort);
+ dst = sort_active_file_to_casefile (ds, agr.sort);
if (dst == NULL)
goto error;
reader = casefile_get_destructive_reader (dst);
else
{
/* Active file is already sorted. */
- if (!procedure (presorted_agr_to_sysfile, &agr))
+ if (!procedure (ds, presorted_agr_to_sysfile, &agr))
goto error;
}
}
/* Parse all the aggregate functions. */
-static int
-parse_aggregate_functions (struct agr_proc *agr)
+static bool
+parse_aggregate_functions (const struct dictionary *dict, struct agr_proc *agr)
{
struct agr_var *tail; /* Tail of linked list starting at agr->vars. */
const struct agr_func *function;
int func_index;
- union value arg[2];
+ union agr_argument arg[2];
struct variable **src;
size_t n_src;
if (token == T_STRING)
{
ds_truncate (&tokstr, 255);
- dest_label[n_dest - 1] = xstrdup (ds_c_str (&tokstr));
+ dest_label[n_dest - 1] = ds_xstrdup (&tokstr);
lex_get ();
}
}
else if (function->n_args)
pv_opts |= PV_SAME_TYPE;
- if (!parse_variables (default_dict, &src, &n_src, pv_opts))
+ if (!parse_variables (dict, &src, &n_src, pv_opts))
goto error;
}
lex_match (',');
if (token == T_STRING)
{
- arg[i].c = xstrdup (ds_c_str (&tokstr));
+ arg[i].c = ds_xstrdup (&tokstr);
type = ALPHA;
}
else if (lex_is_number ())
|| (src[0]->type == ALPHA
&& str_compare_rpad (arg[0].c, arg[1].c) > 0)))
{
- union value t = arg[0];
+ union agr_argument t = arg[0];
arg[0] = arg[1];
arg[1] = t;
destvar = dict_create_var (agr->dict, dest[i], 0);
if (destvar != NULL)
{
+ struct fmt_spec f;
if ((func_index == N || func_index == NMISS)
- && dict_get_weight (default_dict) != NULL)
- destvar->print = destvar->write = f8_2;
+ && dict_get_weight (dict) != NULL)
+ f = fmt_for_output (FMT_F, 8, 2);
else
- destvar->print = destvar->write = function->format;
+ f = function->format;
+ destvar->print = destvar->write = f;
}
}
} else {
+ struct fmt_spec f;
v->src = NULL;
destvar = dict_create_var (agr->dict, dest[i], 0);
- if (func_index == N_NO_VARS
- && dict_get_weight (default_dict) != NULL)
- destvar->print = destvar->write = f8_2;
+ if (func_index == N_NO_VARS && dict_get_weight (dict) != NULL)
+ f = fmt_for_output (FMT_F, 8, 2);
else
- destvar->print = destvar->write = function->format;
+ f = function->format;
+ destvar->print = destvar->write = f;
}
if (!destvar)
}
free (dest[i]);
- destvar->init = 0;
if (dest_label[i])
{
destvar->label = dest_label[i];
if (!lex_match ('/'))
{
if (token == '.')
- return 1;
+ return true;
lex_error ("expecting end of command");
- return 0;
+ return false;
}
continue;
}
free (src);
- return 0;
+ return false;
}
}
static void dump_aggregate_info (struct agr_proc *, struct ccase *);
/* Processes a single case INPUT for aggregation. If output is
- warranted, writes it to OUTPUT and returns nonzero.
- Otherwise, returns zero and OUTPUT is unmodified. */
-static int
+ warranted, writes it to OUTPUT and returns true.
+ Otherwise, returns false and OUTPUT is unmodified. */
+static bool
aggregate_single_case (struct agr_proc *agr,
const struct ccase *input, struct ccase *output)
{
{
struct agr_var *iter;
double weight;
- int bad_warn = 1;
+ bool bad_warn = true;
- weight = dict_get_case_weight (default_dict, input, &bad_warn);
+ weight = dict_get_case_weight (agr->src_dict, input, &bad_warn);
for (iter = agr->agr_vars; iter; iter = iter->next)
if (iter->src)
caught earlier. Nothing to do. */
break;
default:
- assert (0);
+ NOT_REACHED ();
}
} else {
switch (iter->function)
iter->int1++;
break;
default:
- assert (0);
+ NOT_REACHED ();
}
}
}
v->f = i->int1;
break;
default:
- assert (0);
+ NOT_REACHED ();
}
}
}
are dropped.
Returns true if successful, false if an I/O error occurred. */
static bool
-agr_to_active_file (struct ccase *c, void *agr_)
+agr_to_active_file (const struct ccase *c, void *agr_, const struct dataset *ds UNUSED)
{
struct agr_proc *agr = agr_;
/* Aggregate the current case and output it if we passed a
breakpoint. */
static bool
-presorted_agr_to_sysfile (struct ccase *c, void *agr_)
+presorted_agr_to_sysfile (const struct ccase *c, void *agr_, const struct dataset *ds UNUSED)
{
struct agr_proc *agr = agr_;