X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fsfm-write.c;h=d06a65f5a22334048309de1b90f548f339188aa1;hb=16aa47dbdde420fe82032f7d2e166fdf4e974df5;hp=99dd47bdfa65c25c20ad2231518f76e119795d30;hpb=317e6b778833b5dcd5dd195c0b677835a8024b2a;p=pspp diff --git a/src/sfm-write.c b/src/sfm-write.c index 99dd47bdfa..d06a65f5a2 100644 --- a/src/sfm-write.c +++ b/src/sfm-write.c @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include #if HAVE_UNISTD_H #include /* Required by SunOS4. */ @@ -33,15 +35,20 @@ #include "dictionary.h" #include "error.h" #include "file-handle.h" -#include "getline.h" +#include "getl.h" #include "hash.h" #include "magic.h" #include "misc.h" +#include "settings.h" +#include "stat-macros.h" #include "str.h" #include "value-labels.h" #include "var.h" #include "version.h" +#include "gettext.h" +#define _(msgid) gettext (msgid) + #include "debug-print.h" /* Compression bias used by PSPP. Values between (1 - @@ -104,33 +111,61 @@ var_flt64_cnt (const struct variable *v) return v->type == NUMERIC ? 1 : DIV_RND_UP (v->width, sizeof (flt64)); } +/* Returns default options for writing a system file. */ +struct sfm_write_options +sfm_writer_default_options (void) +{ + struct sfm_write_options opts; + opts.create_writeable = true; + opts.compress = get_scompression (); + opts.version = 3; + return opts; +} + /* Opens the system file designated by file handle FH for writing - cases from dictionary D. If COMPRESS is nonzero, the - system file will be compressed. If OMIT_LONG_NAMES is nonzero, the - long name table will be omitted. + cases from dictionary D according to the given OPTS. If + COMPRESS is nonzero, the system file will be compressed. No reference to D is retained, so it may be modified or destroyed at will after this function returns. D is not modified by this function, except to assign short names. */ struct sfm_writer * -sfm_open_writer (struct file_handle *fh, - struct dictionary *d, int compress, - short omit_long_names) +sfm_open_writer (struct file_handle *fh, struct dictionary *d, + struct sfm_write_options opts) { struct sfm_writer *w = NULL; + mode_t mode; + int fd; int idx; int i; + /* Check version. */ + if (opts.version != 2 && opts.version != 3) + { + msg (ME, _("Unknown system file version %d. Treating as version %d."), + opts.version, 3); + opts.version = 3; + } + + /* Create file. */ + mode = S_IRUSR | S_IRGRP | S_IROTH; + if (opts.create_writeable) + mode |= S_IWUSR | S_IWGRP | S_IWOTH; + fd = open (handle_get_filename (fh), O_WRONLY | O_CREAT | O_TRUNC, mode); + if (fd < 0) + goto open_error; + + /* Open file handle. */ if (!fh_open (fh, "system file", "we")) goto error; /* Create and initialize writer. */ w = xmalloc (sizeof *w); w->fh = fh; - w->file = fopen (handle_get_filename (fh), "wb"); + w->file = fdopen (fd, "w"); w->needs_translation = does_dict_need_translation (d); - w->compress = compress; + w->compress = opts.compress; w->case_cnt = 0; w->flt64_cnt = 0; @@ -138,7 +173,7 @@ sfm_open_writer (struct file_handle *fh, w->x = w->y = NULL; w->var_cnt = dict_get_var_cnt (d); - w->vars = xmalloc (sizeof *w->vars * w->var_cnt); + w->vars = xnmalloc (w->var_cnt, sizeof *w->vars); for (i = 0; i < w->var_cnt; i++) { const struct variable *dv = dict_get_var (d, i); @@ -149,13 +184,10 @@ sfm_open_writer (struct file_handle *fh, } /* Check that file create succeeded. */ - if (w->file == NULL) + if (w->file == NULL) { - msg (ME, _("Error opening \"%s\" for writing " - "as a system file: %s."), - handle_get_filename (w->fh), strerror (errno)); - err_cond_fail (); - goto error; + close (fd); + goto open_error; } /* Write the file header. */ @@ -186,7 +218,7 @@ sfm_open_writer (struct file_handle *fh, if (!write_variable_display_parameters (w, d)) goto error; - if (!omit_long_names) + if (opts.version >= 3) { if (!write_longvar_table (w, d)) goto error; @@ -210,7 +242,7 @@ sfm_open_writer (struct file_handle *fh, if (w->compress) { - w->buf = xmalloc (sizeof *w->buf * 128); + w->buf = xnmalloc (128, sizeof *w->buf); w->ptr = w->buf; w->end = &w->buf[128]; w->x = (unsigned char *) w->ptr++; @@ -222,6 +254,12 @@ sfm_open_writer (struct file_handle *fh, error: sfm_close_writer (w); return NULL; + + open_error: + msg (ME, _("Error opening \"%s\" for writing as a system file: %s."), + handle_get_filename (w->fh), strerror (errno)); + err_cond_fail (); + goto error; } static int @@ -359,6 +397,7 @@ write_variable (struct sfm_writer *w, struct variable *v) struct sysfile_variable sv; /* Missing values. */ + struct missing_values mv; flt64 m[3]; /* Missing value values. */ int nm; /* Number of missing values, possibly negative. */ @@ -366,54 +405,27 @@ write_variable (struct sfm_writer *w, struct variable *v) sv.type = v->width; sv.has_var_label = (v->label != NULL); - switch (v->miss_type) + mv_copy (&mv, &v->miss); + nm = 0; + if (mv_has_range (&mv)) { - case MISSING_NONE: - nm = 0; - break; - case MISSING_1: - case MISSING_2: - case MISSING_3: - for (nm = 0; nm < v->miss_type; nm++) - m[nm] = v->missing[nm].f; - break; - case MISSING_RANGE: - m[0] = v->missing[0].f; - m[1] = v->missing[1].f; - nm = -2; - break; - case MISSING_LOW: - m[0] = second_lowest_flt64; - m[1] = v->missing[0].f; - nm = -2; - break; - case MISSING_HIGH: - m[0] = v->missing[0].f; - m[1] = FLT64_MAX; - nm = -2; - break; - case MISSING_RANGE_1: - m[0] = v->missing[0].f; - m[1] = v->missing[1].f; - m[2] = v->missing[2].f; - nm = -3; - break; - case MISSING_LOW_1: - m[0] = second_lowest_flt64; - m[1] = v->missing[0].f; - m[2] = v->missing[1].f; - nm = -3; - break; - case MISSING_HIGH_1: - m[0] = v->missing[0].f; - m[1] = second_lowest_flt64; - m[2] = v->missing[1].f; - nm = -3; - break; - default: - assert (0); - abort (); + double x, y; + mv_pop_range (&mv, &x, &y); + m[nm++] = x == LOWEST ? second_lowest_flt64 : x; + m[nm++] = y == HIGHEST ? FLT64_MAX : y; + } + while (mv_has_value (&mv)) + { + union value value; + mv_pop_value (&mv, &value); + if (v->type == NUMERIC) + m[nm] = value.f; + else + buf_copy_rpad ((char *) &m[nm], sizeof m[nm], value.s, v->width); + nm++; } + if (mv_has_range (&v->miss)) + nm = -nm; sv.n_missing_values = nm; write_format_spec (&v->print, &sv.print); @@ -442,7 +454,7 @@ write_variable (struct sfm_writer *w, struct variable *v) return 0; } - if (nm && !buf_write (w, m, sizeof *m * nm)) + if (nm && !buf_write (w, m, sizeof *m * abs (nm))) return 0; if (v->type == ALPHA && v->width > (int) sizeof (flt64)) @@ -515,8 +527,8 @@ write_value_labels (struct sfm_writer *w, struct variable *v, int idx) *loc++ = vl->value.f; *(unsigned char *) loc = len; - memcpy (&((unsigned char *) loc)[1], vl->label, len); - memset (&((unsigned char *) loc)[1 + len], ' ', + memcpy (&((char *) loc)[1], vl->label, len); + memset (&((char *) loc)[1 + len], ' ', REM_RND_UP (len + 1, sizeof (flt64))); loc += DIV_RND_UP (len + 1, sizeof (flt64)); }