New implementation of long variable names. Each variable has a
[pspp-builds.git] / src / dictionary.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 "dictionary.h"
22 #include <stdlib.h>
23 #include <ctype.h>
24 #include "algorithm.h"
25 #include "alloc.h"
26 #include "case.h"
27 #include "error.h"
28 #include "hash.h"
29 #include "misc.h"
30 #include "settings.h"
31 #include "str.h"
32 #include "value-labels.h"
33 #include "var.h"
34
35 /* A dictionary. */
36 struct dictionary
37   {
38     struct variable **var;      /* Variables. */
39     size_t var_cnt, var_cap;    /* Number of variables, capacity. */
40     struct hsh_table *name_tab; /* Variable index by name. */
41     int next_value_idx;         /* Index of next `union value' to allocate. */
42     struct variable **split;    /* SPLIT FILE vars. */
43     size_t split_cnt;           /* SPLIT FILE count. */
44     struct variable *weight;    /* WEIGHT variable. */
45     struct variable *filter;    /* FILTER variable. */
46     int case_limit;             /* Current case limit (N command). */
47     char *label;                /* File label. */
48     char *documents;            /* Documents, as a string. */
49     struct vector **vector;     /* Vectors of variables. */
50     size_t vector_cnt;          /* Number of vectors. */
51   };
52
53 /* Creates and returns a new dictionary. */
54 struct dictionary *
55 dict_create (void) 
56 {
57   struct dictionary *d = xmalloc (sizeof *d);
58   
59   d->var = NULL;
60   d->var_cnt = d->var_cap = 0;
61   d->name_tab = hsh_create (8, compare_var_names, hash_var_name, NULL, NULL);
62   d->next_value_idx = 0;
63   d->split = NULL;
64   d->split_cnt = 0;
65   d->weight = NULL;
66   d->filter = NULL;
67   d->case_limit = 0;
68   d->label = NULL;
69   d->documents = NULL;
70   d->vector = NULL;
71   d->vector_cnt = 0;
72
73   return d;
74 }
75
76 /* Creates and returns a (deep) copy of an existing
77    dictionary. */
78 struct dictionary *
79 dict_clone (const struct dictionary *s) 
80 {
81   struct dictionary *d;
82   size_t i;
83
84   assert (s != NULL);
85
86   d = dict_create ();
87
88   for (i = 0; i < s->var_cnt; i++) 
89     {
90       struct variable *sv = s->var[i];
91       struct variable *dv = dict_clone_var_assert (d, sv, sv->name);
92       var_set_short_name (dv, sv->short_name);
93     }
94
95   d->next_value_idx = s->next_value_idx;
96
97   d->split_cnt = s->split_cnt;
98   if (d->split_cnt > 0) 
99     {
100       d->split = xmalloc (d->split_cnt * sizeof *d->split);
101       for (i = 0; i < d->split_cnt; i++) 
102         d->split[i] = dict_lookup_var_assert (d, s->split[i]->name);
103     }
104
105   if (s->weight != NULL) 
106     d->weight = dict_lookup_var_assert (d, s->weight->name);
107
108   if (s->filter != NULL) 
109     d->filter = dict_lookup_var_assert (d, s->filter->name);
110
111   d->case_limit = s->case_limit;
112   dict_set_label (d, dict_get_label (s));
113   dict_set_documents (d, dict_get_documents (s));
114
115   d->vector_cnt = s->vector_cnt;
116   d->vector = xmalloc (d->vector_cnt * sizeof *d->vector);
117   for (i = 0; i < s->vector_cnt; i++) 
118     {
119       struct vector *sv = s->vector[i];
120       struct vector *dv = d->vector[i] = xmalloc (sizeof *dv);
121       int j;
122       
123       dv->idx = i;
124       strcpy (dv->name, sv->name);
125       dv->cnt = sv->cnt;
126       dv->var = xmalloc (dv->cnt * sizeof *dv->var);
127       for (j = 0; j < dv->cnt; j++)
128         dv->var[j] = d->var[sv->var[j]->index];
129     }
130
131   return d;
132 }
133
134 /* Clears the contents from a dictionary without destroying the
135    dictionary itself. */
136 void
137 dict_clear (struct dictionary *d) 
138 {
139   /* FIXME?  Should we really clear case_limit, label, documents?
140      Others are necessarily cleared by deleting all the variables.*/
141   int i;
142
143   assert (d != NULL);
144
145   for (i = 0; i < d->var_cnt; i++) 
146     {
147       struct variable *v = d->var[i];
148       var_clear_aux (v);
149       val_labs_destroy (v->val_labs);
150       free (v->label);
151       free (v); 
152     }
153   free (d->var);
154   d->var = NULL;
155   d->var_cnt = d->var_cap = 0;
156   hsh_clear (d->name_tab);
157   d->next_value_idx = 0;
158   free (d->split);
159   d->split = NULL;
160   d->split_cnt = 0;
161   d->weight = NULL;
162   d->filter = NULL;
163   d->case_limit = 0;
164   free (d->label);
165   d->label = NULL;
166   free (d->documents);
167   d->documents = NULL;
168   dict_clear_vectors (d);
169 }
170
171 /* Destroys the aux data for every variable in D, by calling
172    var_clear_aux() for each variable. */
173 void
174 dict_clear_aux (struct dictionary *d) 
175 {
176   int i;
177   
178   assert (d != NULL);
179   
180   for (i = 0; i < d->var_cnt; i++)
181     var_clear_aux (d->var[i]);
182 }
183
184 /* Clears a dictionary and destroys it. */
185 void
186 dict_destroy (struct dictionary *d)
187 {
188   if (d != NULL) 
189     {
190       dict_clear (d);
191       hsh_destroy (d->name_tab);
192       free (d);
193     }
194 }
195
196 /* Returns the number of variables in D. */
197 size_t
198 dict_get_var_cnt (const struct dictionary *d) 
199 {
200   assert (d != NULL);
201
202   return d->var_cnt;
203 }
204
205 /* Returns the variable in D with index IDX, which must be
206    between 0 and the count returned by dict_get_var_cnt(),
207    exclusive. */
208 struct variable *
209 dict_get_var (const struct dictionary *d, size_t idx) 
210 {
211   assert (d != NULL);
212   assert (idx < d->var_cnt);
213
214   return d->var[idx];
215 }
216
217 /* Sets *VARS to an array of pointers to variables in D and *CNT
218    to the number of variables in *D.  By default all variables
219    are returned, but bits may be set in EXCLUDE_CLASSES to
220    exclude ordinary, system, and/or scratch variables. */
221 void
222 dict_get_vars (const struct dictionary *d, struct variable ***vars,
223                size_t *cnt, unsigned exclude_classes)
224 {
225   size_t count;
226   size_t i;
227   
228   assert (d != NULL);
229   assert (vars != NULL);
230   assert (cnt != NULL);
231   assert ((exclude_classes & ~((1u << DC_ORDINARY)
232                                | (1u << DC_SYSTEM)
233                                | (1u << DC_SCRATCH))) == 0);
234   
235   count = 0;
236   for (i = 0; i < d->var_cnt; i++)
237     if (!(exclude_classes & (1u << dict_class_from_id (d->var[i]->name))))
238       count++;
239
240   *vars = xmalloc (count * sizeof **vars);
241   *cnt = 0;
242   for (i = 0; i < d->var_cnt; i++)
243     if (!(exclude_classes & (1u << dict_class_from_id (d->var[i]->name))))
244       (*vars)[(*cnt)++] = d->var[i];
245   assert (*cnt == count);
246 }
247
248
249 /* Creates and returns a new variable in D with the given NAME
250    and WIDTH.  Returns a null pointer if the given NAME would
251    duplicate that of an existing variable in the dictionary. */
252 struct variable *
253 dict_create_var (struct dictionary *d, const char *name, int width)
254 {
255   struct variable *v;
256
257   assert (d != NULL);
258   assert (name != NULL);
259
260   assert (strlen (name) >= 1);
261   assert (strlen (name) <= LONG_NAME_LEN);
262
263   assert (width >= 0 && width < 256);
264     
265   /* Make sure there's not already a variable by that name. */
266   if (dict_lookup_var (d, name) != NULL)
267     return NULL;
268
269   /* Allocate and initialize variable. */
270   v = xmalloc (sizeof *v);
271   st_trim_copy (v->name, name, sizeof v->name);
272   v->type = width == 0 ? NUMERIC : ALPHA;
273   v->width = width;
274   v->fv = d->next_value_idx;
275   v->nv = width == 0 ? 1 : DIV_RND_UP (width, 8);
276   v->init = 1;
277   v->reinit = dict_class_from_id (v->name) != DC_SCRATCH;
278   v->index = d->var_cnt;
279   v->miss_type = MISSING_NONE;
280   if (v->type == NUMERIC)
281     {
282       v->print.type = FMT_F;
283       v->print.w = 8;
284       v->print.d = 2;
285
286       v->alignment = ALIGN_RIGHT;
287       v->display_width = 8;
288       v->measure = MEASURE_SCALE;
289     }
290   else
291     {
292       v->print.type = FMT_A;
293       v->print.w = v->width;
294       v->print.d = 0;
295
296       v->alignment = ALIGN_LEFT;
297       v->display_width = 8;
298       v->measure = MEASURE_NOMINAL;
299     }
300   v->write = v->print;
301   v->val_labs = val_labs_create (v->width);
302   v->label = NULL;
303   var_clear_short_name (v);
304   v->aux = NULL;
305   v->aux_dtor = NULL;
306
307   /* Update dictionary. */
308   if (d->var_cnt >= d->var_cap) 
309     {
310       d->var_cap = 8 + 2 * d->var_cap; 
311       d->var = xrealloc (d->var, d->var_cap * sizeof *d->var);
312     }
313   d->var[v->index] = v;
314   d->var_cnt++;
315   hsh_force_insert (d->name_tab, v);
316
317   d->next_value_idx += v->nv;
318
319   return v;
320 }
321
322 /* Creates and returns a new variable in D with the given NAME
323    and WIDTH.  Assert-fails if the given NAME would duplicate
324    that of an existing variable in the dictionary. */
325 struct variable *
326 dict_create_var_assert (struct dictionary *d, const char *name, int width)
327 {
328   struct variable *v = dict_create_var (d, name, width);
329   assert (v != NULL);
330   return v;
331 }
332
333 /* Creates and returns a new variable in D with name NAME, as a
334    copy of existing variable OV, which need not be in D or in any
335    dictionary.  Returns a null pointer if the given NAME would
336    duplicate that of an existing variable in the dictionary. */
337 struct variable *
338 dict_clone_var (struct dictionary *d, const struct variable *ov,
339                 const char *name)
340 {
341   struct variable *nv;
342
343   assert (d != NULL);
344   assert (ov != NULL);
345   assert (name != NULL);
346
347   assert (strlen (name) >= 1);
348   assert (strlen (name) <= LONG_NAME_LEN);
349
350   nv = dict_create_var (d, name, ov->width);
351   if (nv == NULL)
352     return NULL;
353
354   /* Copy most members not copied via dict_create_var().
355      short_name[] is intentionally not copied, because there is
356      no reason to give a new variable with potentially a new name
357      the same short name. */
358   nv->init = 1;
359   nv->reinit = ov->reinit;
360   nv->miss_type = ov->miss_type;
361   memcpy (nv->missing, ov->missing, sizeof nv->missing);
362   nv->print = ov->print;
363   nv->write = ov->write;
364   val_labs_destroy (nv->val_labs);
365   nv->val_labs = val_labs_copy (ov->val_labs);
366   if (ov->label != NULL)
367     nv->label = xstrdup (ov->label);
368   nv->measure = ov->measure;
369   nv->display_width = ov->display_width;
370   nv->alignment = ov->alignment;
371
372   return nv;
373 }
374
375 /* Creates and returns a new variable in D with name NAME, as a
376    copy of existing variable OV, which need not be in D or in any
377    dictionary.  Assert-fails if the given NAME would duplicate
378    that of an existing variable in the dictionary. */
379 struct variable *
380 dict_clone_var_assert (struct dictionary *d, const struct variable *ov,
381                        const char *name)
382 {
383   struct variable *v = dict_clone_var (d, ov, name);
384   assert (v != NULL);
385   return v;
386 }
387
388 /* Returns the variable named NAME in D, or a null pointer if no
389    variable has that name. */
390 struct variable *
391 dict_lookup_var (const struct dictionary *d, const char *name)
392 {
393   struct variable v;
394   
395   assert (d != NULL);
396   assert (name != NULL);
397
398   st_trim_copy (v.name, name, sizeof v.name);
399   return hsh_find (d->name_tab, &v);
400 }
401
402 /* Returns the variable named NAME in D.  Assert-fails if no
403    variable has that name. */
404 struct variable *
405 dict_lookup_var_assert (const struct dictionary *d, const char *name)
406 {
407   struct variable *v = dict_lookup_var (d, name);
408   assert (v != NULL);
409   return v;
410 }
411
412 /* Returns nonzero if variable V is in dictionary D. */
413 int
414 dict_contains_var (const struct dictionary *d, const struct variable *v)
415 {
416   assert (d != NULL);
417   assert (v != NULL);
418
419   return v->index >= 0 && v->index < d->var_cnt && d->var[v->index] == v;
420 }
421
422 /* Compares two double pointers to variables, which should point
423    to elements of a struct dictionary's `var' member array. */
424 static int
425 compare_var_ptrs (const void *a_, const void *b_, void *aux UNUSED) 
426 {
427   struct variable *const *a = a_;
428   struct variable *const *b = b_;
429
430   return *a < *b ? -1 : *a > *b;
431 }
432
433 /* Deletes variable V from dictionary D and frees V.
434
435    This is a very bad idea if there might be any pointers to V
436    from outside D.  In general, no variable in default_dict
437    should be deleted when any transformations are active, because
438    those transformations might reference the deleted variable.
439    The safest time to delete a variable is just after a procedure
440    has been executed, as done by MODIFY VARS.
441
442    Pointers to V within D are not a problem, because
443    dict_delete_var() knows to remove V from split variables,
444    weights, filters, etc. */
445 void
446 dict_delete_var (struct dictionary *d, struct variable *v) 
447 {
448   size_t i;
449
450   assert (d != NULL);
451   assert (v != NULL);
452   assert (dict_contains_var (d, v));
453   assert (d->var[v->index] == v);
454
455   /* Delete aux data. */
456   var_clear_aux (v);
457
458   /* Remove V from splits, weight, filter variables. */
459   d->split_cnt = remove_equal (d->split, d->split_cnt, sizeof *d->split,
460                                &v, compare_var_ptrs, NULL);
461   if (d->weight == v)
462     d->weight = NULL;
463   if (d->filter == v)
464     d->filter = NULL;
465   dict_clear_vectors (d);
466
467   /* Remove V from var array. */
468   remove_element (d->var, d->var_cnt, sizeof *d->var, v->index);
469   d->var_cnt--;
470
471   /* Update index. */
472   for (i = v->index; i < d->var_cnt; i++)
473     d->var[i]->index = i;
474
475   /* Update name hash. */
476   hsh_force_delete (d->name_tab, v);
477
478   /* Free memory. */
479   val_labs_destroy (v->val_labs);
480   free (v->label);
481   free (v);
482 }
483
484 /* Deletes the COUNT variables listed in VARS from D.  This is
485    unsafe; see the comment on dict_delete_var() for details. */
486 void 
487 dict_delete_vars (struct dictionary *d,
488                   struct variable *const *vars, size_t count) 
489 {
490   /* FIXME: this can be done in O(count) time, but this algorithm
491      is O(count**2). */
492   assert (d != NULL);
493   assert (count == 0 || vars != NULL);
494
495   while (count-- > 0)
496     dict_delete_var (d, *vars++);
497 }
498
499 /* Moves V to 0-based position IDX in D.  Other variables in D,
500    if any, retain their relative positions.  Runs in time linear
501    in the distance moved. */
502 void
503 dict_reorder_var (struct dictionary *d, struct variable *v,
504                   size_t new_index) 
505 {
506   size_t min_idx, max_idx;
507   size_t i;
508   
509   assert (d != NULL);
510   assert (v != NULL);
511   assert (dict_contains_var (d, v));
512   assert (new_index < d->var_cnt);
513
514   move_element (d->var, d->var_cnt, sizeof *d->var, v->index, new_index);
515
516   min_idx = min (v->index, new_index);
517   max_idx = max (v->index, new_index);
518   for (i = min_idx; i <= max_idx; i++)
519     d->var[i]->index = i;
520 }
521
522 /* Reorders the variables in D, placing the COUNT variables
523    listed in ORDER in that order at the beginning of D.  The
524    other variables in D, if any, retain their relative
525    positions. */
526 void 
527 dict_reorder_vars (struct dictionary *d,
528                    struct variable *const *order, size_t count) 
529 {
530   struct variable **new_var;
531   size_t i;
532   
533   assert (d != NULL);
534   assert (count == 0 || order != NULL);
535   assert (count <= d->var_cnt);
536
537   new_var = xmalloc (d->var_cnt * sizeof *new_var);
538   memcpy (new_var, order, count * sizeof *new_var);
539   for (i = 0; i < count; i++) 
540     {
541       assert (d->var[order[i]->index] != NULL);
542       d->var[order[i]->index] = NULL;
543       order[i]->index = i;
544     }
545   for (i = 0; i < d->var_cnt; i++)
546     if (d->var[i] != NULL)
547       {
548         assert (count < d->var_cnt);
549         new_var[count] = d->var[i];
550         new_var[count]->index = count;
551         count++;
552       }
553   free (d->var);
554   d->var = new_var;
555 }
556
557 /* Changes the name of V in D to name NEW_NAME.  Assert-fails if
558    a variable named NEW_NAME is already in D, except that
559    NEW_NAME may be the same as V's existing name. */
560 void 
561 dict_rename_var (struct dictionary *d, struct variable *v,
562                  const char *new_name) 
563 {
564   assert (d != NULL);
565   assert (v != NULL);
566   assert (new_name != NULL);
567   assert (var_is_valid_name (new_name, false));
568   assert (dict_contains_var (d, v));
569   assert (!compare_var_names (v->name, new_name, NULL)
570           || dict_lookup_var (d, new_name) == NULL);
571
572   hsh_force_delete (d->name_tab, v);
573   st_trim_copy (v->name, new_name, sizeof v->name);
574   hsh_force_insert (d->name_tab, v);
575
576   if (get_algorithm () == ENHANCED)
577     var_clear_short_name (v);
578 }
579
580 /* Renames COUNT variables specified in VARS to the names given
581    in NEW_NAMES within dictionary D.  If the renaming would
582    result in a duplicate variable name, returns zero and stores a
583    name that would be duplicated into *ERR_NAME (if ERR_NAME is
584    non-null).  Otherwise, the renaming is successful, and nonzero
585    is returned. */
586 int
587 dict_rename_vars (struct dictionary *d,
588                   struct variable **vars, char **new_names,
589                   size_t count, char **err_name) 
590 {
591   char **old_names;
592   size_t i;
593   int success = 1;
594
595   assert (d != NULL);
596   assert (count == 0 || vars != NULL);
597   assert (count == 0 || new_names != NULL);
598
599   /* Remove the variables to be renamed from the name hash,
600      save their names, and rename them. */
601   old_names = xmalloc (count * sizeof *old_names);
602   for (i = 0; i < count; i++) 
603     {
604       assert (d->var[vars[i]->index] == vars[i]);
605       assert (var_is_valid_name (new_names[i], false));
606       hsh_force_delete (d->name_tab, vars[i]);
607       old_names[i] = xstrdup (vars[i]->name);
608       strcpy (vars[i]->name, new_names[i]);
609     }
610
611   /* Add the renamed variables back into the name hash,
612      checking for conflicts. */
613   for (i = 0; i < count; i++)
614     {
615       assert (new_names[i] != NULL);
616       assert (*new_names[i] != '\0');
617       assert (strlen (new_names[i]) >= 1);
618       assert (strlen (new_names[i]) <= LONG_NAME_LEN);
619
620       if (hsh_insert (d->name_tab, vars[i]) != NULL)
621         {
622           /* There is a name conflict.
623              Back out all the name changes that have already
624              taken place, and indicate failure. */
625           size_t fail_idx = i;
626           if (err_name != NULL) 
627             *err_name = new_names[i];
628
629           for (i = 0; i < fail_idx; i++)
630             hsh_force_delete (d->name_tab, vars[i]);
631           
632           for (i = 0; i < count; i++)
633             {
634               strcpy (vars[i]->name, old_names[i]);
635               hsh_force_insert (d->name_tab, vars[i]);
636             }
637
638           success = 0;
639           goto done;
640         }
641     }
642
643   /* Clear short names. */
644   if (get_algorithm () == ENHANCED)
645     for (i = 0; i < count; i++)
646       var_clear_short_name (vars[i]);
647
648  done:
649   /* Free the old names we kept around. */
650   for (i = 0; i < count; i++)
651     free (old_names[i]);
652   free (old_names);
653
654   return success;
655 }
656
657 /* Returns the weighting variable in dictionary D, or a null
658    pointer if the dictionary is unweighted. */
659 struct variable *
660 dict_get_weight (const struct dictionary *d) 
661 {
662   assert (d != NULL);
663   assert (d->weight == NULL || dict_contains_var (d, d->weight));
664   
665   return d->weight;
666 }
667
668 /* Returns the value of D's weighting variable in case C, except that a
669    negative weight is returned as 0.  Returns 1 if the dictionary is
670    unweighted. Will warn about missing, negative, or zero values if
671    warn_on_invalid is nonzero. The function will set warn_on_invalid to zero
672    if an invalid weight is found. */
673 double
674 dict_get_case_weight (const struct dictionary *d, const struct ccase *c, 
675                       int *warn_on_invalid)
676 {
677   assert (d != NULL);
678   assert (c != NULL);
679
680   if (d->weight == NULL)
681     return 1.0;
682   else 
683     {
684       double w = case_num (c, d->weight->fv);
685       if ( w < 0.0 || w == SYSMIS || is_num_user_missing(w, d->weight) )
686         w = 0.0;
687       if ( w == 0.0 && *warn_on_invalid ) {
688           *warn_on_invalid = 0;
689           msg (SW, _("At least one case in the data file had a weight value "
690                      "that was user-missing, system-missing, zero, or "
691                      "negative.  These case(s) were ignored."));
692       }
693       return w;
694     }
695 }
696
697 /* Sets the weighting variable of D to V, or turning off
698    weighting if V is a null pointer. */
699 void
700 dict_set_weight (struct dictionary *d, struct variable *v) 
701 {
702   assert (d != NULL);
703   assert (v == NULL || dict_contains_var (d, v));
704   assert (v == NULL || v->type == NUMERIC);
705
706   d->weight = v;
707 }
708
709 /* Returns the filter variable in dictionary D (see cmd_filter())
710    or a null pointer if the dictionary is unfiltered. */
711 struct variable *
712 dict_get_filter (const struct dictionary *d) 
713 {
714   assert (d != NULL);
715   assert (d->filter == NULL || dict_contains_var (d, d->filter));
716   
717   return d->filter;
718 }
719
720 /* Sets V as the filter variable for dictionary D.  Passing a
721    null pointer for V turn off filtering. */
722 void
723 dict_set_filter (struct dictionary *d, struct variable *v)
724 {
725   assert (d != NULL);
726   assert (v == NULL || dict_contains_var (d, v));
727
728   d->filter = v;
729 }
730
731 /* Returns the case limit for dictionary D, or zero if the number
732    of cases is unlimited (see cmd_n()). */
733 int
734 dict_get_case_limit (const struct dictionary *d) 
735 {
736   assert (d != NULL);
737
738   return d->case_limit;
739 }
740
741 /* Sets CASE_LIMIT as the case limit for dictionary D.  Zero for
742    CASE_LIMIT indicates no limit. */
743 void
744 dict_set_case_limit (struct dictionary *d, int case_limit) 
745 {
746   assert (d != NULL);
747   assert (case_limit >= 0);
748
749   d->case_limit = case_limit;
750 }
751
752 /* Returns the index of the next value to be added to D.  This
753    value is the number of `union value's that need to be
754    allocated to store a case for dictionary D. */
755 int
756 dict_get_next_value_idx (const struct dictionary *d) 
757 {
758   assert (d != NULL);
759
760   return d->next_value_idx;
761 }
762
763 /* Returns the number of bytes needed to store a case for
764    dictionary D. */
765 size_t
766 dict_get_case_size (const struct dictionary *d) 
767 {
768   assert (d != NULL);
769
770   return sizeof (union value) * dict_get_next_value_idx (d);
771 }
772
773 /* Deletes scratch variables in dictionary D and reassigns values
774    so that fragmentation is eliminated. */
775 void
776 dict_compact_values (struct dictionary *d) 
777 {
778   size_t i;
779
780   d->next_value_idx = 0;
781   for (i = 0; i < d->var_cnt; )
782     {
783       struct variable *v = d->var[i];
784
785       if (dict_class_from_id (v->name) != DC_SCRATCH) 
786         {
787           v->fv = d->next_value_idx;
788           d->next_value_idx += v->nv;
789           i++;
790         }
791       else
792         dict_delete_var (default_dict, v);
793     }
794 }
795
796 /* Copies values from SRC, which represents a case arranged
797    according to dictionary D, to DST, which represents a case
798    arranged according to the dictionary that will be produced by
799    dict_compact_values(D). */
800 void
801 dict_compact_case (const struct dictionary *d,
802                    struct ccase *dst, const struct ccase *src)
803 {
804   size_t i;
805   size_t value_idx;
806
807   value_idx = 0;
808   for (i = 0; i < d->var_cnt; i++) 
809     {
810       struct variable *v = d->var[i];
811
812       if (dict_class_from_id (v->name) != DC_SCRATCH)
813         {
814           case_copy (dst, value_idx, src, v->fv, v->nv);
815           value_idx += v->nv;
816         }
817     }
818 }
819
820 /* Returns the number of values that would be used by a case if
821    dict_compact_values() were called. */
822 size_t
823 dict_get_compacted_value_cnt (const struct dictionary *d) 
824 {
825   size_t i;
826   size_t cnt;
827
828   cnt = 0;
829   for (i = 0; i < d->var_cnt; i++)
830     if (dict_class_from_id (d->var[i]->name) != DC_SCRATCH) 
831       cnt += d->var[i]->nv;
832   return cnt;
833 }
834
835 /* Creates and returns an array mapping from a dictionary index
836    to the `fv' that the corresponding variable will have after
837    calling dict_compact_values().  Scratch variables receive -1
838    for `fv' because dict_compact_values() will delete them. */
839 int *
840 dict_get_compacted_idx_to_fv (const struct dictionary *d) 
841 {
842   size_t i;
843   size_t next_value_idx;
844   int *idx_to_fv;
845   
846   idx_to_fv = xmalloc (d->var_cnt * sizeof *idx_to_fv);
847   next_value_idx = 0;
848   for (i = 0; i < d->var_cnt; i++)
849     {
850       struct variable *v = d->var[i];
851
852       if (dict_class_from_id (v->name) != DC_SCRATCH) 
853         {
854           idx_to_fv[i] = next_value_idx;
855           next_value_idx += v->nv;
856         }
857       else 
858         idx_to_fv[i] = -1;
859     }
860   return idx_to_fv;
861 }
862
863 /* Returns the SPLIT FILE vars (see cmd_split_file()).  Call
864    dict_get_split_cnt() to determine how many SPLIT FILE vars
865    there are.  Returns a null pointer if and only if there are no
866    SPLIT FILE vars. */
867 struct variable *const *
868 dict_get_split_vars (const struct dictionary *d) 
869 {
870   assert (d != NULL);
871   
872   return d->split;
873 }
874
875 /* Returns the number of SPLIT FILE vars. */
876 size_t
877 dict_get_split_cnt (const struct dictionary *d) 
878 {
879   assert (d != NULL);
880
881   return d->split_cnt;
882 }
883
884 /* Sets CNT split vars SPLIT in dictionary D. */
885 void
886 dict_set_split_vars (struct dictionary *d,
887                      struct variable *const *split, size_t cnt)
888 {
889   assert (d != NULL);
890   assert (cnt == 0 || split != NULL);
891
892   d->split_cnt = cnt;
893   d->split = xrealloc (d->split, cnt * sizeof *d->split);
894   memcpy (d->split, split, cnt * sizeof *d->split);
895 }
896
897 /* Returns the file label for D, or a null pointer if D is
898    unlabeled (see cmd_file_label()). */
899 const char *
900 dict_get_label (const struct dictionary *d) 
901 {
902   assert (d != NULL);
903
904   return d->label;
905 }
906
907 /* Sets D's file label to LABEL, truncating it to a maximum of 60
908    characters. */
909 void
910 dict_set_label (struct dictionary *d, const char *label) 
911 {
912   assert (d != NULL);
913
914   free (d->label);
915   if (label == NULL)
916     d->label = NULL;
917   else if (strlen (label) < 60)
918     d->label = xstrdup (label);
919   else 
920     {
921       d->label = xmalloc (61);
922       memcpy (d->label, label, 60);
923       d->label[60] = '\0';
924     }
925 }
926
927 /* Returns the documents for D, or a null pointer if D has no
928    documents (see cmd_document()).. */
929 const char *
930 dict_get_documents (const struct dictionary *d) 
931 {
932   assert (d != NULL);
933
934   return d->documents;
935 }
936
937 /* Sets the documents for D to DOCUMENTS, or removes D's
938    documents if DOCUMENT is a null pointer. */
939 void
940 dict_set_documents (struct dictionary *d, const char *documents)
941 {
942   assert (d != NULL);
943
944   free (d->documents);
945   if (documents == NULL)
946     d->documents = NULL;
947   else
948     d->documents = xstrdup (documents);
949 }
950
951 /* Creates in D a vector named NAME that contains CNT variables
952    VAR (see cmd_vector()).  Returns nonzero if successful, or
953    zero if a vector named NAME already exists in D. */
954 int
955 dict_create_vector (struct dictionary *d,
956                     const char *name,
957                     struct variable **var, size_t cnt) 
958 {
959   struct vector *vector;
960   size_t i;
961
962   assert (d != NULL);
963   assert (name != NULL);
964   assert (var_is_valid_name (name, false));
965   assert (var != NULL);
966   assert (cnt > 0);
967   
968   if (dict_lookup_vector (d, name) != NULL)
969     return 0;
970
971   d->vector = xrealloc (d->vector, (d->vector_cnt + 1) * sizeof *d->vector);
972   vector = d->vector[d->vector_cnt] = xmalloc (sizeof *vector);
973   vector->idx = d->vector_cnt++;
974   st_trim_copy (vector->name, name, sizeof vector->name);
975   vector->var = xmalloc (cnt * sizeof *var);
976   for (i = 0; i < cnt; i++)
977     {
978       assert (dict_contains_var (d, var[i]));
979       vector->var[i] = var[i];
980     }
981   vector->cnt = cnt;
982   
983   return 1;
984 }
985
986 /* Returns the vector in D with index IDX, which must be less
987    than dict_get_vector_cnt (D). */
988 const struct vector *
989 dict_get_vector (const struct dictionary *d, size_t idx) 
990 {
991   assert (d != NULL);
992   assert (idx < d->vector_cnt);
993
994   return d->vector[idx];
995 }
996
997 /* Returns the number of vectors in D. */
998 size_t
999 dict_get_vector_cnt (const struct dictionary *d) 
1000 {
1001   assert (d != NULL);
1002
1003   return d->vector_cnt;
1004 }
1005
1006 /* Looks up and returns the vector within D with the given
1007    NAME. */
1008 const struct vector *
1009 dict_lookup_vector (const struct dictionary *d, const char *name) 
1010 {
1011   size_t i;
1012
1013   assert (d != NULL);
1014   assert (name != NULL);
1015
1016   for (i = 0; i < d->vector_cnt; i++)
1017     if (!strcasecmp (d->vector[i]->name, name))
1018       return d->vector[i];
1019   return NULL;
1020 }
1021
1022 /* Deletes all vectors from D. */
1023 void
1024 dict_clear_vectors (struct dictionary *d) 
1025 {
1026   size_t i;
1027   
1028   assert (d != NULL);
1029
1030   for (i = 0; i < d->vector_cnt; i++) 
1031     {
1032       free (d->vector[i]->var);
1033       free (d->vector[i]);
1034     }
1035   free (d->vector);
1036   d->vector = NULL;
1037   d->vector_cnt = 0;
1038 }
1039
1040 /* Compares two strings. */
1041 static int
1042 compare_strings (const void *a, const void *b, void *aux UNUSED) 
1043 {
1044   return strcmp (a, b);
1045 }
1046
1047 /* Hashes a string. */
1048 static unsigned
1049 hash_string (const void *s, void *aux UNUSED) 
1050 {
1051   return hsh_hash_string (s);
1052 }
1053
1054 /* Assigns a valid, unique short_name[] to each variable in D.
1055    Each variable whose actual name is short has highest priority
1056    for that short name.  Otherwise, variables with an existing
1057    short_name[] have the next highest priority for a given short
1058    name; if it is already taken, then the variable is treated as
1059    if short_name[] had been empty.  Otherwise, long names are
1060    truncated to form short names.  If that causes conflicts,
1061    variables are renamed as PREFIX_A, PREFIX_B, and so on. */
1062 void
1063 dict_assign_short_names (struct dictionary *d) 
1064 {
1065   struct hsh_table *short_names;
1066   size_t i;
1067
1068   /* Give variables whose names are short the corresponding short
1069      names, and clear short_names[] that conflict with a variable
1070      name. */
1071   for (i = 0; i < d->var_cnt; i++)
1072     {
1073       struct variable *v = d->var[i];
1074       if (strlen (v->name) <= SHORT_NAME_LEN)
1075         var_set_short_name (v, v->name);
1076       else if (dict_lookup_var (d, v->short_name) != NULL)
1077         var_clear_short_name (v);
1078     }
1079
1080   /* Each variable with an assigned short_name[] now gets it
1081      unless there is a conflict. */
1082   short_names = hsh_create (d->var_cnt, compare_strings, hash_string,
1083                             NULL, NULL);
1084   for (i = 0; i < d->var_cnt; i++)
1085     {
1086       struct variable *v = d->var[i];
1087       if (v->short_name[0] && hsh_insert (short_names, v->short_name) != NULL)
1088         var_clear_short_name (v);
1089     }
1090   
1091   /* Now assign short names to remaining variables. */
1092   for (i = 0; i < d->var_cnt; i++)
1093     {
1094       struct variable *v = d->var[i];
1095       if (v->short_name[0] == '\0') 
1096         {
1097           int sfx;
1098
1099           /* Form initial short_name. */
1100           var_set_short_name (v, v->name);
1101
1102           /* Try _A, _B, ... _AA, _AB, etc., if needed. */
1103           for (sfx = 0; hsh_insert (short_names, v->short_name) != NULL; sfx++)
1104             var_set_short_name_suffix (v, v->name, sfx);
1105         } 
1106     }
1107
1108   /* Get rid of hash table. */
1109   hsh_destroy (short_names);
1110 }