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