X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdata%2Fpor-file-reader.c;h=7e65c28bdf51c11b54f1f6ddd9eced26670b6197;hb=ef35211c05259417e4f3dd4a7de44e92e4bc54a3;hp=e82e136167b9a06c006be699dd2929a03ddaf4b0;hpb=29956ba4326b9d6a2bc4d22a9f323902c7a08d43;p=pspp-builds.git diff --git a/src/data/por-file-reader.c b/src/data/por-file-reader.c index e82e1361..7e65c28b 100644 --- a/src/data/por-file-reader.c +++ b/src/data/por-file-reader.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2006, 2009 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -30,21 +30,24 @@ #include #include #include +#include #include #include +#include #include #include -#include #include #include -#include #include #include #include #include +#include "xalloc.h" + #include "gettext.h" #define _(msgid) gettext (msgid) +#define N_(msgid) (msgid) /* portable_to_local[PORTABLE] translates the given portable character into the local character set. */ @@ -64,6 +67,7 @@ struct pfm_reader jmp_buf bail_out; /* longjmp() target for error handling. */ struct file_handle *fh; /* File handle. */ + struct fh_lock *lock; /* Read lock for file. */ FILE *file; /* File stream. */ int line_length; /* Number of characters so far on this line. */ char cc; /* Current character. */ @@ -75,7 +79,7 @@ struct pfm_reader bool ok; /* Set false on I/O error. */ }; -static struct casereader_class por_file_casereader_class; +static const struct casereader_class por_file_casereader_class; static void error (struct pfm_reader *r, const char *msg,...) @@ -136,12 +140,42 @@ warning (struct pfm_reader *r, const char *msg, ...) msg_emit (&m); } +/* Close and destroy R. + Returns false if an error was detected on R, true otherwise. */ +static bool +close_reader (struct pfm_reader *r) +{ + bool ok; + if (r == NULL) + return true; + + if (r->file) + { + if (fn_close (fh_get_file_name (r->fh), r->file) == EOF) + { + msg (ME, _("Error closing portable file \"%s\": %s."), + fh_get_file_name (r->fh), strerror (errno)); + r->ok = false; + } + r->file = NULL; + } + + fh_unlock (r->lock); + fh_unref (r->fh); + + ok = r->ok; + pool_destroy (r->pool); + + return ok; +} + /* Closes portable file reader R, after we're done with it. */ static void -por_file_casereader_destroy (struct casereader *reader UNUSED, void *r_) +por_file_casereader_destroy (struct casereader *reader, void *r_) { struct pfm_reader *r = r_; - pool_destroy (r->pool); + if (!close_reader (r)) + casereader_force_error (reader); } /* Read a single character into cur_char. */ @@ -210,17 +244,14 @@ pfm_open_reader (struct file_handle *fh, struct dictionary **dict, struct pfm_reader *volatile r = NULL; *dict = dict_create (); - if (!fh_open (fh, FH_REF_FILE, "portable file", "rs")) - goto error; /* Create and initialize reader. */ pool = pool_create (); r = pool_alloc (pool, sizeof *r); r->pool = pool; - if (setjmp (r->bail_out)) - goto error; - r->fh = fh; - r->file = pool_fopen (r->pool, fh_get_file_name (r->fh), "rb"); + r->fh = fh_ref (fh); + r->lock = NULL; + r->file = NULL; r->line_length = 0; r->weight_index = -1; r->trans = NULL; @@ -228,8 +259,18 @@ pfm_open_reader (struct file_handle *fh, struct dictionary **dict, r->widths = NULL; r->value_cnt = 0; r->ok = true; + if (setjmp (r->bail_out)) + goto error; - /* Check that file open succeeded, prime reading. */ + /* Lock file. */ + /* TRANSLATORS: this fragment will be interpolated into + messages in fh_lock() that identify types of files. */ + r->lock = fh_lock (fh, FH_REF_FILE, N_("portable file"), FH_ACC_READ, false); + if (r->lock == NULL) + goto error; + + /* Open file. */ + r->file = fn_open (fh_get_file_name (r->fh), "rb"); if (r->file == NULL) { msg (ME, _("An error occurred while opening \"%s\" for reading " @@ -260,7 +301,7 @@ pfm_open_reader (struct file_handle *fh, struct dictionary **dict, &por_file_casereader_class, r); error: - pool_destroy (r->pool); + close_reader (r); dict_destroy (*dict); *dict = NULL; return NULL; @@ -468,8 +509,9 @@ read_header (struct pfm_reader *r) static void read_version_data (struct pfm_reader *r, struct pfm_read_info *info) { - static char empty_string[] = ""; - char *date, *time, *product, *author, *subproduct; + static const char empty_string[] = ""; + char *date, *time; + const char *product, *author, *subproduct; int i; /* Read file. */ @@ -483,9 +525,9 @@ read_version_data (struct pfm_reader *r, struct pfm_read_info *info) /* Validate file. */ if (strlen (date) != 8) - error (r, _("Bad date string length %d."), (int) strlen (date)); + error (r, _("Bad date string length %zu."), strlen (date)); if (strlen (time) != 6) - error (r, _("Bad time string length %d."), (int) strlen (time)); + error (r, _("Bad time string length %zu."), strlen (time)); /* Save file info. */ if (info != NULL) @@ -579,7 +621,7 @@ read_variables (struct pfm_reader *r, struct dictionary *dict) error (r, _("Expected variable count record.")); r->var_cnt = read_int (r); - if (r->var_cnt <= 0 || r->var_cnt == NOT_INT) + if (r->var_cnt <= 0) error (r, _("Invalid number of variables %d."), r->var_cnt); r->widths = pool_nalloc (r->pool, r->var_cnt, sizeof *r->widths); @@ -629,8 +671,8 @@ read_variables (struct pfm_reader *r, struct dictionary *dict) int i; for (i = 1; i < 100000; i++) { - char try_name[LONG_NAME_LEN + 1]; - sprintf (try_name, "%.*s_%d", LONG_NAME_LEN - 6, name, i); + char try_name[VAR_NAME_LEN + 1]; + sprintf (try_name, "%.*s_%d", VAR_NAME_LEN - 6, name, i); v = dict_create_var (dict, try_name, width); if (v != NULL) break; @@ -652,12 +694,12 @@ read_variables (struct pfm_reader *r, struct dictionary *dict) { double x = read_float (r); double y = read_float (r); - mv_add_num_range (&miss, x, y); + mv_add_range (&miss, x, y); } else if (match (r, 'A')) - mv_add_num_range (&miss, read_float (r), HIGHEST); + mv_add_range (&miss, read_float (r), HIGHEST); else if (match (r, '9')) - mv_add_num_range (&miss, LOWEST, read_float (r)); + mv_add_range (&miss, LOWEST, read_float (r)); /* Single missing values. */ while (match (r, '8')) @@ -772,28 +814,30 @@ read_documents (struct pfm_reader *r, struct dictionary *dict) } } -/* Reads one case from portable file R into C. */ -static bool -por_file_casereader_read (struct casereader *reader, void *r_, struct ccase *c) +/* Reads and returns one case from portable file R. Returns a + null pointer on failure. */ +static struct ccase * +por_file_casereader_read (struct casereader *reader, void *r_) { struct pfm_reader *r = r_; + struct ccase *volatile c; size_t i; size_t idx; - case_create (c, casereader_get_value_cnt (reader)); + c = case_create (casereader_get_value_cnt (reader)); setjmp (r->bail_out); if (!r->ok) { casereader_force_error (reader); - case_destroy (c); - return false; + case_unref (c); + return NULL; } /* Check for end of file. */ if (r->cc == 'Z') { - case_destroy (c); - return false; + case_unref (c); + return NULL; } idx = 0; @@ -815,7 +859,7 @@ por_file_casereader_read (struct casereader *reader, void *r_, struct ccase *c) } } - return true; + return c; } /* Returns true if FILE is an SPSS portable file, @@ -853,7 +897,7 @@ pfm_detect (FILE *file) return true; } -static struct casereader_class por_file_casereader_class = +static const struct casereader_class por_file_casereader_class = { por_file_casereader_read, por_file_casereader_destroy,