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