crc \
crypto/md4 \
crypto/rijndael \
+ crypto/sha1 \
dirname \
dtoastr \
environ \
dnl Checks for libraries.
AC_SYS_LARGEFILE
+AC_CHECK_LIB([gdbm], [gdbm_open])
AC_SEARCH_LIBS([sin], [m])
PSPP_LC_PAPER
include $(top_srcdir)/src/output/automake.mk
include $(top_srcdir)/src/language/automake.mk
include $(top_srcdir)/src/ui/automake.mk
+include $(top_srcdir)/src/processor/automake.mk
+include $(top_srcdir)/src/db/automake.mk
/* PSPP - a program for statistical analysis.
- Copyright (C) 2008, 2009, 2011, 2012 Free Software Foundation, Inc.
+ Copyright (C) 2008, 2009, 2010, 2011, 2012, 2013 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
#include <string.h>
#include "libpspp/array.h"
+#include "libpspp/compiler.h"
#include "libpspp/hash-functions.h"
#include "libpspp/i18n.h"
+#include "libpspp/pxd.h"
#include "gl/xalloc.h"
set. */
struct attribute
{
+ struct attrset *set; /* Containing set, if any. */
struct hmap_node node; /* Used by attrset. */
+
char *name; /* Name. */
char **values; /* Each value. */
size_t n_values; /* Number of values. */
size_t allocated_values; /* Amount of allocated space for values. */
};
+static void attrset_uncache__ (struct attrset *);
+
/* Creates and returns a new attribute with the given NAME. The
attribute initially has no values. (Attributes with no values
cannot be saved to system files, so at least one value should
attribute_create (const char *name)
{
struct attribute *attr = xmalloc (sizeof *attr);
+ attr->set = NULL;
attr->name = xstrdup (name);
attr->values = NULL;
attr->n_values = 0;
{
size_t i;
+ assert (attr->set == NULL);
+
for (i = 0; i < attr->n_values; i++)
free (attr->values[i]);
free (attr->values);
void
attribute_add_value (struct attribute *attr, const char *value)
{
+ attrset_uncache__ (attr->set);
+
if (attr->n_values >= attr->allocated_values)
attr->values = x2nrealloc (attr->values, &attr->allocated_values,
sizeof *attr->values);
void
attribute_set_value (struct attribute *attr, size_t index, const char *value)
{
+ attrset_uncache__ (attr->set);
+
if (index < attr->n_values)
{
/* Replace existing value. */
void
attribute_del_value (struct attribute *attr, size_t index)
{
+ attrset_uncache__ (attr->set);
+
if (index < attr->n_values)
{
free (attr->values[index]);
attr->n_values--;
}
}
+
+struct pxd_object *
+attribute_save (const struct attribute *attr, struct pxd *pxd)
+{
+ struct pxd_builder b;
+ size_t i;
+
+ pxd_builder_init (&b, pxd);
+
+ pxd_builder_put_string (&b, attr->name);
+ pxd_builder_put_size_t (&b, attr->n_values);
+ for (i = 0; i < attr->n_values; i++)
+ pxd_builder_put_string (&b, attr->values[i]);
+
+ return pxd_builder_commit (&b);
+}
+
+struct attribute *
+attribute_load (struct pxd_object *object, const struct pxd *pxd)
+{
+ struct attribute *attr;
+ struct pxd_parser p;
+ size_t n, i;
+ char *name;
+
+ pxd_parser_init (&p, object, pxd);
+
+ name = pxd_parser_get_string (&p);
+ attr = attribute_create (name);
+ free (name);
+
+ n = pxd_parser_get_size_t (&p);
+ for (i = 0; i < n; i++)
+ {
+ char *value = pxd_parser_get_string (&p);
+ attribute_add_value (attr, value);
+ free (value);
+ }
+
+ pxd_parser_destroy (&p);
+
+ return attr;
+}
\f
/* Initializes SET as a new, initially empty attibute set. */
void
{
struct attribute *attr, *next;
+ attrset_uncache__ (set);
+
HMAP_FOR_EACH_SAFE (attr, next, struct attribute, node, &set->map)
- attribute_destroy (attr);
+ {
+ attr->set = NULL;
+ attribute_destroy (attr);
+ }
hmap_destroy (&set->map);
}
}
attrset_add (struct attrset *set, struct attribute *attr)
{
const char *name = attribute_get_name (attr);
+
assert (attrset_lookup (set, name) == NULL);
+ assert (attr->set == NULL);
+
+ attrset_uncache__ (set);
+
+ attr->set = set;
hmap_insert (&set->map, &attr->node, utf8_hash_case_string (name, 0));
}
struct attribute *attr = attrset_lookup (set, name);
if (attr != NULL)
{
+ attrset_uncache__ (set);
hmap_delete (&set->map, &attr->node);
+ attr->set = NULL;
attribute_destroy (attr);
}
}
void
attrset_clear (struct attrset *set)
{
- attrset_destroy (set);
+ if (!hmap_is_empty (&set->map))
+ {
+ attrset_destroy (set);
+ attrset_init (set);
+ }
+}
+
+struct pxd_object *
+attrset_save (const struct attrset *set, struct pxd *pxd)
+{
+ struct attribute *attr;
+ struct pxd_builder b;
+
+ pxd_builder_init (&b, pxd);
+
+ HMAP_FOR_EACH (attr, struct attribute, node, &set->map)
+ pxd_builder_put_link (&b, attribute_save (attr, pxd));
+
+ return pxd_builder_commit (&b);
+}
+
+void
+attrset_load (struct attrset *set,
+ struct pxd_object *object, const struct pxd *pxd)
+{
+ struct pxd_parser p;
+ unsigned int i;
+
+ pxd_parser_init (&p, object, pxd);
+
attrset_init (set);
+ for (i = 0; i < pxd_object_get_n_links (object); i++)
+ {
+ struct pxd_object *attr_obj = pxd_object_get_link (object, i, pxd);
+ struct attribute *attr = attribute_load (attr_obj, pxd);
+ attrset_add (set, attr);
+ }
+
+ pxd_parser_destroy (&p);
}
static struct attribute *iterator_data (struct attrset_iterator *iterator)
else
return NULL;
}
+
+static void
+attrset_uncache__ (struct attrset *set UNUSED)
+{
+ /* XXX */
+}
+
/* PSPP - a program for statistical analysis.
- Copyright (C) 2008, 2011, 2012 Free Software Foundation, Inc.
+ Copyright (C) 2008, 2010, 2011, 2012 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
#include "libpspp/hmapx.h"
+struct pxd;
+
/* This header supports custom attribute of the sort maintained
by the DATAFILE ATTRIBUTE and VARIABLE ATTRIBUTE commands.
void attribute_del_value (struct attribute *, size_t index);
size_t attribute_get_n_values (const struct attribute *);
+struct pxd_object *attribute_save (const struct attribute *, struct pxd *);
+struct attribute *attribute_load (struct pxd_object *, const struct pxd *);
+
struct attrset
{
struct hmap map;
void attrset_delete (struct attrset *, const char *);
void attrset_clear (struct attrset *);
+struct pxd_object *attrset_save (const struct attrset *, struct pxd *);
+void attrset_load (struct attrset *, struct pxd_object *, const struct pxd *);
+
struct attrset_iterator
{
struct hmap_node *node;
src/data/case.h \
src/data/case-tmpfile.c \
src/data/case-tmpfile.h \
+ src/data/column.h \
src/data/csv-file-writer.c \
src/data/csv-file-writer.h \
src/data/data-in.c \
src/data/por-file-writer.h \
src/data/psql-reader.c \
src/data/psql-reader.h \
+ src/data/relation.h \
src/data/session.c \
src/data/session.h \
src/data/settings.c \
src/data/vardict.h \
src/data/variable.h \
src/data/variable.c \
+ src/data/vec.h \
src/data/vector.c \
src/data/vector.h
--- /dev/null
+/* PSPP - a program for statistical analysis.
+ Copyright (C) 2012 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
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef DATA_COLUMN_H
+#define DATA_COLUMN_H 1
+
+#include "libpspp/compiler.h"
+#include "data/case.h"
+#include "data/value.h"
+
+struct pxd;
+
+struct column *column_create (struct pxd *, int width);
+bool column_destroy (struct column *);
+
+int column_get_width (const struct column *);
+
+void column_read (const struct column *, casenumber, union value *);
+void column_write (struct column *, casenumber, const union value *);
+void column_append (struct column *, casenumber, const union value *);
+
+struct column *column_clone (const struct column *);
+void column_split (struct column *, struct column **, struct column **);
+struct column *column_rename (struct column *);
+void column_swap (struct column *, struct column *);
+
+bool column_is_empty (struct column *);
+
+bool column_error (const struct column *);
+void column_force_error (struct column *);
+const struct taint *column_get_taint (const struct column *);
+
+casenumber column_get_size (struct column *);
+casenumber column_count (const struct column *);
+void column_truncate (struct column *, casenumber);
+
+casenumber column_advance (struct column *, casenumber);
+
+struct pxd_object *column_save (const struct column *, struct pxd *);
+struct column *column_load (struct pxd_object *, const struct pxd *);
+
+#endif /* data/column.h */
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006, 2007, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2007, 2009-2015 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
#include "libpspp/message.h"
#include "libpspp/misc.h"
#include "libpspp/pool.h"
+#include "libpspp/pxd.h"
#include "libpspp/str.h"
#include "libpspp/string-array.h"
static void dict_unset_split_var (struct dictionary *, struct variable *);
static void dict_unset_mrset_var (struct dictionary *, struct variable *);
+static void dict_uncache (struct dictionary *);
+
/* Returns the encoding for data in dictionary D. The return value is a
nonnull string that contains an IANA character set name. */
const char *
void
dict_clear (struct dictionary *d)
{
+ dict_uncache (d);
+
/* FIXME? Should we really clear case_limit, label, documents?
Others are necessarily cleared by deleting all the variables.*/
while (d->var_cnt > 0 )
{
return vardict - vardict->dict->var;
}
+\f
+static struct pxd_object *
+vardict_info_save (const struct vardict_info *vardict, struct pxd *pxd)
+{
+ struct pxd_builder b;
+
+ pxd_builder_init (&b, pxd);
+ pxd_builder_put_s32 (&b, vardict->case_index);
+ pxd_builder_put_link (&b, var_save (vardict->var, pxd));
+ return pxd_builder_commit (&b);
+}
+
+struct pxd_object *
+dict_save (const struct dictionary *dict, struct pxd *pxd)
+{
+ struct pxd_array_builder ab;
+ struct pxd_object *vars;
+ struct pxd_builder b;
+ size_t i;
+
+ pxd_array_builder_init (&ab, pxd);
+ for (i = 0; i < dict->var_cnt; i++)
+ pxd_array_builder_add (&ab, vardict_info_save (&dict->var[i], pxd));
+ vars = pxd_array_builder_commit (&ab);
+
+ pxd_builder_init (&b, pxd);
+ pxd_builder_put_link (&b, vars);
+ pxd_builder_put_u32 (&b, dict->next_value_idx);
+
+ pxd_builder_put_size_t (&b, dict->split_cnt);
+ for (i = 0; i < dict->split_cnt; i++)
+ pxd_builder_put_u32 (&b, var_get_dict_index (dict->split[i]));
+
+ pxd_builder_put_s32 (&b,
+ (dict->weight == NULL ? -1
+ : var_get_dict_index (dict->weight)));
+ pxd_builder_put_s32 (&b,
+ (dict->filter == NULL ? -1
+ : var_get_dict_index (dict->filter)));
+
+ pxd_builder_put_casenumber (&b, dict->case_limit);
+ pxd_builder_put_string (&b, dict->label != NULL ? dict->label : "");
+ //XXX pxd_builder_put_string (&b, ds_cstr (&dict->documents));
+
+ pxd_builder_put_size_t (&b, dict->vector_cnt);
+ for (i = 0; i < dict->split_cnt; i++)
+ pxd_builder_put_link (&b, vector_save (dict->vector[i], pxd));
+
+ pxd_builder_put_link (&b, attrset_save (&dict->attributes, pxd));
+
+ pxd_builder_put_size_t (&b, dict->n_mrsets);
+ for (i = 0; i < dict->n_mrsets; i++)
+ pxd_builder_put_link (&b, mrset_save (dict->mrsets[i], pxd));
+
+ pxd_builder_put_string (&b, dict->encoding ? dict->encoding : "");
+
+ return pxd_builder_commit (&b);
+}
+
+static void
+vardict_info_load (struct dictionary *dict, struct pxd_object *obj,
+ const struct pxd *pxd)
+{
+ struct pxd_parser p;
+ struct variable *var;
+ int case_index;
+
+ pxd_parser_init (&p, obj, pxd);
+ case_index = pxd_parser_get_u32 (&p);
+ var = add_var (dict, var_load (pxd_parser_get_link (&p), pxd));
+ var_get_vardict (var)->case_index = case_index;
+ pxd_parser_destroy (&p);
+}
+
+struct dictionary *
+dict_load (struct pxd_object *obj, const struct pxd *pxd)
+{
+ struct dictionary *dict;
+ struct pxd_array array;
+ struct pxd_parser p;
+ char *encoding;
+ int weight_idx;
+ int filter_idx;
+ size_t i;
+
+ pxd_parser_init (&p, obj, pxd);
+
+ encoding = pxd_parser_get_string (&p);
+ dict = dict_create (encoding);
+ free (encoding);
+
+ pxd_array_init (&array, pxd_parser_get_link (&p), pxd);
+ for (i = 0; i < pxd_array_size (&array); i++)
+ vardict_info_load (dict, pxd_array_get (&array, i), pxd);
+ pxd_array_destroy (&array);
+
+ dict->next_value_idx = pxd_parser_get_u32 (&p);
+
+ dict->split_cnt = pxd_parser_get_size_t (&p);
+ if (dict->split_cnt > 0)
+ {
+ dict->split = xnmalloc (dict->split_cnt, sizeof *dict->split);
+ for (i = 0; i < dict->split_cnt; i++)
+ dict->split[i] = dict_get_var (dict, i);
+ }
+
+ weight_idx = pxd_parser_get_s32 (&p);
+ if (weight_idx >= 0)
+ dict_set_weight (dict, dict_get_var (dict, weight_idx));
+
+ filter_idx = pxd_parser_get_s32 (&p);
+ if (filter_idx >= 0)
+ dict_set_filter (dict, dict_get_var (dict, filter_idx));
+
+ dict->case_limit = pxd_parser_get_casenumber (&p);
+
+ dict->label = pxd_parser_get_string (&p);
+ if (dict->label[0] == '\0')
+ dict_set_label (dict, NULL);
+
+#if 0 /* XXX */
+ documents = pxd_parser_get_string (&p);
+ if (documents[0] != '\0')
+ ds_assign_cstr (&dict->documents, documents);
+ free (documents);
+#endif
+
+ dict->vector_cnt = pxd_parser_get_size_t (&p);
+ if (dict->vector_cnt > 0)
+ {
+ dict->vector = xnmalloc (dict->vector_cnt, sizeof *dict->vector);
+ for (i = 0; i < dict->vector_cnt; i++)
+ dict->vector[i] = vector_load (pxd_parser_get_link (&p), pxd, dict);
+ }
+
+ attrset_destroy (&dict->attributes);
+ attrset_load (&dict->attributes, pxd_parser_get_link (&p), pxd);
+
+ dict->n_mrsets = pxd_parser_get_size_t (&p);
+ if (dict->n_mrsets > 0)
+ {
+ dict->mrsets = xnmalloc (dict->n_mrsets, sizeof *dict->mrsets);
+ for (i = 0; i < dict->n_mrsets; i++)
+ dict->mrsets[i] = mrset_load (pxd_parser_get_link (&p), pxd, dict);
+ }
+
+ dict->encoding = pxd_parser_get_string (&p);
+ if (dict->encoding[0] == '\0')
+ {
+ free (dict->encoding);
+ dict->encoding = NULL;
+ }
+
+ pxd_parser_destroy (&p);
+
+ return dict;
+}
+
+static void
+dict_uncache (struct dictionary *dict UNUSED)
+{
+}
+
#include "data/case.h"
#include "data/dict-class.h"
-struct string;
struct ccase;
+struct pxd;
+struct string;
/* Creating dictionaries. */
struct dictionary *dict_create (const char *encoding);
struct dictionary *dict_clone (const struct dictionary *);
-
/* Clearing and destroying dictionaries. */
void dict_clear (struct dictionary *);
void dict_destroy (struct dictionary *);
/* Debug use only. */
void dict_dump (const struct dictionary *);
+/* Saving and loading. */
+struct pxd_object *dict_save (const struct dictionary *, struct pxd *);
+struct dictionary *dict_load (struct pxd_object *, const struct pxd *);
+
#endif /* data/dictionary.h */
fmt->d = decimals;
fmt_fix (fmt, use);
}
+
+unsigned int
+fmt_to_uint (const struct fmt_spec *fmt)
+{
+ return (fmt_to_io (fmt->type) << 24) | (fmt->w << 8) | fmt->d;
+}
+
+bool
+fmt_from_uint (struct fmt_spec *fmt, unsigned int uint)
+{
+ if (!fmt_from_io (uint >> 24, &fmt->type))
+ return false;
+ fmt->w = (uint >> 8) & 0xffff;
+ fmt->d = uint & 0xff;
+ return true;
+}
\f
/* Describes a display format. */
struct fmt_desc
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006, 2010, 2011, 2012 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2011-2012 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
void fmt_change_width (struct fmt_spec *, int width, enum fmt_use);
void fmt_change_decimals (struct fmt_spec *, int decimals, enum fmt_use);
+unsigned int fmt_to_uint (const struct fmt_spec *);
+bool fmt_from_uint (struct fmt_spec *, unsigned int);
+
/* Format types. */
bool is_fmt_type (enum fmt_type);
/* PSPP - a program for statistical analysis.
- Copyright (C) 2005, 2009, 2011, 2013 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2009, 2011-2015 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
#include "data/variable.h"
#include "libpspp/assertion.h"
#include "libpspp/cast.h"
+#include "libpspp/pxd.h"
#include "libpspp/str.h"
/* Types of user-missing values.
assert (mv->width > 0);
return class & MV_USER && is_str_user_missing (mv, s);
}
+
+struct pxd_object *
+mv_save (const struct missing_values *mv, struct pxd *pxd)
+{
+ struct pxd_builder b;
+ int i;
+
+ pxd_builder_init (&b, pxd);
+
+ pxd_builder_put_u16 (&b, mv->width);
+ pxd_builder_put_u16 (&b, mv->type);
+ for (i = 0; i < 3; i++)
+ if (using_element (mv->type, i))
+ pxd_builder_put_value (&b, &mv->values[i], mv->width);
+
+ return pxd_builder_commit (&b);
+}
+
+void
+mv_load (struct missing_values *mv, struct pxd_object *object,
+ const struct pxd *pxd)
+{
+ struct pxd_parser p;
+ int i;
+
+ pxd_parser_init (&p, object, pxd);
+
+ mv->width = pxd_parser_get_u16 (&p);
+ mv->type = pxd_parser_get_u16 (&p);
+ for (i = 0; i < 3; i++)
+ if (using_element (mv->type, i))
+ pxd_parser_get_value (&p, &mv->values[i], mv->width);
+ else
+ value_init (&mv->values[i], mv->width);
+
+ pxd_parser_destroy (&p);
+}
/* PSPP - a program for statistical analysis.
- Copyright (C) 2005, 2009, 2013 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2009, 2013-2015 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
#include "data/value.h"
struct pool;
+struct pxd;
/* Missing values for long string variables after the first
MV_MAX_STRING bytes must be all spaces. */
bool mv_add_range (struct missing_values *, double low, double high);
void mv_pop_range (struct missing_values *, double *low, double *high);
+/* Saving and loading. */
+struct pxd_object *mv_save (const struct missing_values *, struct pxd *);
+void mv_load (struct missing_values *,
+ struct pxd_object *, const struct pxd *);
+
#endif /* data/missing-values.h */
/* PSPP - a program for statistical analysis.
- Copyright (C) 2010, 2011 Free Software Foundation, Inc.
+ Copyright (C) 2010, 2011, 2012 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
#include "data/val-type.h"
#include "data/variable.h"
#include "libpspp/message.h"
+#include "libpspp/pxd.h"
#include "gl/xalloc.h"
return true;
}
+
+struct pxd_object *
+mrset_save (const struct mrset *mrset, struct pxd *pxd)
+{
+ struct pxd_builder b;
+ size_t i;
+
+ pxd_builder_init (&b, pxd);
+
+ pxd_builder_put_string (&b, mrset->name);
+ pxd_builder_put_string (&b, mrset->label != NULL ? mrset->label : "");
+ pxd_builder_put_u8 (&b, mrset->type);
+
+ pxd_builder_put_size_t (&b, mrset->n_vars);
+ for (i = 0; i < mrset->n_vars; i++)
+ pxd_builder_put_string (&b, var_get_name (mrset->vars[i]));
+
+ if (mrset->type == MRSET_MD)
+ {
+ pxd_builder_put_u8 (&b, mrset->cat_source);
+ pxd_builder_put_bool (&b, mrset->label_from_var_label);
+ pxd_builder_put_u16 (&b, mrset->width);
+ pxd_builder_put_value (&b, &mrset->counted, mrset->width);
+ }
+
+ return pxd_builder_commit (&b);
+}
+
+struct mrset *
+mrset_load (struct pxd_object *object, const struct pxd *pxd,
+ const struct dictionary *dict)
+{
+ struct pxd_parser p;
+ struct mrset *mrset;
+ size_t i;
+
+ mrset = xzalloc (sizeof *mrset);
+
+ pxd_parser_init (&p, object, pxd);
+
+ mrset->name = pxd_parser_get_string (&p);
+
+ mrset->label = pxd_parser_get_string (&p);
+ if (mrset->label[0] == '\0')
+ {
+ free (mrset->label);
+ mrset->label = NULL;
+ }
+
+ mrset->type = pxd_parser_get_u8 (&p);
+
+ mrset->n_vars = pxd_parser_get_size_t (&p);
+ mrset->vars = xmalloc (mrset->n_vars * sizeof *mrset->vars);
+ for (i = 0; i < mrset->n_vars; i++)
+ {
+ char *name = pxd_parser_get_string (&p);
+ mrset->vars[i] = dict_lookup_var_assert (dict, name);
+ free (name);
+ }
+
+ if (mrset->type == MRSET_MD)
+ {
+ mrset->cat_source = pxd_parser_get_u8 (&p);
+ mrset->label_from_var_label = pxd_parser_get_bool (&p);
+ mrset->width = pxd_parser_get_u16 (&p);
+ pxd_parser_get_value (&p, &mrset->counted, mrset->width);
+ }
+ else
+ value_init (&mrset->counted, 0);
+
+ return mrset;
+}
#include "data/value.h"
struct dictionary;
+struct pxd;
/* Type of a multiple response set. */
enum mrset_type
bool mrset_ok (const struct mrset *, const struct dictionary *);
+struct pxd_object *mrset_save (const struct mrset *, struct pxd *);
+struct mrset *mrset_load (struct pxd_object *, const struct pxd *,
+ const struct dictionary *);
+
#endif /* data/mrset.h */
--- /dev/null
+/* PSPP - a program for statistical analysis.
+ Copyright (C) 2012 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
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef DATA_RELATION_H
+#define DATA_RELATION_H 1
+
+#include "libpspp/compiler.h"
+#include "data/column.h"
+
+struct relation_column
+ {
+ struct hmap_node hmap_node;
+ const char *name;
+ struct column *column;
+ };
+
+struct relation *relation_create (void);
+bool relation_destroy (struct relation *);
+
+void relation_add_column (struct relation *,
+ const char *name, struct column *);
+void relation_delete_column (struct relation *, const char *name);
+void relation_rename_column (struct relation *, const char *old_name,
+ const char *new_name);
+
+const struct column *relation_get_column (const struct relation *,
+ const char *name);
+struct column *relation_get_column_rw (struct relation *, const char *name);
+
+struct pxd_object *relation_save (const struct relation *, struct pxd *);
+struct relation *relation_load (struct pxd_object *, const struct pxd *);
+
+#endif /* data/relation.h */
#include "libpspp/hmap.h"
#include "libpspp/intern.h"
#include "libpspp/message.h"
+#include "libpspp/pxd.h"
#include "libpspp/str.h"
#include "gl/xalloc.h"
+static void val_labs_uncache__ (struct val_labs *);
+static void val_lab_uncache__ (struct val_lab *);
+
/* Creates and returns a new, empty set of value labels with the
given WIDTH. */
struct val_labs *
HMAP_FOR_EACH (label, struct val_lab, node, &vls->labels)
value_resize (&label->value, vls->width, new_width);
}
- vls->width = new_width;
+ if (vls->width != new_width)
+ {
+ vls->width = new_width;
+ val_labs_uncache__ (vls);
+ }
}
/* Destroys VLS. */
{
if (vls != NULL)
{
+ val_labs_uncache__ (vls);
val_labs_clear (vls);
hmap_destroy (&vls->labels);
free (vls);
}
}
+static void
+val_lab_clear (struct val_lab *lab, int width)
+{
+ val_lab_uncache__ (lab);
+ value_destroy (&lab->value, width);
+ intern_unref (lab->label);
+}
+
/* Removes all the value labels from VLS. */
void
val_labs_clear (struct val_labs *vls)
HMAP_FOR_EACH_SAFE (label, next, struct val_lab, node, &vls->labels)
{
+ val_lab_clear (label, vls->width);
hmap_delete (&vls->labels, &label->node);
- value_destroy (&label->value, vls->width);
- intern_unref (label->label);
- intern_unref (label->escaped_label);
free (label);
}
}
}
}
+static void
+val_labs_uncache__ (struct val_labs *vls UNUSED)
+{
+}
+
+static void
+val_lab_uncache__ (struct val_lab *vl UNUSED)
+{
+}
+
+static struct pxd_object *
+val_lab_save (const struct val_lab *vl, int width, struct pxd *pxd)
+{
+ struct pxd_builder b;
+
+ pxd_builder_init (&b, pxd);
+
+ pxd_builder_put_value (&b, &vl->value, width);
+ pxd_builder_put_interned_string (&b, vl->label);
+
+ return pxd_builder_commit (&b);
+}
+
+struct pxd_object *
+val_labs_save (const struct val_labs *vls, struct pxd *pxd)
+{
+ struct val_lab *label;
+ struct pxd_builder b;
+
+ pxd_builder_init (&b, pxd);
+
+ pxd_builder_put_u32 (&b, vls->width);
+ HMAP_FOR_EACH (label, struct val_lab, node, &vls->labels)
+ pxd_builder_put_link (&b, val_lab_save (label, vls->width, pxd));
+
+ return pxd_builder_commit (&b);
+}
+
+static struct val_lab *
+val_lab_load (struct pxd_object *object, const struct pxd *pxd, int width)
+{
+ struct pxd_parser p;
+ struct val_lab *vl;
+
+ pxd_parser_init (&p, object, pxd);
+
+ vl = xmalloc (sizeof *vl);
+ pxd_parser_get_value (&p, &vl->value, width);
+ vl->label = pxd_parser_get_interned_string (&p);
+
+ pxd_parser_destroy (&p);
+
+ return vl;
+}
+
+struct val_labs *
+val_labs_load (struct pxd_object *object, const struct pxd *pxd)
+{
+ struct val_labs *vls;
+ struct pxd_parser p;
+ unsigned int i;
+ int width;
+
+ pxd_parser_init (&p, object, pxd);
+ width = pxd_parser_get_u32 (&p);
+
+ vls = val_labs_create (width);
+ for (i = 0; i < pxd_object_get_n_links (object); i++)
+ {
+ struct pxd_object *lab_obj = pxd_object_get_link (object, i, pxd);
+ struct val_lab *lab = val_lab_load (lab_obj, pxd, width);
+ hmap_insert (&vls->labels, &lab->node,
+ value_hash (&lab->value, width, 0));
+ }
+
+ pxd_parser_destroy (&p);
+
+ return vls;
+}
+\f
static void
do_add_val_lab (struct val_labs *vls, const union value *value,
const char *escaped_label)
struct val_lab *vl = val_labs_lookup (vls, value);
if (vl != NULL)
{
+ val_lab_uncache__ (vl);
intern_unref (vl->label);
intern_unref (vl->escaped_label);
set_label (vl, label);
void
val_labs_remove (struct val_labs *vls, struct val_lab *label)
{
+ val_lab_clear (label, vls->width);
hmap_delete (&vls->labels, &label->node);
- value_destroy (&label->value, vls->width);
- intern_unref (label->label);
- intern_unref (label->escaped_label);
free (label);
}
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2009, 2011, 2012 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2009-2012 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
#include "data/value.h"
#include "libpspp/hmap.h"
+struct pxd;
+
/* One value label.
A value label is normally part of a struct val_labs (see
struct val_lab
{
struct hmap_node node; /* Node in hash map. */
+ struct pxd_object *cache; /* Object cache. */
union value value; /* The value being labeled. */
const char *label; /* An interned string. */
const char *escaped_label; /* An interned string. */
/* A set of value labels. */
struct val_labs
{
+ struct pxd_object *cache; /* Object cache. */
int width; /* 0=numeric, otherwise string width. */
struct hmap labels; /* Hash table of `struct val_lab's. */
};
unsigned int val_labs_hash (const struct val_labs *, unsigned int basis);
bool val_labs_equal (const struct val_labs *, const struct val_labs *);
+/* Saving and loading. */
+struct pxd_object *val_labs_save (const struct val_labs *, struct pxd *);
+struct val_labs *val_labs_load (struct pxd_object *, const struct pxd *);
+
#endif /* data/value-labels.h */
/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2009-2015 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
#include "libpspp/compiler.h"
#include "libpspp/hash-functions.h"
#include "libpspp/i18n.h"
+#include "libpspp/intern.h"
#include "libpspp/message.h"
#include "libpspp/misc.h"
+#include "libpspp/pxd.h"
#include "libpspp/str.h"
#include "gl/minmax.h"
/* Custom attributes. */
struct attrset attributes;
};
+
+static void var_uncache (struct variable *);
\f
static void var_set_print_format_quiet (struct variable *v, const struct fmt_spec *print);
if (v != NULL)
{
assert (!var_has_vardict (v));
+ var_uncache (v);
mv_destroy (&v->miss);
var_clear_short_names (v);
val_labs_destroy (v->val_labs);
v->name = xstrdup (name);
ds_destroy (&v->name_and_label);
ds_init_empty (&v->name_and_label);
+ var_uncache (v);
}
/* Sets V's name to NAME, a UTF-8 encoded string.
if (traits != 0)
dict_var_changed (v, traits, ov);
+
+ var_uncache (v);
}
/* Changes the width of V to NEW_WIDTH.
static void
var_set_value_labels_quiet (struct variable *v, const struct val_labs *vls)
{
- val_labs_destroy (v->val_labs);
- v->val_labs = NULL;
+ bool changed = false;
+
+ if (v->val_labs != NULL)
+ {
+ val_labs_destroy (v->val_labs);
+ v->val_labs = NULL;
+ changed = true;
+ }
if (vls != NULL)
{
v->val_labs = val_labs_clone (vls);
val_labs_set_width (v->val_labs, v->width);
}
+
+ if (changed)
+ var_uncache (v);
}
var_add_value_label (struct variable *v,
const union value *value, const char *label)
{
+ bool changed;
+
alloc_value_labels (v);
- return val_labs_add (v->val_labs, value, label);
+
+ changed = val_labs_add (v->val_labs, value, label);
+ if (changed)
+ var_uncache (v);
+ return changed;
}
/* Adds or replaces a value label with the given VALUE and UTF-8 encoded LABEL
{
alloc_value_labels (v);
val_labs_replace (v->val_labs, value, label);
+ var_uncache (v);
}
/* Removes V's value labels, if any. */
{
assert (fmt_check_width_compat (print, v->width));
v->print = *print;
+ var_uncache (v);
}
}
struct variable *ov = var_clone (v);
var_set_print_format_quiet (v, print);
dict_var_changed (v, VAR_TRAIT_PRINT_FORMAT, ov);
+ var_uncache (v);
}
/* Returns V's write format specification. */
{
assert (fmt_check_width_compat (write, v->width));
v->write = *write;
+ var_uncache (v);
}
}
ds_destroy (&v->name_and_label);
ds_init_empty (&v->name_and_label);
+ var_uncache (v);
}
-
-
/* Sets V's variable label to UTF-8 encoded string LABEL, stripping off leading
and trailing white space. If LABEL is a null pointer or if LABEL is an
empty string (after stripping white space), then V's variable label (if any)
v->measure = measure;
}
-
/* Sets V's measurement level to MEASURE. */
void
var_set_measure (struct variable *v, enum measure measure)
void
var_clear_short_names (struct variable *v)
{
- size_t i;
-
- for (i = 0; i < v->short_name_cnt; i++)
- free (v->short_names[i]);
- free (v->short_names);
- v->short_names = NULL;
- v->short_name_cnt = 0;
+ if (v->short_name_cnt > 0)
+ {
+ size_t i;
+
+ for (i = 0; i < v->short_name_cnt; i++)
+ free (v->short_names[i]);
+ free (v->short_names);
+ v->short_names = NULL;
+ v->short_name_cnt = 0;
+ var_uncache (v);
+ }
}
\f
/* Relationship with dictionary. */
{
attrset_destroy (&v->attributes);
attrset_clone (&v->attributes, attrs);
+ var_uncache (v);
}
/* Replaces variable V's attributes set by a copy of ATTRS. */
{
v->vardict = NULL;
}
+\f
+struct pxd_object *
+var_save (const struct variable *var, struct pxd *pxd)
+{
+ struct pxd_builder b;
+ size_t i;
+
+ pxd_builder_init (&b, pxd);
+
+ pxd_builder_put_string (&b, var->name);
+ pxd_builder_put_u16 (&b, var->width);
+ pxd_builder_put_link (&b, mv_save (&var->miss, pxd));
+ pxd_builder_put_u32 (&b, fmt_to_uint (&var->print));
+ pxd_builder_put_u32 (&b, fmt_to_uint (&var->write));
+
+ if (var_has_value_labels (var))
+ {
+ pxd_builder_put_bool (&b, true);
+ pxd_builder_put_link (&b, val_labs_save (var->val_labs, pxd));
+ }
+ else
+ pxd_builder_put_bool (&b, false);
+
+ pxd_builder_put_string (&b, var->label != NULL ? var->label : "");
+
+ pxd_builder_put_u8 (&b, var->measure);
+ pxd_builder_put_u32 (&b, var->display_width);
+ pxd_builder_put_u8 (&b, var->alignment);
+
+ pxd_builder_put_bool (&b, var->leave);
+
+ pxd_builder_put_size_t (&b, var->short_name_cnt);
+ for (i = 0; i < var->short_name_cnt; i++)
+ pxd_builder_put_string (&b, var->short_names[i]);
+
+ pxd_builder_put_link (&b, attrset_save (&var->attributes, pxd));
+
+ return pxd_builder_commit (&b);
+}
+
+struct variable *
+var_load (struct pxd_object *object, const struct pxd *pxd)
+{
+ struct fmt_spec print, write;
+ struct missing_values mv;
+ struct variable *var;
+ struct pxd_parser p;
+ char *label;
+ char *name;
+ int width;
+ size_t i;
+
+#if 0
+ cached_var = pxd_cache_search (&var_cache, pxd_object_id (object));
+ if (cached_var != NULL)
+ {
+ size_t n;
+
+ var = var_clone (cached_var);
+
+ /* var_clone() doesn't copy short names, so we need to. */
+ n = cached_var->short_name_cnt;
+ if (n > 0)
+ {
+ size_t i;
+
+ var->short_name_cnt = n;
+ var->short_names = xmalloc (n * sizeof *var->short_names);
+ for (i = 0; i < n; i++)
+ var->short_names[i] = xstrdup (cached_var->short_names[i]);
+ }
+
+ return var;
+ }
+#endif
+
+ pxd_parser_init (&p, object, pxd);
+
+ name = pxd_parser_get_string (&p);
+ width = pxd_parser_get_u16 (&p);
+ var = var_create (name, width);
+
+ mv_load (&mv, pxd_parser_get_link (&p), pxd);
+ var_set_missing_values (var, &mv);
+ mv_destroy (&mv);
+
+ fmt_from_uint (&print, pxd_parser_get_u32 (&p));
+ var_set_print_format (var, &print);
+
+ fmt_from_uint (&write, pxd_parser_get_u32 (&p));
+ var_set_write_format (var, &write);
+
+ if (pxd_parser_get_bool (&p))
+ var->val_labs = val_labs_load (pxd_parser_get_link (&p), pxd);
+
+ label = pxd_parser_get_string (&p);
+ if (label[0])
+ var_set_label (var, label);
+ free (label);
+
+ var->measure = pxd_parser_get_u8 (&p);
+ var->display_width = pxd_parser_get_u32 (&p);
+ var->alignment = pxd_parser_get_u8 (&p);
+
+ var->leave = pxd_parser_get_bool (&p);
+
+ var->short_name_cnt = pxd_parser_get_size_t (&p);
+ var->short_names = xmalloc (var->short_name_cnt * sizeof *var->short_names);
+ for (i = 0; i < var->short_name_cnt; i++)
+ var->short_names[i] = pxd_parser_get_string (&p);
+
+ attrset_load (&var->attributes, pxd_parser_get_link (&p), pxd);
+
+ pxd_parser_destroy (&p);
+
+ return var;
+}
+
+static void
+var_uncache (struct variable *var UNUSED)
+{
+}
/* Function types. */
typedef bool var_predicate_func (const struct variable *);
+/* Saving and loading. */
+struct pxd_object *var_save (const struct variable *, struct pxd *);
+struct variable *var_load (struct pxd_object *, const struct pxd *);
+
#endif /* data/variable.h */
--- /dev/null
+/* PSPP - a program for statistical analysis.
+ Copyright (C) 2013 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
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef DATA_VEC_H
+#define DATA_VEC_H 1
+
+struct vec;
+
+struct vec *vec_new (int width);
+
+struct vec *vec_ref (const struct vec *);
+void vec_unref (struct vec *);
+
+int vec_width (const struct vec *);
+casenumber vec_count (const struct vec *);
+
+void vec_get (const struct vec *, casenumber, union value *);
+
+struct vec *vec_put (struct vec *, casenumber, const union value *);
+struct vec *vec_insert (struct vec *, casenumber before,
+ const union value *);
+struct vec *vec_delete (struct vec *, casenumber start, casenumber n);
+
+struct vec *vec_head (struct vec *, casenumber n);
+struct vec *vec_tail (struct vec *, casenumber n);
+
+struct vec *vec_delete_head (struct vec *, casenumber n);
+struct vec *vec_delete_tail (struct vec *, casenumber n);
+struct vec *vec_range (struct vec *, casenumber first, casenumber last);
+
+struct pxd_object *vec_save (const struct vec *, struct pxd *);
+struct vec *vec_load (struct pxd_object *, const struct pxd *);
+
+#endif /* data/vec.h */
#include "data/dictionary.h"
#include "data/identifier.h"
+#include "data/variable.h"
#include "libpspp/assertion.h"
#include "libpspp/i18n.h"
+#include "libpspp/pxd.h"
#include "libpspp/str.h"
#include "gl/xalloc.h"
assert (var_cnt > 0);
assert (id_is_plausible (name, false));
+ vector->name = xstrdup (name);
vector->name = xstrdup (name);
vector->vars = xmemdup (vars, var_cnt * sizeof *vector->vars);
return utf8_strcasecmp (a->name, b->name);
}
+struct pxd_object *
+vector_save (const struct vector *vector, struct pxd *pxd)
+{
+ struct pxd_builder b;
+ size_t i;
+
+ pxd_builder_init (&b, pxd);
+
+ pxd_builder_put_string (&b, vector->name);
+
+ pxd_builder_put_size_t (&b, vector->var_cnt);
+ for (i = 0; i < vector->var_cnt; i++)
+ pxd_builder_put_size_t (&b, var_get_dict_index (vector->vars[i]));
+
+ return pxd_builder_commit (&b);
+}
+
+struct vector *
+vector_load (struct pxd_object *object, const struct pxd *pxd,
+ const struct dictionary *dict)
+{
+ struct pxd_parser p;
+ struct vector *vector;
+ size_t i;
+
+ vector = xzalloc (sizeof *vector);
+
+ pxd_parser_init (&p, object, pxd);
+
+ vector->name = pxd_parser_get_string (&p);
+
+ vector->var_cnt = pxd_parser_get_size_t (&p);
+ vector->vars = xmalloc (vector->var_cnt * sizeof *vector->vars);
+ for (i = 0; i < vector->var_cnt; i++)
+ vector->vars[i] = dict_get_var (dict, pxd_parser_get_size_t (&p));
+
+ return vector;
+}
/* PSPP - a program for statistical analysis.
- Copyright (C) 2006, 2010, 2011 Free Software Foundation, Inc.
+ Copyright (C) 2006, 2010-2012 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
#define DATA_VECTOR_H 1
#include <stddef.h>
-#include "data/variable.h"
+#include "data/val-type.h"
struct dictionary;
+struct pxd;
+struct variable;
struct vector *vector_create (const char *name,
struct variable **var, size_t var_cnt);
int compare_vector_ptrs_by_name (const void *a_, const void *b_);
+struct pxd_object *vector_save (const struct vector *, struct pxd *);
+struct vector *vector_load (struct pxd_object *, const struct pxd *,
+ const struct dictionary *);
+
#endif /* data/vector.h */
--- /dev/null
+EXTRA_DIST += src/db/db.c
--- /dev/null
+/* PSPP - a program for statistical analysis.
+ Copyright (C) 2012 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
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+int
+main (int argc, char **argv)
+{
+ set_program_name (argv[0]);
+
+
+}
/* PSPP - a program for statistical analysis.
- Copyright (C) 2006, 2009, 2010, 2011, 2013 Free Software Foundation, Inc.
+ Copyright (C) 2006, 2009, 2010, 2011, 2013, 2015 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
DEF_CMD (S_INITIAL | S_DATA | S_INPUT_PROGRAM | S_FILE_TYPE, 0, "DATA LIST", cmd_data_list)
DEF_CMD (S_INITIAL | S_DATA, 0, "GET", cmd_get)
DEF_CMD (S_INITIAL | S_DATA, 0, "GET DATA", cmd_get_data)
+DEF_CMD (S_INITIAL | S_DATA, 0, "GET SESSION", cmd_get_session)
DEF_CMD (S_INITIAL | S_DATA, 0, "IMPORT", cmd_import)
DEF_CMD (S_INITIAL | S_DATA, 0, "INPUT PROGRAM", cmd_input_program)
DEF_CMD (S_INITIAL | S_DATA, 0, "MATCH FILES", cmd_match_files)
DEF_CMD (S_INITIAL | S_DATA, 0, "DATASET COPY", cmd_dataset_copy)
DEF_CMD (S_INITIAL | S_DATA, 0, "DATASET NAME", cmd_dataset_name)
DEF_CMD (S_INITIAL | S_DATA, 0, "DATASET DISPLAY", cmd_dataset_display)
+DEF_CMD (S_INITIAL | S_DATA, 0, "SAVE SESSION", cmd_save_session)
/* Transformations and utilities that may appear after active
file definition or within INPUT PROGRAM. */
src/language/data-io/print.c \
src/language/data-io/save-translate.c \
src/language/data-io/save.c \
+ src/language/data-io/session.c \
src/language/data-io/trim.c \
src/language/data-io/trim.h
--- /dev/null
+/* PSPP - a program for statistical analysis.
+ Copyright (C) 2010, 2012 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
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#include "data/case.h"
+#include "data/dataset.h"
+#include "data/dictionary.h"
+#include "language/command.h"
+#include "language/data-io/file-handle.h"
+#include "language/lexer/lexer.h"
+#include "libpspp/pxd.h"
+
+#include "gl/xalloc.h"
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+
+int
+cmd_save_session (struct lexer *lexer, struct dataset *ds)
+{
+ struct file_handle *handle;
+ struct pxd_object *obj;
+ struct pxd_id root;
+ struct pxd *pxd;
+
+ if (!lex_force_match_id (lexer, "OUTFILE"))
+ return CMD_FAILURE;
+ lex_match (lexer, '=');
+
+ handle = fh_parse (lexer, FH_REF_FILE, dataset_session (ds));
+ if (handle == NULL)
+ return CMD_FAILURE;
+
+ pxd = pxd_open (fh_get_file_name (handle), true);
+ obj = dict_save (dataset_dict (ds), pxd);
+ pxd_get_root (pxd, &root);
+ pxd_swap_root (pxd, &root, obj);
+ pxd_close (pxd);
+
+ return CMD_SUCCESS;
+}
+
+int
+cmd_get_session (struct lexer *lexer, struct dataset *ds)
+{
+ struct file_handle *handle;
+ struct pxd_object *obj;
+ struct pxd_id root;
+ struct pxd *pxd;
+
+ if (lex_match_id (lexer, "FILE"))
+ lex_match (lexer, '=');
+
+ handle = fh_parse (lexer, FH_REF_FILE, dataset_session (ds));
+ if (handle == NULL)
+ return CMD_FAILURE;
+
+ pxd = pxd_open (fh_get_file_name (handle), false);
+ pxd_get_root (pxd, &root);
+ obj = pxd_fetch (pxd, &root);
+ dict_destroy (dict_load (obj, pxd));
+ pxd_close (pxd);
+
+ return CMD_SUCCESS;
+}
src/libpspp/compiler.h \
src/libpspp/copyleft.c \
src/libpspp/copyleft.h \
+ src/libpspp/db.h \
src/libpspp/deque.c \
src/libpspp/deque.h \
src/libpspp/encoding-guesser.c \
src/libpspp/pool.h \
src/libpspp/prompt.c \
src/libpspp/prompt.h \
+ src/libpspp/pxd.c \
+ src/libpspp/pxd.h \
src/libpspp/range-map.c \
src/libpspp/range-map.h \
src/libpspp/range-set.c \
--- /dev/null
+/* PSPP - a program for statistical analysis.
+ Copyright (C) 2012 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
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef LIBPSPP_DB_H
+#define LIBPSPP_DB_H 1
+
+
+
+#endif /* libpspp/db.h */
/* PSPP - a program for statistical analysis.
- Copyright (C) 2006, 2011 Free Software Foundation, Inc.
+ Copyright (C) 2006, 2010-2012 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
#ifndef LIBPSPP_FLOAT_FORMAT_H
#define LIBPSPP_FLOAT_FORMAT_H 1
+#include <byteswap.h>
#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
#include <stddef.h>
#include "libpspp/compiler.h"
#endif
};
+static inline uint64_t double_to_ieee64le (double x);
+static inline double ieee64le_to_double (uint64_t x);
+
void float_convert (enum float_format, const void *,
enum float_format, void *);
enum float_format *best_guess);
double float_get_lowest (void);
+\f
+static inline uint64_t
+double_to_ieee64le (double x)
+{
+ uint64_t y;
+
+#if FLOAT_NATIVE_DOUBLE == FLOAT_IEEE_DOUBLE_LE
+ memcpy (&y, &x, sizeof y);
+#elif FLOAT_NATIVE_DOUBLE == FLOAT_IEEE_DOUBLE_BE
+ memcpy (&y, &x, sizeof y);
+ y = bswap_64 (y);
+#else
+ float_convert (&x, FLOAT_NATIVE_DOUBLE, &y, FLOAT_IEEE_DOUBLE_LE);
+#endif
+
+ return y;
+}
+
+static inline double
+ieee64le_to_double (uint64_t x)
+{
+ double y;
+
+#if FLOAT_NATIVE_DOUBLE == FLOAT_IEEE_DOUBLE_LE
+ memcpy (&y, &x, sizeof y);
+#elif FLOAT_NATIVE_DOUBLE == FLOAT_IEEE_DOUBLE_BE
+ x = bswap_64 (x);
+ memcpy (&y, &x, sizeof y);
+#else
+ float_convert (&x, FLOAT_IEEE_DOUBLE_LE, &y, FLOAT_NATIVE_DOUBLE);
+#endif
+
+ return y;
+}
#endif /* float-format.h */
#endif
};
-/* Byte-order conversion macros.
+/* Endian conversion macros.
These are intended for use only in contexts where a function cannot be
called, e.g. static initializers or case labels.
#define LE32_TO_CPU(X) CPU_TO_LE32 (X)
#define LE64_TO_CPU(X) CPU_TO_LE64 (X)
-/* Byte-order conversion functions.
+/* Endian conversion functions.
- These should be preferred to the macros. */
+ Use these in preference to the macros above. */
static inline uint16_t cpu_to_be16 (uint16_t x) { return CPU_TO_BE16 (x); }
static inline uint32_t cpu_to_be32 (uint32_t x) { return CPU_TO_BE32 (x); }
static inline uint64_t cpu_to_be64 (uint64_t x) { return CPU_TO_BE64 (x); }
/* PSPP - a program for statistical analysis.
- Copyright (C) 2010, 2011 Free Software Foundation, Inc.
+ Copyright (C) 2010, 2011, 2012 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
const char *
intern_new (const char *s)
{
- size_t length = strlen (s);
+ return intern_buffer (s, strlen (s));
+}
+
+const char *
+intern_buffer (const char *s, size_t length)
+{
unsigned int hash = hash_bytes (s, length, 0);
struct interned_string *is;
}
}
+/* Returns the length of interned string S. */
+size_t
+intern_strlen (const char *s)
+{
+ return interned_string_from_string (s)->length;
+}
+
/* Given null-terminated string S, returns true if S is an interned string
returned by intern_string_new(), false otherwise.
unsigned int hash = hash_bytes (s, length, 0);
return intern_lookup__ (s, length, hash) != NULL;
}
-
-/* Returns the length of S, which must be an interned string returned by
- intern_new(). */
-size_t
-intern_strlen (const char *s)
-{
- return interned_string_from_string (s)->length;
-}
#include <stddef.h>
const char *intern_new (const char *);
+const char *intern_buffer (const char *, size_t length);
+
const char *intern_ref (const char *);
void intern_unref (const char *);
--- /dev/null
+/* PSPP - a program for statistical analysis.
+ Copyright (C) 2010, 2013 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
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#include "libpspp/pxd.h"
+
+#include <gdbm.h>
+#include <stdlib.h>
+
+#include "data/value.h"
+#include "libpspp/cast.h"
+#include "libpspp/compiler.h"
+#include "libpspp/float-format.h"
+#include "libpspp/integer-format.h"
+#include "libpspp/intern.h"
+
+#include "gl/error.h"
+#include "gl/minmax.h"
+#include "gl/sha1.h"
+#include "gl/xalloc.h"
+#include "gl/xmemdup0.h"
+
+struct pxd
+ {
+ GDBM_FILE dbf;
+ };
+
+static struct pxd_object *pxd_object_lookup__ (const struct pxd_id *id);
+static struct pxd_object *pxd_object_create_raw__ (char *raw, size_t n_links,
+ size_t size,
+ const struct pxd_id *);
+
+static datum
+make_datum (const void *data, size_t size)
+{
+ datum d;
+
+ d.dptr = CONST_CAST (void *, data);
+ d.dsize = size;
+
+ return d;
+}
+
+static datum
+string_datum (const char *s)
+{
+ return make_datum (s, strlen (s));
+}
+
+static datum
+id_datum (const struct pxd_id *id)
+{
+ return make_datum (id, sizeof *id);
+}
+
+static datum
+root_key (void)
+{
+ return string_datum ("root");
+}
+
+void
+pxd_get_root (const struct pxd *pxd, struct pxd_id *id)
+{
+ datum content;
+
+ content = gdbm_fetch (pxd->dbf, root_key ());
+ if (content.dptr != NULL && content.dsize == sizeof *id)
+ memcpy (id, content.dptr, sizeof *id);
+ else
+ memset (id, 0, sizeof *id);
+ free (content.dptr);
+}
+
+struct pxd *
+pxd_open (const char *name, bool may_create)
+{
+ struct pxd *pxd;
+ GDBM_FILE dbf;
+
+ dbf = gdbm_open (CONST_CAST (char *, name), 4096,
+ may_create ? GDBM_WRCREAT : GDBM_WRITER, 0777, NULL);
+ if (dbf == NULL)
+ {
+ error (0, 0, "%s: open failed (%s)", name, gdbm_strerror (gdbm_errno));
+ return NULL;
+ }
+
+ pxd = xmalloc (sizeof *pxd);
+ pxd->dbf = dbf;
+ return pxd;
+}
+
+void
+pxd_close (struct pxd *pxd)
+{
+ if (pxd != NULL)
+ {
+ gdbm_close (pxd->dbf);
+ free (pxd);
+ }
+}
+
+struct pxd_object *
+pxd_fetch (const struct pxd *pxd, const struct pxd_id *id)
+{
+ struct pxd_object *obj;
+ datum content;
+ uint32_t n_links;
+ size_t header_size;
+
+ obj = pxd_object_lookup__ (id);
+ if (obj != NULL)
+ return obj;
+
+ content = gdbm_fetch (pxd->dbf, id_datum (id));
+ if (content.dptr == NULL)
+ error (1, 0, PXD_ID_FMT": not found in database", PXD_ID_ARGS (id));
+
+ if (content.dsize < sizeof n_links)
+ error (1, 0, PXD_ID_FMT": size %d is less than minimum size 4",
+ PXD_ID_ARGS(id), content.dsize);
+
+ n_links = le32_to_cpu (*(uint32_t *) content.dptr);
+ header_size = 4 + n_links * sizeof (struct pxd_id);
+ if (header_size > content.dsize)
+ error (1, 0, PXD_ID_FMT": size %d is less than minimum size %zu for "
+ "object with %"PRIu32" links",
+ PXD_ID_ARGS (id), content.dsize, header_size, n_links);
+
+ return pxd_object_create_raw__ (content.dptr, n_links,
+ content.dsize - header_size, id);
+}
+
+void
+pxd_store (struct pxd *pxd, const struct pxd_object *object)
+{
+ datum content;
+
+ content = make_datum (pxd_object_raw_data__ (object),
+ pxd_object_raw_size__ (object));
+ if (gdbm_store (pxd->dbf, id_datum (&object->id), content, GDBM_INSERT) < 0)
+ error (1, 0, PXD_ID_FMT": storing object failed",
+ PXD_ID_ARGS (&object->id));
+}
+
+bool
+pxd_swap_root (struct pxd *pxd, const struct pxd_id *old_root,
+ struct pxd_object *new_root)
+{
+ struct pxd_id cur_root;
+
+ pxd_get_root (pxd, &cur_root);
+ if (pxd_id_equals (&cur_root, old_root))
+ {
+ if (gdbm_store (pxd->dbf, root_key (), id_datum (&new_root->id),
+ GDBM_INSERT) < 0)
+ error (1, 0, "storing root object failed");
+ pxd_object_unref (new_root);
+ return true;
+ }
+ else
+ return false;
+}
+\f
+static struct hmap object_table = HMAP_INITIALIZER (object_table);
+
+static struct pxd_object *
+pxd_object_lookup__ (const struct pxd_id *id)
+{
+ const struct pxd_object *obj;
+
+ HMAP_FOR_EACH_IN_BUCKET (obj, struct pxd_object, hmap_node,
+ pxd_id_hash (id), &object_table)
+ if (pxd_id_equals (id, &obj->id))
+ return pxd_object_ref (obj);
+
+ return NULL;
+}
+
+static struct pxd_object *
+pxd_object_create_raw__ (char *raw, size_t n_links, size_t size,
+ const struct pxd_id *id)
+{
+ struct pxd_object *obj;
+
+ obj = xmalloc (sizeof *obj);
+ hmap_insert (&object_table, &obj->hmap_node, pxd_id_hash (id));
+ obj->n_refs = 1;
+ obj->id = *id;
+ obj->n_links = n_links;
+ obj->size = size;
+ obj->links = (struct pxd_id *) (raw + sizeof (uint32_t));
+ obj->data = (uint8_t *) (obj->links + obj->n_links);
+
+ return obj;
+}
+
+struct pxd_object *
+pxd_object_create (const struct pxd_id links[], size_t n_links,
+ const void *data, size_t size)
+{
+ struct pxd_object *obj;
+ struct sha1_ctx sha;
+ uint32_t le_n_links;
+ struct pxd_id id;
+ char *raw;
+
+ /* Hash the raw form of the object. */
+ sha1_init_ctx (&sha);
+ le_n_links = cpu_to_le32 (n_links);
+ sha1_process_bytes (&le_n_links, sizeof le_n_links, &sha);
+ sha1_process_bytes (links, n_links * sizeof *links, &sha);
+ sha1_process_bytes (data, size, &sha);
+ sha1_finish_ctx (&sha, &id);
+
+ /* Reuse an existing copy if there is one. */
+ obj = pxd_object_lookup__ (&id);
+ if (obj != NULL)
+ return obj;
+
+ /* Build a new object. */
+ raw = xmalloc (sizeof le_n_links + n_links * sizeof *links +
+ size);
+ memcpy (raw, &le_n_links, sizeof le_n_links);
+ memcpy (raw + sizeof le_n_links, links, n_links * sizeof *links);
+ memcpy (raw + sizeof le_n_links + n_links * sizeof *links, data, size);
+
+ return pxd_object_create_raw__ (raw, n_links, size, &id);
+}
+
+struct pxd_object *
+pxd_object_ref (const struct pxd_object *const_obj)
+{
+ struct pxd_object *obj = CONST_CAST (struct pxd_object *, const_obj);
+ obj->n_refs++;
+ return obj;
+}
+
+void
+pxd_object_unref (struct pxd_object *obj)
+{
+ if (obj != NULL && --obj->n_refs == 0)
+ {
+ hmap_delete (&object_table, &obj->hmap_node);
+ free (pxd_object_raw_data__ (obj));
+ free (obj);
+ }
+}
+
+void *
+pxd_object_raw_data__ (const struct pxd_object *obj)
+{
+ return ((uint32_t *) obj->links) - 1;
+}
+
+size_t
+pxd_object_raw_size__ (const struct pxd_object *obj)
+{
+ return sizeof (uint32_t *) + obj->n_links * sizeof *obj->links + obj->size;
+}
+\f
+void
+pxd_builder_init (struct pxd_builder *b, struct pxd *pxd)
+{
+ b->pxd = pxd;
+
+ b->links = NULL;
+ b->n_links = b->links_allocated = 0;
+
+ b->data = NULL;
+ b->size = b->data_allocated = 0;
+}
+
+void
+pxd_builder_destroy (struct pxd_builder *b)
+{
+ if (b != NULL)
+ {
+ free (b->links);
+ b->links = NULL;
+
+ free (b->data);
+ b->data = NULL;
+ }
+}
+
+struct pxd_object *
+pxd_builder_commit (struct pxd_builder *b)
+{
+ struct pxd_object *obj;
+
+ obj = pxd_object_create (b->links, b->n_links, b->data, b->size);
+ pxd_store (b->pxd, obj);
+ pxd_builder_destroy (b);
+
+ return obj;
+}
+
+void *
+pxd_builder_put_uninit (struct pxd_builder *b, size_t n)
+{
+ void *p;
+
+ if (b->size + n > b->data_allocated)
+ {
+ b->data_allocated = MAX (b->size + n + 64, b->data_allocated * 2);
+ b->data = xrealloc (b->data, b->data_allocated);
+ }
+
+ p = &b->data[b->size];
+ b->size += n;
+ return p;
+}
+
+void
+pxd_builder_put (struct pxd_builder *b, const void *p, size_t n)
+{
+ memcpy (pxd_builder_put_uninit (b, n), p, n);
+}
+
+void
+pxd_builder_put_value (struct pxd_builder *b,
+ const union value *value, int width)
+{
+ if (width == 0)
+ pxd_builder_put_double (b, value->f);
+ else
+ {
+ const uint8_t *s = value_str (value, width);
+ if (width < sizeof (struct pxd_id))
+ pxd_builder_put (b, s, width);
+ else
+ pxd_builder_put_link (b, pxd_object_create (NULL, 0, s, width));
+ }
+}
+
+static void
+pxd_builder_put_string__ (struct pxd_builder *b, const char *s, size_t length)
+{
+ pxd_builder_put_u32 (b, length);
+ if (length < sizeof (struct pxd_id))
+ pxd_builder_put (b, s, length);
+ else
+ pxd_builder_put_link (b, pxd_object_create (NULL, 0, s, length));
+}
+
+void
+pxd_builder_put_string (struct pxd_builder *b, const char *s)
+{
+ return pxd_builder_put_string__ (b, s, strlen (s));
+}
+
+void
+pxd_builder_put_interned_string (struct pxd_builder *b, const char *s)
+{
+ return pxd_builder_put_string__ (b, s, intern_strlen (s));
+}
+
+void
+pxd_builder_put_bool (struct pxd_builder *b, bool x)
+{
+ pxd_builder_put_u8 (b, x != 0);
+}
+
+void
+pxd_builder_put_u8 (struct pxd_builder *b, unsigned char x)
+{
+ pxd_builder_put (b, &x, 1);
+}
+
+void
+pxd_builder_put_u16 (struct pxd_builder *b, unsigned short int x)
+{
+ uint16_t le_x = cpu_to_le16 (x);
+ pxd_builder_put (b, &le_x, sizeof (le_x));
+}
+
+void pxd_builder_put_u32 (struct pxd_builder *b, unsigned int x)
+{
+ uint32_t le_x = cpu_to_le32 (x);
+ pxd_builder_put (b, &le_x, sizeof (le_x));
+}
+
+void
+pxd_builder_put_u64 (struct pxd_builder *b, unsigned long long int x)
+{
+ uint64_t le_x = cpu_to_le64 (x);
+ pxd_builder_put (b, &le_x, sizeof (le_x));
+}
+
+void
+pxd_builder_put_s8 (struct pxd_builder *b, signed char x)
+{
+ pxd_builder_put (b, &x, 1);
+}
+
+void
+pxd_builder_put_s16 (struct pxd_builder *b, short int x)
+{
+ uint16_t le_x = cpu_to_le16 (x);
+ pxd_builder_put (b, &le_x, sizeof (le_x));
+}
+
+void pxd_builder_put_s32 (struct pxd_builder *b, int x)
+{
+ uint32_t le_x = cpu_to_le32 (x);
+ pxd_builder_put (b, &le_x, sizeof (le_x));
+}
+
+void
+pxd_builder_put_s64 (struct pxd_builder *b, long long int x)
+{
+ uint64_t le_x = cpu_to_le64 (x);
+ pxd_builder_put (b, &le_x, sizeof (le_x));
+}
+
+void
+pxd_builder_put_size_t (struct pxd_builder *b, size_t x)
+{
+ pxd_builder_put_u64 (b, x);
+}
+
+void
+pxd_builder_put_casenumber (struct pxd_builder *b, casenumber x)
+{
+ pxd_builder_put_u64 (b, x);
+}
+
+void
+pxd_builder_put_double (struct pxd_builder *b, double x)
+{
+ pxd_builder_put_u64 (b, double_to_ieee64le (x));
+}
+
+void
+pxd_builder_put_link (struct pxd_builder *b, struct pxd_object *obj)
+{
+ if (b->n_links >= b->links_allocated)
+ b->links = x2nrealloc (b->links, &b->links_allocated, sizeof *b->links);
+
+ b->links[b->n_links++] = obj->id;
+}
+\f
+void
+pxd_parser_init (struct pxd_parser *p,
+ struct pxd_object *obj, const struct pxd *pxd)
+{
+ p->obj = obj;
+ p->pxd = pxd;
+ p->offset = 0;
+ p->link = 0;
+}
+
+void
+pxd_parser_destroy (struct pxd_parser *p)
+{
+ if (p != NULL)
+ pxd_object_unref (p->obj);
+}
+
+
+const void *
+pxd_parser_get (struct pxd_parser *p, size_t n)
+{
+ const void *data;
+
+ assert (p->offset + n <= p->obj->size);
+
+ data = &p->obj->data[p->offset];
+ p->offset += n;
+ return data;
+}
+
+void
+pxd_parser_get_copy (struct pxd_parser *p, void *dst, size_t n)
+{
+ memcpy (dst, pxd_parser_get (p, n), n);
+}
+
+void
+pxd_parser_get_value (struct pxd_parser *p, union value *value, int width)
+{
+ value_init (value, width);
+ if (width == 0)
+ value->f = ieee64le_to_double (pxd_parser_get_u64 (p));
+ else
+ {
+ uint8_t *s = value_str_rw (value, width);
+ if (width < sizeof (struct pxd_id))
+ pxd_parser_get_copy (p, s, width);
+ else
+ {
+ struct pxd_object *link = pxd_parser_get_link (p);
+ assert (link->size == width);
+ memcpy (s, link->data, width);
+ pxd_object_unref (link);
+ }
+ }
+}
+
+char *
+pxd_parser_get_string (struct pxd_parser *p)
+{
+ uint32_t length = pxd_parser_get_u32 (p);
+ if (length < sizeof (struct pxd_id))
+ return xmemdup0 (pxd_parser_get (p, length), length);
+ else
+ {
+ struct pxd_object *link;
+ char *s;
+
+ link = pxd_parser_get_link (p);
+ assert (link->size == length);
+ s = xmemdup0 (link->data, link->size);
+ pxd_object_unref (link);
+
+ return s;
+ }
+}
+
+const char *
+pxd_parser_get_interned_string (struct pxd_parser *p)
+{
+ uint32_t length = pxd_parser_get_u32 (p);
+ if (length < sizeof (struct pxd_id))
+ return intern_buffer (pxd_parser_get (p, length), length);
+ else
+ {
+ struct pxd_object *link;
+ const char *s;
+
+ link = pxd_parser_get_link (p);
+ assert (link->size == length);
+ s = intern_buffer ((const void *) link->data, link->size);
+ pxd_object_unref (link);
+
+ return s;
+ }
+}
+
+bool
+pxd_parser_get_bool (struct pxd_parser *p)
+{
+ return pxd_parser_get_u8 (p) != 0;
+}
+
+unsigned char
+pxd_parser_get_u8 (struct pxd_parser *p)
+{
+ uint8_t x;
+ pxd_parser_get_copy (p, &x, 1);
+ return x;
+}
+
+unsigned short int
+pxd_parser_get_u16 (struct pxd_parser *p)
+{
+ uint16_t x;
+ pxd_parser_get_copy (p, &x, sizeof x);
+ return le16_to_cpu (x);
+}
+
+unsigned int
+pxd_parser_get_u32 (struct pxd_parser *p)
+{
+ uint32_t x;
+ pxd_parser_get_copy (p, &x, sizeof x);
+ return le32_to_cpu (x);
+}
+
+unsigned long long int
+pxd_parser_get_u64 (struct pxd_parser *p)
+{
+ uint64_t x;
+ pxd_parser_get_copy (p, &x, sizeof x);
+ return le64_to_cpu (x);
+}
+
+signed char
+pxd_parser_get_s8 (struct pxd_parser *p)
+{
+ int8_t x;
+ pxd_parser_get_copy (p, &x, 1);
+ return x;
+}
+
+short int
+pxd_parser_get_s16 (struct pxd_parser *p)
+{
+ uint16_t x;
+ pxd_parser_get_copy (p, &x, sizeof x);
+ return le16_to_cpu (x);
+}
+
+int
+pxd_parser_get_s32 (struct pxd_parser *p)
+{
+ uint32_t x;
+ pxd_parser_get_copy (p, &x, sizeof x);
+ return le32_to_cpu (x);
+}
+
+long long int
+pxd_parser_get_s64 (struct pxd_parser *p)
+{
+ uint64_t x;
+ pxd_parser_get_copy (p, &x, sizeof x);
+ return le64_to_cpu (x);
+}
+
+size_t
+pxd_parser_get_size_t (struct pxd_parser *p)
+{
+ uint64_t x = pxd_parser_get_u64 (p);
+ assert (x <= SIZE_MAX);
+ return x;
+}
+
+casenumber
+pxd_parser_get_casenumber (struct pxd_parser *p)
+{
+ uint64_t x = pxd_parser_get_u64 (p);
+ assert (x <= CASENUMBER_MAX);
+ return x;
+}
+
+double
+pxd_parser_get_double (struct pxd_parser *p)
+{
+ return ieee64le_to_double (pxd_parser_get_u64 (p));
+}
+
+struct pxd_object *
+pxd_parser_get_link (struct pxd_parser *p)
+{
+ assert (p->link < p->obj->n_links);
+
+ return pxd_fetch (p->pxd, &p->obj->links[p->link++]);
+}
+\f
+void
+pxd_array_builder_init (struct pxd_array_builder *ab, struct pxd *pxd)
+{
+ pxd_builder_init (&ab->b, pxd);
+}
+
+void
+pxd_array_builder_destroy (struct pxd_array_builder *ab)
+{
+ pxd_builder_destroy (&ab->b);
+}
+
+struct pxd_object *
+pxd_array_builder_commit (struct pxd_array_builder *ab)
+{
+ return pxd_builder_commit (&ab->b);
+}
+
+void
+pxd_array_builder_add (struct pxd_array_builder *ab, struct pxd_object *obj)
+{
+ pxd_builder_put_link (&ab->b, obj);
+}
+\f
+void
+pxd_array_init (struct pxd_array *array, struct pxd_object *obj,
+ const struct pxd *pxd)
+{
+ array->pxd = pxd;
+ array->obj = obj;
+}
+
+void
+pxd_array_destroy (struct pxd_array *array)
+{
+ pxd_object_unref (array->obj);
+}
--- /dev/null
+/* PSPP - a program for statistical analysis.
+ Copyright (C) 2010, 2012 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
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef LIBPSPP_PXD_H
+#define LIBPSPP_PXD_H 1
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include "data/case.h"
+#include "libpspp/hmap.h"
+
+struct pxd;
+struct pxd_object;
+struct pxd_id;
+union value;
+\f
+/* Databases. */
+
+struct pxd *pxd_open (const char *name, bool create);
+void pxd_close (struct pxd *);
+
+struct pxd_object *pxd_fetch (const struct pxd *, const struct pxd_id *);
+void pxd_store (struct pxd *, const struct pxd_object *);
+
+void pxd_get_root (const struct pxd *, struct pxd_id *);
+bool pxd_swap_root (struct pxd *, const struct pxd_id *old_root,
+ struct pxd_object *new_root);
+\f
+/* Object IDs. */
+
+struct pxd_id
+ {
+ uint32_t opaque[5];
+ };
+
+#define PXD_ID_FMT "%08"PRIx32"%08"PRIx32"%08"PRIx32"%08"PRIx32"%08"PRIx32
+#define PXD_ID_ARGS(ID) \
+ (ID)->opaque[0], \
+ (ID)->opaque[1], \
+ (ID)->opaque[2], \
+ (ID)->opaque[3], \
+ (ID)->opaque[4]
+#define PXD_ID_SCAN_ARGS(ID) \
+ &(ID)->opaque[0], \
+ &(ID)->opaque[1], \
+ &(ID)->opaque[2], \
+ &(ID)->opaque[3], \
+ &(ID)->opaque[4]
+
+static inline bool
+pxd_id_equals (const struct pxd_id *a, const struct pxd_id *b)
+{
+ return (a->opaque[0] == b->opaque[0]
+ && a->opaque[1] == b->opaque[1]
+ && a->opaque[2] == b->opaque[2]
+ && a->opaque[3] == b->opaque[3]
+ && a->opaque[4] == b->opaque[4]);
+}
+
+static inline uint32_t
+pxd_id_hash (const struct pxd_id *id)
+{
+ return id->opaque[0];
+}
+\f
+/* Objects. */
+
+struct pxd_object
+ {
+ struct hmap_node hmap_node;
+ unsigned int n_refs;
+ struct pxd_id id;
+ unsigned int n_links;
+ unsigned int size;
+ struct pxd_id *links;
+ uint8_t *data;
+ };
+
+struct pxd_object *pxd_object_create (const struct pxd_id[], size_t,
+ const void *, size_t);
+
+struct pxd_object *pxd_object_ref (const struct pxd_object *);
+void pxd_object_unref (struct pxd_object *);
+
+static inline const struct pxd_id *
+pxd_object_id (const struct pxd_object *obj)
+{
+ return &obj->id;
+}
+
+static inline unsigned int
+pxd_object_get_n_links (const struct pxd_object *obj)
+{
+ return obj->n_links;
+}
+
+static inline const struct pxd_id *
+pxd_object_get_link_id (const struct pxd_object *obj, unsigned int idx)
+{
+ return &obj->links[idx];
+}
+
+static inline struct pxd_object *
+pxd_object_get_link (const struct pxd_object *obj, unsigned int idx,
+ const struct pxd *pxd)
+{
+ return pxd_fetch (pxd, pxd_object_get_link_id (obj, idx));
+}
+
+static inline unsigned int
+pxd_object_size (const struct pxd_object *obj)
+{
+ return obj->size;
+}
+
+static inline const uint8_t *
+pxd_object_data (const struct pxd_object *obj)
+{
+ return obj->data;
+}
+
+void *pxd_object_raw_data__ (const struct pxd_object *);
+size_t pxd_object_raw_size__ (const struct pxd_object *);
+\f
+/* Object builder. */
+
+struct pxd_builder
+ {
+ struct pxd *pxd;
+
+ struct pxd_id *links;
+ unsigned int n_links, links_allocated;
+
+ uint8_t *data;
+ unsigned int size, data_allocated;
+ };
+
+void pxd_builder_init (struct pxd_builder *, struct pxd *);
+void pxd_builder_destroy (struct pxd_builder *);
+
+struct pxd_object *pxd_builder_commit (struct pxd_builder *);
+
+void *pxd_builder_put_uninit (struct pxd_builder *, size_t);
+void pxd_builder_put (struct pxd_builder *, const void *, size_t);
+void pxd_builder_put_value (struct pxd_builder *,
+ const union value *, int width);
+void pxd_builder_put_string (struct pxd_builder *, const char *);
+void pxd_builder_put_interned_string (struct pxd_builder *, const char *);
+void pxd_builder_put_bool (struct pxd_builder *, bool);
+void pxd_builder_put_u8 (struct pxd_builder *, unsigned char);
+void pxd_builder_put_u16 (struct pxd_builder *, unsigned short int);
+void pxd_builder_put_u32 (struct pxd_builder *, unsigned int);
+void pxd_builder_put_u64 (struct pxd_builder *, unsigned long long int);
+void pxd_builder_put_s8 (struct pxd_builder *, signed char);
+void pxd_builder_put_s16 (struct pxd_builder *, short int);
+void pxd_builder_put_s32 (struct pxd_builder *, int);
+void pxd_builder_put_s64 (struct pxd_builder *, long long int);
+void pxd_builder_put_size_t (struct pxd_builder *, size_t);
+void pxd_builder_put_casenumber (struct pxd_builder *, casenumber);
+void pxd_builder_put_double (struct pxd_builder *, double);
+
+void pxd_builder_put_link (struct pxd_builder *, struct pxd_object *);
+\f
+/* Object parser. */
+
+struct pxd_parser
+ {
+ struct pxd_object *obj;
+ const struct pxd *pxd;
+ unsigned int offset;
+ unsigned int link;
+ };
+
+void pxd_parser_init (struct pxd_parser *,
+ struct pxd_object *, const struct pxd *);
+void pxd_parser_destroy (struct pxd_parser *);
+
+const void *pxd_parser_get (struct pxd_parser *, size_t);
+void pxd_parser_get_copy (struct pxd_parser *, void *, size_t);
+void pxd_parser_get_value (struct pxd_parser *, union value *, int width);
+char *pxd_parser_get_string (struct pxd_parser *);
+const char *pxd_parser_get_interned_string (struct pxd_parser *);
+bool pxd_parser_get_bool (struct pxd_parser *);
+unsigned char pxd_parser_get_u8 (struct pxd_parser *);
+unsigned short int pxd_parser_get_u16 (struct pxd_parser *);
+unsigned int pxd_parser_get_u32 (struct pxd_parser *);
+unsigned long long int pxd_parser_get_u64 (struct pxd_parser *);
+signed char pxd_parser_get_s8 (struct pxd_parser *);
+short int pxd_parser_get_s16 (struct pxd_parser *);
+int pxd_parser_get_s32 (struct pxd_parser *);
+long long int pxd_parser_get_s64 (struct pxd_parser *);
+size_t pxd_parser_get_size_t (struct pxd_parser *);
+casenumber pxd_parser_get_casenumber (struct pxd_parser *);
+double pxd_parser_get_double (struct pxd_parser *);
+struct pxd_object *pxd_parser_get_link (struct pxd_parser *);
+\f
+/* Array builder. */
+
+#define PXD_ARRAY_LEVELS 10
+#define PXD_ARRAY_BITS 5
+
+struct pxd_array_builder
+ {
+ struct pxd_builder b;
+ };
+
+void pxd_array_builder_init (struct pxd_array_builder *, struct pxd *);
+void pxd_array_builder_destroy (struct pxd_array_builder *);
+
+struct pxd_object *pxd_array_builder_commit (struct pxd_array_builder *);
+
+void pxd_array_builder_add (struct pxd_array_builder *, struct pxd_object *);
+\f
+/* Array reader. */
+
+struct pxd_array
+ {
+ const struct pxd *pxd;
+ struct pxd_object *obj;
+ };
+
+void pxd_array_init (struct pxd_array *, struct pxd_object *,
+ const struct pxd *);
+void pxd_array_destroy (struct pxd_array *);
+
+static inline unsigned long long int
+pxd_array_size (const struct pxd_array *array)
+{
+ return array->obj->n_links;
+}
+
+static inline struct pxd_object *
+pxd_array_get (const struct pxd_array *array, unsigned long long int index)
+{
+ return pxd_object_get_link (array->obj, index, array->pxd);
+}
+
+#endif /* libpspp/pxd.h */
--- /dev/null
+## Process this file with automake to produce Makefile.in -*- makefile -*-
+
+EXTRA_DIST += \
+ src/processor/processor.c \
+ src/processor/request.c \
+ src/processor/request.h
--- /dev/null
+/* PSPP - a program for statistical analysis.
+ Copyright (C) 2012 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
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#if HAVE_FPU_CONTROL_H
+#include <fpu_control.h>
+#endif
+#if HAVE_FENV_H
+#include <fenv.h>
+#endif
+#if HAVE_IEEEFP_H
+#include <ieeefp.h>
+#endif
+#include <unistd.h>
+
+#include "data/dataset.h"
+#include "data/dictionary.h"
+#include "data/file-handle-def.h"
+#include "data/file-name.h"
+#include "data/session.h"
+#include "data/settings.h"
+#include "data/variable.h"
+#include "gsl/gsl_errno.h"
+#include "language/command.h"
+#include "language/lexer/lexer.h"
+#include "language/lexer/include-path.h"
+#include "libpspp/argv-parser.h"
+#include "libpspp/compiler.h"
+#include "libpspp/i18n.h"
+#include "libpspp/message.h"
+#include "libpspp/version.h"
+#include "math/random.h"
+#include "output/driver.h"
+#include "output/message-item.h"
+#include "ui/source-init-opts.h"
+
+#include "gl/fatal-signal.h"
+#include "gl/progname.h"
+#include "gl/relocatable.h"
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+
+static void bug_handler(int sig);
+static void fpu_init (void);
+
+/* Program entry point. */
+int
+main (int argc, char **argv)
+{
+ char s[128];
+
+ set_program_name (argv[0]);
+
+ signal (SIGABRT, bug_handler);
+ signal (SIGSEGV, bug_handler);
+ signal (SIGFPE, bug_handler);
+
+ i18n_init ();
+ fpu_init ();
+ gsl_set_error_handler_off ();
+
+ fh_init ();
+ settings_init ();
+ random_init ();
+
+ //msg_set_handler (output_msg, lexer);
+
+ while (fgets (s, sizeof s, stdin))
+ {
+ struct pspp_proc_request *request;
+ struct pxd_object *object;
+ struct pxd_id id;
+ int n = -1;
+
+ if (sscanf (s, PXD_ID_FMT"%n", PXD_ID_SCAN_ARGS (&id), &n) <= 0 || n < 0)
+ {
+ printf ("bad input format\n");
+ fflush (stdout);
+ continue;
+ }
+
+ object = pxd_fetch (pxd, &id);
+ if (object == NULL)
+ {
+ printf (PXD_ID_FMT": object not found\n", PXD_ID_ARGS (&id));
+ fflush (stdout);
+ continue;
+ }
+
+ request = pspp_proc_request_load (object, pxd);
+ pxd_object_unref (object);
+ if (request == NULL)
+ {
+ printf (PXD_ID_FMT": bad request\n", PXD_ID_FMT (&id));
+ fflush (stdout);
+ continue;
+ }
+
+ reply = pspp_proc_request_execute (request);
+ if (reply == NULL)
+ {
+ printf (PXD_ID_FMT": could not execute request\n", PXD_ID_FMT (&id));
+ fflush (stdout);
+ continue;
+ }
+
+ object = pspp_proc_reply_save (reply, pxd);
+ pspp_proc_reply_destroy (reply);
+ if (object == NULL)
+ {
+ printf (PXD_ID_FMT": could not save reply\n", PXD_ID_FMT (&id));
+ fflush (stdout);
+ continue;
+ }
+
+ printf (PXD_ID_FMT"\n", PXD_ID_FMT (pxd_object_id (object)));
+ fflush (stdout);
+ pxd_object_unref (object);
+
+ /* XXX what keeps the reply from getting garbage collected? */
+ }
+
+ random_done ();
+ settings_done ();
+ fh_done ();
+ lex_destroy (lexer);
+ output_close ();
+ i18n_done ();
+}
+\f
+static void
+fpu_init (void)
+{
+#if HAVE_FEHOLDEXCEPT
+ fenv_t foo;
+ feholdexcept (&foo);
+#elif HAVE___SETFPUCW && defined(_FPU_IEEE)
+ __setfpucw (_FPU_IEEE);
+#elif HAVE_FPSETMASK
+ fpsetmask (0);
+#endif
+}
+
+/* If a segfault happens, issue a message to that effect and halt */
+static void
+bug_handler(int sig)
+{
+ /* Reset SIG to its default handling so that if it happens again we won't
+ recurse. */
+ signal (sig, SIG_DFL);
+
+ switch (sig)
+ {
+ case SIGABRT:
+ request_bug_report("Assertion Failure/Abort");
+ break;
+ case SIGFPE:
+ request_bug_report("Floating Point Exception");
+ break;
+ case SIGSEGV:
+ request_bug_report("Segmentation Violation");
+ break;
+ default:
+ request_bug_report("Unknown");
+ break;
+ }
+
+ /* Re-raise the signal so that we terminate with the correct status. */
+ raise (sig);
+}
--- /dev/null
+/* PSPP - a program for statistical analysis.
+ Copyright (C) 2012 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
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#include "request.h"
+
+struct pspp_proc_request
+ {
+ struct session *session;
+
+
+ };
+
+struct pspp_proc_request *
+pspp_proc_request_load (struct pxd_object *object,
+ const struct pxd *pxd)
+{
+
+
+}
+
+struct pxd_object *pspp_proc_reply_save (const struct pspp_proc_reply *,
+ struct pxd *);
+struct pspp_proc_reply *pspp_proc_reply_load (struct pxd_object *,
+ const struct pxd *);
+
+#endif /* processor/request.h */
--- /dev/null
+/* PSPP - a program for statistical analysis.
+ Copyright (C) 2012 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
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef PSPP_PROC_REQUEST_H
+#define PSPP_PROC_REQUEST_H 1
+
+struct pxd_object *pspp_proc_request_save (const struct pspp_proc_request *,
+ struct pxd *);
+struct pspp_proc_request *pspp_proc_request_load (struct pxd_object *,
+ const struct pxd *);
+
+struct pxd_object *pspp_proc_reply_save (const struct pspp_proc_reply *,
+ struct pxd *);
+struct pspp_proc_reply *pspp_proc_reply_load (struct pxd_object *,
+ const struct pxd *);
+
+#endif /* processor/request.h */
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2008, 2009, 2010, 2015 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
int max = INT_MIN;
int j;
- for (j = 0; j <= hmapx.hmap.mask; j++)
+ for (j = 0; j < hmap_n_buckets (&hmapx.hmap); j++)
{
int count = 0;
struct hmap_node *node;