dictionary: Introduce SPLIT_NONE for dictionaries without split variables.
[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_NONE,
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 == SPLIT_NONE ? SPLIT_LAYERED : 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 enum split_type
417 dict_get_split_type (const struct dictionary *d)
418 {
419   return d->split_type;
420 }
421
422 /* Sets N split vars SPLIT in dictionary D. */
423 void
424 dict_set_split_vars (struct dictionary *d,
425                      struct variable *const *split, size_t n,
426                      enum split_type type)
427 {
428   dict_set_split_vars__ (d, split, n, type, false);
429 }
430
431 void
432 dict_clear_split_vars (struct dictionary *d)
433 {
434   dict_set_split_vars (d, NULL, 0, SPLIT_NONE);
435 }
436 \f
437
438 /* Deletes variable V from dictionary D and frees V.
439
440    This is a very bad idea if there might be any pointers to V
441    from outside D.  In general, no variable in the active dataset's
442    dictionary should be deleted when any transformations are
443    active on the dictionary's dataset, because those
444    transformations might reference the deleted variable.  The
445    safest time to delete a variable is just after a procedure has
446    been executed, as done by DELETE VARIABLES.
447
448    Pointers to V within D are not a problem, because
449    dict_delete_var() knows to remove V from split variables,
450    weights, filters, etc. */
451 static void
452 dict_delete_var__ (struct dictionary *d, struct variable *v, bool skip_callbacks)
453 {
454   int dict_index = var_get_dict_index (v);
455   const int case_index = var_get_case_index (v);
456
457   assert (dict_contains_var (d, v));
458
459   dict_unset_split_var (d, v, skip_callbacks);
460   dict_unset_mrset_var (d, v);
461
462   if (d->weight == v)
463     dict_set_weight (d, NULL);
464
465   if (d->filter == v)
466     dict_set_filter (d, NULL);
467
468   dict_clear_vectors (d);
469
470   /* Remove V from var array. */
471   unindex_vars (d, dict_index, d->n_vars);
472   remove_element (d->vars, d->n_vars, sizeof *d->vars, dict_index);
473   d->n_vars--;
474
475   /* Update dict_index for each affected variable. */
476   reindex_vars (d, dict_index, d->n_vars, skip_callbacks);
477
478   /* Free memory. */
479   var_clear_vardict (v);
480
481   if (! skip_callbacks)
482     {
483       if (d->changed) d->changed (d, d->changed_data);
484       if (d->callbacks &&  d->callbacks->var_deleted)
485         d->callbacks->var_deleted (d, v, dict_index, case_index, d->cb_data);
486     }
487
488   invalidate_proto (d);
489   var_unref (v);
490 }
491
492 /* Deletes variable V from dictionary D and frees V.
493
494    This is a very bad idea if there might be any pointers to V
495    from outside D.  In general, no variable in the active dataset's
496    dictionary should be deleted when any transformations are
497    active on the dictionary's dataset, because those
498    transformations might reference the deleted variable.  The
499    safest time to delete a variable is just after a procedure has
500    been executed, as done by DELETE VARIABLES.
501
502    Pointers to V within D are not a problem, because
503    dict_delete_var() knows to remove V from split variables,
504    weights, filters, etc. */
505 void
506 dict_delete_var (struct dictionary *d, struct variable *v)
507 {
508   dict_delete_var__ (d, v, false);
509 }
510
511
512 /* Deletes the COUNT variables listed in VARS from D.  This is
513    unsafe; see the comment on dict_delete_var() for details. */
514 void
515 dict_delete_vars (struct dictionary *d,
516                   struct variable *const *vars, size_t count)
517 {
518   /* FIXME: this can be done in O(count) time, but this algorithm
519      is O(count**2). */
520   assert (count == 0 || vars != NULL);
521
522   while (count-- > 0)
523     dict_delete_var (d, *vars++);
524 }
525
526 /* Deletes the COUNT variables in D starting at index IDX.  This
527    is unsafe; see the comment on dict_delete_var() for
528    details. Deleting consecutive vars will result in less callbacks
529    compared to iterating over dict_delete_var.
530    A simple while loop over dict_delete_var will
531    produce (d->n_vars - IDX) * COUNT variable changed callbacks
532    plus COUNT variable delete callbacks.
533    This here produces d->n_vars - IDX variable changed callbacks
534    plus COUNT variable delete callbacks. */
535 void
536 dict_delete_consecutive_vars (struct dictionary *d, size_t idx, size_t count)
537 {
538   assert (idx + count <= d->n_vars);
539
540   /* We need to store the variable and the corresponding case_index
541      for the delete callbacks later. We store them in a linked list.*/
542   struct delvar {
543     struct ll ll;
544     struct variable *var;
545     int case_index;
546   };
547   struct ll_list list = LL_INITIALIZER (list);
548
549   for (size_t i = idx; i < idx + count; i++)
550     {
551       struct delvar *dv = xmalloc (sizeof (struct delvar));
552       assert (dv);
553       struct variable *v = d->vars[i].var;
554
555       dict_unset_split_var (d, v, false);
556       dict_unset_mrset_var (d, v);
557
558       if (d->weight == v)
559         dict_set_weight (d, NULL);
560
561       if (d->filter == v)
562         dict_set_filter (d, NULL);
563
564       dv->var = v;
565       dv->case_index = var_get_case_index (v);
566       ll_push_tail (&list, (struct ll *)dv);
567     }
568
569   dict_clear_vectors (d);
570
571   /* Remove variables from var array. */
572   unindex_vars (d, idx, d->n_vars);
573   remove_range (d->vars, d->n_vars, sizeof *d->vars, idx, count);
574   d->n_vars -= count;
575
576   /* Reindexing will result variable-changed callback */
577   reindex_vars (d, idx, d->n_vars, false);
578
579   invalidate_proto (d);
580   if (d->changed) d->changed (d, d->changed_data);
581
582   /* Now issue the variable delete callbacks and delete
583      the variables. The vardict is not valid at this point
584      anymore. That is the reason why we stored the
585      caseindex before reindexing. */
586   for (size_t vi = idx; vi < idx + count; vi++)
587     {
588       struct delvar *dv = (struct delvar *) ll_pop_head (&list);
589       var_clear_vardict (dv->var);
590       if (d->callbacks &&  d->callbacks->var_deleted)
591         d->callbacks->var_deleted (d, dv->var, vi, dv->case_index, d->cb_data);
592       var_unref (dv->var);
593       free (dv);
594     }
595 }
596
597 /* Deletes scratch variables from dictionary D. */
598 void
599 dict_delete_scratch_vars (struct dictionary *d)
600 {
601   int i;
602
603   /* FIXME: this can be done in O(count) time, but this algorithm
604      is O(count**2). */
605   for (i = 0; i < d->n_vars;)
606     if (var_get_dict_class (d->vars[i].var) == DC_SCRATCH)
607       dict_delete_var (d, d->vars[i].var);
608     else
609       i++;
610 }
611
612 \f
613
614 /* Clears the contents from a dictionary without destroying the
615    dictionary itself. */
616 static void
617 dict_clear__ (struct dictionary *d, bool skip_callbacks)
618 {
619   /* FIXME?  Should we really clear case_limit, label, documents?
620      Others are necessarily cleared by deleting all the variables.*/
621   while (d->n_vars > 0)
622     {
623       dict_delete_var__ (d, d->vars[d->n_vars - 1].var, skip_callbacks);
624     }
625
626   free (d->vars);
627   d->vars = NULL;
628   d->n_vars = d->allocated_vars = 0;
629   invalidate_proto (d);
630   hmap_clear (&d->name_map);
631   d->next_value_idx = 0;
632   dict_set_split_vars__ (d, NULL, 0, SPLIT_NONE, skip_callbacks);
633
634   if (skip_callbacks)
635     {
636       d->weight = NULL;
637       d->filter = NULL;
638     }
639   else
640     {
641       dict_set_weight (d, NULL);
642       dict_set_filter (d, NULL);
643     }
644   d->case_limit = 0;
645   free (d->label);
646   d->label = NULL;
647   string_array_clear (&d->documents);
648   dict_clear_vectors (d);
649   attrset_clear (&d->attributes);
650 }
651
652 /* Clears the contents from a dictionary without destroying the
653    dictionary itself. */
654 void
655 dict_clear (struct dictionary *d)
656 {
657   dict_clear__ (d, false);
658 }
659
660 /* Clears a dictionary and destroys it. */
661 static void
662 _dict_destroy (struct dictionary *d)
663 {
664   /* In general, we don't want callbacks occurring, if the dictionary
665      is being destroyed */
666   d->callbacks  = NULL ;
667
668   dict_clear__ (d, true);
669   string_array_destroy (&d->documents);
670   hmap_destroy (&d->name_map);
671   attrset_destroy (&d->attributes);
672   dict_clear_mrsets (d);
673   free (d->encoding);
674   free (d);
675 }
676
677 struct dictionary *
678 dict_ref (struct dictionary *d)
679 {
680   d->ref_cnt++;
681   return d;
682 }
683
684 void
685 dict_unref (struct dictionary *d)
686 {
687   if (d == NULL)
688     return;
689   d->ref_cnt--;
690   assert (d->ref_cnt >= 0);
691   if (d->ref_cnt == 0)
692     _dict_destroy (d);
693 }
694
695 /* Returns the number of variables in D. */
696 size_t
697 dict_get_n_vars (const struct dictionary *d)
698 {
699   return d->n_vars;
700 }
701
702 /* Returns the variable in D with dictionary index IDX, which
703    must be between 0 and the count returned by
704    dict_get_n_vars(), exclusive. */
705 struct variable *
706 dict_get_var (const struct dictionary *d, size_t idx)
707 {
708   assert (idx < d->n_vars);
709
710   return d->vars[idx].var;
711 }
712
713 /* Sets *VARS to an array of pointers to variables in D and *N
714    to the number of variables in *D.  All variables are returned
715    except for those, if any, in the classes indicated by EXCLUDE.
716    (There is no point in putting DC_SYSTEM in EXCLUDE as
717    dictionaries never include system variables.) */
718 void
719 dict_get_vars (const struct dictionary *d, const struct variable ***vars,
720                size_t *n, enum dict_class exclude)
721 {
722   dict_get_vars_mutable (d, (struct variable ***) vars, n, exclude);
723 }
724
725 /* Sets *VARS to an array of pointers to variables in D and *N
726    to the number of variables in *D.  All variables are returned
727    except for those, if any, in the classes indicated by EXCLUDE.
728    (There is no point in putting DC_SYSTEM in EXCLUDE as
729    dictionaries never include system variables.) */
730 void
731 dict_get_vars_mutable (const struct dictionary *d, struct variable ***vars,
732                        size_t *n, enum dict_class exclude)
733 {
734   size_t count;
735   size_t i;
736
737   assert (exclude == (exclude & DC_ALL));
738
739   count = 0;
740   for (i = 0; i < d->n_vars; i++)
741     {
742       enum dict_class class = var_get_dict_class (d->vars[i].var);
743       if (!(class & exclude))
744         count++;
745     }
746
747   *vars = xnmalloc (count, sizeof **vars);
748   *n = 0;
749   for (i = 0; i < d->n_vars; i++)
750     {
751       enum dict_class class = var_get_dict_class (d->vars[i].var);
752       if (!(class & exclude))
753         (*vars)[(*n)++] = d->vars[i].var;
754     }
755   assert (*n == count);
756 }
757
758 static struct variable *
759 add_var_with_case_index (struct dictionary *d, struct variable *v,
760                          int case_index)
761 {
762   struct vardict_info *vardict;
763
764   assert (case_index >= d->next_value_idx);
765
766   /* Update dictionary. */
767   if (d->n_vars >= d->allocated_vars)
768     {
769       size_t i;
770
771       d->vars = x2nrealloc (d->vars, &d->allocated_vars, sizeof *d->vars);
772       hmap_clear (&d->name_map);
773       for (i = 0; i < d->n_vars; i++)
774         {
775           var_set_vardict (d->vars[i].var, &d->vars[i]);
776           hmap_insert_fast (&d->name_map, &d->vars[i].name_node,
777                             d->vars[i].name_node.hash);
778         }
779     }
780
781   vardict = &d->vars[d->n_vars++];
782   vardict->dict = d;
783   vardict->var = v;
784   hmap_insert (&d->name_map, &vardict->name_node,
785                utf8_hash_case_string (var_get_name (v), 0));
786   vardict->case_index = case_index;
787   var_set_vardict (v, vardict);
788
789   if (d->changed) d->changed (d, d->changed_data);
790   if (d->callbacks &&  d->callbacks->var_added)
791     d->callbacks->var_added (d, var_get_dict_index (v), d->cb_data);
792
793   invalidate_proto (d);
794   d->next_value_idx = case_index + 1;
795
796   return v;
797 }
798
799 static struct variable *
800 add_var (struct dictionary *d, struct variable *v)
801 {
802   return add_var_with_case_index (d, v, d->next_value_idx);
803 }
804
805 /* Creates and returns a new variable in D with the given NAME
806    and WIDTH.  Returns a null pointer if the given NAME would
807    duplicate that of an existing variable in the dictionary. */
808 struct variable *
809 dict_create_var (struct dictionary *d, const char *name, int width)
810 {
811   return (dict_lookup_var (d, name) == NULL
812           ? dict_create_var_assert (d, name, width)
813           : NULL);
814 }
815
816 /* Creates and returns a new variable in D with the given NAME
817    and WIDTH.  Assert-fails if the given NAME would duplicate
818    that of an existing variable in the dictionary. */
819 struct variable *
820 dict_create_var_assert (struct dictionary *d, const char *name, int width)
821 {
822   assert (dict_lookup_var (d, name) == NULL);
823   return add_var (d, var_create (name, width));
824 }
825
826 /* Creates and returns a new variable in D, as a copy of existing variable
827    OLD_VAR, which need not be in D or in any dictionary.  Returns a null
828    pointer if OLD_VAR's name would duplicate that of an existing variable in
829    the dictionary. */
830 struct variable *
831 dict_clone_var (struct dictionary *d, const struct variable *old_var)
832 {
833   return dict_clone_var_as (d, old_var, var_get_name (old_var));
834 }
835
836 /* Creates and returns a new variable in D, as a copy of existing variable
837    OLD_VAR, which need not be in D or in any dictionary.  Assert-fails if
838    OLD_VAR's name would duplicate that of an existing variable in the
839    dictionary. */
840 struct variable *
841 dict_clone_var_assert (struct dictionary *d, const struct variable *old_var)
842 {
843   return dict_clone_var_as_assert (d, old_var, var_get_name (old_var));
844 }
845
846 /* Creates and returns a new variable in D with name NAME, as a copy of
847    existing variable OLD_VAR, which need not be in D or in any dictionary.
848    Returns a null pointer if the given NAME would duplicate that of an existing
849    variable in the dictionary. */
850 struct variable *
851 dict_clone_var_as (struct dictionary *d, const struct variable *old_var,
852                    const char *name)
853 {
854   return (dict_lookup_var (d, name) == NULL
855           ? dict_clone_var_as_assert (d, old_var, name)
856           : NULL);
857 }
858
859 /* Creates and returns a new variable in D with name NAME, as a copy of
860    existing variable OLD_VAR, which need not be in D or in any dictionary.
861    Assert-fails if the given NAME would duplicate that of an existing variable
862    in the dictionary. */
863 struct variable *
864 dict_clone_var_as_assert (struct dictionary *d, const struct variable *old_var,
865                           const char *name)
866 {
867   struct variable *new_var = var_clone (old_var);
868   assert (dict_lookup_var (d, name) == NULL);
869   var_set_name (new_var, name);
870   return add_var (d, new_var);
871 }
872
873 struct variable *
874 dict_clone_var_in_place_assert (struct dictionary *d,
875                                 const struct variable *old_var)
876 {
877   assert (dict_lookup_var (d, var_get_name (old_var)) == NULL);
878   return add_var_with_case_index (d, var_clone (old_var),
879                                   var_get_case_index (old_var));
880 }
881
882 /* Returns the variable named NAME in D, or a null pointer if no
883    variable has that name. */
884 struct variable *
885 dict_lookup_var (const struct dictionary *d, const char *name)
886 {
887   struct vardict_info *vardict;
888
889   HMAP_FOR_EACH_WITH_HASH (vardict, struct vardict_info, name_node,
890                            utf8_hash_case_string (name, 0), &d->name_map)
891     {
892       struct variable *var = vardict->var;
893       if (!utf8_strcasecmp (var_get_name (var), name))
894         return var;
895     }
896
897   return NULL;
898 }
899
900 /* Returns the variable named NAME in D.  Assert-fails if no
901    variable has that name. */
902 struct variable *
903 dict_lookup_var_assert (const struct dictionary *d, const char *name)
904 {
905   struct variable *v = dict_lookup_var (d, name);
906   assert (v != NULL);
907   return v;
908 }
909
910 /* Returns true if variable V is in dictionary D,
911    false otherwise. */
912 bool
913 dict_contains_var (const struct dictionary *d, const struct variable *v)
914 {
915   return (var_has_vardict (v)
916           && vardict_get_dictionary (var_get_vardict (v)) == d);
917 }
918
919 /* Moves V to 0-based position IDX in D.  Other variables in D,
920    if any, retain their relative positions.  Runs in time linear
921    in the distance moved. */
922 void
923 dict_reorder_var (struct dictionary *d, struct variable *v, size_t new_index)
924 {
925   size_t old_index = var_get_dict_index (v);
926
927   assert (new_index < d->n_vars);
928
929   unindex_vars (d, MIN (old_index, new_index), MAX (old_index, new_index) + 1);
930   move_element (d->vars, d->n_vars, sizeof *d->vars, old_index, new_index);
931   reindex_vars (d, MIN (old_index, new_index), MAX (old_index, new_index) + 1, false);
932 }
933
934 /* Reorders the variables in D, placing the COUNT variables
935    listed in ORDER in that order at the beginning of D.  The
936    other variables in D, if any, retain their relative
937    positions. */
938 void
939 dict_reorder_vars (struct dictionary *d,
940                    struct variable *const *order, size_t count)
941 {
942   struct vardict_info *new_var;
943   size_t i;
944
945   assert (count == 0 || order != NULL);
946   assert (count <= d->n_vars);
947
948   new_var = xnmalloc (d->allocated_vars, sizeof *new_var);
949
950   /* Add variables in ORDER to new_var. */
951   for (i = 0; i < count; i++)
952     {
953       struct vardict_info *old_var;
954
955       assert (dict_contains_var (d, order[i]));
956
957       old_var = var_get_vardict (order[i]);
958       new_var[i] = *old_var;
959       old_var->dict = NULL;
960     }
961
962   /* Add remaining variables to new_var. */
963   for (i = 0; i < d->n_vars; i++)
964     if (d->vars[i].dict != NULL)
965       new_var[count++] = d->vars[i];
966   assert (count == d->n_vars);
967
968   /* Replace old vardicts by new ones. */
969   free (d->vars);
970   d->vars = new_var;
971
972   hmap_clear (&d->name_map);
973   reindex_vars (d, 0, d->n_vars, false);
974 }
975
976 /* Changes the name of variable V that is currently in a dictionary to
977    NEW_NAME. */
978 static void
979 rename_var (struct variable *v, const char *new_name)
980 {
981   struct vardict_info *vardict = var_get_vardict (v);
982   var_clear_vardict (v);
983   var_set_name (v, new_name);
984   vardict->name_node.hash = utf8_hash_case_string (new_name, 0);
985   var_set_vardict (v, vardict);
986 }
987
988 /* Tries to changes the name of V in D to name NEW_NAME.  Returns true if
989    successful, false if a variable (other than V) with the given name already
990    exists in D. */
991 bool
992 dict_try_rename_var (struct dictionary *d, struct variable *v,
993                      const char *new_name)
994 {
995   struct variable *conflict = dict_lookup_var (d, new_name);
996   if (conflict && v != conflict)
997     return false;
998
999   struct variable *old = var_clone (v);
1000   unindex_var (d, var_get_vardict (v));
1001   rename_var (v, new_name);
1002   reindex_var (d, var_get_vardict (v), false);
1003
1004   if (settings_get_algorithm () == ENHANCED)
1005     var_clear_short_names (v);
1006
1007   if (d->changed) d->changed (d, d->changed_data);
1008   if (d->callbacks &&  d->callbacks->var_changed)
1009     d->callbacks->var_changed (d, var_get_dict_index (v), VAR_TRAIT_NAME, old, d->cb_data);
1010
1011   var_unref (old);
1012
1013   return true;
1014 }
1015
1016 /* Changes the name of V in D to name NEW_NAME.  Assert-fails if
1017    a variable named NEW_NAME is already in D, except that
1018    NEW_NAME may be the same as V's existing name. */
1019 void
1020 dict_rename_var (struct dictionary *d, struct variable *v,
1021                  const char *new_name)
1022 {
1023   bool ok UNUSED = dict_try_rename_var (d, v, new_name);
1024   assert (ok);
1025 }
1026
1027 /* Renames COUNT variables specified in VARS to the names given
1028    in NEW_NAMES within dictionary D.  If the renaming would
1029    result in a duplicate variable name, returns false and stores a
1030    name that would be duplicated into *ERR_NAME (if ERR_NAME is
1031    non-null).  Otherwise, the renaming is successful, and true
1032    is returned. */
1033 bool
1034 dict_rename_vars (struct dictionary *d,
1035                   struct variable **vars, char **new_names, size_t count,
1036                   char **err_name)
1037 {
1038   struct pool *pool;
1039   char **old_names;
1040   size_t i;
1041
1042   assert (count == 0 || vars != NULL);
1043   assert (count == 0 || new_names != NULL);
1044
1045   /* Save the names of the variables to be renamed. */
1046   pool = pool_create ();
1047   old_names = pool_nalloc (pool, count, sizeof *old_names);
1048   for (i = 0; i < count; i++)
1049     old_names[i] = pool_strdup (pool, var_get_name (vars[i]));
1050
1051   /* Remove the variables to be renamed from the name hash,
1052      and rename them. */
1053   for (i = 0; i < count; i++)
1054     {
1055       unindex_var (d, var_get_vardict (vars[i]));
1056       rename_var (vars[i], new_names[i]);
1057     }
1058
1059   /* Add the renamed variables back into the name hash,
1060      checking for conflicts. */
1061   for (i = 0; i < count; i++)
1062     {
1063       if (dict_lookup_var (d, var_get_name (vars[i])) != NULL)
1064         {
1065           /* There is a name conflict.
1066              Back out all the name changes that have already
1067              taken place, and indicate failure. */
1068           size_t fail_idx = i;
1069           if (err_name != NULL)
1070             *err_name = new_names[i];
1071
1072           for (i = 0; i < fail_idx; i++)
1073             unindex_var (d, var_get_vardict (vars[i]));
1074
1075           for (i = 0; i < count; i++)
1076             {
1077               rename_var (vars[i], old_names[i]);
1078               reindex_var (d, var_get_vardict (vars[i]), false);
1079             }
1080
1081           pool_destroy (pool);
1082           return false;
1083         }
1084       reindex_var (d, var_get_vardict (vars[i]), false);
1085     }
1086
1087   /* Clear short names. */
1088   if (settings_get_algorithm () == ENHANCED)
1089     for (i = 0; i < count; i++)
1090       var_clear_short_names (vars[i]);
1091
1092   pool_destroy (pool);
1093   return true;
1094 }
1095
1096 /* Returns true if a variable named NAME may be inserted in DICT;
1097    that is, if there is not already a variable with that name in
1098    DICT and if NAME is not a reserved word.  (The caller's checks
1099    have already verified that NAME is otherwise acceptable as a
1100    variable name.) */
1101 static bool
1102 var_name_is_insertable (const struct dictionary *dict, const char *name)
1103 {
1104   return (dict_lookup_var (dict, name) == NULL
1105           && lex_id_to_token (ss_cstr (name)) == T_ID);
1106 }
1107
1108 static char *
1109 make_hinted_name (const struct dictionary *dict, const char *hint)
1110 {
1111   size_t hint_len = strlen (hint);
1112   bool dropped = false;
1113   char *root, *rp;
1114   size_t ofs;
1115   int mblen;
1116
1117   if (hint_len > ID_MAX_LEN)
1118     hint_len = ID_MAX_LEN;
1119
1120   /* The allocation size here is OK: characters that are copied directly fit
1121      OK, and characters that are not copied directly are replaced by a single
1122      '_' byte.  If u8_mbtouc() replaces bad input by 0xfffd, then that will get
1123      replaced by '_' too.  */
1124   root = rp = xmalloc (hint_len + 1);
1125   for (ofs = 0; ofs < hint_len; ofs += mblen)
1126     {
1127       ucs4_t uc;
1128
1129       mblen = u8_mbtouc (&uc, CHAR_CAST (const uint8_t *, hint + ofs),
1130                          hint_len - ofs);
1131       if (rp == root
1132           ? lex_uc_is_id1 (uc) && uc != '$'
1133           : lex_uc_is_idn (uc))
1134         {
1135           if (dropped)
1136             {
1137               *rp++ = '_';
1138               dropped = false;
1139             }
1140           rp += u8_uctomb (CHAR_CAST (uint8_t *, rp), uc, 6);
1141         }
1142       else if (rp != root)
1143         dropped = true;
1144     }
1145   *rp = '\0';
1146
1147   if (root[0] != '\0')
1148     {
1149       unsigned long int i;
1150
1151       if (var_name_is_insertable (dict, root))
1152         return root;
1153
1154       for (i = 0; i < ULONG_MAX; i++)
1155         {
1156           char suffix[INT_BUFSIZE_BOUND (i) + 1];
1157           char *name;
1158
1159           suffix[0] = '_';
1160           if (!str_format_26adic (i + 1, true, &suffix[1], sizeof suffix - 1))
1161             NOT_REACHED ();
1162
1163           name = utf8_encoding_concat (root, suffix, dict->encoding, 64);
1164           if (var_name_is_insertable (dict, name))
1165             {
1166               free (root);
1167               return name;
1168             }
1169           free (name);
1170         }
1171     }
1172
1173   free (root);
1174
1175   return NULL;
1176 }
1177
1178 static char *
1179 make_numeric_name (const struct dictionary *dict, unsigned long int *num_start)
1180 {
1181   unsigned long int number;
1182
1183   for (number = num_start != NULL ? MAX (*num_start, 1) : 1;
1184        number < ULONG_MAX;
1185        number++)
1186     {
1187       char name[3 + INT_STRLEN_BOUND (number) + 1];
1188
1189       sprintf (name, "VAR%03lu", number);
1190       if (dict_lookup_var (dict, name) == NULL)
1191         {
1192           if (num_start != NULL)
1193             *num_start = number + 1;
1194           return xstrdup (name);
1195         }
1196     }
1197
1198   NOT_REACHED ();
1199 }
1200
1201
1202 /* Devises and returns a variable name unique within DICT.  The variable name
1203    is owned by the caller, which must free it with free() when it is no longer
1204    needed.
1205
1206    HINT, if it is non-null, is used as a suggestion that will be
1207    modified for suitability as a variable name and for
1208    uniqueness.
1209
1210    If HINT is null or entirely unsuitable, a name in the form
1211    "VAR%03d" will be generated, where the smallest unused integer
1212    value is used.  If NUM_START is non-null, then its value is
1213    used as the minimum numeric value to check, and it is updated
1214    to the next value to be checked.
1215 */
1216 char *
1217 dict_make_unique_var_name (const struct dictionary *dict, const char *hint,
1218                            unsigned long int *num_start)
1219 {
1220   if (hint != NULL)
1221     {
1222       char *hinted_name = make_hinted_name (dict, hint);
1223       if (hinted_name != NULL)
1224         return hinted_name;
1225     }
1226
1227   return make_numeric_name (dict, num_start);
1228 }
1229
1230 /* Returns whether variable names must be valid identifiers.  Normally, this is
1231    true, but sometimes a dictionary is prepared for external use (e.g. output
1232    to a CSV file) where names don't have to be valid. */
1233 bool
1234 dict_get_names_must_be_ids (const struct dictionary *d)
1235 {
1236   return d->names_must_be_ids;
1237 }
1238
1239 /* Sets whether variable names must be valid identifiers.  Normally, this is
1240    true, but sometimes a dictionary is prepared for external use (e.g. output
1241    to a CSV file) where names don't have to be valid.
1242
1243    Changing this setting from false to true doesn't make the dictionary check
1244    all the existing variable names, so it can cause an invariant violation. */
1245 void
1246 dict_set_names_must_be_ids (struct dictionary *d, bool names_must_be_ids)
1247 {
1248   d->names_must_be_ids = names_must_be_ids;
1249 }
1250
1251 /* Returns the weighting variable in dictionary D, or a null
1252    pointer if the dictionary is unweighted. */
1253 struct variable *
1254 dict_get_weight (const struct dictionary *d)
1255 {
1256   assert (d->weight == NULL || dict_contains_var (d, d->weight));
1257
1258   return d->weight;
1259 }
1260
1261 /* Returns the value of D's weighting variable in case C, except
1262    that a negative or missing weight is returned as 0.  Returns 1 if the
1263    dictionary is unweighted.  Will warn about missing, negative,
1264    or zero values if *WARN_ON_INVALID is true.  The function will
1265    set *WARN_ON_INVALID to false if an invalid weight is
1266    found. */
1267 double
1268 dict_get_case_weight (const struct dictionary *d, const struct ccase *c,
1269                       bool *warn_on_invalid)
1270 {
1271   assert (c != NULL);
1272
1273   if (d->weight == NULL)
1274     return 1.0;
1275   else
1276     {
1277       double w = case_num (c, d->weight);
1278
1279       return var_force_valid_weight (d->weight, w, warn_on_invalid);
1280     }
1281 }
1282
1283 /* Like dict_get_case_weight(), but additionally rounds each weight to the
1284    nearest integer.  */
1285 double
1286 dict_get_rounded_case_weight (const struct dictionary *d,
1287                               const struct ccase *c, bool *warn_on_invalid)
1288 {
1289   return floor (dict_get_case_weight (d, c, warn_on_invalid) + 0.5);
1290 }
1291
1292 /* Returns the format to use for weights. */
1293 const struct fmt_spec *
1294 dict_get_weight_format (const struct dictionary *d)
1295 {
1296   return d->weight ? var_get_print_format (d->weight) : &F_8_0;
1297 }
1298
1299 /* Sets the weighting variable of D to V, or turning off
1300    weighting if V is a null pointer. */
1301 void
1302 dict_set_weight (struct dictionary *d, struct variable *v)
1303 {
1304   assert (v == NULL || dict_contains_var (d, v));
1305   assert (v == NULL || var_is_numeric (v));
1306
1307   d->weight = v;
1308
1309   if (d->changed) d->changed (d, d->changed_data);
1310   if (d->callbacks &&  d->callbacks->weight_changed)
1311     d->callbacks->weight_changed (d,
1312                                   v ? var_get_dict_index (v) : -1,
1313                                   d->cb_data);
1314 }
1315
1316 /* Returns the filter variable in dictionary D (see cmd_filter())
1317    or a null pointer if the dictionary is unfiltered. */
1318 struct variable *
1319 dict_get_filter (const struct dictionary *d)
1320 {
1321   assert (d->filter == NULL || dict_contains_var (d, d->filter));
1322
1323   return d->filter;
1324 }
1325
1326 /* Sets V as the filter variable for dictionary D.  Passing a
1327    null pointer for V turn off filtering. */
1328 void
1329 dict_set_filter (struct dictionary *d, struct variable *v)
1330 {
1331   assert (v == NULL || dict_contains_var (d, v));
1332   assert (v == NULL || var_is_numeric (v));
1333
1334   d->filter = v;
1335
1336   if (d->changed) d->changed (d, d->changed_data);
1337   if (d->callbacks && d->callbacks->filter_changed)
1338     d->callbacks->filter_changed (d,
1339                                   v ? var_get_dict_index (v) : -1,
1340                                       d->cb_data);
1341 }
1342
1343 /* Returns the case limit for dictionary D, or zero if the number
1344    of cases is unlimited. */
1345 casenumber
1346 dict_get_case_limit (const struct dictionary *d)
1347 {
1348   return d->case_limit;
1349 }
1350
1351 /* Sets CASE_LIMIT as the case limit for dictionary D.  Use
1352    0 for CASE_LIMIT to indicate no limit. */
1353 void
1354 dict_set_case_limit (struct dictionary *d, casenumber case_limit)
1355 {
1356   d->case_limit = case_limit;
1357 }
1358
1359 /* Returns the prototype used for cases created by dictionary D. */
1360 const struct caseproto *
1361 dict_get_proto (const struct dictionary *d_)
1362 {
1363   struct dictionary *d = CONST_CAST (struct dictionary *, d_);
1364   if (d->proto == NULL)
1365     {
1366       size_t i;
1367
1368       d->proto = caseproto_create ();
1369       d->proto = caseproto_reserve (d->proto, d->n_vars);
1370       for (i = 0; i < d->n_vars; i++)
1371         d->proto = caseproto_set_width (d->proto,
1372                                         var_get_case_index (d->vars[i].var),
1373                                         var_get_width (d->vars[i].var));
1374     }
1375   return d->proto;
1376 }
1377
1378 /* Returns the case index of the next value to be added to D.
1379    This value is the number of `union value's that need to be
1380    allocated to store a case for dictionary D. */
1381 int
1382 dict_get_next_value_idx (const struct dictionary *d)
1383 {
1384   return d->next_value_idx;
1385 }
1386
1387 /* Returns the number of bytes needed to store a case for
1388    dictionary D. */
1389 size_t
1390 dict_get_case_size (const struct dictionary *d)
1391 {
1392   return sizeof (union value) * dict_get_next_value_idx (d);
1393 }
1394
1395 /* Reassigns values in dictionary D so that fragmentation is
1396    eliminated. */
1397 void
1398 dict_compact_values (struct dictionary *d)
1399 {
1400   size_t i;
1401
1402   d->next_value_idx = 0;
1403   for (i = 0; i < d->n_vars; i++)
1404     {
1405       struct variable *v = d->vars[i].var;
1406       set_var_case_index (v, d->next_value_idx++);
1407     }
1408   invalidate_proto (d);
1409 }
1410
1411 /* Returns the number of values occupied by the variables in
1412    dictionary D.  All variables are considered if EXCLUDE_CLASSES
1413    is 0, or it may contain one or more of (1u << DC_ORDINARY),
1414    (1u << DC_SYSTEM), or (1u << DC_SCRATCH) to exclude the
1415    corresponding type of variable.
1416
1417    The return value may be less than the number of values in one
1418    of dictionary D's cases (as returned by
1419    dict_get_next_value_idx) even if E is 0, because there may be
1420    gaps in D's cases due to deleted variables. */
1421 size_t
1422 dict_count_values (const struct dictionary *d, unsigned int exclude_classes)
1423 {
1424   assert ((exclude_classes & ~((1u << DC_ORDINARY)
1425                                | (1u << DC_SYSTEM)
1426                                | (1u << DC_SCRATCH))) == 0);
1427
1428   size_t n = 0;
1429   for (size_t i = 0; i < d->n_vars; i++)
1430     {
1431       enum dict_class class = var_get_dict_class (d->vars[i].var);
1432       if (!(exclude_classes & (1u << class)))
1433         n++;
1434     }
1435   return n;
1436 }
1437
1438 /* Returns the case prototype that would result after deleting
1439    all variables from D that are not in one of the
1440    EXCLUDE_CLASSES and compacting the dictionary with
1441    dict_compact().
1442
1443    The caller must unref the returned caseproto when it is no
1444    longer needed. */
1445 struct caseproto *
1446 dict_get_compacted_proto (const struct dictionary *d,
1447                           unsigned int exclude_classes)
1448 {
1449   struct caseproto *proto;
1450   size_t i;
1451
1452   assert ((exclude_classes & ~((1u << DC_ORDINARY)
1453                                | (1u << DC_SYSTEM)
1454                                | (1u << DC_SCRATCH))) == 0);
1455
1456   proto = caseproto_create ();
1457   for (i = 0; i < d->n_vars; i++)
1458     {
1459       struct variable *v = d->vars[i].var;
1460       if (!(exclude_classes & (1u << var_get_dict_class (v))))
1461         proto = caseproto_add_width (proto, var_get_width (v));
1462     }
1463   return proto;
1464 }
1465 /* Returns the file label for D, or a null pointer if D is
1466    unlabeled (see cmd_file_label()). */
1467 const char *
1468 dict_get_label (const struct dictionary *d)
1469 {
1470   return d->label;
1471 }
1472
1473 /* Sets D's file label to LABEL, truncating it to at most 60 bytes in D's
1474    encoding.
1475
1476    Removes D's label if LABEL is null or the empty string. */
1477 void
1478 dict_set_label (struct dictionary *d, const char *label)
1479 {
1480   free (d->label);
1481   if (label == NULL || label[0] == '\0')
1482     d->label = NULL;
1483   else
1484     d->label = utf8_encoding_trunc (label, d->encoding, 60);
1485 }
1486
1487 /* Returns the documents for D, as an UTF-8 encoded string_array.  The
1488    return value is always nonnull; if there are no documents then the
1489    string_arary is empty.*/
1490 const struct string_array *
1491 dict_get_documents (const struct dictionary *d)
1492 {
1493   return &d->documents;
1494 }
1495
1496 /* Replaces the documents for D by NEW_DOCS, a UTF-8 encoded string_array. */
1497 void
1498 dict_set_documents (struct dictionary *d, const struct string_array *new_docs)
1499 {
1500   /* Swap out the old documents, instead of destroying them immediately, to
1501      allow the new documents to include pointers into the old ones. */
1502   struct string_array old_docs = STRING_ARRAY_INITIALIZER;
1503   string_array_swap (&d->documents, &old_docs);
1504
1505   for (size_t i = 0; i < new_docs->n; i++)
1506     dict_add_document_line (d, new_docs->strings[i], false);
1507
1508   string_array_destroy (&old_docs);
1509 }
1510
1511 /* Replaces the documents for D by UTF-8 encoded string NEW_DOCS, dividing it
1512    into individual lines at new-line characters.  Each line is truncated to at
1513    most DOC_LINE_LENGTH bytes in D's encoding. */
1514 void
1515 dict_set_documents_string (struct dictionary *d, const char *new_docs)
1516 {
1517   const char *s;
1518
1519   dict_clear_documents (d);
1520   for (s = new_docs; *s != '\0';)
1521     {
1522       size_t len = strcspn (s, "\n");
1523       char *line = xmemdup0 (s, len);
1524       dict_add_document_line (d, line, false);
1525       free (line);
1526
1527       s += len;
1528       if (*s == '\n')
1529         s++;
1530     }
1531 }
1532
1533 /* Drops the documents from dictionary D. */
1534 void
1535 dict_clear_documents (struct dictionary *d)
1536 {
1537   string_array_clear (&d->documents);
1538 }
1539
1540 /* Appends the UTF-8 encoded LINE to the documents in D.  LINE will be
1541    truncated so that it is no more than 80 bytes in the dictionary's
1542    encoding.  If this causes some text to be lost, and ISSUE_WARNING is true,
1543    then a warning will be issued. */
1544 bool
1545 dict_add_document_line (struct dictionary *d, const char *line,
1546                         bool issue_warning)
1547 {
1548   size_t trunc_len;
1549   bool truncated;
1550
1551   trunc_len = utf8_encoding_trunc_len (line, d->encoding, DOC_LINE_LENGTH);
1552   truncated = line[trunc_len] != '\0';
1553   if (truncated && issue_warning)
1554     {
1555       /* TRANSLATORS: "bytes" is correct, not characters due to UTF encoding */
1556       msg (SW, _("Truncating document line to %d bytes."), DOC_LINE_LENGTH);
1557     }
1558
1559   string_array_append_nocopy (&d->documents, xmemdup0 (line, trunc_len));
1560
1561   return !truncated;
1562 }
1563
1564 /* Returns the number of document lines in dictionary D. */
1565 size_t
1566 dict_get_document_n_lines (const struct dictionary *d)
1567 {
1568   return d->documents.n;
1569 }
1570
1571 /* Returns document line number IDX in dictionary D.  The caller must not
1572    modify or free the returned string. */
1573 const char *
1574 dict_get_document_line (const struct dictionary *d, size_t idx)
1575 {
1576   assert (idx < d->documents.n);
1577   return d->documents.strings[idx];
1578 }
1579
1580 /* Creates in D a vector named NAME that contains the N
1581    variables in VAR.  Returns true if successful, or false if a
1582    vector named NAME already exists in D. */
1583 bool
1584 dict_create_vector (struct dictionary *d,
1585                     const char *name,
1586                     struct variable **var, size_t n)
1587 {
1588   assert (n > 0);
1589   for (size_t i = 0; i < n; i++)
1590     assert (dict_contains_var (d, var[i]));
1591
1592   if (dict_lookup_vector (d, name) == NULL)
1593     {
1594       d->vector = xnrealloc (d->vector, d->n_vectors + 1, sizeof *d->vector);
1595       d->vector[d->n_vectors++] = vector_create (name, var, n);
1596       return true;
1597     }
1598   else
1599     return false;
1600 }
1601
1602 /* Creates in D a vector named NAME that contains the N
1603    variables in VAR.  A vector named NAME must not already exist
1604    in D. */
1605 void
1606 dict_create_vector_assert (struct dictionary *d,
1607                            const char *name,
1608                            struct variable **var, size_t n)
1609 {
1610   assert (dict_lookup_vector (d, name) == NULL);
1611   dict_create_vector (d, name, var, n);
1612 }
1613
1614 /* Returns the vector in D with index IDX, which must be less
1615    than dict_get_n_vectors (D). */
1616 const struct vector *
1617 dict_get_vector (const struct dictionary *d, size_t idx)
1618 {
1619   assert (idx < d->n_vectors);
1620
1621   return d->vector[idx];
1622 }
1623
1624 /* Returns the number of vectors in D. */
1625 size_t
1626 dict_get_n_vectors (const struct dictionary *d)
1627 {
1628   return d->n_vectors;
1629 }
1630
1631 /* Looks up and returns the vector within D with the given
1632    NAME. */
1633 const struct vector *
1634 dict_lookup_vector (const struct dictionary *d, const char *name)
1635 {
1636   size_t i;
1637   for (i = 0; i < d->n_vectors; i++)
1638     if (!utf8_strcasecmp (vector_get_name (d->vector[i]), name))
1639       return d->vector[i];
1640   return NULL;
1641 }
1642
1643 /* Deletes all vectors from D. */
1644 void
1645 dict_clear_vectors (struct dictionary *d)
1646 {
1647   size_t i;
1648
1649   for (i = 0; i < d->n_vectors; i++)
1650     vector_destroy (d->vector[i]);
1651   free (d->vector);
1652
1653   d->vector = NULL;
1654   d->n_vectors = 0;
1655 }
1656 \f
1657 /* Multiple response sets. */
1658
1659 /* Returns the multiple response set in DICT with index IDX, which must be
1660    between 0 and the count returned by dict_get_n_mrsets(), exclusive. */
1661 const struct mrset *
1662 dict_get_mrset (const struct dictionary *dict, size_t idx)
1663 {
1664   assert (idx < dict->n_mrsets);
1665   return dict->mrsets[idx];
1666 }
1667
1668 /* Returns the number of multiple response sets in DICT. */
1669 size_t
1670 dict_get_n_mrsets (const struct dictionary *dict)
1671 {
1672   return dict->n_mrsets;
1673 }
1674
1675 /* Looks for a multiple response set named NAME in DICT.  If it finds one,
1676    returns its index; otherwise, returns SIZE_MAX. */
1677 static size_t
1678 dict_lookup_mrset_idx (const struct dictionary *dict, const char *name)
1679 {
1680   size_t i;
1681
1682   for (i = 0; i < dict->n_mrsets; i++)
1683     if (!utf8_strcasecmp (name, dict->mrsets[i]->name))
1684       return i;
1685
1686   return SIZE_MAX;
1687 }
1688
1689 /* Looks for a multiple response set named NAME in DICT.  If it finds one,
1690    returns it; otherwise, returns NULL. */
1691 const struct mrset *
1692 dict_lookup_mrset (const struct dictionary *dict, const char *name)
1693 {
1694   size_t idx = dict_lookup_mrset_idx (dict, name);
1695   return idx != SIZE_MAX ? dict->mrsets[idx] : NULL;
1696 }
1697
1698 /* Adds MRSET to DICT, replacing any existing set with the same name.  Returns
1699    true if a set was replaced, false if none existed with the specified name.
1700
1701    Ownership of MRSET is transferred to DICT. */
1702 bool
1703 dict_add_mrset (struct dictionary *dict, struct mrset *mrset)
1704 {
1705   size_t idx;
1706
1707   assert (mrset_ok (mrset, dict));
1708
1709   idx = dict_lookup_mrset_idx (dict, mrset->name);
1710   if (idx == SIZE_MAX)
1711     {
1712       dict->mrsets = xrealloc (dict->mrsets,
1713                                (dict->n_mrsets + 1) * sizeof *dict->mrsets);
1714       dict->mrsets[dict->n_mrsets++] = mrset;
1715       return true;
1716     }
1717   else
1718     {
1719       mrset_destroy (dict->mrsets[idx]);
1720       dict->mrsets[idx] = mrset;
1721       return false;
1722     }
1723 }
1724
1725 /* Looks for a multiple response set in DICT named NAME.  If found, removes it
1726    from DICT and returns true.  If none is found, returns false without
1727    modifying DICT.
1728
1729    Deleting one multiple response set causes the indexes of other sets within
1730    DICT to change. */
1731 bool
1732 dict_delete_mrset (struct dictionary *dict, const char *name)
1733 {
1734   size_t idx = dict_lookup_mrset_idx (dict, name);
1735   if (idx != SIZE_MAX)
1736     {
1737       mrset_destroy (dict->mrsets[idx]);
1738       dict->mrsets[idx] = dict->mrsets[--dict->n_mrsets];
1739       return true;
1740     }
1741   else
1742     return false;
1743 }
1744
1745 /* Deletes all multiple response sets from DICT. */
1746 void
1747 dict_clear_mrsets (struct dictionary *dict)
1748 {
1749   size_t i;
1750
1751   for (i = 0; i < dict->n_mrsets; i++)
1752     mrset_destroy (dict->mrsets[i]);
1753   free (dict->mrsets);
1754   dict->mrsets = NULL;
1755   dict->n_mrsets = 0;
1756 }
1757
1758 /* Removes VAR, which must be in DICT, from DICT's multiple response sets. */
1759 static void
1760 dict_unset_mrset_var (struct dictionary *dict, struct variable *var)
1761 {
1762   size_t i;
1763
1764   assert (dict_contains_var (dict, var));
1765
1766   for (i = 0; i < dict->n_mrsets;)
1767     {
1768       struct mrset *mrset = dict->mrsets[i];
1769       size_t j;
1770
1771       for (j = 0; j < mrset->n_vars;)
1772         if (mrset->vars[j] == var)
1773           remove_element (mrset->vars, mrset->n_vars--,
1774                           sizeof *mrset->vars, j);
1775         else
1776           j++;
1777
1778       if (mrset->n_vars < 2)
1779         {
1780           mrset_destroy (mrset);
1781           dict->mrsets[i] = dict->mrsets[--dict->n_mrsets];
1782         }
1783       else
1784         i++;
1785     }
1786 }
1787 \f
1788 /* Returns D's attribute set.  The caller may examine or modify
1789    the attribute set, but must not destroy it.  Destroying D or
1790    calling dict_set_attributes for D will also destroy D's
1791    attribute set. */
1792 struct attrset *
1793 dict_get_attributes (const struct dictionary *d)
1794 {
1795   return CONST_CAST (struct attrset *, &d->attributes);
1796 }
1797
1798 /* Replaces D's attributes set by a copy of ATTRS. */
1799 void
1800 dict_set_attributes (struct dictionary *d, const struct attrset *attrs)
1801 {
1802   attrset_destroy (&d->attributes);
1803   attrset_clone (&d->attributes, attrs);
1804 }
1805
1806 /* Returns true if D has at least one attribute in its attribute
1807    set, false if D's attribute set is empty. */
1808 bool
1809 dict_has_attributes (const struct dictionary *d)
1810 {
1811   return attrset_count (&d->attributes) > 0;
1812 }
1813
1814 /* Called from variable.c to notify the dictionary that some property (indicated
1815    by WHAT) of the variable has changed.  OLDVAR is a copy of V as it existed
1816    prior to the change.  OLDVAR is destroyed by this function.
1817 */
1818 void
1819 dict_var_changed (const struct variable *v, unsigned int what, struct variable *oldvar)
1820 {
1821   if (var_has_vardict (v))
1822     {
1823       const struct vardict_info *vardict = var_get_vardict (v);
1824       struct dictionary *d = vardict->dict;
1825
1826       if (NULL == d)
1827         return;
1828
1829       if (what & (VAR_TRAIT_WIDTH | VAR_TRAIT_POSITION))
1830         invalidate_proto (d);
1831
1832       if (d->changed) d->changed (d, d->changed_data);
1833       if (d->callbacks && d->callbacks->var_changed)
1834         d->callbacks->var_changed (d, var_get_dict_index (v), what, oldvar, d->cb_data);
1835     }
1836   var_unref (oldvar);
1837 }
1838
1839
1840 \f
1841 /* Dictionary used to contain "internal variables". */
1842 static struct dictionary *internal_dict;
1843
1844 /* Create a variable of the specified WIDTH to be used for internal
1845    calculations only.  The variable is assigned case index CASE_IDX. */
1846 struct variable *
1847 dict_create_internal_var (int case_idx, int width)
1848 {
1849   if (internal_dict == NULL)
1850     internal_dict = dict_create ("UTF-8");
1851
1852   for (;;)
1853     {
1854       static int counter = INT_MAX / 2;
1855       struct variable *var;
1856       char name[64];
1857
1858       if (++counter == INT_MAX)
1859         counter = INT_MAX / 2;
1860
1861       sprintf (name, "$internal%d", counter);
1862       var = dict_create_var (internal_dict, name, width);
1863       if (var != NULL)
1864         {
1865           set_var_case_index (var, case_idx);
1866           return var;
1867         }
1868     }
1869 }
1870
1871 /* Destroys VAR, which must have been created with
1872    dict_create_internal_var(). */
1873 void
1874 dict_destroy_internal_var (struct variable *var)
1875 {
1876   if (var != NULL)
1877     {
1878       dict_delete_var (internal_dict, var);
1879
1880       /* Destroy internal_dict if it has no variables left, just so that
1881          valgrind --leak-check --show-reachable won't show internal_dict. */
1882       if (dict_get_n_vars (internal_dict) == 0)
1883         {
1884           dict_unref (internal_dict);
1885           internal_dict = NULL;
1886         }
1887     }
1888 }
1889 \f
1890 int
1891 vardict_get_dict_index (const struct vardict_info *vardict)
1892 {
1893   return vardict - vardict->dict->vars;
1894 }