+ if (root[0] != '\0')
+ {
+ unsigned long int i;
+
+ if (var_name_is_insertable (dict, root))
+ return root;
+
+ for (i = 0; i < ULONG_MAX; i++)
+ {
+ char suffix[INT_BUFSIZE_BOUND (i) + 1];
+ char *name;
+
+ suffix[0] = '_';
+ if (!str_format_26adic (i + 1, true, &suffix[1], sizeof suffix - 1))
+ NOT_REACHED ();
+
+ name = utf8_encoding_concat (root, suffix, dict->encoding, 64);
+ if (var_name_is_insertable (dict, name))
+ {
+ free (root);
+ return name;
+ }
+ free (name);
+ }
+ }
+
+ free (root);
+
+ return NULL;
+}
+
+static char *
+make_numeric_name (const struct dictionary *dict, unsigned long int *num_start)
+{
+ unsigned long int number;
+
+ for (number = num_start != NULL ? MAX (*num_start, 1) : 1;
+ number < ULONG_MAX;
+ number++)
+ {
+ char name[3 + INT_STRLEN_BOUND (number) + 1];
+
+ sprintf (name, "VAR%03lu", number);
+ if (dict_lookup_var (dict, name) == NULL)
+ {
+ if (num_start != NULL)
+ *num_start = number + 1;
+ return xstrdup (name);
+ }
+ }
+
+ NOT_REACHED ();
+}
+
+
+/* Devises and returns a variable name unique within DICT. The variable name
+ is owned by the caller, which must free it with free() when it is no longer
+ needed.
+
+ HINT, if it is non-null, is used as a suggestion that will be
+ modified for suitability as a variable name and for
+ uniqueness.
+
+ If HINT is null or entirely unsuitable, a name in the form
+ "VAR%03d" will be generated, where the smallest unused integer
+ value is used. If NUM_START is non-null, then its value is
+ used as the minimum numeric value to check, and it is updated
+ to the next value to be checked.
+*/
+char *
+dict_make_unique_var_name (const struct dictionary *dict, const char *hint,
+ unsigned long int *num_start)
+{
+ if (hint != NULL)
+ {
+ char *hinted_name = make_hinted_name (dict, hint);
+ if (hinted_name != NULL)
+ return hinted_name;
+ }
+ return make_numeric_name (dict, num_start);
+}
+
+/* Returns whether variable names must be valid identifiers. Normally, this is
+ true, but sometimes a dictionary is prepared for external use (e.g. output
+ to a CSV file) where names don't have to be valid. */
+bool
+dict_get_names_must_be_ids (const struct dictionary *d)
+{
+ return d->names_must_be_ids;
+}
+
+/* Sets whether variable names must be valid identifiers. Normally, this is
+ true, but sometimes a dictionary is prepared for external use (e.g. output
+ to a CSV file) where names don't have to be valid.
+
+ Changing this setting from false to true doesn't make the dictionary check
+ all the existing variable names, so it can cause an invariant violation. */
+void
+dict_set_names_must_be_ids (struct dictionary *d, bool names_must_be_ids)
+{
+ d->names_must_be_ids = names_must_be_ids;
+}
+
+/* Returns the weighting variable in dictionary D, or a null
+ pointer if the dictionary is unweighted. */
+struct variable *
+dict_get_weight (const struct dictionary *d)
+{
+ assert (d->weight == NULL || dict_contains_var (d, d->weight));
+
+ return d->weight;
+}
+
+/* Returns the value of D's weighting variable in case C, except
+ that a negative weight is returned as 0. Returns 1 if the
+ dictionary is unweighted. Will warn about missing, negative,
+ or zero values if *WARN_ON_INVALID is true. The function will
+ set *WARN_ON_INVALID to false if an invalid weight is
+ found. */
+double
+dict_get_case_weight (const struct dictionary *d, const struct ccase *c,
+ bool *warn_on_invalid)
+{
+ assert (c != NULL);
+
+ if (d->weight == NULL)
+ return 1.0;
+ else
+ {
+ double w = case_num (c, d->weight);
+
+ return var_force_valid_weight (d->weight, w, warn_on_invalid);
+ }
+}
+
+/* Returns the format to use for weights. */
+const struct fmt_spec *
+dict_get_weight_format (const struct dictionary *d)
+{
+ return d->weight ? var_get_print_format (d->weight) : &F_8_0;
+}
+
+/* Sets the weighting variable of D to V, or turning off