cleanup
[pspp] / src / data / pc+-file-reader.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 1997-2000, 2006-2007, 2009-2016 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 <errno.h>
20 #include <float.h>
21 #include <inttypes.h>
22 #include <stdlib.h>
23 #include <sys/stat.h>
24
25 #include "data/any-reader.h"
26 #include "data/case.h"
27 #include "data/casereader-provider.h"
28 #include "data/casereader.h"
29 #include "data/dictionary.h"
30 #include "data/file-handle-def.h"
31 #include "data/file-name.h"
32 #include "data/format.h"
33 #include "data/identifier.h"
34 #include "data/missing-values.h"
35 #include "data/value-labels.h"
36 #include "data/value.h"
37 #include "data/variable.h"
38 #include "libpspp/float-format.h"
39 #include "libpspp/i18n.h"
40 #include "libpspp/integer-format.h"
41 #include "libpspp/message.h"
42 #include "libpspp/misc.h"
43 #include "libpspp/pool.h"
44 #include "libpspp/str.h"
45
46 #include "gl/localcharset.h"
47 #include "gl/minmax.h"
48 #include "gl/xalloc.h"
49 #include "gl/xsize.h"
50
51 #include "gettext.h"
52 #define _(msgid) gettext (msgid)
53 #define N_(msgid) (msgid)
54
55 struct pcp_dir_entry
56   {
57     unsigned int ofs;
58     unsigned int len;
59   };
60
61 struct pcp_directory
62   {
63     struct pcp_dir_entry main;
64     struct pcp_dir_entry variables;
65     struct pcp_dir_entry labels;
66     struct pcp_dir_entry data;
67   };
68
69 struct pcp_main_header
70   {
71     char product[63];           /* "PCSPSS SYSTEM FILE..." */
72     unsigned int nominal_case_size; /* Number of var positions. */
73     char creation_date[9];      /* "[m]m/dd/yy". */
74     char creation_time[9];      /* "[H]H:MM:SS". */
75     char file_label[65];        /* File label. */
76     unsigned int weight_index;  /* Index of weighting variable, 0 if none. */
77   };
78
79 struct pcp_var_record
80   {
81     unsigned int pos;
82
83     bool drop;
84     union value tmp;
85
86     char name[9];
87     int width;
88     struct fmt_spec format;
89     uint8_t missing[8];
90     char *label;
91
92     bool weight;
93
94     struct pcp_value_label *val_labs;
95     size_t n_val_labs;
96   };
97
98 struct pcp_value_label
99   {
100     uint8_t value[8];
101     char *label;
102   };
103
104 /* System file reader. */
105 struct pcp_reader
106   {
107     struct any_reader any_reader;
108
109     /* Resource tracking. */
110     struct pool *pool;          /* All system file state. */
111
112     /* File data. */
113     unsigned int file_size;
114     struct any_read_info info;
115     struct pcp_directory directory;
116     struct pcp_main_header header;
117     struct pcp_var_record *vars;
118     size_t n_vars;
119
120     /* File state. */
121     struct file_handle *fh;     /* File handle. */
122     struct fh_lock *lock;       /* Mutual exclusion for file handle. */
123     FILE *file;                 /* File stream. */
124     unsigned int pos;           /* Position in file. */
125     bool error;                 /* I/O or corruption error? */
126     struct caseproto *proto;    /* Format of output cases. */
127
128     /* File format. */
129     unsigned int n_cases;       /* Number of cases */
130     const char *encoding;       /* String encoding. */
131
132     /* Decompression. */
133     bool compressed;
134     uint8_t opcodes[8];         /* Current block of opcodes. */
135     size_t opcode_idx;          /* Next opcode to interpret, 8 if none left. */
136     bool corruption_warning;    /* Warned about possible corruption? */
137   };
138
139 static struct pcp_reader *
140 pcp_reader_cast (const struct any_reader *r_)
141 {
142   assert (r_->klass == &pcp_file_reader_class);
143   return UP_CAST (r_, struct pcp_reader, any_reader);
144 }
145
146 static const struct casereader_class pcp_file_casereader_class;
147
148 static bool pcp_close (struct any_reader *);
149
150 static bool read_variables_record (struct pcp_reader *);
151
152 static void pcp_msg (struct pcp_reader *r, off_t, int class,
153                      const char *format, va_list args)
154      PRINTF_FORMAT (4, 0);
155 static void pcp_warn (struct pcp_reader *, off_t, const char *, ...)
156      PRINTF_FORMAT (3, 4);
157 static void pcp_error (struct pcp_reader *, off_t, const char *, ...)
158      PRINTF_FORMAT (3, 4);
159
160 static bool read_bytes (struct pcp_reader *, void *, size_t)
161   WARN_UNUSED_RESULT;
162 static int try_read_bytes (struct pcp_reader *, void *, size_t)
163   WARN_UNUSED_RESULT;
164 static bool read_uint16 (struct pcp_reader *, unsigned int *)
165   WARN_UNUSED_RESULT;
166 static bool read_uint32 (struct pcp_reader *, unsigned int *)
167   WARN_UNUSED_RESULT;
168 static bool read_float (struct pcp_reader *, double *)
169   WARN_UNUSED_RESULT;
170 static double parse_float (const uint8_t number[8]);
171 static bool read_string (struct pcp_reader *, char *, size_t)
172   WARN_UNUSED_RESULT;
173 static bool skip_bytes (struct pcp_reader *, size_t) WARN_UNUSED_RESULT;
174
175 static bool pcp_seek (struct pcp_reader *, off_t);
176
177 static bool pcp_is_sysmis(const uint8_t *);
178 \f
179 /* Dictionary reader. */
180
181 static bool read_dictionary (struct pcp_reader *);
182 static bool read_main_header (struct pcp_reader *, struct pcp_main_header *);
183 static void parse_header (struct pcp_reader *,
184                           const struct pcp_main_header *,
185                           struct any_read_info *, struct dictionary *);
186 static bool parse_variable_records (struct pcp_reader *, struct dictionary *,
187                                     struct pcp_var_record *, size_t n);
188
189 /* Tries to open FH for reading as an SPSS/PC+ system file.  Returns a
190    pcp_reader if successful, otherwise NULL. */
191 static struct any_reader *
192 pcp_open (struct file_handle *fh)
193 {
194   struct stat s;
195
196   /* Create and initialize reader. */
197   struct pcp_reader *r = XZALLOC (struct pcp_reader);
198   r->any_reader.klass = &pcp_file_reader_class;
199   r->pool = pool_create ();
200   pool_register (r->pool, free, r);
201   r->fh = fh_ref (fh);
202   r->opcode_idx = sizeof r->opcodes;
203
204   /* TRANSLATORS: this fragment will be interpolated into
205      messages in fh_lock() that identify types of files. */
206   r->lock = fh_lock (fh, FH_REF_FILE, N_("SPSS/PC+ system file"),
207                      FH_ACC_READ, false);
208   if (r->lock == NULL)
209     goto error;
210
211   /* Open file. */
212   r->file = fn_open (fh, "rb");
213   if (r->file == NULL)
214     {
215       msg (ME, _("Error opening `%s' for reading as an SPSS/PC+ "
216                  "system file: %s."),
217            fh_get_file_name (r->fh), strerror (errno));
218       goto error;
219     }
220
221   /* Fetch file size. */
222   if (fstat (fileno (r->file), &s))
223     {
224       pcp_error (r, 0, _("%s: stat failed (%s)."),
225                  fh_get_file_name (r->fh), strerror (errno));
226       goto error;
227     }
228   if (s.st_size > UINT_MAX)
229     {
230       pcp_error (r, 0, _("%s: file too large."), fh_get_file_name (r->fh));
231       goto error;
232     }
233   r->file_size = s.st_size;
234
235   /* Read dictionary. */
236   if (!read_dictionary (r))
237     goto error;
238
239   if (!pcp_seek (r, r->directory.data.ofs))
240     goto error;
241
242   return &r->any_reader;
243
244 error:
245   pcp_close (&r->any_reader);
246   return NULL;
247 }
248
249 static bool
250 pcp_read_dir_entry (struct pcp_reader *r, struct pcp_dir_entry *de)
251 {
252   if (!read_uint32 (r, &de->ofs) || !read_uint32 (r, &de->len))
253     return false;
254
255   if (de->len > r->file_size || de->ofs > r->file_size - de->len)
256     {
257       pcp_error (r, r->pos - 8, _("Directory entry is for a %u-byte record "
258                                   "starting at offset %u but file is only "
259                                   "%u bytes long."),
260                  de->ofs, de->len, r->file_size);
261       return false;
262     }
263
264   return true;
265 }
266
267 static bool
268 read_dictionary (struct pcp_reader *r)
269 {
270   unsigned int two, zero;
271
272   if (!read_uint32 (r, &two) || !read_uint32 (r, &zero))
273     return false;
274   if (two != 2 || zero != 0)
275     pcp_warn (r, 0, _("Directory fields have unexpected values "
276                       "(%u,%u)."), two, zero);
277
278   if (!pcp_read_dir_entry (r, &r->directory.main)
279       || !pcp_read_dir_entry (r, &r->directory.variables)
280       || !pcp_read_dir_entry (r, &r->directory.labels)
281       || !pcp_read_dir_entry (r, &r->directory.data))
282     return false;
283
284   if (!read_main_header (r, &r->header))
285     return false;
286
287   read_variables_record (r);
288
289   return true;
290 }
291
292 struct get_strings_aux
293   {
294     struct pool *pool;
295     char **titles;
296     char **strings;
297     bool *ids;
298     size_t allocated;
299     size_t n;
300   };
301
302 static void
303 add_string__ (struct get_strings_aux *aux,
304               const char *string, bool id, char *title)
305 {
306   if (aux->n >= aux->allocated)
307     {
308       aux->allocated = 2 * (aux->allocated + 1);
309       aux->titles = pool_realloc (aux->pool, aux->titles,
310                                   aux->allocated * sizeof *aux->titles);
311       aux->strings = pool_realloc (aux->pool, aux->strings,
312                                    aux->allocated * sizeof *aux->strings);
313       aux->ids = pool_realloc (aux->pool, aux->ids,
314                                aux->allocated * sizeof *aux->ids);
315     }
316
317   aux->titles[aux->n] = title;
318   aux->strings[aux->n] = pool_strdup (aux->pool, string);
319   aux->ids[aux->n] = id;
320   aux->n++;
321 }
322
323 static void PRINTF_FORMAT (3, 4)
324 add_string (struct get_strings_aux *aux,
325             const char *string, const char *title, ...)
326 {
327   va_list args;
328
329   va_start (args, title);
330   add_string__ (aux, string, false, pool_vasprintf (aux->pool, title, args));
331   va_end (args);
332 }
333
334 static void PRINTF_FORMAT (3, 4)
335 add_id (struct get_strings_aux *aux, const char *id, const char *title, ...)
336 {
337   va_list args;
338
339   va_start (args, title);
340   add_string__ (aux, id, true, pool_vasprintf (aux->pool, title, args));
341   va_end (args);
342 }
343
344 /* Retrieves significant string data from R in its raw format, to allow the
345    caller to try to detect the encoding in use.
346
347    Returns the number of strings retrieved N.  Sets each of *TITLESP, *IDSP,
348    and *STRINGSP to an array of N elements allocated from POOL.  For each I in
349    0...N-1, UTF-8 string *TITLESP[I] describes *STRINGSP[I], which is in
350    whatever encoding system file R uses.  *IDS[I] is true if *STRINGSP[I] must
351    be a valid PSPP language identifier, false if *STRINGSP[I] is free-form
352    text. */
353 static size_t
354 pcp_get_strings (const struct any_reader *r_, struct pool *pool,
355                  char ***titlesp, bool **idsp, char ***stringsp)
356 {
357   struct pcp_reader *r = pcp_reader_cast (r_);
358   struct get_strings_aux aux;
359   size_t var_idx;
360   size_t i, j;
361
362   aux.pool = pool;
363   aux.titles = NULL;
364   aux.strings = NULL;
365   aux.ids = NULL;
366   aux.allocated = 0;
367   aux.n = 0;
368
369   var_idx = 0;
370   for (i = 0; i < r->n_vars; i++)
371     if (r->vars[i].width != -1)
372       add_id (&aux, r->vars[i].name, _("Variable %zu"), ++var_idx);
373
374   var_idx = 0;
375   for (i = 0; i < r->n_vars; i++)
376     if (r->vars[i].width != -1)
377       {
378         var_idx++;
379         if (r->vars[i].label)
380           add_string (&aux, r->vars[i].label, _("Variable %zu Label"),
381                       var_idx);
382
383         for (j = 0; j < r->vars[i].n_val_labs; j++)
384           add_string (&aux, r->vars[i].label,
385                       _("Variable %zu Value Label %zu"), var_idx, j);
386       }
387
388   add_string (&aux, r->header.creation_date, _("Creation Date"));
389   add_string (&aux, r->header.creation_time, _("Creation Time"));
390   add_string (&aux, r->header.product, _("Product"));
391   add_string (&aux, r->header.file_label, _("File Label"));
392
393   *titlesp = aux.titles;
394   *idsp = aux.ids;
395   *stringsp = aux.strings;
396   return aux.n;
397 }
398
399 /* Decodes the dictionary read from R, saving it into *DICT.  Character
400    strings in R are decoded using ENCODING, or an encoding obtained from R if
401    ENCODING is null, or the locale encoding if R specifies no encoding.
402
403    If INFOP is non-null, then it receives additional info about the system
404    file, which the caller must eventually free with any_read_info_destroy()
405    when it is no longer needed.
406
407    This function consumes R.  The caller must use it again later, even to
408    destroy it with pcp_close(). */
409 static struct casereader *
410 pcp_decode (struct any_reader *r_, const char *encoding,
411             struct dictionary **dictp, struct any_read_info *infop)
412 {
413   struct pcp_reader *r = pcp_reader_cast (r_);
414   struct dictionary *dict;
415
416   if (encoding == NULL)
417     {
418       encoding = locale_charset ();
419       pcp_warn (r, -1, _("Using default encoding %s to read this SPSS/PC+ "
420                          "system file.  For best results, specify an "
421                          "encoding explicitly.  Use SYSFILE INFO with "
422                          "ENCODING=\"DETECT\" to analyze the possible "
423                          "encodings."),
424                 encoding);
425     }
426
427   dict = dict_create (encoding);
428   r->encoding = dict_get_encoding (dict);
429
430   parse_header (r, &r->header, &r->info, dict);
431   if (!parse_variable_records (r, dict, r->vars, r->n_vars))
432     goto error;
433
434   /* Create an index of dictionary variable widths for
435      pcp_read_case to use.  We cannot use the `struct variable's
436      from the dictionary we created, because the caller owns the
437      dictionary and may destroy or modify its variables. */
438   r->proto = caseproto_ref_pool (dict_get_proto (dict), r->pool);
439
440   *dictp = dict;
441   if (infop)
442     {
443       *infop = r->info;
444       memset (&r->info, 0, sizeof r->info);
445     }
446
447   return casereader_create_sequential
448     (NULL, r->proto, r->n_cases, &pcp_file_casereader_class, r);
449
450 error:
451   pcp_close (&r->any_reader);
452   dict_unref (dict);
453   *dictp = NULL;
454   return NULL;
455 }
456
457 /* Closes R, which should have been returned by pcp_open() but not already
458    closed with pcp_decode() or this function.
459    Returns true if an I/O error has occurred on READER, false
460    otherwise. */
461 static bool
462 pcp_close (struct any_reader *r_)
463 {
464   struct pcp_reader *r = pcp_reader_cast (r_);
465   bool error;
466
467   if (r->file)
468     {
469       if (fn_close (r->fh, r->file) == EOF)
470         {
471           msg (ME, _("Error closing system file `%s': %s."),
472                fh_get_file_name (r->fh), strerror (errno));
473           r->error = true;
474         }
475       r->file = NULL;
476     }
477
478   any_read_info_destroy (&r->info);
479   fh_unlock (r->lock);
480   fh_unref (r->fh);
481
482   error = r->error;
483   pool_destroy (r->pool);
484
485   return !error;
486 }
487
488 /* Destroys READER. */
489 static void
490 pcp_file_casereader_destroy (struct casereader *reader UNUSED, void *r_)
491 {
492   struct pcp_reader *r = r_;
493   pcp_close (&r->any_reader);
494 }
495
496 /* Detects whether FILE is an SPSS/PC+ system file.  Returns 1 if so, 0 if
497    not, and a negative errno value if there is an error reading FILE. */
498 static int
499 pcp_detect (FILE *file)
500 {
501   static const char signature[4] = "SPSS";
502   char buf[sizeof signature];
503
504   if (fseek (file, 0x104, SEEK_SET))
505     return -errno;
506
507   if (fread (buf, sizeof buf, 1, file) != 1)
508     return ferror (file) ? -errno : 0;
509
510   return !memcmp (buf, signature, sizeof buf);
511 }
512 \f
513 /* Reads the main header of the SPSS/PC+ system file.  Initializes *HEADER and
514    *INFO, except for the string fields in *INFO, which parse_header() will
515    initialize later once the file's encoding is known. */
516 static bool
517 read_main_header (struct pcp_reader *r, struct pcp_main_header *header)
518 {
519   unsigned int base_ofs = r->directory.main.ofs;
520   unsigned int zero0, zero1, zero2, zero3;
521   size_t min_values, min_data_size;
522   unsigned int one0, one1;
523   unsigned int compressed;
524   unsigned int n_cases1;
525   uint8_t sysmis[8];
526
527   if (!pcp_seek (r, base_ofs))
528     return false;
529
530   if (r->directory.main.len < 0xb0)
531     {
532       pcp_error (r, r->pos, _("This is not an SPSS/PC+ system file."));
533       return false;
534     }
535   else if (r->directory.main.len > 0xb0)
536     pcp_warn (r, r->pos, _("Record 0 has unexpected length %u."),
537               r->directory.main.len);
538
539   if (!read_uint16 (r, &one0)
540       || !read_string (r, header->product, sizeof header->product)
541       || !read_bytes (r, sysmis, sizeof sysmis)
542       || !read_uint32 (r, &zero0)
543       || !read_uint32 (r, &zero1)
544       || !read_uint16 (r, &one1)
545       || !read_uint16 (r, &compressed)
546       || !read_uint16 (r, &header->nominal_case_size)
547       || !read_uint16 (r, &r->n_cases)
548       || !read_uint16 (r, &header->weight_index)
549       || !read_uint16 (r, &zero2)
550       || !read_uint16 (r, &n_cases1)
551       || !read_uint16 (r, &zero3)
552       || !read_string (r, header->creation_date, sizeof header->creation_date)
553       || !read_string (r, header->creation_time, sizeof header->creation_time)
554       || !read_string (r, header->file_label, sizeof header->file_label))
555     return false;
556
557   if (!pcp_is_sysmis (sysmis))
558     {
559       double d = parse_float (sysmis);
560       pcp_warn (r, base_ofs, _("Record 0 specifies unexpected system missing "
561                                "value %g (%a)."), d, d);
562     }
563   if (one0 != 1 || one1 != 1
564       || zero0 != 0 || zero1 != 0 || zero2 != 0 || zero3 != 0)
565     pcp_warn (r, base_ofs, _("Record 0 reserved fields have unexpected values "
566                              "(%u,%u,%u,%u,%u,%u)."),
567               one0, one1, zero0, zero1, zero2, zero3);
568   if (n_cases1 != r->n_cases)
569     pcp_warn (r, base_ofs, _("Record 0 case counts differ (%u versus %u)."),
570               r->n_cases, n_cases1);
571   if (compressed != 0 && compressed != 1)
572     {
573       pcp_error (r, base_ofs, _("Invalid compression type %u."), compressed);
574       return false;
575     }
576
577   r->compressed = compressed != 0;
578
579   min_values = xtimes (header->nominal_case_size, r->n_cases);
580   min_data_size = xtimes (compressed ? 1 : 8, min_values);
581   if (r->directory.data.len < min_data_size
582       || size_overflow_p (min_data_size))
583     {
584       pcp_warn (r, base_ofs, _("Record 0 claims %u cases with %u values per "
585                                "case (requiring at least %zu bytes) but data "
586                                "record is only %u bytes long."),
587                 r->n_cases, header->nominal_case_size, min_data_size,
588                 r->directory.data.len);
589       return true;
590     }
591
592   return true;
593 }
594
595 static bool
596 read_value_labels (struct pcp_reader *r, struct pcp_var_record *var,
597                    unsigned int start, unsigned int end)
598 {
599   size_t allocated_val_labs = 0;
600
601   start += 7;
602   end += 7;
603   if (end > r->directory.labels.len)
604     {
605       pcp_warn (r, r->pos - 32,
606                 _("Value labels claimed to end at offset %u in labels record "
607                   "but labels record is only %u bytes."),
608                 end, r->directory.labels.len);
609       return true;
610     }
611
612   start += r->directory.labels.ofs;
613   end += r->directory.labels.ofs;
614   if (start > end || end > r->file_size)
615     {
616       pcp_warn (r, r->pos - 32,
617                 _("Value labels claimed to be at offset %u with length %u "
618                   "but file size is only %u bytes."),
619                 start, end - start, r->file_size);
620       return true;
621     }
622
623   if (!pcp_seek (r, start))
624     return false;
625
626   while (r->pos < end && end - r->pos > 8)
627     {
628       struct pcp_value_label *vl;
629       uint8_t len;
630
631       if (var->n_val_labs >= allocated_val_labs)
632         var->val_labs = pool_2nrealloc (r->pool, var->val_labs,
633                                         &allocated_val_labs,
634                                         sizeof *var->val_labs);
635       vl = &var->val_labs[var->n_val_labs];
636
637       if (!read_bytes (r, vl->value, sizeof vl->value)
638           || !read_bytes (r, &len, 1))
639         return false;
640
641       if (end - r->pos < len)
642         {
643           pcp_warn (r, r->pos,
644                     _("Value labels end with partial label (%u bytes left in "
645                       "record, label length %"PRIu8")."),
646                     end - r->pos, len);
647           return true;
648         }
649       vl->label = pool_malloc (r->pool, len + 1);
650       if (!read_bytes (r, vl->label, len))
651         return false;
652
653       vl->label[len] = '\0';
654       var->n_val_labs++;
655     }
656   if (r->pos < end)
657     pcp_warn (r, r->pos, _("%u leftover bytes following value labels."),
658               end - r->pos);
659
660   return true;
661 }
662
663 static bool
664 read_var_label (struct pcp_reader *r, struct pcp_var_record *var,
665                 unsigned int ofs)
666 {
667   uint8_t len;
668
669   ofs += 7;
670   if (ofs >= r->directory.labels.len)
671     {
672       pcp_warn (r, r->pos - 32,
673                 _("Variable label claimed to start at offset %u in labels "
674                   "record but labels record is only %u bytes."),
675                 ofs, r->directory.labels.len);
676       return true;
677     }
678
679   if (!pcp_seek (r, ofs + r->directory.labels.ofs) || !read_bytes (r, &len, 1))
680     return false;
681
682   if (len >= r->directory.labels.len - ofs)
683     {
684       pcp_warn (r, r->pos - 1,
685                 _("Variable label with length %u starting at offset %u in "
686                   "labels record overruns end of %u-byte labels record."),
687                 len, ofs + 1, r->directory.labels.len);
688       return false;
689     }
690
691   var->label = pool_malloc (r->pool, len + 1);
692   var->label[len] = '\0';
693   return read_bytes (r, var->label, len);
694 }
695
696 /* Reads the variables record (record 1) into R. */
697 static bool
698 read_variables_record (struct pcp_reader *r)
699 {
700   unsigned int i;
701   bool weighted;
702
703   if (!pcp_seek (r, r->directory.variables.ofs))
704     return false;
705   if (r->directory.variables.len != r->header.nominal_case_size * 32)
706     {
707       pcp_error (r, r->pos, _("Record 1 has length %u (expected %u)."),
708                  r->directory.variables.len, r->header.nominal_case_size * 32);
709       return false;
710     }
711
712   r->vars = pool_calloc (r->pool,
713                          r->header.nominal_case_size, sizeof *r->vars);
714   weighted = false;
715   for (i = 0; i < r->header.nominal_case_size; i++)
716     {
717       struct pcp_var_record *var = &r->vars[r->n_vars++];
718       unsigned int value_label_start, value_label_end;
719       unsigned int var_label_ofs;
720       unsigned int format;
721       uint8_t raw_type;
722
723       var->pos = r->pos;
724       if (!read_uint32 (r, &value_label_start)
725           || !read_uint32 (r, &value_label_end)
726           || !read_uint32 (r, &var_label_ofs)
727           || !read_uint32 (r, &format)
728           || !read_string (r, var->name, sizeof var->name)
729           || !read_bytes (r, var->missing, sizeof var->missing))
730         return false;
731
732       var->weight = r->header.weight_index && i == r->header.weight_index - 1;
733       if (var->weight)
734         weighted = true;
735
736       raw_type = format >> 16;
737       if (!fmt_from_io (raw_type, &var->format.type))
738         {
739           pcp_error (r, var->pos, _("Variable %u has invalid type %"PRIu8"."),
740                      i, raw_type);
741           return false;
742         }
743
744       var->format.w = (format >> 8) & 0xff;
745       var->format.d = format & 0xff;
746       fmt_fix_output (&var->format);
747       var->width = fmt_var_width (var->format);
748
749       if (var_label_ofs)
750         {
751           unsigned int save_pos = r->pos;
752           if (!read_var_label (r, var, var_label_ofs)
753               || !pcp_seek (r, save_pos))
754             return false;
755         }
756
757       if (value_label_end > value_label_start && var->width <= 8)
758         {
759           unsigned int save_pos = r->pos;
760           if (!read_value_labels (r, var, value_label_start, value_label_end)
761               || !pcp_seek (r, save_pos))
762             return false;
763         }
764
765       if (var->width > 8)
766         {
767           int extra = DIV_RND_UP (var->width - 8, 8);
768           i += extra;
769           if (!skip_bytes (r, 32 * extra))
770             return false;
771         }
772     }
773
774   if (r->header.weight_index && !weighted)
775     pcp_warn (r, -1, _("Invalid weight index %u."), r->header.weight_index);
776
777   return true;
778 }
779
780 static char *
781 recode_and_trim_string (struct pool *pool, const char *from, const char *in)
782 {
783   struct substring out;
784
785   out = recode_substring_pool ("UTF-8", from, ss_cstr (in), pool);
786   ss_trim (&out, ss_cstr (" "));
787   return ss_xstrdup (out);
788 }
789
790 static void
791 parse_header (struct pcp_reader *r, const struct pcp_main_header *header,
792               struct any_read_info *info, struct dictionary *dict)
793 {
794   const char *dict_encoding = dict_get_encoding (dict);
795   char *label;
796
797   memset (info, 0, sizeof *info);
798
799   info->integer_format = INTEGER_LSB_FIRST;
800   info->float_format = FLOAT_IEEE_DOUBLE_LE;
801   info->compression = r->compressed ? ANY_COMP_SIMPLE : ANY_COMP_NONE;
802   info->n_cases = r->n_cases;
803
804   /* Convert file label to UTF-8 and put it into DICT. */
805   label = recode_and_trim_string (r->pool, dict_encoding, header->file_label);
806   dict_set_label (dict, label);
807   free (label);
808
809   /* Put creation date, time, and product in UTF-8 into INFO. */
810   info->creation_date = recode_and_trim_string (r->pool, dict_encoding,
811                                                 header->creation_date);
812   info->creation_time = recode_and_trim_string (r->pool, dict_encoding,
813                                                 header->creation_time);
814   info->product = recode_and_trim_string (r->pool, dict_encoding,
815                                           header->product);
816 }
817
818 /* Reads a variable (type 2) record from R and adds the
819    corresponding variable to DICT.
820    Also skips past additional variable records for long string
821    variables. */
822 static bool
823 parse_variable_records (struct pcp_reader *r, struct dictionary *dict,
824                         struct pcp_var_record *var_recs, size_t n_var_recs)
825 {
826   const char *dict_encoding = dict_get_encoding (dict);
827   struct pcp_var_record *rec;
828
829   for (rec = var_recs; rec < &var_recs[n_var_recs]; rec++)
830     {
831       char *name;
832       size_t i;
833
834       name = recode_string_pool ("UTF-8", dict_encoding,
835                                  rec->name, -1, r->pool);
836       name[strcspn (name, " ")] = '\0';
837
838       /* Drop system variables. */
839       rec->drop = name[0] == '$';
840       if (rec->drop)
841         {
842           value_init_pool (r->pool, &rec->tmp, rec->width);
843           continue;
844         }
845
846       if (!dict_id_is_valid (dict, name) || name[0] == '#')
847         {
848           pcp_error (r, rec->pos, _("Invalid variable name `%s'."), name);
849           return false;
850         }
851
852       struct variable *var = dict_create_var (dict, name, rec->width);
853       if (var == NULL)
854         {
855           char *new_name = dict_make_unique_var_name (dict, NULL, NULL);
856           pcp_warn (r, rec->pos, _("Renaming variable with duplicate name "
857                                    "`%s' to `%s'."),
858                     name, new_name);
859           var = dict_create_var_assert (dict, new_name, rec->width);
860           free (new_name);
861         }
862       if (rec->weight)
863         {
864           if (!rec->width)
865             dict_set_weight (dict, var);
866           else
867             pcp_warn (r, rec->pos,
868                       _("Cannot weight by string variable `%s'."), name);
869         }
870
871       /* Set the short name the same as the long name. */
872       var_set_short_name (var, 0, name);
873
874       /* Get variable label, if any. */
875       if (rec->label)
876         {
877           char *utf8_label;
878
879           utf8_label = recode_string ("UTF-8", dict_encoding, rec->label, -1);
880           var_set_label (var, utf8_label);
881           free (utf8_label);
882         }
883
884       /* Add value labels. */
885       for (i = 0; i < rec->n_val_labs; i++)
886         {
887           union value value;
888           char *utf8_label;
889
890           value_init (&value, rec->width);
891           if (var_is_numeric (var))
892             value.f = parse_float (rec->val_labs[i].value);
893           else
894             memcpy (value.s, rec->val_labs[i].value, rec->width);
895
896           utf8_label = recode_string ("UTF-8", dict_encoding,
897                                       rec->val_labs[i].label, -1);
898           var_add_value_label (var, &value, utf8_label);
899           free (utf8_label);
900
901           value_destroy (&value, rec->width);
902         }
903
904       /* Set missing values. */
905       if (rec->width <= 8 && !pcp_is_sysmis (rec->missing))
906         {
907           int width = var_get_width (var);
908           struct missing_values mv;
909
910           mv_init_pool (r->pool, &mv, width);
911           if (var_is_numeric (var))
912             mv_add_num (&mv, parse_float (rec->missing));
913           else
914             mv_add_str (&mv, rec->missing, MIN (width, 8));
915           var_set_missing_values (var, &mv);
916         }
917
918       /* Set formats. */
919       var_set_both_formats (var, rec->format);
920     }
921
922   return true;
923 }
924 \f
925 /* Case reader. */
926
927 static void read_error (struct casereader *, const struct pcp_reader *);
928
929 static bool read_case_number (struct pcp_reader *, double *);
930 static int read_case_string (struct pcp_reader *, uint8_t *, size_t);
931 static int read_opcode (struct pcp_reader *);
932 static bool read_compressed_number (struct pcp_reader *, double *);
933 static int read_compressed_string (struct pcp_reader *, uint8_t *);
934 static int read_whole_strings (struct pcp_reader *, uint8_t *, size_t);
935
936 /* Reads and returns one case from READER's file.  Returns a null
937    pointer if not successful. */
938 static struct ccase *
939 pcp_file_casereader_read (struct casereader *reader, void *r_)
940 {
941   struct pcp_reader *r = r_;
942   unsigned int start_pos = r->pos;
943   struct ccase *c;
944   int retval;
945   int i;
946
947   if (r->error || !r->n_cases)
948     return NULL;
949   r->n_cases--;
950
951   c = case_create (r->proto);
952   size_t case_idx = 0;
953   for (i = 0; i < r->n_vars; i++)
954     {
955       struct pcp_var_record *var = &r->vars[i];
956       union value *v = var->drop ? &var->tmp : case_data_rw_idx (c, case_idx++);
957
958       if (var->width == 0)
959         retval = read_case_number (r, &v->f);
960       else
961         retval = read_case_string (r, v->s, var->width);
962
963       if (retval != 1)
964         {
965           pcp_error (r, r->pos, _("File ends in partial case."));
966           goto error;
967         }
968     }
969   if (r->pos > r->directory.data.ofs + r->directory.data.len)
970     {
971       pcp_error (r, r->pos, _("Case beginning at offset 0x%08x extends past "
972                               "end of data record at offset 0x%08x."),
973                  start_pos, r->directory.data.ofs + r->directory.data.len);
974       goto error;
975     }
976
977   return c;
978
979 error:
980   read_error (reader, r);
981   case_unref (c);
982   return NULL;
983 }
984
985 /* Issues an error that an unspecified error occurred PCP, and
986    marks R tainted. */
987 static void
988 read_error (struct casereader *r, const struct pcp_reader *pcp)
989 {
990   msg (ME, _("Error reading case from file %s."), fh_get_name (pcp->fh));
991   casereader_force_error (r);
992 }
993
994 /* Reads a number from R and stores its value in *D.
995    If R is compressed, reads a compressed number;
996    otherwise, reads a number in the regular way.
997    Returns true if successful, false if end of file is
998    reached immediately. */
999 static bool
1000 read_case_number (struct pcp_reader *r, double *d)
1001 {
1002   if (!r->compressed)
1003     {
1004       uint8_t number[8];
1005       if (!try_read_bytes (r, number, sizeof number))
1006         return false;
1007       *d = parse_float (number);
1008       return true;
1009     }
1010   else
1011     return read_compressed_number (r, d);
1012 }
1013
1014 /* Reads LENGTH string bytes from R into S.  Always reads a multiple of 8
1015    bytes; if LENGTH is not a multiple of 8, then extra bytes are read and
1016    discarded without being written to S.  Reads compressed strings if S is
1017    compressed.  Returns 1 if successful, 0 if end of file is reached
1018    immediately, or -1 for some kind of error. */
1019 static int
1020 read_case_string (struct pcp_reader *r, uint8_t *s, size_t length)
1021 {
1022   size_t whole = ROUND_DOWN (length, 8);
1023   size_t partial = length % 8;
1024
1025   if (whole)
1026     {
1027       int retval = read_whole_strings (r, s, whole);
1028       if (retval != 1)
1029         return retval;
1030     }
1031
1032   if (partial)
1033     {
1034       uint8_t bounce[8];
1035       int retval = read_whole_strings (r, bounce, sizeof bounce);
1036       if (retval <= 0)
1037         return -1;
1038       memcpy (s + whole, bounce, partial);
1039     }
1040
1041   return 1;
1042 }
1043
1044 /* Reads and returns the next compression opcode from R. */
1045 static int
1046 read_opcode (struct pcp_reader *r)
1047 {
1048   assert (r->compressed);
1049   if (r->opcode_idx >= sizeof r->opcodes)
1050     {
1051       int retval = try_read_bytes (r, r->opcodes, sizeof r->opcodes);
1052       if (retval != 1)
1053         return -1;
1054       r->opcode_idx = 0;
1055     }
1056   return r->opcodes[r->opcode_idx++];
1057 }
1058
1059 /* Reads a compressed number from R and stores its value in D.
1060    Returns true if successful, false if end of file is
1061    reached immediately. */
1062 static bool
1063 read_compressed_number (struct pcp_reader *r, double *d)
1064 {
1065   int opcode = read_opcode (r);
1066   switch (opcode)
1067     {
1068     case -1:
1069       return false;
1070
1071     case 0:
1072       *d = SYSMIS;
1073       return true;
1074
1075     case 1:
1076       return read_float (r, d);
1077
1078     default:
1079       *d = opcode - 105.0;
1080       return true;
1081     }
1082 }
1083
1084 /* Reads a compressed 8-byte string segment from R and stores it in DST. */
1085 static int
1086 read_compressed_string (struct pcp_reader *r, uint8_t *dst)
1087 {
1088   int opcode;
1089   int retval;
1090
1091   opcode = read_opcode (r);
1092   switch (opcode)
1093     {
1094     case -1:
1095       return 0;
1096
1097     case 1:
1098       retval = read_bytes (r, dst, 8);
1099       return retval == 1 ? 1 : -1;
1100
1101     default:
1102       if (!r->corruption_warning)
1103         {
1104           r->corruption_warning = true;
1105           pcp_warn (r, r->pos,
1106                     _("Possible compressed data corruption: "
1107                       "string contains compressed integer (opcode %d)."),
1108                     opcode);
1109       }
1110       memset (dst, ' ', 8);
1111       return 1;
1112     }
1113 }
1114
1115 /* Reads LENGTH string bytes from R into S.  LENGTH must be a multiple of 8.
1116    Reads compressed strings if S is compressed.  Returns 1 if successful, 0 if
1117    end of file is reached immediately, or -1 for some kind of error. */
1118 static int
1119 read_whole_strings (struct pcp_reader *r, uint8_t *s, size_t length)
1120 {
1121   assert (length % 8 == 0);
1122   if (!r->compressed)
1123     return try_read_bytes (r, s, length);
1124   else
1125     {
1126       size_t ofs;
1127
1128       for (ofs = 0; ofs < length; ofs += 8)
1129         {
1130           int retval = read_compressed_string (r, s + ofs);
1131           if (retval != 1)
1132             return -1;
1133           }
1134       return 1;
1135     }
1136 }
1137 \f
1138 /* Messages. */
1139
1140 /* Displays a corruption message. */
1141 static void
1142 pcp_msg (struct pcp_reader *r, off_t offset,
1143          int class, const char *format, va_list args)
1144 {
1145   struct string text;
1146   ds_init_empty (&text);
1147   if (offset >= 0)
1148     ds_put_format (&text, _("`%s' near offset 0x%llx: "),
1149                    fh_get_file_name (r->fh), (long long int) offset);
1150   else
1151     ds_put_format (&text, _("`%s': "), fh_get_file_name (r->fh));
1152   ds_put_vformat (&text, format, args);
1153
1154   struct msg *m = xmalloc (sizeof *m);
1155   *m = (struct msg) {
1156     .category = msg_class_to_category (class),
1157     .severity = msg_class_to_severity (class),
1158     .text = ds_steal_cstr (&text),
1159   };
1160   msg_emit (m);
1161 }
1162
1163 /* Displays a warning for offset OFFSET in the file. */
1164 static void
1165 pcp_warn (struct pcp_reader *r, off_t offset, const char *format, ...)
1166 {
1167   va_list args;
1168
1169   va_start (args, format);
1170   pcp_msg (r, offset, MW, format, args);
1171   va_end (args);
1172 }
1173
1174 /* Displays an error for the current file position,
1175    marks it as in an error state,
1176    and aborts reading it using longjmp. */
1177 static void
1178 pcp_error (struct pcp_reader *r, off_t offset, const char *format, ...)
1179 {
1180   va_list args;
1181
1182   va_start (args, format);
1183   pcp_msg (r, offset, ME, format, args);
1184   va_end (args);
1185
1186   r->error = true;
1187 }
1188 \f
1189 /* Reads BYTE_CNT bytes into BUF.
1190    Returns 1 if exactly BYTE_CNT bytes are successfully read.
1191    Returns -1 if an I/O error or a partial read occurs.
1192    Returns 0 for an immediate end-of-file and, if EOF_IS_OK is false, reports
1193    an error. */
1194 static inline int
1195 read_bytes_internal (struct pcp_reader *r, bool eof_is_ok,
1196                      void *buf, size_t n_bytes)
1197 {
1198   size_t bytes_read = fread (buf, 1, n_bytes, r->file);
1199   r->pos += bytes_read;
1200   if (bytes_read == n_bytes)
1201     return 1;
1202   else if (ferror (r->file))
1203     {
1204       pcp_error (r, r->pos, _("System error: %s."), strerror (errno));
1205       return -1;
1206     }
1207   else if (!eof_is_ok || bytes_read != 0)
1208     {
1209       pcp_error (r, r->pos, _("Unexpected end of file."));
1210       return -1;
1211     }
1212   else
1213     return 0;
1214 }
1215
1216 /* Reads BYTE_CNT into BUF.
1217    Returns true if successful.
1218    Returns false upon I/O error or if end-of-file is encountered. */
1219 static bool
1220 read_bytes (struct pcp_reader *r, void *buf, size_t n_bytes)
1221 {
1222   return read_bytes_internal (r, false, buf, n_bytes) == 1;
1223 }
1224
1225 /* Reads BYTE_CNT bytes into BUF.
1226    Returns 1 if exactly BYTE_CNT bytes are successfully read.
1227    Returns 0 if an immediate end-of-file is encountered.
1228    Returns -1 if an I/O error or a partial read occurs. */
1229 static int
1230 try_read_bytes (struct pcp_reader *r, void *buf, size_t n_bytes)
1231 {
1232   return read_bytes_internal (r, true, buf, n_bytes);
1233 }
1234
1235 /* Reads a 16-bit signed integer from R and stores its value in host format in
1236    *X.  Returns true if successful, otherwise false. */
1237 static bool
1238 read_uint16 (struct pcp_reader *r, unsigned int *x)
1239 {
1240   uint8_t integer[2];
1241   if (read_bytes (r, integer, sizeof integer) != 1)
1242     return false;
1243   *x = integer_get (INTEGER_LSB_FIRST, integer, sizeof integer);
1244   return true;
1245 }
1246
1247 /* Reads a 32-bit signed integer from R and stores its value in host format in
1248    *X.  Returns true if successful, otherwise false. */
1249 static bool
1250 read_uint32 (struct pcp_reader *r, unsigned int *x)
1251 {
1252   uint8_t integer[4];
1253   if (read_bytes (r, integer, sizeof integer) != 1)
1254     return false;
1255   *x = integer_get (INTEGER_LSB_FIRST, integer, sizeof integer);
1256   return true;
1257 }
1258
1259 /* Reads exactly SIZE - 1 bytes into BUFFER
1260    and stores a null byte into BUFFER[SIZE - 1]. */
1261 static bool
1262 read_string (struct pcp_reader *r, char *buffer, size_t size)
1263 {
1264   bool ok;
1265
1266   assert (size > 0);
1267   ok = read_bytes (r, buffer, size - 1);
1268   if (ok)
1269     buffer[size - 1] = '\0';
1270   return ok;
1271 }
1272
1273 /* Skips BYTES bytes forward in R. */
1274 static bool
1275 skip_bytes (struct pcp_reader *r, size_t bytes)
1276 {
1277   while (bytes > 0)
1278     {
1279       char buffer[1024];
1280       size_t chunk = MIN (sizeof buffer, bytes);
1281       if (!read_bytes (r, buffer, chunk))
1282         return false;
1283       bytes -= chunk;
1284     }
1285
1286   return true;
1287 }
1288 \f
1289 static bool
1290 pcp_seek (struct pcp_reader *r, off_t offset)
1291 {
1292   if (fseeko (r->file, offset, SEEK_SET))
1293     {
1294       pcp_error (r, 0, _("%s: seek failed (%s)."),
1295                  fh_get_file_name (r->fh), strerror (errno));
1296       return false;
1297     }
1298   r->pos = offset;
1299   return true;
1300 }
1301
1302 /* Reads a 64-bit floating-point number from R and returns its
1303    value in host format. */
1304 static bool
1305 read_float (struct pcp_reader *r, double *d)
1306 {
1307   uint8_t number[8];
1308
1309   if (!read_bytes (r, number, sizeof number))
1310     return false;
1311   else
1312     {
1313       *d = parse_float (number);
1314       return true;
1315     }
1316 }
1317
1318 static double
1319 parse_float (const uint8_t number[8])
1320 {
1321   return (pcp_is_sysmis (number)
1322           ? SYSMIS
1323           : float_get_double (FLOAT_IEEE_DOUBLE_LE, number));
1324 }
1325
1326 static bool
1327 pcp_is_sysmis(const uint8_t *p)
1328 {
1329   static const uint8_t sysmis[8]
1330     = { 0xf5, 0x1e, 0x26, 0x02, 0x8a, 0x8c, 0xed, 0xff };
1331   return !memcmp (p, sysmis, 8);
1332 }
1333 \f
1334 static const struct casereader_class pcp_file_casereader_class =
1335   {
1336     pcp_file_casereader_read,
1337     pcp_file_casereader_destroy,
1338     NULL,
1339     NULL,
1340   };
1341
1342 const struct any_reader_class pcp_file_reader_class =
1343   {
1344     N_("SPSS/PC+ System File"),
1345     pcp_detect,
1346     pcp_open,
1347     pcp_close,
1348     pcp_decode,
1349     pcp_get_strings,
1350   };