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