70669837590a3accc7e99c65581b13d9d39b90e6
[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., 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              name, (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[i], 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."),
285              name[0], name);
286       return false;
287     }
288
289   if (lex_id_to_token (name, strlen (name)) != T_ID) 
290     {
291       if (issue_error)
292         msg (SE, _("%s may not be used as a variable name because it "
293                    "is a reserved word."), name);
294       return false;
295     }
296
297   return true;
298 }
299
300 /* A hsh_compare_func that orders variables A and B by their
301    names. */
302 int
303 compare_var_names (const void *a_, const void *b_, void *foo UNUSED) 
304 {
305   const struct variable *a = a_;
306   const struct variable *b = b_;
307
308   return strcasecmp (a->name, b->name);
309 }
310
311 /* A hsh_hash_func that hashes variable V based on its name. */
312 unsigned
313 hash_var_name (const void *v_, void *foo UNUSED) 
314 {
315   const struct variable *v = v_;
316
317   return hsh_hash_case_string (v->name);
318 }
319
320 /* A hsh_compare_func that orders pointers to variables A and B
321    by their names. */
322 int
323 compare_var_ptr_names (const void *a_, const void *b_, void *foo UNUSED) 
324 {
325   struct variable *const *a = a_;
326   struct variable *const *b = b_;
327
328   return strcasecmp ((*a)->name, (*b)->name);
329 }
330
331 /* A hsh_hash_func that hashes pointer to variable V based on its
332    name. */
333 unsigned
334 hash_var_ptr_name (const void *v_, void *foo UNUSED) 
335 {
336   struct variable *const *v = v_;
337
338   return hsh_hash_case_string ((*v)->name);
339 }
340 \f
341 /* Sets V's short_name to SHORT_NAME, truncating it to
342    SHORT_NAME_LEN characters and converting it to uppercase in
343    the process. */
344 void
345 var_set_short_name (struct variable *v, const char *short_name) 
346 {
347   assert (v != NULL);
348   assert (short_name[0] == '\0' || var_is_valid_name (short_name, false));
349   
350   str_copy_trunc (v->short_name, sizeof v->short_name, short_name);
351   str_uppercase (v->short_name);
352 }
353
354 /* Clears V's short name. */
355 void
356 var_clear_short_name (struct variable *v) 
357 {
358   assert (v != NULL);
359
360   v->short_name[0] = '\0';
361 }
362
363 /* Sets V's short name to BASE, followed by a suffix of the form
364    _A, _B, _C, ..., _AA, _AB, etc. according to the value of
365    SUFFIX.  Truncates BASE as necessary to fit. */
366 void
367 var_set_short_name_suffix (struct variable *v, const char *base, int suffix)
368 {
369   char string[SHORT_NAME_LEN + 1];
370   char *start, *end;
371   int len, ofs;
372
373   assert (v != NULL);
374   assert (suffix >= 0);
375   assert (strlen (v->short_name) > 0);
376
377   /* Set base name. */
378   var_set_short_name (v, base);
379
380   /* Compose suffix_string. */
381   start = end = string + sizeof string - 1;
382   *end = '\0';
383   do 
384     {
385       *--start = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[suffix % 26];
386       if (start <= string + 1)
387         msg (SE, _("Variable suffix too large."));
388       suffix /= 26;
389     }
390   while (suffix > 0);
391   *--start = '_';
392
393   /* Append suffix_string to V's short name. */
394   len = end - start;
395   if (len + strlen (v->short_name) > SHORT_NAME_LEN)
396     ofs = SHORT_NAME_LEN - len;
397   else
398     ofs = strlen (v->short_name);
399   strcpy (v->short_name + ofs, start);
400 }