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