1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 1997-9, 2000, 2006, 2007, 2009 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19 #include <data/sys-file-reader.h>
20 #include <data/sys-file-private.h>
28 #include <libpspp/assertion.h>
29 #include <libpspp/message.h>
30 #include <libpspp/compiler.h>
31 #include <libpspp/misc.h>
32 #include <libpspp/pool.h>
33 #include <libpspp/str.h>
34 #include <libpspp/hash.h>
35 #include <libpspp/array.h>
37 #include <data/attributes.h>
38 #include <data/case.h>
39 #include <data/casereader-provider.h>
40 #include <data/casereader.h>
41 #include <data/dictionary.h>
42 #include <data/file-handle-def.h>
43 #include <data/file-name.h>
44 #include <data/format.h>
45 #include <data/missing-values.h>
46 #include <data/short-names.h>
47 #include <data/value-labels.h>
48 #include <data/variable.h>
49 #include <data/value.h>
54 #include "unlocked-io.h"
59 #define _(msgid) gettext (msgid)
60 #define N_(msgid) (msgid)
62 /* System file reader. */
65 /* Resource tracking. */
66 struct pool *pool; /* All system file state. */
67 jmp_buf bail_out; /* longjmp() target for error handling. */
70 struct file_handle *fh; /* File handle. */
71 struct fh_lock *lock; /* Mutual exclusion for file handle. */
72 FILE *file; /* File stream. */
73 bool error; /* I/O or corruption error? */
74 size_t value_cnt; /* Number of "union value"s in struct case. */
77 enum integer_format integer_format; /* On-disk integer format. */
78 enum float_format float_format; /* On-disk floating point format. */
79 int oct_cnt; /* Number of 8-byte units per case. */
80 struct sfm_var *sfm_vars; /* Variables. */
81 size_t sfm_var_cnt; /* Number of variables. */
82 casenumber case_cnt; /* Number of cases */
83 bool has_long_var_names; /* File has a long variable name map */
86 bool compressed; /* File is compressed? */
87 double bias; /* Compression bias, usually 100.0. */
88 uint8_t opcodes[8]; /* Current block of opcodes. */
89 size_t opcode_idx; /* Next opcode to interpret, 8 if none left. */
92 static const struct casereader_class sys_file_casereader_class;
94 static bool close_reader (struct sfm_reader *);
96 static struct variable **make_var_by_value_idx (struct sfm_reader *,
98 static struct variable *lookup_var_by_value_idx (struct sfm_reader *,
102 static void sys_msg (struct sfm_reader *r, int class,
103 const char *format, va_list args)
104 PRINTF_FORMAT (3, 0);
105 static void sys_warn (struct sfm_reader *, const char *, ...)
106 PRINTF_FORMAT (2, 3);
107 static void sys_error (struct sfm_reader *, const char *, ...)
111 static void read_bytes (struct sfm_reader *, void *, size_t);
112 static bool try_read_bytes (struct sfm_reader *, void *, size_t);
113 static int read_int (struct sfm_reader *);
114 static double read_float (struct sfm_reader *);
115 static void read_string (struct sfm_reader *, char *, size_t);
116 static void skip_bytes (struct sfm_reader *, size_t);
118 static struct text_record *open_text_record (struct sfm_reader *, size_t size);
119 static void close_text_record (struct sfm_reader *r,
120 struct text_record *);
121 static bool read_variable_to_value_pair (struct sfm_reader *,
123 struct text_record *,
124 struct variable **var, char **value);
125 static void text_warn (struct sfm_reader *r, struct text_record *text,
126 const char *format, ...)
127 PRINTF_FORMAT (3, 4);
128 static char *text_get_token (struct text_record *,
129 struct substring delimiters);
130 static bool text_match (struct text_record *, char c);
131 static bool text_read_short_name (struct sfm_reader *, struct dictionary *,
132 struct text_record *,
133 struct substring delimiters,
136 static bool close_reader (struct sfm_reader *r);
138 /* Dictionary reader. */
146 static void read_header (struct sfm_reader *, struct dictionary *,
147 int *weight_idx, int *claimed_oct_cnt,
148 struct sfm_read_info *);
149 static void read_variable_record (struct sfm_reader *, struct dictionary *,
150 int *format_warning_cnt);
151 static void parse_format_spec (struct sfm_reader *, unsigned int,
152 enum which_format, struct variable *,
153 int *format_warning_cnt);
154 static void setup_weight (struct sfm_reader *, int weight_idx,
155 struct variable **var_by_value_idx,
156 struct dictionary *);
157 static void read_documents (struct sfm_reader *, struct dictionary *);
158 static void read_value_labels (struct sfm_reader *, struct dictionary *,
159 struct variable **var_by_value_idx);
161 static void read_extension_record (struct sfm_reader *, struct dictionary *,
162 struct sfm_read_info *);
163 static void read_machine_integer_info (struct sfm_reader *,
164 size_t size, size_t count,
165 struct sfm_read_info *);
166 static void read_machine_float_info (struct sfm_reader *,
167 size_t size, size_t count);
168 static void read_display_parameters (struct sfm_reader *,
169 size_t size, size_t count,
170 struct dictionary *);
171 static void read_long_var_name_map (struct sfm_reader *,
172 size_t size, size_t count,
173 struct dictionary *);
174 static void read_long_string_map (struct sfm_reader *,
175 size_t size, size_t count,
176 struct dictionary *);
177 static void read_data_file_attributes (struct sfm_reader *,
178 size_t size, size_t count,
179 struct dictionary *);
180 static void read_variable_attributes (struct sfm_reader *,
181 size_t size, size_t count,
182 struct dictionary *);
184 /* Opens the system file designated by file handle FH for
185 reading. Reads the system file's dictionary into *DICT.
186 If INFO is non-null, then it receives additional info about the
189 sfm_open_reader (struct file_handle *fh, struct dictionary **dict,
190 struct sfm_read_info *volatile info)
192 struct sfm_reader *volatile r = NULL;
193 struct variable **var_by_value_idx;
194 struct sfm_read_info local_info;
195 int format_warning_cnt = 0;
200 *dict = dict_create ();
202 /* Create and initialize reader. */
203 r = pool_create_container (struct sfm_reader, pool);
209 r->has_long_var_names = false;
210 r->opcode_idx = sizeof r->opcodes;
212 /* TRANSLATORS: this fragment will be interpolated into
213 messages in fh_lock() that identify types of files. */
214 r->lock = fh_lock (fh, FH_REF_FILE, N_("system file"), FH_ACC_READ, false);
218 r->file = fn_open (fh_get_file_name (fh), "rb");
221 msg (ME, _("Error opening \"%s\" for reading as a system file: %s."),
222 fh_get_file_name (r->fh), strerror (errno));
226 /* Initialize info. */
229 memset (info, 0, sizeof *info);
231 if (setjmp (r->bail_out))
236 read_header (r, *dict, &weight_idx, &claimed_oct_cnt, info);
238 /* Read all the variable definition records. */
239 rec_type = read_int (r);
240 while (rec_type == 2)
242 read_variable_record (r, *dict, &format_warning_cnt);
243 rec_type = read_int (r);
246 /* Figure out the case format. */
247 var_by_value_idx = make_var_by_value_idx (r, *dict);
248 setup_weight (r, weight_idx, var_by_value_idx, *dict);
250 /* Read all the rest of the dictionary records. */
251 while (rec_type != 999)
256 read_value_labels (r, *dict, var_by_value_idx);
260 sys_error (r, _("Misplaced type 4 record."));
263 read_documents (r, *dict);
267 read_extension_record (r, *dict, info);
271 sys_error (r, _("Unrecognized record type %d."), rec_type);
273 rec_type = read_int (r);
277 if ( ! r->has_long_var_names )
280 for (i = 0; i < dict_get_var_cnt (*dict); i++)
282 struct variable *var = dict_get_var (*dict, i);
283 char short_name[SHORT_NAME_LEN + 1];
284 char long_name[SHORT_NAME_LEN + 1];
286 strcpy (short_name, var_get_name (var));
288 strcpy (long_name, short_name);
289 str_lowercase (long_name);
291 /* Set long name. Renaming a variable may clear the short
292 name, but we want to retain it, so re-set it
294 dict_rename_var (*dict, var, long_name);
295 var_set_short_name (var, 0, short_name);
298 r->has_long_var_names = true;
301 /* Read record 999 data, which is just filler. */
304 /* Warn if the actual amount of data per case differs from the
305 amount that the header claims. SPSS version 13 gets this
306 wrong when very long strings are involved, so don't warn in
308 if (claimed_oct_cnt != -1 && claimed_oct_cnt != r->oct_cnt
309 && info->version_major != 13)
310 sys_warn (r, _("File header claims %d variable positions but "
311 "%d were read from file."),
312 claimed_oct_cnt, r->oct_cnt);
314 /* Create an index of dictionary variable widths for
315 sfm_read_case to use. We cannot use the `struct variable's
316 from the dictionary we created, because the caller owns the
317 dictionary and may destroy or modify its variables. */
318 sfm_dictionary_to_sfm_vars (*dict, &r->sfm_vars, &r->sfm_var_cnt);
319 pool_register (r->pool, free, r->sfm_vars);
321 pool_free (r->pool, var_by_value_idx);
322 r->value_cnt = dict_get_next_value_idx (*dict);
323 return casereader_create_sequential
325 r->case_cnt == -1 ? CASENUMBER_MAX: r->case_cnt,
326 &sys_file_casereader_class, r);
330 dict_destroy (*dict);
335 /* Closes a system file after we're done with it.
336 Returns true if an I/O error has occurred on READER, false
339 close_reader (struct sfm_reader *r)
348 if (fn_close (fh_get_file_name (r->fh), r->file) == EOF)
350 msg (ME, _("Error closing system file \"%s\": %s."),
351 fh_get_file_name (r->fh), strerror (errno));
361 pool_destroy (r->pool);
366 /* Destroys READER. */
368 sys_file_casereader_destroy (struct casereader *reader UNUSED, void *r_)
370 struct sfm_reader *r = r_;
374 /* Returns true if FILE is an SPSS system file,
377 sfm_detect (FILE *file)
381 if (fread (rec_type, 4, 1, file) != 1)
385 return !strcmp ("$FL2", rec_type);
388 /* Reads the global header of the system file.
389 Sets DICT's file label to the system file's label.
390 Sets *WEIGHT_IDX to 0 if the system file is unweighted,
391 or to the value index of the weight variable otherwise.
392 Sets *CLAIMED_OCT_CNT to the number of "octs" (8-byte units)
393 per case that the file claims to have (although it is not
395 Initializes INFO with header information. */
397 read_header (struct sfm_reader *r, struct dictionary *dict,
398 int *weight_idx, int *claimed_oct_cnt,
399 struct sfm_read_info *info)
402 char eye_catcher[61];
403 uint8_t raw_layout_code[4];
405 char creation_date[10];
406 char creation_time[9];
408 struct substring file_label_ss;
409 struct substring product;
411 read_string (r, rec_type, sizeof rec_type);
412 read_string (r, eye_catcher, sizeof eye_catcher);
414 if (strcmp ("$FL2", rec_type) != 0)
415 sys_error (r, _("This is not an SPSS system file."));
417 /* Identify integer format. */
418 read_bytes (r, raw_layout_code, sizeof raw_layout_code);
419 if ((!integer_identify (2, raw_layout_code, sizeof raw_layout_code,
421 && !integer_identify (3, raw_layout_code, sizeof raw_layout_code,
423 || (r->integer_format != INTEGER_MSB_FIRST
424 && r->integer_format != INTEGER_LSB_FIRST))
425 sys_error (r, _("This is not an SPSS system file."));
427 *claimed_oct_cnt = read_int (r);
428 if (*claimed_oct_cnt < 0 || *claimed_oct_cnt > INT_MAX / 16)
429 *claimed_oct_cnt = -1;
431 r->compressed = read_int (r) != 0;
433 *weight_idx = read_int (r);
435 r->case_cnt = read_int (r);
436 if ( r->case_cnt > INT_MAX / 2)
440 /* Identify floating-point format and obtain compression bias. */
441 read_bytes (r, raw_bias, sizeof raw_bias);
442 if (float_identify (100.0, raw_bias, sizeof raw_bias, &r->float_format) == 0)
444 sys_warn (r, _("Compression bias is not the usual "
445 "value of 100, or system file uses unrecognized "
446 "floating-point format."));
447 if (r->integer_format == INTEGER_MSB_FIRST)
448 r->float_format = FLOAT_IEEE_DOUBLE_BE;
450 r->float_format = FLOAT_IEEE_DOUBLE_LE;
452 float_convert (r->float_format, raw_bias, FLOAT_NATIVE_DOUBLE, &r->bias);
454 read_string (r, creation_date, sizeof creation_date);
455 read_string (r, creation_time, sizeof creation_time);
456 read_string (r, file_label, sizeof file_label);
459 file_label_ss = ss_cstr (file_label);
460 ss_trim (&file_label_ss, ss_cstr (" "));
461 if (!ss_is_empty (file_label_ss))
463 ss_data (file_label_ss)[ss_length (file_label_ss)] = '\0';
464 dict_set_label (dict, ss_data (file_label_ss));
467 strcpy (info->creation_date, creation_date);
468 strcpy (info->creation_time, creation_time);
469 info->integer_format = r->integer_format;
470 info->float_format = r->float_format;
471 info->compressed = r->compressed;
472 info->case_cnt = r->case_cnt;
474 product = ss_cstr (eye_catcher);
475 ss_match_string (&product, ss_cstr ("@(#) SPSS DATA FILE"));
476 ss_trim (&product, ss_cstr (" "));
477 str_copy_buf_trunc (info->product, sizeof info->product,
478 ss_data (product), ss_length (product));
481 /* Reads a variable (type 2) record from R and adds the
482 corresponding variable to DICT.
483 Also skips past additional variable records for long string
486 read_variable_record (struct sfm_reader *r, struct dictionary *dict,
487 int *format_warning_cnt)
490 int has_variable_label;
491 int missing_value_code;
496 struct variable *var;
499 width = read_int (r);
500 has_variable_label = read_int (r);
501 missing_value_code = read_int (r);
502 print_format = read_int (r);
503 write_format = read_int (r);
504 read_string (r, name, sizeof name);
505 name[strcspn (name, " ")] = '\0';
507 /* Check variable name. */
508 if (name[0] == '$' || name[0] == '#')
509 sys_error (r, "Variable name begins with invalid character `%c'.",
511 if (!var_is_plausible_name (name, false))
512 sys_error (r, _("Invalid variable name `%s'."), name);
514 /* Create variable. */
515 if (width < 0 || width > 255)
516 sys_error (r, _("Bad variable width %d."), width);
517 var = dict_create_var (dict, name, width);
520 _("Duplicate variable name `%s' within system file."),
523 /* Set the short name the same as the long name. */
524 var_set_short_name (var, 0, var_get_name (var));
526 /* Get variable label, if any. */
527 if (has_variable_label != 0 && has_variable_label != 1)
528 sys_error (r, _("Variable label indicator field is not 0 or 1."));
529 if (has_variable_label == 1)
535 if (len >= sizeof label)
536 sys_error (r, _("Variable %s has label of invalid length %zu."),
538 read_string (r, label, len + 1);
539 var_set_label (var, label);
541 skip_bytes (r, ROUND_UP (len, 4) - len);
544 /* Set missing values. */
545 if (missing_value_code != 0)
547 struct missing_values mv;
550 mv_init (&mv, var_get_width (var));
551 if (var_is_numeric (var))
553 if (missing_value_code < -3 || missing_value_code > 3
554 || missing_value_code == -1)
555 sys_error (r, _("Numeric missing value indicator field is not "
556 "-3, -2, 0, 1, 2, or 3."));
557 if (missing_value_code < 0)
559 double low = read_float (r);
560 double high = read_float (r);
561 mv_add_range (&mv, low, high);
562 missing_value_code = -missing_value_code - 2;
564 for (i = 0; i < missing_value_code; i++)
565 mv_add_num (&mv, read_float (r));
569 if (missing_value_code < 1 || missing_value_code > 3)
570 sys_error (r, _("String missing value indicator field is not "
572 if (var_is_long_string (var))
573 sys_warn (r, _("Ignoring missing values on long string variable "
574 "%s, which PSPP does not yet support."), name);
575 for (i = 0; i < missing_value_code; i++)
578 read_string (r, string, sizeof string);
579 mv_add_str (&mv, string);
582 if (!var_is_long_string (var))
583 var_set_missing_values (var, &mv);
587 parse_format_spec (r, print_format, PRINT_FORMAT, var, format_warning_cnt);
588 parse_format_spec (r, write_format, WRITE_FORMAT, var, format_warning_cnt);
590 /* Account for values.
591 Skip long string continuation records, if any. */
592 nv = width == 0 ? 1 : DIV_RND_UP (width, 8);
598 for (i = 1; i < nv; i++)
600 /* Check for record type 2 and width -1. */
601 if (read_int (r) != 2 || read_int (r) != -1)
602 sys_error (r, _("Missing string continuation record."));
604 /* Skip and ignore remaining continuation data. */
605 has_variable_label = read_int (r);
606 missing_value_code = read_int (r);
607 print_format = read_int (r);
608 write_format = read_int (r);
609 read_string (r, name, sizeof name);
611 /* Variable label fields on continuation records have
612 been spotted in system files created by "SPSS Power
613 Macintosh Release 6.1". */
614 if (has_variable_label)
615 skip_bytes (r, ROUND_UP (read_int (r), 4));
620 /* Translates the format spec from sysfile format to internal
623 parse_format_spec (struct sfm_reader *r, unsigned int s,
624 enum which_format which, struct variable *v,
625 int *format_warning_cnt)
627 const int max_format_warnings = 8;
629 uint8_t raw_type = s >> 16;
635 if (!fmt_from_io (raw_type, &f.type))
636 sys_error (r, _("Unknown variable format %"PRIu8"."), raw_type);
641 ok = fmt_check_output (&f) && fmt_check_width_compat (&f, var_get_width (v));
646 if (which == PRINT_FORMAT)
647 var_set_print_format (v, &f);
649 var_set_write_format (v, &f);
651 else if (*++format_warning_cnt <= max_format_warnings)
653 char fmt_string[FMT_STRING_LEN_MAX + 1];
654 sys_warn (r, _("%s variable %s has invalid %s format %s."),
655 var_is_numeric (v) ? _("Numeric") : _("String"),
657 which == PRINT_FORMAT ? _("print") : _("write"),
658 fmt_to_string (&f, fmt_string));
660 if (*format_warning_cnt == max_format_warnings)
661 sys_warn (r, _("Suppressing further invalid format warnings."));
665 /* Sets the weighting variable in DICT to the variable
666 corresponding to the given 1-based VALUE_IDX, if VALUE_IDX is
669 setup_weight (struct sfm_reader *r, int weight_idx,
670 struct variable **var_by_value_idx, struct dictionary *dict)
674 struct variable *weight_var
675 = lookup_var_by_value_idx (r, var_by_value_idx, weight_idx);
676 if (var_is_numeric (weight_var))
677 dict_set_weight (dict, weight_var);
679 sys_error (r, _("Weighting variable must be numeric."));
683 /* Reads a document record, type 6, from system file R, and sets up
684 the documents and n_documents fields in the associated
687 read_documents (struct sfm_reader *r, struct dictionary *dict)
692 if (dict_get_documents (dict) != NULL)
693 sys_error (r, _("Multiple type 6 (document) records."));
695 line_cnt = read_int (r);
697 sys_error (r, _("Number of document lines (%d) "
698 "must be greater than 0."), line_cnt);
700 documents = pool_nmalloc (r->pool, line_cnt + 1, DOC_LINE_LENGTH);
701 read_string (r, documents, DOC_LINE_LENGTH * line_cnt + 1);
702 if (strlen (documents) == DOC_LINE_LENGTH * line_cnt)
703 dict_set_documents (dict, documents);
705 sys_error (r, _("Document line contains null byte."));
706 pool_free (r->pool, documents);
709 /* Read a type 7 extension record. */
711 read_extension_record (struct sfm_reader *r, struct dictionary *dict,
712 struct sfm_read_info *info)
714 int subtype = read_int (r);
715 size_t size = read_int (r);
716 size_t count = read_int (r);
717 size_t bytes = size * count;
719 /* Check that SIZE * COUNT + 1 doesn't overflow. Adding 1
720 allows an extra byte for a null terminator, used by some
721 extension processing routines. */
722 if (size != 0 && size_overflow_p (xsum (1, xtimes (count, size))))
723 sys_error (r, "Record type 7 subtype %d too large.", subtype);
728 read_machine_integer_info (r, size, count, info);
732 read_machine_float_info (r, size, count);
736 /* Variable sets information. We don't use these yet.
737 They only apply to GUIs; see VARSETS on the APPLY
738 DICTIONARY command in SPSS documentation. */
742 /* DATE variable information. We don't use it yet, but we
747 /* Used by the MRSETS command. */
751 /* Used by the SPSS Data Entry software. */
755 read_display_parameters (r, size, count, dict);
759 read_long_var_name_map (r, size, count, dict);
763 read_long_string_map (r, size, count, dict);
767 /* New in SPSS v14? Unknown purpose. */
771 read_data_file_attributes (r, size, count, dict);
775 read_variable_attributes (r, size, count, dict);
779 /* New in SPSS 16. Contains a single string that describes
780 the character encoding, e.g. "windows-1252". */
782 char *encoding = calloc (size, count + 1);
783 read_string (r, encoding, count + 1);
784 dict_set_encoding (dict, encoding);
789 /* New in SPSS 16. Encodes value labels for long string
791 sys_warn (r, _("Ignoring value labels for long string variables, "
792 "which PSPP does not yet support."));
796 sys_warn (r, _("Unrecognized record type 7, subtype %d. Please send a copy of this file, and the syntax which created it to %s"),
797 subtype, PACKAGE_BUGREPORT);
801 skip_bytes (r, bytes);
804 /* Read record type 7, subtype 3. */
806 read_machine_integer_info (struct sfm_reader *r, size_t size, size_t count,
807 struct sfm_read_info *info)
809 int version_major = read_int (r);
810 int version_minor = read_int (r);
811 int version_revision = read_int (r);
812 int machine_code UNUSED = read_int (r);
813 int float_representation = read_int (r);
814 int compression_code UNUSED = read_int (r);
815 int integer_representation = read_int (r);
816 int character_code UNUSED = read_int (r);
818 int expected_float_format;
819 int expected_integer_format;
821 if (size != 4 || count != 8)
822 sys_error (r, _("Bad size (%zu) or count (%zu) field on record type 7, "
826 /* Save version info. */
827 info->version_major = version_major;
828 info->version_minor = version_minor;
829 info->version_revision = version_revision;
831 /* Check floating point format. */
832 if (r->float_format == FLOAT_IEEE_DOUBLE_BE
833 || r->float_format == FLOAT_IEEE_DOUBLE_LE)
834 expected_float_format = 1;
835 else if (r->float_format == FLOAT_Z_LONG)
836 expected_float_format = 2;
837 else if (r->float_format == FLOAT_VAX_G || r->float_format == FLOAT_VAX_D)
838 expected_float_format = 3;
841 if (float_representation != expected_float_format)
842 sys_error (r, _("Floating-point representation indicated by "
843 "system file (%d) differs from expected (%d)."),
844 r->float_format, expected_float_format);
846 /* Check integer format. */
847 if (r->integer_format == INTEGER_MSB_FIRST)
848 expected_integer_format = 1;
849 else if (r->integer_format == INTEGER_LSB_FIRST)
850 expected_integer_format = 2;
853 if (integer_representation != expected_integer_format)
855 static const char *const endian[] = {N_("little-endian"), N_("big-endian")};
856 sys_warn (r, _("Integer format indicated by system file (%s) "
857 "differs from expected (%s)."),
858 gettext (endian[integer_representation == 1]),
859 gettext (endian[expected_integer_format == 1]));
863 /* Read record type 7, subtype 4. */
865 read_machine_float_info (struct sfm_reader *r, size_t size, size_t count)
867 double sysmis = read_float (r);
868 double highest = read_float (r);
869 double lowest = read_float (r);
871 if (size != 8 || count != 3)
872 sys_error (r, _("Bad size (%zu) or count (%zu) on extension 4."),
875 if (sysmis != SYSMIS)
876 sys_warn (r, _("File specifies unexpected value %g as SYSMIS."), sysmis);
877 if (highest != HIGHEST)
878 sys_warn (r, _("File specifies unexpected value %g as HIGHEST."), highest);
879 if (lowest != LOWEST)
880 sys_warn (r, _("File specifies unexpected value %g as LOWEST."), lowest);
883 /* Read record type 7, subtype 11, which specifies how variables
884 should be displayed in GUI environments. */
886 read_display_parameters (struct sfm_reader *r, size_t size, size_t count,
887 struct dictionary *dict)
896 sys_warn (r, _("Bad size %zu on extension 11."), size);
897 skip_bytes (r, size * count);
901 n_vars = dict_get_var_cnt (dict);
902 if (count == 3 * n_vars)
903 includes_width = true;
904 else if (count == 2 * n_vars)
905 includes_width = false;
908 sys_warn (r, _("Extension 11 has bad count %zu (for %zu variables)."),
910 skip_bytes (r, size * count);
914 for (i = 0; i < n_vars; ++i)
916 struct variable *v = dict_get_var (dict, i);
917 int measure = read_int (r);
918 int width = includes_width ? read_int (r) : 0;
919 int align = read_int (r);
921 /* SPSS 14 sometimes seems to set string variables' measure
923 if (0 == measure && var_is_alpha (v))
926 if (measure < 1 || measure > 3 || align < 0 || align > 2)
929 sys_warn (r, _("Invalid variable display parameters "
930 "for variable %zu (%s). "
931 "Default parameters substituted."),
932 i, var_get_name (v));
937 var_set_measure (v, (measure == 1 ? MEASURE_NOMINAL
938 : measure == 2 ? MEASURE_ORDINAL
940 var_set_alignment (v, (align == 0 ? ALIGN_LEFT
941 : align == 1 ? ALIGN_RIGHT
944 /* Older versions (SPSS 9.0) sometimes set the display
945 width to zero. This causes confusion in the GUI, so
946 only set the width if it is nonzero. */
948 var_set_display_width (v, width);
952 /* Reads record type 7, subtype 13, which gives the long name
953 that corresponds to each short name. Modifies variable names
954 in DICT accordingly. */
956 read_long_var_name_map (struct sfm_reader *r, size_t size, size_t count,
957 struct dictionary *dict)
959 struct text_record *text;
960 struct variable *var;
963 text = open_text_record (r, size * count);
964 while (read_variable_to_value_pair (r, dict, text, &var, &long_name))
967 size_t short_name_cnt;
970 /* Validate long name. */
971 if (!var_is_valid_name (long_name, false))
973 sys_warn (r, _("Long variable mapping from %s to invalid "
974 "variable name `%s'."),
975 var_get_name (var), long_name);
979 /* Identify any duplicates. */
980 if (strcasecmp (var_get_short_name (var, 0), long_name)
981 && dict_lookup_var (dict, long_name) != NULL)
983 sys_warn (r, _("Duplicate long variable name `%s' "
984 "within system file."), long_name);
988 /* Renaming a variable may clear its short names, but we
989 want to retain them, so we save them and re-set them
991 short_name_cnt = var_get_short_name_cnt (var);
992 short_names = xnmalloc (short_name_cnt, sizeof *short_names);
993 for (i = 0; i < short_name_cnt; i++)
995 const char *s = var_get_short_name (var, i);
996 short_names[i] = s != NULL ? xstrdup (s) : NULL;
1000 dict_rename_var (dict, var, long_name);
1002 /* Restore short names. */
1003 for (i = 0; i < short_name_cnt; i++)
1005 var_set_short_name (var, i, short_names[i]);
1006 free (short_names[i]);
1010 close_text_record (r, text);
1011 r->has_long_var_names = true;
1014 /* Reads record type 7, subtype 14, which gives the real length
1015 of each very long string. Rearranges DICT accordingly. */
1017 read_long_string_map (struct sfm_reader *r, size_t size, size_t count,
1018 struct dictionary *dict)
1020 struct text_record *text;
1021 struct variable *var;
1024 text = open_text_record (r, size * count);
1025 while (read_variable_to_value_pair (r, dict, text, &var, &length_s))
1027 size_t idx = var_get_dict_index (var);
1033 length = strtol (length_s, NULL, 10);
1034 if (length < 1 || length > MAX_STRING)
1036 sys_warn (r, _("%s listed as string of invalid length %s "
1037 "in very length string record."),
1038 var_get_name (var), length_s);
1042 /* Check segments. */
1043 segment_cnt = sfm_width_to_segments (length);
1044 if (segment_cnt == 1)
1046 sys_warn (r, _("%s listed in very long string record with width %s, "
1047 "which requires only one segment."),
1048 var_get_name (var), length_s);
1051 if (idx + segment_cnt > dict_get_var_cnt (dict))
1052 sys_error (r, _("Very long string %s overflows dictionary."),
1053 var_get_name (var));
1055 /* Get the short names from the segments and check their
1057 for (i = 0; i < segment_cnt; i++)
1059 struct variable *seg = dict_get_var (dict, idx + i);
1060 int alloc_width = sfm_segment_alloc_width (length, i);
1061 int width = var_get_width (seg);
1064 var_set_short_name (var, i, var_get_short_name (seg, 0));
1065 if (ROUND_UP (width, 8) != ROUND_UP (alloc_width, 8))
1066 sys_error (r, _("Very long string with width %ld has segment %d "
1067 "of width %d (expected %d)"),
1068 length, i, width, alloc_width);
1070 dict_delete_consecutive_vars (dict, idx + 1, segment_cnt - 1);
1071 var_set_width (var, length);
1073 close_text_record (r, text);
1074 dict_compact_values (dict);
1077 /* Reads value labels from sysfile H and inserts them into the
1078 associated dictionary. */
1080 read_value_labels (struct sfm_reader *r,
1081 struct dictionary *dict, struct variable **var_by_value_idx)
1083 struct pool *subpool;
1087 char raw_value[8]; /* Value as uninterpreted bytes. */
1088 union value value; /* Value. */
1089 char *label; /* Null-terminated label string. */
1092 struct label *labels = NULL;
1093 int label_cnt; /* Number of labels. */
1095 struct variable **var = NULL; /* Associated variables. */
1096 int var_cnt; /* Number of associated variables. */
1100 subpool = pool_create_subpool (r->pool);
1102 /* Read the type 3 record and record its contents. We can't do
1103 much with the data yet because we don't know whether it is
1104 of numeric or string type. */
1106 /* Read number of labels. */
1107 label_cnt = read_int (r);
1109 if (size_overflow_p (xtimes (label_cnt, sizeof *labels)))
1111 sys_warn (r, _("Invalid number of labels: %d. Ignoring labels."),
1116 /* Read each value/label tuple into labels[]. */
1117 labels = pool_nalloc (subpool, label_cnt, sizeof *labels);
1118 for (i = 0; i < label_cnt; i++)
1120 struct label *label = labels + i;
1121 unsigned char label_len;
1125 read_bytes (r, label->raw_value, sizeof label->raw_value);
1127 /* Read label length. */
1128 read_bytes (r, &label_len, sizeof label_len);
1129 padded_len = ROUND_UP (label_len + 1, 8);
1131 /* Read label, padding. */
1132 label->label = pool_alloc (subpool, padded_len + 1);
1133 read_bytes (r, label->label, padded_len - 1);
1134 label->label[label_len] = 0;
1137 /* Now, read the type 4 record that has the list of variables
1138 to which the value labels are to be applied. */
1140 /* Read record type of type 4 record. */
1141 if (read_int (r) != 4)
1142 sys_error (r, _("Variable index record (type 4) does not immediately "
1143 "follow value label record (type 3) as it should."));
1145 /* Read number of variables associated with value label from type 4
1147 var_cnt = read_int (r);
1148 if (var_cnt < 1 || var_cnt > dict_get_var_cnt (dict))
1149 sys_error (r, _("Number of variables associated with a value label (%d) "
1150 "is not between 1 and the number of variables (%zu)."),
1151 var_cnt, dict_get_var_cnt (dict));
1153 /* Read the list of variables. */
1154 var = pool_nalloc (subpool, var_cnt, sizeof *var);
1155 for (i = 0; i < var_cnt; i++)
1157 var[i] = lookup_var_by_value_idx (r, var_by_value_idx, read_int (r));
1158 if (var_is_long_string (var[i]))
1159 sys_error (r, _("Value labels are not allowed on long string "
1160 "variables (%s)."), var_get_name (var[i]));
1163 /* Type check the variables. */
1164 for (i = 1; i < var_cnt; i++)
1165 if (var_get_type (var[i]) != var_get_type (var[0]))
1166 sys_error (r, _("Variables associated with value label are not all of "
1167 "identical type. Variable %s is %s, but variable "
1169 var_get_name (var[0]),
1170 var_is_numeric (var[0]) ? _("numeric") : _("string"),
1171 var_get_name (var[i]),
1172 var_is_numeric (var[i]) ? _("numeric") : _("string"));
1174 /* Fill in labels[].value, now that we know the desired type. */
1175 for (i = 0; i < label_cnt; i++)
1177 struct label *label = labels + i;
1179 if (var_is_alpha (var[0]))
1180 buf_copy_rpad (label->value.s, sizeof label->value.s,
1181 label->raw_value, sizeof label->raw_value);
1183 label->value.f = float_get_double (r->float_format, label->raw_value);
1186 /* Assign the `value_label's to each variable. */
1187 for (i = 0; i < var_cnt; i++)
1189 struct variable *v = var[i];
1192 /* Add each label to the variable. */
1193 for (j = 0; j < label_cnt; j++)
1195 struct label *label = &labels[j];
1196 if (!var_add_value_label (v, &label->value, label->label))
1198 if (var_is_numeric (var[0]))
1199 sys_warn (r, _("Duplicate value label for %g on %s."),
1200 label->value.f, var_get_name (v));
1202 sys_warn (r, _("Duplicate value label for \"%.*s\" on %s."),
1203 var_get_width (v), label->value.s,
1209 pool_destroy (subpool);
1212 /* Reads a set of custom attributes from TEXT into ATTRS.
1213 ATTRS may be a null pointer, in which case the attributes are
1214 read but discarded. */
1216 read_attributes (struct sfm_reader *r, struct text_record *text,
1217 struct attrset *attrs)
1221 struct attribute *attr;
1225 /* Parse the key. */
1226 key = text_get_token (text, ss_cstr ("("));
1230 attr = attribute_create (key);
1231 for (index = 1; ; index++)
1233 /* Parse the value. */
1237 value = text_get_token (text, ss_cstr ("\n"));
1240 text_warn (r, text, _("Error parsing attribute value %s[%d]"),
1245 length = strlen (value);
1246 if (length >= 2 && value[0] == '\'' && value[length - 1] == '\'')
1248 value[length - 1] = '\0';
1249 attribute_add_value (attr, value + 1);
1254 _("Attribute value %s[%d] is not quoted: %s"),
1256 attribute_add_value (attr, value);
1259 /* Was this the last value for this attribute? */
1260 if (text_match (text, ')'))
1264 attrset_add (attrs, attr);
1266 attribute_destroy (attr);
1268 while (!text_match (text, '/'));
1271 /* Reads record type 7, subtype 17, which lists custom
1272 attributes on the data file. */
1274 read_data_file_attributes (struct sfm_reader *r,
1275 size_t size, size_t count,
1276 struct dictionary *dict)
1278 struct text_record *text = open_text_record (r, size * count);
1279 read_attributes (r, text, dict_get_attributes (dict));
1280 close_text_record (r, text);
1283 /* Reads record type 7, subtype 18, which lists custom
1284 attributes on individual variables. */
1286 read_variable_attributes (struct sfm_reader *r,
1287 size_t size, size_t count,
1288 struct dictionary *dict)
1290 struct text_record *text = open_text_record (r, size * count);
1293 struct variable *var;
1294 if (!text_read_short_name (r, dict, text, ss_cstr (":"), &var))
1296 read_attributes (r, text, var != NULL ? var_get_attributes (var) : NULL);
1298 close_text_record (r, text);
1304 static void partial_record (struct sfm_reader *r)
1307 static void read_error (struct casereader *, const struct sfm_reader *);
1309 static bool read_case_number (struct sfm_reader *, double *);
1310 static bool read_case_string (struct sfm_reader *, char *, size_t);
1311 static int read_opcode (struct sfm_reader *);
1312 static bool read_compressed_number (struct sfm_reader *, double *);
1313 static bool read_compressed_string (struct sfm_reader *, char *);
1314 static bool read_whole_strings (struct sfm_reader *, char *, size_t);
1315 static bool skip_whole_strings (struct sfm_reader *, size_t);
1317 /* Reads and returns one case from READER's file. Returns a null
1318 pointer if not successful. */
1319 static struct ccase *
1320 sys_file_casereader_read (struct casereader *reader, void *r_)
1322 struct sfm_reader *r = r_;
1323 struct ccase *volatile c;
1329 c = case_create (r->value_cnt);
1330 if (setjmp (r->bail_out))
1332 casereader_force_error (reader);
1337 for (i = 0; i < r->sfm_var_cnt; i++)
1339 struct sfm_var *sv = &r->sfm_vars[i];
1340 union value *v = case_data_rw_idx (c, sv->case_index);
1344 if (!read_case_number (r, &v->f))
1349 if (!read_case_string (r, v->s + sv->offset, sv->width))
1351 if (!skip_whole_strings (r, ROUND_DOWN (sv->padding, 8)))
1361 if (r->case_cnt != -1)
1362 read_error (reader, r);
1366 /* Issues an error that R ends in a partial record. */
1368 partial_record (struct sfm_reader *r)
1370 sys_error (r, _("File ends in partial case."));
1373 /* Issues an error that an unspecified error occurred SFM, and
1376 read_error (struct casereader *r, const struct sfm_reader *sfm)
1378 msg (ME, _("Error reading case from file %s."), fh_get_name (sfm->fh));
1379 casereader_force_error (r);
1382 /* Reads a number from R and stores its value in *D.
1383 If R is compressed, reads a compressed number;
1384 otherwise, reads a number in the regular way.
1385 Returns true if successful, false if end of file is
1386 reached immediately. */
1388 read_case_number (struct sfm_reader *r, double *d)
1393 if (!try_read_bytes (r, number, sizeof number))
1395 float_convert (r->float_format, number, FLOAT_NATIVE_DOUBLE, d);
1399 return read_compressed_number (r, d);
1402 /* Reads LENGTH string bytes from R into S.
1403 Always reads a multiple of 8 bytes; if LENGTH is not a
1404 multiple of 8, then extra bytes are read and discarded without
1406 Reads compressed strings if S is compressed.
1407 Returns true if successful, false if end of file is
1408 reached immediately. */
1410 read_case_string (struct sfm_reader *r, char *s, size_t length)
1412 size_t whole = ROUND_DOWN (length, 8);
1413 size_t partial = length % 8;
1417 if (!read_whole_strings (r, s, whole))
1424 if (!read_whole_strings (r, bounce, sizeof bounce))
1430 memcpy (s + whole, bounce, partial);
1436 /* Reads and returns the next compression opcode from R. */
1438 read_opcode (struct sfm_reader *r)
1440 assert (r->compressed);
1444 if (r->opcode_idx >= sizeof r->opcodes)
1446 if (!try_read_bytes (r, r->opcodes, sizeof r->opcodes))
1450 opcode = r->opcodes[r->opcode_idx++];
1457 /* Reads a compressed number from R and stores its value in D.
1458 Returns true if successful, false if end of file is
1459 reached immediately. */
1461 read_compressed_number (struct sfm_reader *r, double *d)
1463 int opcode = read_opcode (r);
1471 *d = read_float (r);
1475 sys_error (r, _("Compressed data is corrupt."));
1482 *d = opcode - r->bias;
1489 /* Reads a compressed 8-byte string segment from R and stores it
1491 Returns true if successful, false if end of file is
1492 reached immediately. */
1494 read_compressed_string (struct sfm_reader *r, char *dst)
1496 switch (read_opcode (r))
1503 read_bytes (r, dst, 8);
1507 memset (dst, ' ', 8);
1511 sys_error (r, _("Compressed data is corrupt."));
1517 /* Reads LENGTH string bytes from R into S.
1518 LENGTH must be a multiple of 8.
1519 Reads compressed strings if S is compressed.
1520 Returns true if successful, false if end of file is
1521 reached immediately. */
1523 read_whole_strings (struct sfm_reader *r, char *s, size_t length)
1525 assert (length % 8 == 0);
1527 return try_read_bytes (r, s, length);
1531 for (ofs = 0; ofs < length; ofs += 8)
1532 if (!read_compressed_string (r, s + ofs))
1542 /* Skips LENGTH string bytes from R.
1543 LENGTH must be a multiple of 8.
1544 (LENGTH is also limited to 1024, but that's only because the
1545 current caller never needs more than that many bytes.)
1546 Returns true if successful, false if end of file is
1547 reached immediately. */
1549 skip_whole_strings (struct sfm_reader *r, size_t length)
1552 assert (length < sizeof buffer);
1553 return read_whole_strings (r, buffer, length);
1556 /* Creates and returns a table that can be used for translating a value
1557 index into a case to a "struct variable *" for DICT. Multiple
1558 system file fields reference variables this way.
1560 This table must be created before processing the very long
1561 string extension record, because that record causes some
1562 values to be deleted from the case and the dictionary to be
1564 static struct variable **
1565 make_var_by_value_idx (struct sfm_reader *r, struct dictionary *dict)
1567 struct variable **var_by_value_idx;
1571 var_by_value_idx = pool_nmalloc (r->pool,
1572 r->oct_cnt, sizeof *var_by_value_idx);
1573 for (i = 0; i < dict_get_var_cnt (dict); i++)
1575 struct variable *v = dict_get_var (dict, i);
1576 int nv = var_is_numeric (v) ? 1 : DIV_RND_UP (var_get_width (v), 8);
1579 var_by_value_idx[value_idx++] = v;
1580 for (j = 1; j < nv; j++)
1581 var_by_value_idx[value_idx++] = NULL;
1583 assert (value_idx == r->oct_cnt);
1585 return var_by_value_idx;
1588 /* Returns the "struct variable" corresponding to the given
1589 1-basd VALUE_IDX in VAR_BY_VALUE_IDX. Verifies that the index
1591 static struct variable *
1592 lookup_var_by_value_idx (struct sfm_reader *r,
1593 struct variable **var_by_value_idx, int value_idx)
1595 struct variable *var;
1597 if (value_idx < 1 || value_idx > r->oct_cnt)
1598 sys_error (r, _("Variable index %d not in valid range 1...%d."),
1599 value_idx, r->oct_cnt);
1601 var = var_by_value_idx[value_idx - 1];
1603 sys_error (r, _("Variable index %d refers to long string "
1610 /* Returns the variable in D with the given SHORT_NAME,
1611 or a null pointer if there is none. */
1612 static struct variable *
1613 lookup_var_by_short_name (struct dictionary *d, const char *short_name)
1615 struct variable *var;
1619 /* First try looking up by full name. This often succeeds. */
1620 var = dict_lookup_var (d, short_name);
1621 if (var != NULL && !strcasecmp (var_get_short_name (var, 0), short_name))
1624 /* Iterate through the whole dictionary as a fallback. */
1625 var_cnt = dict_get_var_cnt (d);
1626 for (i = 0; i < var_cnt; i++)
1628 var = dict_get_var (d, i);
1629 if (!strcasecmp (var_get_short_name (var, 0), short_name))
1636 /* Helpers for reading records that contain structured text
1639 /* Maximum number of warnings to issue for a single text
1641 #define MAX_TEXT_WARNINGS 5
1646 struct substring buffer; /* Record contents. */
1647 size_t pos; /* Current position in buffer. */
1648 int n_warnings; /* Number of warnings issued or suppressed. */
1651 /* Reads SIZE bytes into a text record for R,
1652 and returns the new text record. */
1653 static struct text_record *
1654 open_text_record (struct sfm_reader *r, size_t size)
1656 struct text_record *text = pool_alloc (r->pool, sizeof *text);
1657 char *buffer = pool_malloc (r->pool, size + 1);
1658 read_bytes (r, buffer, size);
1659 text->buffer = ss_buffer (buffer, size);
1661 text->n_warnings = 0;
1665 /* Closes TEXT, frees its storage, and issues a final warning
1666 about suppressed warnings if necesary. */
1668 close_text_record (struct sfm_reader *r, struct text_record *text)
1670 if (text->n_warnings > MAX_TEXT_WARNINGS)
1671 sys_warn (r, _("Suppressed %d additional related warnings."),
1672 text->n_warnings - MAX_TEXT_WARNINGS);
1673 pool_free (r->pool, ss_data (text->buffer));
1676 /* Reads a variable=value pair from TEXT.
1677 Looks up the variable in DICT and stores it into *VAR.
1678 Stores a null-terminated value into *VALUE. */
1680 read_variable_to_value_pair (struct sfm_reader *r, struct dictionary *dict,
1681 struct text_record *text,
1682 struct variable **var, char **value)
1686 if (!text_read_short_name (r, dict, text, ss_cstr ("="), var))
1689 *value = text_get_token (text, ss_buffer ("\t\0", 2));
1693 text->pos += ss_span (ss_substr (text->buffer, text->pos, SIZE_MAX),
1694 ss_buffer ("\t\0", 2));
1702 text_read_short_name (struct sfm_reader *r, struct dictionary *dict,
1703 struct text_record *text, struct substring delimiters,
1704 struct variable **var)
1706 char *short_name = text_get_token (text, delimiters);
1707 if (short_name == NULL)
1710 *var = lookup_var_by_short_name (dict, short_name);
1712 text_warn (r, text, _("Variable map refers to unknown variable %s."),
1717 /* Displays a warning for the current file position, limiting the
1718 number to MAX_TEXT_WARNINGS for TEXT. */
1720 text_warn (struct sfm_reader *r, struct text_record *text,
1721 const char *format, ...)
1723 if (text->n_warnings++ < MAX_TEXT_WARNINGS)
1727 va_start (args, format);
1728 sys_msg (r, MW, format, args);
1734 text_get_token (struct text_record *text, struct substring delimiters)
1736 struct substring token;
1738 if (!ss_tokenize (text->buffer, delimiters, &text->pos, &token))
1740 ss_data (token)[ss_length (token)] = '\0';
1741 return ss_data (token);
1745 text_match (struct text_record *text, char c)
1747 if (text->buffer.string[text->pos] == c)
1758 /* Displays a corruption message. */
1760 sys_msg (struct sfm_reader *r, int class, const char *format, va_list args)
1765 ds_init_empty (&text);
1766 ds_put_format (&text, "\"%s\" near offset 0x%lx: ",
1767 fh_get_file_name (r->fh), (unsigned long) ftell (r->file));
1768 ds_put_vformat (&text, format, args);
1770 m.category = msg_class_to_category (class);
1771 m.severity = msg_class_to_severity (class);
1772 m.where.file_name = NULL;
1773 m.where.line_number = 0;
1774 m.text = ds_cstr (&text);
1779 /* Displays a warning for the current file position. */
1781 sys_warn (struct sfm_reader *r, const char *format, ...)
1785 va_start (args, format);
1786 sys_msg (r, MW, format, args);
1790 /* Displays an error for the current file position,
1791 marks it as in an error state,
1792 and aborts reading it using longjmp. */
1794 sys_error (struct sfm_reader *r, const char *format, ...)
1798 va_start (args, format);
1799 sys_msg (r, ME, format, args);
1803 longjmp (r->bail_out, 1);
1806 /* Reads BYTE_CNT bytes into BUF.
1807 Returns true if exactly BYTE_CNT bytes are successfully read.
1808 Aborts if an I/O error or a partial read occurs.
1809 If EOF_IS_OK, then an immediate end-of-file causes false to be
1810 returned; otherwise, immediate end-of-file causes an abort
1813 read_bytes_internal (struct sfm_reader *r, bool eof_is_ok,
1814 void *buf, size_t byte_cnt)
1816 size_t bytes_read = fread (buf, 1, byte_cnt, r->file);
1817 if (bytes_read == byte_cnt)
1819 else if (ferror (r->file))
1820 sys_error (r, _("System error: %s."), strerror (errno));
1821 else if (!eof_is_ok || bytes_read != 0)
1822 sys_error (r, _("Unexpected end of file."));
1827 /* Reads BYTE_CNT into BUF.
1828 Aborts upon I/O error or if end-of-file is encountered. */
1830 read_bytes (struct sfm_reader *r, void *buf, size_t byte_cnt)
1832 read_bytes_internal (r, false, buf, byte_cnt);
1835 /* Reads BYTE_CNT bytes into BUF.
1836 Returns true if exactly BYTE_CNT bytes are successfully read.
1837 Returns false if an immediate end-of-file is encountered.
1838 Aborts if an I/O error or a partial read occurs. */
1840 try_read_bytes (struct sfm_reader *r, void *buf, size_t byte_cnt)
1842 return read_bytes_internal (r, true, buf, byte_cnt);
1845 /* Reads a 32-bit signed integer from R and returns its value in
1848 read_int (struct sfm_reader *r)
1851 read_bytes (r, integer, sizeof integer);
1852 return integer_get (r->integer_format, integer, sizeof integer);
1855 /* Reads a 64-bit floating-point number from R and returns its
1856 value in host format. */
1858 read_float (struct sfm_reader *r)
1861 read_bytes (r, number, sizeof number);
1862 return float_get_double (r->float_format, number);
1865 /* Reads exactly SIZE - 1 bytes into BUFFER
1866 and stores a null byte into BUFFER[SIZE - 1]. */
1868 read_string (struct sfm_reader *r, char *buffer, size_t size)
1871 read_bytes (r, buffer, size - 1);
1872 buffer[size - 1] = '\0';
1875 /* Skips BYTES bytes forward in R. */
1877 skip_bytes (struct sfm_reader *r, size_t bytes)
1882 size_t chunk = MIN (sizeof buffer, bytes);
1883 read_bytes (r, buffer, chunk);
1888 static const struct casereader_class sys_file_casereader_class =
1890 sys_file_casereader_read,
1891 sys_file_casereader_destroy,