X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Faggregate.c;h=4d00a34ad2cbb7404548762a0096f94b22f9e409;hb=37597beca4a11edba50b847932fdfeca3a648fa2;hp=dbfad40f6d4b2b79b938b6a83ed3c771bfa49b8d;hpb=312ad23d59e643e0c72e7ad684b00f3432461dee;p=pspp diff --git a/src/aggregate.c b/src/aggregate.c index dbfad40f6d..4d00a34ad2 100644 --- a/src/aggregate.c +++ b/src/aggregate.c @@ -26,6 +26,7 @@ #include "file-handle.h" #include "lexer.h" #include "misc.h" +#include "pool.h" #include "settings.h" #include "sfm.h" #include "sort.h" @@ -76,7 +77,7 @@ struct agr_func }; /* Attributes of aggregation functions. */ -static struct agr_func agr_func_tab[] = +static const struct agr_func agr_func_tab[] = { {"", 0, -1, {0, 0, 0}}, {"SUM", 0, -1, {FMT_F, 8, 2}}, @@ -116,6 +117,9 @@ enum /* ITEMWISE or COLUMNWISE. */ static int missing; +/* Sort program. */ +static struct sort_cases_pgm *sort; + /* Aggregate variables. */ static struct agr_var *agr_first, *agr_next; @@ -137,15 +141,16 @@ static void initialize_aggregate_info (void); /* Prototypes. */ static int parse_aggregate_functions (void); static void free_aggregate_functions (void); -static int aggregate_single_case (struct ccase *input, struct ccase *output); +static int aggregate_single_case (const struct ccase *input, + struct ccase *output); static int create_sysfile (void); -static int agr_00x_trns_proc (struct trns_header *, struct ccase *); -static void agr_00x_end_func (void *); -static int agr_10x_trns_proc (struct trns_header *, struct ccase *); -static void agr_10x_trns_free (struct trns_header *); +static trns_proc_func agr_00x_trns_proc, agr_10x_trns_proc; +static trns_free_func agr_10x_trns_free; +static void agr_00x_end_func (void *aux); static void agr_10x_end_func (void *); -static int agr_11x_func (write_case_data); +static read_sort_output_func agr_11x_read; +static void agr_11x_finish (void); #if DEBUGGING static void debug_print (int flags); @@ -157,15 +162,12 @@ static void debug_print (int flags); int cmd_aggregate (void) { - /* From sort.c. */ - int parse_sort_variables (void); - /* Have we seen these subcommands? */ unsigned seen = 0; outfile = NULL; missing = ITEMWISE; - v_sort = NULL; + sort = NULL; prev_case = NULL; agr_dict = dict_create (); @@ -183,7 +185,7 @@ cmd_aggregate (void) { if (seen & 1) { - free (v_sort); + destroy_sort_cases_pgm (sort); dict_destroy (agr_dict); msg (SE, _("%s subcommand given multiple times."),"OUTFILE"); return CMD_FAILURE; @@ -198,7 +200,7 @@ cmd_aggregate (void) outfile = fh_parse_file_handle (); if (outfile == NULL) { - free (v_sort); + destroy_sort_cases_pgm (sort); dict_destroy (agr_dict); return CMD_FAILURE; } @@ -209,7 +211,7 @@ cmd_aggregate (void) lex_match ('='); if (!lex_match_id ("COLUMNWISE")) { - free (v_sort); + destroy_sort_cases_pgm (sort); dict_destroy (agr_dict); lex_error (_("while expecting COLUMNWISE")); return CMD_FAILURE; @@ -224,7 +226,7 @@ cmd_aggregate (void) { if (seen & 8) { - free (v_sort); + destroy_sort_cases_pgm (sort); dict_destroy (agr_dict); msg (SE, _("%s subcommand given multiple times."),"BREAK"); return CMD_FAILURE; @@ -232,7 +234,8 @@ cmd_aggregate (void) seen |= 8; lex_match ('='); - if (!parse_sort_variables ()) + sort = parse_sort (); + if (sort == NULL) { dict_destroy (agr_dict); return CMD_FAILURE; @@ -241,11 +244,11 @@ cmd_aggregate (void) { int i; - for (i = 0; i < nv_sort; i++) + for (i = 0; i < sort->var_cnt; i++) { struct variable *v; - v = dict_clone_var (agr_dict, v_sort[i], v_sort[i]->name); + v = dict_clone_var (agr_dict, sort->vars[i], sort->vars[i]->name); assert (v != NULL); } } @@ -261,7 +264,7 @@ cmd_aggregate (void) if (!parse_aggregate_functions ()) { free_aggregate_functions (); - free (v_sort); + destroy_sort_cases_pgm (sort); return CMD_FAILURE; } @@ -312,7 +315,7 @@ cmd_aggregate (void) if (outfile != NULL) type |= 4; - if (nv_sort != 0 && (seen & 4) == 0) + if (sort != NULL && (seen & 4) == 0) type |= 2; if (temporary) type |= 1; @@ -323,7 +326,7 @@ cmd_aggregate (void) cancel_temporary (); /* fall through */ case 2: - sort_cases (0); + sort_cases (sort, 0); goto case0; case 1: @@ -366,20 +369,14 @@ cmd_aggregate (void) } case 6: - case 7: - sort_cases (1); + case 7: + sort_cases (sort, 1); if (!create_sysfile ()) goto lossage; - read_sort_output (agr_11x_func, NULL); - - { - struct ccase *save_temp_case = temp_case; - temp_case = NULL; - agr_11x_func (NULL); - temp_case = save_temp_case; - } - + read_sort_output (sort, agr_11x_read, NULL); + agr_11x_finish (); + break; default: @@ -391,7 +388,7 @@ cmd_aggregate (void) free (buf_1xx); /* Clean up. */ - free (v_sort); + destroy_sort_cases_pgm (sort); free_aggregate_functions (); free (prev_case); @@ -399,7 +396,7 @@ cmd_aggregate (void) lossage: /* Clean up. */ - free (v_sort); + destroy_sort_cases_pgm (sort); free_aggregate_functions (); free (prev_case); @@ -418,7 +415,7 @@ create_sysfile (void) if (!sfm_write_dictionary (&w)) { free_aggregate_functions (); - free (v_sort); + destroy_sort_cases_pgm (sort); dict_destroy (agr_dict); return 0; } @@ -443,7 +440,7 @@ parse_aggregate_functions (void) int n_dest; int include_missing; - struct agr_func *function; + const struct agr_func *function; int func_index; union value arg[2]; @@ -457,6 +454,7 @@ parse_aggregate_functions (void) dest_label = NULL; n_dest = 0; src = NULL; + function = NULL; n_src = 0; arg[0].c = NULL; arg[1].c = NULL; @@ -760,7 +758,7 @@ free_aggregate_functions (void) /* Execution. */ -static void accumulate_aggregate_info (struct ccase *input); +static void accumulate_aggregate_info (const struct ccase *input); static void dump_aggregate_info (struct ccase *output); /* Processes a single case INPUT for aggregation. If output is @@ -770,7 +768,7 @@ static void dump_aggregate_info (struct ccase *output); /* The code in this function has an eerie similarity to vfm.c:SPLIT_FILE_procfunc()... */ static int -aggregate_single_case (struct ccase *input, struct ccase *output) +aggregate_single_case (const struct ccase *input, struct ccase *output) { /* The first case always begins a new break group. We also need to preserve the values of the case for later comparison. */ @@ -781,8 +779,8 @@ aggregate_single_case (struct ccase *input, struct ccase *output) { int i; - for (i = 0; i < nv_sort; i++) - n_elem += v_sort[i]->nv; + for (i = 0; i < sort->var_cnt; i++) + n_elem += sort->vars[i]->nv; } prev_case = xmalloc (sizeof *prev_case * n_elem); @@ -792,9 +790,9 @@ aggregate_single_case (struct ccase *input, struct ccase *output) union value *iter = prev_case; int i; - for (i = 0; i < nv_sort; i++) + for (i = 0; i < sort->var_cnt; i++) { - struct variable *v = v_sort[i]; + struct variable *v = sort->vars[i]; if (v->type == NUMERIC) (iter++)->f = input->data[v->fv].f; @@ -817,9 +815,9 @@ aggregate_single_case (struct ccase *input, struct ccase *output) union value *iter = prev_case; int i; - for (i = 0; i < nv_sort; i++) + for (i = 0; i < sort->var_cnt; i++) { - struct variable *v = v_sort[i]; + struct variable *v = sort->vars[i]; switch (v->type) { @@ -856,9 +854,9 @@ not_equal: union value *iter = prev_case; int i; - for (i = 0; i < nv_sort; i++) + for (i = 0; i < sort->var_cnt; i++) { - struct variable *v = v_sort[i]; + struct variable *v = sort->vars[i]; if (v->type == NUMERIC) (iter++)->f = input->data[v->fv].f; @@ -875,7 +873,7 @@ not_equal: /* Accumulates aggregation data from the case INPUT. */ static void -accumulate_aggregate_info (struct ccase *input) +accumulate_aggregate_info (const struct ccase *input) { struct agr_var *iter; double weight; @@ -885,7 +883,7 @@ accumulate_aggregate_info (struct ccase *input) for (iter = agr_first; iter; iter = iter->next) if (iter->src) { - union value *v = &input->data[iter->src->fv]; + const union value *v = &input->data[iter->src->fv]; if ((!iter->include_missing && is_missing (v, iter->src)) || (iter->include_missing && iter->src->type == NUMERIC @@ -1050,8 +1048,8 @@ dump_aggregate_info (struct ccase *output) { int i; - for (i = 0; i < nv_sort; i++) - n_elem += v_sort[i]->nv; + for (i = 0; i < sort->var_cnt; i++) + n_elem += sort->vars[i]->nv; } debug_printf (("n_elem=%d:", n_elem)); memcpy (output->data, prev_case, sizeof (union value) * n_elem); @@ -1194,7 +1192,8 @@ initialize_aggregate_info (void) /* Aggregate each case as it comes through. Cases which aren't needed are dropped. */ static int -agr_00x_trns_proc (struct trns_header *h UNUSED, struct ccase *c) +agr_00x_trns_proc (struct trns_header *h UNUSED, struct ccase *c, + int case_num UNUSED) { int code = aggregate_single_case (c, compaction_case); debug_printf (("%d ", code)); @@ -1211,8 +1210,7 @@ agr_00x_end_func (void *aux UNUSED) /* Ensure that info for the last break group gets written to the active file. */ dump_aggregate_info (compaction_case); - vfm_sink_info.ncases++; - vfm_sink->write (); + vfm_sink->class->write (vfm_sink, compaction_case); } /* Transform the aggregate case buf_1xx, in internal format, to system @@ -1251,7 +1249,8 @@ write_case_to_sfm (void) /* Aggregate the current case and output it if we passed a breakpoint. */ static int -agr_10x_trns_proc (struct trns_header *h UNUSED, struct ccase *c) +agr_10x_trns_proc (struct trns_header *h UNUSED, struct ccase *c, + int case_num UNUSED) { int code = aggregate_single_case (c, buf_1xx); @@ -1277,31 +1276,30 @@ agr_10x_end_func (void *aux UNUSED) write_case_to_sfm (); } -/* When called with temp_case non-NULL (the normal case), runs the - case through the aggregater and outputs it to the system file if - appropriate. If temp_case is NULL, finishes up writing the last - case if necessary. */ +/* Runs case C through the aggregater and outputs it to the + system file if appropriate. */ static int -agr_11x_func (write_case_data wc_data UNUSED) +agr_11x_read (const struct ccase *c, void *aux UNUSED) { - if (temp_case != NULL) - { - int code = aggregate_single_case (temp_case, buf_1xx); + int code = aggregate_single_case (c, buf_1xx); - assert (code == -2 || code == -1); - if (code == -1) - write_case_to_sfm (); - } - else + assert (code == -2 || code == -1); + if (code == -1) + write_case_to_sfm (); + + return 1; +} + +/* Finishes up writing the last case if necessary. */ +static void +agr_11x_finish (void) +{ + if (case_count) { - if (case_count) - { - dump_aggregate_info (buf_1xx); - write_case_to_sfm (); - } - fh_close_handle (outfile); + dump_aggregate_info (buf_1xx); + write_case_to_sfm (); } - return 1; + fh_close_handle (outfile); } /* Debugging. */ @@ -1325,9 +1323,9 @@ debug_print (int flags) int i; printf (" /BREAK="); - for (i = 0; i < nv_sort; i++) - printf ("%s(%c) ", v_sort[i]->name, - v_sort[i]->p.srt.order == SRT_ASCEND ? 'A' : 'D'); + for (i = 0; i < sort->var_cnt; i++) + printf ("%s(%c) ", sort->vars[i]->name, + sort->vars[i]->p.srt.order == SRT_ASCEND ? 'A' : 'D'); putc ('\n', stdout); }