X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Flanguage%2Fstats%2Faggregate.c;h=648e8896b64bd2b6c6f8ca8ed9e7bfb49e12ff4b;hb=19d0debdc5b72e1bb6c79956403a4d3bc054f300;hp=aef4bbbfa9555cf8ebd3a393773e383115f6126e;hpb=b74d09af5e07f954c18e7cdb8aca3af47fa10208;p=pspp-builds.git diff --git a/src/language/stats/aggregate.c b/src/language/stats/aggregate.c index aef4bbbf..648e8896 100644 --- a/src/language/stats/aggregate.c +++ b/src/language/stats/aggregate.c @@ -1,5 +1,5 @@ /* 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 . This program is free software; you can redistribute it and/or @@ -35,9 +35,10 @@ #include #include #include +#include #include #include -#include +#include #include #include #include @@ -45,6 +46,8 @@ #include #include +#include "minmax.h" + #include "gettext.h" #define _(msgid) gettext (msgid) @@ -145,6 +148,7 @@ struct agr_proc 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. */ }; @@ -153,25 +157,27 @@ static void initialize_aggregate_info (struct agr_proc *, const struct ccase *); /* Prototypes. */ -static int parse_aggregate_functions (struct agr_proc *); +static bool parse_aggregate_functions (struct lexer *, 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 (const 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 (const struct ccase *, void *aux); +static bool presorted_agr_to_sysfile (const struct ccase *, void *aux, const struct dataset *); /* Parsing. */ /* Parses and executes the AGGREGATE procedure. */ int -cmd_aggregate (void) +cmd_aggregate (struct lexer *lexer, struct dataset *ds) { + struct dictionary *dict = dataset_dict (ds); struct agr_proc agr; struct file_handle *out_file = NULL; @@ -184,16 +190,17 @@ cmd_aggregate (void) 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")) + if (!lex_force_match_id (lexer, "OUTFILE")) goto error; - lex_match ('='); - if (!lex_match ('*')) + lex_match (lexer, '='); + if (!lex_match (lexer, '*')) { - out_file = fh_parse (FH_REF_FILE | FH_REF_SCRATCH); + out_file = fh_parse (lexer, FH_REF_FILE | FH_REF_SCRATCH); if (out_file == NULL) goto error; } @@ -201,28 +208,28 @@ cmd_aggregate (void) /* Read most of the subcommands. */ for (;;) { - lex_match ('/'); + lex_match (lexer, '/'); - if (lex_match_id ("MISSING")) + if (lex_match_id (lexer, "MISSING")) { - lex_match ('='); - if (!lex_match_id ("COLUMNWISE")) + lex_match (lexer, '='); + if (!lex_match_id (lexer, "COLUMNWISE")) { - lex_error (_("while expecting COLUMNWISE")); + lex_error (lexer, _("while expecting COLUMNWISE")); goto error; } agr.missing = COLUMNWISE; } - else if (lex_match_id ("DOCUMENT")) + else if (lex_match_id (lexer, "DOCUMENT")) copy_documents = true; - else if (lex_match_id ("PRESORTED")) + else if (lex_match_id (lexer, "PRESORTED")) presorted = true; - else if (lex_match_id ("BREAK")) + else if (lex_match_id (lexer, "BREAK")) { int i; - lex_match ('='); - agr.sort = sort_parse_criteria (default_dict, + lex_match (lexer, '='); + agr.sort = sort_parse_criteria (lexer, dict, &agr.break_vars, &agr.break_var_cnt, &saw_direction, NULL); if (agr.sort == NULL) @@ -237,7 +244,7 @@ cmd_aggregate (void) } else { - lex_error (_("expecting BREAK")); + lex_error (lexer, _("expecting BREAK")); goto error; } } @@ -247,8 +254,8 @@ cmd_aggregate (void) "the same way as the input data.")); /* Read in the aggregate functions. */ - lex_match ('/'); - if (!parse_aggregate_functions (&agr)) + lex_match (lexer, '/'); + if (!parse_aggregate_functions (lexer, dict, &agr)) goto error; /* Delete documents. */ @@ -267,19 +274,21 @@ cmd_aggregate (void) { /* The active file will be replaced by the aggregated data, so TEMPORARY is moot. */ - proc_cancel_temporary_transformations (); + 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); - proc_set_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) { @@ -287,11 +296,12 @@ cmd_aggregate (void) if (!agr.sink->class->write (agr.sink, &agr.agr_case)) goto error; } - discard_variables (); - dict_destroy (default_dict); - default_dict = agr.dict; + discard_variables (ds); + dict_destroy (dict); + dataset_set_dict (ds, agr.dict); agr.dict = NULL; - proc_set_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 @@ -308,7 +318,7 @@ cmd_aggregate (void) 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); @@ -328,7 +338,7 @@ cmd_aggregate (void) else { /* Active file is already sorted. */ - if (!procedure (presorted_agr_to_sysfile, &agr)) + if (!procedure (ds, presorted_agr_to_sysfile, &agr)) goto error; } @@ -350,8 +360,8 @@ error: } /* Parse all the aggregate functions. */ -static int -parse_aggregate_functions (struct agr_proc *agr) +static bool +parse_aggregate_functions (struct lexer *lexer, const struct dictionary *dict, struct agr_proc *agr) { struct agr_var *tail; /* Tail of linked list starting at agr->vars. */ @@ -362,6 +372,7 @@ parse_aggregate_functions (struct agr_proc *agr) char **dest; char **dest_label; size_t n_dest; + struct string function_name; int include_missing; const struct agr_func *function; @@ -384,11 +395,11 @@ parse_aggregate_functions (struct agr_proc *agr) arg[1].c = NULL; /* Parse the list of target variables. */ - while (!lex_match ('=')) + while (!lex_match (lexer, '=')) { size_t n_dest_prev = n_dest; - if (!parse_DATA_LIST_vars (&dest, &n_dest, + if (!parse_DATA_LIST_vars (lexer, &dest, &n_dest, PV_APPEND | PV_SINGLE | PV_NO_SCRATCH)) goto error; @@ -400,42 +411,52 @@ parse_aggregate_functions (struct agr_proc *agr) for (j = n_dest_prev; j < n_dest; j++) dest_label[j] = NULL; } + + - if (token == T_STRING) + if (lex_token (lexer) == T_STRING) { - ds_truncate (&tokstr, 255); - dest_label[n_dest - 1] = ds_xstrdup (&tokstr); - lex_get (); + struct string label; + ds_init_string (&label, lex_tokstr (lexer)); + + ds_truncate (&label, 255); + dest_label[n_dest - 1] = ds_xstrdup (&label); + lex_get (lexer); + ds_destroy (&label); } } /* Get the name of the aggregation function. */ - if (token != T_ID) + if (lex_token (lexer) != T_ID) { - lex_error (_("expecting aggregation function")); + lex_error (lexer, _("expecting aggregation function")); goto error; } include_missing = 0; - if (tokid[strlen (tokid) - 1] == '.') - { + + ds_init_string (&function_name, lex_tokstr (lexer)); + + ds_chomp (&function_name, '.'); + + if (lex_tokid(lexer)[strlen (lex_tokid (lexer)) - 1] == '.') include_missing = 1; - tokid[strlen (tokid) - 1] = 0; - } - + for (function = agr_func_tab; function->name; function++) - if (!strcasecmp (function->name, tokid)) + if (!strcasecmp (function->name, ds_cstr (&function_name))) break; if (NULL == function->name) { - msg (SE, _("Unknown aggregation function %s."), tokid); + msg (SE, _("Unknown aggregation function %s."), + ds_cstr (&function_name)); goto error; } + ds_destroy (&function_name); func_index = function - agr_func_tab; - lex_get (); + lex_get (lexer); /* Check for leading lparen. */ - if (!lex_match ('(')) + if (!lex_match (lexer, '(')) { if (func_index == N) func_index = N_NO_VARS; @@ -443,7 +464,7 @@ parse_aggregate_functions (struct agr_proc *agr) func_index = NU_NO_VARS; else { - lex_error (_("expecting `('")); + lex_error (lexer, _("expecting `('")); goto error; } } @@ -458,7 +479,7 @@ parse_aggregate_functions (struct agr_proc *agr) else if (function->n_args) pv_opts |= PV_SAME_TYPE; - if (!parse_variables (default_dict, &src, &n_src, pv_opts)) + if (!parse_variables (lexer, dict, &src, &n_src, pv_opts)) goto error; } @@ -469,15 +490,15 @@ parse_aggregate_functions (struct agr_proc *agr) { int type; - lex_match (','); - if (token == T_STRING) + lex_match (lexer, ','); + if (lex_token (lexer) == T_STRING) { - arg[i].c = ds_xstrdup (&tokstr); + arg[i].c = ds_xstrdup (lex_tokstr (lexer)); type = ALPHA; } - else if (lex_is_number ()) + else if (lex_is_number (lexer)) { - arg[i].f = tokval; + arg[i].f = lex_tokval (lexer); type = NUMERIC; } else { msg (SE, _("Missing argument %d to %s."), i + 1, @@ -485,7 +506,7 @@ parse_aggregate_functions (struct agr_proc *agr) goto error; } - lex_get (); + lex_get (lexer); if (type != src[0]->type) { @@ -497,9 +518,9 @@ parse_aggregate_functions (struct agr_proc *agr) } /* Trailing rparen. */ - if (!lex_match(')')) + if (!lex_match (lexer, ')')) { - lex_error (_("expecting `)'")); + lex_error (lexer, _("expecting `)'")); goto error; } @@ -575,21 +596,24 @@ parse_aggregate_functions (struct agr_proc *agr) 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) @@ -638,17 +662,18 @@ parse_aggregate_functions (struct agr_proc *agr) free (dest); free (dest_label); - if (!lex_match ('/')) + if (!lex_match (lexer, '/')) { - if (token == '.') - return 1; + if (lex_token (lexer) == '.') + return true; - lex_error ("expecting end of command"); - return 0; + lex_error (lexer, "expecting end of command"); + return false; } continue; error: + ds_destroy (&function_name); for (i = 0; i < n_dest; i++) { free (dest[i]); @@ -666,7 +691,7 @@ parse_aggregate_functions (struct agr_proc *agr) } free (src); - return 0; + return false; } } @@ -712,9 +737,9 @@ static void accumulate_aggregate_info (struct agr_proc *, 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) { @@ -742,9 +767,9 @@ accumulate_aggregate_info (struct agr_proc *agr, { 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) @@ -786,7 +811,7 @@ accumulate_aggregate_info (struct agr_proc *agr, moments1_add (iter->moments, v->f, weight); break; case MAX: - iter->dbl[0] = max (iter->dbl[0], v->f); + iter->dbl[0] = MAX (iter->dbl[0], v->f); iter->int1 = 1; break; case MAX | FSTRING: @@ -795,7 +820,7 @@ accumulate_aggregate_info (struct agr_proc *agr, iter->int1 = 1; break; case MIN: - iter->dbl[0] = min (iter->dbl[0], v->f); + iter->dbl[0] = MIN (iter->dbl[0], v->f); iter->int1 = 1; break; case MIN | FSTRING: @@ -891,7 +916,7 @@ accumulate_aggregate_info (struct agr_proc *agr, caught earlier. Nothing to do. */ break; default: - assert (0); + NOT_REACHED (); } } else { switch (iter->function) @@ -903,7 +928,7 @@ accumulate_aggregate_info (struct agr_proc *agr, iter->int1++; break; default: - assert (0); + NOT_REACHED (); } } } @@ -1032,7 +1057,7 @@ dump_aggregate_info (struct agr_proc *agr, struct ccase *output) v->f = i->int1; break; default: - assert (0); + NOT_REACHED (); } } } @@ -1082,7 +1107,7 @@ initialize_aggregate_info (struct agr_proc *agr, const struct ccase *input) are dropped. Returns true if successful, false if an I/O error occurred. */ static bool -agr_to_active_file (const 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_; @@ -1095,7 +1120,8 @@ agr_to_active_file (const struct ccase *c, void *agr_) /* Aggregate the current case and output it if we passed a breakpoint. */ static bool -presorted_agr_to_sysfile (const 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_;