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