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