X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Flanguage%2Fstats%2Fexamine.q;h=9315e7e89bab621daeae47477ee2762a7b9341a5;hb=f6b8e421cd29ae0aef4018bbe2e1a06d0bef57df;hp=abbf9fc3890aada913b5b771fb57353d2362dd4d;hpb=9f650fc3d2946c216e6cd3c7922a8a63d0f97117;p=pspp diff --git a/src/language/stats/examine.q b/src/language/stats/examine.q index abbf9fc389..9315e7e89b 100644 --- a/src/language/stats/examine.q +++ b/src/language/stats/examine.q @@ -1,21 +1,18 @@ -/* PSPP - EXAMINE data for normality . -*-c-*- +/* PSPP - a program for statistical analysis. + Copyright (C) 2004 Free Software Foundation, Inc. -Copyright (C) 2004 Free Software Foundation, Inc. + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the -License, or (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301, USA. */ + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ #include @@ -26,7 +23,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA #include #include -#include +#include +#include #include #include #include @@ -34,10 +32,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA #include #include #include -#include #include #include -#include #include #include #include @@ -50,6 +46,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA #include #include "minmax.h" +#include "xalloc.h" #include "gettext.h" #define _(msgid) gettext (msgid) @@ -84,7 +81,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA static struct cmd_examine cmd; -static struct variable **dependent_vars; +static const struct variable **dependent_vars; static size_t n_dependent_vars; @@ -116,19 +113,19 @@ static int examine_parse_independent_vars (struct lexer *lexer, const struct dic /* Output functions */ -static void show_summary (struct variable **dependent_var, int n_dep_var, +static void show_summary (const struct variable **dependent_var, int n_dep_var, const struct factor *f); -static void show_extremes (struct variable **dependent_var, +static void show_extremes (const struct variable **dependent_var, int n_dep_var, const struct factor *factor, int n_extremities); -static void show_descriptives (struct variable **dependent_var, +static void show_descriptives (const struct variable **dependent_var, int n_dep_var, struct factor *factor); -static void show_percentiles (struct variable **dependent_var, +static void show_percentiles (const struct variable **dependent_var, int n_dep_var, struct factor *factor); @@ -152,28 +149,30 @@ void box_plot_variables (const struct factor *fctr, /* Per Split function */ -static bool run_examine (const struct ccase *, - const struct casefile *cf, void *cmd_, const struct dataset *); +static void run_examine (struct cmd_examine *, struct casereader *, + struct dataset *); static void output_examine (void); void factor_calc (const struct ccase *c, int case_no, - double weight, int case_missing); + double weight, bool case_missing); /* Represent a factor as a string, so it can be printed in a human readable fashion */ -const char * factor_to_string (const struct factor *fctr, +static void factor_to_string (const struct factor *fctr, const struct factor_statistics *fs, - const struct variable *var); - + const struct variable *var, + struct string *str + ); /* Represent a factor as a string, so it can be printed in a human readable fashion, but sacrificing some readablility for the sake of brevity */ -const char *factor_to_string_concise (const struct factor *fctr, - struct factor_statistics *fs); +static void factor_to_string_concise (const struct factor *fctr, + const struct factor_statistics *fs, + struct string *); @@ -193,6 +192,8 @@ static short sbc_percentile; int cmd_examine (struct lexer *lexer, struct dataset *ds) { + struct casegrouper *grouper; + struct casereader *group; bool ok; subc_list_double_create (&percentile_list); @@ -222,7 +223,11 @@ cmd_examine (struct lexer *lexer, struct dataset *ds) subc_list_double_push (&percentile_list, 75); } - ok = multipass_procedure_with_splits (ds, run_examine, &cmd); + grouper = casegrouper_create_splits (proc_open (ds), dataset_dict (ds)); + while (casegrouper_get_next_group (grouper, &group)) + run_examine (&cmd, group, ds); + ok = casegrouper_destroy (grouper); + ok = proc_commit (ds) && ok; if ( totals ) { @@ -367,10 +372,12 @@ output_examine (void) for ( fs = fctr->fs ; *fs ; ++fs ) { - const char *s = factor_to_string (fctr, *fs, dependent_vars[v]); + struct string str; + ds_init_empty (&str); + factor_to_string (fctr, *fs, dependent_vars[v], &str); if ( cmd.a_plot[XMN_PLT_NPPLOT] ) - np_plot (& (*fs)->m[v], s); + np_plot (& (*fs)->m[v], ds_cstr (&str)); if ( cmd.a_plot[XMN_PLT_HISTOGRAM] ) { @@ -381,9 +388,11 @@ output_examine (void) normal.stddev = (*fs)->m[v].stddev; histogram_plot ((*fs)->m[v].histogram, - s, &normal, 0); + ds_cstr (&str) , &normal, 0); } + ds_destroy (&str); + } /* for ( fs .... */ } /* for ( v = 0 ..... */ @@ -525,7 +534,7 @@ xmn_custom_variables (struct lexer *lexer, struct dataset *ds, struct cmd_examin return 2; } - if (!parse_variables (lexer, dict, &dependent_vars, &n_dependent_vars, + if (!parse_variables_const (lexer, dict, &dependent_vars, &n_dependent_vars, PV_NO_DUPLICATE | PV_NUMERIC | PV_NO_SCRATCH) ) { free (dependent_vars); @@ -627,13 +636,10 @@ void populate_summary (struct tab_table *t, int col, int row, -static bool bad_weight_warn = true; - - /* Perform calculations for the sub factors */ void factor_calc (const struct ccase *c, int case_no, double weight, - int case_missing) + bool case_missing) { size_t v; struct factor *fctr = factors; @@ -694,7 +700,7 @@ factor_calc (const struct ccase *c, int case_no, double weight, if (case_missing || var_is_value_missing (var, val, exclude_values)) { free (val); - continue; + val = NULL; } metrics_calc ( & (*foo)->m[v], val, weight, case_no); @@ -706,23 +712,31 @@ factor_calc (const struct ccase *c, int case_no, double weight, } } -static bool -run_examine (const struct ccase *first, const struct casefile *cf, - void *cmd_, const struct dataset *ds) +static void +run_examine (struct cmd_examine *cmd, struct casereader *input, + struct dataset *ds) { struct dictionary *dict = dataset_dict (ds); - struct casereader *r; + casenumber case_no; struct ccase c; int v; - - const struct cmd_examine *cmd = (struct cmd_examine *) cmd_; + bool ok; struct factor *fctr; - output_split_file_values (ds, first); + if (!casereader_peek (input, 0, &c)) + { + casereader_destroy (input); + return; + } + output_split_file_values (ds, &c); + case_destroy (&c); + + input = casereader_create_filter_weight (input, dict, NULL, NULL); + input = casereader_create_counter (input, &case_no, 0); /* Make sure we haven't got rubbish left over from a - previous split */ + previous split. */ fctr = factors; while (fctr) { @@ -738,15 +752,10 @@ run_examine (const struct ccase *first, const struct casefile *cf, for ( v = 0 ; v < n_dependent_vars ; ++v ) metrics_precalc (&totals[v]); - for (r = casefile_get_reader (cf, NULL); - casereader_read (r, &c) ; - case_destroy (&c) ) + for (; casereader_read (input, &c); case_destroy (&c)) { - int case_missing=0; - const int case_no = casereader_cnum (r); - - const double weight = - dict_get_case_weight (dict, &c, &bad_weight_warn); + bool case_missing = false; + const double weight = dict_get_case_weight (dict, &c, NULL); if ( cmd->miss == XMN_LISTWISE ) { @@ -759,7 +768,7 @@ run_examine (const struct ccase *first, const struct casefile *cf, ); if ( var_is_value_missing (var, val, exclude_values)) - case_missing = 1; + case_missing = true; free (val); } @@ -777,7 +786,7 @@ run_examine (const struct ccase *first, const struct casefile *cf, || case_missing ) { free (val) ; - continue ; + val = NULL; } metrics_calc (&totals[v], val, weight, case_no); @@ -787,6 +796,7 @@ run_examine (const struct ccase *first, const struct casefile *cf, factor_calc (&c, case_no, weight, case_missing); } + ok = casereader_destroy (input); for ( v = 0 ; v < n_dependent_vars ; ++v) { @@ -825,17 +835,17 @@ run_examine (const struct ccase *first, const struct casefile *cf, struct hsh_iterator hi1; struct factor_statistics *fs; - struct hsh_table *idh0=0; - struct hsh_table *idh1=0; - union value *val0; - union value *val1; + struct hsh_table *idh0 = NULL; + struct hsh_table *idh1 = NULL; + union value **val0; + union value **val1; - idh0 = hsh_create (4, (hsh_compare_func *) compare_values, - (hsh_hash_func *) hash_value, + idh0 = hsh_create (4, (hsh_compare_func *) compare_ptr_values, + (hsh_hash_func *) hash_ptr_value, 0,0); - idh1 = hsh_create (4, (hsh_compare_func *) compare_values, - (hsh_hash_func *) hash_value, + idh1 = hsh_create (4, (hsh_compare_func *) compare_ptr_values, + (hsh_hash_func *) hash_ptr_value, 0,0); @@ -843,8 +853,8 @@ run_examine (const struct ccase *first, const struct casefile *cf, fs != 0 ; fs = hsh_next (fctr->fstats, &hi)) { - hsh_insert (idh0, (void *) &fs->id[0]); - hsh_insert (idh1, (void *) &fs->id[1]); + hsh_insert (idh0, &fs->id[0]); + hsh_insert (idh1, &fs->id[1]); } /* Ensure that the factors combination is complete */ @@ -857,17 +867,17 @@ run_examine (const struct ccase *first, const struct casefile *cf, val1 = hsh_next (idh1, &hi1)) { struct factor_statistics **ffs; - union value key[2]; + union value *key[2]; key[0] = *val0; key[1] = *val1; ffs = (struct factor_statistics **) - hsh_probe (fctr->fstats, (void *) &key ); + hsh_probe (fctr->fstats, &key ); if ( !*ffs ) { size_t i; (*ffs) = create_factor_statistics (n_dependent_vars, - &key[0], &key[1]); + key[0], key[1]); for ( i = 0 ; i < n_dependent_vars ; ++i ) metrics_precalc ( & (*ffs)->m[i]); } @@ -882,7 +892,8 @@ run_examine (const struct ccase *first, const struct casefile *cf, fctr = fctr->next; } - output_examine (); + if (ok) + output_examine (); if ( totals ) @@ -893,13 +904,11 @@ run_examine (const struct ccase *first, const struct casefile *cf, metrics_destroy (&totals[i]); } } - - return true; } static void -show_summary (struct variable **dependent_var, int n_dep_var, +show_summary (const struct variable **dependent_var, int n_dep_var, const struct factor *fctr) { static const char *subtitle[]= @@ -966,7 +975,6 @@ show_summary (struct variable **dependent_var, int n_dep_var, tab_title (tbl, _ ("Case Processing Summary")); - tab_joint_text (tbl, heading_columns, 0, n_cols -1, 0, TAB_CENTER | TAT_TITLE, @@ -981,22 +989,21 @@ show_summary (struct variable **dependent_var, int n_dep_var, for ( i = 0 ; i < 3 ; ++i ) { - tab_text (tbl, heading_columns + i*2 , 2, TAB_CENTER | TAT_TITLE, + tab_text (tbl, heading_columns + i * 2 , 2, TAB_CENTER | TAT_TITLE, _ ("N")); - tab_text (tbl, heading_columns + i*2 + 1, 2, TAB_CENTER | TAT_TITLE, + tab_text (tbl, heading_columns + i * 2 + 1, 2, TAB_CENTER | TAT_TITLE, _ ("Percent")); tab_joint_text (tbl, heading_columns + i*2 , 1, - heading_columns + i*2 + 1, 1, + heading_columns + i * 2 + 1, 1, TAB_CENTER | TAT_TITLE, subtitle[i]); tab_box (tbl, -1, -1, TAL_0, TAL_0, - heading_columns + i*2, 1, - heading_columns + i*2 + 1, 1); - + heading_columns + i * 2, 1, + heading_columns + i * 2 + 1, 1); } @@ -1011,7 +1018,6 @@ show_summary (struct variable **dependent_var, int n_dep_var, tab_text (tbl, 2, heading_rows - 1, TAB_CENTER | TAT_TITLE, var_to_string (fctr->indep_var[1])); } - } @@ -1021,7 +1027,6 @@ show_summary (struct variable **dependent_var, int n_dep_var, if ( fctr ) n_factors = hsh_count (fctr->fstats); - if ( i > 0 ) tab_hline (tbl, TAL_1, 0, n_cols -1 , i * n_factors + heading_rows); @@ -1031,13 +1036,10 @@ show_summary (struct variable **dependent_var, int n_dep_var, var_to_string (dependent_var[i]) ); - if ( !fctr ) populate_summary (tbl, heading_columns, (i * n_factors) + heading_rows, &totals[i]); - - else { struct factor_statistics **fs = fctr->fs; @@ -1050,37 +1052,48 @@ show_summary (struct variable **dependent_var, int n_dep_var, 0 != compare_values (prev, (*fs)->id[0], var_get_width (fctr->indep_var[0]))) { + struct string vstr; + ds_init_empty (&vstr); + var_append_value_name (fctr->indep_var[0], + (*fs)->id[0], &vstr); + tab_text (tbl, 1, (i * n_factors ) + count + heading_rows, TAB_LEFT | TAT_TITLE, - var_get_value_name (fctr->indep_var[0], - (*fs)->id[0]) + ds_cstr (&vstr) ); + ds_destroy (&vstr); + if (fctr->indep_var[1] && count > 0 ) tab_hline (tbl, TAL_1, 1, n_cols - 1, (i * n_factors ) + count + heading_rows); - } prev = (*fs)->id[0]; - if ( fctr->indep_var[1]) - tab_text (tbl, - 2, - (i * n_factors ) + count + - heading_rows, - TAB_LEFT | TAT_TITLE, - var_get_value_name (fctr->indep_var[1], (*fs)->id[1]) - ); + { + struct string vstr; + ds_init_empty (&vstr); + var_append_value_name (fctr->indep_var[1], + (*fs)->id[1], &vstr); + tab_text (tbl, + 2, + (i * n_factors ) + count + + heading_rows, + TAB_LEFT | TAT_TITLE, + ds_cstr (&vstr) + ); + ds_destroy (&vstr); + } populate_summary (tbl, heading_columns, - (i * n_factors) + count - + heading_rows, - & (*fs)->m[i]); + (i * n_factors) + count + + heading_rows, + & (*fs)->m[i]); count++ ; fs++; @@ -1114,17 +1127,13 @@ populate_summary (struct tab_table *t, int col, int row, /* This seems a bit pointless !!! */ tab_text (t, col + 5, row + 0, TAB_RIGHT | TAT_PRINTF, "%2.0f%%", 100.0 * total / total ); - - } - - } static void -show_extremes (struct variable **dependent_var, int n_dep_var, +show_extremes (const struct variable **dependent_var, int n_dep_var, const struct factor *fctr, int n_extremities) { int i; @@ -1223,6 +1232,10 @@ show_extremes (struct variable **dependent_var, int n_dep_var, if ( !prev || 0 != compare_values (prev, (*fs)->id[0], var_get_width (fctr->indep_var[0]))) { + struct string vstr; + ds_init_empty (&vstr); + var_append_value_name (fctr->indep_var[0], + (*fs)->id[0], &vstr); if ( count > 0 ) tab_hline (tbl, TAL_1, 1, n_cols - 1, row); @@ -1230,9 +1243,10 @@ show_extremes (struct variable **dependent_var, int n_dep_var, tab_text (tbl, 1, row, TAB_LEFT | TAT_TITLE, - var_get_value_name (fctr->indep_var[0], - (*fs)->id[0]) + ds_cstr (&vstr) ); + + ds_destroy (&vstr); } prev = (*fs)->id[0]; @@ -1241,11 +1255,19 @@ show_extremes (struct variable **dependent_var, int n_dep_var, tab_hline (tbl, TAL_1, 2, n_cols - 1, row); if ( fctr->indep_var[1]) + { + struct string vstr; + ds_init_empty (&vstr); + var_append_value_name (fctr->indep_var[1], (*fs)->id[1], &vstr); + tab_text (tbl, 2, row, TAB_LEFT | TAT_TITLE, - var_get_value_name (fctr->indep_var[1], (*fs)->id[1]) + ds_cstr (&vstr) ); + ds_destroy (&vstr); + } + populate_extremes (tbl, heading_columns - 2, row, n_extremities, & (*fs)->m[i]); @@ -1361,7 +1383,7 @@ populate_extremes (struct tab_table *t, /* Show the descriptives table */ void -show_descriptives (struct variable **dependent_var, +show_descriptives (const struct variable **dependent_var, int n_dep_var, struct factor *fctr) { @@ -1461,6 +1483,10 @@ show_descriptives (struct variable **dependent_var, if ( !prev || 0 != compare_values (prev, (*fs)->id[0], var_get_width (fctr->indep_var[0]))) { + struct string vstr; + ds_init_empty (&vstr); + var_append_value_name (fctr->indep_var[0], + (*fs)->id[0], &vstr); if ( count > 0 ) tab_hline (tbl, TAL_1, 1, n_cols - 1, row); @@ -1468,9 +1494,10 @@ show_descriptives (struct variable **dependent_var, tab_text (tbl, 1, row, TAB_LEFT | TAT_TITLE, - var_get_value_name (fctr->indep_var[0], - (*fs)->id[0]) + ds_cstr (&vstr) ); + + ds_destroy (&vstr); } prev = (*fs)->id[0]; @@ -1479,11 +1506,19 @@ show_descriptives (struct variable **dependent_var, tab_hline (tbl, TAL_1, 2, n_cols - 1, row); if ( fctr->indep_var[1]) + { + struct string vstr; + ds_init_empty (&vstr); + var_append_value_name (fctr->indep_var[1], (*fs)->id[1], &vstr); + tab_text (tbl, 2, row, TAB_LEFT | TAT_TITLE, - var_get_value_name (fctr->indep_var[1], (*fs)->id[1]) + ds_cstr (&vstr) ); + ds_destroy (&vstr); + } + populate_descriptives (tbl, heading_columns - 2, row, & (*fs)->m[i]); @@ -1507,18 +1542,14 @@ show_descriptives (struct variable **dependent_var, } - - /* Fill in the descriptives data */ void populate_descriptives (struct tab_table *tbl, int col, int row, const struct metrics *m) { - - const double t = gsl_cdf_tdist_Qinv (1 - cmd.n_cinterval[0]/100.0/2.0, \ + const double t = gsl_cdf_tdist_Qinv ((1 - cmd.n_cinterval[0] / 100.0)/2.0, m->n -1); - tab_text (tbl, col, row, TAB_LEFT | TAT_TITLE, @@ -1747,12 +1778,14 @@ box_plot_variables (const struct factor *fctr, for ( fs = fctr->fs ; *fs ; ++fs ) { + struct string str; double y_min = DBL_MAX; double y_max = -DBL_MAX; struct chart *ch = chart_create (); - const char *s = factor_to_string (fctr, *fs, 0 ); + ds_init_empty (&str); + factor_to_string (fctr, *fs, 0, &str ); - chart_write_title (ch, s); + chart_write_title (ch, ds_cstr (&str)); for ( i = 0 ; i < n_vars ; ++i ) { @@ -1780,7 +1813,7 @@ box_plot_variables (const struct factor *fctr, } chart_submit (ch); - + ds_destroy (&str); } } @@ -1819,19 +1852,21 @@ box_plot_group (const struct factor *fctr, for ( fs = fctr->fs ; *fs ; ++fs ) { - - const char *s = factor_to_string_concise (fctr, *fs); - + struct string str; const double box_width = (ch->data_right - ch->data_left) / (n_factors * 2.0 ) ; const double box_centre = ( f++ * 2 + 1) * box_width + ch->data_left; + ds_init_empty (&str); + factor_to_string_concise (fctr, *fs, &str); + boxplot_draw_boxplot (ch, box_centre, box_width, & (*fs)->m[i], - s); + ds_cstr (&str)); + ds_destroy (&str); } } else if ( ch ) @@ -1947,7 +1982,7 @@ np_plot (const struct metrics *m, const char *factorname) /* Show the percentiles */ void -show_percentiles (struct variable **dependent_var, +show_percentiles (const struct variable **dependent_var, int n_dep_var, struct factor *fctr) { @@ -2088,6 +2123,11 @@ show_percentiles (struct variable **dependent_var, if ( !prev || 0 != compare_values (prev, (*fs)->id[0], var_get_width (fctr->indep_var[0]))) { + struct string vstr; + ds_init_empty (&vstr); + var_append_value_name (fctr->indep_var[0], + (*fs)->id[0], &vstr); + if ( count > 0 ) tab_hline (tbl, TAL_1, 1, n_cols - 1, row); @@ -2095,11 +2135,10 @@ show_percentiles (struct variable **dependent_var, tab_text (tbl, 1, row, TAB_LEFT | TAT_TITLE, - var_get_value_name (fctr->indep_var[0], - (*fs)->id[0]) + ds_cstr (&vstr) ); - + ds_destroy (&vstr); } prev = (*fs)->id[0]; @@ -2108,11 +2147,19 @@ show_percentiles (struct variable **dependent_var, tab_hline (tbl, TAL_1, 2, n_cols - 1, row); if ( fctr->indep_var[1]) + { + struct string vstr; + ds_init_empty (&vstr); + var_append_value_name (fctr->indep_var[1], (*fs)->id[1], &vstr); + tab_text (tbl, 2, row, TAB_LEFT | TAT_TITLE, - var_get_value_name (fctr->indep_var[1], (*fs)->id[1]) + ds_cstr (&vstr) ); + ds_destroy (&vstr); + } + populate_percentiles (tbl, n_heading_columns - 1, row, & (*fs)->m[i]); @@ -2193,67 +2240,58 @@ populate_percentiles (struct tab_table *tbl, int col, int row, } - - -const char * +static void factor_to_string (const struct factor *fctr, const struct factor_statistics *fs, - const struct variable *var) + const struct variable *var, + struct string *str + ) { - - static char buf1[100]; - char buf2[100]; - - strcpy (buf1,""); - if (var) - sprintf (buf1, "%s (",var_to_string (var) ); + ds_put_format (str, "%s (",var_to_string (var) ); - snprintf (buf2, 100, "%s = %s", - var_to_string (fctr->indep_var[0]), - var_get_value_name (fctr->indep_var[0], fs->id[0])); + ds_put_format (str, "%s = ", + var_to_string (fctr->indep_var[0])); - strcat (buf1, buf2); + var_append_value_name (fctr->indep_var[0], fs->id[0], str); if ( fctr->indep_var[1] ) { - sprintf (buf2, "; %s = %s)", - var_to_string (fctr->indep_var[1]), - var_get_value_name (fctr->indep_var[1], fs->id[1])); - strcat (buf1, buf2); + ds_put_format (str, "; %s = )", + var_to_string (fctr->indep_var[1])); + + var_append_value_name (fctr->indep_var[1], fs->id[1], str); } else { if ( var ) - strcat (buf1, ")"); + ds_put_cstr (str, ")"); } - - return buf1; } - -const char * +static void factor_to_string_concise (const struct factor *fctr, - struct factor_statistics *fs) + const struct factor_statistics *fs, + struct string *str + ) { - - static char buf[100]; - - char buf2[100]; - - snprintf (buf, 100, "%s", - var_get_value_name (fctr->indep_var[0], fs->id[0])); + var_append_value_name (fctr->indep_var[0], fs->id[0], str); if ( fctr->indep_var[1] ) { - sprintf (buf2, ",%s)", var_get_value_name (fctr->indep_var[1], - fs->id[1]) ); - strcat (buf, buf2); - } + ds_put_cstr (str, ","); + var_append_value_name (fctr->indep_var[1],fs->id[1], str); - return buf; + ds_put_cstr (str, ")"); + } } + +/* + Local Variables: + mode: c + End: +*/