X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fpfm-read.c;h=f398747584ae9b7e48c5ffeee25bebfb66581fc1;hb=053e7ff6e0a45a25d5604b211e9c950fff50e75d;hp=50b15c5433be2f78b64f20e9b625294fd0a26312;hpb=e582516e80e5a04f10a651515a35b616911cf4d6;p=pspp-builds.git diff --git a/src/pfm-read.c b/src/pfm-read.c index 50b15c54..f3987475 100644 --- a/src/pfm-read.c +++ b/src/pfm-read.c @@ -1,5 +1,5 @@ /* PSPP - computes sample statistics. - Copyright (C) 1997-9, 2000 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc. Written by Ben Pfaff . Code for parsing floating-point numbers adapted from GNU C library. @@ -16,8 +16,8 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. */ + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ #include #include "pfm-read.h" @@ -30,12 +30,12 @@ #include #include #include "alloc.h" -#include "bool.h" +#include #include "case.h" #include "dictionary.h" #include "file-handle.h" #include "format.h" -#include "getline.h" +#include "getl.h" #include "hash.h" #include "magic.h" #include "misc.h" @@ -44,8 +44,21 @@ #include "value-labels.h" #include "var.h" +#include "gettext.h" +#define _(msgid) gettext (msgid) + #include "debug-print.h" +/* portable_to_local[PORTABLE] translates the given portable + character into the local character set. */ +static const char portable_to_local[256] = + { + " " + "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ." + "<(+|&[]!$*);^-/|,%_>?`:$@'=\" ~- 0123456789 -() {}\\ " + " " + }; + /* Portable file reader. */ struct pfm_reader { @@ -56,8 +69,7 @@ struct pfm_reader struct file_handle *fh; /* File handle. */ FILE *file; /* File stream. */ char cc; /* Current character. */ - unsigned char *trans; /* 256-byte character set translation table. */ - + char *trans; /* 256-byte character set translation table. */ int var_cnt; /* Number of variables. */ int weight_index; /* 0-based index of weight variable, or -1. */ int *widths; /* Variable widths, 0 for numeric. */ @@ -80,7 +92,7 @@ error (struct pfm_reader *r, const char *msg, ...) e.class = ME; getl_location (&e.where.filename, &e.where.line_number); - filename = handle_get_filename (r->fh); + filename = fh_get_filename (r->fh); e.title = title = pool_alloc (r->pool, strlen (filename) + 80); sprintf (title, _("portable file %s corrupt at offset %ld: "), filename, ftell (r->file)); @@ -147,7 +159,7 @@ pfm_open_reader (struct file_handle *fh, struct dictionary **dict, struct pfm_reader *volatile r = NULL; *dict = dict_create (); - if (!fh_open (fh, "portable file", "rs")) + if (!fh_open (fh, FH_REF_FILE, "portable file", "rs")) goto error; /* Create and initialize reader. */ @@ -157,7 +169,7 @@ pfm_open_reader (struct file_handle *fh, struct dictionary **dict, if (setjmp (r->bail_out)) goto error; r->fh = fh; - r->file = pool_fopen (r->pool, handle_get_filename (r->fh), "rb"); + r->file = pool_fopen (r->pool, fh_get_filename (r->fh), "rb"); r->weight_index = -1; r->trans = NULL; r->var_cnt = 0; @@ -169,7 +181,7 @@ pfm_open_reader (struct file_handle *fh, struct dictionary **dict, { msg (ME, _("An error occurred while opening \"%s\" for reading " "as a portable file: %s."), - handle_get_filename (r->fh), strerror (errno)); + fh_get_filename (r->fh), strerror (errno)); err_cond_fail (); goto error; } @@ -339,7 +351,7 @@ read_string (struct pfm_reader *r, char *buf) /* Reads a string and returns a copy of it allocated from R's pool. */ -static unsigned char * +static char * read_pool_string (struct pfm_reader *r) { char string[256]; @@ -351,17 +363,7 @@ read_pool_string (struct pfm_reader *r) static void read_header (struct pfm_reader *r) { - /* portable_to_local[PORTABLE] translates the given portable - character into the local character set. */ - static const unsigned char portable_to_local[256] = - { - " " - "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ." - "<(+|&[]!$*);^-/|,%_>?`:$@'=\" ~- 0123456789 -() {}\\ " - " " - }; - - unsigned char *trans; + char *trans; int i; /* Read and ignore vanity splash strings. */ @@ -398,7 +400,7 @@ read_header (struct pfm_reader *r) for (i = 0; i < 8; i++) if (!match (r, "SPSSPORT"[i])) { - msg (SE, _("%s: Not a portable file."), handle_get_filename (r->fh)); + msg (SE, _("%s: Not a portable file."), fh_get_filename (r->fh)); longjmp (r->bail_out, 1); } } @@ -408,7 +410,8 @@ read_header (struct pfm_reader *r) static void read_version_data (struct pfm_reader *r, struct pfm_read_info *info) { - char *date, *time, *product, *subproduct; + static char empty_string[] = ""; + char *date, *time, *product, *author, *subproduct; int i; /* Read file. */ @@ -416,9 +419,9 @@ read_version_data (struct pfm_reader *r, struct pfm_read_info *info) error (r, "Unrecognized version code `%c'.", r->cc); date = read_pool_string (r); time = read_pool_string (r); - product = match (r, '1') ? read_pool_string (r) : (unsigned char *) ""; - subproduct - = match (r, '3') ? read_pool_string (r) : (unsigned char *) ""; + product = match (r, '1') ? read_pool_string (r) : empty_string; + author = match (r, '2') ? read_pool_string (r) : empty_string; + subproduct = match (r, '3') ? read_pool_string (r) : empty_string; /* Validate file. */ if (strlen (date) != 8) @@ -448,8 +451,8 @@ read_version_data (struct pfm_reader *r, struct pfm_read_info *info) info->creation_time[8] = 0; /* Product. */ - st_trim_copy (info->product, product, sizeof info->product); - st_trim_copy (info->subproduct, subproduct, sizeof info->subproduct); + str_copy_trunc (info->product, sizeof info->product, product); + str_copy_trunc (info->subproduct, sizeof info->subproduct, subproduct); } } @@ -489,7 +492,7 @@ read_variables (struct pfm_reader *r, struct dictionary *dict) r->var_cnt = read_int (r); if (r->var_cnt <= 0 || r->var_cnt == NOT_INT) error (r, _("Invalid number of variables %d."), r->var_cnt); - r->widths = pool_alloc (r->pool, sizeof *r->widths * r->var_cnt); + r->widths = pool_nalloc (r->pool, r->var_cnt, sizeof *r->widths); /* Purpose of this value is unknown. It is typically 161. */ read_int (r); @@ -497,7 +500,7 @@ read_variables (struct pfm_reader *r, struct dictionary *dict) if (match (r, '6')) { weight_name = read_pool_string (r); - if (strlen (weight_name) > 8) + if (strlen (weight_name) > SHORT_NAME_LEN) error (r, _("Weight variable name (%s) truncated."), weight_name); } @@ -521,9 +524,9 @@ read_variables (struct pfm_reader *r, struct dictionary *dict) for (j = 0; j < 6; j++) fmt[j] = read_int (r); - if (!var_is_valid_name (name, false) || *name == '#') - error (r, _("position %d: Invalid variable name `%s'."), name); - st_uppercase (name); + if (!var_is_valid_name (name, false) || *name == '#' || *name == '$') + error (r, _("position %d: Invalid variable name `%s'."), i, name); + str_uppercase (name); if (width < 0 || width > 255) error (r, "Bad width %d for variable %s.", width, name); @@ -536,45 +539,23 @@ read_variables (struct pfm_reader *r, struct dictionary *dict) convert_format (r, &fmt[3], &v->write, v); /* Range missing values. */ - if (match (r, 'B')) - { - v->miss_type = MISSING_RANGE; - v->missing[0] = parse_value (r, v); - v->missing[1] = parse_value (r, v); - } + if (match (r, 'B')) + { + double x = read_float (r); + double y = read_float (r); + mv_add_num_range (&v->miss, x, y); + } else if (match (r, 'A')) - { - v->miss_type = MISSING_HIGH; - v->missing[0] = parse_value (r, v); - } + mv_add_num_range (&v->miss, read_float (r), HIGHEST); else if (match (r, '9')) - { - v->miss_type = MISSING_LOW; - v->missing[0] = parse_value (r, v); - } + mv_add_num_range (&v->miss, LOWEST, read_float (r)); /* Single missing values. */ - while (match (r, '8')) - { - static const int map_next[MISSING_COUNT] = - { - MISSING_1, MISSING_2, MISSING_3, -1, - MISSING_RANGE_1, MISSING_LOW_1, MISSING_HIGH_1, - -1, -1, -1, - }; - - static const int map_ofs[MISSING_COUNT] = - { - -1, 0, 1, 2, -1, -1, -1, 2, 1, 1, - }; - - v->miss_type = map_next[v->miss_type]; - if (v->miss_type == -1) - error (r, _("Bad missing values for %s."), v->name); - - assert (map_ofs[v->miss_type] != -1); - v->missing[map_ofs[v->miss_type]] = parse_value (r, v); - } + while (match (r, '8')) + { + union value value = parse_value (r, v); + mv_add_value (&v->miss, &value); + } if (match (r, 'C')) { @@ -605,7 +586,7 @@ parse_value (struct pfm_reader *r, struct variable *vv) { char string[256]; read_string (r, string); - st_bare_pad_copy (v.s, string, 8); + buf_copy_str_rpad (v.s, 8, string); } else v.f = read_float (r); @@ -627,7 +608,7 @@ read_value_label (struct pfm_reader *r, struct dictionary *dict) int i; nv = read_int (r); - v = pool_alloc (r->pool, sizeof *v * nv); + v = pool_nalloc (r->pool, nv, sizeof *v); for (i = 0; i < nv; i++) { char name[256]; @@ -699,10 +680,45 @@ pfm_read_case (struct pfm_reader *r, struct ccase *c) { char string[256]; read_string (r, string); - st_bare_pad_copy (case_data_rw (c, idx)->s, string, width); + buf_copy_str_rpad (case_data_rw (c, idx)->s, width, string); idx += DIV_RND_UP (width, MAX_SHORT_STRING); } } return true; } + +/* Returns true if FILE is an SPSS portable file, + false otherwise. */ +bool +pfm_detect (FILE *file) +{ + unsigned char header[464]; + char trans[256]; + int cooked_cnt, raw_cnt; + int i; + + cooked_cnt = raw_cnt = 0; + while (cooked_cnt < sizeof header) + { + int c = getc (file); + if (c == EOF || raw_cnt++ > 512) + return false; + else if (c != '\n' && c != '\r') + header[cooked_cnt++] = c; + } + + memset (trans, 0, 256); + for (i = 64; i < 256; i++) + { + unsigned char c = header[i + 200]; + if (trans[c] == 0) + trans[c] = portable_to_local[i]; + } + + for (i = 0; i < 8; i++) + if (trans[header[i + 456]] != "SPSSPORT"[i]) + return false; + + return true; +}