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