+ sys_warn (r, _("File specifies unexpected value %g as %s."),
+ lowest, "LOWEST");
+}
+
+/* Read record type 7, subtype 7 or 19. */
+static void
+read_mrsets (struct sfm_reader *r, size_t size, size_t count,
+ struct dictionary *dict)
+{
+ struct text_record *text;
+ struct mrset *mrset;
+
+ text = open_text_record (r, size * count);
+ for (;;)
+ {
+ const char *name, *label, *counted;
+ struct stringi_set var_names;
+ size_t allocated_vars;
+ char delimiter;
+ int width;
+
+ mrset = xzalloc (sizeof *mrset);
+
+ name = text_get_token (text, ss_cstr ("="), NULL);
+ if (name == NULL)
+ break;
+ mrset->name = xstrdup (name);
+
+ if (mrset->name[0] != '$')
+ {
+ sys_warn (r, _("`%s' does not begin with `$' at offset %zu "
+ "in MRSETS record."), mrset->name, text_pos (text));
+ break;
+ }
+
+ if (text_match (text, 'C'))
+ {
+ mrset->type = MRSET_MC;
+ if (!text_match (text, ' '))
+ {
+ sys_warn (r, _("Missing space following `%c' at offset %zu "
+ "in MRSETS record."), 'C', text_pos (text));
+ break;
+ }
+ }
+ else if (text_match (text, 'D'))
+ {
+ mrset->type = MRSET_MD;
+ mrset->cat_source = MRSET_VARLABELS;
+ }
+ else if (text_match (text, 'E'))
+ {
+ char *number;
+
+ mrset->type = MRSET_MD;
+ mrset->cat_source = MRSET_COUNTEDVALUES;
+ if (!text_match (text, ' '))
+ {
+ sys_warn (r, _("Missing space following `%c' at offset %zu "
+ "in MRSETS record."), 'E', text_pos (text));
+ break;
+ }
+
+ number = text_get_token (text, ss_cstr (" "), NULL);
+ if (!strcmp (number, "11"))
+ mrset->label_from_var_label = true;
+ else if (strcmp (number, "1"))
+ sys_warn (r, _("Unexpected label source value `%s' "
+ "following `E' at offset %zu in MRSETS record."),
+ number, text_pos (text));
+ }
+ else
+ {
+ sys_warn (r, _("Missing `C', `D', or `E' at offset %zu "
+ "in MRSETS record."),
+ text_pos (text));
+ break;
+ }
+
+ if (mrset->type == MRSET_MD)
+ {
+ counted = text_parse_counted_string (r, text);
+ if (counted == NULL)
+ break;
+ }
+
+ label = text_parse_counted_string (r, text);
+ if (label == NULL)
+ break;
+ mrset->label = label[0] != '\0' ? xstrdup (label) : NULL;
+
+ stringi_set_init (&var_names);
+ allocated_vars = 0;
+ width = INT_MAX;
+ do
+ {
+ struct variable *var;
+ const char *var_name;
+
+ var_name = text_get_token (text, ss_cstr (" \n"), &delimiter);
+ if (var_name == NULL)
+ {
+ sys_warn (r, _("Missing new-line parsing variable names "
+ "at offset %zu in MRSETS record."),
+ text_pos (text));
+ break;
+ }
+
+ var = lookup_var_by_short_name (dict, var_name);
+ if (var == NULL)
+ continue;
+ if (!stringi_set_insert (&var_names, var_name))
+ {
+ sys_warn (r, _("Duplicate variable name %s "
+ "at offset %zu in MRSETS record."),
+ var_name, text_pos (text));
+ continue;
+ }
+
+ if (mrset->label == NULL && mrset->label_from_var_label
+ && var_has_label (var))
+ mrset->label = xstrdup (var_get_label (var));
+
+ if (mrset->n_vars
+ && var_get_type (var) != var_get_type (mrset->vars[0]))
+ {
+ sys_warn (r, _("MRSET %s contains both string and "
+ "numeric variables."), name);
+ continue;
+ }
+ width = MIN (width, var_get_width (var));
+
+ if (mrset->n_vars >= allocated_vars)
+ mrset->vars = x2nrealloc (mrset->vars, &allocated_vars,
+ sizeof *mrset->vars);
+ mrset->vars[mrset->n_vars++] = var;
+ }
+ while (delimiter != '\n');
+
+ if (mrset->n_vars < 2)
+ {
+ sys_warn (r, _("MRSET %s has only %zu variables."), mrset->name,
+ mrset->n_vars);
+ mrset_destroy (mrset);
+ continue;
+ }
+
+ if (mrset->type == MRSET_MD)
+ {
+ mrset->width = width;
+ value_init (&mrset->counted, width);
+ if (width == 0)
+ mrset->counted.f = strtod (counted, NULL);
+ else
+ value_copy_str_rpad (&mrset->counted, width,
+ (const uint8_t *) counted, ' ');
+ }
+
+ dict_add_mrset (dict, mrset);
+ mrset = NULL;
+ stringi_set_destroy (&var_names);
+ }
+ mrset_destroy (mrset);
+ close_text_record (r, text);