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