From: Ben Pfaff Date: Fri, 9 Apr 2010 04:06:43 +0000 (-0700) Subject: Make "internal variables" part of a dictionary. X-Git-Tag: sav-api~323 X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?p=pspp;a=commitdiff_plain;h=844259de34f3b5ed9c1b4a024da63f96f4f2194e Make "internal variables" part of a dictionary. The "internal variables" created by var_create_internal() are somewhat of a nasty corner case in the PSPP dictionary and variable implementation, because they are the only variables that have a case index and dictionary index but do not belong to a dictionary. This commit fixes that wart, by putting internal variables in a dictionary that is used just for them. It adds an assertion to var_set_vardict() to ensure that this is now an invariant property. As part of the change, var_create_internal() is renamed dict_Create_internal_var() and moved to dictionary.c, since it fits better there. Also, a new function dict_destroy_internal_var() must now be used to destroy internal variables. The dictionary indexes of internal variables are no longer unique process-wide. A previous commit eliminated the dependencies on this property. --- diff --git a/src/data/dictionary.c b/src/data/dictionary.c index bca92dabe3..6e6ab1edb4 100644 --- a/src/data/dictionary.c +++ b/src/data/dictionary.c @@ -1474,4 +1474,52 @@ dict_var_display_width_changed (const struct variable *v) d->callbacks->var_display_width_changed (d, var_get_dict_index (v), d->cb_data); } } + +/* Dictionary used to contain "internal variables". */ +static struct dictionary *internal_dict; + +/* Create a variable of the specified WIDTH to be used for internal + calculations only. The variable is assigned case index CASE_IDX. */ +struct variable * +dict_create_internal_var (int case_idx, int width) +{ + if (internal_dict == NULL) + internal_dict = dict_create (); + + for (;;) + { + static int counter = INT_MAX / 2; + struct variable *var; + char name[64]; + + if (++counter == INT_MAX) + counter = INT_MAX / 2; + + sprintf (name, "$internal%d", counter); + var = dict_create_var (internal_dict, name, width); + if (var != NULL) + { + set_var_case_index (var, case_idx); + return var; + } + } +} + +/* Destroys VAR, which must have been created with + dict_create_internal_var(). */ +void +dict_destroy_internal_var (struct variable *var) +{ + if (var != NULL) + { + dict_delete_var (internal_dict, var); + /* Destroy internal_dict if it has no variables left, just so that + valgrind --leak-check --show-reachable won't show internal_dict. */ + if (dict_get_var_cnt (internal_dict) == 0) + { + dict_destroy (internal_dict); + internal_dict = NULL; + } + } +} diff --git a/src/data/dictionary.h b/src/data/dictionary.h index 780d5a9412..0b3c6cd273 100644 --- a/src/data/dictionary.h +++ b/src/data/dictionary.h @@ -154,10 +154,13 @@ struct attrset *dict_get_attributes (const struct dictionary *); void dict_set_attributes (struct dictionary *, const struct attrset *); bool dict_has_attributes (const struct dictionary *); - +/* Data encoding. */ void dict_set_encoding (struct dictionary *d, const char *enc); const char *dict_get_encoding (const struct dictionary *d); +/* Internal variables. */ +struct variable *dict_create_internal_var (int case_idx, int width); +void dict_destroy_internal_var (struct variable *); /* Functions to be called upon dictionary changes. */ struct dict_callbacks diff --git a/src/data/variable.c b/src/data/variable.c index 79925fa8cb..dd5e6152f3 100644 --- a/src/data/variable.c +++ b/src/data/variable.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2006, 2009 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2006, 2009, 2010 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 @@ -149,27 +149,6 @@ var_clone (const struct variable *old_var) return new_var; } -/* Create a variable of the specified WIDTH to be used for - internal calculations only. The variable is assigned a unique - dictionary index and a case index of CASE_IDX. */ -struct variable * -var_create_internal (int case_idx, int width) -{ - struct variable *v = var_create ("$internal", width); - struct vardict_info vdi; - static int counter = INT_MAX / 2; - - vdi.dict = NULL; - vdi.case_index = case_idx; - vdi.dict_index = counter++; - if (counter == INT_MAX) - counter = INT_MAX / 2; - - var_set_vardict (v, &vdi); - - return v; -} - /* Destroys variable V. V must not belong to a dictionary. If it does, use dict_delete_var instead. */ @@ -178,11 +157,7 @@ var_destroy (struct variable *v) { if (v != NULL) { - if (var_has_vardict (v)) - { - const struct vardict_info *vdi = var_get_vardict (v); - assert (vdi->dict == NULL); - } + assert (!var_has_vardict (v)); mv_destroy (&v->miss); cat_stored_values_destroy (v->obs_vals); var_clear_short_names (v); @@ -1075,6 +1050,7 @@ var_set_vardict (struct variable *v, const struct vardict_info *vardict) { assert (vardict->dict_index >= 0); assert (vardict->case_index >= 0); + assert (vardict->dict != NULL); v->vardict = *vardict; } diff --git a/src/data/variable.h b/src/data/variable.h index d730768e65..f1a4c8728a 100644 --- a/src/data/variable.h +++ b/src/data/variable.h @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2009 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2009, 2010 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 @@ -32,8 +32,6 @@ union value; struct variable *var_create (const char *name, int width); struct variable *var_clone (const struct variable *); void var_destroy (struct variable *); -struct variable *var_create_internal (int case_idx, int width); - /* Variable names. */ #define VAR_NAME_LEN 64 /* Maximum length of variable name, in bytes. */ diff --git a/src/language/stats/aggregate.c b/src/language/stats/aggregate.c index ba0650937d..b54ebf6376 100644 --- a/src/language/stats/aggregate.c +++ b/src/language/stats/aggregate.c @@ -711,8 +711,8 @@ agr_destroy (struct agr_proc *agr) else if (iter->function == SD) moments1_destroy (iter->moments); - var_destroy (iter->subject); - var_destroy (iter->weight); + dict_destroy_internal_var (iter->subject); + dict_destroy_internal_var (iter->weight); free (iter); } @@ -1105,10 +1105,10 @@ initialize_aggregate_info (struct agr_proc *agr, const struct ccase *input) proto = caseproto_add_width (proto, 0); if ( ! iter->subject) - iter->subject = var_create_internal (0, 0); + iter->subject = dict_create_internal_var (0, 0); if ( ! iter->weight) - iter->weight = var_create_internal (1, 0); + iter->weight = dict_create_internal_var (1, 0); subcase_init_var (&ordering, iter->subject, SC_ASCEND); iter->writer = sort_create_writer (&ordering, proto); diff --git a/src/language/stats/wilcoxon.c b/src/language/stats/wilcoxon.c index e1dab91c9f..197124cf60 100644 --- a/src/language/stats/wilcoxon.c +++ b/src/language/stats/wilcoxon.c @@ -1,5 +1,5 @@ /* Pspp - a program for statistical analysis. - Copyright (C) 2008, 2009 Free Software Foundation, Inc. + Copyright (C) 2008, 2009, 2010 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 @@ -88,7 +88,7 @@ wilcoxon_execute (const struct dataset *ds, struct wilcoxon_state *ws = xcalloc (sizeof (*ws), t2s->n_pairs); const struct variable *weight = dict_get_weight (dict); - struct variable *weightx = var_create_internal (WEIGHT_IDX, 0); + struct variable *weightx = dict_create_internal_var (WEIGHT_IDX, 0); struct caseproto *proto; input = @@ -108,8 +108,8 @@ wilcoxon_execute (const struct dataset *ds, struct subcase ordering; variable_pair *vp = &t2s->pairs[i]; - ws[i].sign = var_create_internal (0, 0); - ws[i].absdiff = var_create_internal (1, 0); + ws[i].sign = dict_create_internal_var (0, 0); + ws[i].absdiff = dict_create_internal_var (1, 0); r = casereader_create_filter_missing (r, *vp, 2, exclude, @@ -195,15 +195,15 @@ wilcoxon_execute (const struct dataset *ds, casereader_destroy (input); - var_destroy (weightx); + dict_destroy_internal_var (weightx); show_ranks_box (ws, t2s, dict); show_tests_box (ws, t2s, exact, timer); for (i = 0 ; i < t2s->n_pairs; ++i ) { - var_destroy (ws[i].sign); - var_destroy (ws[i].absdiff); + dict_destroy_internal_var (ws[i].sign); + dict_destroy_internal_var (ws[i].absdiff); } free (ws); diff --git a/src/math/interaction.c b/src/math/interaction.c index aa8826e01a..2f8da8ccaa 100644 --- a/src/math/interaction.c +++ b/src/math/interaction.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2009 Free Software Foundation, Inc. + Copyright (C) 2009, 2010 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 @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -84,14 +85,14 @@ interaction_variable_create (const struct variable **vars, int n_vars) width += var_get_width (vars[i]); } } - result->intr = var_create_internal (0, width); + result->intr = dict_create_internal_var (0, width); } return result; } void interaction_variable_destroy (struct interaction_variable *iv) { - var_destroy (iv->intr); + dict_destroy_internal_var (iv->intr); free (iv->members); free (iv); }