Instead of making system or portable file readers responsible for
[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 /* 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       v->aux = xmalloc (sizeof (int));
746       *(int *) v->aux = v->fv;
747       if (v == NULL)
748         lose ((r, _("Duplicate variable name %s."), name));
749       if (!convert_format (r, &fmt[0], &v->print, v))
750         goto error;
751       if (!convert_format (r, &fmt[3], &v->write, v))
752         goto error;
753
754       /* Range missing values. */
755       if (match (75 /* B */))
756         {
757           v->miss_type = MISSING_RANGE;
758           if (!parse_value (r, &v->missing[0], v)
759               || !parse_value (r, &v->missing[1], v))
760             goto error;
761         }
762       else if (match (74 /* A */))
763         {
764           v->miss_type = MISSING_HIGH;
765           if (!parse_value (r, &v->missing[0], v))
766             goto error;
767         }
768       else if (match (73 /* 9 */))
769         {
770           v->miss_type = MISSING_LOW;
771           if (!parse_value (r, &v->missing[0], v))
772             goto error;
773         }
774
775       /* Single missing values. */
776       while (match (72 /* 8 */))
777         {
778           static const int map_next[MISSING_COUNT] =
779             {
780               MISSING_1, MISSING_2, MISSING_3, -1,
781               MISSING_RANGE_1, MISSING_LOW_1, MISSING_HIGH_1,
782               -1, -1, -1,
783             };
784
785           static const int map_ofs[MISSING_COUNT] = 
786             {
787               -1, 0, 1, 2, -1, -1, -1, 2, 1, 1,
788             };
789
790           v->miss_type = map_next[v->miss_type];
791           if (v->miss_type == -1)
792             lose ((r, _("Bad missing values for %s."), v->name));
793           
794           assert (map_ofs[v->miss_type] != -1);
795           if (!parse_value (r, &v->missing[map_ofs[v->miss_type]], v))
796             goto error;
797         }
798
799       if (match (76 /* C */))
800         {
801           char *label = read_string (r);
802           
803           if (label == NULL)
804             goto error;
805
806           v->label = xstrdup (label);
807           asciify (v->label);
808         }
809     }
810
811   if (weight_name != NULL) 
812     {
813       struct variable *weight_var = dict_lookup_var (dict, weight_name);
814       if (weight_var == NULL)
815         lose ((r, _("Weighting variable %s not present in dictionary."),
816                weight_name));
817       free (weight_name);
818
819       dict_set_weight (dict, weight_var);
820     }
821
822   return 1;
823
824  error:
825   free (weight_name);
826   return 0;
827 }
828
829 /* Parse a value for variable VV into value V.  Returns success. */
830 static int
831 parse_value (struct pfm_reader *r, union value *v, struct variable *vv)
832 {
833   if (vv->type == ALPHA)
834     {
835       char *mv = read_string (r);
836       int j;
837       
838       if (mv == NULL)
839         return 0;
840
841       strncpy (v->s, mv, 8);
842       for (j = 0; j < 8; j++)
843         if (v->s[j])
844           v->s[j] = spss2ascii[v->s[j]];
845         else
846           /* Value labels are always padded with spaces. */
847           v->s[j] = ' ';
848     }
849   else
850     {
851       v->f = read_float (r);
852       if (v->f == second_lowest_value)
853         return 0;
854     }
855
856   return 1;
857 }
858
859 /* Parse a value label record and return success. */
860 static int
861 read_value_label (struct pfm_reader *r, struct dictionary *dict)
862 {
863   /* Variables. */
864   int nv;
865   struct variable **v;
866
867   /* Labels. */
868   int n_labels;
869
870   int i;
871
872   nv = read_int (r);
873   if (nv == NOT_INT)
874     return 0;
875
876   v = xmalloc (sizeof *v * nv);
877   for (i = 0; i < nv; i++)
878     {
879       char *name = read_string (r);
880       if (name == NULL)
881         goto error;
882       asciify (name);
883
884       v[i] = dict_lookup_var (dict, name);
885       if (v[i] == NULL)
886         lose ((r, _("Unknown variable %s while parsing value labels."), name));
887
888       if (v[0]->width != v[i]->width)
889         lose ((r, _("Cannot assign value labels to %s and %s, which "
890                     "have different variable types or widths."),
891                v[0]->name, v[i]->name));
892     }
893
894   n_labels = read_int (r);
895   if (n_labels == NOT_INT)
896     goto error;
897
898   for (i = 0; i < n_labels; i++)
899     {
900       union value val;
901       char *label;
902
903       int j;
904       
905       if (!parse_value (r, &val, v[0]))
906         goto error;
907       
908       label = read_string (r);
909       if (label == NULL)
910         goto error;
911       asciify (label);
912
913       /* Assign the value_label's to each variable. */
914       for (j = 0; j < nv; j++)
915         {
916           struct variable *var = v[j];
917
918           if (!val_labs_replace (var->val_labs, val, label))
919             continue;
920
921           if (var->type == NUMERIC)
922             lose ((r, _("Duplicate label for value %g for variable %s."),
923                    val.f, var->name));
924           else
925             lose ((r, _("Duplicate label for value `%.*s' for variable %s."),
926                    var->width, val.s, var->name));
927         }
928     }
929   free (v);
930   return 1;
931
932  error:
933   free (v);
934   return 0;
935 }
936
937 /* Reads one case from portable file R into C.  Returns nonzero
938    only if successful. */
939 int
940 pfm_read_case (struct pfm_reader *r, struct ccase *c)
941 {
942   size_t i;
943   size_t idx;
944
945   /* Check for end of file. */
946   if (r->cc == 99 /* Z */)
947     return 0;
948   
949   idx = 0;
950   for (i = 0; i < r->var_cnt; i++) 
951     {
952       int width = r->widths[i];
953       
954       if (width == 0)
955         {
956           double f = read_float (r);
957           if (f == second_lowest_value)
958             goto unexpected_eof;
959
960           case_data_rw (c, idx)->f = f;
961           idx++;
962         }
963       else
964         {
965           char *s = read_string (r);
966           if (s == NULL)
967             goto unexpected_eof;
968           asciify (s);
969
970           st_bare_pad_copy (case_data_rw (c, idx)->s, s, width);
971           idx += DIV_RND_UP (width, MAX_SHORT_STRING);
972         }
973     }
974   
975   return 1;
976
977  unexpected_eof:
978   lose ((r, _("End of file midway through case.")));
979
980  error:
981   return 0;
982 }