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