Don't assume that MEASURE_* and ALIGN_* have the same values found in
[pspp-builds.git] / src / data / sys-file-reader.c
1 /* PSPP - computes sample statistics.
2    Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
3
4    This program is free software; you can redistribute it and/or
5    modify it under the terms of the GNU General Public License as
6    published by the Free Software Foundation; either version 2 of the
7    License, or (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful, but
10    WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    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, write to the Free Software
16    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17    02110-1301, USA. */
18
19 #include <config.h>
20
21 #include "sys-file-reader.h"
22 #include "sys-file-private.h"
23
24 #include <errno.h>
25 #include <float.h>
26 #include <inttypes.h>
27 #include <setjmp.h>
28 #include <stdlib.h>
29
30 #include <libpspp/alloc.h>
31 #include <libpspp/assertion.h>
32 #include <libpspp/message.h>
33 #include <libpspp/compiler.h>
34 #include <libpspp/magic.h>
35 #include <libpspp/misc.h>
36 #include <libpspp/pool.h>
37 #include <libpspp/str.h>
38 #include <libpspp/hash.h>
39 #include <libpspp/array.h>
40
41 #include "case.h"
42 #include "dictionary.h"
43 #include "file-handle-def.h"
44 #include "file-name.h"
45 #include "format.h"
46 #include "missing-values.h"
47 #include "value-labels.h"
48 #include "variable.h"
49 #include "value.h"
50
51 #include "c-ctype.h"
52 #include "inttostr.h"
53 #include "minmax.h"
54 #include "unlocked-io.h"
55 #include "xsize.h"
56
57 #include "gettext.h"
58 #define _(msgid) gettext (msgid)
59 #define N_(msgid) (msgid)
60
61 /* System file reader. */
62 struct sfm_reader
63   {
64     /* Resource tracking. */
65     struct pool *pool;          /* All system file state. */
66     jmp_buf bail_out;           /* longjmp() target for error handling. */
67
68     /* File state. */
69     struct file_handle *fh;     /* File handle. */
70     FILE *file;                 /* File stream. */
71     bool error;                 /* I/O or corruption error? */
72
73     /* File format. */
74     enum integer_format integer_format; /* On-disk integer format. */
75     enum float_format float_format; /* On-disk floating point format. */
76     int value_cnt;              /* Number of 8-byte units per case. */
77     struct sfm_var *vars;       /* Variables. */
78     size_t var_cnt;             /* Number of variables. */
79     bool has_vls;               /* File has one or more very long strings? */
80
81     /* Decompression. */
82     bool compressed;            /* File is compressed? */
83     double bias;                /* Compression bias, usually 100.0. */
84     uint8_t opcodes[8];         /* Current block of opcodes. */
85     size_t opcode_idx;          /* Next opcode to interpret, 8 if none left. */
86   };
87
88 /* A variable in a system file. */
89 struct sfm_var 
90   {
91     int width;                  /* 0=numeric, otherwise string width. */
92     int case_index;             /* Index into case. */
93   };
94
95 static struct variable **make_var_by_value_idx (struct sfm_reader *,
96                                                 struct dictionary *);
97 static struct variable *lookup_var_by_value_idx (struct sfm_reader *,
98                                                  struct variable **,
99                                                  int value_idx);
100
101 static void sys_warn (struct sfm_reader *, const char *, ...)
102      PRINTF_FORMAT (2, 3);
103
104 static void sys_error (struct sfm_reader *, const char *, ...)
105      PRINTF_FORMAT (2, 3)
106      NO_RETURN;
107
108 static void read_bytes (struct sfm_reader *, void *, size_t);
109 static bool try_read_bytes (struct sfm_reader *, void *, size_t);
110 static int32_t read_int32 (struct sfm_reader *);
111 static double read_flt64 (struct sfm_reader *);
112 static void read_string (struct sfm_reader *, char *, size_t);
113 static void skip_bytes (struct sfm_reader *, size_t);
114
115 static int32_t int32_to_native (const struct sfm_reader *, const uint8_t[4]);
116 static double flt64_to_double (const struct sfm_reader *, const uint8_t[8]);
117
118 static struct variable_to_value_map *open_variable_to_value_map (
119   struct sfm_reader *, size_t size);
120 static void close_variable_to_value_map (struct sfm_reader *r,
121                                          struct variable_to_value_map *);
122 static bool read_variable_to_value_map (struct sfm_reader *,
123                                         struct dictionary *,
124                                         struct variable_to_value_map *,
125                                         struct variable **var, char **value,
126                                         int *warning_cnt);
127 \f
128 /* Dictionary reader. */
129
130 enum which_format 
131   {
132     PRINT_FORMAT,
133     WRITE_FORMAT
134   };
135
136 static void read_header (struct sfm_reader *, struct dictionary *,
137                          int *weight_idx, int *claimed_value_cnt,
138                          struct sfm_read_info *);
139 static void read_variable_record (struct sfm_reader *, struct dictionary *,
140                                   int *format_warning_cnt);
141 static void parse_format_spec (struct sfm_reader *, uint32_t,
142                                enum which_format, struct variable *,
143                                int *format_warning_cnt);
144 static void setup_weight (struct sfm_reader *, int weight_idx,
145                           struct variable **var_by_value_idx,
146                           struct dictionary *);
147 static void read_documents (struct sfm_reader *, struct dictionary *);
148 static void read_value_labels (struct sfm_reader *, struct dictionary *,
149                                struct variable **var_by_value_idx);
150
151 static void read_extension_record (struct sfm_reader *, struct dictionary *);
152 static void read_machine_int32_info (struct sfm_reader *,
153                                      size_t size, size_t count);
154 static void read_machine_flt64_info (struct sfm_reader *,
155                                      size_t size, size_t count);
156 static void read_display_parameters (struct sfm_reader *,
157                                      size_t size, size_t count,
158                                      struct dictionary *);
159 static void read_long_var_name_map (struct sfm_reader *,
160                                     size_t size, size_t count,
161                                     struct dictionary *);
162 static void read_long_string_map (struct sfm_reader *,
163                                   size_t size, size_t count,
164                                   struct dictionary *);
165
166
167 /* Opens the system file designated by file handle FH for
168    reading.  Reads the system file's dictionary into *DICT.
169    If INFO is non-null, then it receives additional info about the
170    system file. */
171 struct sfm_reader *
172 sfm_open_reader (struct file_handle *fh, struct dictionary **dict,
173                  struct sfm_read_info *info)
174 {
175   struct sfm_reader *volatile r = NULL;
176   struct variable **var_by_value_idx;
177   int format_warning_cnt = 0;
178   int weight_idx;
179   int claimed_value_cnt;
180   int rec_type;
181   size_t i;
182
183   if (!fh_open (fh, FH_REF_FILE, "system file", "rs"))
184     return NULL;
185
186   *dict = dict_create ();
187
188   /* Create and initialize reader. */
189   r = pool_create_container (struct sfm_reader, pool);
190   r->fh = fh;
191   r->file = fn_open (fh_get_file_name (fh), "rb");
192   r->error = false;
193   r->value_cnt = 0;
194   r->has_vls = false;
195   r->opcode_idx = sizeof r->opcodes;
196
197   if (setjmp (r->bail_out)) 
198     {
199       sfm_close_reader (r);
200       dict_destroy (*dict);
201       *dict = NULL;
202       return NULL;
203     }
204
205   if (r->file == NULL)
206     {
207       msg (ME, _("Error opening \"%s\" for reading as a system file: %s."),
208            fh_get_file_name (r->fh), strerror (errno));
209       longjmp (r->bail_out, 1);
210     }
211
212   /* Read header. */
213   read_header (r, *dict, &weight_idx, &claimed_value_cnt, info);
214
215   /* Read all the variable definition records. */
216   rec_type = read_int32 (r);
217   while (rec_type == 2)
218     {
219       read_variable_record (r, *dict, &format_warning_cnt); 
220       rec_type = read_int32 (r);
221     }
222
223   /* Figure out the case format. */
224   var_by_value_idx = make_var_by_value_idx (r, *dict);
225   setup_weight (r, weight_idx, var_by_value_idx, *dict);
226
227   /* Read all the rest of the dictionary records. */
228   while (rec_type != 999) 
229     {
230       switch (rec_type)
231         {
232         case 3:
233           read_value_labels (r, *dict, var_by_value_idx);
234           break;
235
236         case 4:
237           sys_error (r, _("Misplaced type 4 record."));
238
239         case 6:
240           read_documents (r, *dict);
241           break;
242
243         case 7:
244           read_extension_record (r, *dict);
245           break;
246
247         default:
248           sys_error (r, _("Unrecognized record type %d."), rec_type);
249         }
250       rec_type = read_int32 (r);
251     }
252
253   /* Read record 999 data, which is just filler. */
254   read_int32 (r);
255
256   if (claimed_value_cnt != -1 && claimed_value_cnt != r->value_cnt)
257     sys_warn (r, _("File header claims %d variable positions but "
258                    "%d were read from file."),
259               claimed_value_cnt, r->value_cnt);
260
261   /* Create an index of dictionary variable widths for
262      sfm_read_case to use.  We cannot use the `struct variable's
263      from the dictionary we created, because the caller owns the
264      dictionary and may destroy or modify its variables. */
265   r->var_cnt = dict_get_var_cnt (*dict);
266   r->vars = pool_nalloc (r->pool, r->var_cnt, sizeof *r->vars);
267   for (i = 0; i < r->var_cnt; i++) 
268     {
269       struct variable *v = dict_get_var (*dict, i);
270       struct sfm_var *sv = &r->vars[i];
271       sv->width = var_get_width (v);
272       sv->case_index = var_get_case_index (v); 
273     }
274
275   pool_free (r->pool, var_by_value_idx);
276   return r;
277 }
278
279 /* Closes a system file after we're done with it. */
280 void
281 sfm_close_reader (struct sfm_reader *r)
282 {
283   if (r == NULL)
284     return;
285
286   if (r->file)
287     {
288       if (fn_close (fh_get_file_name (r->fh), r->file) == EOF)
289         msg (ME, _("Error closing system file \"%s\": %s."),
290              fh_get_file_name (r->fh), strerror (errno));
291       r->file = NULL;
292     }
293
294   if (r->fh != NULL)
295     fh_close (r->fh, "system file", "rs");
296
297   pool_destroy (r->pool);
298 }
299
300 /* Returns true if an I/O error has occurred on READER, false
301    otherwise. */
302 bool
303 sfm_read_error (const struct sfm_reader *reader) 
304 {
305   return reader->error;
306 }
307
308 /* Returns true if FILE is an SPSS system file,
309    false otherwise. */
310 bool
311 sfm_detect (FILE *file) 
312 {
313   char rec_type[5];
314
315   if (fread (rec_type, 4, 1, file) != 1)
316     return false;
317   rec_type[4] = '\0';
318   
319   return !strcmp ("$FL2", rec_type);
320 }
321 \f
322 /* Reads the global header of the system file.
323    Sets DICT's file label to the system file's label.
324    Sets *WEIGHT_IDX to 0 if the system file is unweighted,
325    or to the value index of the weight variable otherwise.
326    Sets *CLAIMED_VALUE_CNT to the number of values that the file
327    claims to have (although it is not always correct).
328    If INFO is non-null, initializes *INFO with header
329    information. */   
330 static void
331 read_header (struct sfm_reader *r, struct dictionary *dict,
332              int *weight_idx, int *claimed_value_cnt,
333              struct sfm_read_info *info)
334 {
335   char rec_type[5];
336   char eye_catcher[61];
337   uint8_t raw_layout_code[4];
338   int case_cnt;
339   uint8_t raw_bias[8];
340   char creation_date[10];
341   char creation_time[9];
342   char file_label[65];
343   struct substring file_label_ss;
344
345   read_string (r, rec_type, sizeof rec_type);
346   read_string (r, eye_catcher, sizeof eye_catcher);
347   
348   if (strcmp ("$FL2", rec_type) != 0)
349     sys_error (r, _("This is not an SPSS system file."));
350
351   /* Identify integer format. */
352   read_bytes (r, raw_layout_code, sizeof raw_layout_code);
353   if ((!integer_identify (2, raw_layout_code, sizeof raw_layout_code,
354                           &r->integer_format)
355        && !integer_identify (3, raw_layout_code, sizeof raw_layout_code,
356                              &r->integer_format))
357       || (r->integer_format != INTEGER_MSB_FIRST
358           && r->integer_format != INTEGER_LSB_FIRST))
359     sys_error (r, _("This is not an SPSS system file."));
360
361   *claimed_value_cnt = read_int32 (r);
362   if (*claimed_value_cnt < 0 || *claimed_value_cnt > INT_MAX / 16)
363     *claimed_value_cnt = -1;
364
365   r->compressed = read_int32 (r) != 0;
366
367   *weight_idx = read_int32 (r);
368
369   case_cnt = read_int32 (r);
370   if (case_cnt < -1 || case_cnt > INT_MAX / 2)
371     case_cnt = -1;
372
373   /* Identify floating-point format and obtain compression bias. */
374   read_bytes (r, raw_bias, sizeof raw_bias);
375   if (float_identify (100.0, raw_bias, sizeof raw_bias, &r->float_format) == 0)
376     {
377       sys_warn (r, _("Compression bias (%g) is not the usual "
378                      "value of 100, or system file uses unrecognized "
379                      "floating-point format."),
380                 r->bias);
381       if (r->integer_format == INTEGER_MSB_FIRST)
382         r->float_format = FLOAT_IEEE_DOUBLE_BE;
383       else
384         r->float_format = FLOAT_IEEE_DOUBLE_LE;
385     }
386   float_convert (r->float_format, raw_bias, FLOAT_NATIVE_DOUBLE, &r->bias);
387
388   read_string (r, creation_date, sizeof creation_date);
389   read_string (r, creation_time, sizeof creation_time);
390   read_string (r, file_label, sizeof file_label);
391   skip_bytes (r, 3);
392   
393   file_label_ss = ss_cstr (file_label);
394   ss_trim (&file_label_ss, ss_cstr (" "));
395   if (!ss_is_empty (file_label_ss)) 
396     {
397       ss_data (file_label_ss)[ss_length (file_label_ss)] = '\0';
398       dict_set_label (dict, ss_data (file_label_ss));
399     }
400
401   if (info)
402     {
403       struct substring product;
404
405       strcpy (info->creation_date, creation_date);
406       strcpy (info->creation_time, creation_time);
407       info->integer_format = r->integer_format;
408       info->float_format = r->float_format;
409       info->compressed = r->compressed;
410       info->case_cnt = case_cnt;
411
412       product = ss_cstr (eye_catcher);
413       ss_match_string (&product, ss_cstr ("@(#) SPSS DATA FILE"));
414       ss_trim (&product, ss_cstr (" "));
415       str_copy_buf_trunc (info->product, sizeof info->product,
416                           ss_data (product), ss_length (product));
417     }
418 }
419
420 /* Reads a variable (type 2) record from R and adds the
421    corresponding variable to DICT.
422    Also skips past additional variable records for long string
423    variables. */
424 static void
425 read_variable_record (struct sfm_reader *r, struct dictionary *dict,
426                       int *format_warning_cnt)
427 {
428   int width;
429   int has_variable_label;
430   int missing_value_code;
431   int print_format;
432   int write_format;
433   char name[9];
434
435   struct variable *var;
436   int nv;
437
438   width = read_int32 (r);
439   has_variable_label = read_int32 (r);
440   missing_value_code = read_int32 (r);
441   print_format = read_int32 (r);
442   write_format = read_int32 (r);
443   read_string (r, name, sizeof name);
444   name[strcspn (name, " ")] = '\0';
445
446   /* Check variable name. */
447   if (name[0] == '$' || name[0] == '#')
448     sys_error (r, "Variable name begins with invalid character `%c'.",
449                name[0]);
450   if (!var_is_plausible_name (name, false))
451     sys_error (r, _("Invalid variable name `%s'."), name);
452
453   /* Create variable. */
454   if (width < 0 || width > 255)
455     sys_error (r, _("Bad variable width %d."), width);
456   var = dict_create_var (dict, name, width);
457   if (var == NULL) 
458     sys_error (r,
459                _("Duplicate variable name `%s' within system file."),
460                name);
461
462   /* Set the short name the same as the long name */
463   var_set_short_name (var, var_get_name (var));
464
465   /* Get variable label, if any. */
466   if (has_variable_label != 0 && has_variable_label != 1)
467     sys_error (r, _("Variable label indicator field is not 0 or 1."));
468   if (has_variable_label == 1)
469     {
470       size_t len;
471       char label[255 + 1];
472
473       len = read_int32 (r);
474       if (len >= sizeof label)
475         sys_error (r, _("Variable %s has label of invalid length %d."),
476                    name, len);
477       read_string (r, label, len + 1);
478       var_set_label (var, label);
479       
480       skip_bytes (r, ROUND_UP (len, 4) - len);
481     }
482
483   /* Set missing values. */
484   if (missing_value_code < -3 || missing_value_code > 3
485       || missing_value_code == -1)
486     sys_error (r, _("Missing value indicator field is not "
487                     "-3, -2, 0, 1, 2, or 3."));
488   if (missing_value_code != 0)
489     {
490       struct missing_values mv;
491       mv_init (&mv, var_get_width (var));
492       if (var_is_numeric (var)) 
493         {
494           if (missing_value_code > 0)
495             {
496               int i;
497               for (i = 0; i < missing_value_code; i++)
498                 mv_add_num (&mv, read_flt64 (r));
499             }
500           else
501             {
502               double low = read_flt64 (r);
503               double high = read_flt64 (r);
504               mv_add_num_range (&mv, low, high);
505               if (missing_value_code == -3)
506                 mv_add_num (&mv, read_flt64 (r));
507             }
508         }
509       else if (var_get_width (var) <= MAX_SHORT_STRING)
510         {
511           if (missing_value_code > 0)
512             {
513               int i;
514               for (i = 0; i < missing_value_code; i++)
515                 {
516                   char string[9];
517                   read_string (r, string, sizeof string);
518                   mv_add_str (&mv, string); 
519                 }
520             }
521           else 
522             sys_error (r, _("String variable %s may not have missing "
523                             "values specified as a range."),
524                        name);
525         }
526       else /* var->width > MAX_SHORT_STRING */
527         sys_error (r, _("Long string variable %s may not have missing "
528                         "values."),
529                    name);
530       var_set_missing_values (var, &mv);
531     }
532
533   /* Set formats. */
534   parse_format_spec (r, print_format, PRINT_FORMAT, var, format_warning_cnt);
535   parse_format_spec (r, write_format, WRITE_FORMAT, var, format_warning_cnt);
536
537   /* Account for values.
538      Skip long string continuation records, if any. */
539   nv = width == 0 ? 1 : DIV_RND_UP (width, 8);
540   r->value_cnt += nv;
541   if (width > 8)
542     {
543       int i;
544
545       for (i = 1; i < nv; i++)
546         {
547           /* Check for record type 2 and width -1. */
548           if (read_int32 (r) != 2 || read_int32 (r) != -1)
549             sys_error (r, _("Missing string continuation record."));
550
551           /* Skip and ignore remaining continuation data. */
552           has_variable_label = read_int32 (r);
553           missing_value_code = read_int32 (r);
554           print_format = read_int32 (r);
555           write_format = read_int32 (r);
556           read_string (r, name, sizeof name);
557
558           /* Variable label fields on continuation records have
559              been spotted in system files created by "SPSS Power
560              Macintosh Release 6.1". */
561           if (has_variable_label) 
562             skip_bytes (r, ROUND_UP (read_int32 (r), 4));
563         }
564     }
565 }
566
567 /* Translates the format spec from sysfile format to internal
568    format. */
569 static void
570 parse_format_spec (struct sfm_reader *r, uint32_t s,
571                    enum which_format which, struct variable *v,
572                    int *format_warning_cnt)
573 {
574   const int max_format_warnings = 8;
575   struct fmt_spec f;
576   uint8_t raw_type = s >> 16;
577   uint8_t w = s >> 8;
578   uint8_t d = s;
579   
580   bool ok;
581   
582   if (!fmt_from_io (raw_type, &f.type))
583     sys_error (r, _("Unknown variable format %d."), (int) raw_type);
584   f.w = w;
585   f.d = d;
586
587   msg_disable ();
588   ok = fmt_check_output (&f) && fmt_check_width_compat (&f, var_get_width (v));
589   msg_enable ();
590   
591   if (ok) 
592     {
593       if (which == PRINT_FORMAT)
594         var_set_print_format (v, &f);
595       else
596         var_set_write_format (v, &f);
597     }
598   else if (*++format_warning_cnt <= max_format_warnings)
599     {
600       char fmt_string[FMT_STRING_LEN_MAX + 1];
601       sys_warn (r, _("%s variable %s has invalid %s format %s."),
602                 var_is_numeric (v) ? _("Numeric") : _("String"),
603                 var_get_name (v),
604                 which == PRINT_FORMAT ? _("print") : _("write"),
605                 fmt_to_string (&f, fmt_string));
606
607       if (*format_warning_cnt == max_format_warnings)
608         sys_warn (r, _("Suppressing further invalid format warnings."));
609     }
610 }
611
612 /* Sets the weighting variable in DICT to the variable
613    corresponding to the given 1-based VALUE_IDX, if VALUE_IDX is
614    nonzero. */
615 static void
616 setup_weight (struct sfm_reader *r, int weight_idx,
617               struct variable **var_by_value_idx, struct dictionary *dict) 
618 {
619   if (weight_idx != 0)
620     {
621       struct variable *weight_var
622         = lookup_var_by_value_idx (r, var_by_value_idx, weight_idx);
623       if (var_is_numeric (weight_var))
624         dict_set_weight (dict, weight_var);
625       else
626         sys_error (r, _("Weighting variable must be numeric."));
627     }
628 }
629
630 /* Reads a document record, type 6, from system file R, and sets up
631    the documents and n_documents fields in the associated
632    dictionary. */
633 static void
634 read_documents (struct sfm_reader *r, struct dictionary *dict)
635 {
636   int line_cnt;
637   char *documents;
638
639   if (dict_get_documents (dict) != NULL)
640     sys_error (r, _("Multiple type 6 (document) records."));
641
642   line_cnt = read_int32 (r);
643   if (line_cnt <= 0)
644     sys_error (r, _("Number of document lines (%d) "
645                     "must be greater than 0."), line_cnt);
646
647   documents = pool_nmalloc (r->pool, line_cnt + 1, 80);
648   read_string (r, documents, 80 * line_cnt + 1);
649   dict_set_documents (dict, documents);
650   pool_free (r->pool, documents);
651 }
652
653 /* Read a type 7 extension record. */
654 static void
655 read_extension_record (struct sfm_reader *r, struct dictionary *dict)
656 {
657   int subtype = read_int32 (r);
658   size_t size = read_int32 (r);
659   size_t count = read_int32 (r);
660   size_t bytes = size * count;
661
662   /* Check that SIZE * COUNT + 1 doesn't overflow.  Adding 1
663      allows an extra byte for a null terminator, used by some
664      extension processing routines. */
665   if (size != 0 && size_overflow_p (xsum (1, xtimes (count, size))))
666     sys_error (r, "Record type 7 subtype %d too large.", subtype);
667
668   switch (subtype)
669     {
670     case 3:
671       read_machine_int32_info (r, size, count);
672       return;
673
674     case 4:
675       read_machine_flt64_info (r, size, count);
676       return;
677
678     case 5:
679       /* Variable sets information.  We don't use these yet.
680          They only apply to GUIs; see VARSETS on the APPLY
681          DICTIONARY command in SPSS documentation. */
682       break;
683
684     case 6:
685       /* DATE variable information.  We don't use it yet, but we
686          should. */
687       break;
688                 
689     case 7:
690       /* Unknown purpose. */
691       break;
692       
693     case 11:
694       read_display_parameters (r, size, count, dict);
695       return;
696
697     case 13:
698       read_long_var_name_map (r, size, count, dict);
699       return;
700
701     case 14:
702       read_long_string_map (r, size, count, dict);
703       return;
704
705     case 16:
706       /* New in SPSS v14?  Unknown purpose.  */
707       break;
708
709     case 17:
710       /* Text field that defines variable attributes.  New in
711          SPSS 14. */
712       break;
713       
714     default:
715       sys_warn (r, _("Unrecognized record type 7, subtype %d."), subtype);
716       break;
717     }
718
719   skip_bytes (r, bytes);
720 }
721
722 /* Read record type 7, subtype 3. */
723 static void
724 read_machine_int32_info (struct sfm_reader *r, size_t size, size_t count)
725 {
726   int version_major UNUSED = read_int32 (r);
727   int version_minor UNUSED = read_int32 (r);
728   int version_revision UNUSED = read_int32 (r);
729   int machine_code UNUSED = read_int32 (r);
730   int float_representation = read_int32 (r);
731   int compression_code UNUSED = read_int32 (r);
732   int integer_representation = read_int32 (r);
733   int character_code UNUSED = read_int32 (r);
734
735   int expected_float_format;
736   int expected_integer_format;
737
738   if (size != 4 || count != 8)
739     sys_error (r, _("Bad size (%d) or count (%d) field on record type 7, "
740                     "subtype 3."),
741                size, count);
742
743   /* Check floating point format. */
744   if (r->float_format == FLOAT_IEEE_DOUBLE_BE
745       || r->float_format == FLOAT_IEEE_DOUBLE_LE)
746     expected_float_format = 1;
747   else if (r->float_format == FLOAT_Z_LONG)
748     expected_float_format = 2;
749   else if (r->float_format == FLOAT_VAX_G || r->float_format == FLOAT_VAX_D)
750     expected_float_format = 3;
751   else
752     NOT_REACHED ();
753   if (float_representation != expected_float_format)
754     sys_error (r, _("Floating-point representation indicated by "
755                     "system file (%d) differs from expected (%d)."),
756                r->float_format, expected_float_format);
757
758   /* Check integer format. */
759   if (r->integer_format == INTEGER_MSB_FIRST)
760     expected_integer_format = 1;
761   else if (r->integer_format == INTEGER_LSB_FIRST)
762     expected_integer_format = 2;
763   else
764     NOT_REACHED ();
765   if (integer_representation != expected_integer_format)
766     {
767       static const char *endian[] = {N_("little-endian"), N_("big-endian")};
768       sys_warn (r, _("Integer format indicated by system file (%s) "
769                      "differs from expected (%s)."),
770                 gettext (endian[integer_representation == 1]),
771                 gettext (endian[expected_integer_format == 1]));
772     }
773 }
774
775 /* Read record type 7, subtype 4. */
776 static void
777 read_machine_flt64_info (struct sfm_reader *r, size_t size, size_t count)
778 {
779   double sysmis = read_flt64 (r);
780   double highest = read_flt64 (r);
781   double lowest = read_flt64 (r);
782
783   if (size != 8 || count != 3)
784     sys_error (r, _("Bad size (%d) or count (%d) on extension 4."),
785                size, count);
786
787   if (sysmis != SYSMIS)
788     sys_warn (r, _("File specifies unexpected value %g as SYSMIS."), sysmis);
789   if (highest != HIGHEST)
790     sys_warn (r, _("File specifies unexpected value %g as HIGHEST."), highest);
791   if (lowest != LOWEST)
792     sys_warn (r, _("File specifies unexpected value %g as LOWEST."), lowest);
793 }
794
795 /* Read record type 7, subtype 11, which specifies how variables
796    should be displayed in GUI environments. */
797 static void
798 read_display_parameters (struct sfm_reader *r, size_t size, size_t count,
799                          struct dictionary *dict)
800 {
801   const size_t n_vars = count / 3 ;
802   bool warned = false;
803   int i;
804
805   if (count % 3 || n_vars != dict_get_var_cnt (dict)) 
806     sys_error (r, _("Bad size (%d) or count (%d) on extension 11."),
807                size, count);
808
809   for (i = 0; i < n_vars; ++i) 
810     {
811       int measure = read_int32 (r);
812       int width = read_int32 (r);
813       int align = read_int32 (r);
814       struct variable *v;
815
816       if (measure < 1 || measure > 3 || align < 0 || align > 2)
817         {
818           if (!warned)
819             sys_warn (r, _("Invalid variable display parameters.  "
820                            "Default parameters substituted."));
821           warned = true;
822           continue;
823         }
824
825       v = dict_get_var (dict, i);
826       var_set_measure (v, (measure == 1 ? MEASURE_NOMINAL
827                            : measure == 2 ? MEASURE_ORDINAL
828                            : MEASURE_SCALE));
829       var_set_display_width (v, width);
830       var_set_alignment (v, (align == 0 ? ALIGN_LEFT
831                              : align == 1 ? ALIGN_RIGHT
832                              : ALIGN_CENTRE));
833     }
834 }
835
836 /* Reads record type 7, subtype 13, which gives the long name
837    that corresponds to each short name.  Modifies variable names
838    in DICT accordingly.  */
839 static void
840 read_long_var_name_map (struct sfm_reader *r, size_t size, size_t count,
841                         struct dictionary *dict)
842 {
843   struct variable_to_value_map *map;
844   struct variable *var;
845   char *long_name;
846   int warning_cnt = 0;
847   
848   map = open_variable_to_value_map (r, size * count);
849   while (read_variable_to_value_map (r, dict, map, &var, &long_name,
850                                      &warning_cnt))
851     {
852       char short_name[SHORT_NAME_LEN + 1];
853       strcpy (short_name, var_get_short_name (var));
854
855       /* Validate long name. */
856       if (!var_is_valid_name (long_name, false))
857         {
858           sys_warn (r, _("Long variable mapping from %s to invalid "
859                          "variable name `%s'."),
860                     var_get_name (var), long_name);
861           continue;
862         }
863                       
864       /* Identify any duplicates. */
865       if (strcasecmp (short_name, long_name)
866           && dict_lookup_var (dict, long_name) != NULL)
867         {
868           sys_warn (r, _("Duplicate long variable name `%s' "
869                          "within system file."), long_name);
870           continue;
871         }
872
873       /* Set long name.  Renaming a variable may clear the short
874          name, but we want to retain it, so re-set it
875          explicitly. */
876       dict_rename_var (dict, var, long_name);
877       var_set_short_name (var, short_name);
878     }
879   close_variable_to_value_map (r, map);
880 }
881
882 /* Reads record type 7, subtype 14, which gives the real length
883    of each very long string.  Rearranges DICT accordingly. */
884 static void
885 read_long_string_map (struct sfm_reader *r, size_t size, size_t count,
886                       struct dictionary *dict)
887 {
888   struct variable_to_value_map *map;
889   struct variable *var;
890   char *length_s;
891   int warning_cnt = 0;
892
893   r->has_vls = true;
894
895   map = open_variable_to_value_map (r, size * count);
896   while (read_variable_to_value_map (r, dict, map, &var, &length_s,
897                                      &warning_cnt))
898     {
899       long length, remaining_length;
900       size_t idx;
901
902       /* Get length. */
903       length = strtol (length_s, NULL, 10);
904       if (length < MIN_VERY_LONG_STRING || length == LONG_MAX) 
905         {
906           sys_warn (r, _("%s listed as string of length %s "
907                          "in length table."),
908                     var_get_name (var), length_s);
909           continue;
910         }
911
912       /* Group multiple variables into single variable
913          and delete all but the first. */
914       remaining_length = length;
915       for (idx = var_get_dict_index (var); remaining_length > 0; idx++)
916         if (idx < dict_get_var_cnt (dict)) 
917           remaining_length -= MIN (var_get_width (dict_get_var (dict, idx)),
918                                    EFFECTIVE_LONG_STRING_LENGTH);
919         else
920           sys_error (r, _("Very long string %s overflows dictionary."),
921                      var_get_name (var));
922       dict_delete_consecutive_vars (dict,
923                                     var_get_dict_index (var) + 1,
924                                     idx - var_get_dict_index (var) - 1);
925
926       /* Assign all the length to the first variable. */
927       var_set_width (var, length);
928     }
929   close_variable_to_value_map (r, map);
930   dict_compact_values (dict);
931 }
932
933 /* Reads value labels from sysfile H and inserts them into the
934    associated dictionary. */
935 static void
936 read_value_labels (struct sfm_reader *r,
937                    struct dictionary *dict, struct variable **var_by_value_idx)
938 {
939   struct pool *subpool;
940   
941   struct label 
942     {
943       char raw_value[8];        /* Value as uninterpreted bytes. */
944       union value value;        /* Value. */
945       char *label;              /* Null-terminated label string. */
946     };
947
948   struct label *labels = NULL;
949   int label_cnt;                /* Number of labels. */
950
951   struct variable **var = NULL; /* Associated variables. */
952   int var_cnt;                  /* Number of associated variables. */
953
954   int i;
955
956   subpool = pool_create_subpool (r->pool);
957
958   /* Read the type 3 record and record its contents.  We can't do
959      much with the data yet because we don't know whether it is
960      of numeric or string type. */
961
962   /* Read number of labels. */
963   label_cnt = read_int32 (r);
964
965   if (label_cnt >= INT32_MAX / sizeof *labels)
966     {    
967       sys_warn (r, _("Invalid number of labels: %d.  Ignoring labels."),
968                 label_cnt);
969       label_cnt = 0;
970     }
971
972   /* Read each value/label tuple into labels[]. */
973   labels = pool_nalloc (subpool, label_cnt, sizeof *labels);
974   for (i = 0; i < label_cnt; i++)
975     {
976       struct label *label = labels + i;
977       unsigned char label_len;
978       size_t padded_len;
979
980       /* Read value. */
981       read_bytes (r, label->raw_value, sizeof label->raw_value);
982
983       /* Read label length. */
984       read_bytes (r, &label_len, sizeof label_len);
985       padded_len = ROUND_UP (label_len + 1, 8);
986
987       /* Read label, padding. */
988       label->label = pool_alloc (subpool, padded_len + 1);
989       read_bytes (r, label->label, padded_len - 1);
990       label->label[label_len] = 0;
991     }
992
993   /* Now, read the type 4 record that has the list of variables
994      to which the value labels are to be applied. */
995
996   /* Read record type of type 4 record. */
997   if (read_int32 (r) != 4)
998     sys_error (r, _("Variable index record (type 4) does not immediately "
999                     "follow value label record (type 3) as it should."));
1000
1001   /* Read number of variables associated with value label from type 4
1002      record. */
1003   var_cnt = read_int32 (r);
1004   if (var_cnt < 1 || var_cnt > dict_get_var_cnt (dict))
1005     sys_error (r, _("Number of variables associated with a value label (%d) "
1006                     "is not between 1 and the number of variables (%d)."),
1007                var_cnt, dict_get_var_cnt (dict));
1008
1009   /* Read the list of variables. */
1010   var = pool_nalloc (subpool, var_cnt, sizeof *var);
1011   for (i = 0; i < var_cnt; i++)
1012     {
1013       var[i] = lookup_var_by_value_idx (r, var_by_value_idx, read_int32 (r));
1014       if (var_is_long_string (var[i]))
1015         sys_error (r, _("Value labels are not allowed on long string "
1016                         "variables (%s)."), var_get_name (var[i]));
1017     }
1018
1019   /* Type check the variables. */
1020   for (i = 1; i < var_cnt; i++)
1021     if (var_get_type (var[i]) != var_get_type (var[0]))
1022       sys_error (r, _("Variables associated with value label are not all of "
1023                       "identical type.  Variable %s is %s, but variable "
1024                       "%s is %s."),
1025                  var_get_name (var[0]),
1026                  var_is_numeric (var[0]) ? _("numeric") : _("string"),
1027                  var_get_name (var[i]),
1028                  var_is_numeric (var[i]) ? _("numeric") : _("string"));
1029
1030   /* Fill in labels[].value, now that we know the desired type. */
1031   for (i = 0; i < label_cnt; i++) 
1032     {
1033       struct label *label = labels + i;
1034       
1035       if (var_is_alpha (var[0]))
1036         buf_copy_rpad (label->value.s, sizeof label->value.s,
1037                        label->raw_value, sizeof label->raw_value);
1038       else
1039         label->value.f = flt64_to_double (r, (uint8_t *) label->raw_value);
1040     }
1041   
1042   /* Assign the `value_label's to each variable. */
1043   for (i = 0; i < var_cnt; i++)
1044     {
1045       struct variable *v = var[i];
1046       int j;
1047
1048       /* Add each label to the variable. */
1049       for (j = 0; j < label_cnt; j++)
1050         {
1051           struct label *label = &labels[j];
1052           if (!var_add_value_label (v, &label->value, label->label)) 
1053             {
1054               if (var_is_numeric (var[0]))
1055                 sys_warn (r, _("Duplicate value label for %g on %s."),
1056                           label->value.f, var_get_name (v));
1057               else
1058                 sys_warn (r, _("Duplicate value label for \"%.*s\" on %s."),
1059                           var_get_width (v), label->value.s,
1060                           var_get_name (v)); 
1061             }
1062         }
1063     }
1064
1065   pool_destroy (subpool);
1066 }
1067 \f
1068 /* Case reader. */
1069
1070 static void partial_record (struct sfm_reader *r)
1071      NO_RETURN;
1072 static bool read_case_number (struct sfm_reader *, double *);
1073 static bool read_case_string (struct sfm_reader *, char *, size_t);
1074 static int read_opcode (struct sfm_reader *);
1075 static bool read_compressed_number (struct sfm_reader *, double *);
1076 static bool read_compressed_string (struct sfm_reader *, char *);
1077 static bool read_whole_strings (struct sfm_reader *, char *, size_t);
1078
1079 /* Reads one case from READER's file into C.  Returns nonzero
1080    only if successful. */
1081 int
1082 sfm_read_case (struct sfm_reader *r, struct ccase *c)
1083 {
1084   if (r->error)
1085     return 0;
1086
1087   if (setjmp (r->bail_out))
1088     return 0;
1089
1090   if (!r->compressed && sizeof (double) == 8 && !r->has_vls) 
1091     {
1092       /* Fast path.  Read the whole case directly. */
1093       if (!try_read_bytes (r, case_data_all_rw (c),
1094                          sizeof (union value) * r->value_cnt))
1095         return 0;
1096
1097       /* Convert floating point numbers to native format if needed. */
1098       if (r->float_format != FLOAT_NATIVE_DOUBLE) 
1099         {
1100           int i;
1101           
1102           for (i = 0; i < r->var_cnt; i++) 
1103             if (r->vars[i].width == 0) 
1104               {
1105                 double *d = &case_data_rw_idx (c, r->vars[i].case_index)->f;
1106                 float_convert (r->float_format, d, FLOAT_NATIVE_DOUBLE, d); 
1107               }
1108         }
1109       return 1;
1110     }
1111   else 
1112     {
1113       /* Slow path.  Convert from external to internal format. */
1114       int i;
1115
1116       for (i = 0; i < r->var_cnt; i++)
1117         {
1118           struct sfm_var *sv = &r->vars[i];
1119           union value *v = case_data_rw_idx (c, sv->case_index);
1120
1121           if (sv->width == 0) 
1122             {
1123               if (!read_case_number (r, &v->f))
1124                 goto eof; 
1125             }
1126           else
1127             {
1128               /* Read the string data in segments up to 255 bytes
1129                  at a time, packed into 8-byte units. */
1130               const int max_chunk = MIN_VERY_LONG_STRING - 1;
1131               int ofs, chunk_size;
1132               for (ofs = 0; ofs < sv->width; ofs += chunk_size)
1133                 {
1134                   chunk_size = MIN (max_chunk, sv->width - ofs);
1135                   if (!read_case_string (r, v->s + ofs, chunk_size)) 
1136                     {
1137                       if (ofs)
1138                         partial_record (r);
1139                       goto eof; 
1140                     }
1141                 }
1142
1143               /* Very long strings have trailing wasted space
1144                  that we must skip. */
1145               if (sv->width >= MIN_VERY_LONG_STRING) 
1146                 {
1147                   int bytes_read = (sv->width / max_chunk * 256
1148                                     + ROUND_UP (sv->width % max_chunk, 8));
1149                   int total_bytes = sfm_width_to_bytes (sv->width);
1150                   int excess_bytes = total_bytes - bytes_read;
1151
1152                   while (excess_bytes > 0) 
1153                     {
1154                       char buffer[1024];
1155                       size_t chunk = MIN (sizeof buffer, excess_bytes);
1156                       if (!read_whole_strings (r, buffer, chunk))
1157                         partial_record (r);
1158                       excess_bytes -= chunk;
1159                     }
1160                 }
1161             }
1162         }
1163       return 1; 
1164
1165     eof:
1166       if (i != 0)
1167         partial_record (r);
1168       return 0;
1169     }
1170 }
1171
1172 /* Issues an error that R ends in a partial record. */
1173 static void
1174 partial_record (struct sfm_reader *r)
1175 {
1176   sys_error (r, _("File ends in partial case."));
1177 }
1178
1179 /* Reads a number from R and stores its value in *D.
1180    If R is compressed, reads a compressed number;
1181    otherwise, reads a number in the regular way.
1182    Returns true if successful, false if end of file is
1183    reached immediately. */
1184 static bool
1185 read_case_number (struct sfm_reader *r, double *d) 
1186 {
1187   if (!r->compressed)
1188     {
1189       uint8_t flt64[8];
1190       if (!try_read_bytes (r, flt64, sizeof flt64))
1191         return false;
1192       *d = flt64_to_double (r, flt64);
1193       return true;
1194     }
1195   else
1196     return read_compressed_number (r, d);
1197 }
1198
1199 /* Reads LENGTH string bytes from R into S.
1200    Always reads a multiple of 8 bytes; if LENGTH is not a
1201    multiple of 8, then extra bytes are read and discarded without
1202    being written to S.
1203    Reads compressed strings if S is compressed.
1204    Returns true if successful, false if end of file is
1205    reached immediately. */
1206 static bool
1207 read_case_string (struct sfm_reader *r, char *s, size_t length) 
1208 {
1209   size_t whole = ROUND_DOWN (length, 8);
1210   size_t partial = length % 8;
1211   
1212   if (whole) 
1213     {
1214       if (!read_whole_strings (r, s, whole))
1215         return false;
1216     }
1217
1218   if (partial)
1219     {
1220       char bounce[8];
1221       if (!read_whole_strings (r, bounce, sizeof bounce))
1222         {
1223           if (whole)
1224             partial_record (r);
1225           return false; 
1226         }
1227       memcpy (s + whole, bounce, partial);
1228     }
1229
1230   return true;
1231 }
1232
1233 /* Reads and returns the next compression opcode from R. */
1234 static int
1235 read_opcode (struct sfm_reader *r) 
1236 {
1237   assert (r->compressed);
1238   for (;;)
1239     {
1240       int opcode;
1241       if (r->opcode_idx >= sizeof r->opcodes) 
1242         {
1243           if (!try_read_bytes (r, r->opcodes, sizeof r->opcodes))
1244             return -1;
1245           r->opcode_idx = 0;
1246         }
1247       opcode = r->opcodes[r->opcode_idx++];
1248
1249       if (opcode != 0)
1250         return opcode;
1251     }
1252 }
1253
1254 /* Reads a compressed number from R and stores its value in D.
1255    Returns true if successful, false if end of file is
1256    reached immediately. */
1257 static bool
1258 read_compressed_number (struct sfm_reader *r, double *d)
1259 {
1260   int opcode = read_opcode (r); 
1261   switch (opcode)
1262     {
1263     case -1:
1264     case 252:
1265       return false;
1266
1267     case 253:
1268       *d = read_flt64 (r);
1269       break;
1270       
1271     case 254:
1272       sys_error (r, _("Compressed data is corrupt."));
1273
1274     case 255:
1275       *d = SYSMIS;
1276       break;
1277
1278     default:
1279       *d = opcode - r->bias;
1280       break;
1281     }
1282
1283   return true;
1284 }
1285
1286 /* Reads a compressed 8-byte string segment from R and stores it
1287    in DST.
1288    Returns true if successful, false if end of file is
1289    reached immediately. */
1290 static bool
1291 read_compressed_string (struct sfm_reader *r, char *dst)
1292 {
1293   switch (read_opcode (r))
1294     {
1295     case -1:
1296     case 252:
1297       return false;
1298
1299     case 253:
1300       read_bytes (r, dst, 8);
1301       break;
1302
1303     case 254:
1304       memset (dst, ' ', 8);
1305       break;
1306
1307     default:
1308       sys_error (r, _("Compressed data is corrupt."));
1309     }
1310
1311   return true;
1312 }
1313
1314 /* Reads LENGTH string bytes from R into S.
1315    LENGTH must be a multiple of 8.
1316    Reads compressed strings if S is compressed.
1317    Returns true if successful, false if end of file is
1318    reached immediately. */
1319 static bool
1320 read_whole_strings (struct sfm_reader *r, char *s, size_t length)
1321 {
1322   assert (length % 8 == 0);
1323   if (!r->compressed)
1324     return try_read_bytes (r, s, length);
1325   else
1326     {
1327       size_t ofs;
1328       for (ofs = 0; ofs < length; ofs += 8)
1329         if (!read_compressed_string (r, s + ofs)) 
1330           {
1331             if (ofs != 0)
1332               partial_record (r);
1333             return false;
1334           }
1335       return true;
1336     }
1337 }
1338 \f
1339 /* Creates and returns a table that can be used for translating a value
1340    index into a case to a "struct variable *" for DICT.  Multiple
1341    system file fields reference variables this way.
1342
1343    This table must be created before processing the very long
1344    string extension record, because that record causes some
1345    values to be deleted from the case and the dictionary to be
1346    compacted. */
1347 static struct variable **
1348 make_var_by_value_idx (struct sfm_reader *r, struct dictionary *dict) 
1349 {
1350   struct variable **var_by_value_idx;
1351   int value_idx = 0;
1352   int i;
1353
1354   var_by_value_idx = pool_nmalloc (r->pool,
1355                                    r->value_cnt, sizeof *var_by_value_idx);
1356   for (i = 0; i < dict_get_var_cnt (dict); i++) 
1357     {
1358       struct variable *v = dict_get_var (dict, i);
1359       int nv = var_is_numeric (v) ? 1 : DIV_RND_UP (var_get_width (v), 8);
1360       int j;
1361
1362       var_by_value_idx[value_idx++] = v;
1363       for (j = 1; j < nv; j++)
1364         var_by_value_idx[value_idx++] = NULL;
1365     }
1366   assert (value_idx == r->value_cnt);
1367
1368   return var_by_value_idx;
1369 }
1370
1371 /* Returns the "struct variable" corresponding to the given
1372    1-basd VALUE_IDX in VAR_BY_VALUE_IDX.  Verifies that the index
1373    is valid. */
1374 static struct variable *
1375 lookup_var_by_value_idx (struct sfm_reader *r,
1376                          struct variable **var_by_value_idx, int value_idx) 
1377 {
1378   struct variable *var;
1379   
1380   if (value_idx < 1 || value_idx > r->value_cnt)
1381     sys_error (r, _("Variable index %d not in valid range 1...%d."),
1382                value_idx, r->value_cnt);
1383
1384   var = var_by_value_idx[value_idx - 1];
1385   if (var == NULL)
1386     sys_error (r, _("Variable index %d refers to long string "
1387                     "continuation."),
1388                value_idx);
1389
1390   return var;
1391 }
1392
1393 /* Returns the variable in D with the given SHORT_NAME,
1394    or a null pointer if there is none. */
1395 static struct variable *
1396 lookup_var_by_short_name (struct dictionary *d, const char *short_name)
1397 {
1398   struct variable *var;
1399   size_t var_cnt;
1400   size_t i;
1401
1402   /* First try looking up by full name.  This often succeeds. */
1403   var = dict_lookup_var (d, short_name);
1404   if (var != NULL && !strcasecmp (var_get_short_name (var), short_name))
1405     return var;
1406
1407   /* Iterate through the whole dictionary as a fallback. */
1408   var_cnt = dict_get_var_cnt (d);
1409   for (i = 0; i < var_cnt; i++) 
1410     {
1411       var = dict_get_var (d, i);
1412       if (!strcasecmp (var_get_short_name (var), short_name))
1413         return var;
1414     }
1415
1416   return NULL;
1417 }
1418 \f
1419 /* Helpers for reading records that contain "variable=value"
1420    pairs. */
1421
1422 /* State. */
1423 struct variable_to_value_map 
1424   {
1425     struct substring buffer;    /* Record contents. */
1426     size_t pos;                 /* Current position in buffer. */
1427   };
1428
1429 /* Reads SIZE bytes into a "variable=value" map for R,
1430    and returns the map. */
1431 static struct variable_to_value_map *
1432 open_variable_to_value_map (struct sfm_reader *r, size_t size) 
1433 {
1434   struct variable_to_value_map *map = pool_alloc (r->pool, sizeof *map);
1435   char *buffer = pool_malloc (r->pool, size + 1);
1436   read_bytes (r, buffer, size);
1437   map->buffer = ss_buffer (buffer, size);
1438   map->pos = 0;
1439   return map;
1440 }
1441
1442 /* Closes MAP and frees its storage.
1443    Not really needed, because the pool will free the map anyway,
1444    but can be used to free it earlier. */
1445 static void
1446 close_variable_to_value_map (struct sfm_reader *r,
1447                              struct variable_to_value_map *map) 
1448 {
1449   pool_free (r->pool, ss_data (map->buffer));
1450 }
1451
1452 /* Reads the next variable=value pair from MAP.
1453    Looks up the variable in DICT and stores it into *VAR.
1454    Stores a null-terminated value into *VALUE. */
1455 static bool
1456 read_variable_to_value_map (struct sfm_reader *r, struct dictionary *dict,
1457                             struct variable_to_value_map *map,
1458                             struct variable **var, char **value,
1459                             int *warning_cnt) 
1460 {
1461   int max_warnings = 5;
1462   
1463   for (;;) 
1464     {
1465       struct substring short_name_ss, value_ss;
1466
1467       if (!ss_tokenize (map->buffer, ss_cstr ("="), &map->pos, &short_name_ss)
1468           || !ss_tokenize (map->buffer, ss_buffer ("\t\0", 2), &map->pos,
1469                            &value_ss)) 
1470         {
1471           if (*warning_cnt > max_warnings)
1472             sys_warn (r, _("Suppressed %d additional variable map warnings."),
1473                       *warning_cnt - max_warnings);
1474           return false; 
1475         }
1476       
1477       map->pos += ss_span (ss_substr (map->buffer, map->pos, SIZE_MAX),
1478                            ss_buffer ("\t\0", 2));
1479
1480       ss_data (short_name_ss)[ss_length (short_name_ss)] = '\0';
1481       *var = lookup_var_by_short_name (dict, ss_data (short_name_ss));
1482       if (*var == NULL)
1483         {
1484           if (++*warning_cnt <= 5)
1485             sys_warn (r, _("Variable map refers to unknown variable %s."),
1486                       ss_data (short_name_ss));
1487           continue;
1488         }
1489
1490       ss_data (value_ss)[ss_length (value_ss)] = '\0';
1491       *value = ss_data (value_ss);
1492
1493       return true;
1494     }
1495 }
1496 \f
1497 /* Messages. */
1498
1499 /* Displays a corruption message. */
1500 static void
1501 sys_msg (struct sfm_reader *r, int class, const char *format, va_list args)
1502 {
1503   struct msg m;
1504   struct string text;
1505
1506   ds_init_empty (&text);
1507   ds_put_format (&text, "\"%s\" near offset 0x%lx: ",
1508                  fh_get_file_name (r->fh), (unsigned long) ftell (r->file));
1509   ds_put_vformat (&text, format, args);
1510
1511   m.category = msg_class_to_category (class);
1512   m.severity = msg_class_to_severity (class);
1513   m.where.file_name = NULL;
1514   m.where.line_number = 0;
1515   m.text = ds_cstr (&text);
1516
1517   msg_emit (&m);
1518 }
1519
1520 /* Displays a warning for the current file position. */
1521 static void
1522 sys_warn (struct sfm_reader *r, const char *format, ...) 
1523 {
1524   va_list args;
1525   
1526   va_start (args, format);
1527   sys_msg (r, MW, format, args);
1528   va_end (args);
1529 }
1530
1531 /* Displays an error for the current file position,
1532    marks it as in an error state,
1533    and aborts reading it using longjmp. */
1534 static void
1535 sys_error (struct sfm_reader *r, const char *format, ...) 
1536 {
1537   va_list args;
1538   
1539   va_start (args, format);
1540   sys_msg (r, ME, format, args);
1541   va_end (args);
1542
1543   r->error = true;
1544   longjmp (r->bail_out, 1);
1545 }
1546 \f
1547 /* Reads BYTE_CNT bytes into BUF.
1548    Returns true if exactly BYTE_CNT bytes are successfully read.
1549    Aborts if an I/O error or a partial read occurs.
1550    If EOF_IS_OK, then an immediate end-of-file causes false to be
1551    returned; otherwise, immediate end-of-file causes an abort
1552    too. */
1553 static inline bool
1554 read_bytes_internal (struct sfm_reader *r, bool eof_is_ok,
1555                    void *buf, size_t byte_cnt)
1556 {
1557   size_t bytes_read = fread (buf, 1, byte_cnt, r->file);
1558   if (bytes_read == byte_cnt)
1559     return true;
1560   else if (ferror (r->file))
1561     sys_error (r, _("System error: %s."), strerror (errno));
1562   else if (!eof_is_ok || bytes_read != 0)
1563     sys_error (r, _("Unexpected end of file."));
1564   else
1565     return false;
1566 }
1567
1568 /* Reads BYTE_CNT into BUF.
1569    Aborts upon I/O error or if end-of-file is encountered. */
1570 static void
1571 read_bytes (struct sfm_reader *r, void *buf, size_t byte_cnt)
1572 {
1573   read_bytes_internal (r, false, buf, byte_cnt);
1574 }
1575
1576 /* Reads BYTE_CNT bytes into BUF.
1577    Returns true if exactly BYTE_CNT bytes are successfully read.
1578    Returns false if an immediate end-of-file is encountered.
1579    Aborts if an I/O error or a partial read occurs. */
1580 static bool
1581 try_read_bytes (struct sfm_reader *r, void *buf, size_t byte_cnt)
1582 {
1583   return read_bytes_internal (r, true, buf, byte_cnt);
1584 }
1585
1586 /* Reads a 32-bit signed integer from R and returns its value in
1587    host format. */
1588 static int32_t
1589 read_int32 (struct sfm_reader *r) 
1590 {
1591   uint8_t int32[4];
1592   read_bytes (r, int32, sizeof int32);
1593   return int32_to_native (r, int32);
1594 }
1595
1596 /* Reads a 64-bit floating-point number from R and returns its
1597    value in host format. */
1598 static double
1599 read_flt64 (struct sfm_reader *r) 
1600 {
1601   uint8_t flt64[8];
1602   read_bytes (r, flt64, sizeof flt64);
1603   return flt64_to_double (r, flt64);
1604 }
1605
1606 /* Reads exactly SIZE - 1 bytes into BUFFER
1607    and stores a null byte into BUFFER[SIZE - 1]. */
1608 static void
1609 read_string (struct sfm_reader *r, char *buffer, size_t size) 
1610 {
1611   assert (size > 0);
1612   read_bytes (r, buffer, size - 1);
1613   buffer[size - 1] = '\0';
1614 }
1615
1616 /* Skips BYTES bytes forward in R. */
1617 static void
1618 skip_bytes (struct sfm_reader *r, size_t bytes)
1619 {
1620   while (bytes > 0) 
1621     {
1622       char buffer[1024];
1623       size_t chunk = MIN (sizeof buffer, bytes);
1624       read_bytes (r, buffer, chunk);
1625       bytes -= chunk;
1626     }
1627 }
1628 \f
1629 /* Returns the value of the 32-bit signed integer at INT32,
1630    converted from the format used by R to the host format. */
1631 static int32_t
1632 int32_to_native (const struct sfm_reader *r, const uint8_t int32[4]) 
1633 {
1634   int32_t x;
1635   if (r->integer_format == INTEGER_NATIVE)
1636     memcpy (&x, int32, sizeof x);
1637   else
1638     x = integer_get (r->integer_format, int32, sizeof x);
1639   return x;
1640 }
1641
1642 /* Returns the value of the 64-bit floating point number at
1643    FLT64, converted from the format used by R to the host
1644    format. */
1645 static double
1646 flt64_to_double (const struct sfm_reader *r, const uint8_t flt64[8])
1647 {
1648   double x;
1649   if (r->float_format == FLOAT_NATIVE_DOUBLE)
1650     memcpy (&x, flt64, sizeof x);
1651   else
1652     float_convert (r->float_format, flt64, FLOAT_NATIVE_DOUBLE, &x);
1653   return x;
1654 }
1655