Beginning of VFM cleanup.
[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 "var.h"
22 #include <assert.h>
23 #include <stdlib.h>
24 #include "alloc.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 "misc.h"
31 #include "str.h"
32 #include "value-labels.h"
33 #include "vfm.h"
34
35 #include "debug-print.h"
36
37 /* Compares A and B, which both have the given WIDTH, and returns
38    a strcmp()-type result. */
39 int
40 compare_values (const union value *a, const union value *b, int width) 
41 {
42   if (width == 0) 
43     return a->f < b->f ? -1 : a->f > b->f;
44   else
45     return memcmp (a->s, b->s, width);
46 }
47
48 /* Discards all the current state in preparation for a data-input
49    command like DATA LIST or GET. */
50 void
51 discard_variables (void)
52 {
53   dict_clear (default_dict);
54   default_handle = inline_file;
55
56   n_lag = 0;
57   
58   if (vfm_source != NULL)
59     {
60       if (vfm_source->class->destroy != NULL)
61         vfm_source->class->destroy (vfm_source);
62       free (vfm_source);
63       vfm_source = NULL;
64     }
65
66   cancel_transformations ();
67
68   ctl_stack = NULL;
69
70   expr_free (process_if_expr);
71   process_if_expr = NULL;
72
73   cancel_temporary ();
74
75   pgm_state = STATE_INIT;
76 }
77
78 /* Return nonzero only if X is a user-missing value for numeric
79    variable V. */
80 inline int
81 is_num_user_missing (double x, const struct variable *v)
82 {
83   switch (v->miss_type)
84     {
85     case MISSING_NONE:
86       return 0;
87     case MISSING_1:
88       return x == v->missing[0].f;
89     case MISSING_2:
90       return x == v->missing[0].f || x == v->missing[1].f;
91     case MISSING_3:
92       return (x == v->missing[0].f || x == v->missing[1].f
93               || x == v->missing[2].f);
94     case MISSING_RANGE:
95       return x >= v->missing[0].f && x <= v->missing[1].f;
96     case MISSING_LOW:
97       return x <= v->missing[0].f;
98     case MISSING_HIGH:
99       return x >= v->missing[0].f;
100     case MISSING_RANGE_1:
101       return ((x >= v->missing[0].f && x <= v->missing[1].f)
102               || x == v->missing[2].f);
103     case MISSING_LOW_1:
104       return x <= v->missing[0].f || x == v->missing[1].f;
105     case MISSING_HIGH_1:
106       return x >= v->missing[0].f || x == v->missing[1].f;
107     default:
108       assert (0);
109     }
110   abort ();
111 }
112
113 /* Return nonzero only if string S is a user-missing variable for
114    string variable V. */
115 inline int
116 is_str_user_missing (const unsigned char s[], const struct variable *v)
117 {
118   switch (v->miss_type)
119     {
120     case MISSING_NONE:
121       return 0;
122     case MISSING_1:
123       return !strncmp (s, v->missing[0].s, v->width);
124     case MISSING_2:
125       return (!strncmp (s, v->missing[0].s, v->width)
126               || !strncmp (s, v->missing[1].s, v->width));
127     case MISSING_3:
128       return (!strncmp (s, v->missing[0].s, v->width)
129               || !strncmp (s, v->missing[1].s, v->width)
130               || !strncmp (s, v->missing[2].s, v->width));
131     default:
132       assert (0);
133     }
134   abort ();
135 }
136
137 /* Return nonzero only if value VAL is system-missing for variable
138    V. */
139 int
140 is_system_missing (const union value *val, const struct variable *v)
141 {
142   return v->type == NUMERIC && val->f == SYSMIS;
143 }
144
145 /* Return nonzero only if value VAL is system- or user-missing for
146    variable V. */
147 int
148 is_missing (const union value *val, const struct variable *v)
149 {
150   switch (v->type)
151     {
152     case NUMERIC:
153       if (val->f == SYSMIS)
154         return 1;
155       return is_num_user_missing (val->f, v);
156     case ALPHA:
157       return is_str_user_missing (val->s, v);
158     default:
159       assert (0);
160     }
161   abort ();
162 }
163
164 /* Return nonzero only if value VAL is user-missing for variable V. */
165 int
166 is_user_missing (const union value *val, const struct variable *v)
167 {
168   switch (v->type)
169     {
170     case NUMERIC:
171       return is_num_user_missing (val->f, v);
172     case ALPHA:
173       return is_str_user_missing (val->s, v);
174     default:
175       assert (0);
176     }
177   abort ();
178 }
179 \f
180 /* A hsh_compare_func that orders variables A and B by their
181    names. */
182 int
183 compare_variables (const void *a_, const void *b_, void *foo UNUSED) 
184 {
185   const struct variable *a = a_;
186   const struct variable *b = b_;
187
188   return strcmp (a->name, b->name);
189 }
190
191 /* A hsh_hash_func that hashes variable V based on its name. */
192 unsigned
193 hash_variable (const void *v_, void *foo UNUSED) 
194 {
195   const struct variable *v = v_;
196
197   return hsh_hash_string (v->name);
198 }