1 /* PSPP - computes sample statistics.
2 Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
3 Written by Ben Pfaff <blp@gnu.org>.
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.
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.
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
20 /* AIX requires this to be the first thing in the file. */
23 #define alloca __builtin_alloca
31 #ifndef alloca /* predefined by HP cc +Olibcalls */
42 #include "bitvector.h"
50 /* Allocates an array at *V to contain all the variables in
51 default_dict. If FV_NO_SYSTEM is set in FLAGS then system
52 variables will not be included. If FV_NO_SCRATCH is set in FLAGS
53 then scratch variables will not be included. *C is set to the
54 number of variables in *V. */
56 fill_all_vars (struct variable ***varlist, int *c, int flags)
60 *varlist = xmalloc (default_dict.nvar * sizeof **varlist);
63 *c = default_dict.nvar;
64 for (i = 0; i < default_dict.nvar; i++)
65 (*varlist)[i] = default_dict.var[i];
71 for (i = 0; i < default_dict.nvar; i++)
73 struct variable *v = default_dict.var[i];
75 if ((flags & FV_NO_SYSTEM) && v->name[0] == '$')
77 if ((flags & FV_NO_SCRATCH) && v->name[0] == '#')
84 if (*c != default_dict.nvar)
85 *varlist = xrealloc (*varlist, *c * sizeof **varlist);
90 is_varname (const char *s)
92 return hsh_find (default_dict.name_tab, s) != NULL;
96 is_dict_varname (const struct dictionary *dict, const char *s)
98 return hsh_find (dict->name_tab, s) != NULL;
102 parse_variable (void)
108 lex_error ("expecting variable name");
111 vp = find_variable (tokid);
113 msg (SE, _("%s is not declared as a variable."), tokid);
119 parse_dict_variable (struct dictionary * dict)
125 lex_error ("expecting variable name");
129 vp = hsh_find (dict->name_tab, tokid);
131 msg (SE, _("%s is not a variable name."), tokid);
137 /* Returns the dictionary class of an identifier based on its
138 first letter: `X' if is an ordinary identifier, `$' if it
139 designates a system variable, `#' if it designates a scratch
142 ((C) == '$' ? '$' : ((C) == '#' ? '#' : 'X'))
144 /* FIXME: One interesting variation in the case of PV_APPEND would be
145 to keep the bitmap, reducing time required to an actual O(n log n)
146 instead of having to reproduce the bitmap *every* *single* *time*.
147 Later though. (Another idea would be to keep a marker bit in each
149 /* Note that if parse_variables() returns 0, *v is free()'d.
150 Conversely, if parse_variables() returns non-zero, then *nv is
151 nonzero and *v is non-NULL. */
153 parse_variables (struct dictionary * dict, struct variable *** v, int *nv, int pv_opts)
159 struct variable *v1, *v2;
161 int scratch; /* Dictionary we're reading from. */
162 int delayed_fail = 0;
165 dict = &default_dict;
167 if (!(pv_opts & PV_APPEND))
181 for (i = 0; i < dict->nvar; i++)
182 if (dict->var[i]->index != i)
184 printf ("%s index corruption: variable %s\n",
185 dict == &default_dict ? "default_dict" : "aux dict",
194 nbytes = DIV_RND_UP (dict->nvar, 8);
195 if (!(pv_opts & PV_DUPLICATE))
197 bits = local_alloc (nbytes);
198 memset (bits, 0, nbytes);
199 for (i = 0; i < *nv; i++)
200 SET_BIT (bits, (*v)[i]->index);
205 if (lex_match (T_ALL))
208 v2 = dict->var[dict->nvar - 1];
210 scratch = id_dict ('X');
214 v1 = parse_dict_variable (dict);
218 if (lex_match (T_TO))
220 v2 = parse_dict_variable (dict);
223 lex_error ("expecting variable name");
227 count = v2->index - v1->index + 1;
230 msg (SE, _("%s TO %s is not valid syntax since %s "
231 "precedes %s in the dictionary."),
232 v1->name, v2->name, v2->name, v1->name);
236 scratch = id_dict (v1->name[0]);
237 if (scratch != id_dict (v2->name[0]))
239 msg (SE, _("When using the TO keyword to specify several "
240 "variables, both variables must be from "
241 "the same variable dictionaries, of either "
242 "ordinary, scratch, or system variables. "
243 "%s and %s are from different dictionaries."),
252 scratch = id_dict (v1->name[0]);
254 if (scratch == id_dict ('#') && (pv_opts & PV_NO_SCRATCH))
256 msg (SE, _("Scratch variables (such as %s) are not allowed "
262 if (*nv + count > mv)
264 mv += ROUND_UP (count, 16);
265 *v = xrealloc (*v, mv * sizeof **v);
268 for (i = v1->index; i <= v2->index; i++)
270 struct variable *add = dict->var[i];
272 /* Skip over other dictionaries. */
273 if (scratch != id_dict (add->name[0]))
276 if ((pv_opts & PV_NUMERIC) && add->type != NUMERIC)
279 msg (SW, _("%s is not a numeric variable. It will not be "
280 "included in the variable list."), add->name);
282 else if ((pv_opts & PV_STRING) && add->type != ALPHA)
285 msg (SE, _("%s is not a string variable. It will not be "
286 "included in the variable list."), add->name);
288 else if ((pv_opts & PV_SAME_TYPE) && *nv && add->type != (*v)[0]->type)
291 msg (SE, _("%s and %s are not the same type. All variables in "
292 "this variable list must be of the same type. %s "
293 "will be omitted from list."),
294 (*v)[0]->name, add->name, add->name);
296 else if ((pv_opts & PV_NO_DUPLICATE) && TEST_BIT (bits, add->index))
299 msg (SE, _("Variable %s appears twice in variable list."),
302 else if ((pv_opts & PV_DUPLICATE) || !TEST_BIT (bits, add->index))
304 (*v)[(*nv)++] = dict->var[i];
305 if (!(pv_opts & PV_DUPLICATE))
306 SET_BIT (bits, add->index);
310 if (pv_opts & PV_SINGLE)
319 while ((token == T_ID && is_dict_varname (dict, tokid)) || token == T_ALL);
321 if (!(pv_opts & PV_DUPLICATE))
331 if (!(pv_opts & PV_DUPLICATE))
337 extract_num (char *s, char *r, int *n, int *d)
341 /* Find first digit. */
342 cp = s + strlen (s) - 1;
343 while (isdigit ((unsigned char) *cp) && cp > s)
348 strncpy (r, s, cp - s);
351 /* Count initial zeros. */
360 while (isdigit ((unsigned char) *cp))
363 *n = (*n * 10) + (*cp - '0');
368 if (*n == 0 && *d == 0)
370 msg (SE, _("incorrect use of TO convention"));
376 /* Parses a list of variable names according to the DATA LIST version
377 of the TO convention. */
379 parse_DATA_LIST_vars (char ***names, int *nnames, int pv_opts)
389 if (pv_opts & PV_APPEND)
390 nvar = mvar = *nnames;
397 name1 = xmalloc (36);
398 name2 = &name1[1 * 9];
399 root1 = &name1[2 * 9];
400 root2 = &name1[3 * 9];
405 lex_error ("expecting variable name");
408 if (tokid[0] == '#' && (pv_opts & PV_NO_SCRATCH))
410 msg (SE, _("Scratch variables not allowed here."));
413 strcpy (name1, tokid);
420 lex_error ("expecting variable name");
423 strcpy (name2, tokid);
426 if (!extract_num (name1, root1, &n1, &d1)
427 || !extract_num (name2, root2, &n2, &d2))
430 if (strcmp (root1, root2))
432 msg (SE, _("Prefixes don't match in use of TO convention."));
437 msg (SE, _("Bad bounds in use of TO convention."));
443 if (mvar < nvar + (n2 - n1 + 1))
445 mvar += ROUND_UP (n2 - n1 + 1, 16);
446 *names = xrealloc (*names, mvar * sizeof **names);
449 for (n = n1; n <= n2; n++)
451 (*names)[nvar] = xmalloc (9);
452 sprintf ((*names)[nvar], "%s%0*d", root1, d1, n);
461 *names = xrealloc (*names, mvar * sizeof **names);
463 (*names)[nvar++] = xstrdup (name1);
468 if (pv_opts & PV_SINGLE)
471 while (token == T_ID);
480 for (i = 0; i < nvar; i++)
489 /* Parses a list of variables where some of the variables may be
490 existing and the rest are to be created. Same args as
491 parse_variables(). */
493 parse_mixed_vars (char ***names, int *nnames, int pv_opts)
497 if (!(pv_opts & PV_APPEND))
502 while (token == T_ID || token == T_ALL)
504 if (token == T_ALL || is_varname (tokid))
509 if (!parse_variables (NULL, &v, &nv, PV_NONE))
511 *names = xrealloc (*names, (*nnames + nv) * sizeof **names);
512 for (i = 0; i < nv; i++)
513 (*names)[*nnames + i] = xstrdup (v[i]->name);
517 else if (!parse_DATA_LIST_vars (names, nnames, PV_APPEND))
523 for (i = 0; i < *nnames; i++)
524 free ((*names)[*nnames]);