From ab249f50e9f994b9a92a74b148f596f47fee0de9 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Sun, 14 Jun 2009 21:50:46 -0700 Subject: [PATCH] output: Make table dimension functions work in arbitrary contexts. Until now the function passed to tab_dim has only been called at the time that the table is passed to tab_submit. But in upcoming commits the table will be kept around and rendered possibly much later (by the GUI), so the function to tab_dim has to be sure to only use data that will exist at that time. Thus, this commit makes it possible to free the auxiliary data passed to that function, so that in the few cases where it needs to keep around extra data, it can do so without leaking memory. At the same time, convert the few functions that do need this feature to use it. --- src/language/data-io/data-parser.c | 4 +-- src/language/data-io/print.c | 2 +- src/language/dictionary/split-file.c | 2 +- src/language/dictionary/sys-file-info.c | 35 +++++++++++++++++-------- src/language/stats/binomial.c | 2 +- src/language/stats/chisquare.c | 6 ++--- src/language/stats/crosstabs.q | 29 ++++++++++++++++---- src/language/stats/descriptives.c | 4 +-- src/language/stats/examine.q | 8 +++--- src/language/stats/frequencies.q | 28 ++++++++++++++++---- src/language/stats/npar-summary.c | 2 +- src/language/stats/oneway.q | 10 +++---- src/language/stats/regression.q | 8 +++--- src/language/stats/reliability.q | 8 +++--- src/language/stats/sign.c | 4 +-- src/language/stats/t-test.q | 6 ++--- src/language/stats/wilcoxon.c | 4 +-- src/language/utilities/echo.c | 2 +- src/output/table.c | 20 +++++++++++--- src/output/table.h | 7 ++++- 20 files changed, 129 insertions(+), 62 deletions(-) diff --git a/src/language/data-io/data-parser.c b/src/language/data-io/data-parser.c index 2f503423..258a42a0 100644 --- a/src/language/data-io/data-parser.c +++ b/src/language/data-io/data-parser.c @@ -647,7 +647,7 @@ dump_fixed_table (const struct data_parser *parser, tab_text (t, 3, 0, TAB_CENTER | TAT_TITLE, _("Format")); tab_box (t, TAL_1, TAL_1, TAL_0, TAL_1, 0, 0, 3, parser->field_cnt); tab_hline (t, TAL_2, 0, 3, 1); - tab_dim (t, tab_natural_dimensions, NULL); + tab_dim (t, tab_natural_dimensions, NULL, NULL); for (i = 0; i < parser->field_cnt; i++) { @@ -686,7 +686,7 @@ dump_delimited_table (const struct data_parser *parser, tab_text (t, 1, 0, TAB_CENTER | TAT_TITLE, _("Format")); tab_box (t, TAL_1, TAL_1, TAL_0, TAL_1, 0, 0, 1, parser->field_cnt); tab_hline (t, TAL_2, 0, 1, 1); - tab_dim (t, tab_natural_dimensions, NULL); + tab_dim (t, tab_natural_dimensions, NULL, NULL); for (i = 0; i < parser->field_cnt; i++) { diff --git a/src/language/data-io/print.c b/src/language/data-io/print.c index aae8b38a..cb06dc64 100644 --- a/src/language/data-io/print.c +++ b/src/language/data-io/print.c @@ -404,7 +404,7 @@ dump_table (struct print_trns *trns, const struct file_handle *fh) tab_text (t, 1, 0, TAB_CENTER | TAT_TITLE, _("Record")); tab_text (t, 2, 0, TAB_CENTER | TAT_TITLE, _("Columns")); tab_text (t, 3, 0, TAB_CENTER | TAT_TITLE, _("Format")); - tab_dim (t, tab_natural_dimensions, NULL); + tab_dim (t, tab_natural_dimensions, NULL, NULL); row = 1; ll_for_each (spec, struct prt_out_spec, ll, &trns->specs) { diff --git a/src/language/dictionary/split-file.c b/src/language/dictionary/split-file.c index 155cfa12..62b67762 100644 --- a/src/language/dictionary/split-file.c +++ b/src/language/dictionary/split-file.c @@ -78,7 +78,7 @@ output_split_file_values (const struct dataset *ds, const struct ccase *c) return; t = tab_create (3, split_cnt + 1, 0); - tab_dim (t, tab_natural_dimensions, NULL); + tab_dim (t, tab_natural_dimensions, NULL, NULL); tab_vline (t, TAL_GAP, 1, 0, split_cnt); tab_vline (t, TAL_GAP, 2, 0, split_cnt); tab_text (t, 0, 0, TAB_NONE, _("Variable")); diff --git a/src/language/dictionary/sys-file-info.c b/src/language/dictionary/sys-file-info.c index 7672a380..1eeb9a37 100644 --- a/src/language/dictionary/sys-file-info.c +++ b/src/language/dictionary/sys-file-info.c @@ -161,11 +161,11 @@ cmd_sysfile_info (struct lexer *lexer, struct dataset *ds UNUSED) dict_get_encoding(d) ? dict_get_encoding(d) : _("Unknown")); - tab_dim (t, tab_natural_dimensions, NULL); + tab_dim (t, tab_natural_dimensions, NULL, NULL); tab_submit (t); t = tab_create (4, 1 + 2 * dict_get_var_cnt (d), 1); - tab_dim (t, sysfile_info_dim, NULL); + tab_dim (t, sysfile_info_dim, NULL, NULL); tab_headers (t, 0, 0, 1, 0); tab_text (t, 0, 0, TAB_LEFT | TAT_TITLE, _("Variable")); tab_joint_text (t, 1, 0, 2, 0, TAB_LEFT | TAT_TITLE, _("Description")); @@ -340,35 +340,45 @@ display_documents (const struct dictionary *dict) } } -static int _flags; +struct variables_dim_aux + { + int flags; + }; /* Sets the widths of all the columns and heights of all the rows in table T for driver D. */ static void -variables_dim (struct tab_rendering *r, void *aux UNUSED) +variables_dim (struct tab_rendering *r, void *aux_) { const struct outp_driver *d = r->driver; + struct variables_dim_aux *aux = aux_; tab_natural_dimensions (r, NULL); - if (_flags & (DF_VALUE_LABELS | DF_VARIABLE_LABELS | DF_MISSING_VALUES - | DF_AT_ATTRIBUTES | DF_ATTRIBUTES)) + if (aux->flags & (DF_VALUE_LABELS | DF_VARIABLE_LABELS | DF_MISSING_VALUES + | DF_AT_ATTRIBUTES | DF_ATTRIBUTES)) { r->w[1] = MAX (r->w[1], d->prop_em_width * 5); r->w[2] = MAX (r->w[2], d->prop_em_width * 35); } } +static void +variables_dim_free (void *aux_) +{ + struct variables_dim_aux *aux = aux_; + free (aux); +} + static void display_variables (const struct variable **vl, size_t n, int flags) { struct tab_table *t; + struct variables_dim_aux *aux; int nc; /* Number of columns. */ int pc; /* `Position column' */ int r; /* Current row. */ size_t i; - _flags = flags; - /* One column for the name, two columns for general description, one column for dictionary index. */ @@ -389,7 +399,10 @@ display_variables (const struct variable **vl, size_t n, int flags) ? _("Description") : _("Label"))); if (flags & DF_DICT_INDEX) tab_text (t, pc, 0, TAB_LEFT | TAT_TITLE, _("Position")); - tab_dim (t, variables_dim, NULL); + + aux = xmalloc (sizeof *aux); + aux->flags = flags; + tab_dim (t, variables_dim, variables_dim_free, aux); r = 1; for (i = 0; i < n; i++) @@ -479,7 +492,7 @@ display_data_file_attributes (struct attrset *set, int flags) tab_text (t, 1, 0, TAB_LEFT | TAT_TITLE, _("Value")); display_attributes (t, set, flags, 0, 1); tab_columns (t, TAB_COL_DOWN, 1); - tab_dim (t, tab_natural_dimensions, NULL); + tab_dim (t, tab_natural_dimensions, NULL, NULL); tab_title (t, "Custom data file attributes."); tab_submit (t); } @@ -706,7 +719,7 @@ display_vectors (const struct dictionary *dict, int sorted) t = tab_create (4, nrow + 1, 0); tab_headers (t, 0, 0, 1, 0); tab_columns (t, TAB_COL_DOWN, 1); - tab_dim (t, tab_natural_dimensions, NULL); + tab_dim (t, tab_natural_dimensions, NULL, NULL); tab_box (t, TAL_1, TAL_1, -1, -1, 0, 0, 3, nrow); tab_box (t, -1, -1, -1, TAL_1, 0, 0, 3, nrow); tab_hline (t, TAL_2, 0, 3, 1); diff --git a/src/language/stats/binomial.c b/src/language/stats/binomial.c index b44c5a6f..672bdbf3 100644 --- a/src/language/stats/binomial.c +++ b/src/language/stats/binomial.c @@ -189,7 +189,7 @@ binomial_execute (const struct dataset *ds, struct tab_table *table = tab_create (7, ost->n_vars * 3 + 1, 0); - tab_dim (table, tab_natural_dimensions, NULL); + tab_dim (table, tab_natural_dimensions, NULL, NULL); tab_title (table, _("Binomial Test")); diff --git a/src/language/stats/chisquare.c b/src/language/stats/chisquare.c index 4593df41..10ea0959 100644 --- a/src/language/stats/chisquare.c +++ b/src/language/stats/chisquare.c @@ -180,7 +180,7 @@ create_variable_frequency_table (const struct dictionary *dict, } table = tab_create(4, n_cells + 2, 0); - tab_dim (table, tab_natural_dimensions, NULL); + tab_dim (table, tab_natural_dimensions, NULL, NULL); tab_title (table, var_to_string(var)); tab_text (table, 1, 0, TAB_LEFT, _("Observed N")); @@ -216,7 +216,7 @@ create_combo_frequency_table (const struct chisquare_test *test) int n_cells = test->hi - test->lo + 1; table = tab_create(1 + ost->n_vars * 4, n_cells + 3, 0); - tab_dim (table, tab_natural_dimensions, NULL); + tab_dim (table, tab_natural_dimensions, NULL, NULL); tab_title (table, _("Frequencies")); for ( i = 0 ; i < ost->n_vars ; ++i ) @@ -272,7 +272,7 @@ create_stats_table (const struct chisquare_test *test) struct tab_table *table; table = tab_create (1 + ost->n_vars, 4, 0); - tab_dim (table, tab_natural_dimensions, NULL); + tab_dim (table, tab_natural_dimensions, NULL, NULL); tab_title (table, _("Test Statistics")); tab_headers (table, 1, 0, 1, 0); diff --git a/src/language/stats/crosstabs.q b/src/language/stats/crosstabs.q index 29ed67e4..76cae1b3 100644 --- a/src/language/stats/crosstabs.q +++ b/src/language/stats/crosstabs.q @@ -200,6 +200,12 @@ struct crosstabs_proc unsigned int statistics; /* Bit k is 1 if statistic k is requested. */ }; +/* Auxiliary data structure for tab_dim. */ +struct crosstabs_dim_aux + { + enum mv_class exclude; + }; + static void init_proc (struct crosstabs_proc *proc, struct dataset *ds) { @@ -912,7 +918,8 @@ static void display_symmetric (struct crosstabs_proc *, struct pivot_table *, static void display_risk (struct pivot_table *, struct tab_table *); static void display_directional (struct crosstabs_proc *, struct pivot_table *, struct tab_table *); -static void crosstabs_dim (struct tab_rendering *, void *proc); +static void crosstabs_dim (struct tab_rendering *, void *aux); +static void crosstabs_dim_free (void *aux); static void table_value_missing (struct crosstabs_proc *proc, struct tab_table *table, int c, int r, unsigned char opt, const union value *v, @@ -1343,6 +1350,7 @@ static void submit (struct crosstabs_proc *proc, struct pivot_table *pt, struct tab_table *t) { + struct crosstabs_dim_aux *aux; int i; if (t == NULL) @@ -1365,23 +1373,27 @@ submit (struct crosstabs_proc *proc, struct pivot_table *pt, tab_box (t, -1, -1, -1, TAL_GAP, 0, tab_t (t), tab_l (t) - 1, tab_nr (t) - 1); tab_vline (t, TAL_2, tab_l (t), 0, tab_nr (t) - 1); - tab_dim (t, crosstabs_dim, proc); + + aux = xmalloc (sizeof *aux); + aux->exclude = proc->exclude; + tab_dim (t, crosstabs_dim, crosstabs_dim_free, aux); + tab_submit (t); } /* Sets the widths of all the columns and heights of all the rows in table T for driver D. */ static void -crosstabs_dim (struct tab_rendering *r, void *proc_) +crosstabs_dim (struct tab_rendering *r, void *aux_) { const struct tab_table *t = r->table; struct outp_driver *d = r->driver; - struct crosstabs_proc *proc = proc_; + struct crosstabs_dim_aux *aux = aux_; int i; /* Width of a numerical column. */ int c = outp_string_width (d, "0.000000", OUTP_PROPORTIONAL); - if (proc->exclude == MV_NEVER) + if (aux->exclude == MV_NEVER) c += outp_string_width (d, "M", OUTP_PROPORTIONAL); /* Set width for header columns. */ @@ -1412,6 +1424,13 @@ crosstabs_dim (struct tab_rendering *r, void *proc_) r->h[i] = tab_natural_height (r, i); } +static void +crosstabs_dim_free (void *aux_) +{ + struct crosstabs_dim_aux *aux = aux_; + free (aux); +} + static bool find_crosstab (struct pivot_table *pt, size_t *row0p, size_t *row1p) { diff --git a/src/language/stats/descriptives.c b/src/language/stats/descriptives.c index 58144ceb..16869a18 100644 --- a/src/language/stats/descriptives.c +++ b/src/language/stats/descriptives.c @@ -560,7 +560,7 @@ dump_z_table (struct dsc_proc *dsc) tab_hline (t, TAL_2, 0, 1, 1); tab_text (t, 0, 0, TAB_CENTER | TAT_TITLE, _("Source")); tab_text (t, 1, 0, TAB_CENTER | TAT_TITLE, _("Target")); - tab_dim (t, tab_natural_dimensions, NULL); + tab_dim (t, tab_natural_dimensions, NULL, NULL); { size_t i, y; @@ -879,7 +879,7 @@ display (struct dsc_proc *dsc) tab_box (t, -1, -1, -1, TAL_1, 1, 0, nc - 1, dsc->var_cnt); tab_hline (t, TAL_2, 0, nc - 1, 1); tab_vline (t, TAL_2, 1, 0, dsc->var_cnt); - tab_dim (t, tab_natural_dimensions, NULL); + tab_dim (t, tab_natural_dimensions, NULL, NULL); nc = 0; tab_text (t, nc++, 0, TAB_LEFT | TAT_TITLE, _("Variable")); diff --git a/src/language/stats/examine.q b/src/language/stats/examine.q index a829112e..c0facb0b 100644 --- a/src/language/stats/examine.q +++ b/src/language/stats/examine.q @@ -1245,7 +1245,7 @@ show_summary (const struct variable **dependent_var, int n_dep_var, tbl = tab_create (n_cols, n_rows, 0); tab_headers (tbl, heading_columns, 0, heading_rows, 0); - tab_dim (tbl, tab_natural_dimensions, NULL); + tab_dim (tbl, tab_natural_dimensions, NULL, NULL); /* Outline the box */ tab_box (tbl, @@ -1482,7 +1482,7 @@ show_descriptives (const struct variable **dependent_var, tbl = tab_create (n_cols, n_rows, 0); tab_headers (tbl, heading_columns, 0, heading_rows, 0); - tab_dim (tbl, tab_natural_dimensions, NULL); + tab_dim (tbl, tab_natural_dimensions, NULL, NULL); /* Outline the box */ tab_box (tbl, @@ -1795,7 +1795,7 @@ show_extremes (const struct variable **dependent_var, tbl = tab_create (n_cols, n_rows, 0); tab_headers (tbl, heading_columns, 0, heading_rows, 0); - tab_dim (tbl, tab_natural_dimensions, NULL); + tab_dim (tbl, tab_natural_dimensions, NULL, NULL); /* Outline the box */ tab_box (tbl, @@ -2000,7 +2000,7 @@ show_percentiles (const struct variable **dependent_var, tbl = tab_create (n_cols, n_rows, 0); tab_headers (tbl, heading_columns, 0, heading_rows, 0); - tab_dim (tbl, tab_natural_dimensions, NULL); + tab_dim (tbl, tab_natural_dimensions, NULL, NULL); /* Outline the box */ tab_box (tbl, diff --git a/src/language/stats/frequencies.q b/src/language/stats/frequencies.q index 5a57ffa8..1fd98a30 100644 --- a/src/language/stats/frequencies.q +++ b/src/language/stats/frequencies.q @@ -997,19 +997,25 @@ compare_freq_alpha_d (const void *a_, const void *b_, const void *v_) /* Frequency table display. */ +struct full_dim_aux + { + bool show_labels; + }; + /* Sets the widths of all the columns and heights of all the rows in table T for driver D. */ static void -full_dim (struct tab_rendering *r, void *aux UNUSED) +full_dim (struct tab_rendering *r, void *aux_) { const struct outp_driver *d = r->driver; const struct tab_table *t = r->table; + const struct full_dim_aux *aux = aux_; int i; for (i = 0; i < t->nc; i++) { r->w[i] = tab_natural_width (r, i); - if (cmd.labels == FRQ_LABELS && i == 0) + if (aux->show_labels && i == 0) r->w[i] = MIN (r->w[i], d->prop_em_width * 15); else r->w[i] = MAX (r->w[i], d->prop_em_width * 8); @@ -1019,6 +1025,13 @@ full_dim (struct tab_rendering *r, void *aux UNUSED) r->h[i] = d->font_height; } +static void +full_dim_free (void *aux_) +{ + struct full_dim_aux *aux = aux_; + free (aux); +} + /* Displays a full frequency table for variable V. */ static void dump_full (const struct variable *v, const struct variable *wv) @@ -1059,12 +1072,17 @@ dump_full (const struct variable *v, const struct variable *wv) const bool lab = (cmd.labels == FRQ_LABELS); + struct full_dim_aux *aux; + vf = get_var_freqs (v); ft = &vf->tab; n_categories = ft->n_valid + ft->n_missing; t = tab_create (5 + lab, n_categories + 3, 0); tab_headers (t, 0, 0, 2, 0); - tab_dim (t, full_dim, NULL); + + aux = xmalloc (sizeof *aux); + aux->show_labels = lab; + tab_dim (t, full_dim, full_dim_free, aux); if (lab) tab_text (t, 0, 1, TAB_CENTER | TAT_TITLE, _("Value Label")); @@ -1181,7 +1199,7 @@ dump_condensed (const struct variable *v, const struct variable *wv) tab_text (t, 2, 1, TAB_CENTER | TAT_TITLE, _("Pct")); tab_text (t, 3, 0, TAB_CENTER | TAT_TITLE, _("Cum")); tab_text (t, 3, 1, TAB_CENTER | TAT_TITLE, _("Pct")); - tab_dim (t, condensed_dim, NULL); + tab_dim (t, condensed_dim, NULL, NULL); r = 2; for (f = ft->valid; f < ft->missing; f++) @@ -1380,7 +1398,7 @@ dump_statistics (const struct variable *v, bool show_varname, calc_stats (v, stat_value); t = tab_create (3, n_stats + n_percentiles + 2, 0); - tab_dim (t, tab_natural_dimensions, NULL); + tab_dim (t, tab_natural_dimensions, NULL, NULL); tab_box (t, TAL_1, TAL_1, -1, -1 , 0 , 0 , 2, tab_nr(t) - 1) ; diff --git a/src/language/stats/npar-summary.c b/src/language/stats/npar-summary.c index d626dffa..90a1b656 100644 --- a/src/language/stats/npar-summary.c +++ b/src/language/stats/npar-summary.c @@ -104,7 +104,7 @@ do_summary_box (const struct descriptives *desc, table = tab_create (columns, 2 + n_vars, 0); - tab_dim (table, tab_natural_dimensions, NULL); + tab_dim (table, tab_natural_dimensions, NULL, NULL); tab_title (table, _("Descriptive Statistics")); diff --git a/src/language/stats/oneway.q b/src/language/stats/oneway.q index 2c1c19e8..e1d5b79f 100644 --- a/src/language/stats/oneway.q +++ b/src/language/stats/oneway.q @@ -261,7 +261,7 @@ show_anova_table (void) t = tab_create (n_cols, n_rows, 0); tab_headers (t, 2, 0, 1, 0); - tab_dim (t, tab_natural_dimensions, NULL); + tab_dim (t, tab_natural_dimensions, NULL, NULL); tab_box (t, @@ -372,7 +372,7 @@ show_descriptives (const struct dictionary *dict) t = tab_create (n_cols, n_rows, 0); tab_headers (t, 2, 0, 2, 0); - tab_dim (t, tab_natural_dimensions, NULL); + tab_dim (t, tab_natural_dimensions, NULL, NULL); /* Put a frame around the entire box, and vertical lines inside */ @@ -518,7 +518,7 @@ show_homogeneity (void) t = tab_create (n_cols, n_rows, 0); tab_headers (t, 1, 0, 1, 0); - tab_dim (t, tab_natural_dimensions, NULL); + tab_dim (t, tab_natural_dimensions, NULL, NULL); /* Put a frame around the entire box, and vertical lines inside */ tab_box (t, @@ -578,7 +578,7 @@ show_contrast_coeffs (short *bad_contrast) t = tab_create (n_cols, n_rows, 0); tab_headers (t, 2, 0, 2, 0); - tab_dim (t, tab_natural_dimensions, NULL); + tab_dim (t, tab_natural_dimensions, NULL, NULL); /* Put a frame around the entire box, and vertical lines inside */ tab_box (t, @@ -663,7 +663,7 @@ show_contrast_tests (short *bad_contrast) t = tab_create (n_cols, n_rows, 0); tab_headers (t, 3, 0, 1, 0); - tab_dim (t, tab_natural_dimensions, NULL); + tab_dim (t, tab_natural_dimensions, NULL, NULL); /* Put a frame around the entire box, and vertical lines inside */ tab_box (t, diff --git a/src/language/stats/regression.q b/src/language/stats/regression.q index 05c08dfa..155ac3fd 100644 --- a/src/language/stats/regression.q +++ b/src/language/stats/regression.q @@ -150,7 +150,7 @@ reg_stats_r (pspp_linreg_cache * c) adjrsq = 1.0 - (1.0 - rsq) * (c->n_obs - 1.0) / (c->n_obs - c->n_indeps); std_error = sqrt (pspp_linreg_mse (c)); t = tab_create (n_cols, n_rows, 0); - tab_dim (t, tab_natural_dimensions, NULL); + tab_dim (t, tab_natural_dimensions, NULL, NULL); tab_box (t, TAL_2, TAL_2, -1, TAL_1, 0, 0, n_cols - 1, n_rows - 1); tab_hline (t, TAL_2, 0, n_cols - 1, 1); tab_vline (t, TAL_2, 2, 0, n_rows - 1); @@ -193,7 +193,7 @@ reg_stats_coeff (pspp_linreg_cache * c) t = tab_create (n_cols, n_rows, 0); tab_headers (t, 2, 0, 1, 0); - tab_dim (t, tab_natural_dimensions, NULL); + tab_dim (t, tab_natural_dimensions, NULL, NULL); tab_box (t, TAL_2, TAL_2, -1, TAL_1, 0, 0, n_cols - 1, n_rows - 1); tab_hline (t, TAL_2, 0, n_cols - 1, 1); tab_vline (t, TAL_2, 2, 0, n_rows - 1); @@ -290,7 +290,7 @@ reg_stats_anova (pspp_linreg_cache * c) assert (c != NULL); t = tab_create (n_cols, n_rows, 0); tab_headers (t, 2, 0, 1, 0); - tab_dim (t, tab_natural_dimensions, NULL); + tab_dim (t, tab_natural_dimensions, NULL, NULL); tab_box (t, TAL_2, TAL_2, -1, TAL_1, 0, 0, n_cols - 1, n_rows - 1); @@ -381,7 +381,7 @@ reg_stats_bcov (pspp_linreg_cache * c) n_rows = 2 * (c->n_indeps + 1); t = tab_create (n_cols, n_rows, 0); tab_headers (t, 2, 0, 1, 0); - tab_dim (t, tab_natural_dimensions, NULL); + tab_dim (t, tab_natural_dimensions, NULL, NULL); tab_box (t, TAL_2, TAL_2, -1, TAL_1, 0, 0, n_cols - 1, n_rows - 1); tab_hline (t, TAL_2, 0, n_cols - 1, 1); tab_vline (t, TAL_2, 2, 0, n_rows - 1); diff --git a/src/language/stats/reliability.q b/src/language/stats/reliability.q index 166a4dfa..52d8e3cb 100644 --- a/src/language/stats/reliability.q +++ b/src/language/stats/reliability.q @@ -383,7 +383,7 @@ run_reliability (struct casereader *input, struct dataset *ds, { struct tab_table *tab = tab_create(1, 1, 0); - tab_dim (tab, tab_natural_dimensions, NULL); + tab_dim (tab, tab_natural_dimensions, NULL, NULL); tab_flags (tab, SOMF_NO_TITLE ); tab_text(tab, 0, 0, TAT_PRINTF, "Scale: %s", ds_cstr (&rel->scale_name)); @@ -428,7 +428,7 @@ reliability_statistics (const struct reliability *rel) struct tab_table *tbl = tab_create (n_cols, n_rows, 0); tab_headers (tbl, heading_columns, 0, heading_rows, 0); - tab_dim (tbl, tab_natural_dimensions, NULL); + tab_dim (tbl, tab_natural_dimensions, NULL, NULL); tab_title (tbl, _("Reliability Statistics")); @@ -471,7 +471,7 @@ reliability_summary_total (const struct reliability *rel) struct tab_table *tbl = tab_create (n_cols, n_rows, 0); tab_headers (tbl, heading_columns, 0, heading_rows, 0); - tab_dim (tbl, tab_natural_dimensions, NULL); + tab_dim (tbl, tab_natural_dimensions, NULL, NULL); tab_title (tbl, _("Item-Total Statistics")); @@ -681,7 +681,7 @@ case_processing_summary (casenumber n_valid, casenumber n_missing, tbl = tab_create (n_cols, n_rows, 0); tab_headers (tbl, heading_columns, 0, heading_rows, 0); - tab_dim (tbl, tab_natural_dimensions, NULL); + tab_dim (tbl, tab_natural_dimensions, NULL, NULL); tab_title (tbl, _("Case Processing Summary")); diff --git a/src/language/stats/sign.c b/src/language/stats/sign.c index a5a27212..82b12659 100644 --- a/src/language/stats/sign.c +++ b/src/language/stats/sign.c @@ -57,7 +57,7 @@ output_frequency_table (const struct two_sample_test *t2s, const struct variable *wv = dict_get_weight (dict); const struct fmt_spec *wfmt = wv ? var_get_print_format (wv) : & F_8_0; - tab_dim (table, tab_natural_dimensions, NULL); + tab_dim (table, tab_natural_dimensions, NULL, NULL); tab_title (table, _("Frequencies")); @@ -110,7 +110,7 @@ output_statistics_table (const struct two_sample_test *t2s, int i; struct tab_table *table = tab_create (1 + t2s->n_pairs, 4, 0); - tab_dim (table, tab_natural_dimensions, NULL); + tab_dim (table, tab_natural_dimensions, NULL, NULL); tab_title (table, _("Test Statistics")); diff --git a/src/language/stats/t-test.q b/src/language/stats/t-test.q index c0a6f477..500e18ff 100644 --- a/src/language/stats/t-test.q +++ b/src/language/stats/t-test.q @@ -481,7 +481,7 @@ ssbox_base_init (struct ssbox *this, int cols, int rows) tab_headers (this->t, 0, 0, 1, 0); tab_box (this->t, TAL_2, TAL_2, TAL_0, TAL_1, 0, 0, cols - 1, rows - 1); tab_hline (this->t, TAL_2, 0, cols- 1, 1); - tab_dim (this->t, tab_natural_dimensions, NULL); + tab_dim (this->t, tab_natural_dimensions, NULL, NULL); } /* ssbox implementations. */ @@ -1071,7 +1071,7 @@ trbox_base_init (struct trbox *self, size_t data_rows, int cols) tab_headers (self->t, 0, 0, 3, 0); tab_box (self->t, TAL_2, TAL_2, TAL_0, TAL_0, 0, 0, cols - 1, rows - 1); tab_hline (self->t, TAL_2, 0, cols- 1, 3); - tab_dim (self->t, tab_natural_dimensions, NULL); + tab_dim (self->t, tab_natural_dimensions, NULL, NULL); } /* Base finalizer for the trbox */ @@ -1098,7 +1098,7 @@ pscbox (struct t_test_proc *proc) tab_box (table, TAL_2, TAL_2, TAL_0, TAL_1, 0, 0, cols - 1, rows - 1); tab_hline (table, TAL_2, 0, cols - 1, 1); tab_vline (table, TAL_2, 2, 0, rows - 1); - tab_dim (table, tab_natural_dimensions, NULL); + tab_dim (table, tab_natural_dimensions, NULL, NULL); tab_title (table, _("Paired Samples Correlations")); /* column headings */ diff --git a/src/language/stats/wilcoxon.c b/src/language/stats/wilcoxon.c index 37d2b191..ee14f7e6 100644 --- a/src/language/stats/wilcoxon.c +++ b/src/language/stats/wilcoxon.c @@ -227,7 +227,7 @@ show_ranks_box (const struct wilcoxon_state *ws, struct tab_table *table = tab_create (5, 1 + 4 * t2s->n_pairs, 0); - tab_dim (table, tab_natural_dimensions, NULL); + tab_dim (table, tab_natural_dimensions, NULL, NULL); tab_title (table, _("Ranks")); @@ -308,7 +308,7 @@ show_tests_box (const struct wilcoxon_state *ws, size_t i; struct tab_table *table = tab_create (1 + t2s->n_pairs, exact ? 5 : 3, 0); - tab_dim (table, tab_natural_dimensions, NULL); + tab_dim (table, tab_natural_dimensions, NULL, NULL); tab_title (table, _("Test Statistics")); diff --git a/src/language/utilities/echo.c b/src/language/utilities/echo.c index 19e9f9e5..05353f81 100644 --- a/src/language/utilities/echo.c +++ b/src/language/utilities/echo.c @@ -35,7 +35,7 @@ cmd_echo (struct lexer *lexer, struct dataset *ds UNUSED) tab = tab_create(1, 1, 0); - tab_dim (tab, tab_natural_dimensions, NULL); + tab_dim (tab, tab_natural_dimensions, NULL, NULL); tab_flags (tab, SOMF_NO_TITLE ); tab_text(tab, 0, 0, 0, ds_cstr (lex_tokstr (lexer))); diff --git a/src/output/table.c b/src/output/table.c index 480534e1..3cf6a3ae 100644 --- a/src/output/table.c +++ b/src/output/table.c @@ -91,6 +91,8 @@ void tab_destroy (struct tab_table *t) { assert (t != NULL); + if (t->dim_free != NULL) + t->dim_free (t->dim_aux); free (t->title); pool_destroy (t->container); } @@ -397,12 +399,22 @@ tab_title (struct tab_table *t, const char *title, ...) va_end (args); } -/* Set DIM_FUNC as the dimension function for table T. */ +/* Set DIM_FUNC, which will be passed auxiliary data AUX, as the + dimension function for table T. + + DIM_FUNC must not assume that it is called from the same + context as tab_dim; for example, table T might be kept in + memory and, thus, DIM_FUNC might be called after the currently + running command completes. If it is non-null, FREE_FUNC is + called when the table is destroyed, to allow any data + allocated for use by DIM_FUNC to be freed. */ void -tab_dim (struct tab_table *t, tab_dim_func *dim_func, void *aux) +tab_dim (struct tab_table *t, + tab_dim_func *dim_func, tab_dim_free_func *free_func, void *aux) { - assert (t != NULL && t->dim == NULL); + assert (t->dim == NULL); t->dim = dim_func; + t->dim_free = free_func; t->dim_aux = aux; } @@ -813,7 +825,7 @@ tab_output_text (int options, const char *buf, ...) tab_text (t, 0, 0, options & ~TAT_PRINTF, buf); tab_flags (t, SOMF_NO_TITLE | SOMF_NO_SPACING); - tab_dim (t, options & TAT_NOWRAP ? nowrap_dim : wrap_dim, NULL); + tab_dim (t, options & TAT_NOWRAP ? nowrap_dim : wrap_dim, NULL, NULL); tab_submit (t); free (tmp_buf); diff --git a/src/output/table.h b/src/output/table.h index 1ce69ab4..516db6a5 100644 --- a/src/output/table.h +++ b/src/output/table.h @@ -70,6 +70,7 @@ struct tab_table; struct tab_rendering; typedef void tab_dim_func (struct tab_rendering *, void *aux); +typedef void tab_dim_free_func (void *aux); /* A table. */ struct tab_table @@ -88,7 +89,10 @@ struct tab_table unsigned char *ct; /* Cell types; unsigned char[nr][nc]. */ unsigned char *rh; /* Horiz rules; unsigned char[nr+1][nc]. */ unsigned char *rv; /* Vert rules; unsigned char[nr][nc+1]. */ + + /* Calculating row and column dimensions. */ tab_dim_func *dim; /* Calculates cell widths and heights. */ + tab_dim_free_func *dim_free; /* Frees space allocated for dim function. */ void *dim_aux; /* Auxiliary data for dim function. */ /* Editing info. */ @@ -138,7 +142,8 @@ void tab_submit (struct tab_table *); tab_dim_func tab_natural_dimensions; int tab_natural_width (const struct tab_rendering *, int c); int tab_natural_height (const struct tab_rendering *, int r); -void tab_dim (struct tab_table *, tab_dim_func *, void *aux); +void tab_dim (struct tab_table *, + tab_dim_func *, tab_dim_free_func *, void *aux); /* Rules. */ void tab_hline (struct tab_table *, int style, int x1, int x2, int y); -- 2.30.2