ec8ae3b32fd654c9f9ee0fcbbca007c0049fc075
[pspp] / src / data / sys-file-reader.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 1997-2000, 2006-2007, 2009-2016 Free Software Foundation, Inc.
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
16
17 #include <config.h>
18
19 #include "data/sys-file-private.h"
20
21 #include <errno.h>
22 #include <float.h>
23 #include <inttypes.h>
24 #include <stdlib.h>
25 #include <sys/stat.h>
26 #include <zlib.h>
27
28 #include "data/any-reader.h"
29 #include "data/attributes.h"
30 #include "data/case.h"
31 #include "data/casereader-provider.h"
32 #include "data/casereader.h"
33 #include "data/dictionary.h"
34 #include "data/file-handle-def.h"
35 #include "data/file-name.h"
36 #include "data/format.h"
37 #include "data/identifier.h"
38 #include "data/missing-values.h"
39 #include "data/mrset.h"
40 #include "data/short-names.h"
41 #include "data/value-labels.h"
42 #include "data/value.h"
43 #include "data/variable.h"
44 #include "libpspp/array.h"
45 #include "libpspp/assertion.h"
46 #include "libpspp/compiler.h"
47 #include "libpspp/i18n.h"
48 #include "libpspp/ll.h"
49 #include "libpspp/message.h"
50 #include "libpspp/misc.h"
51 #include "libpspp/pool.h"
52 #include "libpspp/str.h"
53 #include "libpspp/stringi-set.h"
54
55 #include "gl/c-strtod.h"
56 #include "gl/c-ctype.h"
57 #include "gl/inttostr.h"
58 #include "gl/localcharset.h"
59 #include "gl/minmax.h"
60 #include "gl/unlocked-io.h"
61 #include "gl/xalloc.h"
62 #include "gl/xalloc-oversized.h"
63 #include "gl/xsize.h"
64
65 #include "gettext.h"
66 #define _(msgid) gettext (msgid)
67 #define N_(msgid) (msgid)
68
69 enum
70   {
71     /* subtypes 0-2 unknown */
72     EXT_INTEGER       = 3,      /* Machine integer info. */
73     EXT_FLOAT         = 4,      /* Machine floating-point info. */
74     EXT_VAR_SETS      = 5,      /* Variable sets. */
75     EXT_DATE          = 6,      /* DATE. */
76     EXT_MRSETS        = 7,      /* Multiple response sets. */
77     EXT_DATA_ENTRY    = 8,      /* SPSS Data Entry. */
78     /* subtype 9 unknown */
79     EXT_PRODUCT_INFO  = 10,     /* Extra product info text. */
80     EXT_DISPLAY       = 11,     /* Variable display parameters. */
81     /* subtype 12 unknown */
82     EXT_LONG_NAMES    = 13,     /* Long variable names. */
83     EXT_LONG_STRINGS  = 14,     /* Long strings. */
84     /* subtype 15 unknown */
85     EXT_NCASES        = 16,     /* Extended number of cases. */
86     EXT_FILE_ATTRS    = 17,     /* Data file attributes. */
87     EXT_VAR_ATTRS     = 18,     /* Variable attributes. */
88     EXT_MRSETS2       = 19,     /* Multiple response sets (extended). */
89     EXT_ENCODING      = 20,     /* Character encoding. */
90     EXT_LONG_LABELS   = 21,     /* Value labels for long strings. */
91     EXT_LONG_MISSING  = 22,     /* Missing values for long strings. */
92     EXT_DATAVIEW      = 24      /* "Format properties in dataview table". */
93   };
94
95 /* Fields from the top-level header record. */
96 struct sfm_header_record
97   {
98     char magic[5];              /* First 4 bytes of file, then null. */
99     int weight_idx;             /* 0 if unweighted, otherwise a var index. */
100     int nominal_case_size;      /* Number of var positions. */
101
102     /* These correspond to the members of struct any_file_info or a dictionary
103        but in the system file's encoding rather than ASCII. */
104     char creation_date[10];     /* "dd mmm yy". */
105     char creation_time[9];      /* "hh:mm:ss". */
106     char eye_catcher[61];       /* Eye-catcher string, then product name. */
107     char file_label[65];        /* File label. */
108   };
109
110 struct sfm_var_record
111   {
112     off_t pos;
113     int width;
114     char name[9];
115     int print_format;
116     int write_format;
117     int missing_value_code;
118     uint8_t missing[24];
119     char *label;
120     struct variable *var;
121   };
122
123 struct sfm_value_label
124   {
125     uint8_t value[8];
126     char *label;
127   };
128
129 struct sfm_value_label_record
130   {
131     off_t pos;
132     struct sfm_value_label *labels;
133     unsigned int n_labels;
134
135     int *vars;
136     unsigned int n_vars;
137   };
138
139 struct sfm_document_record
140   {
141     off_t pos;
142     char *documents;
143     size_t n_lines;
144   };
145
146 struct sfm_mrset
147   {
148     const char *name;           /* Name. */
149     const char *label;          /* Human-readable label for group. */
150     enum mrset_type type;       /* Group type. */
151     const char **vars;          /* Constituent variables' names. */
152     size_t n_vars;              /* Number of constituent variables. */
153
154     /* MRSET_MD only. */
155     enum mrset_md_cat_source cat_source; /* Source of category labels. */
156     bool label_from_var_label;  /* 'label' taken from variable label? */
157     const char *counted;        /* Counted value, as string. */
158   };
159
160 struct sfm_extension_record
161   {
162     struct ll ll;               /* In struct sfm_reader 'var_attrs' list. */
163     int subtype;                /* Record subtype. */
164     off_t pos;                  /* Starting offset in file. */
165     unsigned int size;          /* Size of data elements. */
166     unsigned int count;         /* Number of data elements. */
167     void *data;                 /* Contents. */
168   };
169
170 /* System file reader. */
171 struct sfm_reader
172   {
173     struct any_reader any_reader;
174
175     /* Resource tracking. */
176     struct pool *pool;          /* All system file state. */
177
178     /* File data. */
179     struct any_read_info info;
180     struct sfm_header_record header;
181     struct sfm_var_record *vars;
182     size_t n_vars;
183     struct sfm_value_label_record *labels;
184     size_t n_labels;
185     struct sfm_document_record *document;
186     struct sfm_mrset *mrsets;
187     size_t n_mrsets;
188     struct sfm_extension_record *extensions[32];
189     struct ll_list var_attrs;   /* Contains "struct sfm_extension_record"s. */
190
191     /* File state. */
192     struct file_handle *fh;     /* File handle. */
193     struct fh_lock *lock;       /* Mutual exclusion for file handle. */
194     FILE *file;                 /* File stream. */
195     off_t pos;                  /* Position in file. */
196     bool error;                 /* I/O or corruption error? */
197     struct caseproto *proto;    /* Format of output cases. */
198
199     /* File format. */
200     enum integer_format integer_format; /* On-disk integer format. */
201     enum float_format float_format; /* On-disk floating point format. */
202     struct sfm_var *sfm_vars;   /* Variables. */
203     size_t sfm_var_cnt;         /* Number of variables. */
204     int case_cnt;               /* Number of cases */
205     const char *encoding;       /* String encoding. */
206     bool written_by_readstat; /* From https://github.com/WizardMac/ReadStat? */
207
208     /* Decompression. */
209     enum any_compression compression;
210     double bias;                /* Compression bias, usually 100.0. */
211     uint8_t opcodes[8];         /* Current block of opcodes. */
212     size_t opcode_idx;          /* Next opcode to interpret, 8 if none left. */
213     bool corruption_warning;    /* Warned about possible corruption? */
214
215     /* ZLIB decompression. */
216     long long int ztrailer_ofs; /* Offset of ZLIB trailer at end of file. */
217 #define ZIN_BUF_SIZE  4096
218     uint8_t *zin_buf;           /* Inflation input buffer. */
219 #define ZOUT_BUF_SIZE 16384
220     uint8_t *zout_buf;          /* Inflation output buffer. */
221     unsigned int zout_end;      /* Number of bytes of data in zout_buf. */
222     unsigned int zout_pos;      /* First unconsumed byte in zout_buf. */
223     z_stream zstream;           /* ZLIB inflater. */
224   };
225
226 static const struct casereader_class sys_file_casereader_class;
227
228 static struct sfm_reader *
229 sfm_reader_cast (const struct any_reader *r_)
230 {
231   assert (r_->klass == &sys_file_reader_class);
232   return UP_CAST (r_, struct sfm_reader, any_reader);
233 }
234
235 static bool sfm_close (struct any_reader *);
236
237 static void sys_msg (struct sfm_reader *r, off_t, int class,
238                      const char *format, va_list args)
239      PRINTF_FORMAT (4, 0);
240 static void sys_warn (struct sfm_reader *, off_t, const char *, ...)
241      PRINTF_FORMAT (3, 4);
242 static void sys_error (struct sfm_reader *, off_t, const char *, ...)
243      PRINTF_FORMAT (3, 4);
244
245 static bool read_bytes (struct sfm_reader *, void *, size_t)
246   WARN_UNUSED_RESULT;
247 static int try_read_bytes (struct sfm_reader *, void *, size_t)
248   WARN_UNUSED_RESULT;
249 static bool read_int (struct sfm_reader *, int *) WARN_UNUSED_RESULT;
250 static bool read_uint (struct sfm_reader *, unsigned int *) WARN_UNUSED_RESULT;
251 static bool read_int64 (struct sfm_reader *, long long int *)
252   WARN_UNUSED_RESULT;
253 static bool read_uint64 (struct sfm_reader *, unsigned long long int *)
254   WARN_UNUSED_RESULT;
255 static bool read_string (struct sfm_reader *, char *, size_t)
256   WARN_UNUSED_RESULT;
257 static bool skip_bytes (struct sfm_reader *, size_t) WARN_UNUSED_RESULT;
258
259 /* ZLIB compressed data handling. */
260 static bool read_zheader (struct sfm_reader *) WARN_UNUSED_RESULT;
261 static bool open_zstream (struct sfm_reader *) WARN_UNUSED_RESULT;
262 static bool close_zstream (struct sfm_reader *) WARN_UNUSED_RESULT;
263 static int read_bytes_zlib (struct sfm_reader *, void *, size_t)
264   WARN_UNUSED_RESULT;
265 static int read_compressed_bytes (struct sfm_reader *, void *, size_t)
266   WARN_UNUSED_RESULT;
267 static int try_read_compressed_bytes (struct sfm_reader *, void *, size_t)
268   WARN_UNUSED_RESULT;
269 static bool read_compressed_float (struct sfm_reader *, double *)
270   WARN_UNUSED_RESULT;
271
272 static char *fix_line_ends (const char *);
273
274 static int parse_int (const struct sfm_reader *, const void *data, size_t ofs);
275 static double parse_float (const struct sfm_reader *,
276                            const void *data, size_t ofs);
277
278 static bool read_variable_record (struct sfm_reader *,
279                                   struct sfm_var_record *);
280 static bool read_value_label_record (struct sfm_reader *,
281                                      struct sfm_value_label_record *);
282 static bool read_document_record (struct sfm_reader *);
283 static bool read_extension_record (struct sfm_reader *, int subtype,
284                                    struct sfm_extension_record **);
285 static bool skip_extension_record (struct sfm_reader *, int subtype);
286
287 static struct text_record *open_text_record (
288   struct sfm_reader *, const struct sfm_extension_record *,
289   bool recode_to_utf8);
290 static void close_text_record (struct sfm_reader *,
291                                struct text_record *);
292 static bool read_variable_to_value_pair (struct sfm_reader *,
293                                          struct dictionary *,
294                                          struct text_record *,
295                                          struct variable **var, char **value);
296 static void text_warn (struct sfm_reader *r, struct text_record *text,
297                        const char *format, ...)  PRINTF_FORMAT (3, 4);
298 static char *text_get_token (struct text_record *,
299                              struct substring delimiters, char *delimiter);
300 static bool text_match (struct text_record *, char c);
301 static bool text_read_variable_name (struct sfm_reader *, struct dictionary *,
302                                      struct text_record *,
303                                      struct substring delimiters,
304                                      struct variable **);
305 static bool text_read_short_name (struct sfm_reader *, struct dictionary *,
306                                   struct text_record *,
307                                   struct substring delimiters,
308                                   struct variable **);
309 static const char *text_parse_counted_string (struct sfm_reader *,
310                                               struct text_record *);
311 static size_t text_pos (const struct text_record *);
312 static const char *text_get_all (const struct text_record *);
313 \f
314 /* Dictionary reader. */
315
316 enum which_format
317   {
318     PRINT_FORMAT,
319     WRITE_FORMAT
320   };
321
322 static bool read_dictionary (struct sfm_reader *);
323 static bool read_record (struct sfm_reader *, int type,
324                          size_t *allocated_vars, size_t *allocated_labels);
325 static bool read_header (struct sfm_reader *, struct any_read_info *,
326                          struct sfm_header_record *);
327 static void parse_header (struct sfm_reader *,
328                           const struct sfm_header_record *,
329                           struct any_read_info *, struct dictionary *);
330 static bool parse_variable_records (struct sfm_reader *, struct dictionary *,
331                                     struct sfm_var_record *, size_t n);
332 static void parse_format_spec (struct sfm_reader *, off_t pos,
333                                unsigned int format, enum which_format,
334                                struct variable *, int *format_warning_cnt);
335 static void parse_document (struct dictionary *, struct sfm_document_record *);
336 static void parse_display_parameters (struct sfm_reader *,
337                                       const struct sfm_extension_record *,
338                                       struct dictionary *);
339 static bool parse_machine_integer_info (struct sfm_reader *,
340                                         const struct sfm_extension_record *,
341                                         struct any_read_info *);
342 static void parse_machine_float_info (struct sfm_reader *,
343                                       const struct sfm_extension_record *);
344 static void parse_extra_product_info (struct sfm_reader *,
345                                       const struct sfm_extension_record *,
346                                       struct any_read_info *);
347 static void parse_mrsets (struct sfm_reader *,
348                           const struct sfm_extension_record *,
349                           size_t *allocated_mrsets);
350 static void decode_mrsets (struct sfm_reader *, struct dictionary *);
351 static void parse_long_var_name_map (struct sfm_reader *,
352                                      const struct sfm_extension_record *,
353                                      struct dictionary *);
354 static bool parse_long_string_map (struct sfm_reader *,
355                                    const struct sfm_extension_record *,
356                                    struct dictionary *);
357 static void parse_value_labels (struct sfm_reader *, struct dictionary *);
358 static struct variable *parse_weight_var (struct sfm_reader *,
359                                           const struct sfm_var_record *, size_t n_var_recs,
360                                           int idx);
361 static void parse_data_file_attributes (struct sfm_reader *,
362                                         const struct sfm_extension_record *,
363                                         struct dictionary *);
364 static void parse_variable_attributes (struct sfm_reader *,
365                                        const struct sfm_extension_record *,
366                                        struct dictionary *);
367 static void assign_variable_roles (struct sfm_reader *, struct dictionary *);
368 static void parse_long_string_value_labels (struct sfm_reader *,
369                                             const struct sfm_extension_record *,
370                                             struct dictionary *);
371 static void parse_long_string_missing_values (
372   struct sfm_reader *, const struct sfm_extension_record *,
373   struct dictionary *);
374
375 /* Frees the strings inside INFO. */
376 void
377 any_read_info_destroy (struct any_read_info *info)
378 {
379   if (info)
380     {
381       free (info->creation_date);
382       free (info->creation_time);
383       free (info->product);
384       free (info->product_ext);
385     }
386 }
387
388 /* Tries to open FH for reading as a system file.  Returns an sfm_reader if
389    successful, otherwise NULL. */
390 static struct any_reader *
391 sfm_open (struct file_handle *fh)
392 {
393   size_t allocated_mrsets = 0;
394   struct sfm_reader *r;
395
396   /* Create and initialize reader. */
397   r = xzalloc (sizeof *r);
398   r->any_reader.klass = &sys_file_reader_class;
399   r->pool = pool_create ();
400   pool_register (r->pool, free, r);
401   r->fh = fh_ref (fh);
402   r->opcode_idx = sizeof r->opcodes;
403   ll_init (&r->var_attrs);
404
405   /* TRANSLATORS: this fragment will be interpolated into
406      messages in fh_lock() that identify types of files. */
407   r->lock = fh_lock (fh, FH_REF_FILE, N_("system file"), FH_ACC_READ, false);
408   if (r->lock == NULL)
409     goto error;
410
411   r->file = fn_open (fh, "rb");
412   if (r->file == NULL)
413     {
414       msg (ME, _("Error opening `%s' for reading as a system file: %s."),
415            fh_get_file_name (r->fh), strerror (errno));
416       goto error;
417     }
418
419   if (!read_dictionary (r))
420     goto error;
421
422   if (r->extensions[EXT_MRSETS] != NULL)
423     parse_mrsets (r, r->extensions[EXT_MRSETS], &allocated_mrsets);
424
425   if (r->extensions[EXT_MRSETS2] != NULL)
426     parse_mrsets (r, r->extensions[EXT_MRSETS2], &allocated_mrsets);
427
428   return &r->any_reader;
429
430 error:
431   if (r)
432     sfm_close (&r->any_reader);
433   return NULL;
434 }
435
436 static bool
437 read_dictionary (struct sfm_reader *r)
438 {
439   size_t allocated_vars;
440   size_t allocated_labels;
441
442   if (!read_header (r, &r->info, &r->header))
443     return false;
444
445   allocated_vars = 0;
446   allocated_labels = 0;
447   for (;;)
448     {
449       int type;
450
451       if (!read_int (r, &type))
452         return false;
453       if (type == 999)
454         break;
455       if (!read_record (r, type, &allocated_vars, &allocated_labels))
456         return false;
457     }
458
459   if (!skip_bytes (r, 4))
460     return false;
461
462   if (r->compression == ANY_COMP_ZLIB && !read_zheader (r))
463     return false;
464
465   return true;
466 }
467
468 static bool
469 read_record (struct sfm_reader *r, int type,
470              size_t *allocated_vars, size_t *allocated_labels)
471 {
472   int subtype;
473
474   switch (type)
475     {
476     case 2:
477       if (r->n_vars >= *allocated_vars)
478         r->vars = pool_2nrealloc (r->pool, r->vars, allocated_vars,
479                                   sizeof *r->vars);
480       return read_variable_record (r, &r->vars[r->n_vars++]);
481
482     case 3:
483       if (r->n_labels >= *allocated_labels)
484         r->labels = pool_2nrealloc (r->pool, r->labels, allocated_labels,
485                                     sizeof *r->labels);
486       return read_value_label_record (r, &r->labels[r->n_labels++]);
487
488     case 4:
489       /* A Type 4 record is always immediately after a type 3 record,
490          so the code for type 3 records reads the type 4 record too. */
491       sys_error (r, r->pos, _("Misplaced type 4 record."));
492       return false;
493
494     case 6:
495       if (r->document != NULL)
496         sys_warn (r, r->pos, _("Duplicate type 6 (document) record."));
497       return read_document_record (r);
498
499     case 7:
500       if (!read_int (r, &subtype))
501         return false;
502       else if (subtype < 0
503                || subtype >= sizeof r->extensions / sizeof *r->extensions)
504         {
505           sys_warn (r, r->pos,
506                     _("Unrecognized record type 7, subtype %d.  For help, "
507                       "please send this file to %s and mention that you were "
508                       "using %s."),
509                     subtype, PACKAGE_BUGREPORT, PACKAGE_STRING);
510           return skip_extension_record (r, subtype);
511         }
512       else if (subtype == 18)
513         {
514           /* System files written by "Stata 14.1/-savespss- 1.77 by S.Radyakin"
515              put each variable attribute into a separate record with subtype
516              18.  I'm surprised that SPSS puts up with this. */
517           struct sfm_extension_record *ext;
518           bool ok = read_extension_record (r, subtype, &ext);
519           if (ok && ext)
520             ll_push_tail (&r->var_attrs, &ext->ll);
521           return ok;
522         }
523       else if (r->extensions[subtype] != NULL)
524         {
525           sys_warn (r, r->pos,
526                     _("Record type 7, subtype %d found here has the same "
527                       "type as the record found near offset 0x%llx.  For "
528                       "help, please send this file to %s and mention that "
529                       "you were using %s."),
530                     subtype, (long long int) r->extensions[subtype]->pos,
531                     PACKAGE_BUGREPORT, PACKAGE_STRING);
532           return skip_extension_record (r, subtype);
533         }
534       else
535         return read_extension_record (r, subtype, &r->extensions[subtype]);
536
537     default:
538       sys_error (r, r->pos, _("Unrecognized record type %d."), type);
539       return false;
540     }
541
542   NOT_REACHED ();
543 }
544
545 /* Returns the character encoding obtained from R, or a null pointer if R
546    doesn't have an indication of its character encoding.  */
547 static const char *
548 sfm_get_encoding (const struct sfm_reader *r)
549 {
550   /* The EXT_ENCODING record is the best way to determine dictionary
551      encoding. */
552   if (r->extensions[EXT_ENCODING])
553     return r->extensions[EXT_ENCODING]->data;
554
555   /* But EXT_INTEGER is better than nothing as a fallback. */
556   if (r->extensions[EXT_INTEGER])
557     {
558       int codepage = parse_int (r, r->extensions[EXT_INTEGER]->data, 7 * 4);
559       const char *encoding;
560
561       switch (codepage)
562         {
563         case 1:
564           return "EBCDIC-US";
565
566         case 2:
567         case 3:
568           /* These ostensibly mean "7-bit ASCII" and "8-bit ASCII"[sic]
569              respectively.  However, many files have character code 2 but data
570              which are clearly not ASCII.  Therefore, ignore these values. */
571           break;
572
573         case 4:
574           return "MS_KANJI";
575
576         default:
577           encoding = sys_get_encoding_from_codepage (codepage);
578           if (encoding != NULL)
579             return encoding;
580           break;
581         }
582     }
583
584   /* If the file magic number is EBCDIC then its character data is too. */
585   if (!strcmp (r->header.magic, EBCDIC_MAGIC))
586     return "EBCDIC-US";
587
588   return NULL;
589 }
590
591 struct get_strings_aux
592   {
593     struct pool *pool;
594     char **titles;
595     char **strings;
596     bool *ids;
597     size_t allocated;
598     size_t n;
599   };
600
601 static void
602 add_string__ (struct get_strings_aux *aux,
603               const char *string, bool id, char *title)
604 {
605   if (aux->n >= aux->allocated)
606     {
607       aux->allocated = 2 * (aux->allocated + 1);
608       aux->titles = pool_realloc (aux->pool, aux->titles,
609                                   aux->allocated * sizeof *aux->titles);
610       aux->strings = pool_realloc (aux->pool, aux->strings,
611                                    aux->allocated * sizeof *aux->strings);
612       aux->ids = pool_realloc (aux->pool, aux->ids,
613                                aux->allocated * sizeof *aux->ids);
614     }
615
616   aux->titles[aux->n] = title;
617   aux->strings[aux->n] = pool_strdup (aux->pool, string);
618   aux->ids[aux->n] = id;
619   aux->n++;
620 }
621
622 static void PRINTF_FORMAT (3, 4)
623 add_string (struct get_strings_aux *aux,
624             const char *string, const char *title, ...)
625 {
626   va_list args;
627
628   va_start (args, title);
629   add_string__ (aux, string, false, pool_vasprintf (aux->pool, title, args));
630   va_end (args);
631 }
632
633 static void PRINTF_FORMAT (3, 4)
634 add_id (struct get_strings_aux *aux, const char *id, const char *title, ...)
635 {
636   va_list args;
637
638   va_start (args, title);
639   add_string__ (aux, id, true, pool_vasprintf (aux->pool, title, args));
640   va_end (args);
641 }
642
643 static const char *
644 skip_prefix (const char *s, const char *prefix)
645 {
646   size_t prefix_len = strlen (prefix);
647   return !strncmp (s, prefix, prefix_len) ? s + prefix_len : s;
648 }
649
650 /* Retrieves significant string data from R in its raw format, to allow the
651    caller to try to detect the encoding in use.
652
653    Returns the number of strings retrieved N.  Sets each of *TITLESP, *IDSP,
654    and *STRINGSP to an array of N elements allocated from POOL.  For each I in
655    0...N-1, UTF-8 string *TITLESP[I] describes *STRINGSP[I], which is in
656    whatever encoding system file R uses.  *IDS[I] is true if *STRINGSP[I] must
657    be a valid PSPP language identifier, false if *STRINGSP[I] is free-form
658    text. */
659 static size_t
660 sfm_get_strings (const struct any_reader *r_, struct pool *pool,
661                  char ***titlesp, bool **idsp, char ***stringsp)
662 {
663   struct sfm_reader *r = sfm_reader_cast (r_);
664   const struct sfm_mrset *mrset;
665   struct get_strings_aux aux;
666   size_t var_idx;
667   size_t i, j, k;
668
669   aux.pool = pool;
670   aux.titles = NULL;
671   aux.strings = NULL;
672   aux.ids = NULL;
673   aux.allocated = 0;
674   aux.n = 0;
675
676   var_idx = 0;
677   for (i = 0; i < r->n_vars; i++)
678     if (r->vars[i].width != -1)
679       add_id (&aux, r->vars[i].name, _("Variable %zu"), ++var_idx);
680
681   var_idx = 0;
682   for (i = 0; i < r->n_vars; i++)
683     if (r->vars[i].width != -1)
684       {
685         var_idx++;
686         if (r->vars[i].label)
687           add_string (&aux, r->vars[i].label, _("Variable %zu Label"),
688                       var_idx);
689       }
690
691   k = 0;
692   for (i = 0; i < r->n_labels; i++)
693     for (j = 0; j < r->labels[i].n_labels; j++)
694       add_string (&aux, r->labels[i].labels[j].label,
695                   _("Value Label %zu"), k++);
696
697   add_string (&aux, r->header.creation_date, _("Creation Date"));
698   add_string (&aux, r->header.creation_time, _("Creation Time"));
699   add_string (&aux, skip_prefix (r->header.eye_catcher, "@(#) "), _("Product"));
700   add_string (&aux, r->header.file_label, _("File Label"));
701
702   if (r->extensions[EXT_PRODUCT_INFO])
703     add_string (&aux, r->extensions[EXT_PRODUCT_INFO]->data,
704                 _("Extra Product Info"));
705
706   if (r->document)
707     {
708       size_t i;
709
710       for (i = 0; i < r->document->n_lines; i++)
711         {
712           char line[81];
713
714           memcpy (line, r->document->documents + i * 80, 80);
715           line[80] = '\0';
716
717           add_string (&aux, line, _("Document Line %zu"), i + 1);
718         }
719     }
720
721   for (mrset = r->mrsets; mrset < &r->mrsets[r->n_mrsets]; mrset++)
722     {
723       size_t mrset_idx = mrset - r->mrsets + 1;
724
725       add_id (&aux, mrset->name, _("MRSET %zu"), mrset_idx);
726       if (mrset->label[0])
727         add_string (&aux, mrset->label, _("MRSET %zu Label"), mrset_idx);
728
729       /* Skip the variables because they ought to be duplicates. */
730
731       if (mrset->counted)
732         add_string (&aux, mrset->counted, _("MRSET %zu Counted Value"),
733                     mrset_idx);
734     }
735
736   /* data file attributes */
737   /* variable attributes */
738   /* long var map */
739   /* long string value labels */
740   /* long string missing values */
741
742   *titlesp = aux.titles;
743   *idsp = aux.ids;
744   *stringsp = aux.strings;
745   return aux.n;
746 }
747
748 /* Decodes the dictionary read from R, saving it into into *DICT.  Character
749    strings in R are decoded using ENCODING, or an encoding obtained from R if
750    ENCODING is null, or the locale encoding if R specifies no encoding.
751
752    If INFOP is non-null, then it receives additional info about the system
753    file, which the caller must eventually free with any_read_info_destroy()
754    when it is no longer needed.
755
756    This function consumes R.  The caller must use it again later, even to
757    destroy it with sfm_close(). */
758 static struct casereader *
759 sfm_decode (struct any_reader *r_, const char *encoding,
760             struct dictionary **dictp, struct any_read_info *infop)
761 {
762   struct sfm_reader *r = sfm_reader_cast (r_);
763   struct dictionary *dict;
764
765   if (encoding == NULL)
766     {
767       encoding = sfm_get_encoding (r);
768       if (encoding == NULL)
769         {
770           sys_warn (r, -1, _("This system file does not indicate its own "
771                              "character encoding.  Using default encoding "
772                              "%s.  For best results, specify an encoding "
773                              "explicitly.  Use SYSFILE INFO with "
774                              "ENCODING=\"DETECT\" to analyze the possible "
775                              "encodings."),
776                     locale_charset ());
777           encoding = locale_charset ();
778         }
779     }
780
781   dict = dict_create (encoding);
782   r->encoding = dict_get_encoding (dict);
783
784   /* These records don't use variables at all. */
785   if (r->document != NULL)
786     parse_document (dict, r->document);
787
788   if (r->extensions[EXT_INTEGER] != NULL
789       && !parse_machine_integer_info (r, r->extensions[EXT_INTEGER], &r->info))
790     goto error;
791
792   if (r->extensions[EXT_FLOAT] != NULL)
793     parse_machine_float_info (r, r->extensions[EXT_FLOAT]);
794
795   if (r->extensions[EXT_PRODUCT_INFO] != NULL)
796     parse_extra_product_info (r, r->extensions[EXT_PRODUCT_INFO], &r->info);
797
798   if (r->extensions[EXT_FILE_ATTRS] != NULL)
799     parse_data_file_attributes (r, r->extensions[EXT_FILE_ATTRS], dict);
800
801   parse_header (r, &r->header, &r->info, dict);
802
803   /* Parse the variable records, the basis of almost everything else. */
804   if (!parse_variable_records (r, dict, r->vars, r->n_vars))
805     goto error;
806
807   /* Parse value labels and the weight variable immediately after the variable
808      records.  These records use indexes into var_recs[], so we must parse them
809      before those indexes become invalidated by very long string variables. */
810   parse_value_labels (r, dict);
811   if (r->header.weight_idx != 0)
812     dict_set_weight (dict, parse_weight_var (r, r->vars, r->n_vars,
813                                              r->header.weight_idx));
814
815   if (r->extensions[EXT_DISPLAY] != NULL)
816     parse_display_parameters (r, r->extensions[EXT_DISPLAY], dict);
817
818   /* The following records use short names, so they need to be parsed before
819      parse_long_var_name_map() changes short names to long names. */
820   decode_mrsets (r, dict);
821
822   if (r->extensions[EXT_LONG_STRINGS] != NULL
823       && !parse_long_string_map (r, r->extensions[EXT_LONG_STRINGS], dict))
824     goto error;
825
826   /* Now rename variables to their long names. */
827   parse_long_var_name_map (r, r->extensions[EXT_LONG_NAMES], dict);
828
829   /* The following records use long names, so they need to follow renaming. */
830   if (!ll_is_empty (&r->var_attrs))
831     {
832       struct sfm_extension_record *ext;
833       ll_for_each (ext, struct sfm_extension_record, ll, &r->var_attrs)
834         parse_variable_attributes (r, ext, dict);
835
836       /* Roles use the $@Role attribute.  */
837       assign_variable_roles (r, dict);
838     }
839   if (r->extensions[EXT_LONG_LABELS] != NULL)
840     parse_long_string_value_labels (r, r->extensions[EXT_LONG_LABELS], dict);
841   if (r->extensions[EXT_LONG_MISSING] != NULL)
842     parse_long_string_missing_values (r, r->extensions[EXT_LONG_MISSING],
843                                       dict);
844
845   /* Warn if the actual amount of data per case differs from the
846      amount that the header claims.  SPSS version 13 gets this
847      wrong when very long strings are involved, so don't warn in
848      that case. */
849   if (r->header.nominal_case_size > 0
850       && r->header.nominal_case_size != r->n_vars
851       && r->info.version_major != 13)
852     sys_warn (r, -1, _("File header claims %d variable positions but "
853                        "%zu were read from file."),
854               r->header.nominal_case_size, r->n_vars);
855
856   /* Create an index of dictionary variable widths for
857      sfm_read_case to use.  We cannot use the `struct variable's
858      from the dictionary we created, because the caller owns the
859      dictionary and may destroy or modify its variables. */
860   sfm_dictionary_to_sfm_vars (dict, &r->sfm_vars, &r->sfm_var_cnt);
861   pool_register (r->pool, free, r->sfm_vars);
862   r->proto = caseproto_ref_pool (dict_get_proto (dict), r->pool);
863
864   *dictp = dict;
865   if (infop)
866     {
867       *infop = r->info;
868       memset (&r->info, 0, sizeof r->info);
869     }
870
871   return casereader_create_sequential
872     (NULL, r->proto,
873      r->case_cnt == -1 ? CASENUMBER_MAX: r->case_cnt,
874                                        &sys_file_casereader_class, r);
875
876 error:
877   sfm_close (r_);
878   dict_unref (dict);
879   *dictp = NULL;
880   return NULL;
881 }
882
883 /* Closes R, which should have been returned by sfm_open() but not already
884    closed with sfm_decode() or this function.
885    Returns true if an I/O error has occurred on READER, false
886    otherwise. */
887 static bool
888 sfm_close (struct any_reader *r_)
889 {
890   struct sfm_reader *r = sfm_reader_cast (r_);
891   bool error;
892
893   if (r->file)
894     {
895       if (fn_close (r->fh, r->file) == EOF)
896         {
897           msg (ME, _("Error closing system file `%s': %s."),
898                fh_get_file_name (r->fh), strerror (errno));
899           r->error = true;
900         }
901       r->file = NULL;
902     }
903
904   any_read_info_destroy (&r->info);
905   fh_unlock (r->lock);
906   fh_unref (r->fh);
907
908   error = r->error;
909   pool_destroy (r->pool);
910
911   return !error;
912 }
913
914 /* Destroys READER. */
915 static void
916 sys_file_casereader_destroy (struct casereader *reader UNUSED, void *r_)
917 {
918   struct sfm_reader *r = r_;
919   sfm_close (&r->any_reader);
920 }
921
922 /* Detects whether FILE is an SPSS system file.  Returns 1 if so, 0 if not, and
923    a negative errno value if there is an error reading FILE. */
924 static int
925 sfm_detect (FILE *file)
926 {
927   char magic[5];
928
929   if (fseek (file, 0, SEEK_SET) != 0)
930     return -errno;
931   if (fread (magic, 4, 1, file) != 1)
932     return ferror (file) ? -errno : 0;
933   magic[4] = '\0';
934
935   return (!strcmp (ASCII_MAGIC, magic)
936           || !strcmp (ASCII_ZMAGIC, magic)
937           || !strcmp (EBCDIC_MAGIC, magic));
938 }
939 \f
940 /* Reads the global header of the system file.  Initializes *HEADER and *INFO,
941    except for the string fields in *INFO, which parse_header() will initialize
942    later once the file's encoding is known. */
943 static bool
944 read_header (struct sfm_reader *r, struct any_read_info *info,
945              struct sfm_header_record *header)
946 {
947   uint8_t raw_layout_code[4];
948   uint8_t raw_bias[8];
949   int compressed;
950   bool zmagic;
951
952   if (!read_string (r, header->magic, sizeof header->magic)
953       || !read_string (r, header->eye_catcher, sizeof header->eye_catcher))
954     return false;
955   r->written_by_readstat = strstr (header->eye_catcher,
956                                    "https://github.com/WizardMac/ReadStat");
957
958   if (!strcmp (ASCII_MAGIC, header->magic)
959       || !strcmp (EBCDIC_MAGIC, header->magic))
960     zmagic = false;
961   else if (!strcmp (ASCII_ZMAGIC, header->magic))
962     zmagic = true;
963   else
964     {
965       sys_error (r, 0, _("This is not an SPSS system file."));
966       return false;
967     }
968
969   /* Identify integer format. */
970   if (!read_bytes (r, raw_layout_code, sizeof raw_layout_code))
971     return false;
972   if ((!integer_identify (2, raw_layout_code, sizeof raw_layout_code,
973                           &r->integer_format)
974        && !integer_identify (3, raw_layout_code, sizeof raw_layout_code,
975                              &r->integer_format))
976       || (r->integer_format != INTEGER_MSB_FIRST
977           && r->integer_format != INTEGER_LSB_FIRST))
978     {
979       sys_error (r, 64, _("This is not an SPSS system file."));
980       return false;
981     }
982
983   if (!read_int (r, &header->nominal_case_size))
984     return false;
985
986   if (header->nominal_case_size < 0
987       || header->nominal_case_size > INT_MAX / 16)
988     header->nominal_case_size = -1;
989
990   if (!read_int (r, &compressed))
991     return false;
992   if (!zmagic)
993     {
994       if (compressed == 0)
995         r->compression = ANY_COMP_NONE;
996       else if (compressed == 1)
997         r->compression = ANY_COMP_SIMPLE;
998       else if (compressed != 0)
999         {
1000           sys_error (r, 0, "System file header has invalid compression "
1001                      "value %d.", compressed);
1002           return false;
1003         }
1004     }
1005   else
1006     {
1007       if (compressed == 2)
1008         r->compression = ANY_COMP_ZLIB;
1009       else
1010         {
1011           sys_error (r, 0, "ZLIB-compressed system file header has invalid "
1012                      "compression value %d.", compressed);
1013           return false;
1014         }
1015     }
1016
1017   if (!read_int (r, &header->weight_idx))
1018     return false;
1019
1020   if (!read_int (r, &r->case_cnt))
1021     return false;
1022   if (r->case_cnt > INT_MAX / 2)
1023     r->case_cnt = -1;
1024
1025   /* Identify floating-point format and obtain compression bias. */
1026   if (!read_bytes (r, raw_bias, sizeof raw_bias))
1027     return false;
1028   if (float_identify (100.0, raw_bias, sizeof raw_bias, &r->float_format) == 0)
1029     {
1030       uint8_t zero_bias[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
1031
1032       if (memcmp (raw_bias, zero_bias, 8))
1033         sys_warn (r, r->pos - 8,
1034                   _("Compression bias is not the usual "
1035                     "value of 100, or system file uses unrecognized "
1036                     "floating-point format."));
1037       else
1038         {
1039           /* Some software is known to write all-zeros to this
1040              field.  Such software also writes floating-point
1041              numbers in the format that we expect by default
1042              (it seems that all software most likely does, in
1043              reality), so don't warn in this case. */
1044         }
1045
1046       if (r->integer_format == INTEGER_MSB_FIRST)
1047         r->float_format = FLOAT_IEEE_DOUBLE_BE;
1048       else
1049         r->float_format = FLOAT_IEEE_DOUBLE_LE;
1050     }
1051   float_convert (r->float_format, raw_bias, FLOAT_NATIVE_DOUBLE, &r->bias);
1052
1053   if (!read_string (r, header->creation_date, sizeof header->creation_date)
1054       || !read_string (r, header->creation_time, sizeof header->creation_time)
1055       || !read_string (r, header->file_label, sizeof header->file_label)
1056       || !skip_bytes (r, 3))
1057     return false;
1058
1059   info->integer_format = r->integer_format;
1060   info->float_format = r->float_format;
1061   info->compression = r->compression;
1062   info->case_cnt = r->case_cnt;
1063
1064   return true;
1065 }
1066
1067 /* Reads a variable (type 2) record from R into RECORD. */
1068 static bool
1069 read_variable_record (struct sfm_reader *r, struct sfm_var_record *record)
1070 {
1071   int has_variable_label;
1072
1073   memset (record, 0, sizeof *record);
1074
1075   record->pos = r->pos;
1076   if (!read_int (r, &record->width)
1077       || !read_int (r, &has_variable_label)
1078       || !read_int (r, &record->missing_value_code)
1079       || !read_int (r, &record->print_format)
1080       || !read_int (r, &record->write_format)
1081       || !read_string (r, record->name, sizeof record->name))
1082     return false;
1083
1084   if (has_variable_label == 1)
1085     {
1086       enum { MAX_LABEL_LEN = 65536 };
1087       unsigned int len, read_len;
1088
1089       if (!read_uint (r, &len))
1090         return false;
1091
1092       /* Read up to MAX_LABEL_LEN bytes of label. */
1093       read_len = MIN (MAX_LABEL_LEN, len);
1094       record->label = pool_malloc (r->pool, read_len + 1);
1095       if (!read_string (r, record->label, read_len + 1))
1096         return false;
1097
1098       /* Skip unread label bytes. */
1099       if (!skip_bytes (r, len - read_len))
1100         return false;
1101
1102       /* Skip label padding up to multiple of 4 bytes. */
1103       if (!skip_bytes (r, ROUND_UP (len, 4) - len))
1104         return false;
1105     }
1106   else if (has_variable_label != 0)
1107     {
1108       sys_error (r, record->pos,
1109                  _("Variable label indicator field is not 0 or 1."));
1110       return false;
1111     }
1112
1113   /* Set missing values. */
1114   if (record->missing_value_code != 0)
1115     {
1116       int code = record->missing_value_code;
1117       if (record->width == 0)
1118         {
1119           if (code < -3 || code > 3 || code == -1)
1120             {
1121               sys_error (r, record->pos,
1122                          _("Numeric missing value indicator field is not "
1123                            "-3, -2, 0, 1, 2, or 3."));
1124               return false;
1125             }
1126         }
1127       else
1128         {
1129           if (code < 1 || code > 3)
1130             {
1131               sys_error (r, record->pos,
1132                          _("String missing value indicator field is not "
1133                            "0, 1, 2, or 3."));
1134               return false;
1135             }
1136         }
1137
1138       if (!read_bytes (r, record->missing, 8 * abs (code)))
1139         return false;
1140     }
1141
1142   return true;
1143 }
1144
1145 /* Reads value labels from R into RECORD. */
1146 static bool
1147 read_value_label_record (struct sfm_reader *r,
1148                          struct sfm_value_label_record *record)
1149 {
1150   size_t i;
1151   int type;
1152
1153   /* Read type 3 record. */
1154   record->pos = r->pos;
1155   if (!read_uint (r, &record->n_labels))
1156     return false;
1157   if (record->n_labels > UINT_MAX / sizeof *record->labels)
1158     {
1159       sys_error (r, r->pos - 4, _("Invalid number of labels %u."),
1160                  record->n_labels);
1161       return false;
1162     }
1163   record->labels = pool_nmalloc (r->pool, record->n_labels,
1164                                  sizeof *record->labels);
1165   for (i = 0; i < record->n_labels; i++)
1166     {
1167       struct sfm_value_label *label = &record->labels[i];
1168       unsigned char label_len;
1169       size_t padded_len;
1170
1171       if (!read_bytes (r, label->value, sizeof label->value))
1172         return false;
1173
1174       /* Read label length. */
1175       if (!read_bytes (r, &label_len, sizeof label_len))
1176         return false;
1177       padded_len = ROUND_UP (label_len + 1, 8);
1178
1179       /* Read label, padding. */
1180       label->label = pool_malloc (r->pool, padded_len + 1);
1181       if (!read_bytes (r, label->label, padded_len - 1))
1182         return false;
1183       label->label[label_len] = '\0';
1184     }
1185
1186   /* Read record type of type 4 record. */
1187   if (!read_int (r, &type))
1188     return false;
1189   if (type != 4)
1190     {
1191       sys_error (r, r->pos - 4,
1192                  _("Variable index record (type 4) does not immediately "
1193                    "follow value label record (type 3) as it should."));
1194       return false;
1195     }
1196
1197   /* Read number of variables associated with value label from type 4
1198      record. */
1199   if (!read_uint (r, &record->n_vars))
1200     return false;
1201   if (record->n_vars < 1 || record->n_vars > r->n_vars)
1202     {
1203       sys_error (r, r->pos - 4,
1204                  _("Number of variables associated with a value label (%u) "
1205                    "is not between 1 and the number of variables (%zu)."),
1206                  record->n_vars, r->n_vars);
1207       return false;
1208     }
1209
1210   record->vars = pool_nmalloc (r->pool, record->n_vars, sizeof *record->vars);
1211   for (i = 0; i < record->n_vars; i++)
1212     if (!read_int (r, &record->vars[i]))
1213       return false;
1214
1215   return true;
1216 }
1217
1218 /* Reads a document record from R.  Returns true if successful, false on
1219    error. */
1220 static bool
1221 read_document_record (struct sfm_reader *r)
1222 {
1223   int n_lines;
1224   if (!read_int (r, &n_lines))
1225     return false;
1226   else if (n_lines == 0)
1227     return true;
1228   else if (n_lines < 0 || n_lines >= INT_MAX / DOC_LINE_LENGTH)
1229     {
1230       sys_error (r, r->pos,
1231                  _("Number of document lines (%d) "
1232                    "must be greater than 0 and less than %d."),
1233                  n_lines, INT_MAX / DOC_LINE_LENGTH);
1234       return false;
1235     }
1236
1237   struct sfm_document_record *record;
1238   record = pool_malloc (r->pool, sizeof *record);
1239   record->pos = r->pos;
1240   record->n_lines = n_lines;
1241   record->documents = pool_malloc (r->pool, DOC_LINE_LENGTH * n_lines);
1242   if (!read_bytes (r, record->documents, DOC_LINE_LENGTH * n_lines))
1243     return false;
1244
1245   r->document = record;
1246   return true;
1247 }
1248
1249 static bool
1250 read_extension_record_header (struct sfm_reader *r, int subtype,
1251                               struct sfm_extension_record *record)
1252 {
1253   record->subtype = subtype;
1254   record->pos = r->pos;
1255   if (!read_uint (r, &record->size) || !read_uint (r, &record->count))
1256     return false;
1257
1258   /* Check that SIZE * COUNT + 1 doesn't overflow.  Adding 1
1259      allows an extra byte for a null terminator, used by some
1260      extension processing routines. */
1261   if (record->size != 0
1262       && xsum (1, xtimes (record->count, record->size)) >= UINT_MAX)
1263     {
1264       sys_error (r, record->pos, "Record type 7 subtype %d too large.",
1265                  subtype);
1266       return false;
1267     }
1268
1269   return true;
1270 }
1271
1272 /* Reads an extension record from R into RECORD. */
1273 static bool
1274 read_extension_record (struct sfm_reader *r, int subtype,
1275                        struct sfm_extension_record **recordp)
1276 {
1277   struct extension_record_type
1278     {
1279       int subtype;
1280       int size;
1281       int count;
1282     };
1283
1284   static const struct extension_record_type types[] =
1285     {
1286       /* Implemented record types. */
1287       { EXT_INTEGER,      4, 8 },
1288       { EXT_FLOAT,        8, 3 },
1289       { EXT_MRSETS,       1, 0 },
1290       { EXT_PRODUCT_INFO, 1, 0 },
1291       { EXT_DISPLAY,      4, 0 },
1292       { EXT_LONG_NAMES,   1, 0 },
1293       { EXT_LONG_STRINGS, 1, 0 },
1294       { EXT_NCASES,       8, 2 },
1295       { EXT_FILE_ATTRS,   1, 0 },
1296       { EXT_VAR_ATTRS,    1, 0 },
1297       { EXT_MRSETS2,      1, 0 },
1298       { EXT_ENCODING,     1, 0 },
1299       { EXT_LONG_LABELS,  1, 0 },
1300       { EXT_LONG_MISSING, 1, 0 },
1301
1302       /* Ignored record types. */
1303       { EXT_VAR_SETS,     0, 0 },
1304       { EXT_DATE,         0, 0 },
1305       { EXT_DATA_ENTRY,   0, 0 },
1306       { EXT_DATAVIEW,     0, 0 },
1307     };
1308
1309   const struct extension_record_type *type;
1310   struct sfm_extension_record *record;
1311   size_t n_bytes;
1312
1313   *recordp = NULL;
1314   record = pool_malloc (r->pool, sizeof *record);
1315   if (!read_extension_record_header (r, subtype, record))
1316     return false;
1317   n_bytes = record->count * record->size;
1318
1319   for (type = types; type < &types[sizeof types / sizeof *types]; type++)
1320     if (subtype == type->subtype)
1321       {
1322         if (type->size > 0 && record->size != type->size)
1323           sys_warn (r, record->pos,
1324                     _("Record type 7, subtype %d has bad size %u "
1325                       "(expected %d)."), subtype, record->size, type->size);
1326         else if (type->count > 0 && record->count != type->count)
1327           sys_warn (r, record->pos,
1328                     _("Record type 7, subtype %d has bad count %u "
1329                       "(expected %d)."), subtype, record->count, type->count);
1330         else if (type->count == 0 && type->size == 0)
1331           {
1332             /* Ignore this record. */
1333           }
1334         else
1335           {
1336             char *data = pool_malloc (r->pool, n_bytes + 1);
1337             data[n_bytes] = '\0';
1338
1339             record->data = data;
1340             if (!read_bytes (r, record->data, n_bytes))
1341               return false;
1342             *recordp = record;
1343             return true;
1344           }
1345
1346         goto skip;
1347       }
1348
1349   sys_warn (r, record->pos,
1350             _("Unrecognized record type 7, subtype %d.  For help, please "
1351               "send this file to %s and mention that you were using %s."),
1352             subtype, PACKAGE_BUGREPORT, PACKAGE_STRING);
1353
1354 skip:
1355   return skip_bytes (r, n_bytes);
1356 }
1357
1358 static bool
1359 skip_extension_record (struct sfm_reader *r, int subtype)
1360 {
1361   struct sfm_extension_record record;
1362
1363   return (read_extension_record_header (r, subtype, &record)
1364           && skip_bytes (r, record.count * record.size));
1365 }
1366
1367 static void
1368 parse_header (struct sfm_reader *r, const struct sfm_header_record *header,
1369               struct any_read_info *info, struct dictionary *dict)
1370 {
1371   const char *dict_encoding = dict_get_encoding (dict);
1372   struct substring product;
1373   struct substring label;
1374   char *fixed_label;
1375
1376   /* Convert file label to UTF-8 and put it into DICT. */
1377   label = recode_substring_pool ("UTF-8", dict_encoding,
1378                                  ss_cstr (header->file_label), r->pool);
1379   ss_trim (&label, ss_cstr (" "));
1380   label.string[label.length] = '\0';
1381   fixed_label = fix_line_ends (label.string);
1382   dict_set_label (dict, fixed_label);
1383   free (fixed_label);
1384
1385   /* Put creation date and time in UTF-8 into INFO. */
1386   info->creation_date = recode_string ("UTF-8", dict_encoding,
1387                                        header->creation_date, -1);
1388   info->creation_time = recode_string ("UTF-8", dict_encoding,
1389                                        header->creation_time, -1);
1390
1391   /* Put product name into INFO, dropping eye-catcher string if present. */
1392   product = recode_substring_pool ("UTF-8", dict_encoding,
1393                                    ss_cstr (header->eye_catcher), r->pool);
1394   ss_match_string (&product, ss_cstr ("@(#) SPSS DATA FILE"));
1395   ss_trim (&product, ss_cstr (" "));
1396   info->product = ss_xstrdup (product);
1397 }
1398
1399 static struct variable *
1400 add_var_with_generated_name (struct dictionary *dict, int width)
1401 {
1402   char *name = dict_make_unique_var_name (dict, NULL, NULL);
1403   struct variable *var = dict_create_var_assert (dict, name, width);
1404   free (name);
1405   return var;
1406 }
1407
1408 /* Reads a variable (type 2) record from R and adds the
1409    corresponding variable to DICT.
1410    Also skips past additional variable records for long string
1411    variables. */
1412 static bool
1413 parse_variable_records (struct sfm_reader *r, struct dictionary *dict,
1414                         struct sfm_var_record *var_recs, size_t n_var_recs)
1415 {
1416   const char *dict_encoding = dict_get_encoding (dict);
1417   struct sfm_var_record *rec;
1418   int n_warnings = 0;
1419
1420   for (rec = var_recs; rec < &var_recs[n_var_recs];)
1421     {
1422       size_t n_values;
1423       char *name;
1424       size_t i;
1425
1426       name = recode_string_pool ("UTF-8", dict_encoding,
1427                                  rec->name, -1, r->pool);
1428       name[strcspn (name, " ")] = '\0';
1429
1430       if (rec->width < 0 || rec->width > 255)
1431         {
1432           sys_error (r, rec->pos,
1433                      _("Bad width %d for variable %s."), rec->width, name);
1434           return false;
1435         }
1436
1437       struct variable *var;
1438       if (!dict_id_is_valid (dict, name, false)
1439           || name[0] == '$' || name[0] == '#')
1440         {
1441           var = add_var_with_generated_name (dict, rec->width);
1442           sys_warn (r, rec->pos, _("Renaming variable with invalid name "
1443                                    "`%s' to `%s'."), name, var_get_name (var));
1444         }
1445       else
1446         {
1447           var = dict_create_var (dict, name, rec->width);
1448           if (var == NULL)
1449             {
1450               var = add_var_with_generated_name (dict, rec->width);
1451               sys_warn (r, rec->pos, _("Renaming variable with duplicate name "
1452                                        "`%s' to `%s'."),
1453                         name, var_get_name (var));
1454             }
1455         }
1456       rec->var = var;
1457
1458       /* Set the short name the same as the long name (even if we renamed
1459          it). */
1460       var_set_short_name (var, 0, var_get_name (var));
1461
1462       /* Get variable label, if any. */
1463       if (rec->label)
1464         {
1465           char *utf8_label;
1466
1467           utf8_label = recode_string_pool ("UTF-8", dict_encoding,
1468                                            rec->label, -1, r->pool);
1469           var_set_label (var, utf8_label);
1470         }
1471
1472       /* Set missing values. */
1473       if (rec->missing_value_code != 0)
1474         {
1475           int width = var_get_width (var);
1476           struct missing_values mv;
1477
1478           mv_init_pool (r->pool, &mv, width);
1479           if (var_is_numeric (var))
1480             {
1481               bool has_range = rec->missing_value_code < 0;
1482               int n_discrete = (has_range
1483                                 ? rec->missing_value_code == -3
1484                                 : rec->missing_value_code);
1485               int ofs = 0;
1486
1487               if (has_range)
1488                 {
1489                   double low = parse_float (r, rec->missing, 0);
1490                   double high = parse_float (r, rec->missing, 8);
1491
1492                   /* Deal with SPSS 21 change in representation. */
1493                   if (low == SYSMIS)
1494                     low = LOWEST;
1495
1496                   mv_add_range (&mv, low, high);
1497                   ofs += 16;
1498                 }
1499
1500               for (i = 0; i < n_discrete; i++)
1501                 {
1502                   mv_add_num (&mv, parse_float (r, rec->missing, ofs));
1503                   ofs += 8;
1504                 }
1505             }
1506           else
1507             for (i = 0; i < rec->missing_value_code; i++)
1508               mv_add_str (&mv, rec->missing + 8 * i, MIN (width, 8));
1509           var_set_missing_values (var, &mv);
1510         }
1511
1512       /* Set formats. */
1513       parse_format_spec (r, rec->pos + 12, rec->print_format,
1514                          PRINT_FORMAT, var, &n_warnings);
1515       parse_format_spec (r, rec->pos + 16, rec->write_format,
1516                          WRITE_FORMAT, var, &n_warnings);
1517
1518       /* Account for values.
1519          Skip long string continuation records, if any. */
1520       n_values = rec->width == 0 ? 1 : DIV_RND_UP (rec->width, 8);
1521       for (i = 1; i < n_values; i++)
1522         if (i + (rec - var_recs) >= n_var_recs || rec[i].width != -1)
1523           {
1524             sys_error (r, rec->pos, _("Missing string continuation record."));
1525             return false;
1526           }
1527       rec += n_values;
1528     }
1529
1530   return true;
1531 }
1532
1533 /* Translates the format spec from sysfile format to internal
1534    format. */
1535 static void
1536 parse_format_spec (struct sfm_reader *r, off_t pos, unsigned int format,
1537                    enum which_format which, struct variable *v,
1538                    int *n_warnings)
1539 {
1540   const int max_warnings = 8;
1541   struct fmt_spec f;
1542
1543   if (fmt_from_u32 (format, var_get_width (v), false, &f))
1544     {
1545       if (which == PRINT_FORMAT)
1546         var_set_print_format (v, &f);
1547       else
1548         var_set_write_format (v, &f);
1549     }
1550   else if (format == 0)
1551     {
1552       /* Actually observed in the wild.  No point in warning about it. */
1553     }
1554   else if (++*n_warnings <= max_warnings)
1555     {
1556       if (which == PRINT_FORMAT)
1557         sys_warn (r, pos, _("Variable %s with width %d has invalid print "
1558                             "format 0x%x."),
1559                   var_get_name (v), var_get_width (v), format);
1560       else
1561         sys_warn (r, pos, _("Variable %s with width %d has invalid write "
1562                             "format 0x%x."),
1563                   var_get_name (v), var_get_width (v), format);
1564
1565       if (*n_warnings == max_warnings)
1566         sys_warn (r, -1, _("Suppressing further invalid format warnings."));
1567     }
1568 }
1569
1570 static void
1571 parse_document (struct dictionary *dict, struct sfm_document_record *record)
1572 {
1573   const char *p;
1574
1575   for (p = record->documents;
1576        p < record->documents + DOC_LINE_LENGTH * record->n_lines;
1577        p += DOC_LINE_LENGTH)
1578     {
1579       struct substring line;
1580
1581       line = recode_substring_pool ("UTF-8", dict_get_encoding (dict),
1582                                     ss_buffer (p, DOC_LINE_LENGTH), NULL);
1583       ss_rtrim (&line, ss_cstr (" "));
1584       line.string[line.length] = '\0';
1585
1586       dict_add_document_line (dict, line.string, false);
1587
1588       ss_dealloc (&line);
1589     }
1590 }
1591
1592 /* Parses record type 7, subtype 3. */
1593 static bool
1594 parse_machine_integer_info (struct sfm_reader *r,
1595                             const struct sfm_extension_record *record,
1596                             struct any_read_info *info)
1597 {
1598   int float_representation, expected_float_format;
1599   int integer_representation, expected_integer_format;
1600
1601   /* Save version info. */
1602   info->version_major = parse_int (r, record->data, 0);
1603   info->version_minor = parse_int (r, record->data, 4);
1604   info->version_revision = parse_int (r, record->data, 8);
1605
1606   /* Check floating point format. */
1607   float_representation = parse_int (r, record->data, 16);
1608   if (r->float_format == FLOAT_IEEE_DOUBLE_BE
1609       || r->float_format == FLOAT_IEEE_DOUBLE_LE)
1610     expected_float_format = 1;
1611   else if (r->float_format == FLOAT_Z_LONG)
1612     expected_float_format = 2;
1613   else if (r->float_format == FLOAT_VAX_G || r->float_format == FLOAT_VAX_D)
1614     expected_float_format = 3;
1615   else
1616     NOT_REACHED ();
1617   if (float_representation != expected_float_format)
1618     {
1619       sys_error (r, record->pos,
1620                  _("Floating-point representation indicated by "
1621                    "system file (%d) differs from expected (%d)."),
1622                  float_representation, expected_float_format);
1623       return false;
1624     }
1625
1626   /* Check integer format. */
1627   integer_representation = parse_int (r, record->data, 24);
1628   if (r->integer_format == INTEGER_MSB_FIRST)
1629     expected_integer_format = 1;
1630   else if (r->integer_format == INTEGER_LSB_FIRST)
1631     expected_integer_format = 2;
1632   else
1633     NOT_REACHED ();
1634   if (integer_representation != expected_integer_format)
1635     sys_warn (r, record->pos,
1636               _("Integer format indicated by system file (%d) "
1637                 "differs from expected (%d)."),
1638               integer_representation, expected_integer_format);
1639
1640   return true;
1641 }
1642
1643 /* Parses record type 7, subtype 4. */
1644 static void
1645 parse_machine_float_info (struct sfm_reader *r,
1646                           const struct sfm_extension_record *record)
1647 {
1648   double sysmis = parse_float (r, record->data, 0);
1649   double highest = parse_float (r, record->data, 8);
1650   double lowest = parse_float (r, record->data, 16);
1651
1652   if (sysmis != SYSMIS)
1653     sys_warn (r, record->pos,
1654               _("File specifies unexpected value %g (%a) as %s, "
1655                 "instead of %g (%a)."),
1656               sysmis, sysmis, "SYSMIS", SYSMIS, SYSMIS);
1657
1658   if (highest != HIGHEST)
1659     sys_warn (r, record->pos,
1660               _("File specifies unexpected value %g (%a) as %s, "
1661                 "instead of %g (%a)."),
1662               highest, highest, "HIGHEST", HIGHEST, HIGHEST);
1663
1664   /* SPSS before version 21 used a unique value just bigger than SYSMIS as
1665      LOWEST.  SPSS 21 uses SYSMIS for LOWEST, which is OK because LOWEST only
1666      appears in a context (missing values) where SYSMIS cannot. */
1667   if (lowest != LOWEST && lowest != SYSMIS)
1668     sys_warn (r, record->pos,
1669               _("File specifies unexpected value %g (%a) as %s, "
1670                 "instead of %g (%a) or %g (%a)."),
1671               lowest, lowest, "LOWEST", LOWEST, LOWEST, SYSMIS, SYSMIS);
1672 }
1673
1674 /* Parses record type 7, subtype 10. */
1675 static void
1676 parse_extra_product_info (struct sfm_reader *r,
1677                           const struct sfm_extension_record *record,
1678                           struct any_read_info *info)
1679 {
1680   struct text_record *text;
1681
1682   text = open_text_record (r, record, true);
1683   info->product_ext = fix_line_ends (text_get_all (text));
1684   close_text_record (r, text);
1685 }
1686
1687 /* Parses record type 7, subtype 7 or 19. */
1688 static void
1689 parse_mrsets (struct sfm_reader *r, const struct sfm_extension_record *record,
1690               size_t *allocated_mrsets)
1691 {
1692   struct text_record *text;
1693
1694   text = open_text_record (r, record, false);
1695   for (;;)
1696     {
1697       struct sfm_mrset *mrset = NULL;
1698       size_t allocated_vars = 0;
1699       char delimiter = '4';
1700
1701       /* Skip extra line feeds if present. */
1702       while (text_match (text, '\n'))
1703         continue;
1704
1705       if (r->n_mrsets >= *allocated_mrsets)
1706         r->mrsets = pool_2nrealloc (r->pool, r->mrsets, allocated_mrsets,
1707                                     sizeof *r->mrsets);
1708       mrset = &r->mrsets[r->n_mrsets];
1709       memset(mrset, 0, sizeof *mrset);
1710
1711       mrset->name = text_get_token (text, ss_cstr ("="), NULL);
1712       if (mrset->name == NULL)
1713         break;
1714
1715       if (text_match (text, 'C'))
1716         {
1717           mrset->type = MRSET_MC;
1718           if (!text_match (text, ' '))
1719             {
1720               sys_warn (r, record->pos,
1721                         _("Missing space following `%c' at offset %zu "
1722                           "in MRSETS record."), 'C', text_pos (text));
1723               break;
1724             }
1725         }
1726       else if (text_match (text, 'D'))
1727         {
1728           mrset->type = MRSET_MD;
1729           mrset->cat_source = MRSET_VARLABELS;
1730         }
1731       else if (text_match (text, 'E'))
1732         {
1733           char *number;
1734
1735           mrset->type = MRSET_MD;
1736           mrset->cat_source = MRSET_COUNTEDVALUES;
1737           if (!text_match (text, ' '))
1738             {
1739               sys_warn (r, record->pos,
1740                         _("Missing space following `%c' at offset %zu "
1741                           "in MRSETS record."), 'E',  text_pos (text));
1742               break;
1743             }
1744
1745           number = text_get_token (text, ss_cstr (" "), NULL);
1746           if (!number)
1747             sys_warn (r, record->pos,
1748                       _("Missing label source value "
1749                         "following `E' at offset %zu in MRSETS record."),
1750                       text_pos (text));
1751           else if (!strcmp (number, "11"))
1752             mrset->label_from_var_label = true;
1753           else if (strcmp (number, "1"))
1754             sys_warn (r, record->pos,
1755                       _("Unexpected label source value following `E' "
1756                         "at offset %zu in MRSETS record."),
1757                       text_pos (text));
1758         }
1759       else
1760         {
1761           sys_warn (r, record->pos,
1762                     _("Missing `C', `D', or `E' at offset %zu "
1763                       "in MRSETS record."),
1764                     text_pos (text));
1765           break;
1766         }
1767
1768       if (mrset->type == MRSET_MD)
1769         {
1770           mrset->counted = text_parse_counted_string (r, text);
1771           if (mrset->counted == NULL)
1772             break;
1773         }
1774
1775       mrset->label = text_parse_counted_string (r, text);
1776       if (mrset->label == NULL)
1777         break;
1778
1779       allocated_vars = 0;
1780       do
1781         {
1782           const char *var;
1783
1784           var = text_get_token (text, ss_cstr (" \n"), &delimiter);
1785           if (var == NULL)
1786             {
1787               if (delimiter != '\n')
1788                 sys_warn (r, record->pos,
1789                           _("Missing new-line parsing variable names "
1790                             "at offset %zu in MRSETS record."),
1791                           text_pos (text));
1792               break;
1793             }
1794
1795           if (mrset->n_vars >= allocated_vars)
1796             mrset->vars = pool_2nrealloc (r->pool, mrset->vars,
1797                                           &allocated_vars,
1798                                           sizeof *mrset->vars);
1799           mrset->vars[mrset->n_vars++] = var;
1800         }
1801       while (delimiter != '\n');
1802
1803       r->n_mrsets++;
1804     }
1805   close_text_record (r, text);
1806 }
1807
1808 static void
1809 decode_mrsets (struct sfm_reader *r, struct dictionary *dict)
1810 {
1811   const struct sfm_mrset *s;
1812
1813   for (s = r->mrsets; s < &r->mrsets[r->n_mrsets]; s++)
1814     {
1815       struct stringi_set var_names;
1816       struct mrset *mrset;
1817       char *name;
1818       int width;
1819       size_t i;
1820
1821       name = recode_string ("UTF-8", r->encoding, s->name, -1);
1822       if (!mrset_is_valid_name (name, dict_get_encoding (dict), false))
1823         {
1824           sys_warn (r, -1, _("Invalid multiple response set name `%s'."),
1825                     name);
1826           free (name);
1827           continue;
1828         }
1829
1830       mrset = xzalloc (sizeof *mrset);
1831       mrset->name = name;
1832       mrset->type = s->type;
1833       mrset->cat_source = s->cat_source;
1834       mrset->label_from_var_label = s->label_from_var_label;
1835       if (s->label[0] != '\0')
1836         mrset->label = recode_string ("UTF-8", r->encoding, s->label, -1);
1837
1838       stringi_set_init (&var_names);
1839       mrset->vars = xmalloc (s->n_vars * sizeof *mrset->vars);
1840       width = INT_MAX;
1841       for (i = 0; i < s->n_vars; i++)
1842         {
1843           struct variable *var;
1844           char *var_name;
1845
1846           var_name = recode_string ("UTF-8", r->encoding, s->vars[i], -1);
1847
1848           var = dict_lookup_var (dict, var_name);
1849           if (var == NULL)
1850             {
1851               free (var_name);
1852               continue;
1853             }
1854           if (!stringi_set_insert (&var_names, var_name))
1855             {
1856               sys_warn (r, -1,
1857                         _("MRSET %s contains duplicate variable name %s."),
1858                         mrset->name, var_name);
1859               free (var_name);
1860               continue;
1861             }
1862           free (var_name);
1863
1864           if (mrset->label == NULL && mrset->label_from_var_label
1865               && var_has_label (var))
1866             mrset->label = xstrdup (var_get_label (var));
1867
1868           if (mrset->n_vars
1869               && var_get_type (var) != var_get_type (mrset->vars[0]))
1870             {
1871               sys_warn (r, -1,
1872                         _("MRSET %s contains both string and "
1873                           "numeric variables."), mrset->name);
1874               continue;
1875             }
1876           width = MIN (width, var_get_width (var));
1877
1878           mrset->vars[mrset->n_vars++] = var;
1879         }
1880
1881       if (mrset->n_vars < 2)
1882         {
1883           if (mrset->n_vars == 0)
1884             sys_warn (r, -1, _("MRSET %s has no variables."), mrset->name);
1885           else
1886             sys_warn (r, -1, _("MRSET %s has only one variable."),
1887                       mrset->name);
1888           mrset_destroy (mrset);
1889           stringi_set_destroy (&var_names);
1890           continue;
1891         }
1892
1893       if (mrset->type == MRSET_MD)
1894         {
1895           mrset->width = width;
1896           value_init (&mrset->counted, width);
1897           if (width == 0)
1898             mrset->counted.f = c_strtod (s->counted, NULL);
1899           else
1900             value_copy_str_rpad (&mrset->counted, width,
1901                                  (const uint8_t *) s->counted, ' ');
1902         }
1903
1904       dict_add_mrset (dict, mrset);
1905       stringi_set_destroy (&var_names);
1906     }
1907 }
1908
1909 /* Read record type 7, subtype 11, which specifies how variables
1910    should be displayed in GUI environments. */
1911 static void
1912 parse_display_parameters (struct sfm_reader *r,
1913                          const struct sfm_extension_record *record,
1914                          struct dictionary *dict)
1915 {
1916   bool includes_width;
1917   bool warned = false;
1918   size_t n_vars;
1919   size_t ofs;
1920   size_t i;
1921
1922   n_vars = dict_get_var_cnt (dict);
1923   if (record->count == 3 * n_vars)
1924     includes_width = true;
1925   else if (record->count == 2 * n_vars)
1926     includes_width = false;
1927   else
1928     {
1929       sys_warn (r, record->pos,
1930                 _("Extension 11 has bad count %u (for %zu variables)."),
1931                 record->count, n_vars);
1932       return;
1933     }
1934
1935   ofs = 0;
1936   for (i = 0; i < n_vars; ++i)
1937     {
1938       struct variable *v = dict_get_var (dict, i);
1939       int measure, width, align;
1940
1941       measure = parse_int (r, record->data, ofs);
1942       ofs += 4;
1943
1944       if (includes_width)
1945         {
1946           width = parse_int (r, record->data, ofs);
1947           ofs += 4;
1948         }
1949       else
1950         width = 0;
1951
1952       align = parse_int (r, record->data, ofs);
1953       ofs += 4;
1954
1955       /* SPSS sometimes seems to set variables' measure to zero. */
1956       if (0 == measure)
1957         measure = 1;
1958
1959       if (measure < 1 || measure > 3 || align < 0 || align > 2)
1960         {
1961           if (!warned)
1962             sys_warn (r, record->pos,
1963                       _("Invalid variable display parameters for variable "
1964                         "%zu (%s).  Default parameters substituted."),
1965                       i, var_get_name (v));
1966           warned = true;
1967           continue;
1968         }
1969
1970       var_set_measure (v, (measure == 1 ? MEASURE_NOMINAL
1971                            : measure == 2 ? MEASURE_ORDINAL
1972                            : MEASURE_SCALE));
1973       var_set_alignment (v, (align == 0 ? ALIGN_LEFT
1974                              : align == 1 ? ALIGN_RIGHT
1975                              : ALIGN_CENTRE));
1976
1977       /* Older versions (SPSS 9.0) sometimes set the display
1978          width to zero.  This causes confusion in the GUI, so
1979          only set the width if it is nonzero. */
1980       if (width > 0)
1981         var_set_display_width (v, width);
1982     }
1983 }
1984
1985 static void
1986 rename_var_and_save_short_names (struct sfm_reader *r, off_t pos,
1987                                  struct dictionary *dict,
1988                                  struct variable *var, const char *new_name)
1989 {
1990   size_t n_short_names;
1991   char **short_names;
1992   size_t i;
1993
1994   /* Renaming a variable may clear its short names, but we
1995      want to retain them, so we save them and re-set them
1996      afterward. */
1997   n_short_names = var_get_short_name_cnt (var);
1998   short_names = xnmalloc (n_short_names, sizeof *short_names);
1999   for (i = 0; i < n_short_names; i++)
2000     {
2001       const char *s = var_get_short_name (var, i);
2002       short_names[i] = s != NULL ? xstrdup (s) : NULL;
2003     }
2004
2005   /* Set long name. */
2006   if (!dict_try_rename_var (dict, var, new_name))
2007     sys_warn (r, pos, _("Duplicate long variable name `%s'."), new_name);
2008
2009   /* Restore short names. */
2010   for (i = 0; i < n_short_names; i++)
2011     {
2012       var_set_short_name (var, i, short_names[i]);
2013       free (short_names[i]);
2014     }
2015   free (short_names);
2016 }
2017
2018 /* Parses record type 7, subtype 13, which gives the long name that corresponds
2019    to each short name.  Modifies variable names in DICT accordingly.  */
2020 static void
2021 parse_long_var_name_map (struct sfm_reader *r,
2022                          const struct sfm_extension_record *record,
2023                          struct dictionary *dict)
2024 {
2025   struct text_record *text;
2026   struct variable *var;
2027   char *long_name;
2028
2029   if (record == NULL)
2030     {
2031       /* There are no long variable names.  Use the short variable names,
2032          converted to lowercase, as the long variable names. */
2033       size_t i;
2034
2035       for (i = 0; i < dict_get_var_cnt (dict); i++)
2036         {
2037           struct variable *var = dict_get_var (dict, i);
2038           char *new_name;
2039
2040           new_name = utf8_to_lower (var_get_name (var));
2041           rename_var_and_save_short_names (r, -1, dict, var, new_name);
2042           free (new_name);
2043         }
2044
2045       return;
2046     }
2047
2048   /* Rename each of the variables, one by one.  (In a correctly constructed
2049      system file, this cannot create any intermediate duplicate variable names,
2050      because all of the new variable names are longer than any of the old
2051      variable names and thus there cannot be any overlaps.) */
2052   text = open_text_record (r, record, true);
2053   while (read_variable_to_value_pair (r, dict, text, &var, &long_name))
2054     {
2055       /* Validate long name. */
2056       if (!dict_id_is_valid (dict, long_name, false)
2057           || long_name[0] == '$' || long_name[0] == '#')
2058         {
2059           sys_warn (r, record->pos,
2060                     _("Long variable mapping from %s to invalid "
2061                       "variable name `%s'."),
2062                     var_get_name (var), long_name);
2063           continue;
2064         }
2065
2066       rename_var_and_save_short_names (r, record->pos, dict, var, long_name);
2067     }
2068   close_text_record (r, text);
2069 }
2070
2071 /* Reads record type 7, subtype 14, which gives the real length
2072    of each very long string.  Rearranges DICT accordingly. */
2073 static bool
2074 parse_long_string_map (struct sfm_reader *r,
2075                        const struct sfm_extension_record *record,
2076                        struct dictionary *dict)
2077 {
2078   struct text_record *text;
2079   struct variable *var;
2080   char *length_s;
2081
2082   text = open_text_record (r, record, true);
2083   while (read_variable_to_value_pair (r, dict, text, &var, &length_s))
2084     {
2085       size_t idx = var_get_dict_index (var);
2086       long int length;
2087       int segment_cnt;
2088       int i;
2089
2090       /* Get length. */
2091       length = strtol (length_s, NULL, 10);
2092       if (length < 1 || length > MAX_STRING)
2093         {
2094           sys_warn (r, record->pos,
2095                     _("%s listed as string of invalid length %s "
2096                       "in very long string record."),
2097                     var_get_name (var), length_s);
2098           continue;
2099         }
2100
2101       /* Check segments. */
2102       segment_cnt = sfm_width_to_segments (length);
2103       if (segment_cnt == 1)
2104         {
2105           sys_warn (r, record->pos,
2106                     _("%s listed in very long string record with width %s, "
2107                       "which requires only one segment."),
2108                     var_get_name (var), length_s);
2109           continue;
2110         }
2111       if (idx + segment_cnt > dict_get_var_cnt (dict))
2112         {
2113           sys_error (r, record->pos,
2114                      _("Very long string %s overflows dictionary."),
2115                      var_get_name (var));
2116           return false;
2117         }
2118
2119       /* Get the short names from the segments and check their
2120          lengths. */
2121       for (i = 0; i < segment_cnt; i++)
2122         {
2123           struct variable *seg = dict_get_var (dict, idx + i);
2124           int alloc_width = sfm_segment_alloc_width (length, i);
2125           int width = var_get_width (seg);
2126
2127           if (i > 0)
2128             var_set_short_name (var, i, var_get_short_name (seg, 0));
2129           if (ROUND_UP (width, 8) != ROUND_UP (alloc_width, 8))
2130             {
2131               sys_error (r, record->pos,
2132                          _("Very long string with width %ld has segment %d "
2133                            "of width %d (expected %d)."),
2134                          length, i, width, alloc_width);
2135               return false;
2136             }
2137         }
2138       dict_delete_consecutive_vars (dict, idx + 1, segment_cnt - 1);
2139       var_set_width (var, length);
2140     }
2141   close_text_record (r, text);
2142   dict_compact_values (dict);
2143
2144   return true;
2145 }
2146
2147 #define MAX_LABEL_WARNINGS 5
2148
2149 /* Displays a warning for offset OFFSET in the file. */
2150 static void
2151 value_label_warning (struct sfm_reader *r, off_t offset, int *n_label_warnings,
2152                      const char *format, ...)
2153 {
2154   if (++*n_label_warnings > MAX_LABEL_WARNINGS)
2155     return;
2156
2157   va_list args;
2158
2159   va_start (args, format);
2160   sys_msg (r, offset, MW, format, args);
2161   va_end (args);
2162 }
2163
2164 #define MAX_LABEL_WARNINGS 5
2165
2166 static void
2167 parse_one_value_label_set (struct sfm_reader *r, struct dictionary *dict,
2168                            const struct sfm_var_record *var_recs,
2169                            size_t n_var_recs,
2170                            const struct sfm_value_label_record *record,
2171                            int *n_label_warnings)
2172 {
2173   char **utf8_labels
2174     = pool_nmalloc (r->pool, record->n_labels, sizeof *utf8_labels);
2175   for (size_t i = 0; i < record->n_labels; i++)
2176     utf8_labels[i] = recode_string_pool ("UTF-8", dict_get_encoding (dict),
2177                                          record->labels[i].label, -1,
2178                                          r->pool);
2179
2180   struct variable **vars = pool_nmalloc (r->pool,
2181                                          record->n_vars, sizeof *vars);
2182   unsigned int n_vars = 0;
2183   for (size_t i = 0; i < record->n_vars; i++)
2184     {
2185       int idx = record->vars[i];
2186       if (idx < 1 || idx > n_var_recs)
2187         {
2188           value_label_warning (
2189             r, record->pos, n_label_warnings,
2190             _("Value label variable index %d not in valid range 1...%zu."),
2191             idx, n_var_recs);
2192           continue;
2193         }
2194
2195       const struct sfm_var_record *rec = &var_recs[idx - 1];
2196       if (rec->var == NULL)
2197         {
2198           value_label_warning (
2199             r, record->pos, n_label_warnings,
2200             _("Value label variable index %d "
2201               "refers to long string continuation."), idx);
2202           continue;
2203         }
2204
2205       vars[n_vars++] = rec->var;
2206     }
2207   if (!n_vars)
2208     return;
2209
2210   for (size_t i = 1; i < n_vars; i++)
2211     if (var_get_type (vars[i]) != var_get_type (vars[0]))
2212       {
2213         value_label_warning (
2214           r, record->pos, n_label_warnings,
2215           _("Variables associated with value label are not all of "
2216             "identical type.  Variable %s is %s, but variable "
2217             "%s is %s."),
2218           var_get_name (vars[0]),
2219           var_is_numeric (vars[0]) ? _("numeric") : _("string"),
2220           var_get_name (vars[i]),
2221           var_is_numeric (vars[i]) ? _("numeric") : _("string"));
2222         return;
2223       }
2224
2225   for (size_t i = 0; i < n_vars; i++)
2226     {
2227       struct variable *var = vars[i];
2228       int width = var_get_width (var);
2229       if (width > 8)
2230         {
2231           value_label_warning (
2232             r, record->pos, n_label_warnings,
2233             _("Value labels may not be added to long string "
2234               "variables (e.g. %s) using records types 3 and 4."),
2235             var_get_name (var));
2236           continue;
2237         }
2238
2239       for (size_t j = 0; j < record->n_labels; j++)
2240         {
2241           struct sfm_value_label *label = &record->labels[j];
2242           union value value;
2243
2244           value_init (&value, width);
2245           if (width == 0)
2246             value.f = parse_float (r, label->value, 0);
2247           else
2248             memcpy (value.s, label->value, width);
2249
2250           if (!var_add_value_label (var, &value, utf8_labels[j]))
2251             {
2252               if (r->written_by_readstat)
2253                 {
2254                   /* Ignore the problem.  ReadStat is buggy and emits value
2255                      labels whose values are longer than string variables'
2256                      widths, that are identical in the actual width of the
2257                      variable, e.g. both values "ABC123" and "ABC456" for a
2258                      string variable with width 3. */
2259                 }
2260               else if (var_is_numeric (var))
2261                 value_label_warning (r, record->pos, n_label_warnings,
2262                                      _("Duplicate value label for %g on %s."),
2263                                      value.f, var_get_name (var));
2264               else
2265                 value_label_warning (
2266                   r, record->pos, n_label_warnings,
2267                   _("Duplicate value label for `%.*s' on %s."),
2268                   width, value.s, var_get_name (var));
2269             }
2270
2271           value_destroy (&value, width);
2272         }
2273     }
2274
2275   pool_free (r->pool, vars);
2276   for (size_t i = 0; i < record->n_labels; i++)
2277     pool_free (r->pool, utf8_labels[i]);
2278   pool_free (r->pool, utf8_labels);
2279 }
2280
2281 static void
2282 parse_value_labels (struct sfm_reader *r, struct dictionary *dict)
2283 {
2284   int n_label_warnings = 0;
2285   for (size_t i = 0; i < r->n_labels; i++)
2286     parse_one_value_label_set (r, dict, r->vars, r->n_vars, &r->labels[i],
2287                                &n_label_warnings);
2288   if (n_label_warnings > MAX_LABEL_WARNINGS)
2289       sys_warn (r, -1,
2290                 _("Suppressed %d additional warnings for value labels."),
2291                 n_label_warnings - MAX_LABEL_WARNINGS);
2292 }
2293
2294 static struct variable *
2295 parse_weight_var (struct sfm_reader *r,
2296                   const struct sfm_var_record *var_recs, size_t n_var_recs,
2297                   int idx)
2298 {
2299   off_t offset = 76;            /* Offset to variable index in header. */
2300
2301   if (idx < 1 || idx > n_var_recs)
2302     {
2303       sys_warn (r, offset,
2304                 _("Weight variable index %d not in valid range 1...%zu.  "
2305                   "Treating file as unweighted."),
2306                 idx, n_var_recs);
2307       return NULL;
2308     }
2309
2310   const struct sfm_var_record *rec = &var_recs[idx - 1];
2311   if (rec->var == NULL)
2312     {
2313       sys_warn (r, offset,
2314                 _("Weight variable index %d refers to long string "
2315                   "continuation.  Treating file as unweighted."), idx);
2316       return NULL;
2317     }
2318
2319   struct variable *weight_var = rec->var;
2320   if (!var_is_numeric (weight_var))
2321     {
2322       sys_warn (r, offset, _("Ignoring string variable `%s' set "
2323                              "as weighting variable."),
2324                 var_get_name (weight_var));
2325       return NULL;
2326     }
2327
2328   return weight_var;
2329 }
2330
2331 /* Parses a set of custom attributes from TEXT into ATTRS.
2332    ATTRS may be a null pointer, in which case the attributes are
2333    read but discarded. */
2334 static void
2335 parse_attributes (struct sfm_reader *r, struct text_record *text,
2336                   struct attrset *attrs)
2337 {
2338   do
2339     {
2340       struct attribute *attr;
2341       char *key;
2342       int index;
2343
2344       /* Parse the key. */
2345       key = text_get_token (text, ss_cstr ("("), NULL);
2346       if (key == NULL)
2347         return;
2348
2349       attr = attribute_create (key);
2350       for (index = 1; ; index++)
2351         {
2352           /* Parse the value. */
2353           char *value;
2354           size_t length;
2355
2356           value = text_get_token (text, ss_cstr ("\n"), NULL);
2357           if (value == NULL)
2358             {
2359               text_warn (r, text, _("Error parsing attribute value %s[%d]."),
2360                          key, index);
2361               break;
2362             }
2363
2364           length = strlen (value);
2365           if (length >= 2 && value[0] == '\'' && value[length - 1] == '\'')
2366             {
2367               value[length - 1] = '\0';
2368               attribute_add_value (attr, value + 1);
2369             }
2370           else
2371             {
2372               text_warn (r, text,
2373                          _("Attribute value %s[%d] is not quoted: %s."),
2374                          key, index, value);
2375               attribute_add_value (attr, value);
2376             }
2377
2378           /* Was this the last value for this attribute? */
2379           if (text_match (text, ')'))
2380             break;
2381         }
2382       if (attrs != NULL && attribute_get_n_values (attr) > 0)
2383         {
2384           if (!attrset_try_add (attrs, attr))
2385             {
2386               text_warn (r, text, _("Duplicate attribute %s."),
2387                          attribute_get_name (attr));
2388               attribute_destroy (attr);
2389             }
2390         }
2391       else
2392         attribute_destroy (attr);
2393     }
2394   while (!text_match (text, '/'));
2395 }
2396
2397 /* Reads record type 7, subtype 17, which lists custom
2398    attributes on the data file.  */
2399 static void
2400 parse_data_file_attributes (struct sfm_reader *r,
2401                             const struct sfm_extension_record *record,
2402                             struct dictionary *dict)
2403 {
2404   struct text_record *text = open_text_record (r, record, true);
2405   parse_attributes (r, text, dict_get_attributes (dict));
2406   close_text_record (r, text);
2407 }
2408
2409 /* Parses record type 7, subtype 18, which lists custom
2410    attributes on individual variables.  */
2411 static void
2412 parse_variable_attributes (struct sfm_reader *r,
2413                            const struct sfm_extension_record *record,
2414                            struct dictionary *dict)
2415 {
2416   struct text_record *text;
2417   struct variable *var;
2418
2419   text = open_text_record (r, record, true);
2420   while (text_read_variable_name (r, dict, text, ss_cstr (":"), &var))
2421     parse_attributes (r, text, var != NULL ? var_get_attributes (var) : NULL);
2422   close_text_record (r, text);
2423 }
2424
2425 static void
2426 assign_variable_roles (struct sfm_reader *r, struct dictionary *dict)
2427 {
2428   size_t n_warnings = 0;
2429   size_t i;
2430
2431   for (i = 0; i < dict_get_var_cnt (dict); i++)
2432     {
2433       struct variable *var = dict_get_var (dict, i);
2434       struct attrset *attrs = var_get_attributes (var);
2435       const struct attribute *attr = attrset_lookup (attrs, "$@Role");
2436       if (attr != NULL && attribute_get_n_values (attr) > 0)
2437         {
2438           int value = atoi (attribute_get_value (attr, 0));
2439           enum var_role role;
2440
2441           switch (value)
2442             {
2443             case 0:
2444               role = ROLE_INPUT;
2445               break;
2446
2447             case 1:
2448               role = ROLE_TARGET;
2449               break;
2450
2451             case 2:
2452               role = ROLE_BOTH;
2453               break;
2454
2455             case 3:
2456               role = ROLE_NONE;
2457               break;
2458
2459             case 4:
2460               role = ROLE_PARTITION;
2461               break;
2462
2463             case 5:
2464               role = ROLE_SPLIT;
2465               break;
2466
2467             default:
2468               role = ROLE_INPUT;
2469               if (n_warnings++ == 0)
2470                 sys_warn (r, -1, _("Invalid role for variable %s."),
2471                           var_get_name (var));
2472             }
2473
2474           var_set_role (var, role);
2475         }
2476     }
2477
2478   if (n_warnings > 1)
2479     sys_warn (r, -1, _("%zu other variables had invalid roles."),
2480               n_warnings - 1);
2481 }
2482
2483 static bool
2484 check_overflow (struct sfm_reader *r,
2485                 const struct sfm_extension_record *record,
2486                 size_t ofs, size_t length)
2487 {
2488   size_t end = record->size * record->count;
2489   if (length >= end || ofs + length > end)
2490     {
2491       sys_warn (r, record->pos + end,
2492                 _("Extension record subtype %d ends unexpectedly."),
2493                 record->subtype);
2494       return false;
2495     }
2496   return true;
2497 }
2498
2499 static void
2500 parse_long_string_value_labels (struct sfm_reader *r,
2501                                 const struct sfm_extension_record *record,
2502                                 struct dictionary *dict)
2503 {
2504   const char *dict_encoding = dict_get_encoding (dict);
2505   size_t end = record->size * record->count;
2506   size_t ofs = 0;
2507
2508   while (ofs < end)
2509     {
2510       char *var_name;
2511       size_t n_labels, i;
2512       struct variable *var;
2513       union value value;
2514       int var_name_len;
2515       int width;
2516
2517       /* Parse variable name length. */
2518       if (!check_overflow (r, record, ofs, 4))
2519         return;
2520       var_name_len = parse_int (r, record->data, ofs);
2521       ofs += 4;
2522
2523       /* Parse variable name, width, and number of labels. */
2524       if (!check_overflow (r, record, ofs, var_name_len)
2525           || !check_overflow (r, record, ofs, var_name_len + 8))
2526         return;
2527       var_name = recode_string_pool ("UTF-8", dict_encoding,
2528                                      (const char *) record->data + ofs,
2529                                      var_name_len, r->pool);
2530       width = parse_int (r, record->data, ofs + var_name_len);
2531       n_labels = parse_int (r, record->data, ofs + var_name_len + 4);
2532       ofs += var_name_len + 8;
2533
2534       /* Look up 'var' and validate. */
2535       var = dict_lookup_var (dict, var_name);
2536       if (var == NULL)
2537         sys_warn (r, record->pos + ofs,
2538                   _("Ignoring long string value label record for "
2539                     "unknown variable %s."), var_name);
2540       else if (var_is_numeric (var))
2541         {
2542           sys_warn (r, record->pos + ofs,
2543                     _("Ignoring long string value label record for "
2544                       "numeric variable %s."), var_name);
2545           var = NULL;
2546         }
2547       else if (width != var_get_width (var))
2548         {
2549           sys_warn (r, record->pos + ofs,
2550                     _("Ignoring long string value label record for variable "
2551                       "%s because the record's width (%d) does not match the "
2552                       "variable's width (%d)."),
2553                     var_name, width, var_get_width (var));
2554           var = NULL;
2555         }
2556
2557       /* Parse values. */
2558       value_init_pool (r->pool, &value, width);
2559       for (i = 0; i < n_labels; i++)
2560         {
2561           size_t value_length, label_length;
2562           bool skip = var == NULL;
2563
2564           /* Parse value length. */
2565           if (!check_overflow (r, record, ofs, 4))
2566             return;
2567           value_length = parse_int (r, record->data, ofs);
2568           ofs += 4;
2569
2570           /* Parse value. */
2571           if (!check_overflow (r, record, ofs, value_length))
2572             return;
2573           if (!skip)
2574             {
2575               if (value_length == width)
2576                 memcpy (value.s, (const uint8_t *) record->data + ofs, width);
2577               else
2578                 {
2579                   sys_warn (r, record->pos + ofs,
2580                             _("Ignoring long string value label %zu for "
2581                               "variable %s, with width %d, that has bad value "
2582                               "width %zu."),
2583                             i, var_get_name (var), width, value_length);
2584                   skip = true;
2585                 }
2586             }
2587           ofs += value_length;
2588
2589           /* Parse label length. */
2590           if (!check_overflow (r, record, ofs, 4))
2591             return;
2592           label_length = parse_int (r, record->data, ofs);
2593           ofs += 4;
2594
2595           /* Parse label. */
2596           if (!check_overflow (r, record, ofs, label_length))
2597             return;
2598           if (!skip)
2599             {
2600               char *label;
2601
2602               label = recode_string_pool ("UTF-8", dict_encoding,
2603                                           (const char *) record->data + ofs,
2604                                           label_length, r->pool);
2605               if (!var_add_value_label (var, &value, label))
2606                 sys_warn (r, record->pos + ofs,
2607                           _("Duplicate value label for `%.*s' on %s."),
2608                           width, value.s, var_get_name (var));
2609               pool_free (r->pool, label);
2610             }
2611           ofs += label_length;
2612         }
2613     }
2614 }
2615
2616 static void
2617 parse_long_string_missing_values (struct sfm_reader *r,
2618                                   const struct sfm_extension_record *record,
2619                                   struct dictionary *dict)
2620 {
2621   const char *dict_encoding = dict_get_encoding (dict);
2622   size_t end = record->size * record->count;
2623   size_t ofs = 0;
2624
2625   while (ofs < end)
2626     {
2627       struct missing_values mv;
2628       char *var_name;
2629       struct variable *var;
2630       int n_missing_values;
2631       int var_name_len;
2632       size_t i;
2633
2634       /* Parse variable name length. */
2635       if (!check_overflow (r, record, ofs, 4))
2636         return;
2637       var_name_len = parse_int (r, record->data, ofs);
2638       ofs += 4;
2639
2640       /* Parse variable name. */
2641       if (!check_overflow (r, record, ofs, var_name_len)
2642           || !check_overflow (r, record, ofs, var_name_len + 1))
2643         return;
2644       var_name = recode_string_pool ("UTF-8", dict_encoding,
2645                                      (const char *) record->data + ofs,
2646                                      var_name_len, r->pool);
2647       ofs += var_name_len;
2648
2649       /* Parse number of missing values. */
2650       n_missing_values = ((const uint8_t *) record->data)[ofs];
2651       if (n_missing_values < 1 || n_missing_values > 3)
2652         sys_warn (r, record->pos + ofs,
2653                   _("Long string missing values record says variable %s "
2654                     "has %d missing values, but only 1 to 3 missing values "
2655                     "are allowed."),
2656                   var_name, n_missing_values);
2657       ofs++;
2658
2659       /* Look up 'var' and validate. */
2660       var = dict_lookup_var (dict, var_name);
2661       if (var == NULL)
2662         sys_warn (r, record->pos + ofs,
2663                   _("Ignoring long string missing value record for "
2664                     "unknown variable %s."), var_name);
2665       else if (var_is_numeric (var))
2666         {
2667           sys_warn (r, record->pos + ofs,
2668                     _("Ignoring long string missing value record for "
2669                       "numeric variable %s."), var_name);
2670           var = NULL;
2671         }
2672
2673       /* Parse values. */
2674       mv_init_pool (r->pool, &mv, var ? var_get_width (var) : 8);
2675       for (i = 0; i < n_missing_values; i++)
2676         {
2677           size_t value_length;
2678
2679           /* Parse value length. */
2680           if (!check_overflow (r, record, ofs, 4))
2681             return;
2682           value_length = parse_int (r, record->data, ofs);
2683           ofs += 4;
2684
2685           /* Parse value. */
2686           if (!check_overflow (r, record, ofs, value_length))
2687             return;
2688           if (var != NULL
2689               && i < 3
2690               && !mv_add_str (&mv, (const uint8_t *) record->data + ofs,
2691                               value_length))
2692             sys_warn (r, record->pos + ofs,
2693                       _("Ignoring long string missing value %zu for variable "
2694                         "%s, with width %d, that has bad value width %zu."),
2695                       i, var_get_name (var), var_get_width (var),
2696                       value_length);
2697           ofs += value_length;
2698         }
2699       if (var != NULL)
2700         var_set_missing_values (var, &mv);
2701     }
2702 }
2703 \f
2704 /* Case reader. */
2705
2706 static void partial_record (struct sfm_reader *);
2707
2708 static void read_error (struct casereader *, const struct sfm_reader *);
2709
2710 static bool read_case_number (struct sfm_reader *, double *);
2711 static int read_case_string (struct sfm_reader *, uint8_t *, size_t);
2712 static int read_opcode (struct sfm_reader *);
2713 static bool read_compressed_number (struct sfm_reader *, double *);
2714 static int read_compressed_string (struct sfm_reader *, uint8_t *);
2715 static int read_whole_strings (struct sfm_reader *, uint8_t *, size_t);
2716 static bool skip_whole_strings (struct sfm_reader *, size_t);
2717
2718 /* Reads and returns one case from READER's file.  Returns a null
2719    pointer if not successful. */
2720 static struct ccase *
2721 sys_file_casereader_read (struct casereader *reader, void *r_)
2722 {
2723   struct sfm_reader *r = r_;
2724   struct ccase *c;
2725   int retval;
2726   int i;
2727
2728   if (r->error || !r->sfm_var_cnt)
2729     return NULL;
2730
2731   c = case_create (r->proto);
2732
2733   for (i = 0; i < r->sfm_var_cnt; i++)
2734     {
2735       struct sfm_var *sv = &r->sfm_vars[i];
2736       union value *v = case_data_rw_idx (c, sv->case_index);
2737
2738       if (sv->var_width == 0)
2739         retval = read_case_number (r, &v->f);
2740       else
2741         {
2742           retval = read_case_string (r, v->s + sv->offset, sv->segment_width);
2743           if (retval == 1)
2744             {
2745               retval = skip_whole_strings (r, ROUND_DOWN (sv->padding, 8));
2746               if (retval == 0)
2747                 sys_error (r, r->pos, _("File ends in partial string value."));
2748             }
2749         }
2750
2751       if (retval != 1)
2752         goto eof;
2753     }
2754   return c;
2755
2756 eof:
2757   if (i != 0)
2758     partial_record (r);
2759   if (r->case_cnt != -1)
2760     read_error (reader, r);
2761   case_unref (c);
2762   return NULL;
2763 }
2764
2765 /* Issues an error that R ends in a partial record. */
2766 static void
2767 partial_record (struct sfm_reader *r)
2768 {
2769   sys_error (r, r->pos, _("File ends in partial case."));
2770 }
2771
2772 /* Issues an error that an unspecified error occurred SFM, and
2773    marks R tainted. */
2774 static void
2775 read_error (struct casereader *r, const struct sfm_reader *sfm)
2776 {
2777   msg (ME, _("Error reading case from file %s."), fh_get_name (sfm->fh));
2778   casereader_force_error (r);
2779 }
2780
2781 /* Reads a number from R and stores its value in *D.
2782    If R is compressed, reads a compressed number;
2783    otherwise, reads a number in the regular way.
2784    Returns true if successful, false if end of file is
2785    reached immediately. */
2786 static bool
2787 read_case_number (struct sfm_reader *r, double *d)
2788 {
2789   if (r->compression == ANY_COMP_NONE)
2790     {
2791       uint8_t number[8];
2792       if (!try_read_bytes (r, number, sizeof number))
2793         return false;
2794       float_convert (r->float_format, number, FLOAT_NATIVE_DOUBLE, d);
2795       return true;
2796     }
2797   else
2798     return read_compressed_number (r, d);
2799 }
2800
2801 /* Reads LENGTH string bytes from R into S.  Always reads a multiple of 8
2802    bytes; if LENGTH is not a multiple of 8, then extra bytes are read and
2803    discarded without being written to S.  Reads compressed strings if S is
2804    compressed.  Returns 1 if successful, 0 if end of file is reached
2805    immediately, or -1 for some kind of error. */
2806 static int
2807 read_case_string (struct sfm_reader *r, uint8_t *s, size_t length)
2808 {
2809   size_t whole = ROUND_DOWN (length, 8);
2810   size_t partial = length % 8;
2811
2812   if (whole)
2813     {
2814       int retval = read_whole_strings (r, s, whole);
2815       if (retval != 1)
2816         return retval;
2817     }
2818
2819   if (partial)
2820     {
2821       uint8_t bounce[8];
2822       int retval = read_whole_strings (r, bounce, sizeof bounce);
2823       if (retval == -1)
2824         return -1;
2825       else if (!retval)
2826         {
2827           if (whole)
2828             {
2829               partial_record (r);
2830               return -1;
2831             }
2832           return 0;
2833         }
2834       memcpy (s + whole, bounce, partial);
2835     }
2836
2837   return 1;
2838 }
2839
2840 /* Reads and returns the next compression opcode from R. */
2841 static int
2842 read_opcode (struct sfm_reader *r)
2843 {
2844   assert (r->compression != ANY_COMP_NONE);
2845   for (;;)
2846     {
2847       int opcode;
2848       if (r->opcode_idx >= sizeof r->opcodes)
2849         {
2850
2851           int retval = try_read_compressed_bytes (r, r->opcodes,
2852                                                   sizeof r->opcodes);
2853           if (retval != 1)
2854             return -1;
2855           r->opcode_idx = 0;
2856         }
2857       opcode = r->opcodes[r->opcode_idx++];
2858
2859       if (opcode != 0)
2860         return opcode;
2861     }
2862 }
2863
2864 /* Reads a compressed number from R and stores its value in D.
2865    Returns true if successful, false if end of file is
2866    reached immediately. */
2867 static bool
2868 read_compressed_number (struct sfm_reader *r, double *d)
2869 {
2870   int opcode = read_opcode (r);
2871   switch (opcode)
2872     {
2873     case -1:
2874     case 252:
2875       return false;
2876
2877     case 253:
2878       return read_compressed_float (r, d);
2879
2880     case 254:
2881       float_convert (r->float_format, "        ", FLOAT_NATIVE_DOUBLE, d);
2882       if (!r->corruption_warning)
2883         {
2884           r->corruption_warning = true;
2885           sys_warn (r, r->pos,
2886                     _("Possible compressed data corruption: "
2887                       "compressed spaces appear in numeric field."));
2888         }
2889       break;
2890
2891     case 255:
2892       *d = SYSMIS;
2893       break;
2894
2895     default:
2896       *d = opcode - r->bias;
2897       break;
2898     }
2899
2900   return true;
2901 }
2902
2903 /* Reads a compressed 8-byte string segment from R and stores it in DST. */
2904 static int
2905 read_compressed_string (struct sfm_reader *r, uint8_t *dst)
2906 {
2907   int opcode;
2908   int retval;
2909
2910   opcode = read_opcode (r);
2911   switch (opcode)
2912     {
2913     case -1:
2914     case 252:
2915       return 0;
2916
2917     case 253:
2918       retval = read_compressed_bytes (r, dst, 8);
2919       return retval == 1 ? 1 : -1;
2920
2921     case 254:
2922       memset (dst, ' ', 8);
2923       return 1;
2924
2925     default:
2926       {
2927         double value = opcode - r->bias;
2928         float_convert (FLOAT_NATIVE_DOUBLE, &value, r->float_format, dst);
2929         if (value == 0.0)
2930           {
2931             /* This has actually been seen "in the wild".  The submitter of the
2932                file that showed that the contents decoded as spaces, but they
2933                were at the end of the field so it's possible that the null
2934                bytes just acted as null terminators. */
2935           }
2936         else if (!r->corruption_warning)
2937           {
2938             r->corruption_warning = true;
2939             sys_warn (r, r->pos,
2940                       _("Possible compressed data corruption: "
2941                         "string contains compressed integer (opcode %d)."),
2942                       opcode);
2943           }
2944       }
2945       return 1;
2946     }
2947 }
2948
2949 /* Reads LENGTH string bytes from R into S.  LENGTH must be a multiple of 8.
2950    Reads compressed strings if S is compressed.  Returns 1 if successful, 0 if
2951    end of file is reached immediately, or -1 for some kind of error. */
2952 static int
2953 read_whole_strings (struct sfm_reader *r, uint8_t *s, size_t length)
2954 {
2955   assert (length % 8 == 0);
2956   if (r->compression == ANY_COMP_NONE)
2957     return try_read_bytes (r, s, length);
2958   else
2959     {
2960       size_t ofs;
2961
2962       for (ofs = 0; ofs < length; ofs += 8)
2963         {
2964           int retval = read_compressed_string (r, s + ofs);
2965           if (retval != 1)
2966             {
2967               if (ofs != 0)
2968                 {
2969                   partial_record (r);
2970                   return -1;
2971                 }
2972               return retval;
2973             }
2974           }
2975       return 1;
2976     }
2977 }
2978
2979 /* Skips LENGTH string bytes from R.
2980    LENGTH must be a multiple of 8.
2981    (LENGTH is also limited to 1024, but that's only because the
2982    current caller never needs more than that many bytes.)
2983    Returns true if successful, false if end of file is
2984    reached immediately. */
2985 static bool
2986 skip_whole_strings (struct sfm_reader *r, size_t length)
2987 {
2988   uint8_t buffer[1024];
2989   assert (length < sizeof buffer);
2990   return read_whole_strings (r, buffer, length);
2991 }
2992 \f
2993 /* Helpers for reading records that contain structured text
2994    strings. */
2995
2996 /* Maximum number of warnings to issue for a single text
2997    record. */
2998 #define MAX_TEXT_WARNINGS 5
2999
3000 /* State. */
3001 struct text_record
3002   {
3003     struct substring buffer;    /* Record contents. */
3004     off_t start;                /* Starting offset in file. */
3005     size_t pos;                 /* Current position in buffer. */
3006     int n_warnings;             /* Number of warnings issued or suppressed. */
3007     bool recoded;               /* Recoded into UTF-8? */
3008   };
3009
3010 static struct text_record *
3011 open_text_record (struct sfm_reader *r,
3012                   const struct sfm_extension_record *record,
3013                   bool recode_to_utf8)
3014 {
3015   struct text_record *text;
3016   struct substring raw;
3017
3018   text = pool_alloc (r->pool, sizeof *text);
3019   raw = ss_buffer (record->data, record->size * record->count);
3020   text->start = record->pos;
3021   text->buffer = (recode_to_utf8
3022                   ? recode_substring_pool ("UTF-8", r->encoding, raw, r->pool)
3023                   : raw);
3024   text->pos = 0;
3025   text->n_warnings = 0;
3026   text->recoded = recode_to_utf8;
3027
3028   return text;
3029 }
3030
3031 /* Closes TEXT, frees its storage, and issues a final warning
3032    about suppressed warnings if necessary. */
3033 static void
3034 close_text_record (struct sfm_reader *r, struct text_record *text)
3035 {
3036   if (text->n_warnings > MAX_TEXT_WARNINGS)
3037     sys_warn (r, -1, _("Suppressed %d additional related warnings."),
3038               text->n_warnings - MAX_TEXT_WARNINGS);
3039   if (text->recoded)
3040     pool_free (r->pool, ss_data (text->buffer));
3041 }
3042
3043 /* Reads a variable=value pair from TEXT.
3044    Looks up the variable in DICT and stores it into *VAR.
3045    Stores a null-terminated value into *VALUE. */
3046 static bool
3047 read_variable_to_value_pair (struct sfm_reader *r, struct dictionary *dict,
3048                              struct text_record *text,
3049                              struct variable **var, char **value)
3050 {
3051   for (;;)
3052     {
3053       if (!text_read_short_name (r, dict, text, ss_cstr ("="), var))
3054         return false;
3055
3056       *value = text_get_token (text, ss_buffer ("\t\0", 2), NULL);
3057       if (*value == NULL)
3058         return false;
3059
3060       text->pos += ss_span (ss_substr (text->buffer, text->pos, SIZE_MAX),
3061                             ss_buffer ("\t\0", 2));
3062
3063       if (*var != NULL)
3064         return true;
3065     }
3066 }
3067
3068 static bool
3069 text_read_variable_name (struct sfm_reader *r, struct dictionary *dict,
3070                          struct text_record *text, struct substring delimiters,
3071                          struct variable **var)
3072 {
3073   char *name;
3074
3075   name = text_get_token (text, delimiters, NULL);
3076   if (name == NULL)
3077     return false;
3078
3079   *var = dict_lookup_var (dict, name);
3080   if (*var != NULL)
3081     return true;
3082
3083   text_warn (r, text, _("Dictionary record refers to unknown variable %s."),
3084              name);
3085   return false;
3086 }
3087
3088
3089 static bool
3090 text_read_short_name (struct sfm_reader *r, struct dictionary *dict,
3091                       struct text_record *text, struct substring delimiters,
3092                       struct variable **var)
3093 {
3094   char *short_name = text_get_token (text, delimiters, NULL);
3095   if (short_name == NULL)
3096     return false;
3097
3098   *var = dict_lookup_var (dict, short_name);
3099   if (*var == NULL)
3100     text_warn (r, text, _("Dictionary record refers to unknown variable %s."),
3101                short_name);
3102   return true;
3103 }
3104
3105 /* Displays a warning for the current file position, limiting the
3106    number to MAX_TEXT_WARNINGS for TEXT. */
3107 static void
3108 text_warn (struct sfm_reader *r, struct text_record *text,
3109            const char *format, ...)
3110 {
3111   if (text->n_warnings++ < MAX_TEXT_WARNINGS)
3112     {
3113       va_list args;
3114
3115       va_start (args, format);
3116       sys_msg (r, text->start + text->pos, MW, format, args);
3117       va_end (args);
3118     }
3119 }
3120
3121 static char *
3122 text_get_token (struct text_record *text, struct substring delimiters,
3123                 char *delimiter)
3124 {
3125   struct substring token;
3126   char *end;
3127
3128   if (!ss_tokenize (text->buffer, delimiters, &text->pos, &token))
3129     {
3130       if (delimiter != NULL)
3131         *delimiter = ss_data (text->buffer)[text->pos-1];
3132       return NULL;
3133     }
3134
3135   end = &ss_data (token)[ss_length (token)];
3136   if (delimiter != NULL)
3137     *delimiter = *end;
3138   *end = '\0';
3139   return ss_data (token);
3140 }
3141
3142 /* Reads a integer value expressed in decimal, then a space, then a string that
3143    consists of exactly as many bytes as specified by the integer, then a space,
3144    from TEXT.  Returns the string, null-terminated, as a subset of TEXT's
3145    buffer (so the caller should not free the string). */
3146 static const char *
3147 text_parse_counted_string (struct sfm_reader *r, struct text_record *text)
3148 {
3149   size_t start;
3150   size_t n;
3151   char *s;
3152
3153   start = text->pos;
3154   n = 0;
3155   while (text->pos < text->buffer.length)
3156     {
3157       int c = text->buffer.string[text->pos];
3158       if (c < '0' || c > '9')
3159         break;
3160       n = (n * 10) + (c - '0');
3161       text->pos++;
3162     }
3163   if (text->pos >= text->buffer.length || start == text->pos)
3164     {
3165       sys_warn (r, text->start,
3166                 _("Expecting digit at offset %zu in MRSETS record."),
3167                 text->pos);
3168       return NULL;
3169     }
3170
3171   if (!text_match (text, ' '))
3172     {
3173       sys_warn (r, text->start,
3174                 _("Expecting space at offset %zu in MRSETS record."),
3175                 text->pos);
3176       return NULL;
3177     }
3178
3179   if (text->pos + n > text->buffer.length)
3180     {
3181       sys_warn (r, text->start,
3182                 _("%zu-byte string starting at offset %zu "
3183                   "exceeds record length %zu."),
3184                 n, text->pos, text->buffer.length);
3185       return NULL;
3186     }
3187
3188   s = &text->buffer.string[text->pos];
3189   if (s[n] != ' ')
3190     {
3191       sys_warn (r, text->start,
3192                 _("Expecting space at offset %zu following %zu-byte string."),
3193                 text->pos + n, n);
3194       return NULL;
3195     }
3196   s[n] = '\0';
3197   text->pos += n + 1;
3198   return s;
3199 }
3200
3201 static bool
3202 text_match (struct text_record *text, char c)
3203 {
3204   if (text->pos >= text->buffer.length)
3205     return false;
3206
3207   if (text->buffer.string[text->pos] == c)
3208     {
3209       text->pos++;
3210       return true;
3211     }
3212   else
3213     return false;
3214 }
3215
3216 /* Returns the current byte offset (as converted to UTF-8, if it was converted)
3217    inside the TEXT's string. */
3218 static size_t
3219 text_pos (const struct text_record *text)
3220 {
3221   return text->pos;
3222 }
3223
3224 static const char *
3225 text_get_all (const struct text_record *text)
3226 {
3227   return text->buffer.string;
3228 }
3229 \f
3230 /* Messages. */
3231
3232 /* Displays a corruption message. */
3233 static void
3234 sys_msg (struct sfm_reader *r, off_t offset,
3235          int class, const char *format, va_list args)
3236 {
3237   struct string text;
3238
3239   ds_init_empty (&text);
3240   if (offset >= 0)
3241     ds_put_format (&text, _("`%s' near offset 0x%llx: "),
3242                    fh_get_file_name (r->fh), (long long int) offset);
3243   else
3244     ds_put_format (&text, _("`%s': "), fh_get_file_name (r->fh));
3245   ds_put_vformat (&text, format, args);
3246
3247   struct msg m = {
3248     .category = msg_class_to_category (class),
3249     .severity = msg_class_to_severity (class),
3250     .text = ds_cstr (&text),
3251   };
3252   msg_emit (&m);
3253 }
3254
3255 /* Displays a warning for offset OFFSET in the file. */
3256 static void
3257 sys_warn (struct sfm_reader *r, off_t offset, const char *format, ...)
3258 {
3259   va_list args;
3260
3261   va_start (args, format);
3262   sys_msg (r, offset, MW, format, args);
3263   va_end (args);
3264 }
3265
3266 /* Displays an error for the current file position and marks it as in an error
3267    state. */
3268 static void
3269 sys_error (struct sfm_reader *r, off_t offset, const char *format, ...)
3270 {
3271   va_list args;
3272
3273   va_start (args, format);
3274   sys_msg (r, offset, ME, format, args);
3275   va_end (args);
3276
3277   r->error = true;
3278 }
3279 \f
3280 /* Reads BYTE_CNT bytes into BUF.
3281    Returns 1 if exactly BYTE_CNT bytes are successfully read.
3282    Returns -1 if an I/O error or a partial read occurs.
3283    Returns 0 for an immediate end-of-file and, if EOF_IS_OK is false, reports
3284    an error. */
3285 static inline int
3286 read_bytes_internal (struct sfm_reader *r, bool eof_is_ok,
3287                      void *buf, size_t byte_cnt)
3288 {
3289   size_t bytes_read = fread (buf, 1, byte_cnt, r->file);
3290   r->pos += bytes_read;
3291   if (bytes_read == byte_cnt)
3292     return 1;
3293   else if (ferror (r->file))
3294     {
3295       sys_error (r, r->pos, _("System error: %s."), strerror (errno));
3296       return -1;
3297     }
3298   else if (!eof_is_ok || bytes_read != 0)
3299     {
3300       sys_error (r, r->pos, _("Unexpected end of file."));
3301       return -1;
3302     }
3303   else
3304     return 0;
3305 }
3306
3307 /* Reads BYTE_CNT into BUF.
3308    Returns true if successful.
3309    Returns false upon I/O error or if end-of-file is encountered. */
3310 static bool
3311 read_bytes (struct sfm_reader *r, void *buf, size_t byte_cnt)
3312 {
3313   return read_bytes_internal (r, false, buf, byte_cnt) == 1;
3314 }
3315
3316 /* Reads BYTE_CNT bytes into BUF.
3317    Returns 1 if exactly BYTE_CNT bytes are successfully read.
3318    Returns 0 if an immediate end-of-file is encountered.
3319    Returns -1 if an I/O error or a partial read occurs. */
3320 static int
3321 try_read_bytes (struct sfm_reader *r, void *buf, size_t byte_cnt)
3322 {
3323   return read_bytes_internal (r, true, buf, byte_cnt);
3324 }
3325
3326 /* Reads a 32-bit signed integer from R and stores its value in host format in
3327    *X.  Returns true if successful, otherwise false. */
3328 static bool
3329 read_int (struct sfm_reader *r, int *x)
3330 {
3331   uint8_t integer[4];
3332   if (read_bytes (r, integer, sizeof integer) != 1)
3333     return false;
3334   *x = integer_get (r->integer_format, integer, sizeof integer);
3335   return true;
3336 }
3337
3338 static bool
3339 read_uint (struct sfm_reader *r, unsigned int *x)
3340 {
3341   bool ok;
3342   int y;
3343
3344   ok = read_int (r, &y);
3345   *x = y;
3346   return ok;
3347 }
3348
3349 /* Reads a 64-bit signed integer from R and returns its value in
3350    host format. */
3351 static bool
3352 read_int64 (struct sfm_reader *r, long long int *x)
3353 {
3354   uint8_t integer[8];
3355   if (read_bytes (r, integer, sizeof integer) != 1)
3356     return false;
3357   *x = integer_get (r->integer_format, integer, sizeof integer);
3358   return true;
3359 }
3360
3361 /* Reads a 64-bit signed integer from R and returns its value in
3362    host format. */
3363 static bool
3364 read_uint64 (struct sfm_reader *r, unsigned long long int *x)
3365 {
3366   long long int y;
3367   bool ok;
3368
3369   ok = read_int64 (r, &y);
3370   *x = y;
3371   return ok;
3372 }
3373
3374 static int
3375 parse_int (const struct sfm_reader *r, const void *data, size_t ofs)
3376 {
3377   return integer_get (r->integer_format, (const uint8_t *) data + ofs, 4);
3378 }
3379
3380 static double
3381 parse_float (const struct sfm_reader *r, const void *data, size_t ofs)
3382 {
3383   return float_get_double (r->float_format, (const uint8_t *) data + ofs);
3384 }
3385
3386 /* Reads exactly SIZE - 1 bytes into BUFFER
3387    and stores a null byte into BUFFER[SIZE - 1]. */
3388 static bool
3389 read_string (struct sfm_reader *r, char *buffer, size_t size)
3390 {
3391   bool ok;
3392
3393   assert (size > 0);
3394   ok = read_bytes (r, buffer, size - 1);
3395   if (ok)
3396     buffer[size - 1] = '\0';
3397   return ok;
3398 }
3399
3400 /* Skips BYTES bytes forward in R. */
3401 static bool
3402 skip_bytes (struct sfm_reader *r, size_t bytes)
3403 {
3404   while (bytes > 0)
3405     {
3406       char buffer[1024];
3407       size_t chunk = MIN (sizeof buffer, bytes);
3408       if (!read_bytes (r, buffer, chunk))
3409         return false;
3410       bytes -= chunk;
3411     }
3412
3413   return true;
3414 }
3415
3416 /* Returns a malloc()'d copy of S in which all lone CRs and CR LF pairs have
3417    been replaced by LFs.
3418
3419    (A product that identifies itself as VOXCO INTERVIEWER 4.3 produces system
3420    files that use CR-only line ends in the file label and extra product
3421    info.) */
3422 static char *
3423 fix_line_ends (const char *s)
3424 {
3425   char *dst, *d;
3426
3427   d = dst = xmalloc (strlen (s) + 1);
3428   while (*s != '\0')
3429     {
3430       if (*s == '\r')
3431         {
3432           s++;
3433           if (*s == '\n')
3434             s++;
3435           *d++ = '\n';
3436         }
3437       else
3438         *d++ = *s++;
3439     }
3440   *d = '\0';
3441
3442   return dst;
3443 }
3444 \f
3445 static bool
3446 read_ztrailer (struct sfm_reader *r,
3447                long long int zheader_ofs,
3448                long long int ztrailer_len);
3449
3450 static void *
3451 zalloc (voidpf pool_, uInt items, uInt size)
3452 {
3453   struct pool *pool = pool_;
3454
3455   return (!size || xalloc_oversized (items, size)
3456           ? Z_NULL
3457           : pool_malloc (pool, items * size));
3458 }
3459
3460 static void
3461 zfree (voidpf pool_, voidpf address)
3462 {
3463   struct pool *pool = pool_;
3464
3465   pool_free (pool, address);
3466 }
3467
3468 static bool
3469 read_zheader (struct sfm_reader *r)
3470 {
3471   off_t pos = r->pos;
3472   long long int zheader_ofs;
3473   long long int ztrailer_ofs;
3474   long long int ztrailer_len;
3475
3476   if (!read_int64 (r, &zheader_ofs)
3477       || !read_int64 (r, &ztrailer_ofs)
3478       || !read_int64 (r, &ztrailer_len))
3479     return false;
3480
3481   if (zheader_ofs != pos)
3482     {
3483       sys_error (r, pos, _("Wrong ZLIB data header offset %#llx "
3484                            "(expected %#llx)."),
3485                  zheader_ofs, (long long int) pos);
3486       return false;
3487     }
3488
3489   if (ztrailer_ofs < r->pos)
3490     {
3491       sys_error (r, pos, _("Impossible ZLIB trailer offset 0x%llx."),
3492                  ztrailer_ofs);
3493       return false;
3494     }
3495
3496   if (ztrailer_len < 24 || ztrailer_len % 24)
3497     {
3498       sys_error (r, pos, _("Invalid ZLIB trailer length %lld."), ztrailer_len);
3499       return false;
3500     }
3501
3502   r->ztrailer_ofs = ztrailer_ofs;
3503   if (!read_ztrailer (r, zheader_ofs, ztrailer_len))
3504     return false;
3505
3506   if (r->zin_buf == NULL)
3507     {
3508       r->zin_buf = pool_malloc (r->pool, ZIN_BUF_SIZE);
3509       r->zout_buf = pool_malloc (r->pool, ZOUT_BUF_SIZE);
3510       r->zstream.next_in = NULL;
3511       r->zstream.avail_in = 0;
3512     }
3513
3514   r->zstream.zalloc = zalloc;
3515   r->zstream.zfree = zfree;
3516   r->zstream.opaque = r->pool;
3517
3518   return open_zstream (r);
3519 }
3520
3521 static void
3522 seek (struct sfm_reader *r, off_t offset)
3523 {
3524   if (fseeko (r->file, offset, SEEK_SET))
3525     sys_error (r, 0, _("%s: seek failed (%s)."),
3526                fh_get_file_name (r->fh), strerror (errno));
3527   r->pos = offset;
3528 }
3529
3530 /* Performs some additional consistency checks on the ZLIB compressed data
3531    trailer. */
3532 static bool
3533 read_ztrailer (struct sfm_reader *r,
3534                long long int zheader_ofs,
3535                long long int ztrailer_len)
3536 {
3537   long long int expected_uncmp_ofs;
3538   long long int expected_cmp_ofs;
3539   long long int bias;
3540   long long int zero;
3541   unsigned int block_size;
3542   unsigned int n_blocks;
3543   unsigned int i;
3544   struct stat s;
3545
3546   if (fstat (fileno (r->file), &s))
3547     {
3548       sys_error (r, 0, _("%s: stat failed (%s)."),
3549                  fh_get_file_name (r->fh), strerror (errno));
3550       return false;
3551     }
3552
3553   if (!S_ISREG (s.st_mode))
3554     {
3555       /* We can't seek to the trailer and then back to the data in this file,
3556          so skip doing extra checks. */
3557       return true;
3558     }
3559
3560   if (r->ztrailer_ofs + ztrailer_len != s.st_size)
3561     sys_warn (r, r->pos,
3562               _("End of ZLIB trailer (0x%llx) is not file size (0x%llx)."),
3563               r->ztrailer_ofs + ztrailer_len, (long long int) s.st_size);
3564
3565   seek (r, r->ztrailer_ofs);
3566
3567   /* Read fixed header from ZLIB data trailer. */
3568   if (!read_int64 (r, &bias))
3569     return false;
3570   if (-bias != r->bias)
3571     {
3572       sys_error (r, r->pos, _("ZLIB trailer bias (%lld) differs from "
3573                               "file header bias (%.2f)."),
3574                  -bias, r->bias);
3575       return false;
3576     }
3577
3578   if (!read_int64 (r, &zero))
3579     return false;
3580   if (zero != 0)
3581     sys_warn (r, r->pos,
3582               _("ZLIB trailer \"zero\" field has nonzero value %lld."), zero);
3583
3584   if (!read_uint (r, &block_size))
3585     return false;
3586   if (block_size != ZBLOCK_SIZE)
3587     sys_warn (r, r->pos,
3588               _("ZLIB trailer specifies unexpected %u-byte block size."),
3589               block_size);
3590
3591   if (!read_uint (r, &n_blocks))
3592     return false;
3593   if (n_blocks != (ztrailer_len - 24) / 24)
3594     {
3595       sys_error (r, r->pos,
3596                  _("%lld-byte ZLIB trailer specifies %u data blocks (expected "
3597                    "%lld)."),
3598                  ztrailer_len, n_blocks, (ztrailer_len - 24) / 24);
3599       return false;
3600     }
3601
3602   expected_uncmp_ofs = zheader_ofs;
3603   expected_cmp_ofs = zheader_ofs + 24;
3604   for (i = 0; i < n_blocks; i++)
3605     {
3606       off_t desc_ofs = r->pos;
3607       unsigned long long int uncompressed_ofs;
3608       unsigned long long int compressed_ofs;
3609       unsigned int uncompressed_size;
3610       unsigned int compressed_size;
3611
3612       if (!read_uint64 (r, &uncompressed_ofs)
3613           || !read_uint64 (r, &compressed_ofs)
3614           || !read_uint (r, &uncompressed_size)
3615           || !read_uint (r, &compressed_size))
3616         return false;
3617
3618       if (uncompressed_ofs != expected_uncmp_ofs)
3619         {
3620           sys_error (r, desc_ofs,
3621                      _("ZLIB block descriptor %u reported uncompressed data "
3622                        "offset %#llx, when %#llx was expected."),
3623                      i, uncompressed_ofs, expected_uncmp_ofs);
3624           return false;
3625         }
3626
3627       if (compressed_ofs != expected_cmp_ofs)
3628         {
3629           sys_error (r, desc_ofs,
3630                      _("ZLIB block descriptor %u reported compressed data "
3631                        "offset %#llx, when %#llx was expected."),
3632                      i, compressed_ofs, expected_cmp_ofs);
3633           return false;
3634         }
3635
3636       if (i < n_blocks - 1)
3637         {
3638           if (uncompressed_size != block_size)
3639             sys_warn (r, desc_ofs,
3640                       _("ZLIB block descriptor %u reported block size %#x, "
3641                         "when %#x was expected."),
3642                       i, uncompressed_size, block_size);
3643         }
3644       else
3645         {
3646           if (uncompressed_size > block_size)
3647             sys_warn (r, desc_ofs,
3648                       _("ZLIB block descriptor %u reported block size %#x, "
3649                         "when at most %#x was expected."),
3650                       i, uncompressed_size, block_size);
3651         }
3652
3653       /* http://www.zlib.net/zlib_tech.html says that the maximum expansion
3654          from compression, with worst-case parameters, is 13.5% plus 11 bytes.
3655          This code checks for an expansion of more than 14.3% plus 11
3656          bytes.  */
3657       if (compressed_size > uncompressed_size + uncompressed_size / 7 + 11)
3658         {
3659           sys_error (r, desc_ofs,
3660                      _("ZLIB block descriptor %u reports compressed size %u "
3661                        "and uncompressed size %u."),
3662                      i, compressed_size, uncompressed_size);
3663           return false;
3664         }
3665
3666       expected_uncmp_ofs += uncompressed_size;
3667       expected_cmp_ofs += compressed_size;
3668     }
3669
3670   if (expected_cmp_ofs != r->ztrailer_ofs)
3671     {
3672       sys_error (r, r->pos, _("ZLIB trailer is at offset %#llx but %#llx "
3673                               "would be expected from block descriptors."),
3674                  r->ztrailer_ofs, expected_cmp_ofs);
3675       return false;
3676     }
3677
3678   seek (r, zheader_ofs + 24);
3679   return true;
3680 }
3681
3682 static bool
3683 open_zstream (struct sfm_reader *r)
3684 {
3685   int error;
3686
3687   r->zout_pos = r->zout_end = 0;
3688   error = inflateInit (&r->zstream);
3689   if (error != Z_OK)
3690     {
3691       sys_error (r, r->pos, _("ZLIB initialization failed (%s)."),
3692                  r->zstream.msg);
3693       return false;
3694     }
3695   return true;
3696 }
3697
3698 static bool
3699 close_zstream (struct sfm_reader *r)
3700 {
3701   int error;
3702
3703   error = inflateEnd (&r->zstream);
3704   if (error != Z_OK)
3705     {
3706       sys_error (r, r->pos, _("Inconsistency at end of ZLIB stream (%s)."),
3707                  r->zstream.msg);
3708       return false;
3709     }
3710   return true;
3711 }
3712
3713 static int
3714 read_bytes_zlib (struct sfm_reader *r, void *buf_, size_t byte_cnt)
3715 {
3716   uint8_t *buf = buf_;
3717
3718   if (byte_cnt == 0)
3719     return 1;
3720
3721   for (;;)
3722     {
3723       int error;
3724
3725       /* Use already inflated data if there is any. */
3726       if (r->zout_pos < r->zout_end)
3727         {
3728           unsigned int n = MIN (byte_cnt, r->zout_end - r->zout_pos);
3729           memcpy (buf, &r->zout_buf[r->zout_pos], n);
3730           r->zout_pos += n;
3731           byte_cnt -= n;
3732           buf += n;
3733
3734           if (byte_cnt == 0)
3735             return 1;
3736         }
3737
3738       /* We need to inflate some more data.
3739          Get some more input data if we don't have any. */
3740       if (r->zstream.avail_in == 0)
3741         {
3742           unsigned int n = MIN (ZIN_BUF_SIZE, r->ztrailer_ofs - r->pos);
3743           if (n == 0)
3744             return 0;
3745           else
3746             {
3747               int retval = try_read_bytes (r, r->zin_buf, n);
3748               if (retval != 1)
3749                 return retval;
3750               r->zstream.avail_in = n;
3751               r->zstream.next_in = r->zin_buf;
3752             }
3753         }
3754
3755       /* Inflate the (remaining) input data. */
3756       r->zstream.avail_out = ZOUT_BUF_SIZE;
3757       r->zstream.next_out = r->zout_buf;
3758       error = inflate (&r->zstream, Z_SYNC_FLUSH);
3759       r->zout_pos = 0;
3760       r->zout_end = r->zstream.next_out - r->zout_buf;
3761       if (r->zout_end == 0)
3762         {
3763           if (error != Z_STREAM_END)
3764             {
3765               sys_error (r, r->pos, _("ZLIB stream inconsistency (%s)."),
3766                          r->zstream.msg);
3767               return -1;
3768             }
3769           else if (!close_zstream (r) || !open_zstream (r))
3770             return -1;
3771         }
3772       else
3773         {
3774           /* Process the output data and ignore 'error' for now.  ZLIB will
3775              present it to us again on the next inflate() call. */
3776         }
3777     }
3778 }
3779
3780 static int
3781 read_compressed_bytes (struct sfm_reader *r, void *buf, size_t byte_cnt)
3782 {
3783   if (r->compression == ANY_COMP_SIMPLE)
3784     return read_bytes (r, buf, byte_cnt);
3785   else
3786     {
3787       int retval = read_bytes_zlib (r, buf, byte_cnt);
3788       if (retval == 0)
3789         sys_error (r, r->pos, _("Unexpected end of ZLIB compressed data."));
3790       return retval;
3791     }
3792 }
3793
3794 static int
3795 try_read_compressed_bytes (struct sfm_reader *r, void *buf, size_t byte_cnt)
3796 {
3797   if (r->compression == ANY_COMP_SIMPLE)
3798     return try_read_bytes (r, buf, byte_cnt);
3799   else
3800     return read_bytes_zlib (r, buf, byte_cnt);
3801 }
3802
3803 /* Reads a 64-bit floating-point number from R and returns its
3804    value in host format. */
3805 static bool
3806 read_compressed_float (struct sfm_reader *r, double *d)
3807 {
3808   uint8_t number[8];
3809
3810   if (!read_compressed_bytes (r, number, sizeof number))
3811     return false;
3812
3813   *d = float_get_double (r->float_format, number);
3814   return true;
3815 }
3816 \f
3817 static const struct casereader_class sys_file_casereader_class =
3818   {
3819     sys_file_casereader_read,
3820     sys_file_casereader_destroy,
3821     NULL,
3822     NULL,
3823   };
3824
3825 const struct any_reader_class sys_file_reader_class =
3826   {
3827     N_("SPSS System File"),
3828     sfm_detect,
3829     sfm_open,
3830     sfm_close,
3831     sfm_decode,
3832     sfm_get_strings,
3833   };