1 /* PSPP - computes sample statistics.
2 Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
3 Written by Ben Pfaff <blp@gnu.org>.
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
28 #include "file-handle.h"
35 #include "value-labels.h"
38 #include "debug-print.h"
40 /* Clear the default dictionary. Note: This is probably not what you
41 want to do. Use discard_variables() instead. */
43 clear_default_dict (void)
47 for (i = 0; i < default_dict.nvar; i++)
49 clear_variable (&default_dict, default_dict.var[i]);
50 free (default_dict.var[i]);
53 assert (default_dict.splits == NULL);
55 default_dict.nvar = 0;
57 default_dict.nval = 0;
58 default_handle = inline_file;
59 stop_weighting (&default_dict);
62 /* Discards all the current state in preparation for a data-input
63 command like DATA LIST or GET. */
65 discard_variables (void)
67 clear_default_dict ();
73 vfm_source->destroy_source ();
77 cancel_transformations ();
85 expr_free (process_if_expr);
86 process_if_expr = NULL;
90 pgm_state = STATE_INIT;
93 /* Find and return the variable in default_dict having name NAME, or
94 NULL if no such variable exists in default_dict. */
96 find_variable (const char *name)
98 return hsh_find (default_dict.name_tab, name);
101 /* Find and return the variable in dictionary D having name NAME, or
102 NULL if no such variable exists in D. */
104 find_dict_variable (const struct dictionary *d, const char *name)
106 return hsh_find (d->name_tab, name);
109 /* Creates a variable named NAME in dictionary DICT having type TYPE
110 (ALPHA or NUMERIC) and, if type==ALPHA, width WIDTH. Returns a
111 pointer to the newly created variable if successful. On failure
112 (which indicates that a variable having the specified name already
113 exists), returns NULL. */
115 create_variable (struct dictionary *dict, const char *name,
118 if (find_dict_variable (dict, name))
122 struct variable *new_var;
124 dict->var = xrealloc (dict->var, (dict->nvar + 1) * sizeof *dict->var);
125 new_var = dict->var[dict->nvar] = xmalloc (sizeof *new_var);
127 new_var->index = dict->nvar;
130 init_variable (dict, new_var, name, type, width);
137 /* For situations in which we know that there are no variables with an
138 identical name in the dictionary. */
140 force_create_variable (struct dictionary *dict, const char *name,
143 struct variable *new_var = create_variable (dict, name, type, width);
144 assert (new_var != NULL);
148 /* For situations in which we know that there are no variables with an
149 identical name in the dictionary. */
151 force_dup_variable (struct dictionary *dict, const struct variable *src,
154 struct variable *new_var = dup_variable (dict, src, name);
155 assert (new_var != NULL);
160 /* Delete variable V from DICT. It should only be used when there are
161 guaranteed to be absolutely NO REFERENCES to it, for instance in
162 the very same function that created it. */
164 delete_variable (struct dictionary *dict, struct variable *v)
168 clear_variable (dict, v);
170 for (i = v->index; i < dict->nvar; i++)
172 dict->var[i] = dict->var[i + 1];
173 dict->var[i]->index = i;
178 /* Initialize fields in variable V inside dictionary D with name NAME,
179 type TYPE, and width WIDTH. Initializes some other fields too. */
181 common_init_stuff (struct dictionary *dict, struct variable *v,
182 const char *name, int type, int width)
185 /* Avoid problems with overlap. */
186 strcpy (v->name, name);
188 hsh_force_insert (dict->name_tab, v);
191 v->left = name[0] == '#';
192 v->width = type == NUMERIC ? 0 : width;
193 v->miss_type = MISSING_NONE;
194 if (v->type == NUMERIC)
196 v->print.type = FMT_F;
202 v->print.type = FMT_A;
203 v->print.w = v->width;
209 /* Initialize (for the first time) a variable V in dictionary DICT
210 with name NAME, type TYPE, and width WIDTH. */
212 init_variable (struct dictionary *dict, struct variable *v, const char *name,
215 common_init_stuff (dict, v, name, type, width);
216 v->nv = type == NUMERIC ? 1 : DIV_RND_UP (width, 8);
220 v->val_labs = val_labs_create (width);
223 if (vfm_source == &input_program_source
224 || vfm_source == &file_type_source)
226 size_t nbytes = DIV_RND_UP (v->fv + 1, 4);
229 if (inp_init_size < nbytes)
231 inp_init = xrealloc (inp_init, nbytes);
232 memset (&inp_init[inp_init_size], 0, nbytes - inp_init_size);
233 inp_init_size = nbytes;
236 if (v->type == ALPHA)
240 inp_init[v->fv / 4] |= val << ((unsigned) (v->fv) % 4 * 2);
244 /* Replace variable V in default_dict with a different variable having
245 name NAME, type TYPE, and width WIDTH. */
247 replace_variable (struct variable *v, const char *name, int type, int width)
251 assert (v && name && (type == NUMERIC || type == ALPHA) && width >= 0
252 && (type == ALPHA || width == 0));
253 clear_variable (&default_dict, v);
254 common_init_stuff (&default_dict, v, name, type, width);
256 nv = (type == NUMERIC) ? 1 : DIV_RND_UP (width, 8);
260 v->fv = default_dict.nval;
261 default_dict.nval += nv;
266 /* Changes the name of variable V in dictionary DICT to name NEW_NAME.
267 NEW_NAME must be known not to already exist in dictionary DICT. */
269 rename_variable (struct dictionary * dict, struct variable *v,
270 const char *new_name)
272 assert (dict && dict->name_tab && v && new_name);
273 hsh_delete (dict->name_tab, v);
274 strncpy (v->name, new_name, 9);
275 hsh_force_insert (dict->name_tab, v);
278 /* Delete the contents of variable V within dictionary DICT. Does not
279 remove the variable from the vector of variables in the dictionary.
282 clear_variable (struct dictionary *dict, struct variable *v)
284 assert (dict != NULL);
287 if (dict->name_tab != NULL)
288 hsh_force_delete (dict->name_tab, v);
290 val_labs_clear (v->val_labs);
300 struct variable **iter, **trailer;
302 for (trailer = iter = dict->splits; *iter; iter++)
310 if (dict->n_splits == 0)
318 /* Creates a new variable in dictionary DICT, whose properties are
319 copied from variable SRC, and returns a pointer to the new variable
320 of name NAME, if successful. If unsuccessful (which only happens
321 if a variable of the same name NAME exists in DICT), returns
324 dup_variable (struct dictionary *dict, const struct variable *src,
327 if (find_dict_variable (dict, name))
331 struct variable *new_var;
333 dict->var = xrealloc (dict->var, (dict->nvar + 1) * sizeof *dict->var);
334 new_var = dict->var[dict->nvar] = xmalloc (sizeof *new_var);
336 new_var->index = dict->nvar;
338 new_var->get.fv = -1;
339 new_var->get.nv = -1;
342 copy_variable (new_var, src);
344 assert (new_var->nv >= 0);
345 new_var->fv = dict->nval;
346 dict->nval += new_var->nv;
348 strcpy (new_var->name, name);
349 hsh_force_insert (dict->name_tab, new_var);
356 /* Return nonzero only if X is a user-missing value for numeric
359 is_num_user_missing (double x, const struct variable *v)
361 switch (v->miss_type)
366 return approx_eq (x, v->missing[0].f);
368 return (approx_eq (x, v->missing[0].f)
369 || approx_eq (x, v->missing[1].f));
371 return (approx_eq (x, v->missing[0].f)
372 || approx_eq (x, v->missing[1].f)
373 || approx_eq (x, v->missing[2].f));
375 return (approx_ge (x, v->missing[0].f)
376 && approx_le (x, v->missing[1].f));
378 return approx_le (x, v->missing[0].f);
380 return approx_ge (x, v->missing[0].f);
381 case MISSING_RANGE_1:
382 return ((approx_ge (x, v->missing[0].f)
383 && approx_le (x, v->missing[1].f))
384 || approx_eq (x, v->missing[2].f));
386 return (approx_le (x, v->missing[0].f)
387 || approx_eq (x, v->missing[1].f));
389 return (approx_ge (x, v->missing[0].f)
390 || approx_eq (x, v->missing[1].f));
397 /* Return nonzero only if string S is a user-missing variable for
398 string variable V. */
400 is_str_user_missing (const unsigned char s[], const struct variable *v)
402 switch (v->miss_type)
407 return !strncmp (s, v->missing[0].s, v->width);
409 return (!strncmp (s, v->missing[0].s, v->width)
410 || !strncmp (s, v->missing[1].s, v->width));
412 return (!strncmp (s, v->missing[0].s, v->width)
413 || !strncmp (s, v->missing[1].s, v->width)
414 || !strncmp (s, v->missing[2].s, v->width));
421 /* Return nonzero only if value VAL is system-missing for variable
424 is_system_missing (const union value *val, const struct variable *v)
426 return v->type == NUMERIC && val->f == SYSMIS;
429 /* Return nonzero only if value VAL is system- or user-missing for
432 is_missing (const union value *val, const struct variable *v)
437 if (val->f == SYSMIS)
439 return is_num_user_missing (val->f, v);
441 return is_str_user_missing (val->s, v);
448 /* Return nonzero only if value VAL is user-missing for variable V. */
450 is_user_missing (const union value *val, const struct variable *v)
455 return is_num_user_missing (val->f, v);
457 return is_str_user_missing (val->s, v);
464 /* A hsh_compare_func that orders variables A and B by their
467 compare_variables (const void *a_, const void *b_, void *foo unused)
469 const struct variable *a = a_;
470 const struct variable *b = b_;
472 return strcmp (a->name, b->name);
475 /* A hsh_hash_func that hashes variable V based on its name. */
477 hash_variable (const void *v_, void *foo unused)
479 const struct variable *v = v_;
481 return hsh_hash_string (v->name);