X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fsfm-write.c;h=3b74efe151231730bda08eee441900908621c7d3;hb=1e06be73a426544652cdd7d73f001c962bac1a34;hp=e1e103e5005c247dd9477c6dbd3c280a7f7bcef8;hpb=4de79b34b329d1da6cdeb145993d3efd911e2967;p=pspp diff --git a/src/sfm-write.c b/src/sfm-write.c index e1e103e500..3b74efe151 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. */ @@ -37,6 +39,8 @@ #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" @@ -107,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 (fh_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; @@ -141,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); @@ -152,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. */ @@ -189,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; @@ -213,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++; @@ -225,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."), + fh_get_filename (w->fh), strerror (errno)); + err_cond_fail (); + goto error; } static int @@ -362,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. */ @@ -369,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); @@ -445,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)) @@ -518,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)); } @@ -740,7 +749,7 @@ buf_write (struct sfm_writer *w, const void *buf, size_t nbytes) if (fwrite (buf, nbytes, 1, w->file) != 1) { msg (ME, _("%s: Writing system file: %s."), - handle_get_filename (w->fh), strerror (errno)); + fh_get_filename (w->fh), strerror (errno)); return 0; } return 1; @@ -920,7 +929,7 @@ sfm_close_writer (struct sfm_writer *w) if (fclose (w->file) == EOF) msg (ME, _("%s: Closing system file: %s."), - handle_get_filename (w->fh), strerror (errno)); + fh_get_filename (w->fh), strerror (errno)); } free (w->buf);