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