/* 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 <blp@gnu.org>.
This program is free software; you can redistribute it and/or
02110-1301, USA. */
#include <config.h>
+
#include "sys-file-writer.h"
#include "sfm-private.h"
-#include <libpspp/message.h>
-#include <stdlib.h>
+
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
+#include <stdlib.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
+
#include <libpspp/alloc.h>
-#include "case.h"
-#include "dictionary.h"
-#include <libpspp/message.h>
-#include "file-handle-def.h"
#include <libpspp/hash.h>
#include <libpspp/magic.h>
+#include <libpspp/message.h>
#include <libpspp/misc.h>
-#include "settings.h"
-#include "stat-macros.h"
#include <libpspp/str.h>
+#include <libpspp/version.h>
+
+#include "case.h"
+#include "dictionary.h"
+#include "file-handle-def.h"
+#include "settings.h"
#include "value-labels.h"
#include "variable.h"
-#include <libpspp/version.h>
+
+#include "stat-macros.h"
+#include "minmax.h"
#include "gettext.h"
#define _(msgid) gettext (msgid)
int compress; /* 1=compressed, 0=not compressed. */
int case_cnt; /* Number of cases written so far. */
size_t flt64_cnt; /* Number of flt64 elements in case. */
+ bool has_vls; /* Does the dict have very long strings? */
/* Compression buffering. */
flt64 *buf; /* Buffered data. */
const struct dictionary *dict);
static void write_documents (struct sfm_writer *, const struct dictionary *);
-static int does_dict_need_translation (const struct dictionary *);
static inline int
var_flt64_cnt (const struct variable *v)
w->fh = fh;
w->file = fdopen (fd, "w");
- w->needs_translation = does_dict_need_translation (d);
+ w->needs_translation = dict_compacting_would_change (d);
w->compress = opts.compress;
w->case_cnt = 0;
w->flt64_cnt = 0;
+ w->has_vls = false;
w->buf = w->end = w->ptr = NULL;
w->x = w->y = NULL;
sv->width = dv->width;
/* spss compatibility nonsense */
if ( dv->width > MAX_LONG_STRING )
- sv->width = (dv->width / MAX_LONG_STRING) * (MAX_LONG_STRING + 1)
- + (dv->width % MAX_LONG_STRING) ;
+ w->has_vls = true;
+
sv->fv = dv->fv;
sv->flt64_cnt = var_flt64_cnt (dv);
}
{
struct
{
- int32_t rec_type P;
- int32_t filler P;
- }
+ int32_t rec_type ;
+ int32_t filler ;
+ } ATTRIBUTE((packed))
rec_999;
rec_999.rec_type = 999;
goto error;
}
-static int
-does_dict_need_translation (const struct dictionary *d)
-{
- size_t case_idx;
- size_t i;
-
- case_idx = 0;
- for (i = 0; i < dict_get_var_cnt (d); i++)
- {
- struct variable *v = dict_get_var (d, i);
- if (v->fv != case_idx)
- return 0;
- case_idx += v->nv;
- }
- return 1;
-}
-
/* Returns value of X truncated to two least-significant digits. */
static int
rerange (int x)
if (dict_get_weight (d) != NULL)
{
- struct variable *weight_var;
+ const struct variable *weight_var;
int recalc_weight_idx = 1;
int i;
static inline void
write_format_spec (const struct fmt_spec *src, int32_t *dest)
{
- assert(check_output_specifier(src, true));
- *dest = (formats[src->type].spss << 16) | (src->w << 8) | src->d;
+ assert (fmt_check_output (src));
+ *dest = (fmt_to_io (src->type) << 16) | (src->w << 8) | src->d;
}
/* Write the variable record(s) for primary variable P and secondary
int nm; /* Number of missing values, possibly negative. */
sv.rec_type = 2;
- sv.type = min(v->width, MAX_LONG_STRING);
+ sv.type = MIN(v->width, MAX_LONG_STRING);
sv.has_var_label = (v->label != NULL);
mv_copy (&mv, &v->miss);
{
struct label
{
- int32_t label_len P;
- char label[255] P;
- }
+ int32_t label_len ;
+ char label[255] ;
+ } ATTRIBUTE((packed))
l;
int ext_len;
- l.label_len = min (strlen (v->label), 255);
+ l.label_len = MIN (strlen (v->label), 255);
ext_len = ROUND_UP (l.label_len, sizeof l.label_len);
memcpy (l.label, v->label, l.label_len);
memset (&l.label[l.label_len], ' ', ext_len - l.label_len);
memset (&sv.write, 0, sizeof sv.write);
memset (&sv.name, 0, sizeof sv.name);
- pad_count = DIV_RND_UP (min(v->width, MAX_LONG_STRING),
+ pad_count = DIV_RND_UP (MIN(v->width, MAX_LONG_STRING),
(int) sizeof (flt64)) - 1;
for (i = 0; i < pad_count; i++)
buf_write (w, &sv, sizeof sv);
{
struct value_label_rec
{
- int32_t rec_type P;
- int32_t n_labels P;
- flt64 labels[1] P;
- };
+ int32_t rec_type ;
+ int32_t n_labels ;
+ flt64 labels[1] ;
+ } ATTRIBUTE((packed));
struct var_idx_rec
{
- int32_t rec_type P;
- int32_t n_vars P;
- int32_t vars[1] P;
- };
+ int32_t rec_type ;
+ int32_t n_vars ;
+ int32_t vars[1] ;
+ } ATTRIBUTE((packed));
struct val_labs_iterator *i;
struct value_label_rec *vlr;
write_documents (struct sfm_writer *w, const struct dictionary *d)
{
struct
- {
- int32_t rec_type P; /* Always 6. */
- int32_t n_lines P; /* Number of lines of documents. */
- }
- rec_6;
+ {
+ int32_t rec_type ; /* Always 6. */
+ int32_t n_lines ; /* Number of lines of documents. */
+ } ATTRIBUTE((packed)) rec_6;
const char *documents;
size_t n_lines;
struct
{
- int32_t rec_type P;
- int32_t subtype P;
- int32_t elem_size P;
- int32_t n_elem P;
- } vdp_hdr;
+ int32_t rec_type ;
+ int32_t subtype ;
+ int32_t elem_size ;
+ int32_t n_elem ;
+ } ATTRIBUTE((packed)) vdp_hdr;
vdp_hdr.rec_type = 7;
vdp_hdr.subtype = 11;
struct variable *v;
struct
{
- int32_t measure P;
- int32_t width P;
- int32_t align P;
- }
- params;
+ int32_t measure ;
+ int32_t width ;
+ int32_t align ;
+ } ATTRIBUTE((packed)) params;
v = dict_get_var(dict, i);
{
int i;
struct
- {
- int32_t rec_type P;
- int32_t subtype P;
- int32_t elem_size P;
- int32_t n_elem P;
- }
- vls_hdr;
+ {
+ int32_t rec_type ;
+ int32_t subtype ;
+ int32_t elem_size ;
+ int32_t n_elem ;
+ } ATTRIBUTE((packed)) vls_hdr;
struct string vls_length_map;
- ds_init (&vls_length_map, 12 * dict_get_var_cnt (dict));
+ ds_init_empty (&vls_length_map);
vls_hdr.rec_type = 7;
vls_hdr.subtype = 14;
if ( v->width <= MAX_LONG_STRING )
continue;
- ds_printf (&vls_length_map, "%s=%05d", v->short_name, v->width);
- ds_putc (&vls_length_map, '\0');
- ds_putc (&vls_length_map, '\t');
+ ds_put_format (&vls_length_map, "%s=%05d", v->short_name, v->width);
+ ds_put_char (&vls_length_map, '\0');
+ ds_put_char (&vls_length_map, '\t');
}
vls_hdr.n_elem = ds_length (&vls_length_map);
{
struct
{
- int32_t rec_type P;
- int32_t subtype P;
- int32_t elem_size P;
- int32_t n_elem P;
- }
- lv_hdr;
+ int32_t rec_type ;
+ int32_t subtype ;
+ int32_t elem_size ;
+ int32_t n_elem ;
+ } ATTRIBUTE((packed)) lv_hdr;
struct string long_name_map;
size_t i;
- ds_init (&long_name_map, 10 * dict_get_var_cnt (dict));
+ ds_init_empty (&long_name_map);
for (i = 0; i < dict_get_var_cnt (dict); i++)
{
struct variable *v = dict_get_var (dict, i);
if (i)
- ds_putc (&long_name_map, '\t');
- ds_printf (&long_name_map, "%s=%s", v->short_name, v->name);
+ ds_put_char (&long_name_map, '\t');
+ ds_put_format (&long_name_map, "%s=%s", v->short_name, v->name);
}
lv_hdr.rec_type = 7;
{
struct
{
- int32_t rec_type_3 P;
- int32_t subtype_3 P;
- int32_t data_type_3 P;
- int32_t n_elem_3 P;
- int32_t elem_3[8] P;
- int32_t rec_type_4 P;
- int32_t subtype_4 P;
- int32_t data_type_4 P;
- int32_t n_elem_4 P;
- flt64 elem_4[3] P;
- }
- rec_7;
+ int32_t rec_type_3 ;
+ int32_t subtype_3 ;
+ int32_t data_type_3 ;
+ int32_t n_elem_3 ;
+ int32_t elem_3[8] ;
+ int32_t rec_type_4 ;
+ int32_t subtype_4 ;
+ int32_t data_type_4 ;
+ int32_t n_elem_4 ;
+ flt64 elem_4[3] ;
+ } ATTRIBUTE((packed)) rec_7;
/* Components of the version number, from major to minor. */
int version_component[3];
static char *
append_string_max (char *dest, const char *src, const char *end)
{
- int nbytes = min (end - dest, (int) strlen (src));
+ int nbytes = MIN (end - dest, (int) strlen (src));
memcpy (dest, src, nbytes);
return dest + nbytes;
}
w->case_cnt++;
if (!w->needs_translation && !w->compress
- && sizeof (flt64) == sizeof (union value))
+ && sizeof (flt64) == sizeof (union value) && ! w->has_vls )
{
/* Fast path: external and internal representations are the
same and the dictionary is properly ordered. Write
memset(bounce_cur, ' ', v->flt64_cnt * sizeof (flt64));
if (v->width == 0)
- *bounce_cur = case_num (c, v->fv);
- else
{
- buf_copy_rpad((char*)bounce_cur, v->flt64_cnt * sizeof (flt64),
- case_data(c, v->fv)->s,
- v->width);
+ *bounce_cur = case_num (c, v->fv);
+ bounce_cur += v->flt64_cnt;
}
- bounce_cur += v->flt64_cnt;
+ else
+ { int ofs = 0;
+ while (ofs < v->width)
+ {
+ int chunk = MIN (MAX_LONG_STRING, v->width - ofs);
+ int nv = DIV_RND_UP (chunk, sizeof (flt64));
+ buf_copy_rpad ((char *) bounce_cur, nv * sizeof (flt64),
+ case_data (c, v->fv)->s + ofs, chunk);
+ bounce_cur += nv;
+ ofs += chunk;
+ }
+ }
+
}
if (!w->compress)