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