2a723d96dffed427d90641800eadadeac483179c
[pspp-builds.git] / src / vars-atr.c
1 /* PSPP - computes sample statistics.
2    Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
3    Written by Ben Pfaff <blp@gnu.org>.
4
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.
9
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.
14
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
18    02111-1307, USA. */
19
20 #include <config.h>
21 #include <assert.h>
22 #include <stdlib.h>
23 #include "alloc.h"
24 #include "approx.h"
25 #include "command.h"
26 #include "do-ifP.h"
27 #include "expr.h"
28 #include "file-handle.h"
29 #include "hash.h"
30 #include "inpt-pgm.h"
31 #include "misc.h"
32 #include "str.h"
33 #include "var.h"
34 #include "vector.h"
35 #include "value-labels.h"
36 #include "vfm.h"
37
38 #include "debug-print.h"
39
40 /* Clear the default dictionary.  Note: This is probably not what you
41    want to do.  Use discard_variables() instead. */
42 void
43 clear_default_dict (void)
44 {
45   int i;
46   
47   for (i = 0; i < default_dict.nvar; i++)
48     {
49       clear_variable (&default_dict, default_dict.var[i]);
50       free (default_dict.var[i]);
51     }
52
53   assert (default_dict.splits == NULL);
54
55   default_dict.nvar = 0;
56   default_dict.N = 0;
57   default_dict.nval = 0;
58   default_handle = inline_file;
59   stop_weighting (&default_dict);
60 }
61
62 /* Discards all the current state in preparation for a data-input
63    command like DATA LIST or GET. */
64 void
65 discard_variables (void)
66 {
67   clear_default_dict ();
68   
69   n_lag = 0;
70   
71   if (vfm_source)
72     {
73       vfm_source->destroy_source ();
74       vfm_source = NULL;
75     }
76
77   cancel_transformations ();
78
79   ctl_stack = NULL;
80
81   free (vec);
82   vec = NULL;
83   nvec = 0;
84
85   expr_free (process_if_expr);
86   process_if_expr = NULL;
87
88   cancel_temporary ();
89
90   pgm_state = STATE_INIT;
91 }
92
93 /* Find and return the variable in default_dict having name NAME, or
94    NULL if no such variable exists in default_dict. */
95 struct variable *
96 find_variable (const char *name)
97 {
98   return hsh_find (default_dict.name_tab, name);
99 }
100
101 /* Find and return the variable in dictionary D having name NAME, or
102    NULL if no such variable exists in D. */
103 struct variable *
104 find_dict_variable (const struct dictionary *d, const char *name)
105 {
106   return hsh_find (d->name_tab, name);
107 }
108
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.  */
114 struct variable *
115 create_variable (struct dictionary *dict, const char *name,
116                  int type, int width)
117 {
118   if (find_dict_variable (dict, name))
119     return NULL;
120   
121   {
122     struct variable *new_var;
123     
124     dict->var = xrealloc (dict->var, (dict->nvar + 1) * sizeof *dict->var);
125     new_var = dict->var[dict->nvar] = xmalloc (sizeof *new_var);
126     
127     new_var->index = dict->nvar;
128     dict->nvar++;
129     
130     init_variable (dict, new_var, name, type, width);
131     
132     return new_var;
133   }
134 }
135
136 #if GLOBAL_DEBUGGING
137 /* For situations in which we know that there are no variables with an
138    identical name in the dictionary. */
139 struct variable *
140 force_create_variable (struct dictionary *dict, const char *name,
141                        int type, int width)
142 {
143   struct variable *new_var = create_variable (dict, name, type, width);
144   assert (new_var != NULL);
145   return new_var;
146 }
147
148 /* For situations in which we know that there are no variables with an
149    identical name in the dictionary. */
150 struct variable *
151 force_dup_variable (struct dictionary *dict, const struct variable *src,
152                     const char *name)
153 {
154   struct variable *new_var = dup_variable (dict, src, name);
155   assert (new_var != NULL);
156   return new_var;
157 }
158 #endif
159                                  
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. */
163 void
164 delete_variable (struct dictionary *dict, struct variable *v)
165 {
166   int i;
167
168   clear_variable (dict, v);
169   dict->nvar--;
170   for (i = v->index; i < dict->nvar; i++)
171     {
172       dict->var[i] = dict->var[i + 1];
173       dict->var[i]->index = i;
174     }
175   free (v);
176 }
177
178 /* Initialize fields in variable V inside dictionary D with name NAME,
179    type TYPE, and width WIDTH.  Initializes some other fields too. */
180 static inline void
181 common_init_stuff (struct dictionary *dict, struct variable *v,
182                    const char *name, int type, int width)
183 {
184   if (v->name != name)
185     /* Avoid problems with overlap. */
186     strcpy (v->name, name);
187
188   hsh_force_insert (dict->name_tab, v);
189
190   v->type = type;
191   v->left = name[0] == '#';
192   v->width = type == NUMERIC ? 0 : width;
193   v->miss_type = MISSING_NONE;
194   if (v->type == NUMERIC)
195     {
196       v->print.type = FMT_F;
197       v->print.w = 8;
198       v->print.d = 2;
199     }
200   else
201     {
202       v->print.type = FMT_A;
203       v->print.w = v->width;
204       v->print.d = 0;
205     }
206   v->write = v->print;
207 }
208
209 /* Initialize (for the first time) a variable V in dictionary DICT
210    with name NAME, type TYPE, and width WIDTH.  */
211 void
212 init_variable (struct dictionary *dict, struct variable *v, const char *name,
213                int type, int width)
214 {
215   common_init_stuff (dict, v, name, type, width);
216   v->nv = type == NUMERIC ? 1 : DIV_RND_UP (width, 8);
217   v->fv = dict->nval;
218   dict->nval += v->nv;
219   v->label = NULL;
220   v->val_labs = val_labs_create (width);
221   v->get.fv = -1;
222
223   if (vfm_source == &input_program_source
224       || vfm_source == &file_type_source)
225     {
226       size_t nbytes = DIV_RND_UP (v->fv + 1, 4);
227       unsigned val = 0;
228
229       if (inp_init_size < nbytes)
230         {
231           inp_init = xrealloc (inp_init, nbytes);
232           memset (&inp_init[inp_init_size], 0, nbytes - inp_init_size);
233           inp_init_size = nbytes;
234         }
235
236       if (v->type == ALPHA)
237         val |= INP_STRING;
238       if (v->left)
239         val |= INP_LEFT;
240       inp_init[v->fv / 4] |= val << ((unsigned) (v->fv) % 4 * 2);
241     }
242 }
243
244 /* Replace variable V in default_dict with a different variable having
245    name NAME, type TYPE, and width WIDTH. */
246 void
247 replace_variable (struct variable *v, const char *name, int type, int width)
248 {
249   int nv;
250
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);
255
256   nv = (type == NUMERIC) ? 1 : DIV_RND_UP (width, 8);
257   if (nv > v->nv)
258     {
259       v->fv = v->nv = 0;
260       v->fv = default_dict.nval;
261       default_dict.nval += nv;
262     }
263   v->nv = nv;
264 }
265
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. */
268 void
269 rename_variable (struct dictionary * dict, struct variable *v,
270                  const char *new_name)
271 {
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);
276 }
277
278 /* Delete the contents of variable V within dictionary DICT.  Does not
279    remove the variable from the vector of variables in the dictionary.
280    Use with caution. */
281 void
282 clear_variable (struct dictionary *dict, struct variable *v)
283 {
284   assert (dict != NULL);
285   assert (v != NULL);
286   
287   if (dict->name_tab != NULL)
288     hsh_force_delete (dict->name_tab, v);
289   
290   val_labs_clear (v->val_labs);
291   
292   if (v->label)
293     {
294       free (v->label);
295       v->label = NULL;
296     }
297
298   if (dict->splits)
299     {
300       struct variable **iter, **trailer;
301
302       for (trailer = iter = dict->splits; *iter; iter++)
303         if (*iter != v)
304           *trailer++ = *iter;
305         else
306           dict->n_splits--;
307
308       *trailer = NULL;
309       
310       if (dict->n_splits == 0)
311         {
312           free (dict->splits);
313           dict->splits = NULL;
314         }
315     }
316 }
317
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
322    NULL. */
323 struct variable *
324 dup_variable (struct dictionary *dict, const struct variable *src,
325               const char *name)
326 {
327   if (find_dict_variable (dict, name))
328     return NULL;
329   
330   {
331     struct variable *new_var;
332     
333     dict->var = xrealloc (dict->var, (dict->nvar + 1) * sizeof *dict->var);
334     new_var = dict->var[dict->nvar] = xmalloc (sizeof *new_var);
335
336     new_var->index = dict->nvar;
337     new_var->foo = -1;
338     new_var->get.fv = -1;
339     new_var->get.nv = -1;
340     dict->nvar++;
341     
342     copy_variable (new_var, src);
343
344     assert (new_var->nv >= 0);
345     new_var->fv = dict->nval;
346     dict->nval += new_var->nv;
347
348     strcpy (new_var->name, name);
349     hsh_force_insert (dict->name_tab, new_var);
350
351     return new_var;
352   }
353 }
354
355    
356 /* Return nonzero only if X is a user-missing value for numeric
357    variable V. */
358 inline int
359 is_num_user_missing (double x, const struct variable *v)
360 {
361   switch (v->miss_type)
362     {
363     case MISSING_NONE:
364       return 0;
365     case MISSING_1:
366       return approx_eq (x, v->missing[0].f);
367     case MISSING_2:
368       return (approx_eq (x, v->missing[0].f)
369               || approx_eq (x, v->missing[1].f));
370     case MISSING_3:
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));
374     case MISSING_RANGE:
375       return (approx_ge (x, v->missing[0].f)
376               && approx_le (x, v->missing[1].f));
377     case MISSING_LOW:
378       return approx_le (x, v->missing[0].f);
379     case MISSING_HIGH:
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));
385     case MISSING_LOW_1:
386       return (approx_le (x, v->missing[0].f)
387               || approx_eq (x, v->missing[1].f));
388     case MISSING_HIGH_1:
389       return (approx_ge (x, v->missing[0].f)
390               || approx_eq (x, v->missing[1].f));
391     default:
392       assert (0);
393     }
394   abort ();
395 }
396
397 /* Return nonzero only if string S is a user-missing variable for
398    string variable V. */
399 inline int
400 is_str_user_missing (const unsigned char s[], const struct variable *v)
401 {
402   switch (v->miss_type)
403     {
404     case MISSING_NONE:
405       return 0;
406     case MISSING_1:
407       return !strncmp (s, v->missing[0].s, v->width);
408     case MISSING_2:
409       return (!strncmp (s, v->missing[0].s, v->width)
410               || !strncmp (s, v->missing[1].s, v->width));
411     case MISSING_3:
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));
415     default:
416       assert (0);
417     }
418   abort ();
419 }
420
421 /* Return nonzero only if value VAL is system-missing for variable
422    V. */
423 int
424 is_system_missing (const union value *val, const struct variable *v)
425 {
426   return v->type == NUMERIC && val->f == SYSMIS;
427 }
428
429 /* Return nonzero only if value VAL is system- or user-missing for
430    variable V. */
431 int
432 is_missing (const union value *val, const struct variable *v)
433 {
434   switch (v->type)
435     {
436     case NUMERIC:
437       if (val->f == SYSMIS)
438         return 1;
439       return is_num_user_missing (val->f, v);
440     case ALPHA:
441       return is_str_user_missing (val->s, v);
442     default:
443       assert (0);
444     }
445   abort ();
446 }
447
448 /* Return nonzero only if value VAL is user-missing for variable V. */
449 int
450 is_user_missing (const union value *val, const struct variable *v)
451 {
452   switch (v->type)
453     {
454     case NUMERIC:
455       return is_num_user_missing (val->f, v);
456     case ALPHA:
457       return is_str_user_missing (val->s, v);
458     default:
459       assert (0);
460     }
461   abort ();
462 }
463 \f
464 /* A hsh_compare_func that orders variables A and B by their
465    names. */
466 int
467 compare_variables (const void *a_, const void *b_, void *foo unused) 
468 {
469   const struct variable *a = a_;
470   const struct variable *b = b_;
471
472   return strcmp (a->name, b->name);
473 }
474
475 /* A hsh_hash_func that hashes variable V based on its name. */
476 unsigned
477 hash_variable (const void *v_, void *foo unused) 
478 {
479   const struct variable *v = v_;
480
481   return hsh_hash_string (v->name);
482 }