str: Make str_format_26adic() able to use lowercase.
[pspp] / src / data / dictionary.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 1997-9, 2000, 2006, 2007, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc.
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
16
17 #include <config.h>
18
19 #include "data/dictionary.h"
20
21 #include <stdint.h>
22 #include <stdlib.h>
23 #include <ctype.h>
24 #include <unistr.h>
25
26 #include "data/attributes.h"
27 #include "data/case.h"
28 #include "data/identifier.h"
29 #include "data/mrset.h"
30 #include "data/settings.h"
31 #include "data/value-labels.h"
32 #include "data/vardict.h"
33 #include "data/variable.h"
34 #include "data/vector.h"
35 #include "libpspp/array.h"
36 #include "libpspp/assertion.h"
37 #include "libpspp/compiler.h"
38 #include "libpspp/hash-functions.h"
39 #include "libpspp/hmap.h"
40 #include "libpspp/i18n.h"
41 #include "libpspp/message.h"
42 #include "libpspp/misc.h"
43 #include "libpspp/pool.h"
44 #include "libpspp/str.h"
45 #include "libpspp/string-array.h"
46
47 #include "gl/intprops.h"
48 #include "gl/minmax.h"
49 #include "gl/xalloc.h"
50 #include "gl/xmemdup0.h"
51
52 #include "gettext.h"
53 #define _(msgid) gettext (msgid)
54
55 /* A dictionary. */
56 struct dictionary
57   {
58     struct vardict_info *var;   /* Variables. */
59     size_t var_cnt, var_cap;    /* Number of variables, capacity. */
60     struct caseproto *proto;    /* Prototype for dictionary cases
61                                    (updated lazily). */
62     struct hmap name_map;       /* Variable index by name. */
63     int next_value_idx;         /* Index of next `union value' to allocate. */
64     const struct variable **split;    /* SPLIT FILE vars. */
65     size_t split_cnt;           /* SPLIT FILE count. */
66     struct variable *weight;    /* WEIGHT variable. */
67     struct variable *filter;    /* FILTER variable. */
68     casenumber case_limit;      /* Current case limit (N command). */
69     char *label;                /* File label. */
70     struct string_array documents; /* Documents. */
71     struct vector **vector;     /* Vectors of variables. */
72     size_t vector_cnt;          /* Number of vectors. */
73     struct attrset attributes;  /* Custom attributes. */
74     struct mrset **mrsets;      /* Multiple response sets. */
75     size_t n_mrsets;            /* Number of multiple response sets. */
76
77     char *encoding;             /* Character encoding of string data */
78
79     const struct dict_callbacks *callbacks; /* Callbacks on dictionary
80                                                modification */
81     void *cb_data ;                  /* Data passed to callbacks */
82
83     void (*changed) (struct dictionary *, void *); /* Generic change callback */
84     void *changed_data;
85   };
86
87 static void dict_unset_split_var (struct dictionary *, struct variable *);
88 static void dict_unset_mrset_var (struct dictionary *, struct variable *);
89
90 /* Returns the encoding for data in dictionary D.  The return value is a
91    nonnull string that contains an IANA character set name. */
92 const char *
93 dict_get_encoding (const struct dictionary *d)
94 {
95   return d->encoding ;
96 }
97
98 /* Returns true if UTF-8 string ID is an acceptable identifier in DICT's
99    encoding, false otherwise.  If ISSUE_ERROR is true, issues an explanatory
100    error message on failure. */
101 bool
102 dict_id_is_valid (const struct dictionary *dict, const char *id,
103                   bool issue_error)
104 {
105   return id_is_valid (id, dict->encoding, issue_error);
106 }
107
108 void
109 dict_set_change_callback (struct dictionary *d,
110                           void (*changed) (struct dictionary *, void*),
111                           void *data)
112 {
113   d->changed = changed;
114   d->changed_data = data;
115 }
116
117 /* Discards dictionary D's caseproto.  (It will be regenerated
118    lazily, on demand.) */
119 static void
120 invalidate_proto (struct dictionary *d)
121 {
122   caseproto_unref (d->proto);
123   d->proto = NULL;
124 }
125
126 /* Print a representation of dictionary D to stdout, for
127    debugging purposes. */
128 void
129 dict_dump (const struct dictionary *d)
130 {
131   int i;
132   for (i = 0 ; i < d->var_cnt ; ++i )
133     {
134       const struct variable *v = d->var[i].var;
135       printf ("Name: %s;\tdict_idx: %zu; case_idx: %zu\n",
136               var_get_name (v),
137               var_get_dict_index (v),
138               var_get_case_index (v));
139
140     }
141 }
142
143 /* Associate CALLBACKS with DICT.  Callbacks will be invoked whenever
144    the dictionary or any of the variables it contains are modified.
145    Each callback will get passed CALLBACK_DATA.
146    Any callback may be NULL, in which case it'll be ignored.
147 */
148 void
149 dict_set_callbacks (struct dictionary *dict,
150                     const struct dict_callbacks *callbacks,
151                     void *callback_data)
152 {
153   dict->callbacks = callbacks;
154   dict->cb_data = callback_data;
155 }
156
157 /* Shallow copy the callbacks from SRC to DEST */
158 void
159 dict_copy_callbacks (struct dictionary *dest,
160                      const struct dictionary *src)
161 {
162   dest->callbacks = src->callbacks;
163   dest->cb_data = src->cb_data;
164 }
165
166 /* Creates and returns a new dictionary with the specified ENCODING. */
167 struct dictionary *
168 dict_create (const char *encoding)
169 {
170   struct dictionary *d = xzalloc (sizeof *d);
171
172   d->encoding = xstrdup (encoding);
173   hmap_init (&d->name_map);
174   attrset_init (&d->attributes);
175
176   return d;
177 }
178
179 /* Creates and returns a (deep) copy of an existing
180    dictionary.
181
182    The new dictionary's case indexes are copied from the old
183    dictionary.  If the new dictionary won't be used to access
184    cases produced with the old dictionary, then the new
185    dictionary's case indexes should be compacted with
186    dict_compact_values to save space.
187
188    Callbacks are not cloned. */
189 struct dictionary *
190 dict_clone (const struct dictionary *s)
191 {
192   struct dictionary *d;
193   size_t i;
194
195   d = dict_create (s->encoding);
196
197   for (i = 0; i < s->var_cnt; i++)
198     {
199       struct variable *sv = s->var[i].var;
200       struct variable *dv = dict_clone_var_assert (d, sv);
201       size_t i;
202
203       for (i = 0; i < var_get_short_name_cnt (sv); i++)
204         var_set_short_name (dv, i, var_get_short_name (sv, i));
205
206       var_get_vardict (dv)->case_index = var_get_vardict (sv)->case_index;
207     }
208
209   d->next_value_idx = s->next_value_idx;
210
211   d->split_cnt = s->split_cnt;
212   if (d->split_cnt > 0)
213     {
214       d->split = xnmalloc (d->split_cnt, sizeof *d->split);
215       for (i = 0; i < d->split_cnt; i++)
216         d->split[i] = dict_lookup_var_assert (d, var_get_name (s->split[i]));
217     }
218
219   if (s->weight != NULL)
220     dict_set_weight (d, dict_lookup_var_assert (d, var_get_name (s->weight)));
221
222   if (s->filter != NULL)
223     dict_set_filter (d, dict_lookup_var_assert (d, var_get_name (s->filter)));
224
225   d->case_limit = s->case_limit;
226   dict_set_label (d, dict_get_label (s));
227   dict_set_documents (d, dict_get_documents (s));
228
229   d->vector_cnt = s->vector_cnt;
230   d->vector = xnmalloc (d->vector_cnt, sizeof *d->vector);
231   for (i = 0; i < s->vector_cnt; i++)
232     d->vector[i] = vector_clone (s->vector[i], s, d);
233
234   dict_set_attributes (d, dict_get_attributes (s));
235
236   for (i = 0; i < s->n_mrsets; i++)
237     {
238       const struct mrset *old = s->mrsets[i];
239       struct mrset *new;
240       size_t j;
241
242       /* Clone old mrset, then replace vars from D by vars from S. */
243       new = mrset_clone (old);
244       for (j = 0; j < new->n_vars; j++)
245         new->vars[j] = dict_lookup_var_assert (d, var_get_name (new->vars[j]));
246
247       dict_add_mrset (d, new);
248     }
249
250   return d;
251 }
252
253 /* Clears the contents from a dictionary without destroying the
254    dictionary itself. */
255 void
256 dict_clear (struct dictionary *d)
257 {
258   /* FIXME?  Should we really clear case_limit, label, documents?
259      Others are necessarily cleared by deleting all the variables.*/
260   while (d->var_cnt > 0 )
261     {
262       dict_delete_var (d, d->var[d->var_cnt - 1].var);
263     }
264
265   free (d->var);
266   d->var = NULL;
267   d->var_cnt = d->var_cap = 0;
268   invalidate_proto (d);
269   hmap_clear (&d->name_map);
270   d->next_value_idx = 0;
271   dict_set_split_vars (d, NULL, 0);
272   dict_set_weight (d, NULL);
273   dict_set_filter (d, NULL);
274   d->case_limit = 0;
275   free (d->label);
276   d->label = NULL;
277   string_array_clear (&d->documents);
278   dict_clear_vectors (d);
279   attrset_clear (&d->attributes);
280 }
281
282 /* Clears a dictionary and destroys it. */
283 void
284 dict_destroy (struct dictionary *d)
285 {
286   if (d != NULL)
287     {
288       /* In general, we don't want callbacks occuring, if the dictionary
289          is being destroyed */
290       d->callbacks  = NULL ;
291
292       dict_clear (d);
293       string_array_destroy (&d->documents);
294       hmap_destroy (&d->name_map);
295       attrset_destroy (&d->attributes);
296       dict_clear_mrsets (d);
297       free (d->encoding);
298       free (d);
299     }
300 }
301
302 /* Returns the number of variables in D. */
303 size_t
304 dict_get_var_cnt (const struct dictionary *d)
305 {
306   return d->var_cnt;
307 }
308
309 /* Returns the variable in D with dictionary index IDX, which
310    must be between 0 and the count returned by
311    dict_get_var_cnt(), exclusive. */
312 struct variable *
313 dict_get_var (const struct dictionary *d, size_t idx)
314 {
315   assert (idx < d->var_cnt);
316
317   return d->var[idx].var;
318 }
319
320 /* Sets *VARS to an array of pointers to variables in D and *CNT
321    to the number of variables in *D.  All variables are returned
322    except for those, if any, in the classes indicated by EXCLUDE.
323    (There is no point in putting DC_SYSTEM in EXCLUDE as
324    dictionaries never include system variables.) */
325 void
326 dict_get_vars (const struct dictionary *d, const struct variable ***vars,
327                size_t *cnt, enum dict_class exclude)
328 {
329   dict_get_vars_mutable (d, (struct variable ***) vars, cnt, exclude);
330 }
331
332 /* Sets *VARS to an array of pointers to variables in D and *CNT
333    to the number of variables in *D.  All variables are returned
334    except for those, if any, in the classes indicated by EXCLUDE.
335    (There is no point in putting DC_SYSTEM in EXCLUDE as
336    dictionaries never include system variables.) */
337 void
338 dict_get_vars_mutable (const struct dictionary *d, struct variable ***vars,
339                        size_t *cnt, enum dict_class exclude)
340 {
341   size_t count;
342   size_t i;
343
344   assert (exclude == (exclude & DC_ALL));
345
346   count = 0;
347   for (i = 0; i < d->var_cnt; i++)
348     {
349       enum dict_class class = var_get_dict_class (d->var[i].var);
350       if (!(class & exclude))
351         count++;
352     }
353
354   *vars = xnmalloc (count, sizeof **vars);
355   *cnt = 0;
356   for (i = 0; i < d->var_cnt; i++)
357     {
358       enum dict_class class = var_get_dict_class (d->var[i].var);
359       if (!(class & exclude))
360         (*vars)[(*cnt)++] = d->var[i].var;
361     }
362   assert (*cnt == count);
363 }
364
365 static struct variable *
366 add_var_with_case_index (struct dictionary *d, struct variable *v,
367                          int case_index)
368 {
369   struct vardict_info *vardict;
370
371   assert (case_index >= d->next_value_idx);
372
373   /* Update dictionary. */
374   if (d->var_cnt >= d->var_cap)
375     {
376       size_t i;
377
378       d->var = x2nrealloc (d->var, &d->var_cap, sizeof *d->var);
379       hmap_clear (&d->name_map);
380       for (i = 0; i < d->var_cnt; i++)
381         {
382           var_set_vardict (d->var[i].var, &d->var[i]);
383           hmap_insert_fast (&d->name_map, &d->var[i].name_node,
384                             d->var[i].name_node.hash);
385         }
386     }
387
388   vardict = &d->var[d->var_cnt++];
389   vardict->dict = d;
390   vardict->var = v;
391   hmap_insert (&d->name_map, &vardict->name_node,
392                utf8_hash_case_string (var_get_name (v), 0));
393   vardict->case_index = case_index;
394   var_set_vardict (v, vardict);
395
396   if ( d->changed ) d->changed (d, d->changed_data);
397   if ( d->callbacks &&  d->callbacks->var_added )
398     d->callbacks->var_added (d, var_get_dict_index (v), d->cb_data);
399
400   invalidate_proto (d);
401   d->next_value_idx = case_index + 1;
402
403   return v;
404 }
405
406 static struct variable *
407 add_var (struct dictionary *d, struct variable *v)
408 {
409   return add_var_with_case_index (d, v, d->next_value_idx);
410 }
411
412 /* Creates and returns a new variable in D with the given NAME
413    and WIDTH.  Returns a null pointer if the given NAME would
414    duplicate that of an existing variable in the dictionary. */
415 struct variable *
416 dict_create_var (struct dictionary *d, const char *name, int width)
417 {
418   return (dict_lookup_var (d, name) == NULL
419           ? dict_create_var_assert (d, name, width)
420           : NULL);
421 }
422
423 /* Creates and returns a new variable in D with the given NAME
424    and WIDTH.  Assert-fails if the given NAME would duplicate
425    that of an existing variable in the dictionary. */
426 struct variable *
427 dict_create_var_assert (struct dictionary *d, const char *name, int width)
428 {
429   assert (dict_lookup_var (d, name) == NULL);
430   return add_var (d, var_create (name, width));
431 }
432
433 /* Creates and returns a new variable in D, as a copy of existing variable
434    OLD_VAR, which need not be in D or in any dictionary.  Returns a null
435    pointer if OLD_VAR's name would duplicate that of an existing variable in
436    the dictionary. */
437 struct variable *
438 dict_clone_var (struct dictionary *d, const struct variable *old_var)
439 {
440   return dict_clone_var_as (d, old_var, var_get_name (old_var));
441 }
442
443 /* Creates and returns a new variable in D, as a copy of existing variable
444    OLD_VAR, which need not be in D or in any dictionary.  Assert-fails if
445    OLD_VAR's name would duplicate that of an existing variable in the
446    dictionary. */
447 struct variable *
448 dict_clone_var_assert (struct dictionary *d, const struct variable *old_var)
449 {
450   return dict_clone_var_as_assert (d, old_var, var_get_name (old_var));
451 }
452
453 /* Creates and returns a new variable in D with name NAME, as a copy of
454    existing variable OLD_VAR, which need not be in D or in any dictionary.
455    Returns a null pointer if the given NAME would duplicate that of an existing
456    variable in the dictionary. */
457 struct variable *
458 dict_clone_var_as (struct dictionary *d, const struct variable *old_var,
459                    const char *name)
460 {
461   return (dict_lookup_var (d, name) == NULL
462           ? dict_clone_var_as_assert (d, old_var, name)
463           : NULL);
464 }
465
466 /* Creates and returns a new variable in D with name NAME, as a copy of
467    existing variable OLD_VAR, which need not be in D or in any dictionary.
468    Assert-fails if the given NAME would duplicate that of an existing variable
469    in the dictionary. */
470 struct variable *
471 dict_clone_var_as_assert (struct dictionary *d, const struct variable *old_var,
472                           const char *name)
473 {
474   struct variable *new_var = var_clone (old_var);
475   assert (dict_lookup_var (d, name) == NULL);
476   var_set_name (new_var, name);
477   return add_var (d, new_var);
478 }
479
480 struct variable *
481 dict_clone_var_in_place_assert (struct dictionary *d,
482                                 const struct variable *old_var)
483 {
484   assert (dict_lookup_var (d, var_get_name (old_var)) == NULL);
485   return add_var_with_case_index (d, var_clone (old_var),
486                                   var_get_case_index (old_var));
487 }
488
489 /* Returns the variable named NAME in D, or a null pointer if no
490    variable has that name. */
491 struct variable *
492 dict_lookup_var (const struct dictionary *d, const char *name)
493 {
494   struct vardict_info *vardict;
495
496   HMAP_FOR_EACH_WITH_HASH (vardict, struct vardict_info, name_node,
497                            utf8_hash_case_string (name, 0), &d->name_map)
498     {
499       struct variable *var = vardict->var;
500       if (!utf8_strcasecmp (var_get_name (var), name))
501         return var;
502     }
503
504   return NULL;
505 }
506
507 /* Returns the variable named NAME in D.  Assert-fails if no
508    variable has that name. */
509 struct variable *
510 dict_lookup_var_assert (const struct dictionary *d, const char *name)
511 {
512   struct variable *v = dict_lookup_var (d, name);
513   assert (v != NULL);
514   return v;
515 }
516
517 /* Returns true if variable V is in dictionary D,
518    false otherwise. */
519 bool
520 dict_contains_var (const struct dictionary *d, const struct variable *v)
521 {
522   return (var_has_vardict (v)
523           && vardict_get_dictionary (var_get_vardict (v)) == d);
524 }
525
526 /* Compares two double pointers to variables, which should point
527    to elements of a struct dictionary's `var' member array. */
528 static int
529 compare_var_ptrs (const void *a_, const void *b_, const void *aux UNUSED)
530 {
531   struct variable *const *a = a_;
532   struct variable *const *b = b_;
533
534   return *a < *b ? -1 : *a > *b;
535 }
536
537 static void
538 unindex_var (struct dictionary *d, struct vardict_info *vardict)
539 {
540   hmap_delete (&d->name_map, &vardict->name_node);
541 }
542
543 /* This function assumes that vardict->name_node.hash is valid, that is, that
544    its name has not changed since it was hashed (rename_var() updates this
545    hash along with the name itself). */
546 static void
547 reindex_var (struct dictionary *d, struct vardict_info *vardict)
548 {
549   struct variable *var = vardict->var;
550   struct variable *old = var_clone (var);
551
552   var_set_vardict (var, vardict);
553   hmap_insert_fast (&d->name_map, &vardict->name_node,
554                     vardict->name_node.hash);
555
556   if ( d->changed ) d->changed (d, d->changed_data);
557   if ( d->callbacks &&  d->callbacks->var_changed )
558     d->callbacks->var_changed (d, var_get_dict_index (var), VAR_TRAIT_POSITION, old, d->cb_data);
559   var_destroy (old);
560 }
561
562 /* Sets the case_index in V's vardict to CASE_INDEX. */
563 static void
564 set_var_case_index (struct variable *v, int case_index)
565 {
566   var_get_vardict (v)->case_index = case_index;
567 }
568
569 /* Removes the dictionary variables with indexes from FROM to TO (exclusive)
570    from name_map. */
571 static void
572 unindex_vars (struct dictionary *d, size_t from, size_t to)
573 {
574   size_t i;
575
576   for (i = from; i < to; i++)
577     unindex_var (d, &d->var[i]);
578 }
579
580 /* Re-sets the dict_index in the dictionary variables with
581    indexes from FROM to TO (exclusive). */
582 static void
583 reindex_vars (struct dictionary *d, size_t from, size_t to)
584 {
585   size_t i;
586
587   for (i = from; i < to; i++)
588     reindex_var (d, &d->var[i]);
589 }
590
591 /* Deletes variable V from dictionary D and frees V.
592
593    This is a very bad idea if there might be any pointers to V
594    from outside D.  In general, no variable in the active dataset's
595    dictionary should be deleted when any transformations are
596    active on the dictionary's dataset, because those
597    transformations might reference the deleted variable.  The
598    safest time to delete a variable is just after a procedure has
599    been executed, as done by DELETE VARIABLES.
600
601    Pointers to V within D are not a problem, because
602    dict_delete_var() knows to remove V from split variables,
603    weights, filters, etc. */
604 void
605 dict_delete_var (struct dictionary *d, struct variable *v)
606 {
607   int dict_index = var_get_dict_index (v);
608   const int case_index = var_get_case_index (v);
609
610   assert (dict_contains_var (d, v));
611
612   dict_unset_split_var (d, v);
613   dict_unset_mrset_var (d, v);
614
615   if (d->weight == v)
616     dict_set_weight (d, NULL);
617
618   if (d->filter == v)
619     dict_set_filter (d, NULL);
620
621   dict_clear_vectors (d);
622
623   /* Remove V from var array. */
624   unindex_vars (d, dict_index, d->var_cnt);
625   remove_element (d->var, d->var_cnt, sizeof *d->var, dict_index);
626   d->var_cnt--;
627
628   /* Update dict_index for each affected variable. */
629   reindex_vars (d, dict_index, d->var_cnt);
630
631   /* Free memory. */
632   var_clear_vardict (v);
633
634   if ( d->changed ) d->changed (d, d->changed_data);
635
636   invalidate_proto (d);
637   if (d->callbacks &&  d->callbacks->var_deleted )
638     d->callbacks->var_deleted (d, v, dict_index, case_index, d->cb_data);
639
640   var_destroy (v);
641 }
642
643 /* Deletes the COUNT variables listed in VARS from D.  This is
644    unsafe; see the comment on dict_delete_var() for details. */
645 void
646 dict_delete_vars (struct dictionary *d,
647                   struct variable *const *vars, size_t count)
648 {
649   /* FIXME: this can be done in O(count) time, but this algorithm
650      is O(count**2). */
651   assert (count == 0 || vars != NULL);
652
653   while (count-- > 0)
654     dict_delete_var (d, *vars++);
655 }
656
657 /* Deletes the COUNT variables in D starting at index IDX.  This
658    is unsafe; see the comment on dict_delete_var() for
659    details. */
660 void
661 dict_delete_consecutive_vars (struct dictionary *d, size_t idx, size_t count)
662 {
663   /* FIXME: this can be done in O(count) time, but this algorithm
664      is O(count**2). */
665   assert (idx + count <= d->var_cnt);
666
667   while (count-- > 0)
668     dict_delete_var (d, d->var[idx].var);
669 }
670
671 /* Deletes scratch variables from dictionary D. */
672 void
673 dict_delete_scratch_vars (struct dictionary *d)
674 {
675   int i;
676
677   /* FIXME: this can be done in O(count) time, but this algorithm
678      is O(count**2). */
679   for (i = 0; i < d->var_cnt; )
680     if (var_get_dict_class (d->var[i].var) == DC_SCRATCH)
681       dict_delete_var (d, d->var[i].var);
682     else
683       i++;
684 }
685
686 /* Moves V to 0-based position IDX in D.  Other variables in D,
687    if any, retain their relative positions.  Runs in time linear
688    in the distance moved. */
689 void
690 dict_reorder_var (struct dictionary *d, struct variable *v, size_t new_index)
691 {
692   size_t old_index = var_get_dict_index (v);
693
694   assert (new_index < d->var_cnt);
695
696   unindex_vars (d, MIN (old_index, new_index), MAX (old_index, new_index) + 1);
697   move_element (d->var, d->var_cnt, sizeof *d->var, old_index, new_index);
698   reindex_vars (d, MIN (old_index, new_index), MAX (old_index, new_index) + 1);
699 }
700
701 /* Reorders the variables in D, placing the COUNT variables
702    listed in ORDER in that order at the beginning of D.  The
703    other variables in D, if any, retain their relative
704    positions. */
705 void
706 dict_reorder_vars (struct dictionary *d,
707                    struct variable *const *order, size_t count)
708 {
709   struct vardict_info *new_var;
710   size_t i;
711
712   assert (count == 0 || order != NULL);
713   assert (count <= d->var_cnt);
714
715   new_var = xnmalloc (d->var_cap, sizeof *new_var);
716
717   /* Add variables in ORDER to new_var. */
718   for (i = 0; i < count; i++)
719     {
720       struct vardict_info *old_var;
721
722       assert (dict_contains_var (d, order[i]));
723
724       old_var = var_get_vardict (order[i]);
725       new_var[i] = *old_var;
726       old_var->dict = NULL;
727     }
728
729   /* Add remaining variables to new_var. */
730   for (i = 0; i < d->var_cnt; i++)
731     if (d->var[i].dict != NULL)
732       new_var[count++] = d->var[i];
733   assert (count == d->var_cnt);
734
735   /* Replace old vardicts by new ones. */
736   free (d->var);
737   d->var = new_var;
738
739   hmap_clear (&d->name_map);
740   reindex_vars (d, 0, d->var_cnt);
741 }
742
743 /* Changes the name of variable V that is currently in a dictionary to
744    NEW_NAME. */
745 static void
746 rename_var (struct variable *v, const char *new_name)
747 {
748   struct vardict_info *vardict = var_get_vardict (v);
749   var_clear_vardict (v);
750   var_set_name (v, new_name);
751   vardict->name_node.hash = utf8_hash_case_string (new_name, 0);
752   var_set_vardict (v, vardict);
753 }
754
755 /* Changes the name of V in D to name NEW_NAME.  Assert-fails if
756    a variable named NEW_NAME is already in D, except that
757    NEW_NAME may be the same as V's existing name. */
758 void
759 dict_rename_var (struct dictionary *d, struct variable *v,
760                  const char *new_name)
761 {
762   struct variable *old = var_clone (v);
763   assert (!utf8_strcasecmp (var_get_name (v), new_name)
764           || dict_lookup_var (d, new_name) == NULL);
765
766   unindex_var (d, var_get_vardict (v));
767   rename_var (v, new_name);
768   reindex_var (d, var_get_vardict (v));
769
770   if (settings_get_algorithm () == ENHANCED)
771     var_clear_short_names (v);
772
773   if ( d->changed ) d->changed (d, d->changed_data);
774   if ( d->callbacks &&  d->callbacks->var_changed )
775     d->callbacks->var_changed (d, var_get_dict_index (v), VAR_TRAIT_NAME, old, d->cb_data);
776
777   var_destroy (old);
778 }
779
780 /* Renames COUNT variables specified in VARS to the names given
781    in NEW_NAMES within dictionary D.  If the renaming would
782    result in a duplicate variable name, returns false and stores a
783    name that would be duplicated into *ERR_NAME (if ERR_NAME is
784    non-null).  Otherwise, the renaming is successful, and true
785    is returned. */
786 bool
787 dict_rename_vars (struct dictionary *d,
788                   struct variable **vars, char **new_names, size_t count,
789                   char **err_name)
790 {
791   struct pool *pool;
792   char **old_names;
793   size_t i;
794
795   assert (count == 0 || vars != NULL);
796   assert (count == 0 || new_names != NULL);
797
798   /* Save the names of the variables to be renamed. */
799   pool = pool_create ();
800   old_names = pool_nalloc (pool, count, sizeof *old_names);
801   for (i = 0; i < count; i++)
802     old_names[i] = pool_strdup (pool, var_get_name (vars[i]));
803
804   /* Remove the variables to be renamed from the name hash,
805      and rename them. */
806   for (i = 0; i < count; i++)
807     {
808       unindex_var (d, var_get_vardict (vars[i]));
809       rename_var (vars[i], new_names[i]);
810     }
811
812   /* Add the renamed variables back into the name hash,
813      checking for conflicts. */
814   for (i = 0; i < count; i++)
815     {
816       if (dict_lookup_var (d, var_get_name (vars[i])) != NULL)
817         {
818           /* There is a name conflict.
819              Back out all the name changes that have already
820              taken place, and indicate failure. */
821           size_t fail_idx = i;
822           if (err_name != NULL)
823             *err_name = new_names[i];
824
825           for (i = 0; i < fail_idx; i++)
826             unindex_var (d, var_get_vardict (vars[i]));
827
828           for (i = 0; i < count; i++)
829             {
830               rename_var (vars[i], old_names[i]);
831               reindex_var (d, var_get_vardict (vars[i]));
832             }
833
834           pool_destroy (pool);
835           return false;
836         }
837       reindex_var (d, var_get_vardict (vars[i]));
838     }
839
840   /* Clear short names. */
841   if (settings_get_algorithm () == ENHANCED)
842     for (i = 0; i < count; i++)
843       var_clear_short_names (vars[i]);
844
845   pool_destroy (pool);
846   return true;
847 }
848
849 /* Returns true if a variable named NAME may be inserted in DICT;
850    that is, if there is not already a variable with that name in
851    DICT and if NAME is not a reserved word.  (The caller's checks
852    have already verified that NAME is otherwise acceptable as a
853    variable name.) */
854 static bool
855 var_name_is_insertable (const struct dictionary *dict, const char *name)
856 {
857   return (dict_lookup_var (dict, name) == NULL
858           && lex_id_to_token (ss_cstr (name)) == T_ID);
859 }
860
861 static char *
862 make_hinted_name (const struct dictionary *dict, const char *hint)
863 {
864   size_t hint_len = strlen (hint);
865   bool dropped = false;
866   char *root, *rp;
867   size_t ofs;
868   int mblen;
869
870   /* The allocation size here is OK: characters that are copied directly fit
871      OK, and characters that are not copied directly are replaced by a single
872      '_' byte.  If u8_mbtouc() replaces bad input by 0xfffd, then that will get
873      replaced by '_' too.  */
874   root = rp = xmalloc (hint_len + 1);
875   for (ofs = 0; ofs < hint_len; ofs += mblen)
876     {
877       ucs4_t uc;
878
879       mblen = u8_mbtouc (&uc, CHAR_CAST (const uint8_t *, hint + ofs),
880                          hint_len - ofs);
881       if (rp == root
882           ? lex_uc_is_id1 (uc) && uc != '$'
883           : lex_uc_is_idn (uc))
884         {
885           if (dropped)
886             {
887               *rp++ = '_';
888               dropped = false;
889             }
890           rp += u8_uctomb (CHAR_CAST (uint8_t *, rp), uc, 6);
891         }
892       else if (rp != root)
893         dropped = true;
894     }
895   *rp = '\0';
896
897   if (root[0] != '\0')
898     {
899       unsigned long int i;
900
901       if (var_name_is_insertable (dict, root))
902         return root;
903
904       for (i = 0; i < ULONG_MAX; i++)
905         {
906           char suffix[INT_BUFSIZE_BOUND (i) + 1];
907           char *name;
908
909           suffix[0] = '_';
910           if (!str_format_26adic (i + 1, true, &suffix[1], sizeof suffix - 1))
911             NOT_REACHED ();
912
913           name = utf8_encoding_concat (root, suffix, dict->encoding, 64);
914           if (var_name_is_insertable (dict, name))
915             {
916               free (root);
917               return name;
918             }
919           free (name);
920         }
921     }
922
923   free (root);
924
925   return NULL;
926 }
927
928 static char *
929 make_numeric_name (const struct dictionary *dict, unsigned long int *num_start)
930 {
931   unsigned long int number;
932
933   for (number = num_start != NULL ? MAX (*num_start, 1) : 1;
934        number < ULONG_MAX;
935        number++)
936     {
937       char name[3 + INT_STRLEN_BOUND (number) + 1];
938
939       sprintf (name, "VAR%03lu", number);
940       if (dict_lookup_var (dict, name) == NULL)
941         {
942           if (num_start != NULL)
943             *num_start = number + 1;
944           return xstrdup (name);
945         }
946     }
947
948   NOT_REACHED ();
949 }
950
951
952 /* Devises and returns a variable name unique within DICT.  The variable name
953    is owned by the caller, which must free it with free() when it is no longer
954    needed.
955
956    HINT, if it is non-null, is used as a suggestion that will be
957    modified for suitability as a variable name and for
958    uniqueness.
959
960    If HINT is null or entirely unsuitable, a name in the form
961    "VAR%03d" will be generated, where the smallest unused integer
962    value is used.  If NUM_START is non-null, then its value is
963    used as the minimum numeric value to check, and it is updated
964    to the next value to be checked.
965 */
966 char *
967 dict_make_unique_var_name (const struct dictionary *dict, const char *hint,
968                            unsigned long int *num_start)
969 {
970   if (hint != NULL)
971     {
972       char *hinted_name = make_hinted_name (dict, hint);
973       if (hinted_name != NULL)
974         return hinted_name;
975     }
976   return make_numeric_name (dict, num_start);
977 }
978
979 /* Returns the weighting variable in dictionary D, or a null
980    pointer if the dictionary is unweighted. */
981 struct variable *
982 dict_get_weight (const struct dictionary *d)
983 {
984   assert (d->weight == NULL || dict_contains_var (d, d->weight));
985
986   return d->weight;
987 }
988
989 /* Returns the value of D's weighting variable in case C, except
990    that a negative weight is returned as 0.  Returns 1 if the
991    dictionary is unweighted.  Will warn about missing, negative,
992    or zero values if *WARN_ON_INVALID is true.  The function will
993    set *WARN_ON_INVALID to false if an invalid weight is
994    found. */
995 double
996 dict_get_case_weight (const struct dictionary *d, const struct ccase *c,
997                       bool *warn_on_invalid)
998 {
999   assert (c != NULL);
1000
1001   if (d->weight == NULL)
1002     return 1.0;
1003   else
1004     {
1005       double w = case_num (c, d->weight);
1006       if (w < 0.0 || var_is_num_missing (d->weight, w, MV_ANY))
1007         w = 0.0;
1008       if ( w == 0.0 && warn_on_invalid != NULL && *warn_on_invalid ) {
1009           *warn_on_invalid = false;
1010           msg (SW, _("At least one case in the data file had a weight value "
1011                      "that was user-missing, system-missing, zero, or "
1012                      "negative.  These case(s) were ignored."));
1013       }
1014       return w;
1015     }
1016 }
1017
1018 /* Sets the weighting variable of D to V, or turning off
1019    weighting if V is a null pointer. */
1020 void
1021 dict_set_weight (struct dictionary *d, struct variable *v)
1022 {
1023   assert (v == NULL || dict_contains_var (d, v));
1024   assert (v == NULL || var_is_numeric (v));
1025
1026   d->weight = v;
1027
1028   if (d->changed) d->changed (d, d->changed_data);
1029   if ( d->callbacks &&  d->callbacks->weight_changed )
1030     d->callbacks->weight_changed (d,
1031                                   v ? var_get_dict_index (v) : -1,
1032                                   d->cb_data);
1033 }
1034
1035 /* Returns the filter variable in dictionary D (see cmd_filter())
1036    or a null pointer if the dictionary is unfiltered. */
1037 struct variable *
1038 dict_get_filter (const struct dictionary *d)
1039 {
1040   assert (d->filter == NULL || dict_contains_var (d, d->filter));
1041
1042   return d->filter;
1043 }
1044
1045 /* Sets V as the filter variable for dictionary D.  Passing a
1046    null pointer for V turn off filtering. */
1047 void
1048 dict_set_filter (struct dictionary *d, struct variable *v)
1049 {
1050   assert (v == NULL || dict_contains_var (d, v));
1051   assert (v == NULL || var_is_numeric (v));
1052
1053   d->filter = v;
1054
1055   if (d->changed) d->changed (d, d->changed_data);
1056   if ( d->callbacks && d->callbacks->filter_changed )
1057     d->callbacks->filter_changed (d,
1058                                   v ? var_get_dict_index (v) : -1,
1059                                   d->cb_data);
1060 }
1061
1062 /* Returns the case limit for dictionary D, or zero if the number
1063    of cases is unlimited. */
1064 casenumber
1065 dict_get_case_limit (const struct dictionary *d)
1066 {
1067   return d->case_limit;
1068 }
1069
1070 /* Sets CASE_LIMIT as the case limit for dictionary D.  Use
1071    0 for CASE_LIMIT to indicate no limit. */
1072 void
1073 dict_set_case_limit (struct dictionary *d, casenumber case_limit)
1074 {
1075   d->case_limit = case_limit;
1076 }
1077
1078 /* Returns the prototype used for cases created by dictionary D. */
1079 const struct caseproto *
1080 dict_get_proto (const struct dictionary *d_)
1081 {
1082   struct dictionary *d = CONST_CAST (struct dictionary *, d_);
1083   if (d->proto == NULL)
1084     {
1085       size_t i;
1086
1087       d->proto = caseproto_create ();
1088       d->proto = caseproto_reserve (d->proto, d->var_cnt);
1089       for (i = 0; i < d->var_cnt; i++)
1090         d->proto = caseproto_set_width (d->proto,
1091                                         var_get_case_index (d->var[i].var),
1092                                         var_get_width (d->var[i].var));
1093     }
1094   return d->proto;
1095 }
1096
1097 /* Returns the case index of the next value to be added to D.
1098    This value is the number of `union value's that need to be
1099    allocated to store a case for dictionary D. */
1100 int
1101 dict_get_next_value_idx (const struct dictionary *d)
1102 {
1103   return d->next_value_idx;
1104 }
1105
1106 /* Returns the number of bytes needed to store a case for
1107    dictionary D. */
1108 size_t
1109 dict_get_case_size (const struct dictionary *d)
1110 {
1111   return sizeof (union value) * dict_get_next_value_idx (d);
1112 }
1113
1114 /* Reassigns values in dictionary D so that fragmentation is
1115    eliminated. */
1116 void
1117 dict_compact_values (struct dictionary *d)
1118 {
1119   size_t i;
1120
1121   d->next_value_idx = 0;
1122   for (i = 0; i < d->var_cnt; i++)
1123     {
1124       struct variable *v = d->var[i].var;
1125       set_var_case_index (v, d->next_value_idx++);
1126     }
1127   invalidate_proto (d);
1128 }
1129
1130 /* Returns the number of values occupied by the variables in
1131    dictionary D.  All variables are considered if EXCLUDE_CLASSES
1132    is 0, or it may contain one or more of (1u << DC_ORDINARY),
1133    (1u << DC_SYSTEM), or (1u << DC_SCRATCH) to exclude the
1134    corresponding type of variable.
1135
1136    The return value may be less than the number of values in one
1137    of dictionary D's cases (as returned by
1138    dict_get_next_value_idx) even if E is 0, because there may be
1139    gaps in D's cases due to deleted variables. */
1140 size_t
1141 dict_count_values (const struct dictionary *d, unsigned int exclude_classes)
1142 {
1143   size_t i;
1144   size_t cnt;
1145
1146   assert ((exclude_classes & ~((1u << DC_ORDINARY)
1147                                | (1u << DC_SYSTEM)
1148                                | (1u << DC_SCRATCH))) == 0);
1149
1150   cnt = 0;
1151   for (i = 0; i < d->var_cnt; i++)
1152     {
1153       enum dict_class class = var_get_dict_class (d->var[i].var);
1154       if (!(exclude_classes & (1u << class)))
1155         cnt++;
1156     }
1157   return cnt;
1158 }
1159
1160 /* Returns the case prototype that would result after deleting
1161    all variables from D that are not in one of the
1162    EXCLUDE_CLASSES and compacting the dictionary with
1163    dict_compact().
1164
1165    The caller must unref the returned caseproto when it is no
1166    longer needed. */
1167 struct caseproto *
1168 dict_get_compacted_proto (const struct dictionary *d,
1169                           unsigned int exclude_classes)
1170 {
1171   struct caseproto *proto;
1172   size_t i;
1173
1174   assert ((exclude_classes & ~((1u << DC_ORDINARY)
1175                                | (1u << DC_SYSTEM)
1176                                | (1u << DC_SCRATCH))) == 0);
1177
1178   proto = caseproto_create ();
1179   for (i = 0; i < d->var_cnt; i++)
1180     {
1181       struct variable *v = d->var[i].var;
1182       if (!(exclude_classes & (1u << var_get_dict_class (v))))
1183         proto = caseproto_add_width (proto, var_get_width (v));
1184     }
1185   return proto;
1186 }
1187 \f
1188 /* Returns the SPLIT FILE vars (see cmd_split_file()).  Call
1189    dict_get_split_cnt() to determine how many SPLIT FILE vars
1190    there are.  Returns a null pointer if and only if there are no
1191    SPLIT FILE vars. */
1192 const struct variable *const *
1193 dict_get_split_vars (const struct dictionary *d)
1194 {
1195   return d->split;
1196 }
1197
1198 /* Returns the number of SPLIT FILE vars. */
1199 size_t
1200 dict_get_split_cnt (const struct dictionary *d)
1201 {
1202   return d->split_cnt;
1203 }
1204
1205 /* Removes variable V, which must be in D, from D's set of split
1206    variables. */
1207 static void
1208 dict_unset_split_var (struct dictionary *d, struct variable *v)
1209 {
1210   int orig_count;
1211
1212   assert (dict_contains_var (d, v));
1213
1214   orig_count = d->split_cnt;
1215   d->split_cnt = remove_equal (d->split, d->split_cnt, sizeof *d->split,
1216                                &v, compare_var_ptrs, NULL);
1217   if (orig_count != d->split_cnt)
1218     {
1219       if (d->changed) d->changed (d, d->changed_data);
1220       /* We changed the set of split variables so invoke the
1221          callback. */
1222       if (d->callbacks &&  d->callbacks->split_changed)
1223         d->callbacks->split_changed (d, d->cb_data);
1224     }
1225 }
1226
1227 /* Sets CNT split vars SPLIT in dictionary D. */
1228 void
1229 dict_set_split_vars (struct dictionary *d,
1230                      struct variable *const *split, size_t cnt)
1231 {
1232   assert (cnt == 0 || split != NULL);
1233
1234   d->split_cnt = cnt;
1235   if ( cnt > 0 )
1236    {
1237     d->split = xnrealloc (d->split, cnt, sizeof *d->split) ;
1238     memcpy (d->split, split, cnt * sizeof *d->split);
1239    }
1240   else
1241    {
1242     free (d->split);
1243     d->split = NULL;
1244    }
1245
1246   if (d->changed) d->changed (d, d->changed_data);
1247   if ( d->callbacks &&  d->callbacks->split_changed )
1248     d->callbacks->split_changed (d, d->cb_data);
1249 }
1250
1251 /* Returns the file label for D, or a null pointer if D is
1252    unlabeled (see cmd_file_label()). */
1253 const char *
1254 dict_get_label (const struct dictionary *d)
1255 {
1256   return d->label;
1257 }
1258
1259 /* Sets D's file label to LABEL, truncating it to at most 60 bytes in D's
1260    encoding.
1261
1262    Removes D's label if LABEL is null or the empty string. */
1263 void
1264 dict_set_label (struct dictionary *d, const char *label)
1265 {
1266   free (d->label);
1267   if (label == NULL || label[0] == '\0')
1268     d->label = NULL;
1269   else
1270     d->label = utf8_encoding_trunc (label, d->encoding, 60);
1271 }
1272
1273 /* Returns the documents for D, as an UTF-8 encoded string_array.  The
1274    return value is always nonnull; if there are no documents then the
1275    string_arary is empty.*/
1276 const struct string_array *
1277 dict_get_documents (const struct dictionary *d)
1278 {
1279   return &d->documents;
1280 }
1281
1282 /* Replaces the documents for D by NEW_DOCS, a UTF-8 encoded string_array. */
1283 void
1284 dict_set_documents (struct dictionary *d, const struct string_array *new_docs)
1285 {
1286   size_t i;
1287
1288   dict_clear_documents (d);
1289
1290   for (i = 0; i < new_docs->n; i++)
1291     dict_add_document_line (d, new_docs->strings[i], false);
1292 }
1293
1294 /* Replaces the documents for D by UTF-8 encoded string NEW_DOCS, dividing it
1295    into individual lines at new-line characters.  Each line is truncated to at
1296    most DOC_LINE_LENGTH bytes in D's encoding. */
1297 void
1298 dict_set_documents_string (struct dictionary *d, const char *new_docs)
1299 {
1300   const char *s;
1301
1302   dict_clear_documents (d);
1303   for (s = new_docs; *s != '\0'; )
1304     {
1305       size_t len = strcspn (s, "\n");
1306       char *line = xmemdup0 (s, len);
1307       dict_add_document_line (d, line, false);
1308       free (line);
1309
1310       s += len;
1311       if (*s == '\n')
1312         s++;
1313     }
1314 }
1315
1316 /* Drops the documents from dictionary D. */
1317 void
1318 dict_clear_documents (struct dictionary *d)
1319 {
1320   string_array_clear (&d->documents);
1321 }
1322
1323 /* Appends the UTF-8 encoded LINE to the documents in D.  LINE will be
1324    truncated so that it is no more than 80 bytes in the dictionary's
1325    encoding.  If this causes some text to be lost, and ISSUE_WARNING is true,
1326    then a warning will be issued. */
1327 bool
1328 dict_add_document_line (struct dictionary *d, const char *line,
1329                         bool issue_warning)
1330 {
1331   size_t trunc_len;
1332   bool truncated;
1333
1334   trunc_len = utf8_encoding_trunc_len (line, d->encoding, DOC_LINE_LENGTH);
1335   truncated = line[trunc_len] != '\0';
1336   if (truncated && issue_warning)
1337     {
1338       /* Note to translators: "bytes" is correct, not characters */
1339       msg (SW, _("Truncating document line to %d bytes."), DOC_LINE_LENGTH);
1340     }
1341
1342   string_array_append_nocopy (&d->documents, xmemdup0 (line, trunc_len));
1343
1344   return !truncated;
1345 }
1346
1347 /* Returns the number of document lines in dictionary D. */
1348 size_t
1349 dict_get_document_line_cnt (const struct dictionary *d)
1350 {
1351   return d->documents.n;
1352 }
1353
1354 /* Returns document line number IDX in dictionary D.  The caller must not
1355    modify or free the returned string. */
1356 const char *
1357 dict_get_document_line (const struct dictionary *d, size_t idx)
1358 {
1359   assert (idx < d->documents.n);
1360   return d->documents.strings[idx];
1361 }
1362
1363 /* Creates in D a vector named NAME that contains the CNT
1364    variables in VAR.  Returns true if successful, or false if a
1365    vector named NAME already exists in D. */
1366 bool
1367 dict_create_vector (struct dictionary *d,
1368                     const char *name,
1369                     struct variable **var, size_t cnt)
1370 {
1371   size_t i;
1372
1373   assert (cnt > 0);
1374   for (i = 0; i < cnt; i++)
1375     assert (dict_contains_var (d, var[i]));
1376
1377   if (dict_lookup_vector (d, name) == NULL)
1378     {
1379       d->vector = xnrealloc (d->vector, d->vector_cnt + 1, sizeof *d->vector);
1380       d->vector[d->vector_cnt++] = vector_create (name, var, cnt);
1381       return true;
1382     }
1383   else
1384     return false;
1385 }
1386
1387 /* Creates in D a vector named NAME that contains the CNT
1388    variables in VAR.  A vector named NAME must not already exist
1389    in D. */
1390 void
1391 dict_create_vector_assert (struct dictionary *d,
1392                            const char *name,
1393                            struct variable **var, size_t cnt)
1394 {
1395   assert (dict_lookup_vector (d, name) == NULL);
1396   dict_create_vector (d, name, var, cnt);
1397 }
1398
1399 /* Returns the vector in D with index IDX, which must be less
1400    than dict_get_vector_cnt (D). */
1401 const struct vector *
1402 dict_get_vector (const struct dictionary *d, size_t idx)
1403 {
1404   assert (idx < d->vector_cnt);
1405
1406   return d->vector[idx];
1407 }
1408
1409 /* Returns the number of vectors in D. */
1410 size_t
1411 dict_get_vector_cnt (const struct dictionary *d)
1412 {
1413   return d->vector_cnt;
1414 }
1415
1416 /* Looks up and returns the vector within D with the given
1417    NAME. */
1418 const struct vector *
1419 dict_lookup_vector (const struct dictionary *d, const char *name)
1420 {
1421   size_t i;
1422   for (i = 0; i < d->vector_cnt; i++)
1423     if (!utf8_strcasecmp (vector_get_name (d->vector[i]), name))
1424       return d->vector[i];
1425   return NULL;
1426 }
1427
1428 /* Deletes all vectors from D. */
1429 void
1430 dict_clear_vectors (struct dictionary *d)
1431 {
1432   size_t i;
1433
1434   for (i = 0; i < d->vector_cnt; i++)
1435     vector_destroy (d->vector[i]);
1436   free (d->vector);
1437
1438   d->vector = NULL;
1439   d->vector_cnt = 0;
1440 }
1441 \f
1442 /* Multiple response sets. */
1443
1444 /* Returns the multiple response set in DICT with index IDX, which must be
1445    between 0 and the count returned by dict_get_n_mrsets(), exclusive. */
1446 const struct mrset *
1447 dict_get_mrset (const struct dictionary *dict, size_t idx)
1448 {
1449   assert (idx < dict->n_mrsets);
1450   return dict->mrsets[idx];
1451 }
1452
1453 /* Returns the number of multiple response sets in DICT. */
1454 size_t
1455 dict_get_n_mrsets (const struct dictionary *dict)
1456 {
1457   return dict->n_mrsets;
1458 }
1459
1460 /* Looks for a multiple response set named NAME in DICT.  If it finds one,
1461    returns its index; otherwise, returns SIZE_MAX. */
1462 static size_t
1463 dict_lookup_mrset_idx (const struct dictionary *dict, const char *name)
1464 {
1465   size_t i;
1466
1467   for (i = 0; i < dict->n_mrsets; i++)
1468     if (!utf8_strcasecmp (name, dict->mrsets[i]->name))
1469       return i;
1470
1471   return SIZE_MAX;
1472 }
1473
1474 /* Looks for a multiple response set named NAME in DICT.  If it finds one,
1475    returns it; otherwise, returns NULL. */
1476 const struct mrset *
1477 dict_lookup_mrset (const struct dictionary *dict, const char *name)
1478 {
1479   size_t idx = dict_lookup_mrset_idx (dict, name);
1480   return idx != SIZE_MAX ? dict->mrsets[idx] : NULL;
1481 }
1482
1483 /* Adds MRSET to DICT, replacing any existing set with the same name.  Returns
1484    true if a set was replaced, false if none existed with the specified name.
1485
1486    Ownership of MRSET is transferred to DICT. */
1487 bool
1488 dict_add_mrset (struct dictionary *dict, struct mrset *mrset)
1489 {
1490   size_t idx;
1491
1492   assert (mrset_ok (mrset, dict));
1493
1494   idx = dict_lookup_mrset_idx (dict, mrset->name);
1495   if (idx == SIZE_MAX)
1496     {
1497       dict->mrsets = xrealloc (dict->mrsets,
1498                                (dict->n_mrsets + 1) * sizeof *dict->mrsets);
1499       dict->mrsets[dict->n_mrsets++] = mrset;
1500       return true;
1501     }
1502   else
1503     {
1504       mrset_destroy (dict->mrsets[idx]);
1505       dict->mrsets[idx] = mrset;
1506       return false;
1507     }
1508 }
1509
1510 /* Looks for a multiple response set in DICT named NAME.  If found, removes it
1511    from DICT and returns true.  If none is found, returns false without
1512    modifying DICT.
1513
1514    Deleting one multiple response set causes the indexes of other sets within
1515    DICT to change. */
1516 bool
1517 dict_delete_mrset (struct dictionary *dict, const char *name)
1518 {
1519   size_t idx = dict_lookup_mrset_idx (dict, name);
1520   if (idx != SIZE_MAX)
1521     {
1522       mrset_destroy (dict->mrsets[idx]);
1523       dict->mrsets[idx] = dict->mrsets[--dict->n_mrsets];
1524       return true;
1525     }
1526   else
1527     return false;
1528 }
1529
1530 /* Deletes all multiple response sets from DICT. */
1531 void
1532 dict_clear_mrsets (struct dictionary *dict)
1533 {
1534   size_t i;
1535
1536   for (i = 0; i < dict->n_mrsets; i++)
1537     mrset_destroy (dict->mrsets[i]);
1538   free (dict->mrsets);
1539   dict->mrsets = NULL;
1540   dict->n_mrsets = 0;
1541 }
1542
1543 /* Removes VAR, which must be in DICT, from DICT's multiple response sets. */
1544 static void
1545 dict_unset_mrset_var (struct dictionary *dict, struct variable *var)
1546 {
1547   size_t i;
1548
1549   assert (dict_contains_var (dict, var));
1550
1551   for (i = 0; i < dict->n_mrsets; )
1552     {
1553       struct mrset *mrset = dict->mrsets[i];
1554       size_t j;
1555
1556       for (j = 0; j < mrset->n_vars; )
1557         if (mrset->vars[j] == var)
1558           remove_element (mrset->vars, mrset->n_vars--,
1559                           sizeof *mrset->vars, j);
1560         else
1561           j++;
1562
1563       if (mrset->n_vars < 2)
1564         {
1565           mrset_destroy (mrset);
1566           dict->mrsets[i] = dict->mrsets[--dict->n_mrsets];
1567         }
1568       else
1569         i++;
1570     }
1571 }
1572 \f
1573 /* Returns D's attribute set.  The caller may examine or modify
1574    the attribute set, but must not destroy it.  Destroying D or
1575    calling dict_set_attributes for D will also destroy D's
1576    attribute set. */
1577 struct attrset *
1578 dict_get_attributes (const struct dictionary *d) 
1579 {
1580   return CONST_CAST (struct attrset *, &d->attributes);
1581 }
1582
1583 /* Replaces D's attributes set by a copy of ATTRS. */
1584 void
1585 dict_set_attributes (struct dictionary *d, const struct attrset *attrs)
1586 {
1587   attrset_destroy (&d->attributes);
1588   attrset_clone (&d->attributes, attrs);
1589 }
1590
1591 /* Returns true if D has at least one attribute in its attribute
1592    set, false if D's attribute set is empty. */
1593 bool
1594 dict_has_attributes (const struct dictionary *d) 
1595 {
1596   return attrset_count (&d->attributes) > 0;
1597 }
1598
1599 /* Called from variable.c to notify the dictionary that some property (indicated
1600    by WHAT) of the variable has changed.  OLDVAR is a copy of V as it existed
1601    prior to the change.  OLDVAR is destroyed by this function.
1602 */
1603 void
1604 dict_var_changed (const struct variable *v, unsigned int what, struct variable *oldvar)
1605 {
1606   if ( var_has_vardict (v))
1607     {
1608       const struct vardict_info *vardict = var_get_vardict (v);
1609       struct dictionary *d = vardict->dict;
1610
1611       if ( NULL == d)
1612         return;
1613
1614       if (d->changed ) d->changed (d, d->changed_data);
1615       if ( d->callbacks && d->callbacks->var_changed )
1616         d->callbacks->var_changed (d, var_get_dict_index (v), what, oldvar, d->cb_data);
1617     }
1618   var_destroy (oldvar);
1619 }
1620
1621
1622 \f
1623 /* Dictionary used to contain "internal variables". */
1624 static struct dictionary *internal_dict;
1625
1626 /* Create a variable of the specified WIDTH to be used for internal
1627    calculations only.  The variable is assigned case index CASE_IDX. */
1628 struct variable *
1629 dict_create_internal_var (int case_idx, int width)
1630 {
1631   if (internal_dict == NULL)
1632     internal_dict = dict_create ("UTF-8");
1633
1634   for (;;)
1635     {
1636       static int counter = INT_MAX / 2;
1637       struct variable *var;
1638       char name[64];
1639
1640       if (++counter == INT_MAX)
1641         counter = INT_MAX / 2;
1642
1643       sprintf (name, "$internal%d", counter);
1644       var = dict_create_var (internal_dict, name, width);
1645       if (var != NULL)
1646         {
1647           set_var_case_index (var, case_idx);
1648           return var;
1649         }
1650     }
1651 }
1652
1653 /* Destroys VAR, which must have been created with
1654    dict_create_internal_var(). */
1655 void
1656 dict_destroy_internal_var (struct variable *var)
1657 {
1658   if (var != NULL)
1659     {
1660       dict_delete_var (internal_dict, var);
1661
1662       /* Destroy internal_dict if it has no variables left, just so that
1663          valgrind --leak-check --show-reachable won't show internal_dict. */
1664       if (dict_get_var_cnt (internal_dict) == 0)
1665         {
1666           dict_destroy (internal_dict);
1667           internal_dict = NULL;
1668         }
1669     }
1670 }
1671 \f
1672 int
1673 vardict_get_dict_index (const struct vardict_info *vardict)
1674 {
1675   return vardict - vardict->dict->var;
1676 }