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