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