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