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