Added framework for the ONEWAY command.
[pspp] / 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 "error.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 /* Create a hash of v */
49 unsigned 
50 hash_value(const union value  *v, int width)
51 {
52   unsigned id_hash;
53
54   if ( 0 == width ) 
55     id_hash = hsh_hash_double (v->f);
56   else
57     id_hash = hsh_hash_bytes (v->s, width);
58
59   return id_hash;
60 }
61
62
63
64 /* Discards all the current state in preparation for a data-input
65    command like DATA LIST or GET. */
66 void
67 discard_variables (void)
68 {
69   dict_clear (default_dict);
70   default_handle = inline_file;
71
72   n_lag = 0;
73   
74   if (vfm_source != NULL)
75     {
76       free_case_source (vfm_source);
77       vfm_source = NULL;
78     }
79
80   cancel_transformations ();
81
82   ctl_stack = NULL;
83
84   expr_free (process_if_expr);
85   process_if_expr = NULL;
86
87   cancel_temporary ();
88
89   pgm_state = STATE_INIT;
90 }
91
92 /* Return nonzero only if X is a user-missing value for numeric
93    variable V. */
94 inline int
95 is_num_user_missing (double x, const struct variable *v)
96 {
97   switch (v->miss_type)
98     {
99     case MISSING_NONE:
100       return 0;
101     case MISSING_1:
102       return x == v->missing[0].f;
103     case MISSING_2:
104       return x == v->missing[0].f || x == v->missing[1].f;
105     case MISSING_3:
106       return (x == v->missing[0].f || x == v->missing[1].f
107               || x == v->missing[2].f);
108     case MISSING_RANGE:
109       return x >= v->missing[0].f && x <= v->missing[1].f;
110     case MISSING_LOW:
111       return x <= v->missing[0].f;
112     case MISSING_HIGH:
113       return x >= v->missing[0].f;
114     case MISSING_RANGE_1:
115       return ((x >= v->missing[0].f && x <= v->missing[1].f)
116               || x == v->missing[2].f);
117     case MISSING_LOW_1:
118       return x <= v->missing[0].f || x == v->missing[1].f;
119     case MISSING_HIGH_1:
120       return x >= v->missing[0].f || x == v->missing[1].f;
121     default:
122       assert (0);
123     }
124   abort ();
125 }
126
127 /* Return nonzero only if string S is a user-missing variable for
128    string variable V. */
129 inline int
130 is_str_user_missing (const unsigned char s[], const struct variable *v)
131 {
132   switch (v->miss_type)
133     {
134     case MISSING_NONE:
135       return 0;
136     case MISSING_1:
137       return !strncmp (s, v->missing[0].s, v->width);
138     case MISSING_2:
139       return (!strncmp (s, v->missing[0].s, v->width)
140               || !strncmp (s, v->missing[1].s, v->width));
141     case MISSING_3:
142       return (!strncmp (s, v->missing[0].s, v->width)
143               || !strncmp (s, v->missing[1].s, v->width)
144               || !strncmp (s, v->missing[2].s, v->width));
145     default:
146       assert (0);
147     }
148   abort ();
149 }
150
151 /* Return nonzero only if value VAL is system-missing for variable
152    V. */
153 int
154 is_system_missing (const union value *val, const struct variable *v)
155 {
156   return v->type == NUMERIC && val->f == SYSMIS;
157 }
158
159 /* Return nonzero only if value VAL is system- or user-missing for
160    variable V. */
161 int
162 is_missing (const union value *val, const struct variable *v)
163 {
164   switch (v->type)
165     {
166     case NUMERIC:
167       if (val->f == SYSMIS)
168         return 1;
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
178 /* Return nonzero only if value VAL is user-missing for variable V. */
179 int
180 is_user_missing (const union value *val, const struct variable *v)
181 {
182   switch (v->type)
183     {
184     case NUMERIC:
185       return is_num_user_missing (val->f, v);
186     case ALPHA:
187       return is_str_user_missing (val->s, v);
188     default:
189       assert (0);
190     }
191   abort ();
192 }
193 \f
194 /* A hsh_compare_func that orders variables A and B by their
195    names. */
196 int
197 compare_variables (const void *a_, const void *b_, void *foo UNUSED) 
198 {
199   const struct variable *a = a_;
200   const struct variable *b = b_;
201
202   return strcmp (a->name, b->name);
203 }
204
205 /* A hsh_hash_func that hashes variable V based on its name. */
206 unsigned
207 hash_variable (const void *v_, void *foo UNUSED) 
208 {
209   const struct variable *v = v_;
210
211   return hsh_hash_string (v->name);
212 }