adaa6a4cc2c46deca2c00269a793bcaead0ba6fa
[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 "gettext.h"
38 #define _(msgid) gettext (msgid)
39
40 #include "debug-print.h"
41
42 /* Assign auxiliary data AUX to variable V, which must not
43    already have auxiliary data.  Before V's auxiliary data is
44    cleared, AUX_DTOR(V) will be called. */
45 void *
46 var_attach_aux (struct variable *v,
47                 void *aux, void (*aux_dtor) (struct variable *)) 
48 {
49   assert (v->aux == NULL);
50   assert (aux != NULL);
51   v->aux = aux;
52   v->aux_dtor = aux_dtor;
53   return aux;
54 }
55
56 /* Remove auxiliary data, if any, from V, and returns it, without
57    calling any associated destructor. */
58 void *
59 var_detach_aux (struct variable *v) 
60 {
61   void *aux = v->aux;
62   assert (aux != NULL);
63   v->aux = NULL;
64   return aux;
65 }
66
67 /* Clears auxiliary data, if any, from V, and calls any
68    associated destructor. */
69 void
70 var_clear_aux (struct variable *v) 
71 {
72   assert (v != NULL);
73   if (v->aux != NULL) 
74     {
75       if (v->aux_dtor != NULL)
76         v->aux_dtor (v);
77       v->aux = NULL;
78     }
79 }
80
81 /* This function is appropriate for use an auxiliary data
82    destructor (passed as AUX_DTOR to var_attach_aux()) for the
83    case where the auxiliary data should be passed to free(). */
84 void
85 var_dtor_free (struct variable *v) 
86 {
87   free (v->aux);
88 }
89
90 /* Compares A and B, which both have the given WIDTH, and returns
91    a strcmp()-type result. */
92 int
93 compare_values (const union value *a, const union value *b, int width) 
94 {
95   if (width == 0) 
96     return a->f < b->f ? -1 : a->f > b->f;
97   else
98     return memcmp (a->s, b->s, min(MAX_SHORT_STRING, width));
99 }
100
101 /* Create a hash of v */
102 unsigned 
103 hash_value(const union value  *v, int width)
104 {
105   unsigned id_hash;
106
107   if ( 0 == width ) 
108     id_hash = hsh_hash_double (v->f);
109   else
110     id_hash = hsh_hash_bytes (v->s, min(MAX_SHORT_STRING, width));
111
112   return id_hash;
113 }
114
115
116
117 \f
118 /* Returns true if NAME is an acceptable name for a variable,
119    false otherwise.  If ISSUE_ERROR is true, issues an
120    explanatory error message on failure. */
121 bool
122 var_is_valid_name (const char *name, bool issue_error) 
123 {
124   size_t length, i;
125   
126   assert (name != NULL);
127
128   length = strlen (name);
129   if (length < 1) 
130     {
131       if (issue_error)
132         msg (SE, _("Variable name cannot be empty string."));
133       return false;
134     }
135   else if (length > LONG_NAME_LEN) 
136     {
137       if (issue_error)
138         msg (SE, _("Variable name %s exceeds %d-character limit."),
139              name, (int) LONG_NAME_LEN);
140       return false;
141     }
142
143   for (i = 0; i < length; i++)
144     if (!CHAR_IS_IDN (name[i])) 
145       {
146         if (issue_error)
147           msg (SE, _("Character `%c' (in %s) may not appear in "
148                      "a variable name."),
149                name[i], name);
150         return false;
151       }
152         
153   if (!CHAR_IS_ID1 (name[0]))
154     {
155       if (issue_error)
156         msg (SE, _("Character `%c' (in %s), may not appear "
157                    "as the first character in a variable name."),
158              name[0], name);
159       return false;
160     }
161
162   if (lex_id_to_token (name, strlen (name)) != T_ID) 
163     {
164       if (issue_error)
165         msg (SE, _("%s may not be used as a variable name because it "
166                    "is a reserved word."), name);
167       return false;
168     }
169
170   return true;
171 }
172
173 /* A hsh_compare_func that orders variables A and B by their
174    names. */
175 int
176 compare_var_names (const void *a_, const void *b_, void *foo UNUSED) 
177 {
178   const struct variable *a = a_;
179   const struct variable *b = b_;
180
181   return strcasecmp (a->name, b->name);
182 }
183
184 /* A hsh_hash_func that hashes variable V based on its name. */
185 unsigned
186 hash_var_name (const void *v_, void *foo UNUSED) 
187 {
188   const struct variable *v = v_;
189
190   return hsh_hash_case_string (v->name);
191 }
192
193 /* A hsh_compare_func that orders pointers to variables A and B
194    by their names. */
195 int
196 compare_var_ptr_names (const void *a_, const void *b_, void *foo UNUSED) 
197 {
198   struct variable *const *a = a_;
199   struct variable *const *b = b_;
200
201   return strcasecmp ((*a)->name, (*b)->name);
202 }
203
204 /* A hsh_hash_func that hashes pointer to variable V based on its
205    name. */
206 unsigned
207 hash_var_ptr_name (const void *v_, void *foo UNUSED) 
208 {
209   struct variable *const *v = v_;
210
211   return hsh_hash_case_string ((*v)->name);
212 }
213 \f
214 /* Sets V's short_name to SHORT_NAME, truncating it to
215    SHORT_NAME_LEN characters and converting it to uppercase in
216    the process. */
217 void
218 var_set_short_name (struct variable *v, const char *short_name) 
219 {
220   assert (v != NULL);
221   assert (short_name[0] == '\0' || var_is_valid_name (short_name, false));
222   
223   str_copy_trunc (v->short_name, sizeof v->short_name, short_name);
224   str_uppercase (v->short_name);
225 }
226
227 /* Clears V's short name. */
228 void
229 var_clear_short_name (struct variable *v) 
230 {
231   assert (v != NULL);
232
233   v->short_name[0] = '\0';
234 }
235
236 /* Sets V's short name to BASE, followed by a suffix of the form
237    _A, _B, _C, ..., _AA, _AB, etc. according to the value of
238    SUFFIX.  Truncates BASE as necessary to fit. */
239 void
240 var_set_short_name_suffix (struct variable *v, const char *base, int suffix)
241 {
242   char string[SHORT_NAME_LEN + 1];
243   char *start, *end;
244   int len, ofs;
245
246   assert (v != NULL);
247   assert (suffix >= 0);
248   assert (strlen (v->short_name) > 0);
249
250   /* Set base name. */
251   var_set_short_name (v, base);
252
253   /* Compose suffix_string. */
254   start = end = string + sizeof string - 1;
255   *end = '\0';
256   do 
257     {
258       *--start = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[suffix % 26];
259       if (start <= string + 1)
260         msg (SE, _("Variable suffix too large."));
261       suffix /= 26;
262     }
263   while (suffix > 0);
264   *--start = '_';
265
266   /* Append suffix_string to V's short name. */
267   len = end - start;
268   if (len + strlen (v->short_name) > SHORT_NAME_LEN)
269     ofs = SHORT_NAME_LEN - len;
270   else
271     ofs = strlen (v->short_name);
272   strcpy (v->short_name + ofs, start);
273 }
274
275
276 /* Returns the dictionary class corresponding to a variable named
277    NAME. */
278 enum dict_class
279 dict_class_from_id (const char *name) 
280 {
281   assert (name != NULL);
282
283   switch (name[0]) 
284     {
285     default:
286       return DC_ORDINARY;
287     case '$':
288       return DC_SYSTEM;
289     case '#':
290       return DC_SCRATCH;
291     }
292 }
293
294 /* Returns the name of dictionary class DICT_CLASS. */
295 const char *
296 dict_class_to_name (enum dict_class dict_class) 
297 {
298   switch (dict_class) 
299     {
300     case DC_ORDINARY:
301       return _("ordinary");
302     case DC_SYSTEM:
303       return _("system");
304     case DC_SCRATCH:
305       return _("scratch");
306     default:
307       assert (0);
308       abort ();
309     }
310 }