a1b8276fcb2987fa064a89a8e1c60d0320a6a61c
[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., 51 Franklin Street, Fifth Floor, Boston, MA
18    02110-1301, 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 "dictionary.h"
27 #include "do-ifP.h"
28 #include "expressions/public.h"
29 #include "file-handle.h"
30 #include "hash.h"
31 #include "lexer.h"
32 #include "misc.h"
33 #include "str.h"
34 #include "value-labels.h"
35 #include "vfm.h"
36
37 #include "debug-print.h"
38
39 /* Assign auxiliary data AUX to variable V, which must not
40    already have auxiliary data.  Before V's auxiliary data is
41    cleared, AUX_DTOR(V) will be called. */
42 void *
43 var_attach_aux (struct variable *v,
44                 void *aux, void (*aux_dtor) (struct variable *)) 
45 {
46   assert (v->aux == NULL);
47   assert (aux != NULL);
48   v->aux = aux;
49   v->aux_dtor = aux_dtor;
50   return aux;
51 }
52
53 /* Remove auxiliary data, if any, from V, and returns it, without
54    calling any associated destructor. */
55 void *
56 var_detach_aux (struct variable *v) 
57 {
58   void *aux = v->aux;
59   assert (aux != NULL);
60   v->aux = NULL;
61   return aux;
62 }
63
64 /* Clears auxiliary data, if any, from V, and calls any
65    associated destructor. */
66 void
67 var_clear_aux (struct variable *v) 
68 {
69   assert (v != NULL);
70   if (v->aux != NULL) 
71     {
72       if (v->aux_dtor != NULL)
73         v->aux_dtor (v);
74       v->aux = NULL;
75     }
76 }
77
78 /* This function is appropriate for use an auxiliary data
79    destructor (passed as AUX_DTOR to var_attach_aux()) for the
80    case where the auxiliary data should be passed to free(). */
81 void
82 var_dtor_free (struct variable *v) 
83 {
84   free (v->aux);
85 }
86
87 /* Compares A and B, which both have the given WIDTH, and returns
88    a strcmp()-type result. */
89 int
90 compare_values (const union value *a, const union value *b, int width) 
91 {
92   if (width == 0) 
93     return a->f < b->f ? -1 : a->f > b->f;
94   else
95     return memcmp (a->s, b->s, min(MAX_SHORT_STRING, width));
96 }
97
98 /* Create a hash of v */
99 unsigned 
100 hash_value(const union value  *v, int width)
101 {
102   unsigned id_hash;
103
104   if ( 0 == width ) 
105     id_hash = hsh_hash_double (v->f);
106   else
107     id_hash = hsh_hash_bytes (v->s, min(MAX_SHORT_STRING, width));
108
109   return id_hash;
110 }
111
112
113
114 /* Discards all the current state in preparation for a data-input
115    command like DATA LIST or GET. */
116 void
117 discard_variables (void)
118 {
119   dict_clear (default_dict);
120   default_handle = NULL;
121
122   n_lag = 0;
123   
124   if (vfm_source != NULL)
125     {
126       free_case_source (vfm_source);
127       vfm_source = NULL;
128     }
129
130   cancel_transformations ();
131
132   ctl_stack = NULL;
133
134   expr_free (process_if_expr);
135   process_if_expr = NULL;
136
137   cancel_temporary ();
138
139   pgm_state = STATE_INIT;
140 }
141
142 /* Return nonzero only if X is a user-missing value for numeric
143    variable V. */
144 inline int
145 is_num_user_missing (double x, const struct variable *v)
146 {
147   switch (v->miss_type)
148     {
149     case MISSING_NONE:
150       return 0;
151     case MISSING_1:
152       return x == v->missing[0].f;
153     case MISSING_2:
154       return x == v->missing[0].f || x == v->missing[1].f;
155     case MISSING_3:
156       return (x == v->missing[0].f || x == v->missing[1].f
157               || x == v->missing[2].f);
158     case MISSING_RANGE:
159       return x >= v->missing[0].f && x <= v->missing[1].f;
160     case MISSING_LOW:
161       return x <= v->missing[0].f;
162     case MISSING_HIGH:
163       return x >= v->missing[0].f;
164     case MISSING_RANGE_1:
165       return ((x >= v->missing[0].f && x <= v->missing[1].f)
166               || x == v->missing[2].f);
167     case MISSING_LOW_1:
168       return x <= v->missing[0].f || x == v->missing[1].f;
169     case MISSING_HIGH_1:
170       return x >= v->missing[0].f || x == v->missing[1].f;
171     default:
172       assert (0);
173     }
174   abort ();
175 }
176
177 /* Return nonzero only if string S is a user-missing variable for
178    string variable V. */
179 inline int
180 is_str_user_missing (const unsigned char s[], const struct variable *v)
181 {
182   /* FIXME: should these be memcmp()? */
183   switch (v->miss_type)
184     {
185     case MISSING_NONE:
186       return 0;
187     case MISSING_1:
188       return !strncmp (s, v->missing[0].s, v->width);
189     case MISSING_2:
190       return (!strncmp (s, v->missing[0].s, v->width)
191               || !strncmp (s, v->missing[1].s, v->width));
192     case MISSING_3:
193       return (!strncmp (s, v->missing[0].s, v->width)
194               || !strncmp (s, v->missing[1].s, v->width)
195               || !strncmp (s, v->missing[2].s, v->width));
196     default:
197       assert (0);
198     }
199   abort ();
200 }
201
202 /* Return nonzero only if value VAL is system-missing for variable
203    V. */
204 int
205 is_system_missing (const union value *val, const struct variable *v)
206 {
207   return v->type == NUMERIC && val->f == SYSMIS;
208 }
209
210 /* Return nonzero only if value VAL is system- or user-missing for
211    variable V. */
212 int
213 is_missing (const union value *val, const struct variable *v)
214 {
215   switch (v->type)
216     {
217     case NUMERIC:
218       if (val->f == SYSMIS)
219         return 1;
220       return is_num_user_missing (val->f, v);
221     case ALPHA:
222       return is_str_user_missing (val->s, v);
223     default:
224       assert (0);
225     }
226   abort ();
227 }
228
229 /* Return nonzero only if value VAL is user-missing for variable V. */
230 int
231 is_user_missing (const union value *val, const struct variable *v)
232 {
233   switch (v->type)
234     {
235     case NUMERIC:
236       return is_num_user_missing (val->f, v);
237     case ALPHA:
238       return is_str_user_missing (val->s, v);
239     default:
240       assert (0);
241     }
242   abort ();
243 }
244 \f
245 /* Returns true if NAME is an acceptable name for a variable,
246    false otherwise.  If ISSUE_ERROR is true, issues an
247    explanatory error message on failure. */
248 bool
249 var_is_valid_name (const char *name, bool issue_error) 
250 {
251   size_t length, i;
252   
253   assert (name != NULL);
254
255   length = strlen (name);
256   if (length < 1) 
257     {
258       if (issue_error)
259         msg (SE, _("Variable name cannot be empty string."));
260       return false;
261     }
262   else if (length > LONG_NAME_LEN) 
263     {
264       if (issue_error)
265         msg (SE, _("Variable name %s exceeds %d-character limit."),
266              (int) LONG_NAME_LEN);
267       return false;
268     }
269
270   for (i = 0; i < length; i++)
271     if (!CHAR_IS_IDN (name[i])) 
272       {
273         if (issue_error)
274           msg (SE, _("Character `%c' (in %s) may not appear in "
275                      "a variable name."),
276                name);
277         return false;
278       }
279         
280   if (!CHAR_IS_ID1 (name[0]))
281     {
282       if (issue_error)
283         msg (SE, _("Character `%c' (in %s), may not appear "
284                    "as the first character in a variable name."), name);
285       return false;
286     }
287
288   if (lex_id_to_token (name, strlen (name)) != T_ID) 
289     {
290       if (issue_error)
291         msg (SE, _("%s may not be used as a variable name because it "
292                    "is a reserved word."), name);
293       return false;
294     }
295
296   return true;
297 }
298
299 /* A hsh_compare_func that orders variables A and B by their
300    names. */
301 int
302 compare_var_names (const void *a_, const void *b_, void *foo UNUSED) 
303 {
304   const struct variable *a = a_;
305   const struct variable *b = b_;
306
307   return strcasecmp (a->name, b->name);
308 }
309
310 /* A hsh_hash_func that hashes variable V based on its name. */
311 unsigned
312 hash_var_name (const void *v_, void *foo UNUSED) 
313 {
314   const struct variable *v = v_;
315
316   return hsh_hash_case_string (v->name);
317 }
318
319 /* A hsh_compare_func that orders pointers to variables A and B
320    by their names. */
321 int
322 compare_var_ptr_names (const void *a_, const void *b_, void *foo UNUSED) 
323 {
324   struct variable *const *a = a_;
325   struct variable *const *b = b_;
326
327   return strcasecmp ((*a)->name, (*b)->name);
328 }
329
330 /* A hsh_hash_func that hashes pointer to variable V based on its
331    name. */
332 unsigned
333 hash_var_ptr_name (const void *v_, void *foo UNUSED) 
334 {
335   struct variable *const *v = v_;
336
337   return hsh_hash_case_string ((*v)->name);
338 }
339 \f
340 /* Sets V's short_name to SHORT_NAME, truncating it to
341    SHORT_NAME_LEN characters and converting it to uppercase in
342    the process. */
343 void
344 var_set_short_name (struct variable *v, const char *short_name) 
345 {
346   assert (v != NULL);
347   assert (short_name[0] == '\0' || var_is_valid_name (short_name, false));
348   
349   st_trim_copy (v->short_name, short_name, sizeof v->short_name);
350   st_uppercase (v->short_name);
351 }
352
353 /* Clears V's short name. */
354 void
355 var_clear_short_name (struct variable *v) 
356 {
357   assert (v != NULL);
358
359   v->short_name[0] = '\0';
360 }
361
362 /* Sets V's short name to BASE, followed by a suffix of the form
363    _A, _B, _C, ..., _AA, _AB, etc. according to the value of
364    SUFFIX.  Truncates BASE as necessary to fit. */
365 void
366 var_set_short_name_suffix (struct variable *v, const char *base, int suffix)
367 {
368   char string[SHORT_NAME_LEN + 1];
369   char *start, *end;
370   int len, ofs;
371
372   assert (v != NULL);
373   assert (suffix >= 0);
374   assert (strlen (v->short_name) > 0);
375
376   /* Set base name. */
377   var_set_short_name (v, base);
378
379   /* Compose suffix_string. */
380   start = end = string + sizeof string - 1;
381   *end = '\0';
382   do 
383     {
384       *--start = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[suffix % 26];
385       if (start <= string + 1)
386         msg (SE, _("Variable suffix too large."));
387       suffix /= 26;
388     }
389   while (suffix > 0);
390   *--start = '_';
391
392   /* Append suffix_string to V's short name. */
393   len = end - start;
394   if (len + strlen (v->short_name) > SHORT_NAME_LEN)
395     ofs = SHORT_NAME_LEN - len;
396   else
397     ofs = strlen (v->short_name);
398   strcpy (v->short_name + ofs, start);
399 }