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