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