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