Makefiles: Make a couple of targets build more quietly.
[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   dict_compact_values (dict);
2145
2146   return true;
2147 }
2148
2149 #define MAX_LABEL_WARNINGS 5
2150
2151 /* Displays a warning for offset OFFSET in the file. */
2152 static void
2153 value_label_warning (struct sfm_reader *r, off_t offset, int *n_label_warnings,
2154                      const char *format, ...)
2155 {
2156   if (++*n_label_warnings > MAX_LABEL_WARNINGS)
2157     return;
2158
2159   va_list args;
2160
2161   va_start (args, format);
2162   sys_msg (r, offset, MW, format, args);
2163   va_end (args);
2164 }
2165
2166 #define MAX_LABEL_WARNINGS 5
2167
2168 static void
2169 parse_one_value_label_set (struct sfm_reader *r, struct dictionary *dict,
2170                            const struct sfm_var_record *var_recs,
2171                            size_t n_var_recs,
2172                            const struct sfm_value_label_record *record,
2173                            int *n_label_warnings)
2174 {
2175   char **utf8_labels
2176     = pool_nmalloc (r->pool, record->n_labels, sizeof *utf8_labels);
2177   for (size_t i = 0; i < record->n_labels; i++)
2178     utf8_labels[i] = recode_string_pool ("UTF-8", dict_get_encoding (dict),
2179                                          record->labels[i].label, -1,
2180                                          r->pool);
2181
2182   struct variable **vars = pool_nmalloc (r->pool,
2183                                          record->n_vars, sizeof *vars);
2184   unsigned int n_vars = 0;
2185   for (size_t i = 0; i < record->n_vars; i++)
2186     {
2187       int idx = record->vars[i];
2188       if (idx < 1 || idx > n_var_recs)
2189         {
2190           value_label_warning (
2191             r, record->pos, n_label_warnings,
2192             _("Value label variable index %d not in valid range 1...%zu."),
2193             idx, n_var_recs);
2194           continue;
2195         }
2196
2197       const struct sfm_var_record *rec = &var_recs[idx - 1];
2198       if (rec->var == NULL)
2199         {
2200           value_label_warning (
2201             r, record->pos, n_label_warnings,
2202             _("Value label variable index %d "
2203               "refers to long string continuation."), idx);
2204           continue;
2205         }
2206
2207       vars[n_vars++] = rec->var;
2208     }
2209   if (!n_vars)
2210     return;
2211
2212   for (size_t i = 1; i < n_vars; i++)
2213     if (var_get_type (vars[i]) != var_get_type (vars[0]))
2214       {
2215         value_label_warning (
2216           r, record->pos, n_label_warnings,
2217           _("Variables associated with value label are not all of "
2218             "identical type.  Variable %s is %s, but variable "
2219             "%s is %s."),
2220           var_get_name (vars[0]),
2221           var_is_numeric (vars[0]) ? _("numeric") : _("string"),
2222           var_get_name (vars[i]),
2223           var_is_numeric (vars[i]) ? _("numeric") : _("string"));
2224         return;
2225       }
2226
2227   for (size_t i = 0; i < n_vars; i++)
2228     {
2229       struct variable *var = vars[i];
2230       int width = var_get_width (var);
2231       if (width > 8)
2232         {
2233           value_label_warning (
2234             r, record->pos, n_label_warnings,
2235             _("Value labels may not be added to long string "
2236               "variables (e.g. %s) using records types 3 and 4."),
2237             var_get_name (var));
2238           continue;
2239         }
2240
2241       for (size_t j = 0; j < record->n_labels; j++)
2242         {
2243           struct sfm_value_label *label = &record->labels[j];
2244           union value value;
2245
2246           value_init (&value, width);
2247           if (width == 0)
2248             value.f = parse_float (r, label->value, 0);
2249           else
2250             memcpy (value.s, label->value, width);
2251
2252           if (!var_add_value_label (var, &value, utf8_labels[j]))
2253             {
2254               if (r->written_by_readstat)
2255                 {
2256                   /* Ignore the problem.  ReadStat is buggy and emits value
2257                      labels whose values are longer than string variables'
2258                      widths, that are identical in the actual width of the
2259                      variable, e.g. both values "ABC123" and "ABC456" for a
2260                      string variable with width 3. */
2261                 }
2262               else if (var_is_numeric (var))
2263                 value_label_warning (r, record->pos, n_label_warnings,
2264                                      _("Duplicate value label for %g on %s."),
2265                                      value.f, var_get_name (var));
2266               else
2267                 value_label_warning (
2268                   r, record->pos, n_label_warnings,
2269                   _("Duplicate value label for `%.*s' on %s."),
2270                   width, value.s, var_get_name (var));
2271             }
2272
2273           value_destroy (&value, width);
2274         }
2275     }
2276
2277   pool_free (r->pool, vars);
2278   for (size_t i = 0; i < record->n_labels; i++)
2279     pool_free (r->pool, utf8_labels[i]);
2280   pool_free (r->pool, utf8_labels);
2281 }
2282
2283 static void
2284 parse_value_labels (struct sfm_reader *r, struct dictionary *dict)
2285 {
2286   int n_label_warnings = 0;
2287   for (size_t i = 0; i < r->n_labels; i++)
2288     parse_one_value_label_set (r, dict, r->vars, r->n_vars, &r->labels[i],
2289                                &n_label_warnings);
2290   if (n_label_warnings > MAX_LABEL_WARNINGS)
2291       sys_warn (r, -1,
2292                 _("Suppressed %d additional warnings for value labels."),
2293                 n_label_warnings - MAX_LABEL_WARNINGS);
2294 }
2295
2296 static struct variable *
2297 parse_weight_var (struct sfm_reader *r,
2298                   const struct sfm_var_record *var_recs, size_t n_var_recs,
2299                   int idx)
2300 {
2301   off_t offset = 76;            /* Offset to variable index in header. */
2302
2303   if (idx < 1 || idx > n_var_recs)
2304     {
2305       sys_warn (r, offset,
2306                 _("Weight variable index %d not in valid range 1...%zu.  "
2307                   "Treating file as unweighted."),
2308                 idx, n_var_recs);
2309       return NULL;
2310     }
2311
2312   const struct sfm_var_record *rec = &var_recs[idx - 1];
2313   if (rec->var == NULL)
2314     {
2315       sys_warn (r, offset,
2316                 _("Weight variable index %d refers to long string "
2317                   "continuation.  Treating file as unweighted."), idx);
2318       return NULL;
2319     }
2320
2321   struct variable *weight_var = rec->var;
2322   if (!var_is_numeric (weight_var))
2323     {
2324       sys_warn (r, offset, _("Ignoring string variable `%s' set "
2325                              "as weighting variable."),
2326                 var_get_name (weight_var));
2327       return NULL;
2328     }
2329
2330   return weight_var;
2331 }
2332
2333 /* Parses a set of custom attributes from TEXT into ATTRS.
2334    ATTRS may be a null pointer, in which case the attributes are
2335    read but discarded. */
2336 static void
2337 parse_attributes (struct sfm_reader *r, struct text_record *text,
2338                   struct attrset *attrs)
2339 {
2340   do
2341     {
2342       struct attribute *attr;
2343       char *key;
2344       int index;
2345
2346       /* Parse the key. */
2347       key = text_get_token (text, ss_cstr ("("), NULL);
2348       if (key == NULL)
2349         return;
2350
2351       attr = attribute_create (key);
2352       for (index = 1; ; index++)
2353         {
2354           /* Parse the value. */
2355           char *value;
2356           size_t length;
2357
2358           value = text_get_token (text, ss_cstr ("\n"), NULL);
2359           if (value == NULL)
2360             {
2361               text_warn (r, text, _("Error parsing attribute value %s[%d]."),
2362                          key, index);
2363               break;
2364             }
2365
2366           length = strlen (value);
2367           if (length >= 2 && value[0] == '\'' && value[length - 1] == '\'')
2368             {
2369               value[length - 1] = '\0';
2370               attribute_add_value (attr, value + 1);
2371             }
2372           else
2373             {
2374               text_warn (r, text,
2375                          _("Attribute value %s[%d] is not quoted: %s."),
2376                          key, index, value);
2377               attribute_add_value (attr, value);
2378             }
2379
2380           /* Was this the last value for this attribute? */
2381           if (text_match (text, ')'))
2382             break;
2383         }
2384       if (attrs != NULL && attribute_get_n_values (attr) > 0)
2385         {
2386           if (!attrset_try_add (attrs, attr))
2387             {
2388               text_warn (r, text, _("Duplicate attribute %s."),
2389                          attribute_get_name (attr));
2390               attribute_destroy (attr);
2391             }
2392         }
2393       else
2394         attribute_destroy (attr);
2395     }
2396   while (!text_match (text, '/'));
2397 }
2398
2399 /* Reads record type 7, subtype 17, which lists custom
2400    attributes on the data file.  */
2401 static void
2402 parse_data_file_attributes (struct sfm_reader *r,
2403                             const struct sfm_extension_record *record,
2404                             struct dictionary *dict)
2405 {
2406   struct text_record *text = open_text_record (r, record, true);
2407   parse_attributes (r, text, dict_get_attributes (dict));
2408   close_text_record (r, text);
2409 }
2410
2411 /* Parses record type 7, subtype 18, which lists custom
2412    attributes on individual variables.  */
2413 static void
2414 parse_variable_attributes (struct sfm_reader *r,
2415                            const struct sfm_extension_record *record,
2416                            struct dictionary *dict)
2417 {
2418   struct text_record *text;
2419   struct variable *var;
2420
2421   text = open_text_record (r, record, true);
2422   while (text_read_variable_name (r, dict, text, ss_cstr (":"), &var))
2423     parse_attributes (r, text, var != NULL ? var_get_attributes (var) : NULL);
2424   close_text_record (r, text);
2425 }
2426
2427 static void
2428 assign_variable_roles (struct sfm_reader *r, struct dictionary *dict)
2429 {
2430   size_t n_warnings = 0;
2431   size_t i;
2432
2433   for (i = 0; i < dict_get_n_vars (dict); i++)
2434     {
2435       struct variable *var = dict_get_var (dict, i);
2436       struct attrset *attrs = var_get_attributes (var);
2437       const struct attribute *attr = attrset_lookup (attrs, "$@Role");
2438       if (attr != NULL && attribute_get_n_values (attr) > 0)
2439         {
2440           int value = atoi (attribute_get_value (attr, 0));
2441           enum var_role role;
2442
2443           switch (value)
2444             {
2445             case 0:
2446               role = ROLE_INPUT;
2447               break;
2448
2449             case 1:
2450               role = ROLE_TARGET;
2451               break;
2452
2453             case 2:
2454               role = ROLE_BOTH;
2455               break;
2456
2457             case 3:
2458               role = ROLE_NONE;
2459               break;
2460
2461             case 4:
2462               role = ROLE_PARTITION;
2463               break;
2464
2465             case 5:
2466               role = ROLE_SPLIT;
2467               break;
2468
2469             default:
2470               role = ROLE_INPUT;
2471               if (n_warnings++ == 0)
2472                 sys_warn (r, -1, _("Invalid role for variable %s."),
2473                           var_get_name (var));
2474             }
2475
2476           var_set_role (var, role);
2477         }
2478     }
2479
2480   if (n_warnings > 1)
2481     sys_warn (r, -1, _("%zu other variables had invalid roles."),
2482               n_warnings - 1);
2483 }
2484
2485 static bool
2486 check_overflow__ (const struct sfm_extension_record *record,
2487                   size_t ofs, size_t length)
2488 {
2489   size_t end = record->size * record->count;
2490   if (length >= end || ofs + length > end)
2491     return false;
2492   return true;
2493 }
2494
2495 static bool
2496 check_overflow (struct sfm_reader *r,
2497                 const struct sfm_extension_record *record,
2498                 size_t ofs, size_t length)
2499 {
2500   bool ok = check_overflow__ (record, ofs, length);
2501   if (!ok)
2502     sys_warn (r, record->pos + record->size * record->count,
2503               _("Extension record subtype %d ends unexpectedly."),
2504               record->subtype);
2505   return ok;
2506 }
2507
2508 static void
2509 parse_long_string_value_labels (struct sfm_reader *r,
2510                                 const struct sfm_extension_record *record,
2511                                 struct dictionary *dict)
2512 {
2513   const char *dict_encoding = dict_get_encoding (dict);
2514   size_t end = record->size * record->count;
2515   size_t ofs = 0;
2516
2517   while (ofs < end)
2518     {
2519       char *var_name;
2520       size_t n_labels, i;
2521       struct variable *var;
2522       union value value;
2523       int var_name_len;
2524       int width;
2525
2526       /* Parse variable name length. */
2527       if (!check_overflow (r, record, ofs, 4))
2528         return;
2529       var_name_len = parse_int (r, record->data, ofs);
2530       ofs += 4;
2531
2532       /* Parse variable name, width, and number of labels. */
2533       if (!check_overflow (r, record, ofs, var_name_len)
2534           || !check_overflow (r, record, ofs, var_name_len + 8))
2535         return;
2536       var_name = recode_string_pool ("UTF-8", dict_encoding,
2537                                      (const char *) record->data + ofs,
2538                                      var_name_len, r->pool);
2539       width = parse_int (r, record->data, ofs + var_name_len);
2540       n_labels = parse_int (r, record->data, ofs + var_name_len + 4);
2541       ofs += var_name_len + 8;
2542
2543       /* Look up 'var' and validate. */
2544       var = dict_lookup_var (dict, var_name);
2545       if (var == NULL)
2546         sys_warn (r, record->pos + ofs,
2547                   _("Ignoring long string value label record for "
2548                     "unknown variable %s."), var_name);
2549       else if (var_is_numeric (var))
2550         {
2551           sys_warn (r, record->pos + ofs,
2552                     _("Ignoring long string value label record for "
2553                       "numeric variable %s."), var_name);
2554           var = NULL;
2555         }
2556       else if (width != var_get_width (var))
2557         {
2558           sys_warn (r, record->pos + ofs,
2559                     _("Ignoring long string value label record for variable "
2560                       "%s because the record's width (%d) does not match the "
2561                       "variable's width (%d)."),
2562                     var_name, width, var_get_width (var));
2563           var = NULL;
2564         }
2565
2566       /* Parse values. */
2567       value_init_pool (r->pool, &value, width);
2568       for (i = 0; i < n_labels; i++)
2569         {
2570           size_t value_length, label_length;
2571           bool skip = var == NULL;
2572
2573           /* Parse value length. */
2574           if (!check_overflow (r, record, ofs, 4))
2575             return;
2576           value_length = parse_int (r, record->data, ofs);
2577           ofs += 4;
2578
2579           /* Parse value. */
2580           if (!check_overflow (r, record, ofs, value_length))
2581             return;
2582           if (!skip)
2583             {
2584               if (value_length == width)
2585                 memcpy (value.s, (const uint8_t *) record->data + ofs, width);
2586               else
2587                 {
2588                   sys_warn (r, record->pos + ofs,
2589                             _("Ignoring long string value label %zu for "
2590                               "variable %s, with width %d, that has bad value "
2591                               "width %zu."),
2592                             i, var_get_name (var), width, value_length);
2593                   skip = true;
2594                 }
2595             }
2596           ofs += value_length;
2597
2598           /* Parse label length. */
2599           if (!check_overflow (r, record, ofs, 4))
2600             return;
2601           label_length = parse_int (r, record->data, ofs);
2602           ofs += 4;
2603
2604           /* Parse label. */
2605           if (!check_overflow (r, record, ofs, label_length))
2606             return;
2607           if (!skip)
2608             {
2609               char *label;
2610
2611               label = recode_string_pool ("UTF-8", dict_encoding,
2612                                           (const char *) record->data + ofs,
2613                                           label_length, r->pool);
2614               if (!var_add_value_label (var, &value, label))
2615                 sys_warn (r, record->pos + ofs,
2616                           _("Duplicate value label for `%.*s' on %s."),
2617                           width, value.s, var_get_name (var));
2618               pool_free (r->pool, label);
2619             }
2620           ofs += label_length;
2621         }
2622     }
2623 }
2624
2625 static void
2626 parse_long_string_missing_values (struct sfm_reader *r,
2627                                   const struct sfm_extension_record *record,
2628                                   struct dictionary *dict)
2629 {
2630   const char *dict_encoding = dict_get_encoding (dict);
2631   size_t end = record->size * record->count;
2632   size_t ofs = 0;
2633
2634   bool warned = false;
2635   while (ofs < end)
2636     {
2637       struct missing_values mv;
2638       char *var_name;
2639       struct variable *var;
2640       int n_missing_values;
2641       int var_name_len;
2642       size_t i;
2643
2644       /* Parse variable name length. */
2645       if (!check_overflow (r, record, ofs, 4))
2646         return;
2647       var_name_len = parse_int (r, record->data, ofs);
2648       ofs += 4;
2649
2650       /* Parse variable name. */
2651       if (!check_overflow (r, record, ofs, var_name_len)
2652           || !check_overflow (r, record, ofs, var_name_len + 1))
2653         return;
2654       var_name = recode_string_pool ("UTF-8", dict_encoding,
2655                                      (const char *) record->data + ofs,
2656                                      var_name_len, r->pool);
2657       ofs += var_name_len;
2658
2659       /* Parse number of missing values. */
2660       n_missing_values = ((const uint8_t *) record->data)[ofs];
2661       if (n_missing_values < 1 || n_missing_values > 3)
2662         sys_warn (r, record->pos + ofs,
2663                   _("Long string missing values record says variable %s "
2664                     "has %d missing values, but only 1 to 3 missing values "
2665                     "are allowed."),
2666                   var_name, n_missing_values);
2667       ofs++;
2668
2669       /* Look up 'var' and validate. */
2670       var = dict_lookup_var (dict, var_name);
2671       if (var == NULL)
2672         sys_warn (r, record->pos + ofs,
2673                   _("Ignoring long string missing value record for "
2674                     "unknown variable %s."), var_name);
2675       else if (var_is_numeric (var))
2676         {
2677           sys_warn (r, record->pos + ofs,
2678                     _("Ignoring long string missing value record for "
2679                       "numeric variable %s."), var_name);
2680           var = NULL;
2681         }
2682
2683       /* Parse value length. */
2684       if (!check_overflow (r, record, ofs, 4))
2685         return;
2686       size_t value_length = parse_int (r, record->data, ofs);
2687       ofs += 4;
2688
2689       /* Parse values. */
2690       mv_init_pool (r->pool, &mv, var ? var_get_width (var) : 8);
2691       for (i = 0; i < n_missing_values; i++)
2692         {
2693           /* Tolerate files written by old, buggy versions of PSPP where we
2694              believed that the value_length was repeated before each missing
2695              value. */
2696           if (check_overflow__ (record, ofs, value_length)
2697               && parse_int (r, record->data, ofs) == 8)
2698             {
2699               if (!warned)
2700                 {
2701                   sys_warn (r, record->pos + ofs,
2702                             _("This file has corrupted metadata written by a "
2703                               "buggy version of PSPP.  To fix it, save a new "
2704                               "copy of the file."));
2705                   warned = true;
2706                 }
2707               ofs += 4;
2708             }
2709
2710           /* Parse value. */
2711           if (!check_overflow (r, record, ofs, value_length))
2712             return;
2713           if (var != NULL
2714               && i < 3
2715               && !mv_add_str (&mv, (const uint8_t *) record->data + ofs,
2716                               value_length))
2717             sys_warn (r, record->pos + ofs,
2718                       _("Ignoring long string missing value %zu for variable "
2719                         "%s, with width %d, that has bad value width %zu."),
2720                       i, var_get_name (var), var_get_width (var),
2721                       value_length);
2722           ofs += value_length;
2723         }
2724       if (var != NULL)
2725         var_set_missing_values (var, &mv);
2726     }
2727 }
2728
2729 static void
2730 parse_var_sets (struct sfm_reader *r,
2731                 const struct sfm_extension_record *record,
2732                 struct dictionary *dict)
2733 {
2734   struct text_record *text = open_text_record (r, record, true);
2735   for (;;)
2736     {
2737       char *varset_name = text_get_token (text, ss_cstr ("="), NULL);
2738       if (!varset_name)
2739         break;
2740
2741       struct varset *varset = xmalloc (sizeof *varset);
2742       *varset = (struct varset) {
2743         .name = xstrdup (varset_name),
2744       };
2745
2746       text_match (text, ' ');
2747
2748       size_t allocated_vars = 0;
2749       char delimiter;
2750       do
2751         {
2752           char *var_name = text_get_token (text, ss_cstr (" \n"), &delimiter);
2753           if (!var_name)
2754             break;
2755
2756           size_t len = strlen (var_name);
2757           if (len > 0 && var_name[len - 1] == '\r')
2758             var_name[len - 1] = '\0';
2759
2760           struct variable *var = dict_lookup_var (dict, var_name);
2761           if (var)
2762             {
2763               if (varset->n_vars >= allocated_vars)
2764                 varset->vars = x2nrealloc (varset->vars, &allocated_vars,
2765                                            sizeof *varset->vars);
2766               varset->vars[varset->n_vars++] = var;
2767             }
2768           else
2769             sys_warn (r, record->pos,
2770                       _("Variable set %s contains unknown variable %s."),
2771                       varset_name, var_name);
2772         }
2773       while (delimiter == ' ');
2774
2775       dict_add_varset (dict, varset);
2776     }
2777   close_text_record (r, text);
2778 }
2779 \f
2780 /* Case reader. */
2781
2782 static void partial_record (struct sfm_reader *);
2783
2784 static void read_error (struct casereader *, const struct sfm_reader *);
2785
2786 static bool read_case_number (struct sfm_reader *, double *);
2787 static int read_case_string (struct sfm_reader *, uint8_t *, size_t);
2788 static int read_opcode (struct sfm_reader *);
2789 static bool read_compressed_number (struct sfm_reader *, double *);
2790 static int read_compressed_string (struct sfm_reader *, uint8_t *);
2791 static int read_whole_strings (struct sfm_reader *, uint8_t *, size_t);
2792 static bool skip_whole_strings (struct sfm_reader *, size_t);
2793
2794 /* Reads and returns one case from READER's file.  Returns a null
2795    pointer if not successful. */
2796 static struct ccase *
2797 sys_file_casereader_read (struct casereader *reader, void *r_)
2798 {
2799   struct sfm_reader *r = r_;
2800   struct ccase *c;
2801   int retval;
2802   int i;
2803
2804   if (r->error || !r->sfm_n_vars)
2805     return NULL;
2806
2807   c = case_create (r->proto);
2808
2809   for (i = 0; i < r->sfm_n_vars; i++)
2810     {
2811       struct sfm_var *sv = &r->sfm_vars[i];
2812       union value *v = case_data_rw_idx (c, sv->case_index);
2813
2814       if (sv->var_width == 0)
2815         retval = read_case_number (r, &v->f);
2816       else
2817         {
2818           retval = read_case_string (r, v->s + sv->offset, sv->segment_width);
2819           if (retval == 1)
2820             {
2821               retval = skip_whole_strings (r, ROUND_DOWN (sv->padding, 8));
2822               if (retval == 0)
2823                 sys_error (r, r->pos, _("File ends in partial string value."));
2824             }
2825         }
2826
2827       if (retval != 1)
2828         goto eof;
2829     }
2830   return c;
2831
2832 eof:
2833   if (i != 0)
2834     partial_record (r);
2835   if (r->n_cases != -1)
2836     read_error (reader, r);
2837   case_unref (c);
2838   return NULL;
2839 }
2840
2841 /* Issues an error that R ends in a partial record. */
2842 static void
2843 partial_record (struct sfm_reader *r)
2844 {
2845   sys_error (r, r->pos, _("File ends in partial case."));
2846 }
2847
2848 /* Issues an error that an unspecified error occurred SFM, and
2849    marks R tainted. */
2850 static void
2851 read_error (struct casereader *r, const struct sfm_reader *sfm)
2852 {
2853   msg (ME, _("Error reading case from file %s."), fh_get_name (sfm->fh));
2854   casereader_force_error (r);
2855 }
2856
2857 /* Reads a number from R and stores its value in *D.
2858    If R is compressed, reads a compressed number;
2859    otherwise, reads a number in the regular way.
2860    Returns true if successful, false if end of file is
2861    reached immediately. */
2862 static bool
2863 read_case_number (struct sfm_reader *r, double *d)
2864 {
2865   if (r->compression == ANY_COMP_NONE)
2866     {
2867       uint8_t number[8];
2868       if (!try_read_bytes (r, number, sizeof number))
2869         return false;
2870       float_convert (r->float_format, number, FLOAT_NATIVE_DOUBLE, d);
2871       return true;
2872     }
2873   else
2874     return read_compressed_number (r, d);
2875 }
2876
2877 /* Reads LENGTH string bytes from R into S.  Always reads a multiple of 8
2878    bytes; if LENGTH is not a multiple of 8, then extra bytes are read and
2879    discarded without being written to S.  Reads compressed strings if S is
2880    compressed.  Returns 1 if successful, 0 if end of file is reached
2881    immediately, or -1 for some kind of error. */
2882 static int
2883 read_case_string (struct sfm_reader *r, uint8_t *s, size_t length)
2884 {
2885   size_t whole = ROUND_DOWN (length, 8);
2886   size_t partial = length % 8;
2887
2888   if (whole)
2889     {
2890       int retval = read_whole_strings (r, s, whole);
2891       if (retval != 1)
2892         return retval;
2893     }
2894
2895   if (partial)
2896     {
2897       uint8_t bounce[8];
2898       int retval = read_whole_strings (r, bounce, sizeof bounce);
2899       if (retval == -1)
2900         return -1;
2901       else if (!retval)
2902         {
2903           if (whole)
2904             {
2905               partial_record (r);
2906               return -1;
2907             }
2908           return 0;
2909         }
2910       memcpy (s + whole, bounce, partial);
2911     }
2912
2913   return 1;
2914 }
2915
2916 /* Reads and returns the next compression opcode from R. */
2917 static int
2918 read_opcode (struct sfm_reader *r)
2919 {
2920   assert (r->compression != ANY_COMP_NONE);
2921   for (;;)
2922     {
2923       int opcode;
2924       if (r->opcode_idx >= sizeof r->opcodes)
2925         {
2926
2927           int retval = try_read_compressed_bytes (r, r->opcodes,
2928                                                   sizeof r->opcodes);
2929           if (retval != 1)
2930             return -1;
2931           r->opcode_idx = 0;
2932         }
2933       opcode = r->opcodes[r->opcode_idx++];
2934
2935       if (opcode != 0)
2936         return opcode;
2937     }
2938 }
2939
2940 /* Reads a compressed number from R and stores its value in D.
2941    Returns true if successful, false if end of file is
2942    reached immediately. */
2943 static bool
2944 read_compressed_number (struct sfm_reader *r, double *d)
2945 {
2946   int opcode = read_opcode (r);
2947   switch (opcode)
2948     {
2949     case -1:
2950     case 252:
2951       return false;
2952
2953     case 253:
2954       return read_compressed_float (r, d);
2955
2956     case 254:
2957       float_convert (r->float_format, "        ", FLOAT_NATIVE_DOUBLE, d);
2958       if (!r->corruption_warning)
2959         {
2960           r->corruption_warning = true;
2961           sys_warn (r, r->pos,
2962                     _("Possible compressed data corruption: "
2963                       "compressed spaces appear in numeric field."));
2964         }
2965       break;
2966
2967     case 255:
2968       *d = SYSMIS;
2969       break;
2970
2971     default:
2972       *d = opcode - r->bias;
2973       break;
2974     }
2975
2976   return true;
2977 }
2978
2979 /* Reads a compressed 8-byte string segment from R and stores it in DST. */
2980 static int
2981 read_compressed_string (struct sfm_reader *r, uint8_t *dst)
2982 {
2983   int opcode;
2984   int retval;
2985
2986   opcode = read_opcode (r);
2987   switch (opcode)
2988     {
2989     case -1:
2990     case 252:
2991       return 0;
2992
2993     case 253:
2994       retval = read_compressed_bytes (r, dst, 8);
2995       return retval == 1 ? 1 : -1;
2996
2997     case 254:
2998       memset (dst, ' ', 8);
2999       return 1;
3000
3001     default:
3002       {
3003         double value = opcode - r->bias;
3004         float_convert (FLOAT_NATIVE_DOUBLE, &value, r->float_format, dst);
3005         if (value == 0.0)
3006           {
3007             /* This has actually been seen "in the wild".  The submitter of the
3008                file that showed that the contents decoded as spaces, but they
3009                were at the end of the field so it's possible that the null
3010                bytes just acted as null terminators. */
3011           }
3012         else if (!r->corruption_warning)
3013           {
3014             r->corruption_warning = true;
3015             sys_warn (r, r->pos,
3016                       _("Possible compressed data corruption: "
3017                         "string contains compressed integer (opcode %d)."),
3018                       opcode);
3019           }
3020       }
3021       return 1;
3022     }
3023 }
3024
3025 /* Reads LENGTH string bytes from R into S.  LENGTH must be a multiple of 8.
3026    Reads compressed strings if S is compressed.  Returns 1 if successful, 0 if
3027    end of file is reached immediately, or -1 for some kind of error. */
3028 static int
3029 read_whole_strings (struct sfm_reader *r, uint8_t *s, size_t length)
3030 {
3031   assert (length % 8 == 0);
3032   if (r->compression == ANY_COMP_NONE)
3033     return try_read_bytes (r, s, length);
3034   else
3035     {
3036       size_t ofs;
3037
3038       for (ofs = 0; ofs < length; ofs += 8)
3039         {
3040           int retval = read_compressed_string (r, s + ofs);
3041           if (retval != 1)
3042             {
3043               if (ofs != 0)
3044                 {
3045                   partial_record (r);
3046                   return -1;
3047                 }
3048               return retval;
3049             }
3050           }
3051       return 1;
3052     }
3053 }
3054
3055 /* Skips LENGTH string bytes from R.
3056    LENGTH must be a multiple of 8.
3057    (LENGTH is also limited to 1024, but that's only because the
3058    current caller never needs more than that many bytes.)
3059    Returns true if successful, false if end of file is
3060    reached immediately. */
3061 static bool
3062 skip_whole_strings (struct sfm_reader *r, size_t length)
3063 {
3064   uint8_t buffer[1024];
3065   assert (length < sizeof buffer);
3066   return read_whole_strings (r, buffer, length);
3067 }
3068 \f
3069 /* Helpers for reading records that contain structured text
3070    strings. */
3071
3072 /* Maximum number of warnings to issue for a single text
3073    record. */
3074 #define MAX_TEXT_WARNINGS 5
3075
3076 /* State. */
3077 struct text_record
3078   {
3079     struct substring buffer;    /* Record contents. */
3080     off_t start;                /* Starting offset in file. */
3081     size_t pos;                 /* Current position in buffer. */
3082     int n_warnings;             /* Number of warnings issued or suppressed. */
3083     bool recoded;               /* Recoded into UTF-8? */
3084   };
3085
3086 static struct text_record *
3087 open_text_record (struct sfm_reader *r,
3088                   const struct sfm_extension_record *record,
3089                   bool recode_to_utf8)
3090 {
3091   struct text_record *text;
3092   struct substring raw;
3093
3094   text = pool_alloc (r->pool, sizeof *text);
3095   raw = ss_buffer (record->data, record->size * record->count);
3096   text->start = record->pos;
3097   text->buffer = (recode_to_utf8
3098                   ? recode_substring_pool ("UTF-8", r->encoding, raw, r->pool)
3099                   : raw);
3100   text->pos = 0;
3101   text->n_warnings = 0;
3102   text->recoded = recode_to_utf8;
3103
3104   return text;
3105 }
3106
3107 /* Closes TEXT, frees its storage, and issues a final warning
3108    about suppressed warnings if necessary. */
3109 static void
3110 close_text_record (struct sfm_reader *r, struct text_record *text)
3111 {
3112   if (text->n_warnings > MAX_TEXT_WARNINGS)
3113     sys_warn (r, -1, _("Suppressed %d additional related warnings."),
3114               text->n_warnings - MAX_TEXT_WARNINGS);
3115   if (text->recoded)
3116     pool_free (r->pool, ss_data (text->buffer));
3117 }
3118
3119 /* Reads a variable=value pair from TEXT.
3120    Looks up the variable in DICT and stores it into *VAR.
3121    Stores a null-terminated value into *VALUE. */
3122 static bool
3123 read_variable_to_value_pair (struct sfm_reader *r, struct dictionary *dict,
3124                              struct text_record *text,
3125                              struct variable **var, char **value)
3126 {
3127   for (;;)
3128     {
3129       if (!text_read_short_name (r, dict, text, ss_cstr ("="), var))
3130         return false;
3131
3132       *value = text_get_token (text, ss_buffer ("\t\0", 2), NULL);
3133       if (*value == NULL)
3134         return false;
3135
3136       text->pos += ss_span (ss_substr (text->buffer, text->pos, SIZE_MAX),
3137                             ss_buffer ("\t\0", 2));
3138
3139       if (*var != NULL)
3140         return true;
3141     }
3142 }
3143
3144 static bool
3145 text_read_variable_name (struct sfm_reader *r, struct dictionary *dict,
3146                          struct text_record *text, struct substring delimiters,
3147                          struct variable **var)
3148 {
3149   char *name;
3150
3151   name = text_get_token (text, delimiters, NULL);
3152   if (name == NULL)
3153     return false;
3154
3155   *var = dict_lookup_var (dict, name);
3156   if (*var != NULL)
3157     return true;
3158
3159   text_warn (r, text, _("Dictionary record refers to unknown variable %s."),
3160              name);
3161   return false;
3162 }
3163
3164
3165 static bool
3166 text_read_short_name (struct sfm_reader *r, struct dictionary *dict,
3167                       struct text_record *text, struct substring delimiters,
3168                       struct variable **var)
3169 {
3170   char *short_name = text_get_token (text, delimiters, NULL);
3171   if (short_name == NULL)
3172     return false;
3173
3174   *var = dict_lookup_var (dict, short_name);
3175   if (*var == NULL)
3176     text_warn (r, text, _("Dictionary record refers to unknown variable %s."),
3177                short_name);
3178   return true;
3179 }
3180
3181 /* Displays a warning for the current file position, limiting the
3182    number to MAX_TEXT_WARNINGS for TEXT. */
3183 static void
3184 text_warn (struct sfm_reader *r, struct text_record *text,
3185            const char *format, ...)
3186 {
3187   if (text->n_warnings++ < MAX_TEXT_WARNINGS)
3188     {
3189       va_list args;
3190
3191       va_start (args, format);
3192       sys_msg (r, text->start + text->pos, MW, format, args);
3193       va_end (args);
3194     }
3195 }
3196
3197 static char *
3198 text_get_token (struct text_record *text, struct substring delimiters,
3199                 char *delimiter)
3200 {
3201   struct substring token;
3202   char *end;
3203
3204   if (!ss_tokenize (text->buffer, delimiters, &text->pos, &token))
3205     {
3206       if (delimiter != NULL)
3207         *delimiter = ss_data (text->buffer)[text->pos-1];
3208       return NULL;
3209     }
3210
3211   end = &ss_data (token)[ss_length (token)];
3212   if (delimiter != NULL)
3213     *delimiter = *end;
3214   *end = '\0';
3215   return ss_data (token);
3216 }
3217
3218 /* Reads a integer value expressed in decimal, then a space, then a string that
3219    consists of exactly as many bytes as specified by the integer, then a space,
3220    from TEXT.  Returns the string, null-terminated, as a subset of TEXT's
3221    buffer (so the caller should not free the string). */
3222 static const char *
3223 text_parse_counted_string (struct sfm_reader *r, struct text_record *text)
3224 {
3225   size_t start;
3226   size_t n;
3227   char *s;
3228
3229   start = text->pos;
3230   n = 0;
3231   while (text->pos < text->buffer.length)
3232     {
3233       int c = text->buffer.string[text->pos];
3234       if (c < '0' || c > '9')
3235         break;
3236       n = (n * 10) + (c - '0');
3237       text->pos++;
3238     }
3239   if (text->pos >= text->buffer.length || start == text->pos)
3240     {
3241       sys_warn (r, text->start,
3242                 _("Expecting digit at offset %zu in MRSETS record."),
3243                 text->pos);
3244       return NULL;
3245     }
3246
3247   if (!text_match (text, ' '))
3248     {
3249       sys_warn (r, text->start,
3250                 _("Expecting space at offset %zu in MRSETS record."),
3251                 text->pos);
3252       return NULL;
3253     }
3254
3255   if (text->pos + n > text->buffer.length)
3256     {
3257       sys_warn (r, text->start,
3258                 _("%zu-byte string starting at offset %zu "
3259                   "exceeds record length %zu."),
3260                 n, text->pos, text->buffer.length);
3261       return NULL;
3262     }
3263
3264   s = &text->buffer.string[text->pos];
3265   if (s[n] != ' ')
3266     {
3267       sys_warn (r, text->start,
3268                 _("Expecting space at offset %zu following %zu-byte string."),
3269                 text->pos + n, n);
3270       return NULL;
3271     }
3272   s[n] = '\0';
3273   text->pos += n + 1;
3274   return s;
3275 }
3276
3277 static bool
3278 text_match (struct text_record *text, char c)
3279 {
3280   if (text->pos >= text->buffer.length)
3281     return false;
3282
3283   if (text->buffer.string[text->pos] == c)
3284     {
3285       text->pos++;
3286       return true;
3287     }
3288   else
3289     return false;
3290 }
3291
3292 /* Returns the current byte offset (as converted to UTF-8, if it was converted)
3293    inside the TEXT's string. */
3294 static size_t
3295 text_pos (const struct text_record *text)
3296 {
3297   return text->pos;
3298 }
3299
3300 static const char *
3301 text_get_all (const struct text_record *text)
3302 {
3303   return text->buffer.string;
3304 }
3305 \f
3306 /* Messages. */
3307
3308 /* Displays a corruption message. */
3309 static void
3310 sys_msg (struct sfm_reader *r, off_t offset,
3311          int class, const char *format, va_list args)
3312 {
3313   struct string text;
3314
3315   ds_init_empty (&text);
3316   if (offset >= 0)
3317     ds_put_format (&text, _("`%s' near offset 0x%llx: "),
3318                    fh_get_file_name (r->fh), (long long int) offset);
3319   else
3320     ds_put_format (&text, _("`%s': "), fh_get_file_name (r->fh));
3321   ds_put_vformat (&text, format, args);
3322
3323   struct msg *m = xmalloc (sizeof *m);
3324   *m = (struct msg) {
3325     .category = msg_class_to_category (class),
3326     .severity = msg_class_to_severity (class),
3327     .text = ds_steal_cstr (&text),
3328   };
3329   msg_emit (m);
3330 }
3331
3332 /* Displays a warning for offset OFFSET in the file. */
3333 static void
3334 sys_warn (struct sfm_reader *r, off_t offset, const char *format, ...)
3335 {
3336   va_list args;
3337
3338   va_start (args, format);
3339   sys_msg (r, offset, MW, format, args);
3340   va_end (args);
3341 }
3342
3343 /* Displays an error for the current file position and marks it as in an error
3344    state. */
3345 static void
3346 sys_error (struct sfm_reader *r, off_t offset, const char *format, ...)
3347 {
3348   va_list args;
3349
3350   va_start (args, format);
3351   sys_msg (r, offset, ME, format, args);
3352   va_end (args);
3353
3354   r->error = true;
3355 }
3356 \f
3357 /* Reads BYTE_CNT bytes into BUF.
3358    Returns 1 if exactly BYTE_CNT bytes are successfully read.
3359    Returns -1 if an I/O error or a partial read occurs.
3360    Returns 0 for an immediate end-of-file and, if EOF_IS_OK is false, reports
3361    an error. */
3362 static inline int
3363 read_bytes_internal (struct sfm_reader *r, bool eof_is_ok,
3364                      void *buf, size_t n_bytes)
3365 {
3366   size_t bytes_read = fread (buf, 1, n_bytes, r->file);
3367   r->pos += bytes_read;
3368   if (bytes_read == n_bytes)
3369     return 1;
3370   else if (ferror (r->file))
3371     {
3372       sys_error (r, r->pos, _("System error: %s."), strerror (errno));
3373       return -1;
3374     }
3375   else if (!eof_is_ok || bytes_read != 0)
3376     {
3377       sys_error (r, r->pos, _("Unexpected end of file."));
3378       return -1;
3379     }
3380   else
3381     return 0;
3382 }
3383
3384 /* Reads BYTE_CNT into BUF.
3385    Returns true if successful.
3386    Returns false upon I/O error or if end-of-file is encountered. */
3387 static bool
3388 read_bytes (struct sfm_reader *r, void *buf, size_t n_bytes)
3389 {
3390   return read_bytes_internal (r, false, buf, n_bytes) == 1;
3391 }
3392
3393 /* Reads BYTE_CNT bytes into BUF.
3394    Returns 1 if exactly BYTE_CNT bytes are successfully read.
3395    Returns 0 if an immediate end-of-file is encountered.
3396    Returns -1 if an I/O error or a partial read occurs. */
3397 static int
3398 try_read_bytes (struct sfm_reader *r, void *buf, size_t n_bytes)
3399 {
3400   return read_bytes_internal (r, true, buf, n_bytes);
3401 }
3402
3403 /* Reads a 32-bit signed integer from R and stores its value in host format in
3404    *X.  Returns true if successful, otherwise false. */
3405 static bool
3406 read_int (struct sfm_reader *r, int *x)
3407 {
3408   uint8_t integer[4];
3409   if (read_bytes (r, integer, sizeof integer) != 1)
3410     return false;
3411   *x = integer_get (r->integer_format, integer, sizeof integer);
3412   return true;
3413 }
3414
3415 static bool
3416 read_uint (struct sfm_reader *r, unsigned int *x)
3417 {
3418   bool ok;
3419   int y;
3420
3421   ok = read_int (r, &y);
3422   *x = y;
3423   return ok;
3424 }
3425
3426 /* Reads a 64-bit signed integer from R and returns its value in
3427    host format. */
3428 static bool
3429 read_int64 (struct sfm_reader *r, long long int *x)
3430 {
3431   uint8_t integer[8];
3432   if (read_bytes (r, integer, sizeof integer) != 1)
3433     return false;
3434   *x = integer_get (r->integer_format, integer, sizeof integer);
3435   return true;
3436 }
3437
3438 /* Reads a 64-bit signed integer from R and returns its value in
3439    host format. */
3440 static bool
3441 read_uint64 (struct sfm_reader *r, unsigned long long int *x)
3442 {
3443   long long int y;
3444   bool ok;
3445
3446   ok = read_int64 (r, &y);
3447   *x = y;
3448   return ok;
3449 }
3450
3451 static int
3452 parse_int (const struct sfm_reader *r, const void *data, size_t ofs)
3453 {
3454   return integer_get (r->integer_format, (const uint8_t *) data + ofs, 4);
3455 }
3456
3457 static double
3458 parse_float (const struct sfm_reader *r, const void *data, size_t ofs)
3459 {
3460   return float_get_double (r->float_format, (const uint8_t *) data + ofs);
3461 }
3462
3463 /* Reads exactly SIZE - 1 bytes into BUFFER
3464    and stores a null byte into BUFFER[SIZE - 1]. */
3465 static bool
3466 read_string (struct sfm_reader *r, char *buffer, size_t size)
3467 {
3468   bool ok;
3469
3470   assert (size > 0);
3471   ok = read_bytes (r, buffer, size - 1);
3472   if (ok)
3473     buffer[size - 1] = '\0';
3474   return ok;
3475 }
3476
3477 /* Skips BYTES bytes forward in R. */
3478 static bool
3479 skip_bytes (struct sfm_reader *r, size_t bytes)
3480 {
3481   while (bytes > 0)
3482     {
3483       char buffer[1024];
3484       size_t chunk = MIN (sizeof buffer, bytes);
3485       if (!read_bytes (r, buffer, chunk))
3486         return false;
3487       bytes -= chunk;
3488     }
3489
3490   return true;
3491 }
3492
3493 /* Returns a malloc()'d copy of S in which all lone CRs and CR LF pairs have
3494    been replaced by LFs.
3495
3496    (A product that identifies itself as VOXCO INTERVIEWER 4.3 produces system
3497    files that use CR-only line ends in the file label and extra product
3498    info.) */
3499 static char *
3500 fix_line_ends (const char *s)
3501 {
3502   char *dst, *d;
3503
3504   d = dst = xmalloc (strlen (s) + 1);
3505   while (*s != '\0')
3506     {
3507       if (*s == '\r')
3508         {
3509           s++;
3510           if (*s == '\n')
3511             s++;
3512           *d++ = '\n';
3513         }
3514       else
3515         *d++ = *s++;
3516     }
3517   *d = '\0';
3518
3519   return dst;
3520 }
3521 \f
3522 static bool
3523 read_ztrailer (struct sfm_reader *r,
3524                long long int zheader_ofs,
3525                long long int ztrailer_len);
3526
3527 static void *
3528 zalloc (voidpf pool_, uInt items, uInt size)
3529 {
3530   struct pool *pool = pool_;
3531
3532   return (!size || xalloc_oversized (items, size)
3533           ? Z_NULL
3534           : pool_malloc (pool, items * size));
3535 }
3536
3537 static void
3538 zfree (voidpf pool_, voidpf address)
3539 {
3540   struct pool *pool = pool_;
3541
3542   pool_free (pool, address);
3543 }
3544
3545 static bool
3546 read_zheader (struct sfm_reader *r)
3547 {
3548   off_t pos = r->pos;
3549   long long int zheader_ofs;
3550   long long int ztrailer_ofs;
3551   long long int ztrailer_len;
3552
3553   if (!read_int64 (r, &zheader_ofs)
3554       || !read_int64 (r, &ztrailer_ofs)
3555       || !read_int64 (r, &ztrailer_len))
3556     return false;
3557
3558   if (zheader_ofs != pos)
3559     {
3560       sys_error (r, pos, _("Wrong ZLIB data header offset %#llx "
3561                            "(expected %#llx)."),
3562                  zheader_ofs, (long long int) pos);
3563       return false;
3564     }
3565
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   };