dictionary: Get rid of "internal var" concept.
[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/varset.h"
36 #include "data/vector.h"
37 #include "libpspp/array.h"
38 #include "libpspp/assertion.h"
39 #include "libpspp/compiler.h"
40 #include "libpspp/hash-functions.h"
41 #include "libpspp/hmap.h"
42 #include "libpspp/i18n.h"
43 #include "libpspp/message.h"
44 #include "libpspp/misc.h"
45 #include "libpspp/pool.h"
46 #include "libpspp/str.h"
47 #include "libpspp/string-array.h"
48 #include "libpspp/ll.h"
49
50 #include "gl/intprops.h"
51 #include "gl/minmax.h"
52 #include "gl/xalloc.h"
53 #include "gl/xmemdup0.h"
54
55 #include "gettext.h"
56 #define _(msgid) gettext (msgid)
57
58 /* A dictionary. */
59 struct dictionary
60   {
61     int ref_cnt;
62     struct vardict_info *vars;  /* Variables. */
63     size_t n_vars;              /* Number of variables. */
64     size_t allocated_vars;      /* Allocated space in 'vars'. */
65     struct caseproto *proto;    /* Prototype for dictionary cases
66                                    (updated lazily). */
67     struct hmap name_map;       /* Variable index by name. */
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     struct varset **varsets;    /* Variable sets. */
82     size_t n_varsets;           /* Number of variable sets. */
83
84     /* Whether variable names must be valid identifiers.  Normally, this is
85        true, but sometimes a dictionary is prepared for external use
86        (e.g. output to a CSV file) where names don't have to be valid. */
87     bool names_must_be_ids;
88
89     char *encoding;             /* Character encoding of string data */
90
91     const struct dict_callbacks *callbacks; /* Callbacks on dictionary
92                                                modification */
93     void *cb_data ;                  /* Data passed to callbacks */
94
95     void (*changed) (struct dictionary *, void *); /* Generic change callback */
96     void *changed_data;
97   };
98
99 static void dict_unset_split_var (struct dictionary *, struct variable *, bool);
100 static void dict_unset_mrset_var (struct dictionary *, struct variable *);
101 static void dict_unset_varset_var (struct dictionary *, struct variable *);
102
103 /* Compares two double pointers to variables, which should point
104    to elements of a struct dictionary's `var' member array. */
105 static int
106 compare_var_ptrs (const void *a_, const void *b_, const void *aux UNUSED)
107 {
108   struct variable *const *a = a_;
109   struct variable *const *b = b_;
110
111   return *a < *b ? -1 : *a > *b;
112 }
113
114 static void
115 unindex_var (struct dictionary *d, struct vardict_info *vardict)
116 {
117   hmap_delete (&d->name_map, &vardict->name_node);
118 }
119
120 /* This function assumes that vardict->name_node.hash is valid, that is, that
121    its name has not changed since it was hashed (rename_var() updates this
122    hash along with the name itself). */
123 static void
124 reindex_var (struct dictionary *d, struct vardict_info *vardict, bool skip_callbacks)
125 {
126   struct variable *old = (d->callbacks && d->callbacks->var_changed
127                           ? var_clone (vardict->var)
128                           : NULL);
129
130   struct variable *var = vardict->var;
131   var_set_vardict (var, vardict);
132   hmap_insert_fast (&d->name_map, &vardict->name_node,
133                     vardict->name_node.hash);
134
135   if (! skip_callbacks)
136     {
137       if (d->changed) d->changed (d, d->changed_data);
138       if (old)
139         {
140           d->callbacks->var_changed (d, var_get_dict_index (var), VAR_TRAIT_POSITION, old, d->cb_data);
141           var_unref (old);
142         }
143     }
144 }
145
146 /* Sets the case_index in V's vardict to CASE_INDEX. */
147 static void
148 set_var_case_index (struct variable *v, int case_index)
149 {
150   var_get_vardict (v)->case_index = case_index;
151 }
152
153 /* Removes the dictionary variables with indexes from FROM to TO (exclusive)
154    from name_map. */
155 static void
156 unindex_vars (struct dictionary *d, size_t from, size_t to)
157 {
158   size_t i;
159
160   for (i = from; i < to; i++)
161     unindex_var (d, &d->vars[i]);
162 }
163
164 /* Re-sets the dict_index in the dictionary variables with
165    indexes from FROM to TO (exclusive). */
166 static void
167 reindex_vars (struct dictionary *d, size_t from, size_t to, bool skip_callbacks)
168 {
169   size_t i;
170
171   for (i = from; i < to; i++)
172     reindex_var (d, &d->vars[i], skip_callbacks);
173 }
174
175 \f
176
177 /* Returns the encoding for data in dictionary D.  The return value is a
178    nonnull string that contains an IANA character set name. */
179 const char *
180 dict_get_encoding (const struct dictionary *d)
181 {
182   return d->encoding ;
183 }
184
185 /* Checks whether UTF-8 string ID is an acceptable identifier in DICT's
186    encoding.  Returns true if it is, otherwise an error message that the caller
187    must free(). */
188 char * WARN_UNUSED_RESULT
189 dict_id_is_valid__ (const struct dictionary *dict, const char *id)
190 {
191   if (!dict->names_must_be_ids)
192     return NULL;
193   return id_is_valid__ (id, dict->encoding);
194 }
195
196 static bool
197 error_to_bool (char *error)
198 {
199   if (error)
200     {
201       free (error);
202       return false;
203     }
204   else
205     return true;
206 }
207
208 /* Returns true if UTF-8 string ID is an acceptable identifier in DICT's
209    encoding, false otherwise. */
210 bool
211 dict_id_is_valid (const struct dictionary *dict, const char *id)
212 {
213   return error_to_bool (dict_id_is_valid__ (dict, id));
214 }
215
216 void
217 dict_set_change_callback (struct dictionary *d,
218                           void (*changed) (struct dictionary *, void*),
219                           void *data)
220 {
221   d->changed = changed;
222   d->changed_data = data;
223 }
224
225 /* Discards dictionary D's caseproto.  (It will be regenerated
226    lazily, on demand.) */
227 static void
228 invalidate_proto (struct dictionary *d)
229 {
230   caseproto_unref (d->proto);
231   d->proto = NULL;
232 }
233
234 /* Print a representation of dictionary D to stdout, for
235    debugging purposes. */
236 void
237 dict_dump (const struct dictionary *d)
238 {
239   int i;
240   for (i = 0 ; i < d->n_vars ; ++i)
241     {
242       const struct variable *v = d->vars[i].var;
243       printf ("Name: %s;\tdict_idx: %zu; case_idx: %zu\n",
244               var_get_name (v),
245               var_get_dict_index (v),
246               var_get_case_index (v));
247
248     }
249 }
250
251 /* Associate CALLBACKS with DICT.  Callbacks will be invoked whenever
252    the dictionary or any of the variables it contains are modified.
253    Each callback will get passed CALLBACK_DATA.
254    Any callback may be NULL, in which case it'll be ignored.
255 */
256 void
257 dict_set_callbacks (struct dictionary *dict,
258                     const struct dict_callbacks *callbacks,
259                     void *callback_data)
260 {
261   dict->callbacks = callbacks;
262   dict->cb_data = callback_data;
263 }
264
265 /* Shallow copy the callbacks from SRC to DEST */
266 void
267 dict_copy_callbacks (struct dictionary *dest,
268                      const struct dictionary *src)
269 {
270   dest->callbacks = src->callbacks;
271   dest->cb_data = src->cb_data;
272 }
273
274 /* Creates and returns a new dictionary with the specified ENCODING. */
275 struct dictionary *
276 dict_create (const char *encoding)
277 {
278   struct dictionary *d = xmalloc (sizeof *d);
279
280   *d = (struct dictionary) {
281     .encoding = xstrdup (encoding),
282     .names_must_be_ids = true,
283     .name_map = HMAP_INITIALIZER (d->name_map),
284     .attributes = ATTRSET_INITIALIZER (d->attributes),
285     .split_type = SPLIT_NONE,
286     .ref_cnt = 1,
287   };
288
289   return d;
290 }
291
292 /* Creates and returns a (deep) copy of an existing
293    dictionary.
294
295    Callbacks are not cloned. */
296 struct dictionary *
297 dict_clone (const struct dictionary *s)
298 {
299   struct dictionary *d = dict_create (s->encoding);
300   dict_set_names_must_be_ids (d, dict_get_names_must_be_ids (s));
301
302   for (size_t i = 0; i < s->n_vars; i++)
303     {
304       struct variable *sv = s->vars[i].var;
305       struct variable *dv = dict_clone_var_assert (d, sv);
306
307       for (size_t j = 0; j < var_get_n_short_names (sv); j++)
308         var_set_short_name (dv, j, var_get_short_name (sv, j));
309
310       var_get_vardict (dv)->case_index = var_get_vardict (sv)->case_index;
311     }
312
313   d->n_splits = s->n_splits;
314   if (d->n_splits > 0)
315     {
316        d->split = xnmalloc (d->n_splits, sizeof *d->split);
317        for (size_t i = 0; i < d->n_splits; i++)
318          d->split[i] = dict_lookup_var_assert (d, var_get_name (s->split[i]));
319     }
320   d->split_type = s->split_type;
321
322   if (s->weight != NULL)
323     dict_set_weight (d, dict_lookup_var_assert (d, var_get_name (s->weight)));
324
325   if (s->filter != NULL)
326     dict_set_filter (d, dict_lookup_var_assert (d, var_get_name (s->filter)));
327
328   d->case_limit = s->case_limit;
329   dict_set_label (d, dict_get_label (s));
330   dict_set_documents (d, dict_get_documents (s));
331
332   d->n_vectors = s->n_vectors;
333   d->vector = xnmalloc (d->n_vectors, sizeof *d->vector);
334   for (size_t i = 0; i < s->n_vectors; i++)
335     d->vector[i] = vector_clone (s->vector[i], s, d);
336
337   dict_set_attributes (d, dict_get_attributes (s));
338
339   for (size_t i = 0; i < s->n_mrsets; i++)
340     {
341       const struct mrset *old = s->mrsets[i];
342       struct mrset *new;
343       size_t j;
344
345       /* Clone old mrset, then replace vars from D by vars from S. */
346       new = mrset_clone (old);
347       for (j = 0; j < new->n_vars; j++)
348         new->vars[j] = dict_lookup_var_assert (d, var_get_name (new->vars[j]));
349
350       dict_add_mrset (d, new);
351     }
352
353   for (size_t i = 0; i < s->n_varsets; i++)
354     {
355       const struct varset *old = s->varsets[i];
356
357       /* Clone old varset, then replace vars from D by vars from S. */
358       struct varset *new = varset_clone (old);
359       for (size_t j = 0; j < new->n_vars; j++)
360         new->vars[j] = dict_lookup_var_assert (d, var_get_name (new->vars[j]));
361
362       dict_add_varset (d, new);
363     }
364
365   return d;
366 }
367 \f
368 /* Returns the SPLIT FILE vars (see cmd_split_file()).  Call
369    dict_get_n_splits() to determine how many SPLIT FILE vars
370    there are.  Returns a null pointer if and only if there are no
371    SPLIT FILE vars. */
372 const struct variable *const *
373 dict_get_split_vars (const struct dictionary *d)
374 {
375   return d->split;
376 }
377
378 /* Returns the number of SPLIT FILE vars. */
379 size_t
380 dict_get_n_splits (const struct dictionary *d)
381 {
382   return d->n_splits;
383 }
384
385 /* Removes variable V, which must be in D, from D's set of split
386    variables. */
387 static void
388 dict_unset_split_var (struct dictionary *d, struct variable *v, bool skip_callbacks)
389 {
390   int orig_count;
391
392   assert (dict_contains_var (d, v));
393
394   orig_count = d->n_splits;
395   d->n_splits = remove_equal (d->split, d->n_splits, sizeof *d->split,
396                                &v, compare_var_ptrs, NULL);
397   if (orig_count != d->n_splits && !skip_callbacks)
398     {
399       if (d->changed) d->changed (d, d->changed_data);
400       /* We changed the set of split variables so invoke the
401          callback. */
402       if (d->callbacks &&  d->callbacks->split_changed)
403         d->callbacks->split_changed (d, d->cb_data);
404     }
405 }
406
407
408 /* Sets N split vars SPLIT in dictionary D.  N is silently capped to a maximum
409    of MAX_SPLITS. */
410 static void
411 dict_set_split_vars__ (struct dictionary *d,
412                        struct variable *const *split, size_t n,
413                        enum split_type type, bool skip_callbacks)
414 {
415   if (n > MAX_SPLITS)
416     n = MAX_SPLITS;
417   assert (n == 0 || split != NULL);
418
419   d->n_splits = n;
420   d->split_type = (n == 0 ? SPLIT_NONE
421                    : type == SPLIT_NONE ? SPLIT_LAYERED
422                    : type);
423   if (n > 0)
424     {
425       d->split = xnrealloc (d->split, n, sizeof *d->split) ;
426       memcpy (d->split, split, n * sizeof *d->split);
427     }
428   else
429     {
430       free (d->split);
431       d->split = NULL;
432     }
433
434   if (!skip_callbacks)
435     {
436       if (d->changed) d->changed (d, d->changed_data);
437       if (d->callbacks &&  d->callbacks->split_changed)
438         d->callbacks->split_changed (d, d->cb_data);
439     }
440 }
441
442 enum split_type
443 dict_get_split_type (const struct dictionary *d)
444 {
445   return d->split_type;
446 }
447
448 /* Sets N split vars SPLIT in dictionary D. */
449 void
450 dict_set_split_vars (struct dictionary *d,
451                      struct variable *const *split, size_t n,
452                      enum split_type type)
453 {
454   dict_set_split_vars__ (d, split, n, type, false);
455 }
456
457 void
458 dict_clear_split_vars (struct dictionary *d)
459 {
460   dict_set_split_vars (d, NULL, 0, SPLIT_NONE);
461 }
462 \f
463
464 /* Deletes variable V from dictionary D and frees V.
465
466    This is a very bad idea if there might be any pointers to V
467    from outside D.  In general, no variable in the active dataset's
468    dictionary should be deleted when any transformations are
469    active on the dictionary's dataset, because those
470    transformations might reference the deleted variable.  The
471    safest time to delete a variable is just after a procedure has
472    been executed, as done by DELETE VARIABLES.
473
474    Pointers to V within D are not a problem, because
475    dict_delete_var() knows to remove V from split variables,
476    weights, filters, etc. */
477 static void
478 dict_delete_var__ (struct dictionary *d, struct variable *v, bool skip_callbacks)
479 {
480   int dict_index = var_get_dict_index (v);
481   const int case_index = var_get_case_index (v);
482
483   assert (dict_contains_var (d, v));
484
485   dict_unset_split_var (d, v, skip_callbacks);
486   dict_unset_mrset_var (d, v);
487   dict_unset_varset_var (d, v);
488
489   if (d->weight == v)
490     dict_set_weight (d, NULL);
491
492   if (d->filter == v)
493     dict_set_filter (d, NULL);
494
495   dict_clear_vectors (d);
496
497   /* Remove V from var array. */
498   unindex_vars (d, dict_index, d->n_vars);
499   remove_element (d->vars, d->n_vars, sizeof *d->vars, dict_index);
500   d->n_vars--;
501
502   /* Update dict_index for each affected variable. */
503   reindex_vars (d, dict_index, d->n_vars, skip_callbacks);
504
505   /* Free memory. */
506   var_clear_vardict (v);
507
508   if (! skip_callbacks)
509     {
510       if (d->changed) d->changed (d, d->changed_data);
511       if (d->callbacks &&  d->callbacks->var_deleted)
512         d->callbacks->var_deleted (d, v, dict_index, case_index, d->cb_data);
513     }
514
515   invalidate_proto (d);
516   var_unref (v);
517 }
518
519 /* Deletes variable V from dictionary D and frees V.
520
521    This is a very bad idea if there might be any pointers to V
522    from outside D.  In general, no variable in the active dataset's
523    dictionary should be deleted when any transformations are
524    active on the dictionary's dataset, because those
525    transformations might reference the deleted variable.  The
526    safest time to delete a variable is just after a procedure has
527    been executed, as done by DELETE VARIABLES.
528
529    Pointers to V within D are not a problem, because
530    dict_delete_var() knows to remove V from split variables,
531    weights, filters, etc. */
532 void
533 dict_delete_var (struct dictionary *d, struct variable *v)
534 {
535   dict_delete_var__ (d, v, false);
536 }
537
538
539 /* Deletes the COUNT variables listed in VARS from D.  This is
540    unsafe; see the comment on dict_delete_var() for details. */
541 void
542 dict_delete_vars (struct dictionary *d,
543                   struct variable *const *vars, size_t count)
544 {
545   /* FIXME: this can be done in O(count) time, but this algorithm
546      is O(count**2). */
547   assert (count == 0 || vars != NULL);
548
549   while (count-- > 0)
550     dict_delete_var (d, *vars++);
551 }
552
553 /* Deletes the COUNT variables in D starting at index IDX.  This
554    is unsafe; see the comment on dict_delete_var() for
555    details. Deleting consecutive vars will result in less callbacks
556    compared to iterating over dict_delete_var.
557    A simple while loop over dict_delete_var will
558    produce (d->n_vars - IDX) * COUNT variable changed callbacks
559    plus COUNT variable delete callbacks.
560    This here produces d->n_vars - IDX variable changed callbacks
561    plus COUNT variable delete callbacks. */
562 void
563 dict_delete_consecutive_vars (struct dictionary *d, size_t idx, size_t count)
564 {
565   assert (idx + count <= d->n_vars);
566
567   /* We need to store the variable and the corresponding case_index
568      for the delete callbacks later. We store them in a linked list.*/
569   struct delvar {
570     struct ll ll;
571     struct variable *var;
572     int case_index;
573   };
574   struct ll_list list = LL_INITIALIZER (list);
575
576   for (size_t i = idx; i < idx + count; i++)
577     {
578       struct delvar *dv = xmalloc (sizeof (struct delvar));
579       assert (dv);
580       struct variable *v = d->vars[i].var;
581
582       dict_unset_split_var (d, v, false);
583       dict_unset_mrset_var (d, v);
584       dict_unset_varset_var (d, v);
585
586       if (d->weight == v)
587         dict_set_weight (d, NULL);
588
589       if (d->filter == v)
590         dict_set_filter (d, NULL);
591
592       dv->var = v;
593       dv->case_index = var_get_case_index (v);
594       ll_push_tail (&list, (struct ll *)dv);
595     }
596
597   dict_clear_vectors (d);
598
599   /* Remove variables from var array. */
600   unindex_vars (d, idx, d->n_vars);
601   remove_range (d->vars, d->n_vars, sizeof *d->vars, idx, count);
602   d->n_vars -= count;
603
604   /* Reindexing will result variable-changed callback */
605   reindex_vars (d, idx, d->n_vars, false);
606
607   invalidate_proto (d);
608   if (d->changed) d->changed (d, d->changed_data);
609
610   /* Now issue the variable delete callbacks and delete
611      the variables. The vardict is not valid at this point
612      anymore. That is the reason why we stored the
613      caseindex before reindexing. */
614   for (size_t vi = idx; vi < idx + count; vi++)
615     {
616       struct delvar *dv = (struct delvar *) ll_pop_head (&list);
617       var_clear_vardict (dv->var);
618       if (d->callbacks &&  d->callbacks->var_deleted)
619         d->callbacks->var_deleted (d, dv->var, vi, dv->case_index, d->cb_data);
620       var_unref (dv->var);
621       free (dv);
622     }
623 }
624
625 /* Deletes scratch variables from dictionary D. */
626 void
627 dict_delete_scratch_vars (struct dictionary *d)
628 {
629   int i;
630
631   /* FIXME: this can be done in O(count) time, but this algorithm
632      is O(count**2). */
633   for (i = 0; i < d->n_vars;)
634     if (var_get_dict_class (d->vars[i].var) == DC_SCRATCH)
635       dict_delete_var (d, d->vars[i].var);
636     else
637       i++;
638 }
639
640 \f
641
642 /* Clears the contents from a dictionary without destroying the
643    dictionary itself. */
644 static void
645 dict_clear__ (struct dictionary *d, bool skip_callbacks)
646 {
647   /* FIXME?  Should we really clear case_limit, label, documents?
648      Others are necessarily cleared by deleting all the variables.*/
649   while (d->n_vars > 0)
650     {
651       dict_delete_var__ (d, d->vars[d->n_vars - 1].var, skip_callbacks);
652     }
653
654   free (d->vars);
655   d->vars = NULL;
656   d->n_vars = d->allocated_vars = 0;
657   invalidate_proto (d);
658   hmap_clear (&d->name_map);
659   dict_set_split_vars__ (d, NULL, 0, SPLIT_NONE, skip_callbacks);
660
661   if (skip_callbacks)
662     {
663       d->weight = NULL;
664       d->filter = NULL;
665     }
666   else
667     {
668       dict_set_weight (d, NULL);
669       dict_set_filter (d, NULL);
670     }
671   d->case_limit = 0;
672   free (d->label);
673   d->label = NULL;
674   string_array_clear (&d->documents);
675   dict_clear_vectors (d);
676   attrset_clear (&d->attributes);
677 }
678
679 /* Clears the contents from a dictionary without destroying the
680    dictionary itself. */
681 void
682 dict_clear (struct dictionary *d)
683 {
684   dict_clear__ (d, false);
685 }
686
687 /* Clears a dictionary and destroys it. */
688 static void
689 _dict_destroy (struct dictionary *d)
690 {
691   /* In general, we don't want callbacks occurring, if the dictionary
692      is being destroyed */
693   d->callbacks  = NULL ;
694
695   dict_clear__ (d, true);
696   string_array_destroy (&d->documents);
697   hmap_destroy (&d->name_map);
698   attrset_destroy (&d->attributes);
699   dict_clear_mrsets (d);
700   dict_clear_varsets (d);
701   free (d->encoding);
702   free (d);
703 }
704
705 struct dictionary *
706 dict_ref (struct dictionary *d)
707 {
708   d->ref_cnt++;
709   return d;
710 }
711
712 void
713 dict_unref (struct dictionary *d)
714 {
715   if (d == NULL)
716     return;
717   d->ref_cnt--;
718   assert (d->ref_cnt >= 0);
719   if (d->ref_cnt == 0)
720     _dict_destroy (d);
721 }
722
723 /* Returns the number of variables in D. */
724 size_t
725 dict_get_n_vars (const struct dictionary *d)
726 {
727   return d->n_vars;
728 }
729
730 /* Returns the variable in D with dictionary index IDX, which
731    must be between 0 and the count returned by
732    dict_get_n_vars(), exclusive. */
733 struct variable *
734 dict_get_var (const struct dictionary *d, size_t idx)
735 {
736   assert (idx < d->n_vars);
737
738   return d->vars[idx].var;
739 }
740
741 /* Sets *VARS to an array of pointers to variables in D and *N
742    to the number of variables in *D.  All variables are returned
743    except for those, if any, in the classes indicated by EXCLUDE.
744    (There is no point in putting DC_SYSTEM in EXCLUDE as
745    dictionaries never include system variables.) */
746 void
747 dict_get_vars (const struct dictionary *d, const struct variable ***vars,
748                size_t *n, enum dict_class exclude)
749 {
750   dict_get_vars_mutable (d, (struct variable ***) vars, n, exclude);
751 }
752
753 /* Sets *VARS to an array of pointers to variables in D and *N
754    to the number of variables in *D.  All variables are returned
755    except for those, if any, in the classes indicated by EXCLUDE.
756    (There is no point in putting DC_SYSTEM in EXCLUDE as
757    dictionaries never include system variables.) */
758 void
759 dict_get_vars_mutable (const struct dictionary *d, struct variable ***vars,
760                        size_t *n, enum dict_class exclude)
761 {
762   size_t count;
763   size_t i;
764
765   assert (exclude == (exclude & DC_ALL));
766
767   count = 0;
768   for (i = 0; i < d->n_vars; i++)
769     {
770       enum dict_class class = var_get_dict_class (d->vars[i].var);
771       if (!(class & exclude))
772         count++;
773     }
774
775   *vars = xnmalloc (count, sizeof **vars);
776   *n = 0;
777   for (i = 0; i < d->n_vars; i++)
778     {
779       enum dict_class class = var_get_dict_class (d->vars[i].var);
780       if (!(class & exclude))
781         (*vars)[(*n)++] = d->vars[i].var;
782     }
783   assert (*n == count);
784 }
785
786 static struct variable *
787 add_var_with_case_index (struct dictionary *d, struct variable *v,
788                          int case_index)
789 {
790   struct vardict_info *vardict;
791
792   /* Update dictionary. */
793   if (d->n_vars >= d->allocated_vars)
794     {
795       size_t i;
796
797       d->vars = x2nrealloc (d->vars, &d->allocated_vars, sizeof *d->vars);
798       hmap_clear (&d->name_map);
799       for (i = 0; i < d->n_vars; i++)
800         {
801           var_set_vardict (d->vars[i].var, &d->vars[i]);
802           hmap_insert_fast (&d->name_map, &d->vars[i].name_node,
803                             d->vars[i].name_node.hash);
804         }
805     }
806
807   vardict = &d->vars[d->n_vars++];
808   vardict->dict = d;
809   vardict->var = v;
810   hmap_insert (&d->name_map, &vardict->name_node,
811                utf8_hash_case_string (var_get_name (v), 0));
812   vardict->case_index = case_index;
813   var_set_vardict (v, vardict);
814
815   if (d->changed) d->changed (d, d->changed_data);
816   if (d->callbacks &&  d->callbacks->var_added)
817     d->callbacks->var_added (d, var_get_dict_index (v), d->cb_data);
818
819   invalidate_proto (d);
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, dict_get_n_vars (d));
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       short int *widths = xnmalloc (d->n_vars, sizeof *widths);
1392       for (size_t i = 0; i < d->n_vars; i++)
1393         widths[i] = -1;
1394       for (size_t i = 0; i < d->n_vars; i++)
1395         {
1396           const struct variable *var = d->vars[i].var;
1397           size_t case_idx = var_get_case_index (var);
1398           assert (case_idx < d->n_vars);
1399           assert (widths[case_idx] == -1);
1400           widths[case_idx] = var_get_width (var);
1401         }
1402
1403       d->proto = caseproto_from_widths (widths, d->n_vars);
1404     }
1405   return d->proto;
1406 }
1407
1408 /* Reassigns values in dictionary D so that fragmentation is
1409    eliminated. */
1410 void
1411 dict_compact_values (struct dictionary *d)
1412 {
1413   for (size_t i = 0; i < d->n_vars; i++)
1414     {
1415       struct variable *v = d->vars[i].var;
1416       set_var_case_index (v, i);
1417     }
1418   invalidate_proto (d);
1419 }
1420
1421 /* Returns the number of values occupied by the variables in
1422    dictionary D.  All variables are considered if EXCLUDE_CLASSES
1423    is 0, or it may contain one or more of DC_ORDINARY, DC_SYSTEM,
1424    or DC_SCRATCH to exclude the corresponding type of variable. */
1425 size_t
1426 dict_count_values (const struct dictionary *d, unsigned int exclude_classes)
1427 {
1428   assert (!(exclude_classes & ~DC_ALL));
1429
1430   size_t n = 0;
1431   for (size_t i = 0; i < d->n_vars; i++)
1432     {
1433       enum dict_class class = var_get_dict_class (d->vars[i].var);
1434       if (!(exclude_classes & class))
1435         n++;
1436     }
1437   return n;
1438 }
1439
1440 /* Returns the case prototype that would result after deleting
1441    all variables from D that are not in one of the
1442    EXCLUDE_CLASSES and compacting the dictionary with
1443    dict_compact().
1444
1445    The caller must unref the returned caseproto when it is no
1446    longer needed. */
1447 struct caseproto *
1448 dict_get_compacted_proto (const struct dictionary *d,
1449                           unsigned int exclude_classes)
1450 {
1451   struct caseproto *proto;
1452   size_t i;
1453
1454   assert (!(exclude_classes & ~DC_ALL));
1455
1456   proto = caseproto_create ();
1457   for (i = 0; i < d->n_vars; i++)
1458     {
1459       struct variable *v = d->vars[i].var;
1460       if (!(exclude_classes & var_get_dict_class (v)))
1461         proto = caseproto_add_width (proto, var_get_width (v));
1462     }
1463   return proto;
1464 }
1465 /* Returns the file label for D, or a null pointer if D is
1466    unlabeled (see cmd_file_label()). */
1467 const char *
1468 dict_get_label (const struct dictionary *d)
1469 {
1470   return d->label;
1471 }
1472
1473 /* Sets D's file label to LABEL, truncating it to at most 60 bytes in D's
1474    encoding.
1475
1476    Removes D's label if LABEL is null or the empty string. */
1477 void
1478 dict_set_label (struct dictionary *d, const char *label)
1479 {
1480   free (d->label);
1481   if (label == NULL || label[0] == '\0')
1482     d->label = NULL;
1483   else
1484     d->label = utf8_encoding_trunc (label, d->encoding, 60);
1485 }
1486
1487 /* Returns the documents for D, as an UTF-8 encoded string_array.  The
1488    return value is always nonnull; if there are no documents then the
1489    string_arary is empty.*/
1490 const struct string_array *
1491 dict_get_documents (const struct dictionary *d)
1492 {
1493   return &d->documents;
1494 }
1495
1496 /* Replaces the documents for D by NEW_DOCS, a UTF-8 encoded string_array. */
1497 void
1498 dict_set_documents (struct dictionary *d, const struct string_array *new_docs)
1499 {
1500   /* Swap out the old documents, instead of destroying them immediately, to
1501      allow the new documents to include pointers into the old ones. */
1502   struct string_array old_docs = STRING_ARRAY_INITIALIZER;
1503   string_array_swap (&d->documents, &old_docs);
1504
1505   for (size_t i = 0; i < new_docs->n; i++)
1506     dict_add_document_line (d, new_docs->strings[i], false);
1507
1508   string_array_destroy (&old_docs);
1509 }
1510
1511 /* Replaces the documents for D by UTF-8 encoded string NEW_DOCS, dividing it
1512    into individual lines at new-line characters.  Each line is truncated to at
1513    most DOC_LINE_LENGTH bytes in D's encoding. */
1514 void
1515 dict_set_documents_string (struct dictionary *d, const char *new_docs)
1516 {
1517   const char *s;
1518
1519   dict_clear_documents (d);
1520   for (s = new_docs; *s != '\0';)
1521     {
1522       size_t len = strcspn (s, "\n");
1523       char *line = xmemdup0 (s, len);
1524       dict_add_document_line (d, line, false);
1525       free (line);
1526
1527       s += len;
1528       if (*s == '\n')
1529         s++;
1530     }
1531 }
1532
1533 /* Drops the documents from dictionary D. */
1534 void
1535 dict_clear_documents (struct dictionary *d)
1536 {
1537   string_array_clear (&d->documents);
1538 }
1539
1540 /* Appends the UTF-8 encoded LINE to the documents in D.  LINE will be
1541    truncated so that it is no more than 80 bytes in the dictionary's
1542    encoding.  If this causes some text to be lost, and ISSUE_WARNING is true,
1543    then a warning will be issued. */
1544 bool
1545 dict_add_document_line (struct dictionary *d, const char *line,
1546                         bool issue_warning)
1547 {
1548   size_t trunc_len;
1549   bool truncated;
1550
1551   trunc_len = utf8_encoding_trunc_len (line, d->encoding, DOC_LINE_LENGTH);
1552   truncated = line[trunc_len] != '\0';
1553   if (truncated && issue_warning)
1554     {
1555       /* TRANSLATORS: "bytes" is correct, not characters due to UTF encoding */
1556       msg (SW, _("Truncating document line to %d bytes."), DOC_LINE_LENGTH);
1557     }
1558
1559   string_array_append_nocopy (&d->documents, xmemdup0 (line, trunc_len));
1560
1561   return !truncated;
1562 }
1563
1564 /* Returns the number of document lines in dictionary D. */
1565 size_t
1566 dict_get_document_n_lines (const struct dictionary *d)
1567 {
1568   return d->documents.n;
1569 }
1570
1571 /* Returns document line number IDX in dictionary D.  The caller must not
1572    modify or free the returned string. */
1573 const char *
1574 dict_get_document_line (const struct dictionary *d, size_t idx)
1575 {
1576   assert (idx < d->documents.n);
1577   return d->documents.strings[idx];
1578 }
1579
1580 /* Creates in D a vector named NAME that contains the N
1581    variables in VAR.  Returns true if successful, or false if a
1582    vector named NAME already exists in D. */
1583 bool
1584 dict_create_vector (struct dictionary *d,
1585                     const char *name,
1586                     struct variable **var, size_t n)
1587 {
1588   assert (n > 0);
1589   for (size_t i = 0; i < n; i++)
1590     assert (dict_contains_var (d, var[i]));
1591
1592   if (dict_lookup_vector (d, name) == NULL)
1593     {
1594       d->vector = xnrealloc (d->vector, d->n_vectors + 1, sizeof *d->vector);
1595       d->vector[d->n_vectors++] = vector_create (name, var, n);
1596       return true;
1597     }
1598   else
1599     return false;
1600 }
1601
1602 /* Creates in D a vector named NAME that contains the N
1603    variables in VAR.  A vector named NAME must not already exist
1604    in D. */
1605 void
1606 dict_create_vector_assert (struct dictionary *d,
1607                            const char *name,
1608                            struct variable **var, size_t n)
1609 {
1610   assert (dict_lookup_vector (d, name) == NULL);
1611   dict_create_vector (d, name, var, n);
1612 }
1613
1614 /* Returns the vector in D with index IDX, which must be less
1615    than dict_get_n_vectors (D). */
1616 const struct vector *
1617 dict_get_vector (const struct dictionary *d, size_t idx)
1618 {
1619   assert (idx < d->n_vectors);
1620
1621   return d->vector[idx];
1622 }
1623
1624 /* Returns the number of vectors in D. */
1625 size_t
1626 dict_get_n_vectors (const struct dictionary *d)
1627 {
1628   return d->n_vectors;
1629 }
1630
1631 /* Looks up and returns the vector within D with the given
1632    NAME. */
1633 const struct vector *
1634 dict_lookup_vector (const struct dictionary *d, const char *name)
1635 {
1636   size_t i;
1637   for (i = 0; i < d->n_vectors; i++)
1638     if (!utf8_strcasecmp (vector_get_name (d->vector[i]), name))
1639       return d->vector[i];
1640   return NULL;
1641 }
1642
1643 /* Deletes all vectors from D. */
1644 void
1645 dict_clear_vectors (struct dictionary *d)
1646 {
1647   size_t i;
1648
1649   for (i = 0; i < d->n_vectors; i++)
1650     vector_destroy (d->vector[i]);
1651   free (d->vector);
1652
1653   d->vector = NULL;
1654   d->n_vectors = 0;
1655 }
1656 \f
1657 /* Multiple response sets. */
1658
1659 /* Returns the multiple response set in DICT with index IDX, which must be
1660    between 0 and the count returned by dict_get_n_mrsets(), exclusive. */
1661 const struct mrset *
1662 dict_get_mrset (const struct dictionary *dict, size_t idx)
1663 {
1664   assert (idx < dict->n_mrsets);
1665   return dict->mrsets[idx];
1666 }
1667
1668 /* Returns the number of multiple response sets in DICT. */
1669 size_t
1670 dict_get_n_mrsets (const struct dictionary *dict)
1671 {
1672   return dict->n_mrsets;
1673 }
1674
1675 /* Looks for a multiple response set named NAME in DICT.  If it finds one,
1676    returns its index; otherwise, returns SIZE_MAX. */
1677 static size_t
1678 dict_lookup_mrset_idx (const struct dictionary *dict, const char *name)
1679 {
1680   size_t i;
1681
1682   for (i = 0; i < dict->n_mrsets; i++)
1683     if (!utf8_strcasecmp (name, dict->mrsets[i]->name))
1684       return i;
1685
1686   return SIZE_MAX;
1687 }
1688
1689 /* Looks for a multiple response set named NAME in DICT.  If it finds one,
1690    returns it; otherwise, returns NULL. */
1691 const struct mrset *
1692 dict_lookup_mrset (const struct dictionary *dict, const char *name)
1693 {
1694   size_t idx = dict_lookup_mrset_idx (dict, name);
1695   return idx != SIZE_MAX ? dict->mrsets[idx] : NULL;
1696 }
1697
1698 /* Adds MRSET to DICT, replacing any existing set with the same name.  Returns
1699    true if a set was replaced, false if none existed with the specified name.
1700
1701    Ownership of MRSET is transferred to DICT. */
1702 bool
1703 dict_add_mrset (struct dictionary *dict, struct mrset *mrset)
1704 {
1705   size_t idx;
1706
1707   assert (mrset_ok (mrset, dict));
1708
1709   idx = dict_lookup_mrset_idx (dict, mrset->name);
1710   if (idx == SIZE_MAX)
1711     {
1712       dict->mrsets = xrealloc (dict->mrsets,
1713                                (dict->n_mrsets + 1) * sizeof *dict->mrsets);
1714       dict->mrsets[dict->n_mrsets++] = mrset;
1715       return true;
1716     }
1717   else
1718     {
1719       mrset_destroy (dict->mrsets[idx]);
1720       dict->mrsets[idx] = mrset;
1721       return false;
1722     }
1723 }
1724
1725 /* Looks for a multiple response set in DICT named NAME.  If found, removes it
1726    from DICT and returns true.  If none is found, returns false without
1727    modifying DICT.
1728
1729    Deleting one multiple response set causes the indexes of other sets within
1730    DICT to change. */
1731 bool
1732 dict_delete_mrset (struct dictionary *dict, const char *name)
1733 {
1734   size_t idx = dict_lookup_mrset_idx (dict, name);
1735   if (idx != SIZE_MAX)
1736     {
1737       mrset_destroy (dict->mrsets[idx]);
1738       dict->mrsets[idx] = dict->mrsets[--dict->n_mrsets];
1739       return true;
1740     }
1741   else
1742     return false;
1743 }
1744
1745 /* Deletes all multiple response sets from DICT. */
1746 void
1747 dict_clear_mrsets (struct dictionary *dict)
1748 {
1749   size_t i;
1750
1751   for (i = 0; i < dict->n_mrsets; i++)
1752     mrset_destroy (dict->mrsets[i]);
1753   free (dict->mrsets);
1754   dict->mrsets = NULL;
1755   dict->n_mrsets = 0;
1756 }
1757
1758 /* Removes VAR, which must be in DICT, from DICT's multiple response sets. */
1759 static void
1760 dict_unset_mrset_var (struct dictionary *dict, struct variable *var)
1761 {
1762   size_t i;
1763
1764   assert (dict_contains_var (dict, var));
1765
1766   for (i = 0; i < dict->n_mrsets;)
1767     {
1768       struct mrset *mrset = dict->mrsets[i];
1769       size_t j;
1770
1771       for (j = 0; j < mrset->n_vars;)
1772         if (mrset->vars[j] == var)
1773           remove_element (mrset->vars, mrset->n_vars--,
1774                           sizeof *mrset->vars, j);
1775         else
1776           j++;
1777
1778       if (mrset->n_vars < 2)
1779         {
1780           mrset_destroy (mrset);
1781           dict->mrsets[i] = dict->mrsets[--dict->n_mrsets];
1782         }
1783       else
1784         i++;
1785     }
1786 }
1787 \f
1788
1789 /* Returns the variable set in DICT with index IDX, which must be between 0 and
1790    the count returned by dict_get_n_varsets(), exclusive. */
1791 const struct varset *
1792 dict_get_varset (const struct dictionary *dict, size_t idx)
1793 {
1794   assert (idx < dict->n_varsets);
1795   return dict->varsets[idx];
1796 }
1797
1798 /* Returns the number of variable sets in DICT. */
1799 size_t
1800 dict_get_n_varsets (const struct dictionary *dict)
1801 {
1802   return dict->n_varsets;
1803 }
1804
1805 /* Looks for a variable set named NAME in DICT.  If it finds one, returns its
1806    index; otherwise, returns SIZE_MAX. */
1807 static size_t
1808 dict_lookup_varset_idx (const struct dictionary *dict, const char *name)
1809 {
1810   for (size_t i = 0; i < dict->n_varsets; i++)
1811     if (!utf8_strcasecmp (name, dict->varsets[i]->name))
1812       return i;
1813
1814   return SIZE_MAX;
1815 }
1816
1817 /* Looks for a multiple response set named NAME in DICT.  If it finds one,
1818    returns it; otherwise, returns NULL. */
1819 const struct varset *
1820 dict_lookup_varset (const struct dictionary *dict, const char *name)
1821 {
1822   size_t idx = dict_lookup_varset_idx (dict, name);
1823   return idx != SIZE_MAX ? dict->varsets[idx] : NULL;
1824 }
1825
1826 /* Adds VARSET to DICT, replacing any existing set with the same name.  Returns
1827    true if a set was replaced, false if none existed with the specified name.
1828
1829    Ownership of VARSET is transferred to DICT. */
1830 bool
1831 dict_add_varset (struct dictionary *dict, struct varset *varset)
1832 {
1833   size_t idx = dict_lookup_varset_idx (dict, varset->name);
1834   if (idx == SIZE_MAX)
1835     {
1836       dict->varsets = xrealloc (dict->varsets,
1837                                (dict->n_varsets + 1) * sizeof *dict->varsets);
1838       dict->varsets[dict->n_varsets++] = varset;
1839       return true;
1840     }
1841   else
1842     {
1843       varset_destroy (dict->varsets[idx]);
1844       dict->varsets[idx] = varset;
1845       return false;
1846     }
1847 }
1848
1849 /* Deletes all variable sets from DICT. */
1850 void
1851 dict_clear_varsets (struct dictionary *dict)
1852 {
1853   for (size_t i = 0; i < dict->n_varsets; i++)
1854     varset_destroy (dict->varsets[i]);
1855   free (dict->varsets);
1856   dict->varsets = NULL;
1857   dict->n_varsets = 0;
1858 }
1859
1860 /* Removes VAR, which must be in DICT, from DICT's multiple response sets. */
1861 static void
1862 dict_unset_varset_var (struct dictionary *dict, struct variable *var)
1863 {
1864   assert (dict_contains_var (dict, var));
1865
1866   for (size_t i = 0; i < dict->n_varsets; i++)
1867     {
1868       struct varset *varset = dict->varsets[i];
1869
1870       for (size_t j = 0; j < varset->n_vars;)
1871         if (varset->vars[j] == var)
1872           remove_element (varset->vars, varset->n_vars--,
1873                           sizeof *varset->vars, j);
1874         else
1875           j++;
1876     }
1877 }
1878 \f
1879 /* Returns D's attribute set.  The caller may examine or modify
1880    the attribute set, but must not destroy it.  Destroying D or
1881    calling dict_set_attributes for D will also destroy D's
1882    attribute set. */
1883 struct attrset *
1884 dict_get_attributes (const struct dictionary *d)
1885 {
1886   return CONST_CAST (struct attrset *, &d->attributes);
1887 }
1888
1889 /* Replaces D's attributes set by a copy of ATTRS. */
1890 void
1891 dict_set_attributes (struct dictionary *d, const struct attrset *attrs)
1892 {
1893   attrset_destroy (&d->attributes);
1894   attrset_clone (&d->attributes, attrs);
1895 }
1896
1897 /* Returns true if D has at least one attribute in its attribute
1898    set, false if D's attribute set is empty. */
1899 bool
1900 dict_has_attributes (const struct dictionary *d)
1901 {
1902   return attrset_count (&d->attributes) > 0;
1903 }
1904
1905 /* Called from variable.c to notify the dictionary that some property (indicated
1906    by WHAT) of the variable has changed.  OLDVAR is a copy of V as it existed
1907    prior to the change.  OLDVAR is destroyed by this function.
1908 */
1909 void
1910 dict_var_changed (const struct variable *v, unsigned int what, struct variable *oldvar)
1911 {
1912   if (var_has_vardict (v))
1913     {
1914       const struct vardict_info *vardict = var_get_vardict (v);
1915       struct dictionary *d = vardict->dict;
1916
1917       if (NULL == d)
1918         return;
1919
1920       if (what & (VAR_TRAIT_WIDTH | VAR_TRAIT_POSITION))
1921         invalidate_proto (d);
1922
1923       if (d->changed) d->changed (d, d->changed_data);
1924       if (d->callbacks && d->callbacks->var_changed)
1925         d->callbacks->var_changed (d, var_get_dict_index (v), what, oldvar, d->cb_data);
1926     }
1927   var_unref (oldvar);
1928 }
1929
1930
1931 \f
1932 int
1933 vardict_get_dict_index (const struct vardict_info *vardict)
1934 {
1935   return vardict - vardict->dict->vars;
1936 }