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