abc14edb0198a5c0f5ff432a8f8eae3f59ffa0c7
[pspp-builds.git] / src / pfm-read.c
1 /* PSPP - computes sample statistics.
2    Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
3    Written by Ben Pfaff <blp@gnu.org>.
4    Code for parsing floating-point numbers adapted from GNU C
5    library.
6
7    This program is free software; you can redistribute it and/or
8    modify it under the terms of the GNU General Public License as
9    published by the Free Software Foundation; either version 2 of the
10    License, or (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful, but
13    WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15    General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20    02111-1307, USA. */
21
22 #include <config.h>
23 #include "pfm-read.h"
24 #include "error.h"
25 #include <stdarg.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <ctype.h>
29 #include <errno.h>
30 #include <math.h>
31 #include "alloc.h"
32 #include "case.h"
33 #include "dictionary.h"
34 #include "file-handle.h"
35 #include "format.h"
36 #include "getline.h"
37 #include "hash.h"
38 #include "magic.h"
39 #include "misc.h"
40 #include "str.h"
41 #include "value-labels.h"
42 #include "var.h"
43
44 #include "debug-print.h"
45
46 /* Portable file reader. */
47 struct pfm_reader
48   {
49     struct file_handle *fh;     /* File handle. */
50     FILE *file;                 /* File stream. */
51
52     int weight_index;           /* 0-based index of weight variable, or -1. */
53
54     unsigned char *trans;       /* 256-byte character set translation table. */
55
56     int var_cnt;                /* Number of variables. */
57     int *widths;                /* Variable widths, 0 for numeric. */
58     int value_cnt;              /* Number of `value's per case. */
59
60     unsigned char buf[83];      /* Input buffer. */
61     unsigned char *bp;          /* Buffer pointer. */
62     int cc;                     /* Current character. */
63   };
64
65 static int 
66 corrupt_msg (struct pfm_reader *r, const char *format,...)
67      PRINTF_FORMAT (2, 3);
68
69 /* Displays a corruption error. */
70 static int
71 corrupt_msg (struct pfm_reader *r, const char *format, ...)
72 {
73   char buf[1024];
74   
75   {
76     va_list args;
77
78     va_start (args, format);
79     vsnprintf (buf, 1024, format, args);
80     va_end (args);
81   }
82   
83   {
84     char *title;
85     struct error e;
86     const char *filename;
87
88     e.class = ME;
89     getl_location (&e.where.filename, &e.where.line_number);
90     filename = handle_get_filename (r->fh);
91     e.title = title = local_alloc (strlen (filename) + 80);
92     sprintf (title, _("portable file %s corrupt at offset %ld: "),
93              filename, ftell (r->file) - (82 - (long) (r->bp - r->buf)));
94     e.text = buf;
95
96     err_vmsg (&e);
97
98     local_free (title);
99   }
100   
101   return 0;
102 }
103
104 static unsigned char * read_string (struct pfm_reader *r);
105
106 /* Closes a portable file after we're done with it. */
107 void
108 pfm_close_reader (struct pfm_reader *r)
109 {
110   if (r == NULL)
111     return;
112
113   read_string (NULL);
114
115   if (r->fh != NULL)
116     fh_close (r->fh, "portable file", "rs");
117   if (fclose (r->file) == EOF)
118     msg (ME, _("%s: Closing portable file: %s."),
119          handle_get_filename (r->fh), strerror (errno));
120   free (r->trans);
121   free (r->widths);
122   free (r);
123 }
124
125 /* Displays the message X with corrupt_msg, then jumps to the error
126    label. */
127 #define lose(X)                                 \
128         do {                                    \
129             corrupt_msg X;                      \
130             goto error;                       \
131         } while (0)
132
133 /* Read an 80-character line into handle H's buffer.  Return
134    success. */
135 static int
136 fill_buf (struct pfm_reader *r)
137 {
138   if (80 != fread (r->buf, 1, 80, r->file))
139     lose ((r, _("Unexpected end of file.")));
140
141   /* PORTME: line ends. */
142   {
143     int c;
144     
145     c = getc (r->file);
146     if (c != '\n' && c != '\r')
147       lose ((r, _("Bad line end.")));
148
149     c = getc (r->file);
150     if (c != '\n' && c != '\r')
151       ungetc (c, r->file);
152   }
153   
154   if (r->trans)
155     {
156       int i;
157       
158       for (i = 0; i < 80; i++)
159         r->buf[i] = r->trans[r->buf[i]];
160     }
161
162   r->bp = r->buf;
163
164   return 1;
165
166  error:
167   return 0;
168 }
169
170 /* Read a single character into cur_char.  Return success; */
171 static int
172 read_char (struct pfm_reader *r)
173 {
174   if (r->bp >= &r->buf[80] && !fill_buf (r))
175     return 0;
176   r->cc = *r->bp++;
177   return 1;
178 }
179
180 /* Advance a single character. */
181 #define advance()                               \
182         do {                                    \
183           if (!read_char (r))                   \
184             goto error;                       \
185         } while (0)
186
187 /* Skip a single character if present, and return whether it was
188    skipped. */
189 static inline int
190 skip_char (struct pfm_reader *r, int c)
191 {
192   if (r->cc == c)
193     {
194       advance ();
195       return 1;
196     }
197  error:
198   return 0;
199 }
200
201 /* Skip a single character if present, and return whether it was
202    skipped. */
203 #define match(C) skip_char (r, C)
204
205 static int read_header (struct pfm_reader *);
206 static int read_version_data (struct pfm_reader *, struct pfm_read_info *);
207 static int read_variables (struct pfm_reader *, struct dictionary *);
208 static int read_value_label (struct pfm_reader *, struct dictionary *);
209 void dump_dictionary (struct dictionary *);
210
211 /* Reads the dictionary from file with handle H, and returns it in a
212    dictionary structure.  This dictionary may be modified in order to
213    rename, reorder, and delete variables, etc. */
214 struct pfm_reader *
215 pfm_open_reader (struct file_handle *fh, struct dictionary **dict,
216                  struct pfm_read_info *info)
217 {
218   struct pfm_reader *r = NULL;
219
220   *dict = dict_create ();
221   if (!fh_open (fh, "portable file", "rs"))
222     goto error;
223
224   /* Create and initialize reader. */
225   r = xmalloc (sizeof *r);
226   r->fh = fh;
227   r->file = fopen (handle_get_filename (r->fh), "rb");
228   r->weight_index = -1;
229   r->trans = NULL;
230   r->var_cnt = 0;
231   r->widths = NULL;
232   r->value_cnt = 0;
233   r->bp = NULL;
234
235   /* Check that file open succeeded, prime reading. */
236   if (r->file == NULL)
237     {
238       msg (ME, _("An error occurred while opening \"%s\" for reading "
239                  "as a portable file: %s."),
240            handle_get_filename (r->fh), strerror (errno));
241       err_cond_fail ();
242       goto error;
243     }
244   if (!fill_buf (r))
245     goto error;
246   advance ();
247
248   /* Read header, version, date info, product id, variables. */
249   if (!read_header (r)
250       || !read_version_data (r, info)
251       || !read_variables (r, *dict))
252     goto error;
253
254   /* Read value labels. */
255   while (match (77 /* D */))
256     if (!read_value_label (r, *dict))
257       goto error;
258
259   /* Check that we've made it to the data. */
260   if (!match (79 /* F */))
261     lose ((r, _("Data record expected.")));
262
263   return r;
264
265  error:
266   pfm_close_reader (r);
267   dict_destroy (*dict);
268   *dict = NULL;
269   return NULL;
270 }
271 \f
272 /* Read a floating point value and return its value, or
273    second_lowest_value on error. */
274 static double
275 read_float (struct pfm_reader *r)
276 {
277   double num = 0.;
278   int got_dot = 0;
279   int got_digit = 0;
280   int exponent = 0;
281   int neg = 0;
282
283   /* Skip leading spaces. */
284   while (match (126 /* space */))
285     ;
286
287   if (match (137 /* * */))
288     {
289       advance ();       /* Probably a dot (.) but doesn't appear to matter. */
290       return SYSMIS;
291     }
292   else if (match (141 /* - */))
293     neg = 1;
294
295   for (;;)
296     {
297       if (r->cc >= 64 /* 0 */ && r->cc <= 93 /* T */)
298         {
299           got_digit++;
300
301           /* Make sure that multiplication by 30 will not overflow.  */
302           if (num > DBL_MAX * (1. / 30.))
303             /* The value of the digit doesn't matter, since we have already
304                gotten as many digits as can be represented in a `double'.
305                This doesn't necessarily mean the result will overflow.
306                The exponent may reduce it to within range.
307
308                We just need to record that there was another
309                digit so that we can multiply by 10 later.  */
310             ++exponent;
311           else
312             num = (num * 30.0) + (r->cc - 64);
313
314           /* Keep track of the number of digits after the decimal point.
315              If we just divided by 30 here, we would lose precision.  */
316           if (got_dot)
317             --exponent;
318         }
319       else if (!got_dot && r->cc == 127 /* . */)
320         /* Record that we have found the decimal point.  */
321         got_dot = 1;
322       else
323         /* Any other character terminates the number.  */
324         break;
325
326       advance ();
327     }
328
329   if (!got_digit)
330     lose ((r, "Number expected."));
331       
332   if (r->cc == 130 /* + */ || r->cc == 141 /* - */)
333     {
334       /* Get the exponent.  */
335       long int exp = 0;
336       int neg_exp = r->cc == 141 /* - */;
337
338       for (;;)
339         {
340           advance ();
341
342           if (r->cc < 64 /* 0 */ || r->cc > 93 /* T */)
343             break;
344
345           if (exp > LONG_MAX / 30)
346             goto overflow;
347           exp = exp * 30 + (r->cc - 64);
348         }
349
350       /* We don't check whether there were actually any digits, but we
351          probably should. */
352       if (neg_exp)
353         exp = -exp;
354       exponent += exp;
355     }
356   
357   if (!match (142 /* / */))
358     lose ((r, _("Missing numeric terminator.")));
359
360   /* Multiply NUM by 30 to the EXPONENT power, checking for overflow.  */
361
362   if (exponent < 0)
363     num *= pow (30.0, (double) exponent);
364   else if (exponent > 0)
365     {
366       if (num > DBL_MAX * pow (30.0, (double) -exponent))
367         goto overflow;
368       num *= pow (30.0, (double) exponent);
369     }
370
371   if (neg)
372     return -num;
373   else
374     return num;
375
376  overflow:
377   if (neg)
378     return -DBL_MAX / 10.;
379   else
380     return DBL_MAX / 10;
381
382  error:
383   return second_lowest_value;
384 }
385   
386 /* Read an integer and return its value, or NOT_INT on failure. */
387 static int
388 read_int (struct pfm_reader *r)
389 {
390   double f = read_float (r);
391
392   if (f == second_lowest_value)
393     goto error;
394   if (floor (f) != f || f >= INT_MAX || f <= INT_MIN)
395     lose ((r, _("Bad integer format.")));
396   return f;
397
398  error:
399   return NOT_INT;
400 }
401
402 /* Reads a string and returns its value in a static buffer, or NULL on
403    failure.  The buffer can be deallocated by calling with a NULL
404    argument. */
405 static unsigned char *
406 read_string (struct pfm_reader *r)
407 {
408   static char *buf;
409   int n;
410   
411   if (r == NULL)
412     {
413       free (buf);
414       buf = NULL;
415       return NULL;
416     }
417   else if (buf == NULL)
418     buf = xmalloc (256);
419
420   n = read_int (r);
421   if (n == NOT_INT)
422     return NULL;
423   if (n < 0 || n > 255)
424     lose ((r, _("Bad string length %d."), n));
425   
426   {
427     int i;
428
429     for (i = 0; i < n; i++)
430       {
431         buf[i] = r->cc;
432         advance ();
433       }
434   }
435   
436   buf[n] = 0;
437   return buf;
438
439  error:
440   return NULL;
441 }
442 \f
443 /* Reads the 464-byte file header. */
444 int
445 read_header (struct pfm_reader *r)
446 {
447   /* For now at least, just ignore the vanity splash strings. */
448   {
449     int i;
450
451     for (i = 0; i < 200; i++)
452       advance ();
453   }
454   
455   {
456     unsigned char src[256];
457     int trans_temp[256];
458     int i;
459
460     for (i = 0; i < 256; i++)
461       {
462         src[i] = (unsigned char) r->cc;
463         advance ();
464       }
465
466     for (i = 0; i < 256; i++)
467       trans_temp[i] = -1;
468
469     /* 0 is used to mark untranslatable characters, so we have to mark
470        it specially. */
471     trans_temp[src[64]] = 64;
472     for (i = 0; i < 256; i++)
473       if (trans_temp[src[i]] == -1)
474         trans_temp[src[i]] = i;
475     
476     r->trans = xmalloc (256);
477     for (i = 0; i < 256; i++)
478       r->trans[i] = trans_temp[i] == -1 ? 0 : trans_temp[i];
479
480     /* Translate the input buffer. */
481     for (i = 0; i < 80; i++)
482       r->buf[i] = r->trans[r->buf[i]];
483     r->cc = r->trans[r->cc];
484   }
485   
486   {
487     unsigned char sig[8] = {92, 89, 92, 92, 89, 88, 91, 93};
488     int i;
489
490     for (i = 0; i < 8; i++)
491       if (!match (sig[i]))
492         lose ((r, "Missing SPSSPORT signature."));
493   }
494
495   return 1;
496
497  error:
498   return 0;
499 }
500
501 /* Reads the version and date info record, as well as product and
502    subproduct identification records if present. */
503 int
504 read_version_data (struct pfm_reader *r, struct pfm_read_info *info)
505 {
506   /* Version. */
507   if (!match (74 /* A */))
508     lose ((r, "Unrecognized version code %d.", r->cc));
509
510   /* Date. */
511   {
512     static const int map[] = {6, 7, 8, 9, 3, 4, 0, 1};
513     char *date = read_string (r);
514     int i;
515     
516     if (!date)
517       return 0;
518     if (strlen (date) != 8)
519       lose ((r, _("Bad date string length %d."), strlen (date)));
520     for (i = 0; i < 8; i++)
521       {
522         if (date[i] < 64 /* 0 */ || date[i] > 73 /* 9 */)
523           lose ((r, _("Bad character in date.")));
524         if (info)
525           info->creation_date[map[i]] = date[i] - 64 /* 0 */ + '0';
526       }
527     if (info)
528       {
529         info->creation_date[2] = info->creation_date[5] = ' ';
530         info->creation_date[10] = 0;
531       }
532   }
533   
534   /* Time. */
535   {
536     static const int map[] = {0, 1, 3, 4, 6, 7};
537     char *time = read_string (r);
538     int i;
539
540     if (!time)
541       return 0;
542     if (strlen (time) != 6)
543       lose ((r, _("Bad time string length %d."), strlen (time)));
544     for (i = 0; i < 6; i++)
545       {
546         if (time[i] < 64 /* 0 */ || time[i] > 73 /* 9 */)
547           lose ((r, _("Bad character in time.")));
548         if (info)
549           info->creation_time[map[i]] = time[i] - 64 /* 0 */ + '0';
550       }
551     if (info)
552       {
553         info->creation_time[2] = info->creation_time[5] = ' ';
554         info->creation_time[8] = 0;
555       }
556   }
557
558   /* Product. */
559   if (match (65 /* 1 */))
560     {
561       char *product;
562       
563       product = read_string (r);
564       if (product == NULL)
565         return 0;
566       if (info)
567         strncpy (info->product, product, 61);
568     }
569   else if (info)
570     info->product[0] = 0;
571
572   /* Subproduct. */
573   if (match (67 /* 3 */))
574     {
575       char *subproduct;
576
577       subproduct = read_string (r);
578       if (subproduct == NULL)
579         return 0;
580       if (info)
581         strncpy (info->subproduct, subproduct, 61);
582     }
583   else if (info)
584     info->subproduct[0] = 0;
585   return 1;
586   
587  error:
588   return 0;
589 }
590
591 static int
592 convert_format (struct pfm_reader *r, int fmt[3], struct fmt_spec *v,
593                 struct variable *vv)
594 {
595   v->type = translate_fmt (fmt[0]);
596   if (v->type == -1)
597     lose ((r, _("%s: Bad format specifier byte (%d)."), vv->name, fmt[0]));
598   v->w = fmt[1];
599   v->d = fmt[2];
600
601   /* FIXME?  Should verify the resulting specifier more thoroughly. */
602
603   if (v->type == -1)
604     lose ((r, _("%s: Bad format specifier byte (%d)."), vv->name, fmt[0]));
605   if ((vv->type == ALPHA) ^ ((formats[v->type].cat & FCAT_STRING) != 0))
606     lose ((r, _("%s variable %s has %s format specifier %s."),
607            vv->type == ALPHA ? _("String") : _("Numeric"),
608            vv->name,
609            formats[v->type].cat & FCAT_STRING ? _("string") : _("numeric"),
610            formats[v->type].name));
611   return 1;
612
613  error:
614   return 0;
615 }
616
617 /* Translation table from SPSS character code to this computer's
618    native character code (which is probably ASCII). */
619 static const unsigned char spss2ascii[256] =
620   {
621     "                                                                "
622     "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ."
623     "<(+|&[]!$*);^-/|,%_>?`:$@'=\"      ~-   0123456789   -() {}\\     "
624     "                                                                "
625   };
626
627 /* Translate string S into ASCII. */
628 static void
629 asciify (char *s)
630 {
631   for (; *s; s++)
632     *s = spss2ascii[(unsigned char) *s];
633 }
634
635 static int parse_value (struct pfm_reader *, union value *, struct variable *);
636
637 /* Read information on all the variables.  */
638 static int
639 read_variables (struct pfm_reader *r, struct dictionary *dict)
640 {
641   char *weight_name = NULL;
642   int i;
643   
644   if (!match (68 /* 4 */))
645     lose ((r, _("Expected variable count record.")));
646   
647   r->var_cnt = read_int (r);
648   if (r->var_cnt <= 0 || r->var_cnt == NOT_INT)
649     lose ((r, _("Invalid number of variables %d."), r->var_cnt));
650   r->widths = xmalloc (sizeof *r->widths * r->var_cnt);
651
652   /* Purpose of this value is unknown.  It is typically 161. */
653   {
654     int x = read_int (r);
655
656     if (x == NOT_INT)
657       goto error;
658     if (x != 161)
659       corrupt_msg (r, _("Unexpected flag value %d."), x);
660   }
661
662   if (match (70 /* 6 */))
663     {
664       weight_name = read_string (r);
665       if (!weight_name)
666         goto error;
667
668       asciify (weight_name);
669       if (strlen (weight_name) > 8) 
670         {
671           corrupt_msg (r, _("Weight variable name (%s) truncated."),
672                        weight_name);
673           weight_name[8] = '\0';
674         }
675     }
676   
677   for (i = 0; i < r->var_cnt; i++)
678     {
679       int width;
680       unsigned char *name;
681       int fmt[6];
682       struct variable *v;
683       int j;
684
685       if (!match (71 /* 7 */))
686         lose ((r, _("Expected variable record.")));
687
688       width = read_int (r);
689       if (width == NOT_INT)
690         goto error;
691       if (width < 0)
692         lose ((r, _("Invalid variable width %d."), width));
693       r->widths[i] = width;
694       
695       name = read_string (r);
696       if (name == NULL)
697         goto error;
698       for (j = 0; j < 6; j++)
699         {
700           fmt[j] = read_int (r);
701           if (fmt[j] == NOT_INT)
702             goto error;
703         }
704
705       /* Verify first character of variable name.
706
707          Weirdly enough, there is no # character in the SPSS portable
708          character set, so we can't check for it. */
709       if (strlen (name) > 8)
710         lose ((r, _("position %d: Variable name has %u characters."),
711                i, strlen (name)));
712       if ((name[0] < 74 /* A */ || name[0] > 125 /* Z */)
713           && name[0] != 152 /* @ */)
714         lose ((r, _("position %d: Variable name begins with invalid "
715                "character."), i));
716       if (name[0] >= 100 /* a */ && name[0] <= 125 /* z */)
717         {
718           corrupt_msg (r, _("position %d: Variable name begins with "
719                             "lowercase letter %c."),
720                        i, name[0] - 100 + 'a');
721           name[0] -= 26 /* a - A */;
722         }
723
724       /* Verify remaining characters of variable name. */
725       for (j = 1; j < (int) strlen (name); j++)
726         {
727           int c = name[j];
728
729           if (c >= 100 /* a */ && c <= 125 /* z */)
730             {
731               corrupt_msg (r, _("position %d: Variable name character %d "
732                                 "is lowercase letter %c."),
733                            i, j + 1, c - 100 + 'a');
734               name[j] -= 26 /* z - Z */;
735             }
736           else if ((c >= 64 /* 0 */ && c <= 99 /* Z */)
737                    || c == 127 /* . */ || c == 152 /* @ */
738                    || c == 136 /* $ */ || c == 146 /* _ */)
739             name[j] = c;
740           else
741             lose ((r, _("position %d: character `\\%03o' is not "
742                         "valid in a variable name."), i, c));
743         }
744
745       asciify (name);
746       if (width < 0 || width > 255)
747         lose ((r, "Bad width %d for variable %s.", width, name));
748
749       v = dict_create_var (dict, name, width);
750       if (v == NULL)
751         lose ((r, _("Duplicate variable name %s."), name));
752       if (!convert_format (r, &fmt[0], &v->print, v))
753         goto error;
754       if (!convert_format (r, &fmt[3], &v->write, v))
755         goto error;
756
757       /* Range missing values. */
758       if (match (75 /* B */))
759         {
760           v->miss_type = MISSING_RANGE;
761           if (!parse_value (r, &v->missing[0], v)
762               || !parse_value (r, &v->missing[1], v))
763             goto error;
764         }
765       else if (match (74 /* A */))
766         {
767           v->miss_type = MISSING_HIGH;
768           if (!parse_value (r, &v->missing[0], v))
769             goto error;
770         }
771       else if (match (73 /* 9 */))
772         {
773           v->miss_type = MISSING_LOW;
774           if (!parse_value (r, &v->missing[0], v))
775             goto error;
776         }
777
778       /* Single missing values. */
779       while (match (72 /* 8 */))
780         {
781           static const int map_next[MISSING_COUNT] =
782             {
783               MISSING_1, MISSING_2, MISSING_3, -1,
784               MISSING_RANGE_1, MISSING_LOW_1, MISSING_HIGH_1,
785               -1, -1, -1,
786             };
787
788           static const int map_ofs[MISSING_COUNT] = 
789             {
790               -1, 0, 1, 2, -1, -1, -1, 2, 1, 1,
791             };
792
793           v->miss_type = map_next[v->miss_type];
794           if (v->miss_type == -1)
795             lose ((r, _("Bad missing values for %s."), v->name));
796           
797           assert (map_ofs[v->miss_type] != -1);
798           if (!parse_value (r, &v->missing[map_ofs[v->miss_type]], v))
799             goto error;
800         }
801
802       if (match (76 /* C */))
803         {
804           char *label = read_string (r);
805           
806           if (label == NULL)
807             goto error;
808
809           v->label = xstrdup (label);
810           asciify (v->label);
811         }
812     }
813
814   if (weight_name != NULL) 
815     {
816       struct variable *weight_var = dict_lookup_var (dict, weight_name);
817       if (weight_var == NULL)
818         lose ((r, _("Weighting variable %s not present in dictionary."),
819                weight_name));
820       free (weight_name);
821
822       dict_set_weight (dict, weight_var);
823     }
824
825   return 1;
826
827  error:
828   free (weight_name);
829   return 0;
830 }
831
832 /* Parse a value for variable VV into value V.  Returns success. */
833 static int
834 parse_value (struct pfm_reader *r, union value *v, struct variable *vv)
835 {
836   if (vv->type == ALPHA)
837     {
838       char *mv = read_string (r);
839       int j;
840       
841       if (mv == NULL)
842         return 0;
843
844       strncpy (v->s, mv, 8);
845       for (j = 0; j < 8; j++)
846         if (v->s[j])
847           v->s[j] = spss2ascii[v->s[j]];
848         else
849           /* Value labels are always padded with spaces. */
850           v->s[j] = ' ';
851     }
852   else
853     {
854       v->f = read_float (r);
855       if (v->f == second_lowest_value)
856         return 0;
857     }
858
859   return 1;
860 }
861
862 /* Parse a value label record and return success. */
863 static int
864 read_value_label (struct pfm_reader *r, struct dictionary *dict)
865 {
866   /* Variables. */
867   int nv;
868   struct variable **v;
869
870   /* Labels. */
871   int n_labels;
872
873   int i;
874
875   nv = read_int (r);
876   if (nv == NOT_INT)
877     return 0;
878
879   v = xmalloc (sizeof *v * nv);
880   for (i = 0; i < nv; i++)
881     {
882       char *name = read_string (r);
883       if (name == NULL)
884         goto error;
885       asciify (name);
886
887       v[i] = dict_lookup_var (dict, name);
888       if (v[i] == NULL)
889         lose ((r, _("Unknown variable %s while parsing value labels."), name));
890
891       if (v[0]->width != v[i]->width)
892         lose ((r, _("Cannot assign value labels to %s and %s, which "
893                     "have different variable types or widths."),
894                v[0]->name, v[i]->name));
895     }
896
897   n_labels = read_int (r);
898   if (n_labels == NOT_INT)
899     goto error;
900
901   for (i = 0; i < n_labels; i++)
902     {
903       union value val;
904       char *label;
905
906       int j;
907       
908       if (!parse_value (r, &val, v[0]))
909         goto error;
910       
911       label = read_string (r);
912       if (label == NULL)
913         goto error;
914       asciify (label);
915
916       /* Assign the value_label's to each variable. */
917       for (j = 0; j < nv; j++)
918         {
919           struct variable *var = v[j];
920
921           if (!val_labs_replace (var->val_labs, val, label))
922             continue;
923
924           if (var->type == NUMERIC)
925             lose ((r, _("Duplicate label for value %g for variable %s."),
926                    val.f, var->name));
927           else
928             lose ((r, _("Duplicate label for value `%.*s' for variable %s."),
929                    var->width, val.s, var->name));
930         }
931     }
932   free (v);
933   return 1;
934
935  error:
936   free (v);
937   return 0;
938 }
939
940 /* Reads one case from portable file R into C.  Returns nonzero
941    only if successful. */
942 int
943 pfm_read_case (struct pfm_reader *r, struct ccase *c)
944 {
945   size_t i;
946   size_t idx;
947
948   /* Check for end of file. */
949   if (r->cc == 99 /* Z */)
950     return 0;
951   
952   idx = 0;
953   for (i = 0; i < r->var_cnt; i++) 
954     {
955       int width = r->widths[i];
956       
957       if (width == 0)
958         {
959           double f = read_float (r);
960           if (f == second_lowest_value)
961             goto unexpected_eof;
962
963           case_data_rw (c, idx)->f = f;
964           idx++;
965         }
966       else
967         {
968           char *s = read_string (r);
969           if (s == NULL)
970             goto unexpected_eof;
971           asciify (s);
972
973           st_bare_pad_copy (case_data_rw (c, idx)->s, s, width);
974           idx += DIV_RND_UP (width, MAX_SHORT_STRING);
975         }
976     }
977   
978   return 1;
979
980  unexpected_eof:
981   lose ((r, _("End of file midway through case.")));
982
983  error:
984   return 0;
985 }