checkin of 0.3.0
[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 "avl.h"
26 #include "command.h"
27 #include "do-ifP.h"
28 #include "expr.h"
29 #include "file-handle.h"
30 #include "inpt-pgm.h"
31 #include "misc.h"
32 #include "str.h"
33 #include "var.h"
34 #include "vector.h"
35 #include "vfm.h"
36
37 #undef DEBUGGING
38 /*#define DEBUGGING 1*/
39 #include "debug-print.h"
40
41 #if DEBUGGING
42 /* Dumps one variable to standard output. */
43 void
44 dump_one_var_node (void * pnode, void *param, int level)
45 {
46   variable *node = pnode;
47   int i;
48
49   for (i = 0; i < level - 1; i++)
50     printf ("   ");
51   if (node == NULL)
52     printf ("NULL_TREE\n");
53   else
54     printf ("%p=>%s\n", node, node->name ? node->name : "<null>");
55 }
56
57 /* Dumps a tree of the variables to standard output. */
58 void
59 dump_var_tree (void)
60 {
61   printf (_("Vartree:\n"));
62   avl_walk_inorder (default_dict.var_by_name, dump_one_var_node, NULL);
63 }
64 #endif
65
66 /* Clear the default dictionary.  Note: This is probably not what you
67    want to do.  Use discard_variables() instead. */
68 void
69 clear_default_dict (void)
70 {
71   int i;
72   
73   for (i = 0; i < default_dict.nvar; i++)
74     {
75       clear_variable (&default_dict, default_dict.var[i]);
76       free (default_dict.var[i]);
77     }
78
79   assert (default_dict.splits == NULL);
80
81   default_dict.nvar = 0;
82   default_dict.N = 0;
83   default_dict.nval = 0;
84   default_handle = inline_file;
85   stop_weighting (&default_dict);
86 }
87
88 /* Discards all the current state in preparation for a data-input
89    command like DATA LIST or GET. */
90 void
91 discard_variables (void)
92 {
93   clear_default_dict ();
94   
95   n_lag = 0;
96   
97   if (vfm_source)
98     {
99       vfm_source->destroy_source ();
100       vfm_source = NULL;
101     }
102
103   cancel_transformations ();
104
105   ctl_stack = NULL;
106
107   free (vec);
108   vec = NULL;
109   nvec = 0;
110
111   expr_free (process_if_expr);
112   process_if_expr = NULL;
113
114   cancel_temporary ();
115
116   pgm_state = STATE_INIT;
117 }
118
119 /* Find and return the variable in default_dict having name NAME, or
120    NULL if no such variable exists in default_dict. */
121 struct variable *
122 find_variable (const char *name)
123 {
124   return avl_find (default_dict.var_by_name, (struct variable *) name);
125 }
126
127 /* Find and return the variable in dictionary D having name NAME, or
128    NULL if no such variable exists in D. */
129 struct variable *
130 find_dict_variable (const struct dictionary *d, const char *name)
131 {
132   return avl_find (d->var_by_name, (struct variable *) name);
133 }
134
135 /* Creates a variable named NAME in dictionary DICT having type TYPE
136    (ALPHA or NUMERIC) and, if type==ALPHA, width WIDTH.  Returns a
137    pointer to the newly created variable if successful.  On failure
138    (which indicates that a variable having the specified name already
139    exists), returns NULL.  */
140 struct variable *
141 create_variable (struct dictionary *dict, const char *name,
142                  int type, int width)
143 {
144   if (find_dict_variable (dict, name))
145     return NULL;
146   
147   {
148     struct variable *new_var;
149     
150     dict->var = xrealloc (dict->var, (dict->nvar + 1) * sizeof *dict->var);
151     new_var = dict->var[dict->nvar] = xmalloc (sizeof *new_var);
152     
153     new_var->index = dict->nvar;
154     dict->nvar++;
155     
156     init_variable (dict, new_var, name, type, width);
157     
158     return new_var;
159   }
160 }
161
162 #if GLOBAL_DEBUGGING
163 /* For situations in which we know that there are no variables with an
164    identical name in the dictionary. */
165 struct variable *
166 force_create_variable (struct dictionary *dict, const char *name,
167                        int type, int width)
168 {
169   struct variable *new_var = create_variable (dict, name, type, width);
170   assert (new_var != NULL);
171   return new_var;
172 }
173
174 /* For situations in which we know that there are no variables with an
175    identical name in the dictionary. */
176 struct variable *
177 force_dup_variable (struct dictionary *dict, const struct variable *src,
178                     const char *name)
179 {
180   struct variable *new_var = dup_variable (dict, src, name);
181   assert (new_var != NULL);
182   return new_var;
183 }
184 #endif
185                                  
186 /* Delete variable V from DICT.  It should only be used when there are
187    guaranteed to be absolutely NO REFERENCES to it, for instance in
188    the very same function that created it. */
189 void
190 delete_variable (struct dictionary *dict, struct variable *v)
191 {
192   int i;
193
194   clear_variable (dict, v);
195   dict->nvar--;
196   for (i = v->index; i < dict->nvar; i++)
197     {
198       dict->var[i] = dict->var[i + 1];
199       dict->var[i]->index = i;
200     }
201   free (v);
202 }
203
204 /* Initialize fields in variable V inside dictionary D with name NAME,
205    type TYPE, and width WIDTH.  Initializes some other fields too. */
206 static inline void
207 common_init_stuff (struct dictionary *dict, struct variable *v,
208                    const char *name, int type, int width)
209 {
210   if (v->name != name)
211     /* Avoid problems with overlap. */
212     strcpy (v->name, name);
213
214   avl_force_insert (dict->var_by_name, v);
215
216   v->type = type;
217   v->left = name[0] == '#';
218   v->width = type == NUMERIC ? 0 : width;
219   v->miss_type = MISSING_NONE;
220   if (v->type == NUMERIC)
221     {
222       v->print.type = FMT_F;
223       v->print.w = 8;
224       v->print.d = 2;
225     }
226   else
227     {
228       v->print.type = FMT_A;
229       v->print.w = v->width;
230       v->print.d = 0;
231     }
232   v->write = v->print;
233 }
234
235 /* Initialize (for the first time) a variable V in dictionary DICT
236    with name NAME, type TYPE, and width WIDTH.  */
237 void
238 init_variable (struct dictionary *dict, struct variable *v, const char *name,
239                int type, int width)
240 {
241   common_init_stuff (dict, v, name, type, width);
242   v->nv = type == NUMERIC ? 1 : DIV_RND_UP (width, 8);
243   v->fv = dict->nval;
244   dict->nval += v->nv;
245   v->label = NULL;
246   v->val_lab = NULL;
247   v->get.fv = -1;
248
249   if (vfm_source == &input_program_source
250       || vfm_source == &file_type_source)
251     {
252       size_t nbytes = DIV_RND_UP (v->fv + 1, 4);
253       unsigned val = 0;
254
255       if (inp_init_size < nbytes)
256         {
257           inp_init = xrealloc (inp_init, nbytes);
258           memset (&inp_init[inp_init_size], 0, nbytes - inp_init_size);
259           inp_init_size = nbytes;
260         }
261
262       if (v->type == ALPHA)
263         val |= INP_STRING;
264       if (v->left)
265         val |= INP_LEFT;
266       inp_init[v->fv / 4] |= val << ((unsigned) (v->fv) % 4 * 2);
267     }
268 }
269
270 /* Replace variable V in default_dict with a different variable having
271    name NAME, type TYPE, and width WIDTH. */
272 void
273 replace_variable (struct variable *v, const char *name, int type, int width)
274 {
275   int nv;
276
277   assert (v && name && (type == NUMERIC || type == ALPHA) && width >= 0
278           && (type == ALPHA || width == 0));
279   clear_variable (&default_dict, v);
280   common_init_stuff (&default_dict, v, name, type, width);
281
282   nv = (type == NUMERIC) ? 1 : DIV_RND_UP (width, 8);
283   if (nv > v->nv)
284     {
285       v->fv = v->nv = 0;
286       v->fv = default_dict.nval;
287       default_dict.nval += nv;
288     }
289   v->nv = nv;
290 }
291
292 /* Changes the name of variable V in dictionary DICT to name NEW_NAME.
293    NEW_NAME must be known not to already exist in dictionary DICT. */
294 void
295 rename_variable (struct dictionary * dict, struct variable *v,
296                  const char *new_name)
297 {
298   assert (dict && dict->var_by_name && v && new_name);
299   avl_delete (dict->var_by_name, v);
300   strncpy (v->name, new_name, 9);
301   avl_force_insert (dict->var_by_name, v);
302 }
303
304 /* Delete the contents of variable V within dictionary DICT.  Does not
305    remove the variable from the vector of variables in the dictionary.
306    Use with caution. */
307 void
308 clear_variable (struct dictionary *dict, struct variable *v)
309 {
310   assert (dict && v);
311   
312 #if DEBUGGING
313   printf (_("clearing variable %d:%s %s\n"), v->index, v->name,
314           (dict == &default_dict ? _("in default dictionary")
315            : _("in auxiliary dictionary")));
316   if (dict->var_by_name != NULL)
317     dump_var_tree ();
318 #endif
319   
320   if (dict->var_by_name != NULL)
321     avl_force_delete (dict->var_by_name, v);
322   
323   if (v->val_lab)
324     {
325       avl_destroy (v->val_lab, free_val_lab);
326       v->val_lab = NULL;
327     }
328   
329   if (v->label)
330     {
331       free (v->label);
332       v->label = NULL;
333     }
334
335   if (dict->splits)
336     {
337       struct variable **iter, **trailer;
338
339       for (trailer = iter = dict->splits; *iter; iter++)
340         if (*iter != v)
341           *trailer++ = *iter;
342         else
343           dict->n_splits--;
344
345       *trailer = NULL;
346       
347       if (dict->n_splits == 0)
348         {
349           free (dict->splits);
350           dict->splits = NULL;
351         }
352     }
353           
354 #if DEBUGGING
355   if (dict->var_by_name != NULL)
356     dump_var_tree ();
357 #endif
358 }
359
360 /* Creates a new variable in dictionary DICT, whose properties are
361    copied from variable SRC, and returns a pointer to the new variable
362    of name NAME, if successful.  If unsuccessful (which only happens
363    if a variable of the same name NAME exists in DICT), returns
364    NULL. */
365 struct variable *
366 dup_variable (struct dictionary *dict, const struct variable *src,
367               const char *name)
368 {
369   if (find_dict_variable (dict, name))
370     return NULL;
371   
372   {
373     struct variable *new_var;
374     
375     dict->var = xrealloc (dict->var, (dict->nvar + 1) * sizeof *dict->var);
376     new_var = dict->var[dict->nvar] = xmalloc (sizeof *new_var);
377
378     new_var->index = dict->nvar;
379     new_var->foo = -1;
380     new_var->get.fv = -1;
381     new_var->get.nv = -1;
382     dict->nvar++;
383     
384     copy_variable (new_var, src);
385
386     assert (new_var->nv >= 0);
387     new_var->fv = dict->nval;
388     dict->nval += new_var->nv;
389
390     strcpy (new_var->name, name);
391     avl_force_insert (dict->var_by_name, new_var);
392
393     return new_var;
394   }
395 }
396
397    
398 /* Decrements the reference count for value label V.  Destroys the
399    value label if the reference count reaches zero. */
400 void
401 free_value_label (struct value_label * v)
402 {
403   assert (v->ref_count >= 1);
404   if (--v->ref_count == 0)
405     {
406       free (v->s);
407       free (v);
408     }
409 }
410
411 /* Frees value label P.  PARAM is ignored.  Used as a callback with
412    avl_destroy(). */
413 void
414 free_val_lab (void *p, void *param unused)
415 {
416   free_value_label ((struct value_label *) p);
417 }
418
419 /* Returns a value label corresponding to VAL in variable V padded to
420    length N.  If N==0 then no padding is performed, and NULL is
421    returned if no label exists.  (Normally a string of spaces is
422    returned in this case.) */
423 char *
424 get_val_lab (const struct variable *v, union value val, int n)
425 {
426   static char *buf;
427   static int bufsize;
428   struct value_label template, *find;
429
430   if (bufsize < n)
431     {
432       buf = xrealloc (buf, n + 1);
433       bufsize = n;
434     }
435   if (n)
436     buf[0] = 0;
437   template.v = val;
438   find = NULL;
439   if (v->val_lab)
440     find = avl_find (v->val_lab, &template);
441   if (find)
442     {
443       if (n)
444         {
445           st_pad_copy (buf, find->s, n + 1);
446           return buf;
447         }
448       else
449         return find->s;
450     }
451   else
452     {
453       if (n)
454         {
455           memset (buf, ' ', n);
456           buf[n] = '\0';
457           return buf;
458         }
459       else
460         return NULL;
461     }
462 }
463
464 /* Return nonzero only if X is a user-missing value for numeric
465    variable V. */
466 inline int
467 is_num_user_missing (double x, const struct variable *v)
468 {
469   switch (v->miss_type)
470     {
471     case MISSING_NONE:
472       return 0;
473     case MISSING_1:
474       return approx_eq (x, v->missing[0].f);
475     case MISSING_2:
476       return (approx_eq (x, v->missing[0].f)
477               || approx_eq (x, v->missing[1].f));
478     case MISSING_3:
479       return (approx_eq (x, v->missing[0].f)
480               || approx_eq (x, v->missing[1].f)
481               || approx_eq (x, v->missing[2].f));
482     case MISSING_RANGE:
483       return (approx_ge (x, v->missing[0].f)
484               && approx_le (x, v->missing[1].f));
485     case MISSING_LOW:
486       return approx_le (x, v->missing[0].f);
487     case MISSING_HIGH:
488       return approx_ge (x, v->missing[0].f);
489     case MISSING_RANGE_1:
490       return ((approx_ge (x, v->missing[0].f)
491                && approx_le (x, v->missing[1].f))
492               || approx_eq (x, v->missing[2].f));
493     case MISSING_LOW_1:
494       return (approx_le (x, v->missing[0].f)
495               || approx_eq (x, v->missing[1].f));
496     case MISSING_HIGH_1:
497       return (approx_ge (x, v->missing[0].f)
498               || approx_eq (x, v->missing[1].f));
499     default:
500       assert (0);
501     }
502   abort ();
503 }
504
505 /* Return nonzero only if string S is a user-missing variable for
506    string variable V. */
507 inline int
508 is_str_user_missing (const unsigned char s[], const struct variable *v)
509 {
510   switch (v->miss_type)
511     {
512     case MISSING_NONE:
513       return 0;
514     case MISSING_1:
515       return !strncmp (s, v->missing[0].s, v->width);
516     case MISSING_2:
517       return (!strncmp (s, v->missing[0].s, v->width)
518               || !strncmp (s, v->missing[1].s, v->width));
519     case MISSING_3:
520       return (!strncmp (s, v->missing[0].s, v->width)
521               || !strncmp (s, v->missing[1].s, v->width)
522               || !strncmp (s, v->missing[2].s, v->width));
523     default:
524       assert (0);
525     }
526   abort ();
527 }
528
529 /* Return nonzero only if value VAL is system-missing for variable
530    V. */
531 int
532 is_system_missing (const union value *val, const struct variable *v)
533 {
534   return v->type == NUMERIC && val->f == SYSMIS;
535 }
536
537 /* Return nonzero only if value VAL is system- or user-missing for
538    variable V. */
539 int
540 is_missing (const union value *val, const struct variable *v)
541 {
542   switch (v->type)
543     {
544     case NUMERIC:
545       if (val->f == SYSMIS)
546         return 1;
547       return is_num_user_missing (val->f, v);
548     case ALPHA:
549       return is_str_user_missing (val->s, v);
550     default:
551       assert (0);
552     }
553   abort ();
554 }
555
556 /* Return nonzero only if value VAL is user-missing for variable V. */
557 int
558 is_user_missing (const union value *val, const struct variable *v)
559 {
560   switch (v->type)
561     {
562     case NUMERIC:
563       return is_num_user_missing (val->f, v);
564     case ALPHA:
565       return is_str_user_missing (val->s, v);
566     default:
567       assert (0);
568     }
569   abort ();
570 }