Increase width of N and DEF cells in T-TEST.
[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 %u."),
476                    name, (unsigned int) 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 (%u) or count (%u) field on record type 7, "
740                     "subtype 3."),
741                (unsigned int) size, (unsigned int) 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 (%u) or count (%u) on extension 4."),
785                (unsigned int) size, (unsigned int) 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 (%u) or count (%u) on extension 11."),
807                (unsigned int) size, (unsigned int) 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 = dict_get_var (dict, i);
815
816       /* spss v14 sometimes seems to set string variables' measure to zero */
817       if ( 0 == measure && var_is_alpha (v) ) measure = 1;
818
819
820       if (measure < 1 || measure > 3 || align < 0 || align > 2)
821         {
822           if (!warned)
823             sys_warn (r, _("Invalid variable display parameters.  "
824                            "Default parameters substituted."));
825           warned = true;
826           continue;
827         }
828
829       var_set_measure (v, (measure == 1 ? MEASURE_NOMINAL
830                            : measure == 2 ? MEASURE_ORDINAL
831                            : MEASURE_SCALE));
832       var_set_display_width (v, width);
833       var_set_alignment (v, (align == 0 ? ALIGN_LEFT
834                              : align == 1 ? ALIGN_RIGHT
835                              : ALIGN_CENTRE));
836     }
837 }
838
839 /* Reads record type 7, subtype 13, which gives the long name
840    that corresponds to each short name.  Modifies variable names
841    in DICT accordingly.  */
842 static void
843 read_long_var_name_map (struct sfm_reader *r, size_t size, size_t count,
844                         struct dictionary *dict)
845 {
846   struct variable_to_value_map *map;
847   struct variable *var;
848   char *long_name;
849   int warning_cnt = 0;
850   
851   map = open_variable_to_value_map (r, size * count);
852   while (read_variable_to_value_map (r, dict, map, &var, &long_name,
853                                      &warning_cnt))
854     {
855       char short_name[SHORT_NAME_LEN + 1];
856       strcpy (short_name, var_get_short_name (var));
857
858       /* Validate long name. */
859       if (!var_is_valid_name (long_name, false))
860         {
861           sys_warn (r, _("Long variable mapping from %s to invalid "
862                          "variable name `%s'."),
863                     var_get_name (var), long_name);
864           continue;
865         }
866                       
867       /* Identify any duplicates. */
868       if (strcasecmp (short_name, long_name)
869           && dict_lookup_var (dict, long_name) != NULL)
870         {
871           sys_warn (r, _("Duplicate long variable name `%s' "
872                          "within system file."), long_name);
873           continue;
874         }
875
876       /* Set long name.  Renaming a variable may clear the short
877          name, but we want to retain it, so re-set it
878          explicitly. */
879       dict_rename_var (dict, var, long_name);
880       var_set_short_name (var, short_name);
881     }
882   close_variable_to_value_map (r, map);
883 }
884
885 /* Reads record type 7, subtype 14, which gives the real length
886    of each very long string.  Rearranges DICT accordingly. */
887 static void
888 read_long_string_map (struct sfm_reader *r, size_t size, size_t count,
889                       struct dictionary *dict)
890 {
891   struct variable_to_value_map *map;
892   struct variable *var;
893   char *length_s;
894   int warning_cnt = 0;
895
896   r->has_vls = true;
897
898   map = open_variable_to_value_map (r, size * count);
899   while (read_variable_to_value_map (r, dict, map, &var, &length_s,
900                                      &warning_cnt))
901     {
902       long length, remaining_length;
903       size_t idx;
904
905       /* Get length. */
906       length = strtol (length_s, NULL, 10);
907       if (length < MIN_VERY_LONG_STRING || length == LONG_MAX) 
908         {
909           sys_warn (r, _("%s listed as string of length %s "
910                          "in length table."),
911                     var_get_name (var), length_s);
912           continue;
913         }
914
915       /* Group multiple variables into single variable
916          and delete all but the first. */
917       remaining_length = length;
918       for (idx = var_get_dict_index (var); remaining_length > 0; idx++)
919         if (idx < dict_get_var_cnt (dict)) 
920           remaining_length -= MIN (var_get_width (dict_get_var (dict, idx)),
921                                    EFFECTIVE_LONG_STRING_LENGTH);
922         else
923           sys_error (r, _("Very long string %s overflows dictionary."),
924                      var_get_name (var));
925       dict_delete_consecutive_vars (dict,
926                                     var_get_dict_index (var) + 1,
927                                     idx - var_get_dict_index (var) - 1);
928
929       /* Assign all the length to the first variable. */
930       var_set_width (var, length);
931     }
932   close_variable_to_value_map (r, map);
933   dict_compact_values (dict);
934 }
935
936 /* Reads value labels from sysfile H and inserts them into the
937    associated dictionary. */
938 static void
939 read_value_labels (struct sfm_reader *r,
940                    struct dictionary *dict, struct variable **var_by_value_idx)
941 {
942   struct pool *subpool;
943   
944   struct label 
945     {
946       char raw_value[8];        /* Value as uninterpreted bytes. */
947       union value value;        /* Value. */
948       char *label;              /* Null-terminated label string. */
949     };
950
951   struct label *labels = NULL;
952   int label_cnt;                /* Number of labels. */
953
954   struct variable **var = NULL; /* Associated variables. */
955   int var_cnt;                  /* Number of associated variables. */
956
957   int i;
958
959   subpool = pool_create_subpool (r->pool);
960
961   /* Read the type 3 record and record its contents.  We can't do
962      much with the data yet because we don't know whether it is
963      of numeric or string type. */
964
965   /* Read number of labels. */
966   label_cnt = read_int32 (r);
967
968   if (label_cnt >= INT32_MAX / sizeof *labels)
969     {    
970       sys_warn (r, _("Invalid number of labels: %d.  Ignoring labels."),
971                 label_cnt);
972       label_cnt = 0;
973     }
974
975   /* Read each value/label tuple into labels[]. */
976   labels = pool_nalloc (subpool, label_cnt, sizeof *labels);
977   for (i = 0; i < label_cnt; i++)
978     {
979       struct label *label = labels + i;
980       unsigned char label_len;
981       size_t padded_len;
982
983       /* Read value. */
984       read_bytes (r, label->raw_value, sizeof label->raw_value);
985
986       /* Read label length. */
987       read_bytes (r, &label_len, sizeof label_len);
988       padded_len = ROUND_UP (label_len + 1, 8);
989
990       /* Read label, padding. */
991       label->label = pool_alloc (subpool, padded_len + 1);
992       read_bytes (r, label->label, padded_len - 1);
993       label->label[label_len] = 0;
994     }
995
996   /* Now, read the type 4 record that has the list of variables
997      to which the value labels are to be applied. */
998
999   /* Read record type of type 4 record. */
1000   if (read_int32 (r) != 4)
1001     sys_error (r, _("Variable index record (type 4) does not immediately "
1002                     "follow value label record (type 3) as it should."));
1003
1004   /* Read number of variables associated with value label from type 4
1005      record. */
1006   var_cnt = read_int32 (r);
1007   if (var_cnt < 1 || var_cnt > dict_get_var_cnt (dict))
1008     sys_error (r, _("Number of variables associated with a value label (%d) "
1009                     "is not between 1 and the number of variables (%u)."),
1010                var_cnt, (unsigned int) dict_get_var_cnt (dict));
1011
1012   /* Read the list of variables. */
1013   var = pool_nalloc (subpool, var_cnt, sizeof *var);
1014   for (i = 0; i < var_cnt; i++)
1015     {
1016       var[i] = lookup_var_by_value_idx (r, var_by_value_idx, read_int32 (r));
1017       if (var_is_long_string (var[i]))
1018         sys_error (r, _("Value labels are not allowed on long string "
1019                         "variables (%s)."), var_get_name (var[i]));
1020     }
1021
1022   /* Type check the variables. */
1023   for (i = 1; i < var_cnt; i++)
1024     if (var_get_type (var[i]) != var_get_type (var[0]))
1025       sys_error (r, _("Variables associated with value label are not all of "
1026                       "identical type.  Variable %s is %s, but variable "
1027                       "%s is %s."),
1028                  var_get_name (var[0]),
1029                  var_is_numeric (var[0]) ? _("numeric") : _("string"),
1030                  var_get_name (var[i]),
1031                  var_is_numeric (var[i]) ? _("numeric") : _("string"));
1032
1033   /* Fill in labels[].value, now that we know the desired type. */
1034   for (i = 0; i < label_cnt; i++) 
1035     {
1036       struct label *label = labels + i;
1037       
1038       if (var_is_alpha (var[0]))
1039         buf_copy_rpad (label->value.s, sizeof label->value.s,
1040                        label->raw_value, sizeof label->raw_value);
1041       else
1042         label->value.f = flt64_to_double (r, (uint8_t *) label->raw_value);
1043     }
1044   
1045   /* Assign the `value_label's to each variable. */
1046   for (i = 0; i < var_cnt; i++)
1047     {
1048       struct variable *v = var[i];
1049       int j;
1050
1051       /* Add each label to the variable. */
1052       for (j = 0; j < label_cnt; j++)
1053         {
1054           struct label *label = &labels[j];
1055           if (!var_add_value_label (v, &label->value, label->label)) 
1056             {
1057               if (var_is_numeric (var[0]))
1058                 sys_warn (r, _("Duplicate value label for %g on %s."),
1059                           label->value.f, var_get_name (v));
1060               else
1061                 sys_warn (r, _("Duplicate value label for \"%.*s\" on %s."),
1062                           var_get_width (v), label->value.s,
1063                           var_get_name (v)); 
1064             }
1065         }
1066     }
1067
1068   pool_destroy (subpool);
1069 }
1070 \f
1071 /* Case reader. */
1072
1073 static void partial_record (struct sfm_reader *r)
1074      NO_RETURN;
1075 static bool read_case_number (struct sfm_reader *, double *);
1076 static bool read_case_string (struct sfm_reader *, char *, size_t);
1077 static int read_opcode (struct sfm_reader *);
1078 static bool read_compressed_number (struct sfm_reader *, double *);
1079 static bool read_compressed_string (struct sfm_reader *, char *);
1080 static bool read_whole_strings (struct sfm_reader *, char *, size_t);
1081
1082 /* Reads one case from READER's file into C.  Returns nonzero
1083    only if successful. */
1084 int
1085 sfm_read_case (struct sfm_reader *r, struct ccase *c)
1086 {
1087   if (r->error)
1088     return 0;
1089
1090   if (setjmp (r->bail_out))
1091     return 0;
1092
1093   if (!r->compressed && sizeof (double) == 8 && !r->has_vls) 
1094     {
1095       /* Fast path.  Read the whole case directly. */
1096       if (!try_read_bytes (r, case_data_all_rw (c),
1097                          sizeof (union value) * r->value_cnt))
1098         return 0;
1099
1100       /* Convert floating point numbers to native format if needed. */
1101       if (r->float_format != FLOAT_NATIVE_DOUBLE) 
1102         {
1103           int i;
1104           
1105           for (i = 0; i < r->var_cnt; i++) 
1106             if (r->vars[i].width == 0) 
1107               {
1108                 double *d = &case_data_rw_idx (c, r->vars[i].case_index)->f;
1109                 float_convert (r->float_format, d, FLOAT_NATIVE_DOUBLE, d); 
1110               }
1111         }
1112       return 1;
1113     }
1114   else 
1115     {
1116       /* Slow path.  Convert from external to internal format. */
1117       int i;
1118
1119       for (i = 0; i < r->var_cnt; i++)
1120         {
1121           struct sfm_var *sv = &r->vars[i];
1122           union value *v = case_data_rw_idx (c, sv->case_index);
1123
1124           if (sv->width == 0) 
1125             {
1126               if (!read_case_number (r, &v->f))
1127                 goto eof; 
1128             }
1129           else
1130             {
1131               /* Read the string data in segments up to 255 bytes
1132                  at a time, packed into 8-byte units. */
1133               const int max_chunk = MIN_VERY_LONG_STRING - 1;
1134               int ofs, chunk_size;
1135               for (ofs = 0; ofs < sv->width; ofs += chunk_size)
1136                 {
1137                   chunk_size = MIN (max_chunk, sv->width - ofs);
1138                   if (!read_case_string (r, v->s + ofs, chunk_size)) 
1139                     {
1140                       if (ofs)
1141                         partial_record (r);
1142                       goto eof; 
1143                     }
1144                 }
1145
1146               /* Very long strings have trailing wasted space
1147                  that we must skip. */
1148               if (sv->width >= MIN_VERY_LONG_STRING) 
1149                 {
1150                   int bytes_read = (sv->width / max_chunk * 256
1151                                     + ROUND_UP (sv->width % max_chunk, 8));
1152                   int total_bytes = sfm_width_to_bytes (sv->width);
1153                   int excess_bytes = total_bytes - bytes_read;
1154
1155                   while (excess_bytes > 0) 
1156                     {
1157                       char buffer[1024];
1158                       size_t chunk = MIN (sizeof buffer, excess_bytes);
1159                       if (!read_whole_strings (r, buffer, chunk))
1160                         partial_record (r);
1161                       excess_bytes -= chunk;
1162                     }
1163                 }
1164             }
1165         }
1166       return 1; 
1167
1168     eof:
1169       if (i != 0)
1170         partial_record (r);
1171       return 0;
1172     }
1173 }
1174
1175 /* Issues an error that R ends in a partial record. */
1176 static void
1177 partial_record (struct sfm_reader *r)
1178 {
1179   sys_error (r, _("File ends in partial case."));
1180 }
1181
1182 /* Reads a number from R and stores its value in *D.
1183    If R is compressed, reads a compressed number;
1184    otherwise, reads a number in the regular way.
1185    Returns true if successful, false if end of file is
1186    reached immediately. */
1187 static bool
1188 read_case_number (struct sfm_reader *r, double *d) 
1189 {
1190   if (!r->compressed)
1191     {
1192       uint8_t flt64[8];
1193       if (!try_read_bytes (r, flt64, sizeof flt64))
1194         return false;
1195       *d = flt64_to_double (r, flt64);
1196       return true;
1197     }
1198   else
1199     return read_compressed_number (r, d);
1200 }
1201
1202 /* Reads LENGTH string bytes from R into S.
1203    Always reads a multiple of 8 bytes; if LENGTH is not a
1204    multiple of 8, then extra bytes are read and discarded without
1205    being written to S.
1206    Reads compressed strings if S is compressed.
1207    Returns true if successful, false if end of file is
1208    reached immediately. */
1209 static bool
1210 read_case_string (struct sfm_reader *r, char *s, size_t length) 
1211 {
1212   size_t whole = ROUND_DOWN (length, 8);
1213   size_t partial = length % 8;
1214   
1215   if (whole) 
1216     {
1217       if (!read_whole_strings (r, s, whole))
1218         return false;
1219     }
1220
1221   if (partial)
1222     {
1223       char bounce[8];
1224       if (!read_whole_strings (r, bounce, sizeof bounce))
1225         {
1226           if (whole)
1227             partial_record (r);
1228           return false; 
1229         }
1230       memcpy (s + whole, bounce, partial);
1231     }
1232
1233   return true;
1234 }
1235
1236 /* Reads and returns the next compression opcode from R. */
1237 static int
1238 read_opcode (struct sfm_reader *r) 
1239 {
1240   assert (r->compressed);
1241   for (;;)
1242     {
1243       int opcode;
1244       if (r->opcode_idx >= sizeof r->opcodes) 
1245         {
1246           if (!try_read_bytes (r, r->opcodes, sizeof r->opcodes))
1247             return -1;
1248           r->opcode_idx = 0;
1249         }
1250       opcode = r->opcodes[r->opcode_idx++];
1251
1252       if (opcode != 0)
1253         return opcode;
1254     }
1255 }
1256
1257 /* Reads a compressed number from R and stores its value in D.
1258    Returns true if successful, false if end of file is
1259    reached immediately. */
1260 static bool
1261 read_compressed_number (struct sfm_reader *r, double *d)
1262 {
1263   int opcode = read_opcode (r); 
1264   switch (opcode)
1265     {
1266     case -1:
1267     case 252:
1268       return false;
1269
1270     case 253:
1271       *d = read_flt64 (r);
1272       break;
1273       
1274     case 254:
1275       sys_error (r, _("Compressed data is corrupt."));
1276
1277     case 255:
1278       *d = SYSMIS;
1279       break;
1280
1281     default:
1282       *d = opcode - r->bias;
1283       break;
1284     }
1285
1286   return true;
1287 }
1288
1289 /* Reads a compressed 8-byte string segment from R and stores it
1290    in DST.
1291    Returns true if successful, false if end of file is
1292    reached immediately. */
1293 static bool
1294 read_compressed_string (struct sfm_reader *r, char *dst)
1295 {
1296   switch (read_opcode (r))
1297     {
1298     case -1:
1299     case 252:
1300       return false;
1301
1302     case 253:
1303       read_bytes (r, dst, 8);
1304       break;
1305
1306     case 254:
1307       memset (dst, ' ', 8);
1308       break;
1309
1310     default:
1311       sys_error (r, _("Compressed data is corrupt."));
1312     }
1313
1314   return true;
1315 }
1316
1317 /* Reads LENGTH string bytes from R into S.
1318    LENGTH must be a multiple of 8.
1319    Reads compressed strings if S is compressed.
1320    Returns true if successful, false if end of file is
1321    reached immediately. */
1322 static bool
1323 read_whole_strings (struct sfm_reader *r, char *s, size_t length)
1324 {
1325   assert (length % 8 == 0);
1326   if (!r->compressed)
1327     return try_read_bytes (r, s, length);
1328   else
1329     {
1330       size_t ofs;
1331       for (ofs = 0; ofs < length; ofs += 8)
1332         if (!read_compressed_string (r, s + ofs)) 
1333           {
1334             if (ofs != 0)
1335               partial_record (r);
1336             return false;
1337           }
1338       return true;
1339     }
1340 }
1341 \f
1342 /* Creates and returns a table that can be used for translating a value
1343    index into a case to a "struct variable *" for DICT.  Multiple
1344    system file fields reference variables this way.
1345
1346    This table must be created before processing the very long
1347    string extension record, because that record causes some
1348    values to be deleted from the case and the dictionary to be
1349    compacted. */
1350 static struct variable **
1351 make_var_by_value_idx (struct sfm_reader *r, struct dictionary *dict) 
1352 {
1353   struct variable **var_by_value_idx;
1354   int value_idx = 0;
1355   int i;
1356
1357   var_by_value_idx = pool_nmalloc (r->pool,
1358                                    r->value_cnt, sizeof *var_by_value_idx);
1359   for (i = 0; i < dict_get_var_cnt (dict); i++) 
1360     {
1361       struct variable *v = dict_get_var (dict, i);
1362       int nv = var_is_numeric (v) ? 1 : DIV_RND_UP (var_get_width (v), 8);
1363       int j;
1364
1365       var_by_value_idx[value_idx++] = v;
1366       for (j = 1; j < nv; j++)
1367         var_by_value_idx[value_idx++] = NULL;
1368     }
1369   assert (value_idx == r->value_cnt);
1370
1371   return var_by_value_idx;
1372 }
1373
1374 /* Returns the "struct variable" corresponding to the given
1375    1-basd VALUE_IDX in VAR_BY_VALUE_IDX.  Verifies that the index
1376    is valid. */
1377 static struct variable *
1378 lookup_var_by_value_idx (struct sfm_reader *r,
1379                          struct variable **var_by_value_idx, int value_idx) 
1380 {
1381   struct variable *var;
1382   
1383   if (value_idx < 1 || value_idx > r->value_cnt)
1384     sys_error (r, _("Variable index %d not in valid range 1...%d."),
1385                value_idx, r->value_cnt);
1386
1387   var = var_by_value_idx[value_idx - 1];
1388   if (var == NULL)
1389     sys_error (r, _("Variable index %d refers to long string "
1390                     "continuation."),
1391                value_idx);
1392
1393   return var;
1394 }
1395
1396 /* Returns the variable in D with the given SHORT_NAME,
1397    or a null pointer if there is none. */
1398 static struct variable *
1399 lookup_var_by_short_name (struct dictionary *d, const char *short_name)
1400 {
1401   struct variable *var;
1402   size_t var_cnt;
1403   size_t i;
1404
1405   /* First try looking up by full name.  This often succeeds. */
1406   var = dict_lookup_var (d, short_name);
1407   if (var != NULL && !strcasecmp (var_get_short_name (var), short_name))
1408     return var;
1409
1410   /* Iterate through the whole dictionary as a fallback. */
1411   var_cnt = dict_get_var_cnt (d);
1412   for (i = 0; i < var_cnt; i++) 
1413     {
1414       var = dict_get_var (d, i);
1415       if (!strcasecmp (var_get_short_name (var), short_name))
1416         return var;
1417     }
1418
1419   return NULL;
1420 }
1421 \f
1422 /* Helpers for reading records that contain "variable=value"
1423    pairs. */
1424
1425 /* State. */
1426 struct variable_to_value_map 
1427   {
1428     struct substring buffer;    /* Record contents. */
1429     size_t pos;                 /* Current position in buffer. */
1430   };
1431
1432 /* Reads SIZE bytes into a "variable=value" map for R,
1433    and returns the map. */
1434 static struct variable_to_value_map *
1435 open_variable_to_value_map (struct sfm_reader *r, size_t size) 
1436 {
1437   struct variable_to_value_map *map = pool_alloc (r->pool, sizeof *map);
1438   char *buffer = pool_malloc (r->pool, size + 1);
1439   read_bytes (r, buffer, size);
1440   map->buffer = ss_buffer (buffer, size);
1441   map->pos = 0;
1442   return map;
1443 }
1444
1445 /* Closes MAP and frees its storage.
1446    Not really needed, because the pool will free the map anyway,
1447    but can be used to free it earlier. */
1448 static void
1449 close_variable_to_value_map (struct sfm_reader *r,
1450                              struct variable_to_value_map *map) 
1451 {
1452   pool_free (r->pool, ss_data (map->buffer));
1453 }
1454
1455 /* Reads the next variable=value pair from MAP.
1456    Looks up the variable in DICT and stores it into *VAR.
1457    Stores a null-terminated value into *VALUE. */
1458 static bool
1459 read_variable_to_value_map (struct sfm_reader *r, struct dictionary *dict,
1460                             struct variable_to_value_map *map,
1461                             struct variable **var, char **value,
1462                             int *warning_cnt) 
1463 {
1464   int max_warnings = 5;
1465   
1466   for (;;) 
1467     {
1468       struct substring short_name_ss, value_ss;
1469
1470       if (!ss_tokenize (map->buffer, ss_cstr ("="), &map->pos, &short_name_ss)
1471           || !ss_tokenize (map->buffer, ss_buffer ("\t\0", 2), &map->pos,
1472                            &value_ss)) 
1473         {
1474           if (*warning_cnt > max_warnings)
1475             sys_warn (r, _("Suppressed %d additional variable map warnings."),
1476                       *warning_cnt - max_warnings);
1477           return false; 
1478         }
1479       
1480       map->pos += ss_span (ss_substr (map->buffer, map->pos, SIZE_MAX),
1481                            ss_buffer ("\t\0", 2));
1482
1483       ss_data (short_name_ss)[ss_length (short_name_ss)] = '\0';
1484       *var = lookup_var_by_short_name (dict, ss_data (short_name_ss));
1485       if (*var == NULL)
1486         {
1487           if (++*warning_cnt <= 5)
1488             sys_warn (r, _("Variable map refers to unknown variable %s."),
1489                       ss_data (short_name_ss));
1490           continue;
1491         }
1492
1493       ss_data (value_ss)[ss_length (value_ss)] = '\0';
1494       *value = ss_data (value_ss);
1495
1496       return true;
1497     }
1498 }
1499 \f
1500 /* Messages. */
1501
1502 /* Displays a corruption message. */
1503 static void
1504 sys_msg (struct sfm_reader *r, int class, const char *format, va_list args)
1505 {
1506   struct msg m;
1507   struct string text;
1508
1509   ds_init_empty (&text);
1510   ds_put_format (&text, "\"%s\" near offset 0x%lx: ",
1511                  fh_get_file_name (r->fh), (unsigned long) ftell (r->file));
1512   ds_put_vformat (&text, format, args);
1513
1514   m.category = msg_class_to_category (class);
1515   m.severity = msg_class_to_severity (class);
1516   m.where.file_name = NULL;
1517   m.where.line_number = 0;
1518   m.text = ds_cstr (&text);
1519
1520   msg_emit (&m);
1521 }
1522
1523 /* Displays a warning for the current file position. */
1524 static void
1525 sys_warn (struct sfm_reader *r, const char *format, ...) 
1526 {
1527   va_list args;
1528   
1529   va_start (args, format);
1530   sys_msg (r, MW, format, args);
1531   va_end (args);
1532 }
1533
1534 /* Displays an error for the current file position,
1535    marks it as in an error state,
1536    and aborts reading it using longjmp. */
1537 static void
1538 sys_error (struct sfm_reader *r, const char *format, ...) 
1539 {
1540   va_list args;
1541   
1542   va_start (args, format);
1543   sys_msg (r, ME, format, args);
1544   va_end (args);
1545
1546   r->error = true;
1547   longjmp (r->bail_out, 1);
1548 }
1549 \f
1550 /* Reads BYTE_CNT bytes into BUF.
1551    Returns true if exactly BYTE_CNT bytes are successfully read.
1552    Aborts if an I/O error or a partial read occurs.
1553    If EOF_IS_OK, then an immediate end-of-file causes false to be
1554    returned; otherwise, immediate end-of-file causes an abort
1555    too. */
1556 static inline bool
1557 read_bytes_internal (struct sfm_reader *r, bool eof_is_ok,
1558                    void *buf, size_t byte_cnt)
1559 {
1560   size_t bytes_read = fread (buf, 1, byte_cnt, r->file);
1561   if (bytes_read == byte_cnt)
1562     return true;
1563   else if (ferror (r->file))
1564     sys_error (r, _("System error: %s."), strerror (errno));
1565   else if (!eof_is_ok || bytes_read != 0)
1566     sys_error (r, _("Unexpected end of file."));
1567   else
1568     return false;
1569 }
1570
1571 /* Reads BYTE_CNT into BUF.
1572    Aborts upon I/O error or if end-of-file is encountered. */
1573 static void
1574 read_bytes (struct sfm_reader *r, void *buf, size_t byte_cnt)
1575 {
1576   read_bytes_internal (r, false, buf, byte_cnt);
1577 }
1578
1579 /* Reads BYTE_CNT bytes into BUF.
1580    Returns true if exactly BYTE_CNT bytes are successfully read.
1581    Returns false if an immediate end-of-file is encountered.
1582    Aborts if an I/O error or a partial read occurs. */
1583 static bool
1584 try_read_bytes (struct sfm_reader *r, void *buf, size_t byte_cnt)
1585 {
1586   return read_bytes_internal (r, true, buf, byte_cnt);
1587 }
1588
1589 /* Reads a 32-bit signed integer from R and returns its value in
1590    host format. */
1591 static int32_t
1592 read_int32 (struct sfm_reader *r) 
1593 {
1594   uint8_t int32[4];
1595   read_bytes (r, int32, sizeof int32);
1596   return int32_to_native (r, int32);
1597 }
1598
1599 /* Reads a 64-bit floating-point number from R and returns its
1600    value in host format. */
1601 static double
1602 read_flt64 (struct sfm_reader *r) 
1603 {
1604   uint8_t flt64[8];
1605   read_bytes (r, flt64, sizeof flt64);
1606   return flt64_to_double (r, flt64);
1607 }
1608
1609 /* Reads exactly SIZE - 1 bytes into BUFFER
1610    and stores a null byte into BUFFER[SIZE - 1]. */
1611 static void
1612 read_string (struct sfm_reader *r, char *buffer, size_t size) 
1613 {
1614   assert (size > 0);
1615   read_bytes (r, buffer, size - 1);
1616   buffer[size - 1] = '\0';
1617 }
1618
1619 /* Skips BYTES bytes forward in R. */
1620 static void
1621 skip_bytes (struct sfm_reader *r, size_t bytes)
1622 {
1623   while (bytes > 0) 
1624     {
1625       char buffer[1024];
1626       size_t chunk = MIN (sizeof buffer, bytes);
1627       read_bytes (r, buffer, chunk);
1628       bytes -= chunk;
1629     }
1630 }
1631 \f
1632 /* Returns the value of the 32-bit signed integer at INT32,
1633    converted from the format used by R to the host format. */
1634 static int32_t
1635 int32_to_native (const struct sfm_reader *r, const uint8_t int32[4]) 
1636 {
1637   int32_t x;
1638   if (r->integer_format == INTEGER_NATIVE)
1639     memcpy (&x, int32, sizeof x);
1640   else
1641     x = integer_get (r->integer_format, int32, sizeof x);
1642   return x;
1643 }
1644
1645 /* Returns the value of the 64-bit floating point number at
1646    FLT64, converted from the format used by R to the host
1647    format. */
1648 static double
1649 flt64_to_double (const struct sfm_reader *r, const uint8_t flt64[8])
1650 {
1651   double x;
1652   if (r->float_format == FLOAT_NATIVE_DOUBLE)
1653     memcpy (&x, flt64, sizeof x);
1654   else
1655     float_convert (r->float_format, flt64, FLOAT_NATIVE_DOUBLE, &x);
1656   return x;
1657 }
1658