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