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