ee4d230246c6e233d68a52e65b8de7f97b60a897
[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)
59     {
60       vfm_source->destroy_source ();
61       vfm_source = NULL;
62     }
63
64   cancel_transformations ();
65
66   ctl_stack = NULL;
67
68   expr_free (process_if_expr);
69   process_if_expr = NULL;
70
71   cancel_temporary ();
72
73   pgm_state = STATE_INIT;
74 }
75
76 /* Return nonzero only if X is a user-missing value for numeric
77    variable V. */
78 inline int
79 is_num_user_missing (double x, const struct variable *v)
80 {
81   switch (v->miss_type)
82     {
83     case MISSING_NONE:
84       return 0;
85     case MISSING_1:
86       return x == v->missing[0].f;
87     case MISSING_2:
88       return x == v->missing[0].f || x == v->missing[1].f;
89     case MISSING_3:
90       return (x == v->missing[0].f || x == v->missing[1].f
91               || x == v->missing[2].f);
92     case MISSING_RANGE:
93       return x >= v->missing[0].f && x <= v->missing[1].f;
94     case MISSING_LOW:
95       return x <= v->missing[0].f;
96     case MISSING_HIGH:
97       return x >= v->missing[0].f;
98     case MISSING_RANGE_1:
99       return ((x >= v->missing[0].f && x <= v->missing[1].f)
100               || x == v->missing[2].f);
101     case MISSING_LOW_1:
102       return x <= v->missing[0].f || x == v->missing[1].f;
103     case MISSING_HIGH_1:
104       return x >= v->missing[0].f || x == v->missing[1].f;
105     default:
106       assert (0);
107     }
108   abort ();
109 }
110
111 /* Return nonzero only if string S is a user-missing variable for
112    string variable V. */
113 inline int
114 is_str_user_missing (const unsigned char s[], const struct variable *v)
115 {
116   switch (v->miss_type)
117     {
118     case MISSING_NONE:
119       return 0;
120     case MISSING_1:
121       return !strncmp (s, v->missing[0].s, v->width);
122     case MISSING_2:
123       return (!strncmp (s, v->missing[0].s, v->width)
124               || !strncmp (s, v->missing[1].s, v->width));
125     case MISSING_3:
126       return (!strncmp (s, v->missing[0].s, v->width)
127               || !strncmp (s, v->missing[1].s, v->width)
128               || !strncmp (s, v->missing[2].s, v->width));
129     default:
130       assert (0);
131     }
132   abort ();
133 }
134
135 /* Return nonzero only if value VAL is system-missing for variable
136    V. */
137 int
138 is_system_missing (const union value *val, const struct variable *v)
139 {
140   return v->type == NUMERIC && val->f == SYSMIS;
141 }
142
143 /* Return nonzero only if value VAL is system- or user-missing for
144    variable V. */
145 int
146 is_missing (const union value *val, const struct variable *v)
147 {
148   switch (v->type)
149     {
150     case NUMERIC:
151       if (val->f == SYSMIS)
152         return 1;
153       return is_num_user_missing (val->f, v);
154     case ALPHA:
155       return is_str_user_missing (val->s, v);
156     default:
157       assert (0);
158     }
159   abort ();
160 }
161
162 /* Return nonzero only if value VAL is user-missing for variable V. */
163 int
164 is_user_missing (const union value *val, const struct variable *v)
165 {
166   switch (v->type)
167     {
168     case NUMERIC:
169       return is_num_user_missing (val->f, v);
170     case ALPHA:
171       return is_str_user_missing (val->s, v);
172     default:
173       assert (0);
174     }
175   abort ();
176 }
177 \f
178 /* A hsh_compare_func that orders variables A and B by their
179    names. */
180 int
181 compare_variables (const void *a_, const void *b_, void *foo UNUSED) 
182 {
183   const struct variable *a = a_;
184   const struct variable *b = b_;
185
186   return strcmp (a->name, b->name);
187 }
188
189 /* A hsh_hash_func that hashes variable V based on its name. */
190 unsigned
191 hash_variable (const void *v_, void *foo UNUSED) 
192 {
193   const struct variable *v = v_;
194
195   return hsh_hash_string (v->name);
196 }