Continue reforming procedure execution. In this phase, move
authorBen Pfaff <blp@gnu.org>
Fri, 5 May 2006 04:53:12 +0000 (04:53 +0000)
committerBen Pfaff <blp@gnu.org>
Fri, 5 May 2006 04:53:12 +0000 (04:53 +0000)
procedure.c and procedure.h from src to src/data.  Update makefiles
and #includes accordingly.

63 files changed:
src/ChangeLog
src/automake.mk
src/data/ChangeLog
src/data/automake.mk
src/data/procedure.c [new file with mode: 0644]
src/data/procedure.h [new file with mode: 0644]
src/data/transformations.c
src/language/command.c
src/language/control/do-if.c
src/language/control/loop.c
src/language/control/repeat.c
src/language/control/temporary.c
src/language/data-io/data-list.c
src/language/data-io/data-reader.c
src/language/data-io/get.c
src/language/data-io/inpt-pgm.c
src/language/data-io/list.q
src/language/data-io/matrix-data.c
src/language/data-io/print.c
src/language/dictionary/apply-dictionary.c
src/language/dictionary/formats.c
src/language/dictionary/missing-values.c
src/language/dictionary/modify-variables.c
src/language/dictionary/numeric.c
src/language/dictionary/rename-variables.c
src/language/dictionary/split-file.c
src/language/dictionary/sys-file-info.c
src/language/dictionary/value-labels.c
src/language/dictionary/variable-display.c
src/language/dictionary/variable-label.c
src/language/dictionary/vector.c
src/language/dictionary/weight.c
src/language/expressions/helpers.h
src/language/expressions/parse.c
src/language/lexer/variable-parser.c
src/language/stats/aggregate.c
src/language/stats/autorecode.c
src/language/stats/correlations.q
src/language/stats/crosstabs.q
src/language/stats/descriptives.c
src/language/stats/examine.q
src/language/stats/flip.c
src/language/stats/frequencies.q
src/language/stats/means.q
src/language/stats/oneway.q
src/language/stats/rank.q
src/language/stats/regression.q
src/language/stats/sort-cases.c
src/language/stats/t-test.q
src/language/utilities/set.q
src/language/utilities/title.c
src/language/xforms/compute.c
src/language/xforms/count.c
src/language/xforms/recode.c
src/language/xforms/sample.c
src/language/xforms/select-if.c
src/math/levene.c
src/math/sort.c
src/procedure.c [deleted file]
src/procedure.h [deleted file]
src/ui/terminal/ChangeLog
src/ui/terminal/automake.mk
src/ui/terminal/main.c

index 0fded64c13f6bdbac2011853221a2bc679f56c9a..d64ac34a4b9656fc948a479ce6acd4133c2b654a 100644 (file)
@@ -1,3 +1,15 @@
+Thu May  4 21:47:48 2006  Ben Pfaff  <blp@gnu.org>
+
+       Continue reforming procedure execution.  In this phase, move
+       procedure.c and procedure.h from src to src/data.  Update
+       makefiles and #includes accordingly.
+
+       * automake.mk: Remove special rule for src/procedure.o.
+
+       * procedure.c: Moved to src/data.
+
+       * procedure.h: Moved to src/data.
+
 Wed May  3 22:24:34 2006  Ben Pfaff  <blp@gnu.org>
 
        Continue reforming procedure execution.  In this phase, get rid of
index 64b4928468c2e84521fb71313e346e8386e9ec66..3d309a6c78e749c646a56f5560f9ea606fce07ce 100644 (file)
@@ -14,12 +14,3 @@ include $(top_srcdir)/src/ui/gui/automake.mk
 endif
 
 AM_CPPFLAGS += -DPKGDATADIR=\"$(pkgdatadir)\"
-
-src/procedure.o: AM_CPPFLAGS += \
- -I$(top_srcdir)/src/language \
- -I$(top_srcdir)/src/language/control \
- -I$(top_srcdir)/src/output \
- -I$(top_srcdir)/src/data \
- -I$(top_srcdir)/src/libpspp
-
-
index 49c1af84e19bbf8be7e1c7df90c1437cc85f1a38..0da663bf2ece5a4b343e88ab6b77f4053a50d4d8 100644 (file)
@@ -1,3 +1,13 @@
+Thu May  4 21:50:11 2006  Ben Pfaff  <blp@gnu.org>
+
+       Continue reforming procedure execution.  In this phase, move
+       procedure.c and procedure.h from src to src/data.  Update
+       makefiles and #includes accordingly.
+
+       * procedure.c: Moved here from src/.
+
+       * procedure.h: Moved here from src/.
+
 Wed May  3 22:42:12 2006  Ben Pfaff  <blp@gnu.org>
 
        Continue reforming procedure execution.  In this phase, get rid of
index 2084e4f61f66158a7bcb3e33a16b842927c53714..d79828b763f3d110c21d892872fc9e480c986c2f 100644 (file)
@@ -38,6 +38,8 @@ src_data_libdata_a_SOURCES = \
        src/data/missing-values.h \
        src/data/make-file.c \
        src/data/make-file.h \
+       src/data/procedure.c \
+       src/data/procedure.h \
        src/data/por-file-reader.c \
        src/data/por-file-reader.h \
        src/data/por-file-writer.c \
diff --git a/src/data/procedure.c b/src/data/procedure.c
new file mode 100644 (file)
index 0000000..4a5e9dd
--- /dev/null
@@ -0,0 +1,1015 @@
+/* PSPP - computes sample statistics.
+   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
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 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, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA. */
+
+#include <config.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <data/case-source.h>
+#include <data/case-sink.h>
+#include <data/case.h>
+#include <data/casefile.h>
+#include <data/dictionary.h>
+#include <data/file-handle-def.h>
+#include <data/procedure.h>
+#include <data/settings.h>
+#include <data/storage-stream.h>
+#include <data/transformations.h>
+#include <data/value-labels.h>
+#include <data/variable.h>
+#include <language/expressions/public.h>
+#include <libpspp/alloc.h>
+#include <libpspp/message.h>
+#include <libpspp/misc.h>
+#include <libpspp/str.h>
+#include <output/manager.h>
+#include <output/table.h>
+
+#include "gettext.h"
+#define _(msgid) gettext (msgid)
+
+/*
+   Virtual File Manager (vfm):
+
+   vfm is used to process data files.  It uses the model that
+   data is read from one stream (the data source), processed,
+   then written to another (the data sink).  The data source is
+   then deleted and the data sink becomes the data source for the
+   next procedure. */
+
+/* Procedure execution data. */
+struct write_case_data
+  {
+    /* Function to call for each case. */
+    bool (*proc_func) (struct ccase *, void *); /* Function. */
+    void *aux;                                 /* Auxiliary data. */ 
+
+    struct ccase trns_case;     /* Case used for transformations. */
+    struct ccase sink_case;     /* Case written to sink, if
+                                   compaction is necessary. */
+    size_t cases_written;       /* Cases output so far. */
+    size_t cases_analyzed;      /* Cases passed to procedure so far. */
+  };
+
+/* Cases are read from vfm_source,
+   pass through permanent_trns_chain (which transforms them into
+   the format described by permanent_dict),
+   are written to vfm_sink,
+   pass through temporary_trns_chain (which transforms them into
+   the format described by default_dict),
+   and are finally passed to the procedure. */
+static struct case_source *vfm_source;
+static struct trns_chain *permanent_trns_chain;
+static struct dictionary *permanent_dict;
+static struct case_sink *vfm_sink;
+static struct trns_chain *temporary_trns_chain;
+struct dictionary *default_dict;
+
+/* The transformation chain that the next transformation will be
+   added to. */
+static struct trns_chain *cur_trns_chain;
+
+/* The compactor used to compact a case, if necessary;
+   otherwise a null pointer. */
+static struct dict_compactor *compactor;
+
+/* Time at which vfm was last invoked. */
+static time_t last_vfm_invocation;
+
+/* Lag queue. */
+int n_lag;                     /* Number of cases to lag. */
+static int lag_count;          /* Number of cases in lag_queue so far. */
+static int lag_head;           /* Index where next case will be added. */
+static struct ccase *lag_queue; /* Array of n_lag ccase * elements. */
+
+static void add_case_limit_trns (void);
+static void add_filter_trns (void);
+static void add_process_if_trns (void);
+
+static bool internal_procedure (bool (*proc_func) (struct ccase *, void *),
+                                void *aux);
+static void update_last_vfm_invocation (void);
+static void create_trns_case (struct ccase *, struct dictionary *);
+static void open_active_file (void);
+static bool write_case (struct write_case_data *wc_data);
+static void lag_case (const struct ccase *c);
+static void clear_case (struct ccase *c);
+static bool close_active_file (void);
+\f
+/* Public functions. */
+
+/* Returns the last time the data was read. */
+time_t
+time_of_last_procedure (void) 
+{
+  if (last_vfm_invocation == 0)
+    update_last_vfm_invocation ();
+  return last_vfm_invocation;
+}
+
+/* Reads the data from the input program and writes it to a new
+   active file.  For each case we read from the input program, we
+   do the following:
+
+   1. Execute permanent transformations.  If these drop the case,
+      start the next case from step 1.
+
+   2. Write case to replacement active file.
+   
+   3. Execute temporary transformations.  If these drop the case,
+      start the next case from step 1.
+      
+   4. Pass case to PROC_FUNC, passing AUX as auxiliary data.
+
+   Returns true if successful, false if an I/O error occurred. */
+bool
+procedure (bool (*proc_func) (struct ccase *, void *), void *aux)
+{
+  if (proc_func == NULL
+      && case_source_is_class (vfm_source, &storage_source_class)
+      && vfm_sink == NULL
+      && temporary_trns_chain == NULL
+      && trns_chain_is_empty (permanent_trns_chain))
+    {
+      expr_free (process_if_expr);
+      process_if_expr = NULL;
+      dict_set_case_limit (default_dict, 0);
+      dict_clear_vectors (default_dict);
+
+      update_last_vfm_invocation ();
+      return true;
+    }
+  else 
+    {
+      bool ok;
+      
+      open_active_file ();
+      ok = internal_procedure (proc_func, aux);
+      ok = close_active_file () && ok;
+
+      return ok;
+    }
+}
+
+/* Callback function for multipass_procedure(). */
+static bool
+multipass_callback (struct ccase *c, void *cf_) 
+{
+  struct casefile *cf = cf_;
+  return casefile_append (cf, c);
+}
+
+/* Procedure that allows multiple passes over the input data.
+   The entire active file is passed to PROC_FUNC, with the given
+   AUX as auxiliary data, as a unit. */
+bool
+multipass_procedure (bool (*proc_func) (const struct casefile *, void *aux),
+                     void *aux) 
+{
+  if (case_source_is_class (vfm_source, &storage_source_class)
+      && vfm_sink == NULL
+      && temporary_trns_chain == NULL
+      && trns_chain_is_empty (permanent_trns_chain))
+    {
+      proc_func (storage_source_get_casefile (vfm_source), aux);
+
+      expr_free (process_if_expr);
+      process_if_expr = NULL;
+      dict_set_case_limit (default_dict, 0);
+      dict_clear_vectors (default_dict);
+
+      update_last_vfm_invocation ();
+      return true;
+    }
+  else 
+    {
+      struct casefile *cf;
+      bool ok;
+
+      assert (proc_func != NULL);
+
+      cf = casefile_create (dict_get_next_value_idx (default_dict));
+
+      open_active_file ();
+      ok = internal_procedure (multipass_callback, cf);
+      ok = proc_func (cf, aux) && ok;
+      ok = close_active_file () && ok;
+
+      casefile_destroy (cf);
+
+      return ok;
+    }
+}
+
+/* Executes a procedure, as procedure(), except that the caller
+   is responsible for calling open_active_file() and
+   close_active_file().
+   Returns true if successful, false if an I/O error occurred. */
+static bool
+internal_procedure (bool (*proc_func) (struct ccase *, void *), void *aux) 
+{
+  struct write_case_data wc_data;
+  bool ok;
+
+  wc_data.proc_func = proc_func;
+  wc_data.aux = aux;
+  create_trns_case (&wc_data.trns_case, default_dict);
+  case_create (&wc_data.sink_case, dict_get_next_value_idx (default_dict));
+  wc_data.cases_written = 0;
+
+  update_last_vfm_invocation ();
+
+  ok = (vfm_source == NULL
+        || vfm_source->class->read (vfm_source,
+                                    &wc_data.trns_case,
+                                    write_case, &wc_data));
+
+  case_destroy (&wc_data.sink_case);
+  case_destroy (&wc_data.trns_case);
+
+  return ok;
+}
+
+/* Updates last_vfm_invocation. */
+static void
+update_last_vfm_invocation (void) 
+{
+  last_vfm_invocation = time (NULL);
+}
+
+/* Creates and returns a case, initializing it from the vectors
+   that say which `value's need to be initialized just once, and
+   which ones need to be re-initialized before every case. */
+static void
+create_trns_case (struct ccase *trns_case, struct dictionary *dict)
+{
+  size_t var_cnt = dict_get_var_cnt (dict);
+  size_t i;
+
+  case_create (trns_case, dict_get_next_value_idx (dict));
+  for (i = 0; i < var_cnt; i++) 
+    {
+      struct variable *v = dict_get_var (dict, i);
+      union value *value = case_data_rw (trns_case, v->fv);
+
+      if (v->type == NUMERIC)
+        value->f = v->leave ? 0.0 : SYSMIS;
+      else
+        memset (value->s, ' ', v->width);
+    }
+}
+
+/* Makes all preparations for reading from the data source and writing
+   to the data sink. */
+static void
+open_active_file (void)
+{
+  add_case_limit_trns ();
+  add_filter_trns ();
+  add_process_if_trns ();
+
+  /* Finalize transformations. */
+  trns_chain_finalize (cur_trns_chain);
+
+  /* Make permanent_dict refer to the dictionary right before
+     data reaches the sink. */
+  if (permanent_dict == NULL)
+    permanent_dict = default_dict;
+
+  /* Figure out compaction. */
+  compactor = (dict_needs_compaction (permanent_dict)
+               ? dict_make_compactor (permanent_dict)
+               : NULL);
+
+  /* Prepare sink. */
+  if (vfm_sink == NULL)
+    vfm_sink = create_case_sink (&storage_sink_class, permanent_dict, NULL);
+  if (vfm_sink->class->open != NULL)
+    vfm_sink->class->open (vfm_sink);
+
+  /* Allocate memory for lag queue. */
+  if (n_lag > 0)
+    {
+      int i;
+  
+      lag_count = 0;
+      lag_head = 0;
+      lag_queue = xnmalloc (n_lag, sizeof *lag_queue);
+      for (i = 0; i < n_lag; i++)
+        case_nullify (&lag_queue[i]);
+    }
+}
+
+/* Transforms trns_case and writes it to the replacement active
+   file if advisable.  Returns true if more cases can be
+   accepted, false otherwise.  Do not call this function again
+   after it has returned false once.  */
+static bool
+write_case (struct write_case_data *wc_data)
+{
+  enum trns_result retval;
+  size_t case_nr;
+  
+  /* Execute permanent transformations.  */
+  case_nr = wc_data->cases_written + 1;
+  retval = trns_chain_execute (permanent_trns_chain,
+                               &wc_data->trns_case, &case_nr);
+  if (retval != TRNS_CONTINUE)
+    goto done;
+
+  /* Write case to LAG queue. */
+  if (n_lag)
+    lag_case (&wc_data->trns_case);
+
+  /* Write case to replacement active file. */
+  wc_data->cases_written++;
+  if (vfm_sink->class->write != NULL) 
+    {
+      if (compactor != NULL) 
+        {
+          dict_compactor_compact (compactor, &wc_data->sink_case,
+                                  &wc_data->trns_case);
+          vfm_sink->class->write (vfm_sink, &wc_data->sink_case);
+        }
+      else
+        vfm_sink->class->write (vfm_sink, &wc_data->trns_case);
+    }
+  
+  /* Execute temporary transformations. */
+  if (temporary_trns_chain != NULL) 
+    {
+      retval = trns_chain_execute (temporary_trns_chain,
+                                   &wc_data->trns_case,
+                                   &wc_data->cases_written);
+      if (retval != TRNS_CONTINUE)
+        goto done;
+    }
+
+  /* Pass case to procedure. */
+  wc_data->cases_analyzed++;
+  if (wc_data->proc_func != NULL)
+    if (!wc_data->proc_func (&wc_data->trns_case, wc_data->aux))
+      retval = TRNS_ERROR;
+
+ done:
+  clear_case (&wc_data->trns_case);
+  return retval != TRNS_ERROR;
+}
+
+/* Add C to the lag queue. */
+static void
+lag_case (const struct ccase *c)
+{
+  if (lag_count < n_lag)
+    lag_count++;
+  case_destroy (&lag_queue[lag_head]);
+  case_clone (&lag_queue[lag_head], c);
+  if (++lag_head >= n_lag)
+    lag_head = 0;
+}
+
+/* Clears the variables in C that need to be cleared between
+   processing cases.  */
+static void
+clear_case (struct ccase *c)
+{
+  size_t var_cnt = dict_get_var_cnt (default_dict);
+  size_t i;
+  
+  for (i = 0; i < var_cnt; i++) 
+    {
+      struct variable *v = dict_get_var (default_dict, i);
+      if (!v->leave) 
+        {
+          if (v->type == NUMERIC)
+            case_data_rw (c, v->fv)->f = SYSMIS;
+          else
+            memset (case_data_rw (c, v->fv)->s, ' ', v->width);
+        } 
+    }
+}
+
+/* Closes the active file. */
+static bool
+close_active_file (void)
+{
+  /* Free memory for lag queue, and turn off lagging. */
+  if (n_lag > 0)
+    {
+      int i;
+      
+      for (i = 0; i < n_lag; i++)
+       case_destroy (&lag_queue[i]);
+      free (lag_queue);
+      n_lag = 0;
+    }
+  
+  /* Dictionary from before TEMPORARY becomes permanent. */
+  proc_cancel_temporary_transformations ();
+
+  /* Finish compaction. */
+  if (compactor != NULL) 
+    {
+      dict_compactor_destroy (compactor);
+      dict_compact_values (default_dict); 
+    }
+    
+  /* Free data source. */
+  free_case_source (vfm_source);
+  vfm_source = NULL;
+
+  /* Old data sink becomes new data source. */
+  if (vfm_sink->class->make_source != NULL)
+    vfm_source = vfm_sink->class->make_source (vfm_sink);
+  free_case_sink (vfm_sink);
+  vfm_sink = NULL;
+
+  /* Cancel TEMPORARY, PROCESS IF, FILTER, N OF CASES, vectors,
+     and get rid of all the transformations. */
+  dict_clear_vectors (default_dict);
+  permanent_dict = NULL;
+  return proc_cancel_all_transformations ();
+}
+\f
+/* Returns a pointer to the lagged case from N_BEFORE cases before the
+   current one, or NULL if there haven't been that many cases yet. */
+struct ccase *
+lagged_case (int n_before)
+{
+  assert (n_before >= 1 );
+  assert (n_before <= n_lag);
+
+  if (n_before <= lag_count)
+    {
+      int index = lag_head - n_before;
+      if (index < 0)
+        index += n_lag;
+      return &lag_queue[index];
+    }
+  else
+    return NULL;
+}
+\f
+/* Represents auxiliary data for handling SPLIT FILE. */
+struct split_aux_data 
+  {
+    size_t case_count;          /* Number of cases so far. */
+    struct ccase prev_case;     /* Data in previous case. */
+
+    /* Functions to call... */
+    void (*begin_func) (void *);               /* ...before data. */
+    bool (*proc_func) (struct ccase *, void *); /* ...with data. */
+    void (*end_func) (void *);                 /* ...after data. */
+    void *func_aux;                            /* Auxiliary data. */ 
+  };
+
+static int equal_splits (const struct ccase *, const struct ccase *);
+static bool procedure_with_splits_callback (struct ccase *, void *);
+static void dump_splits (struct ccase *);
+
+/* Like procedure(), but it automatically breaks the case stream
+   into SPLIT FILE break groups.  Before each group of cases with
+   identical SPLIT FILE variable values, BEGIN_FUNC is called.
+   Then PROC_FUNC is called with each case in the group.  
+   END_FUNC is called when the group is finished.  FUNC_AUX is
+   passed to each of the functions as auxiliary data.
+
+   If the active file is empty, none of BEGIN_FUNC, PROC_FUNC,
+   and END_FUNC will be called at all. 
+
+   If SPLIT FILE is not in effect, then there is one break group
+   (if the active file is nonempty), and BEGIN_FUNC and END_FUNC
+   will be called once.
+   
+   Returns true if successful, false if an I/O error occurred. */
+bool
+procedure_with_splits (void (*begin_func) (void *aux),
+                       bool (*proc_func) (struct ccase *, void *aux),
+                       void (*end_func) (void *aux),
+                       void *func_aux) 
+{
+  struct split_aux_data split_aux;
+  bool ok;
+
+  split_aux.case_count = 0;
+  case_nullify (&split_aux.prev_case);
+  split_aux.begin_func = begin_func;
+  split_aux.proc_func = proc_func;
+  split_aux.end_func = end_func;
+  split_aux.func_aux = func_aux;
+
+  open_active_file ();
+  ok = internal_procedure (procedure_with_splits_callback, &split_aux);
+  if (split_aux.case_count > 0 && end_func != NULL)
+    end_func (func_aux);
+  if (!close_active_file ())
+    ok = false;
+
+  case_destroy (&split_aux.prev_case);
+
+  return ok;
+}
+
+/* procedure() callback used by procedure_with_splits(). */
+static bool
+procedure_with_splits_callback (struct ccase *c, void *split_aux_) 
+{
+  struct split_aux_data *split_aux = split_aux_;
+
+  /* Start a new series if needed. */
+  if (split_aux->case_count == 0
+      || !equal_splits (c, &split_aux->prev_case))
+    {
+      if (split_aux->case_count > 0 && split_aux->end_func != NULL)
+        split_aux->end_func (split_aux->func_aux);
+
+      dump_splits (c);
+      case_destroy (&split_aux->prev_case);
+      case_clone (&split_aux->prev_case, c);
+
+      if (split_aux->begin_func != NULL)
+       split_aux->begin_func (split_aux->func_aux);
+    }
+
+  split_aux->case_count++;
+  if (split_aux->proc_func != NULL)
+    return split_aux->proc_func (c, split_aux->func_aux);
+  else
+    return true;
+}
+
+/* Compares the SPLIT FILE variables in cases A and B and returns
+   nonzero only if they differ. */
+static int
+equal_splits (const struct ccase *a, const struct ccase *b) 
+{
+  return case_compare (a, b,
+                       dict_get_split_vars (default_dict),
+                       dict_get_split_cnt (default_dict)) == 0;
+}
+
+/* Dumps out the values of all the split variables for the case C. */
+static void
+dump_splits (struct ccase *c)
+{
+  struct variable *const *split;
+  struct tab_table *t;
+  size_t split_cnt;
+  int i;
+
+  split_cnt = dict_get_split_cnt (default_dict);
+  if (split_cnt == 0)
+    return;
+
+  t = tab_create (3, split_cnt + 1, 0);
+  tab_dim (t, tab_natural_dimensions);
+  tab_vline (t, TAL_GAP, 1, 0, split_cnt);
+  tab_vline (t, TAL_GAP, 2, 0, split_cnt);
+  tab_text (t, 0, 0, TAB_NONE, _("Variable"));
+  tab_text (t, 1, 0, TAB_LEFT, _("Value"));
+  tab_text (t, 2, 0, TAB_LEFT, _("Label"));
+  split = dict_get_split_vars (default_dict);
+  for (i = 0; i < split_cnt; i++)
+    {
+      struct variable *v = split[i];
+      char temp_buf[80];
+      const char *val_lab;
+
+      assert (v->type == NUMERIC || v->type == ALPHA);
+      tab_text (t, 0, i + 1, TAB_LEFT | TAT_PRINTF, "%s", v->name);
+      
+      data_out (temp_buf, &v->print, case_data (c, v->fv));
+      
+      temp_buf[v->print.w] = 0;
+      tab_text (t, 1, i + 1, TAT_PRINTF, "%.*s", v->print.w, temp_buf);
+
+      val_lab = val_labs_find (v->val_labs, *case_data (c, v->fv));
+      if (val_lab)
+       tab_text (t, 2, i + 1, TAB_LEFT, val_lab);
+    }
+  tab_flags (t, SOMF_NO_TITLE);
+  tab_submit (t);
+}
+\f
+/* Represents auxiliary data for handling SPLIT FILE in a
+   multipass procedure. */
+struct multipass_split_aux_data 
+  {
+    struct ccase prev_case;     /* Data in previous case. */
+    struct casefile *casefile;  /* Accumulates data for a split. */
+
+    /* Function to call with the accumulated data. */
+    bool (*split_func) (const struct casefile *, void *);
+    void *func_aux;                            /* Auxiliary data. */ 
+  };
+
+static bool multipass_split_callback (struct ccase *c, void *aux_);
+static bool multipass_split_output (struct multipass_split_aux_data *);
+
+/* Returns true if successful, false if an I/O error occurred. */
+bool
+multipass_procedure_with_splits (bool (*split_func) (const struct casefile *,
+                                                     void *),
+                                 void *func_aux) 
+{
+  struct multipass_split_aux_data aux;
+  bool ok;
+
+  assert (split_func != NULL);
+
+  open_active_file ();
+
+  case_nullify (&aux.prev_case);
+  aux.casefile = NULL;
+  aux.split_func = split_func;
+  aux.func_aux = func_aux;
+
+  ok = internal_procedure (multipass_split_callback, &aux);
+  if (aux.casefile != NULL)
+    ok = multipass_split_output (&aux) && ok;
+  case_destroy (&aux.prev_case);
+
+  if (!close_active_file ())
+    ok = false;
+
+  return ok;
+}
+
+/* procedure() callback used by multipass_procedure_with_splits(). */
+static bool
+multipass_split_callback (struct ccase *c, void *aux_)
+{
+  struct multipass_split_aux_data *aux = aux_;
+  bool ok = true;
+
+  /* Start a new series if needed. */
+  if (aux->casefile == NULL || !equal_splits (c, &aux->prev_case))
+    {
+      /* Pass any cases to split_func. */
+      if (aux->casefile != NULL)
+        ok = multipass_split_output (aux);
+
+      /* Start a new casefile. */
+      aux->casefile = casefile_create (dict_get_next_value_idx (default_dict));
+
+      /* Record split values. */
+      dump_splits (c);
+      case_destroy (&aux->prev_case);
+      case_clone (&aux->prev_case, c);
+    }
+
+  return casefile_append (aux->casefile, c) && ok;
+}
+
+static bool
+multipass_split_output (struct multipass_split_aux_data *aux)
+{
+  bool ok;
+  
+  assert (aux->casefile != NULL);
+  ok = aux->split_func (aux->casefile, aux->func_aux);
+  casefile_destroy (aux->casefile);
+  aux->casefile = NULL;
+
+  return ok;
+}
+
+/* Discards all the current state in preparation for a data-input
+   command like DATA LIST or GET. */
+void
+discard_variables (void)
+{
+  dict_clear (default_dict);
+  fh_set_default_handle (NULL);
+
+  n_lag = 0;
+  
+  if (vfm_source != NULL)
+    {
+      free_case_source (vfm_source);
+      vfm_source = NULL;
+    }
+
+  proc_cancel_all_transformations ();
+
+  expr_free (process_if_expr);
+  process_if_expr = NULL;
+
+  proc_cancel_temporary_transformations ();
+}
+\f
+/* Returns the current set of permanent transformations,
+   and clears the permanent transformations.
+   For use by INPUT PROGRAM. */
+struct trns_chain *
+proc_capture_transformations (void) 
+{
+  struct trns_chain *chain;
+  
+  assert (temporary_trns_chain == NULL);
+  chain = permanent_trns_chain;
+  cur_trns_chain = permanent_trns_chain = trns_chain_create ();
+  return chain;
+}
+
+/* Adds a transformation that processes a case with PROC and
+   frees itself with FREE to the current set of transformations.
+   The functions are passed AUX as auxiliary data. */
+void
+add_transformation (trns_proc_func *proc, trns_free_func *free, void *aux)
+{
+  trns_chain_append (cur_trns_chain, NULL, proc, free, aux);
+}
+
+/* Adds a transformation that processes a case with PROC and
+   frees itself with FREE to the current set of transformations.
+   When parsing of the block of transformations is complete,
+   FINALIZE will be called.
+   The functions are passed AUX as auxiliary data. */
+void
+add_transformation_with_finalizer (trns_finalize_func *finalize,
+                                   trns_proc_func *proc,
+                                   trns_free_func *free, void *aux)
+{
+  trns_chain_append (cur_trns_chain, finalize, proc, free, aux);
+}
+
+/* Returns the index of the next transformation.
+   This value can be returned by a transformation procedure
+   function to indicate a "jump" to that transformation. */
+size_t
+next_transformation (void) 
+{
+  return trns_chain_next (cur_trns_chain);
+}
+
+/* Returns true if the next call to add_transformation() will add
+   a temporary transformation, false if it will add a permanent
+   transformation. */
+bool
+proc_in_temporary_transformations (void) 
+{
+  return temporary_trns_chain != NULL;
+}
+
+/* Marks the start of temporary transformations.
+   Further calls to add_transformation() will add temporary
+   transformations. */
+void
+proc_start_temporary_transformations (void) 
+{
+  if (!proc_in_temporary_transformations ())
+    {
+      add_case_limit_trns ();
+
+      permanent_dict = dict_clone (default_dict);
+      trns_chain_finalize (permanent_trns_chain);
+      temporary_trns_chain = cur_trns_chain = trns_chain_create ();
+    }
+}
+
+/* Converts all the temporary transformations, if any, to
+   permanent transformations.  Further transformations will be
+   permanent.
+   Returns true if anything changed, false otherwise. */
+bool
+proc_make_temporary_transformations_permanent (void) 
+{
+  if (proc_in_temporary_transformations ()) 
+    {
+      trns_chain_finalize (temporary_trns_chain);
+      trns_chain_splice (permanent_trns_chain, temporary_trns_chain);
+      temporary_trns_chain = NULL;
+
+      dict_destroy (permanent_dict);
+      permanent_dict = NULL;
+
+      return true;
+    }
+  else
+    return false;
+}
+
+/* Cancels all temporary transformations, if any.  Further
+   transformations will be permanent.
+   Returns true if anything changed, false otherwise. */
+bool
+proc_cancel_temporary_transformations (void) 
+{
+  if (proc_in_temporary_transformations ()) 
+    {
+      dict_destroy (default_dict);
+      default_dict = permanent_dict;
+      permanent_dict = NULL;
+
+      trns_chain_destroy (temporary_trns_chain);
+      temporary_trns_chain = NULL;
+
+      return true;
+    }
+  else
+    return false;
+}
+
+/* Cancels all transformations, if any.
+   Returns true if successful, false on I/O error. */
+bool
+proc_cancel_all_transformations (void)
+{
+  bool ok;
+  ok = trns_chain_destroy (permanent_trns_chain);
+  ok = trns_chain_destroy (temporary_trns_chain) && ok;
+  permanent_trns_chain = cur_trns_chain = trns_chain_create ();
+  temporary_trns_chain = NULL;
+  return ok;
+}
+\f
+/* Initializes procedure handling. */
+void
+proc_init (void) 
+{
+  default_dict = dict_create ();
+  proc_cancel_all_transformations ();
+}
+
+/* Finishes up procedure handling. */
+void
+proc_done (void)
+{
+  discard_variables ();
+}
+
+/* Sets SINK as the destination for procedure output from the
+   next procedure. */
+void
+proc_set_sink (struct case_sink *sink) 
+{
+  assert (vfm_sink == NULL);
+  vfm_sink = sink;
+}
+
+/* Sets SOURCE as the source for procedure input for the next
+   procedure. */
+void
+proc_set_source (struct case_source *source) 
+{
+  assert (vfm_source == NULL);
+  vfm_source = source;
+}
+
+/* Returns true if a source for the next procedure has been
+   configured, false otherwise. */
+bool
+proc_has_source (void) 
+{
+  return vfm_source != NULL;
+}
+
+/* Returns the output from the previous procedure.
+   For use only immediately after executing a procedure.
+   The returned casefile is owned by the caller; it will not be
+   automatically used for the next procedure's input. */
+struct casefile *
+proc_capture_output (void) 
+{
+  struct casefile *casefile;
+
+  /* Try to make sure that this function is called immediately
+     after procedure() or a similar function. */
+  assert (vfm_source != NULL);
+  assert (case_source_is_class (vfm_source, &storage_source_class));
+  assert (trns_chain_is_empty (permanent_trns_chain));
+  assert (!proc_in_temporary_transformations ());
+
+  casefile = storage_source_decapsulate (vfm_source);
+  vfm_source = NULL;
+
+  return casefile;
+}
+\f
+static trns_proc_func case_limit_trns_proc;
+static trns_free_func case_limit_trns_free;
+
+/* Adds a transformation that limits the number of cases that may
+   pass through, if default_dict has a case limit. */
+static void
+add_case_limit_trns (void) 
+{
+  size_t case_limit = dict_get_case_limit (default_dict);
+  if (case_limit != 0)
+    {
+      size_t *cases_remaining = xmalloc (sizeof *cases_remaining);
+      *cases_remaining = case_limit;
+      add_transformation (case_limit_trns_proc, case_limit_trns_free,
+                          cases_remaining);
+      dict_set_case_limit (default_dict, 0);
+    }
+}
+
+/* Limits the maximum number of cases processed to
+   *CASES_REMAINING. */
+static int
+case_limit_trns_proc (void *cases_remaining_,
+                      struct ccase *c UNUSED, int case_nr UNUSED) 
+{
+  size_t *cases_remaining = cases_remaining_;
+  if (*cases_remaining > 0) 
+    {
+      *cases_remaining--;
+      return TRNS_CONTINUE;
+    }
+  else
+    return TRNS_DROP_CASE;
+}
+
+/* Frees the data associated with a case limit transformation. */
+static bool
+case_limit_trns_free (void *cases_remaining_) 
+{
+  size_t *cases_remaining = cases_remaining_;
+  free (cases_remaining);
+  return true;
+}
+\f
+static trns_proc_func filter_trns_proc;
+
+/* Adds a temporary transformation to filter data according to
+   the variable specified on FILTER, if any. */
+static void
+add_filter_trns (void) 
+{
+  struct variable *filter_var = dict_get_filter (default_dict);
+  if (filter_var != NULL) 
+    {
+      proc_start_temporary_transformations ();
+      add_transformation (filter_trns_proc, NULL, filter_var);
+    }
+}
+
+/* FILTER transformation. */
+static int
+filter_trns_proc (void *filter_var_,
+                  struct ccase *c UNUSED, int case_nr UNUSED) 
+  
+{
+  struct variable *filter_var = filter_var_;
+  double f = case_num (c, filter_var->fv);
+  return (f != 0.0 && !mv_is_num_missing (&filter_var->miss, f)
+          ? TRNS_CONTINUE : TRNS_DROP_CASE);
+}
+\f
+static trns_proc_func process_if_trns_proc;
+static trns_free_func process_if_trns_free;
+
+/* Adds a temporary transformation to filter data according to
+   the expression specified on PROCESS IF, if any. */
+static void
+add_process_if_trns (void) 
+{
+  if (process_if_expr != NULL) 
+    {
+      proc_start_temporary_transformations ();
+      add_transformation (process_if_trns_proc, process_if_trns_free,
+                          process_if_expr);
+      process_if_expr = NULL;
+    }
+}
+
+/* PROCESS IF transformation. */
+static int
+process_if_trns_proc (void *expression_,
+                      struct ccase *c UNUSED, int case_nr UNUSED) 
+  
+{
+  struct expression *expression = expression_;
+  return (expr_evaluate_num (expression, c, case_nr) == 1.0
+          ? TRNS_CONTINUE : TRNS_DROP_CASE);
+}
+
+/* Frees a PROCESS IF transformation. */
+static bool
+process_if_trns_free (void *expression_) 
+{
+  struct expression *expression = expression_;
+  expr_free (expression);
+  return true;
+}
diff --git a/src/data/procedure.h b/src/data/procedure.h
new file mode 100644 (file)
index 0000000..5a19687
--- /dev/null
@@ -0,0 +1,83 @@
+/* PSPP - computes sample statistics.
+   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
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 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, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA. */
+
+#ifndef PROCEDURE_H
+#define PROCEDURE_H 1
+
+#include <time.h>
+#include <stdbool.h>
+#include <data/transformations.h>
+
+struct ccase;
+struct casefile;
+struct case_sink;
+struct case_source;
+
+/* Dictionary produced by permanent and temporary transformations
+   on data from the source. */
+extern struct dictionary *default_dict;
+\f
+/* Transformations. */
+
+void add_transformation (trns_proc_func *, trns_free_func *, void *);
+void add_transformation_with_finalizer (trns_finalize_func *,
+                                        trns_proc_func *,
+                                        trns_free_func *, void *);
+size_t next_transformation (void);
+
+void discard_variables (void);
+
+bool proc_cancel_all_transformations (void);
+struct trns_chain *proc_capture_transformations (void);
+
+void proc_start_temporary_transformations (void);
+bool proc_in_temporary_transformations (void);
+bool proc_make_temporary_transformations_permanent (void);
+bool proc_cancel_temporary_transformations (void);
+\f
+/* Procedures. */
+
+void proc_init (void);
+void proc_done (void);
+
+void proc_set_source (struct case_source *);
+bool proc_has_source (void);
+
+void proc_set_sink (struct case_sink *);
+struct casefile *proc_capture_output (void);
+
+bool procedure (bool (*proc_func) (struct ccase *, void *aux), void *aux);
+bool procedure_with_splits (void (*begin_func) (void *aux),
+                            bool (*proc_func) (struct ccase *, void *aux),
+                            void (*end_func) (void *aux),
+                            void *aux);
+bool multipass_procedure (bool (*proc_func) (const struct casefile *,
+                                             void *aux),
+                          void *aux);
+bool multipass_procedure_with_splits (bool (*) (const struct casefile *,
+                                                void *),
+                                      void *aux);
+time_t time_of_last_procedure (void);
+\f
+/* Number of cases to lag. */
+extern int n_lag;
+
+struct ccase *lagged_case (int n_before);
+
+#endif /* procedure.h */
index e5542b882e94a4b3d928078c546ef67cc02c6d5f..675e1c91d95b682b87acb05a3d477125398e88d5 100644 (file)
@@ -25,7 +25,6 @@
 #include <stdlib.h>
 
 #include <libpspp/str.h>
-#include <procedure.h>
 
 #include "xalloc.h"
 
index b5002caedfba30eea2c1a2580f066fa891b050ee..1e040d6c677deb202604844e746c25c3d9555d18 100644 (file)
@@ -28,6 +28,7 @@
 #include <unistd.h>
 
 #include <data/dictionary.h>
+#include <data/procedure.h>
 #include <data/settings.h>
 #include <data/variable.h>
 #include <language/lexer/lexer.h>
@@ -38,7 +39,6 @@
 #include <libpspp/str.h>
 #include <output/manager.h>
 #include <output/table.h>
-#include <procedure.h>
 
 #if HAVE_SYS_WAIT_H
 #include <sys/wait.h>
index 0c0ead940b744124af9a4830ce18a4f3cb80cbe4..47fceee6781bbb3d158b6073ea24cfa210132315 100644 (file)
@@ -22,7 +22,7 @@
 #include <stdlib.h>
 
 #include "control-stack.h"
-#include <procedure.h>
+#include <data/procedure.h>
 #include <data/transformations.h>
 #include <data/variable.h>
 #include <language/command.h>
index abbc44675841afe3dfef4454504091ee7792eace..f31486f605f7bd7680257bf4dd0710738374b02a 100644 (file)
@@ -22,7 +22,7 @@
 #include "control-stack.h"
 #include <data/case.h>
 #include <data/dictionary.h>
-#include <procedure.h>
+#include <data/procedure.h>
 #include <data/settings.h>
 #include <data/transformations.h>
 #include <data/variable.h>
index ec37382b56caa0f27bc5a93273458233f259c3ba..bc4b8295b74b7a5fedbd37fd5c4ef6edbb627fa2 100644 (file)
@@ -26,7 +26,7 @@
 #include <stdlib.h>
 
 #include <data/dictionary.h>
-#include <procedure.h>
+#include <data/procedure.h>
 #include <data/settings.h>
 #include <language/command.h>
 #include <language/lexer/lexer.h>
index 2424c2551de8e552025b9b132a05af227bc6daa5..6cfd48ec981f1a20f8524b041e7368813fcb47a8 100644 (file)
@@ -24,7 +24,7 @@
 
 #include "control-stack.h"
 #include <data/dictionary.h>
-#include <procedure.h>
+#include <data/procedure.h>
 #include <data/transformations.h>
 #include <data/value-labels.h>
 #include <data/variable.h>
index a778b5d8b166c55f91b25e8b6c14a4cf39a113a4..89505dbc805871b3f5cf7d02ac4c3f070ee7de62 100644 (file)
@@ -30,6 +30,7 @@
 #include <data/data-in.h>
 #include <data/dictionary.h>
 #include <data/format.h>
+#include <data/procedure.h>
 #include <data/settings.h>
 #include <data/transformations.h>
 #include <data/variable.h>
@@ -45,7 +46,6 @@
 #include <libpspp/misc.h>
 #include <libpspp/str.h>
 #include <output/table.h>
-#include <procedure.h>
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
index 8fc7a80ad7b0dc0ce3d894c6733e2e46fea9c83d..a8b484d469010808af15ac90e9098225086c9123 100644 (file)
    02110-1301, USA. */
 
 #include <config.h>
+
 #include <language/data-io/data-reader.h>
+
 #include <ctype.h>
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <libpspp/alloc.h>
-#include <language/command.h>
-#include <libpspp/message.h>
-#include <language/data-io/file-handle.h>
+
 #include <data/file-handle-def.h>
 #include <data/file-name.h>
-#include <language/line-buffer.h>
+#include <data/procedure.h>
+#include <language/command.h>
+#include <language/data-io/file-handle.h>
 #include <language/lexer/lexer.h>
+#include <language/line-buffer.h>
+#include <libpspp/alloc.h>
+#include <libpspp/message.h>
 #include <libpspp/str.h>
-#include <procedure.h>
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
index b9634b1942d645ba1d86aad729fca50b19e9ca2c..0cc628be098797ad6070facc032e84d66f865688 100644 (file)
@@ -28,6 +28,7 @@
 #include <data/case.h>
 #include <data/dictionary.h>
 #include <data/por-file-writer.h>
+#include <data/procedure.h>
 #include <data/settings.h>
 #include <data/storage-stream.h>
 #include <data/sys-file-writer.h>
@@ -44,7 +45,6 @@
 #include <libpspp/message.h>
 #include <libpspp/misc.h>
 #include <libpspp/str.h>
-#include <procedure.h>
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
index fbf1d3422d940c0667dda3f295cd3d6d690ef895..51c369810f9d2872810a00341a0623321f4f04c8 100644 (file)
@@ -28,6 +28,7 @@
 #include <data/case.h>
 #include <data/case-source.h>
 #include <data/dictionary.h>
+#include <data/procedure.h>
 #include <data/transformations.h>
 #include <data/variable.h>
 #include <language/command.h>
@@ -41,7 +42,6 @@
 #include <libpspp/message.h>
 #include <libpspp/misc.h>
 #include <libpspp/str.h>
-#include <procedure.h>
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
index a79c51ada6f452e7f21baa45225377bb7ba96fec..dd9a8ae1cf329b089d40c8a0994753b4cb3da7fb 100644 (file)
    02110-1301, USA. */
 
 #include <config.h>
-#include <libpspp/message.h>
+
 #include <stdio.h>
 #include <stdlib.h>
-#include <libpspp/alloc.h>
+
+#include "intprops.h"
+#include "size_max.h"
 #include <data/case.h>
-#include <language/command.h>
-#include <libpspp/compiler.h>
 #include <data/dictionary.h>
-#include "intprops.h"
+#include <data/format.h>
+#include <data/procedure.h>
+#include <data/variable.h>
+#include <language/command.h>
 #include <language/lexer/lexer.h>
-#include <libpspp/message.h>
+#include <libpspp/alloc.h>
+#include <libpspp/compiler.h>
 #include <libpspp/magic.h>
+#include <libpspp/message.h>
+#include <libpspp/message.h>
 #include <libpspp/misc.h>
 #include <output/htmlP.h>
-#include <output/output.h>
-#include "size_max.h"
 #include <output/manager.h>
+#include <output/output.h>
 #include <output/table.h>
-#include <data/variable.h>
-#include <procedure.h>
-#include <data/format.h>
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
index ff008caa412c60532cae4b5e363d93f703bf616c..d5b489c34cd1dac103bd7fc492d8b89949aa9a19 100644 (file)
@@ -27,6 +27,7 @@
 #include <data/case.h>
 #include <data/data-in.h>
 #include <data/dictionary.h>
+#include <data/procedure.h>
 #include <data/variable.h>
 #include <language/command.h>
 #include <language/data-io/data-reader.h>
@@ -40,7 +41,6 @@
 #include <libpspp/misc.h>
 #include <libpspp/pool.h>
 #include <libpspp/str.h>
-#include <procedure.h>
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
index f6633652a6847baaf244241144c3161e5e29ba0f..63270160d949dd9654776fd13ffa4e8572415cd0 100644 (file)
@@ -24,7 +24,7 @@
 #include <stdlib.h>
 
 #include <data/case.h>
-#include <procedure.h>
+#include <data/procedure.h>
 #include <data/transformations.h>
 #include <data/variable.h>
 #include <language/command.h>
index 87b71eee03ad1599ff87db765a4d8277f0a6f6a3..1c9e7ef81a19d95647f0ca7f6cb6aea90969bc2b 100644 (file)
@@ -24,7 +24,7 @@
 #include <data/any-reader.h>
 #include <data/dictionary.h>
 #include <data/file-handle-def.h>
-#include <procedure.h>
+#include <data/procedure.h>
 #include <data/value-labels.h>
 #include <data/variable.h>
 #include <language/command.h>
index 2d5e1c354dfadbbae4d9f9a0a4898426d3083757..8658634b364e64edf434243a9997fe315389ed3a 100644 (file)
@@ -23,7 +23,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 
-#include <procedure.h>
+#include <data/procedure.h>
 #include <data/variable.h>
 #include <language/command.h>
 #include <language/lexer/lexer.h>
index 0757fb1dc1def6fca52d0d6590cc87ef9d0d6642..e37fa987deddfb3dd642b777d8582a1fd3070d75 100644 (file)
@@ -22,7 +22,7 @@
 #include <stdlib.h>
 
 #include <data/data-in.h>
-#include <procedure.h>
+#include <data/procedure.h>
 #include <data/variable.h>
 #include <language/command.h>
 #include <language/lexer/lexer.h>
index ad6a48e49962ba142d8a313ee5bd83addf75ebe9..1b0a27b061016591056d3fead86ee23f28aa3bbf 100644 (file)
@@ -31,8 +31,8 @@
 #include <language/lexer/lexer.h>
 #include <libpspp/misc.h>
 #include <libpspp/str.h>
+#include <data/procedure.h>
 #include <data/variable.h>
-#include <procedure.h>
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
index f946e74a4808e61696f4bdcb563fb582904b1ceb..379348835462343d0bce897170e31bb106039506 100644 (file)
@@ -22,7 +22,7 @@
 #include <stdlib.h>
 
 #include <data/dictionary.h>
-#include <procedure.h>
+#include <data/procedure.h>
 #include <data/variable.h>
 #include <language/command.h>
 #include <language/lexer/lexer.h>
index eedc84d4c2543f0871c96c1ad3357a3b21d2b0a4..6165787fbb155431fb86b30f4a72feed3c92211b 100644 (file)
@@ -22,7 +22,7 @@
 #include <stdlib.h>
 
 #include <data/dictionary.h>
-#include <procedure.h>
+#include <data/procedure.h>
 #include <data/variable.h>
 #include <language/command.h>
 #include <language/lexer/lexer.h>
index 149523d36df741f0fcbf013496622624b51207f4..7e003018f496d4da71f2af1807778d14dcb4a5a4 100644 (file)
@@ -22,7 +22,7 @@
 #include <stdlib.h>
 
 #include <data/dictionary.h>
-#include <procedure.h>
+#include <data/procedure.h>
 #include <data/variable.h>
 #include <language/command.h>
 #include <language/lexer/lexer.h>
index 97bf3df58a9c2035151f01cff8bcb27794e16f70..13c3275e035093a5c2c7be31bd1fc479f3d2c3a6 100644 (file)
@@ -24,7 +24,7 @@
 
 #include <data/dictionary.h>
 #include <data/file-handle-def.h>
-#include <procedure.h>
+#include <data/procedure.h>
 #include <data/sys-file-reader.h>
 #include <data/value-labels.h>
 #include <data/variable.h>
index a9d3d8751799d5fc6bc1d4ea0e2184ae28858982..89e0160a82d21ce7a85716e39f250fe749c79ae5 100644 (file)
@@ -22,7 +22,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 
-#include <procedure.h>
+#include <data/procedure.h>
 #include <data/value-labels.h>
 #include <data/variable.h>
 #include <language/command.h>
index ef43c5313e4aed91b860648a8233331f780f5ab1..2348b721157b2bc6868ba81ed8f9e667eafabb69 100644 (file)
@@ -22,7 +22,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 
-#include <procedure.h>
+#include <data/procedure.h>
 #include <data/variable.h>
 #include <language/command.h>
 #include <language/lexer/lexer.h>
index 3692a6c4c2d532b2f7c8431c5a897f3bd4a294e0..7380d3d6f5a7a4e01770f13d7e22fd3802b40bee 100644 (file)
@@ -22,7 +22,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 
-#include <procedure.h>
+#include <data/procedure.h>
 #include <data/variable.h>
 #include <language/command.h>
 #include <language/lexer/lexer.h>
index 90f245c85f4b84b9ca54490667fa7fd751aeadd9..82870d9d447f8e881a80e202e47c26f8413d0b8d 100644 (file)
@@ -21,7 +21,7 @@
 
 #include <stdlib.h>
 
-#include <procedure.h>
+#include <data/procedure.h>
 #include <data/dictionary.h>
 #include <data/variable.h>
 #include <language/command.h>
index 121728b68e454b8d371e750f91cbb093eb4ab9a1..5d492c4f50ceefcad2e807f85391e0629a3dfe86 100644 (file)
@@ -21,7 +21,7 @@
 
 #include <stdio.h>
 
-#include <procedure.h>
+#include <data/procedure.h>
 #include <data/dictionary.h>
 #include <data/variable.h>
 #include <language/command.h>
index c8355550ed22f44919f57ea829cc64f020e3f494..f5cfb67b65d5dae1f912b023571e3c1650a20e1a 100644 (file)
@@ -9,21 +9,22 @@
 #include <limits.h>
 #include <math.h>
 #include <stdbool.h>
+
+#include <data/calendar.h>
 #include <data/case.h>
-#include <libpspp/compiler.h>
 #include <data/data-in.h>
 #include <data/dictionary.h>
-#include <libpspp/message.h>
-#include <data/calendar.h>
+#include <data/procedure.h>
+#include <data/settings.h>
+#include <data/value.h>
+#include <data/variable.h>
 #include <gsl-extras/gsl-extras.h>
+#include <libpspp/compiler.h>
+#include <libpspp/message.h>
 #include <libpspp/misc.h>
+#include <libpspp/str.h>
 #include <math/moments.h>
 #include <math/random.h>
-#include <data/settings.h>
-#include <libpspp/str.h>
-#include <data/value.h>
-#include <data/variable.h>
-#include <procedure.h>
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
index b6c8076ce4a1fbb3b2fbdf33ce270dd8ec121b07..715430087fa8ebb20bf088f2298c535db0624268 100644 (file)
@@ -35,7 +35,6 @@
 #include <data/settings.h>
 #include <libpspp/str.h>
 #include <data/variable.h>
-#include <procedure.h>
 \f
 /* Declarations. */
 
index 6475caf4eb951d092125f172642bdacbb81b1101..64792aaaec56ced30eadc35077efd292c7bf41a7 100644 (file)
@@ -25,7 +25,7 @@
 
 #include "lexer.h"
 #include <data/dictionary.h>
-#include <procedure.h>
+#include <data/procedure.h>
 #include <data/variable.h>
 #include <libpspp/alloc.h>
 #include <libpspp/bit-vector.h>
index e51a5a6a13724cea3a1a85357a46ffbc6e895c8a..aa289716f5a6aaaabf26a7d7ec45b38ff7434ec9 100644 (file)
@@ -27,7 +27,7 @@
 #include <data/casefile.h>
 #include <data/dictionary.h>
 #include <data/file-handle-def.h>
-#include <procedure.h>
+#include <data/procedure.h>
 #include <data/settings.h>
 #include <data/storage-stream.h>
 #include <data/sys-file-writer.h>
@@ -44,7 +44,6 @@
 #include <libpspp/str.h>
 #include <math/moments.h>
 #include <math/sort.h>
-#include <procedure.h>
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
index a4177be8e2a18ef4975b2a1a0a208a015244cc18..e808359bb17f5cc45cb57336476456c4708b46ac 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <data/case.h>
 #include <data/dictionary.h>
+#include <data/procedure.h>
 #include <data/transformations.h>
 #include <data/variable.h>
 #include <language/command.h>
@@ -33,7 +34,6 @@
 #include <libpspp/message.h>
 #include <libpspp/pool.h>
 #include <libpspp/str.h>
-#include <procedure.h>
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
index 68d55635e36d92132822632d940a1c34f4125845..594a53875c0286a6e50e4f03e0439c7650caf100 100644 (file)
@@ -23,7 +23,7 @@
 
 #include <data/dictionary.h>
 #include <data/file-handle-def.h>
-#include <procedure.h>
+#include <data/procedure.h>
 #include <data/variable.h>
 #include <language/command.h>
 #include <language/data-io/file-handle.h>
index 8f1e42b430e37f38b8977f1b18bc7a09260562f3..55c92d8c4b2e9b6e768fdcecc9aa1085dab14664 100644 (file)
 */
 
 #include <config.h>
-#include <libpspp/message.h>
+
 #include <ctype.h>
+#include <gsl/gsl_cdf.h>
 #include <stdlib.h>
 #include <stdio.h>
-#include <gsl/gsl_cdf.h>
-#include <libpspp/array.h>
-#include <libpspp/alloc.h>
+
 #include <data/case.h>
 #include <data/dictionary.h>
-#include <libpspp/hash.h>
-#include <libpspp/pool.h>
+#include <data/procedure.h>
+#include <data/value-labels.h>
+#include <data/variable.h>
 #include <language/command.h>
-#include <libpspp/compiler.h>
 #include <language/lexer/lexer.h>
-#include <libpspp/message.h>
+#include <libpspp/alloc.h>
+#include <libpspp/array.h>
+#include <libpspp/compiler.h>
+#include <libpspp/hash.h>
 #include <libpspp/magic.h>
+#include <libpspp/message.h>
+#include <libpspp/message.h>
 #include <libpspp/misc.h>
-#include <output/output.h>
+#include <libpspp/pool.h>
 #include <libpspp/str.h>
+#include <output/output.h>
 #include <output/table.h>
-#include <data/value-labels.h>
-#include <data/variable.h>
-#include <procedure.h>
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
index b72371488d226fa14ed31ea17c3bda8e08e4ac9e..4c5b7ff0a836ed268dc2843c5305d03a2dd01624 100644 (file)
@@ -28,6 +28,7 @@
 #include <data/case.h>
 #include <data/casefile.h>
 #include <data/dictionary.h>
+#include <data/procedure.h>
 #include <data/transformations.h>
 #include <data/variable.h>
 #include <language/command.h>
@@ -40,7 +41,6 @@
 #include <math/moments.h>
 #include <output/manager.h>
 #include <output/table.h>
-#include <procedure.h>
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
index 4f8e45de6c52f9aea8c3acd012a73b6d3b79bcf6..bf2c3fd17f96fac51778adcbc04604dcce86e17e 100644 (file)
@@ -19,33 +19,35 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 02110-1301, USA. */
 
 #include <config.h>
+
 #include <gsl/gsl_cdf.h>
 #include <libpspp/message.h>
+#include <math.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <math.h>
-#include <libpspp/alloc.h>
-#include <libpspp/str.h>
+
 #include <data/case.h>
+#include <data/casefile.h>
 #include <data/dictionary.h>
+#include <data/procedure.h>
+#include <data/value-labels.h>
+#include <data/variable.h>
 #include <language/command.h>
-#include <libpspp/compiler.h>
 #include <language/lexer/lexer.h>
-#include <libpspp/message.h>
+#include <libpspp/alloc.h>
+#include <libpspp/compiler.h>
+#include <libpspp/hash.h>
 #include <libpspp/magic.h>
+#include <libpspp/message.h>
 #include <libpspp/misc.h>
-#include <output/table.h>
-#include <output/manager.h>
-#include <data/value-labels.h>
-#include <data/variable.h>
-#include <procedure.h>
-#include <libpspp/hash.h>
-#include <data/casefile.h>
+#include <libpspp/str.h>
 #include <math/factor-stats.h>
 #include <math/moments.h>
 #include <math/percentiles.h>
 #include <output/charts/box-whisker.h>
 #include <output/charts/cartesian.h>
+#include <output/manager.h>
+#include <output/table.h>
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
index 02c764b57202ab73dc616d2d329d098266a10528..3aed8323e29b8830bfe305d8ab913328ff4e7486 100644 (file)
@@ -32,7 +32,7 @@
 #include <data/case-source.h>
 #include <data/case.h>
 #include <data/dictionary.h>
-#include <procedure.h>
+#include <data/procedure.h>
 #include <data/settings.h>
 #include <data/value.h>
 #include <data/variable.h>
@@ -45,7 +45,6 @@
 #include <libpspp/misc.h>
 #include <libpspp/pool.h>
 #include <libpspp/str.h>
-#include <procedure.h>
 
 #include "intprops.h"
 
index 5de38ad5f05a4786935d42a7a31dff9c9221b35d..db480bce497ff8fc574bf6140c19a1b22f713a7f 100644 (file)
 */
 
 #include <config.h>
-#include <libpspp/message.h>
+
 #include <math.h>
 #include <stdlib.h>
 #include <gsl/gsl_histogram.h>
 
-#include <libpspp/alloc.h>
-#include <libpspp/bit-vector.h>
 #include <data/case.h>
-#include <libpspp/compiler.h>
 #include <data/dictionary.h>
-#include <libpspp/hash.h>
-#include <libpspp/pool.h>
+#include <data/procedure.h>
+#include <data/settings.h>
+#include <data/value-labels.h>
+#include <data/variable.h>
 #include <language/command.h>
 #include <language/lexer/lexer.h>
-#include <math/moments.h>
-#include <libpspp/message.h>
+#include <libpspp/alloc.h>
 #include <libpspp/array.h>
+#include <libpspp/bit-vector.h>
+#include <libpspp/compiler.h>
+#include <libpspp/hash.h>
 #include <libpspp/magic.h>
+#include <libpspp/message.h>
+#include <libpspp/message.h>
 #include <libpspp/misc.h>
-#include <output/output.h>
-#include <output/manager.h>
+#include <libpspp/pool.h>
 #include <libpspp/str.h>
-#include <output/table.h>
-#include <data/value-labels.h>
-#include <data/variable.h>
-#include <procedure.h>
-#include <data/settings.h>
-#include <output/charts/piechart.h>
+#include <math/histogram.h>
+#include <math/moments.h>
 #include <output/chart.h>
+#include <output/charts/piechart.h>
 #include <output/charts/plot-hist.h>
-#include <math/histogram.h>
+#include <output/manager.h>
+#include <output/output.h>
+#include <output/table.h>
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
index 7fc176f78913c20682f1bac007b1e4cc2ff61446..a1aa7229ebaa87d0feabe9a27d5cb51df0411bc7 100644 (file)
@@ -23,7 +23,7 @@
 #include <stdio.h>
 
 #include <data/dictionary.h>
-#include <procedure.h>
+#include <data/procedure.h>
 #include <data/variable.h>
 #include <language/command.h>
 #include <language/lexer/lexer.h>
index 2ef2d4869c5c22c870dd0aad50e1350667110645..ab221e03fa0e16c85c0e1d5a32ce2de2b1286778 100644 (file)
@@ -19,32 +19,33 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 02110-1301, USA. */
 
 #include <config.h>
+
 #include <gsl/gsl_cdf.h>
-#include <libpspp/message.h>
+#include <math.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <math.h>
-#include <libpspp/alloc.h>
-#include <libpspp/str.h>
+
 #include <data/case.h>
+#include <data/casefile.h>
 #include <data/dictionary.h>
+#include <data/procedure.h>
+#include <data/value-labels.h>
+#include <data/variable.h>
 #include <language/command.h>
-#include <libpspp/compiler.h>
 #include <language/lexer/lexer.h>
-#include <libpspp/message.h>
+#include <libpspp/alloc.h>
+#include <libpspp/compiler.h>
+#include <libpspp/hash.h>
 #include <libpspp/magic.h>
+#include <libpspp/message.h>
+#include <libpspp/message.h>
 #include <libpspp/misc.h>
-#include <output/table.h>
-#include <output/manager.h>
-#include <data/value-labels.h>
-#include <data/variable.h>
-#include <procedure.h>
-#include <libpspp/hash.h>
-#include <data/casefile.h>
+#include <libpspp/str.h>
 #include <math/group-proc.h>
 #include <math/group.h>
 #include <math/levene.h>
-
+#include <output/manager.h>
+#include <output/table.h>
 #include "sort-criteria.h"
 
 #include "gettext.h"
index d3ac8edd6eb502a895992189d08fe03a8452142f..2022aaaf460a27123dd1588c9b1293d9cb8eacbf 100644 (file)
@@ -21,8 +21,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 #include <config.h>
 
 #include "sort-criteria.h"
+
 #include <data/dictionary.h>
-#include <procedure.h>
+#include <data/procedure.h>
 #include <data/variable.h>
 #include <language/command.h>
 #include <language/stats/sort-criteria.h>
index b5dabb1577ffd924e5c125541e89f5484b6bdf7a..d79007ac24a6f484471b67606aec43900e150545 100644 (file)
@@ -32,6 +32,7 @@
 #include <data/category.h>
 #include <data/dictionary.h>
 #include <data/missing-values.h>
+#include <data/procedure.h>
 #include <data/transformations.h>
 #include <data/value-labels.h>
 #include <data/variable.h>
@@ -45,7 +46,6 @@
 #include <math/linreg/coefficient.h>
 #include <math/linreg/linreg.h>
 #include <output/table.h>
-#include <procedure.h>
 
 #include "gettext.h"
 
index 156c5b42ad92de4f2e1cd920e9b04971c497d235..f50b67fec156245c32ebf328c14d5eac35aae5cc 100644 (file)
@@ -24,7 +24,7 @@
 #include <limits.h>
 
 #include "sort-criteria.h"
-#include <procedure.h>
+#include <data/procedure.h>
 #include <data/settings.h>
 #include <data/variable.h>
 #include <language/command.h>
index 4754b211297bf4182ef2be42994d47595f9bb920..6d3f4ba263fe2314baca3999c2ee1678bf4dd105 100644 (file)
    02110-1301, USA. */
 
 #include <config.h>
+
 #include <gsl/gsl_cdf.h>
-#include <libpspp/message.h>
+#include <math.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <math.h>
-#include <libpspp/alloc.h>
+
 #include <data/case.h>
 #include <data/casefile.h>
+#include <data/dictionary.h>
+#include <data/procedure.h>
+#include <data/value-labels.h>
+#include <data/variable.h>
 #include <language/command.h>
+#include <language/lexer/lexer.h>
+#include <libpspp/alloc.h>
 #include <libpspp/compiler.h>
-#include <data/dictionary.h>
-#include <libpspp/message.h>
-#include <math/group-proc.h>
 #include <libpspp/hash.h>
-#include <math/levene.h>
-#include <language/lexer/lexer.h>
 #include <libpspp/magic.h>
+#include <libpspp/message.h>
+#include <libpspp/message.h>
 #include <libpspp/misc.h>
-#include "size_max.h"
-#include <output/manager.h>
 #include <libpspp/str.h>
+#include <math/group-proc.h>
+#include <math/levene.h>
+#include <output/manager.h>
 #include <output/table.h>
-#include <data/value-labels.h>
-#include <data/variable.h>
-#include <procedure.h>
+
+#include "size_max.h"
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
index 2ad52b77a31a53cf0cd6312e7d4cbfd10aec7afc..a230c7d58a035eabea8bb79256d63b2b2a4f6419 100644 (file)
@@ -26,7 +26,7 @@
 
 #include <data/dictionary.h>
 #include <data/format.h>
-#include <procedure.h>
+#include <data/procedure.h>
 #include <data/settings.h>
 #include <data/variable.h>
 #include <language/command.h>
index d494e35e8e2cad2aa96cc1ebb736929c4ca421cf..9fa1309d3fe64e796f1d5487514a4e5f68448fe8 100644 (file)
    02110-1301, USA. */
 
 #include <config.h>
+
 #include <ctype.h>
 #include <stdlib.h>
-#include <libpspp/alloc.h>
-#include <language/command.h>
+
 #include <data/dictionary.h>
-#include <libpspp/message.h>
+#include <data/procedure.h>
+#include <data/variable.h>
+#include <language/command.h>
 #include <language/lexer/lexer.h>
-#include <output/output.h>
+#include <libpspp/alloc.h>
+#include <libpspp/message.h>
 #include <libpspp/start-date.h>
-#include <data/variable.h>
 #include <libpspp/version.h>
-#include <procedure.h>
+#include <output/output.h>
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
index 0a399285604e7da5fc967d77fd767d205d9cbaa4..0bc6e4d3fd231581fcc9448792f89d494cd964f7 100644 (file)
@@ -23,7 +23,7 @@
 
 #include <data/case.h>
 #include <data/dictionary.h>
-#include <procedure.h>
+#include <data/procedure.h>
 #include <data/transformations.h>
 #include <data/variable.h>
 #include <language/command.h>
index a8a208b3a4df4ab4371a91b26fbc6292d12906fc..8673c6de2435fd6b71ce7ad563ccc9c274885b6f 100644 (file)
@@ -23,7 +23,7 @@
 
 #include <data/case.h>
 #include <data/dictionary.h>
-#include <procedure.h>
+#include <data/procedure.h>
 #include <data/transformations.h>
 #include <data/variable.h>
 #include <language/command.h>
index c9cb203961071d556cbb2a279838fe42f36e8bb0..09eafb6a8c73c720937c5c39a330e6579805a06f 100644 (file)
@@ -26,7 +26,7 @@
 #include <data/case.h>
 #include <data/data-in.h>
 #include <data/dictionary.h>
-#include <procedure.h>
+#include <data/procedure.h>
 #include <data/transformations.h>
 #include <data/variable.h>
 #include <language/command.h>
index 830c981e703aeef1513d27dbf6989aafff2f98fd..41b47f869d34bceecfa24f1299a6f9d6cd4674c9 100644 (file)
@@ -24,6 +24,7 @@
 #include <stdio.h>
 #include <math.h>
 
+#include <data/procedure.h>
 #include <data/variable.h>
 #include <language/command.h>
 #include <language/lexer/lexer.h>
@@ -32,7 +33,6 @@
 #include <libpspp/message.h>
 #include <libpspp/str.h>
 #include <math/random.h>
-#include <procedure.h>
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
index f6be43c26a58b8c9bf802d5b44870d2c0821e9fc..4666f52db9f1964a32df42a524e249089319dbc8 100644 (file)
@@ -23,7 +23,7 @@
 
 #include <data/dictionary.h>
 #include <data/transformations.h>
-#include <procedure.h>
+#include <data/procedure.h>
 #include <data/variable.h>
 #include <language/command.h>
 #include <language/expressions/public.h>
index 7a034621d507605574010dd87ac722a4069023f4..86a32e7ab92a380763ececcc1984955eff768a10 100644 (file)
@@ -29,7 +29,7 @@
 #include <libpspp/hash.h>
 #include <libpspp/str.h>
 #include <data/variable.h>
-#include <procedure.h>
+#include <data/procedure.h>
 #include <libpspp/alloc.h>
 #include <libpspp/misc.h>
 #include "group.h"
index 8ce955384b674eb4599f98a2b072e83eaa76c64b..1d2257b246ded9d0f33f1aa3d42ad5ea40592ef5 100644 (file)
@@ -30,6 +30,7 @@
 #include <data/case-source.h>
 #include <data/case.h>
 #include <data/casefile.h>
+#include <data/procedure.h>
 #include <data/settings.h>
 #include <data/variable.h>
 #include <data/storage-stream.h>
@@ -40,7 +41,6 @@
 #include <libpspp/message.h>
 #include <libpspp/misc.h>
 #include <libpspp/str.h>
-#include <procedure.h>
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
diff --git a/src/procedure.c b/src/procedure.c
deleted file mode 100644 (file)
index 9b94da0..0000000
+++ /dev/null
@@ -1,1016 +0,0 @@
-/* PSPP - computes sample statistics.
-   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
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 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, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, USA. */
-
-#include <config.h>
-
-#include <procedure.h>
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include "expressions/public.h"
-#include <data/case-source.h>
-#include <data/case-sink.h>
-#include <data/case.h>
-#include <data/casefile.h>
-#include <data/dictionary.h>
-#include <data/file-handle-def.h>
-#include <data/settings.h>
-#include <data/storage-stream.h>
-#include <data/transformations.h>
-#include <data/value-labels.h>
-#include <data/variable.h>
-#include <libpspp/alloc.h>
-#include <libpspp/message.h>
-#include <libpspp/misc.h>
-#include <libpspp/str.h>
-#include <output/manager.h>
-#include <output/table.h>
-
-#include "gettext.h"
-#define _(msgid) gettext (msgid)
-
-/*
-   Virtual File Manager (vfm):
-
-   vfm is used to process data files.  It uses the model that
-   data is read from one stream (the data source), processed,
-   then written to another (the data sink).  The data source is
-   then deleted and the data sink becomes the data source for the
-   next procedure. */
-
-/* Procedure execution data. */
-struct write_case_data
-  {
-    /* Function to call for each case. */
-    bool (*proc_func) (struct ccase *, void *); /* Function. */
-    void *aux;                                 /* Auxiliary data. */ 
-
-    struct ccase trns_case;     /* Case used for transformations. */
-    struct ccase sink_case;     /* Case written to sink, if
-                                   compaction is necessary. */
-    size_t cases_written;       /* Cases output so far. */
-    size_t cases_analyzed;      /* Cases passed to procedure so far. */
-  };
-
-/* Cases are read from vfm_source,
-   pass through permanent_trns_chain (which transforms them into
-   the format described by permanent_dict),
-   are written to vfm_sink,
-   pass through temporary_trns_chain (which transforms them into
-   the format described by default_dict),
-   and are finally passed to the procedure. */
-static struct case_source *vfm_source;
-static struct trns_chain *permanent_trns_chain;
-static struct dictionary *permanent_dict;
-static struct case_sink *vfm_sink;
-static struct trns_chain *temporary_trns_chain;
-struct dictionary *default_dict;
-
-/* The transformation chain that the next transformation will be
-   added to. */
-static struct trns_chain *cur_trns_chain;
-
-/* The compactor used to compact a case, if necessary;
-   otherwise a null pointer. */
-static struct dict_compactor *compactor;
-
-/* Time at which vfm was last invoked. */
-static time_t last_vfm_invocation;
-
-/* Lag queue. */
-int n_lag;                     /* Number of cases to lag. */
-static int lag_count;          /* Number of cases in lag_queue so far. */
-static int lag_head;           /* Index where next case will be added. */
-static struct ccase *lag_queue; /* Array of n_lag ccase * elements. */
-
-static void add_case_limit_trns (void);
-static void add_filter_trns (void);
-static void add_process_if_trns (void);
-
-static bool internal_procedure (bool (*proc_func) (struct ccase *, void *),
-                                void *aux);
-static void update_last_vfm_invocation (void);
-static void create_trns_case (struct ccase *, struct dictionary *);
-static void open_active_file (void);
-static bool write_case (struct write_case_data *wc_data);
-static void lag_case (const struct ccase *c);
-static void clear_case (struct ccase *c);
-static bool close_active_file (void);
-\f
-/* Public functions. */
-
-/* Returns the last time the data was read. */
-time_t
-time_of_last_procedure (void) 
-{
-  if (last_vfm_invocation == 0)
-    update_last_vfm_invocation ();
-  return last_vfm_invocation;
-}
-
-/* Reads the data from the input program and writes it to a new
-   active file.  For each case we read from the input program, we
-   do the following:
-
-   1. Execute permanent transformations.  If these drop the case,
-      start the next case from step 1.
-
-   2. Write case to replacement active file.
-   
-   3. Execute temporary transformations.  If these drop the case,
-      start the next case from step 1.
-      
-   4. Pass case to PROC_FUNC, passing AUX as auxiliary data.
-
-   Returns true if successful, false if an I/O error occurred. */
-bool
-procedure (bool (*proc_func) (struct ccase *, void *), void *aux)
-{
-  if (proc_func == NULL
-      && case_source_is_class (vfm_source, &storage_source_class)
-      && vfm_sink == NULL
-      && temporary_trns_chain == NULL
-      && trns_chain_is_empty (permanent_trns_chain))
-    {
-      expr_free (process_if_expr);
-      process_if_expr = NULL;
-      dict_set_case_limit (default_dict, 0);
-      dict_clear_vectors (default_dict);
-
-      update_last_vfm_invocation ();
-      return true;
-    }
-  else 
-    {
-      bool ok;
-      
-      open_active_file ();
-      ok = internal_procedure (proc_func, aux);
-      ok = close_active_file () && ok;
-
-      return ok;
-    }
-}
-
-/* Callback function for multipass_procedure(). */
-static bool
-multipass_callback (struct ccase *c, void *cf_) 
-{
-  struct casefile *cf = cf_;
-  return casefile_append (cf, c);
-}
-
-/* Procedure that allows multiple passes over the input data.
-   The entire active file is passed to PROC_FUNC, with the given
-   AUX as auxiliary data, as a unit. */
-bool
-multipass_procedure (bool (*proc_func) (const struct casefile *, void *aux),
-                     void *aux) 
-{
-  if (case_source_is_class (vfm_source, &storage_source_class)
-      && vfm_sink == NULL
-      && temporary_trns_chain == NULL
-      && trns_chain_is_empty (permanent_trns_chain))
-    {
-      proc_func (storage_source_get_casefile (vfm_source), aux);
-
-      expr_free (process_if_expr);
-      process_if_expr = NULL;
-      dict_set_case_limit (default_dict, 0);
-      dict_clear_vectors (default_dict);
-
-      update_last_vfm_invocation ();
-      return true;
-    }
-  else 
-    {
-      struct casefile *cf;
-      bool ok;
-
-      assert (proc_func != NULL);
-
-      cf = casefile_create (dict_get_next_value_idx (default_dict));
-
-      open_active_file ();
-      ok = internal_procedure (multipass_callback, cf);
-      ok = proc_func (cf, aux) && ok;
-      ok = close_active_file () && ok;
-
-      casefile_destroy (cf);
-
-      return ok;
-    }
-}
-
-/* Executes a procedure, as procedure(), except that the caller
-   is responsible for calling open_active_file() and
-   close_active_file().
-   Returns true if successful, false if an I/O error occurred. */
-static bool
-internal_procedure (bool (*proc_func) (struct ccase *, void *), void *aux) 
-{
-  struct write_case_data wc_data;
-  bool ok;
-
-  wc_data.proc_func = proc_func;
-  wc_data.aux = aux;
-  create_trns_case (&wc_data.trns_case, default_dict);
-  case_create (&wc_data.sink_case, dict_get_next_value_idx (default_dict));
-  wc_data.cases_written = 0;
-
-  update_last_vfm_invocation ();
-
-  ok = (vfm_source == NULL
-        || vfm_source->class->read (vfm_source,
-                                    &wc_data.trns_case,
-                                    write_case, &wc_data));
-
-  case_destroy (&wc_data.sink_case);
-  case_destroy (&wc_data.trns_case);
-
-  return ok;
-}
-
-/* Updates last_vfm_invocation. */
-static void
-update_last_vfm_invocation (void) 
-{
-  last_vfm_invocation = time (NULL);
-}
-
-/* Creates and returns a case, initializing it from the vectors
-   that say which `value's need to be initialized just once, and
-   which ones need to be re-initialized before every case. */
-static void
-create_trns_case (struct ccase *trns_case, struct dictionary *dict)
-{
-  size_t var_cnt = dict_get_var_cnt (dict);
-  size_t i;
-
-  case_create (trns_case, dict_get_next_value_idx (dict));
-  for (i = 0; i < var_cnt; i++) 
-    {
-      struct variable *v = dict_get_var (dict, i);
-      union value *value = case_data_rw (trns_case, v->fv);
-
-      if (v->type == NUMERIC)
-        value->f = v->leave ? 0.0 : SYSMIS;
-      else
-        memset (value->s, ' ', v->width);
-    }
-}
-
-/* Makes all preparations for reading from the data source and writing
-   to the data sink. */
-static void
-open_active_file (void)
-{
-  add_case_limit_trns ();
-  add_filter_trns ();
-  add_process_if_trns ();
-
-  /* Finalize transformations. */
-  trns_chain_finalize (cur_trns_chain);
-
-  /* Make permanent_dict refer to the dictionary right before
-     data reaches the sink. */
-  if (permanent_dict == NULL)
-    permanent_dict = default_dict;
-
-  /* Figure out compaction. */
-  compactor = (dict_needs_compaction (permanent_dict)
-               ? dict_make_compactor (permanent_dict)
-               : NULL);
-
-  /* Prepare sink. */
-  if (vfm_sink == NULL)
-    vfm_sink = create_case_sink (&storage_sink_class, permanent_dict, NULL);
-  if (vfm_sink->class->open != NULL)
-    vfm_sink->class->open (vfm_sink);
-
-  /* Allocate memory for lag queue. */
-  if (n_lag > 0)
-    {
-      int i;
-  
-      lag_count = 0;
-      lag_head = 0;
-      lag_queue = xnmalloc (n_lag, sizeof *lag_queue);
-      for (i = 0; i < n_lag; i++)
-        case_nullify (&lag_queue[i]);
-    }
-}
-
-/* Transforms trns_case and writes it to the replacement active
-   file if advisable.  Returns true if more cases can be
-   accepted, false otherwise.  Do not call this function again
-   after it has returned false once.  */
-static bool
-write_case (struct write_case_data *wc_data)
-{
-  enum trns_result retval;
-  size_t case_nr;
-  
-  /* Execute permanent transformations.  */
-  case_nr = wc_data->cases_written + 1;
-  retval = trns_chain_execute (permanent_trns_chain,
-                               &wc_data->trns_case, &case_nr);
-  if (retval != TRNS_CONTINUE)
-    goto done;
-
-  /* Write case to LAG queue. */
-  if (n_lag)
-    lag_case (&wc_data->trns_case);
-
-  /* Write case to replacement active file. */
-  wc_data->cases_written++;
-  if (vfm_sink->class->write != NULL) 
-    {
-      if (compactor != NULL) 
-        {
-          dict_compactor_compact (compactor, &wc_data->sink_case,
-                                  &wc_data->trns_case);
-          vfm_sink->class->write (vfm_sink, &wc_data->sink_case);
-        }
-      else
-        vfm_sink->class->write (vfm_sink, &wc_data->trns_case);
-    }
-  
-  /* Execute temporary transformations. */
-  if (temporary_trns_chain != NULL) 
-    {
-      retval = trns_chain_execute (temporary_trns_chain,
-                                   &wc_data->trns_case,
-                                   &wc_data->cases_written);
-      if (retval != TRNS_CONTINUE)
-        goto done;
-    }
-
-  /* Pass case to procedure. */
-  wc_data->cases_analyzed++;
-  if (wc_data->proc_func != NULL)
-    if (!wc_data->proc_func (&wc_data->trns_case, wc_data->aux))
-      retval = TRNS_ERROR;
-
- done:
-  clear_case (&wc_data->trns_case);
-  return retval != TRNS_ERROR;
-}
-
-/* Add C to the lag queue. */
-static void
-lag_case (const struct ccase *c)
-{
-  if (lag_count < n_lag)
-    lag_count++;
-  case_destroy (&lag_queue[lag_head]);
-  case_clone (&lag_queue[lag_head], c);
-  if (++lag_head >= n_lag)
-    lag_head = 0;
-}
-
-/* Clears the variables in C that need to be cleared between
-   processing cases.  */
-static void
-clear_case (struct ccase *c)
-{
-  size_t var_cnt = dict_get_var_cnt (default_dict);
-  size_t i;
-  
-  for (i = 0; i < var_cnt; i++) 
-    {
-      struct variable *v = dict_get_var (default_dict, i);
-      if (!v->leave) 
-        {
-          if (v->type == NUMERIC)
-            case_data_rw (c, v->fv)->f = SYSMIS;
-          else
-            memset (case_data_rw (c, v->fv)->s, ' ', v->width);
-        } 
-    }
-}
-
-/* Closes the active file. */
-static bool
-close_active_file (void)
-{
-  /* Free memory for lag queue, and turn off lagging. */
-  if (n_lag > 0)
-    {
-      int i;
-      
-      for (i = 0; i < n_lag; i++)
-       case_destroy (&lag_queue[i]);
-      free (lag_queue);
-      n_lag = 0;
-    }
-  
-  /* Dictionary from before TEMPORARY becomes permanent. */
-  proc_cancel_temporary_transformations ();
-
-  /* Finish compaction. */
-  if (compactor != NULL) 
-    {
-      dict_compactor_destroy (compactor);
-      dict_compact_values (default_dict); 
-    }
-    
-  /* Free data source. */
-  free_case_source (vfm_source);
-  vfm_source = NULL;
-
-  /* Old data sink becomes new data source. */
-  if (vfm_sink->class->make_source != NULL)
-    vfm_source = vfm_sink->class->make_source (vfm_sink);
-  free_case_sink (vfm_sink);
-  vfm_sink = NULL;
-
-  /* Cancel TEMPORARY, PROCESS IF, FILTER, N OF CASES, vectors,
-     and get rid of all the transformations. */
-  dict_clear_vectors (default_dict);
-  permanent_dict = NULL;
-  return proc_cancel_all_transformations ();
-}
-\f
-/* Returns a pointer to the lagged case from N_BEFORE cases before the
-   current one, or NULL if there haven't been that many cases yet. */
-struct ccase *
-lagged_case (int n_before)
-{
-  assert (n_before >= 1 );
-  assert (n_before <= n_lag);
-
-  if (n_before <= lag_count)
-    {
-      int index = lag_head - n_before;
-      if (index < 0)
-        index += n_lag;
-      return &lag_queue[index];
-    }
-  else
-    return NULL;
-}
-\f
-/* Represents auxiliary data for handling SPLIT FILE. */
-struct split_aux_data 
-  {
-    size_t case_count;          /* Number of cases so far. */
-    struct ccase prev_case;     /* Data in previous case. */
-
-    /* Functions to call... */
-    void (*begin_func) (void *);               /* ...before data. */
-    bool (*proc_func) (struct ccase *, void *); /* ...with data. */
-    void (*end_func) (void *);                 /* ...after data. */
-    void *func_aux;                            /* Auxiliary data. */ 
-  };
-
-static int equal_splits (const struct ccase *, const struct ccase *);
-static bool procedure_with_splits_callback (struct ccase *, void *);
-static void dump_splits (struct ccase *);
-
-/* Like procedure(), but it automatically breaks the case stream
-   into SPLIT FILE break groups.  Before each group of cases with
-   identical SPLIT FILE variable values, BEGIN_FUNC is called.
-   Then PROC_FUNC is called with each case in the group.  
-   END_FUNC is called when the group is finished.  FUNC_AUX is
-   passed to each of the functions as auxiliary data.
-
-   If the active file is empty, none of BEGIN_FUNC, PROC_FUNC,
-   and END_FUNC will be called at all. 
-
-   If SPLIT FILE is not in effect, then there is one break group
-   (if the active file is nonempty), and BEGIN_FUNC and END_FUNC
-   will be called once.
-   
-   Returns true if successful, false if an I/O error occurred. */
-bool
-procedure_with_splits (void (*begin_func) (void *aux),
-                       bool (*proc_func) (struct ccase *, void *aux),
-                       void (*end_func) (void *aux),
-                       void *func_aux) 
-{
-  struct split_aux_data split_aux;
-  bool ok;
-
-  split_aux.case_count = 0;
-  case_nullify (&split_aux.prev_case);
-  split_aux.begin_func = begin_func;
-  split_aux.proc_func = proc_func;
-  split_aux.end_func = end_func;
-  split_aux.func_aux = func_aux;
-
-  open_active_file ();
-  ok = internal_procedure (procedure_with_splits_callback, &split_aux);
-  if (split_aux.case_count > 0 && end_func != NULL)
-    end_func (func_aux);
-  if (!close_active_file ())
-    ok = false;
-
-  case_destroy (&split_aux.prev_case);
-
-  return ok;
-}
-
-/* procedure() callback used by procedure_with_splits(). */
-static bool
-procedure_with_splits_callback (struct ccase *c, void *split_aux_) 
-{
-  struct split_aux_data *split_aux = split_aux_;
-
-  /* Start a new series if needed. */
-  if (split_aux->case_count == 0
-      || !equal_splits (c, &split_aux->prev_case))
-    {
-      if (split_aux->case_count > 0 && split_aux->end_func != NULL)
-        split_aux->end_func (split_aux->func_aux);
-
-      dump_splits (c);
-      case_destroy (&split_aux->prev_case);
-      case_clone (&split_aux->prev_case, c);
-
-      if (split_aux->begin_func != NULL)
-       split_aux->begin_func (split_aux->func_aux);
-    }
-
-  split_aux->case_count++;
-  if (split_aux->proc_func != NULL)
-    return split_aux->proc_func (c, split_aux->func_aux);
-  else
-    return true;
-}
-
-/* Compares the SPLIT FILE variables in cases A and B and returns
-   nonzero only if they differ. */
-static int
-equal_splits (const struct ccase *a, const struct ccase *b) 
-{
-  return case_compare (a, b,
-                       dict_get_split_vars (default_dict),
-                       dict_get_split_cnt (default_dict)) == 0;
-}
-
-/* Dumps out the values of all the split variables for the case C. */
-static void
-dump_splits (struct ccase *c)
-{
-  struct variable *const *split;
-  struct tab_table *t;
-  size_t split_cnt;
-  int i;
-
-  split_cnt = dict_get_split_cnt (default_dict);
-  if (split_cnt == 0)
-    return;
-
-  t = tab_create (3, split_cnt + 1, 0);
-  tab_dim (t, tab_natural_dimensions);
-  tab_vline (t, TAL_GAP, 1, 0, split_cnt);
-  tab_vline (t, TAL_GAP, 2, 0, split_cnt);
-  tab_text (t, 0, 0, TAB_NONE, _("Variable"));
-  tab_text (t, 1, 0, TAB_LEFT, _("Value"));
-  tab_text (t, 2, 0, TAB_LEFT, _("Label"));
-  split = dict_get_split_vars (default_dict);
-  for (i = 0; i < split_cnt; i++)
-    {
-      struct variable *v = split[i];
-      char temp_buf[80];
-      const char *val_lab;
-
-      assert (v->type == NUMERIC || v->type == ALPHA);
-      tab_text (t, 0, i + 1, TAB_LEFT | TAT_PRINTF, "%s", v->name);
-      
-      data_out (temp_buf, &v->print, case_data (c, v->fv));
-      
-      temp_buf[v->print.w] = 0;
-      tab_text (t, 1, i + 1, TAT_PRINTF, "%.*s", v->print.w, temp_buf);
-
-      val_lab = val_labs_find (v->val_labs, *case_data (c, v->fv));
-      if (val_lab)
-       tab_text (t, 2, i + 1, TAB_LEFT, val_lab);
-    }
-  tab_flags (t, SOMF_NO_TITLE);
-  tab_submit (t);
-}
-\f
-/* Represents auxiliary data for handling SPLIT FILE in a
-   multipass procedure. */
-struct multipass_split_aux_data 
-  {
-    struct ccase prev_case;     /* Data in previous case. */
-    struct casefile *casefile;  /* Accumulates data for a split. */
-
-    /* Function to call with the accumulated data. */
-    bool (*split_func) (const struct casefile *, void *);
-    void *func_aux;                            /* Auxiliary data. */ 
-  };
-
-static bool multipass_split_callback (struct ccase *c, void *aux_);
-static bool multipass_split_output (struct multipass_split_aux_data *);
-
-/* Returns true if successful, false if an I/O error occurred. */
-bool
-multipass_procedure_with_splits (bool (*split_func) (const struct casefile *,
-                                                     void *),
-                                 void *func_aux) 
-{
-  struct multipass_split_aux_data aux;
-  bool ok;
-
-  assert (split_func != NULL);
-
-  open_active_file ();
-
-  case_nullify (&aux.prev_case);
-  aux.casefile = NULL;
-  aux.split_func = split_func;
-  aux.func_aux = func_aux;
-
-  ok = internal_procedure (multipass_split_callback, &aux);
-  if (aux.casefile != NULL)
-    ok = multipass_split_output (&aux) && ok;
-  case_destroy (&aux.prev_case);
-
-  if (!close_active_file ())
-    ok = false;
-
-  return ok;
-}
-
-/* procedure() callback used by multipass_procedure_with_splits(). */
-static bool
-multipass_split_callback (struct ccase *c, void *aux_)
-{
-  struct multipass_split_aux_data *aux = aux_;
-  bool ok = true;
-
-  /* Start a new series if needed. */
-  if (aux->casefile == NULL || !equal_splits (c, &aux->prev_case))
-    {
-      /* Pass any cases to split_func. */
-      if (aux->casefile != NULL)
-        ok = multipass_split_output (aux);
-
-      /* Start a new casefile. */
-      aux->casefile = casefile_create (dict_get_next_value_idx (default_dict));
-
-      /* Record split values. */
-      dump_splits (c);
-      case_destroy (&aux->prev_case);
-      case_clone (&aux->prev_case, c);
-    }
-
-  return casefile_append (aux->casefile, c) && ok;
-}
-
-static bool
-multipass_split_output (struct multipass_split_aux_data *aux)
-{
-  bool ok;
-  
-  assert (aux->casefile != NULL);
-  ok = aux->split_func (aux->casefile, aux->func_aux);
-  casefile_destroy (aux->casefile);
-  aux->casefile = NULL;
-
-  return ok;
-}
-
-/* Discards all the current state in preparation for a data-input
-   command like DATA LIST or GET. */
-void
-discard_variables (void)
-{
-  dict_clear (default_dict);
-  fh_set_default_handle (NULL);
-
-  n_lag = 0;
-  
-  if (vfm_source != NULL)
-    {
-      free_case_source (vfm_source);
-      vfm_source = NULL;
-    }
-
-  proc_cancel_all_transformations ();
-
-  expr_free (process_if_expr);
-  process_if_expr = NULL;
-
-  proc_cancel_temporary_transformations ();
-}
-\f
-/* Returns the current set of permanent transformations,
-   and clears the permanent transformations.
-   For use by INPUT PROGRAM. */
-struct trns_chain *
-proc_capture_transformations (void) 
-{
-  struct trns_chain *chain;
-  
-  assert (temporary_trns_chain == NULL);
-  chain = permanent_trns_chain;
-  cur_trns_chain = permanent_trns_chain = trns_chain_create ();
-  return chain;
-}
-
-/* Adds a transformation that processes a case with PROC and
-   frees itself with FREE to the current set of transformations.
-   The functions are passed AUX as auxiliary data. */
-void
-add_transformation (trns_proc_func *proc, trns_free_func *free, void *aux)
-{
-  trns_chain_append (cur_trns_chain, NULL, proc, free, aux);
-}
-
-/* Adds a transformation that processes a case with PROC and
-   frees itself with FREE to the current set of transformations.
-   When parsing of the block of transformations is complete,
-   FINALIZE will be called.
-   The functions are passed AUX as auxiliary data. */
-void
-add_transformation_with_finalizer (trns_finalize_func *finalize,
-                                   trns_proc_func *proc,
-                                   trns_free_func *free, void *aux)
-{
-  trns_chain_append (cur_trns_chain, finalize, proc, free, aux);
-}
-
-/* Returns the index of the next transformation.
-   This value can be returned by a transformation procedure
-   function to indicate a "jump" to that transformation. */
-size_t
-next_transformation (void) 
-{
-  return trns_chain_next (cur_trns_chain);
-}
-
-/* Returns true if the next call to add_transformation() will add
-   a temporary transformation, false if it will add a permanent
-   transformation. */
-bool
-proc_in_temporary_transformations (void) 
-{
-  return temporary_trns_chain != NULL;
-}
-
-/* Marks the start of temporary transformations.
-   Further calls to add_transformation() will add temporary
-   transformations. */
-void
-proc_start_temporary_transformations (void) 
-{
-  if (!proc_in_temporary_transformations ())
-    {
-      add_case_limit_trns ();
-
-      permanent_dict = dict_clone (default_dict);
-      trns_chain_finalize (permanent_trns_chain);
-      temporary_trns_chain = cur_trns_chain = trns_chain_create ();
-    }
-}
-
-/* Converts all the temporary transformations, if any, to
-   permanent transformations.  Further transformations will be
-   permanent.
-   Returns true if anything changed, false otherwise. */
-bool
-proc_make_temporary_transformations_permanent (void) 
-{
-  if (proc_in_temporary_transformations ()) 
-    {
-      trns_chain_finalize (temporary_trns_chain);
-      trns_chain_splice (permanent_trns_chain, temporary_trns_chain);
-      temporary_trns_chain = NULL;
-
-      dict_destroy (permanent_dict);
-      permanent_dict = NULL;
-
-      return true;
-    }
-  else
-    return false;
-}
-
-/* Cancels all temporary transformations, if any.  Further
-   transformations will be permanent.
-   Returns true if anything changed, false otherwise. */
-bool
-proc_cancel_temporary_transformations (void) 
-{
-  if (proc_in_temporary_transformations ()) 
-    {
-      dict_destroy (default_dict);
-      default_dict = permanent_dict;
-      permanent_dict = NULL;
-
-      trns_chain_destroy (temporary_trns_chain);
-      temporary_trns_chain = NULL;
-
-      return true;
-    }
-  else
-    return false;
-}
-
-/* Cancels all transformations, if any.
-   Returns true if successful, false on I/O error. */
-bool
-proc_cancel_all_transformations (void)
-{
-  bool ok;
-  ok = trns_chain_destroy (permanent_trns_chain);
-  ok = trns_chain_destroy (temporary_trns_chain) && ok;
-  permanent_trns_chain = cur_trns_chain = trns_chain_create ();
-  temporary_trns_chain = NULL;
-  return ok;
-}
-\f
-/* Initializes procedure handling. */
-void
-proc_init (void) 
-{
-  default_dict = dict_create ();
-  proc_cancel_all_transformations ();
-}
-
-/* Finishes up procedure handling. */
-void
-proc_done (void)
-{
-  discard_variables ();
-}
-
-/* Sets SINK as the destination for procedure output from the
-   next procedure. */
-void
-proc_set_sink (struct case_sink *sink) 
-{
-  assert (vfm_sink == NULL);
-  vfm_sink = sink;
-}
-
-/* Sets SOURCE as the source for procedure input for the next
-   procedure. */
-void
-proc_set_source (struct case_source *source) 
-{
-  assert (vfm_source == NULL);
-  vfm_source = source;
-}
-
-/* Returns true if a source for the next procedure has been
-   configured, false otherwise. */
-bool
-proc_has_source (void) 
-{
-  return vfm_source != NULL;
-}
-
-/* Returns the output from the previous procedure.
-   For use only immediately after executing a procedure.
-   The returned casefile is owned by the caller; it will not be
-   automatically used for the next procedure's input. */
-struct casefile *
-proc_capture_output (void) 
-{
-  struct casefile *casefile;
-
-  /* Try to make sure that this function is called immediately
-     after procedure() or a similar function. */
-  assert (vfm_source != NULL);
-  assert (case_source_is_class (vfm_source, &storage_source_class));
-  assert (trns_chain_is_empty (permanent_trns_chain));
-  assert (!proc_in_temporary_transformations ());
-
-  casefile = storage_source_decapsulate (vfm_source);
-  vfm_source = NULL;
-
-  return casefile;
-}
-\f
-static trns_proc_func case_limit_trns_proc;
-static trns_free_func case_limit_trns_free;
-
-/* Adds a transformation that limits the number of cases that may
-   pass through, if default_dict has a case limit. */
-static void
-add_case_limit_trns (void) 
-{
-  size_t case_limit = dict_get_case_limit (default_dict);
-  if (case_limit != 0)
-    {
-      size_t *cases_remaining = xmalloc (sizeof *cases_remaining);
-      *cases_remaining = case_limit;
-      add_transformation (case_limit_trns_proc, case_limit_trns_free,
-                          cases_remaining);
-      dict_set_case_limit (default_dict, 0);
-    }
-}
-
-/* Limits the maximum number of cases processed to
-   *CASES_REMAINING. */
-static int
-case_limit_trns_proc (void *cases_remaining_,
-                      struct ccase *c UNUSED, int case_nr UNUSED) 
-{
-  size_t *cases_remaining = cases_remaining_;
-  if (*cases_remaining > 0) 
-    {
-      *cases_remaining--;
-      return TRNS_CONTINUE;
-    }
-  else
-    return TRNS_DROP_CASE;
-}
-
-/* Frees the data associated with a case limit transformation. */
-static bool
-case_limit_trns_free (void *cases_remaining_) 
-{
-  size_t *cases_remaining = cases_remaining_;
-  free (cases_remaining);
-  return true;
-}
-\f
-static trns_proc_func filter_trns_proc;
-
-/* Adds a temporary transformation to filter data according to
-   the variable specified on FILTER, if any. */
-static void
-add_filter_trns (void) 
-{
-  struct variable *filter_var = dict_get_filter (default_dict);
-  if (filter_var != NULL) 
-    {
-      proc_start_temporary_transformations ();
-      add_transformation (filter_trns_proc, NULL, filter_var);
-    }
-}
-
-/* FILTER transformation. */
-static int
-filter_trns_proc (void *filter_var_,
-                  struct ccase *c UNUSED, int case_nr UNUSED) 
-  
-{
-  struct variable *filter_var = filter_var_;
-  double f = case_num (c, filter_var->fv);
-  return (f != 0.0 && !mv_is_num_missing (&filter_var->miss, f)
-          ? TRNS_CONTINUE : TRNS_DROP_CASE);
-}
-\f
-static trns_proc_func process_if_trns_proc;
-static trns_free_func process_if_trns_free;
-
-/* Adds a temporary transformation to filter data according to
-   the expression specified on PROCESS IF, if any. */
-static void
-add_process_if_trns (void) 
-{
-  if (process_if_expr != NULL) 
-    {
-      proc_start_temporary_transformations ();
-      add_transformation (process_if_trns_proc, process_if_trns_free,
-                          process_if_expr);
-      process_if_expr = NULL;
-    }
-}
-
-/* PROCESS IF transformation. */
-static int
-process_if_trns_proc (void *expression_,
-                      struct ccase *c UNUSED, int case_nr UNUSED) 
-  
-{
-  struct expression *expression = expression_;
-  return (expr_evaluate_num (expression, c, case_nr) == 1.0
-          ? TRNS_CONTINUE : TRNS_DROP_CASE);
-}
-
-/* Frees a PROCESS IF transformation. */
-static bool
-process_if_trns_free (void *expression_) 
-{
-  struct expression *expression = expression_;
-  expr_free (expression);
-  return true;
-}
diff --git a/src/procedure.h b/src/procedure.h
deleted file mode 100644 (file)
index 5a19687..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-/* PSPP - computes sample statistics.
-   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
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 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, write to the Free Software
-   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, USA. */
-
-#ifndef PROCEDURE_H
-#define PROCEDURE_H 1
-
-#include <time.h>
-#include <stdbool.h>
-#include <data/transformations.h>
-
-struct ccase;
-struct casefile;
-struct case_sink;
-struct case_source;
-
-/* Dictionary produced by permanent and temporary transformations
-   on data from the source. */
-extern struct dictionary *default_dict;
-\f
-/* Transformations. */
-
-void add_transformation (trns_proc_func *, trns_free_func *, void *);
-void add_transformation_with_finalizer (trns_finalize_func *,
-                                        trns_proc_func *,
-                                        trns_free_func *, void *);
-size_t next_transformation (void);
-
-void discard_variables (void);
-
-bool proc_cancel_all_transformations (void);
-struct trns_chain *proc_capture_transformations (void);
-
-void proc_start_temporary_transformations (void);
-bool proc_in_temporary_transformations (void);
-bool proc_make_temporary_transformations_permanent (void);
-bool proc_cancel_temporary_transformations (void);
-\f
-/* Procedures. */
-
-void proc_init (void);
-void proc_done (void);
-
-void proc_set_source (struct case_source *);
-bool proc_has_source (void);
-
-void proc_set_sink (struct case_sink *);
-struct casefile *proc_capture_output (void);
-
-bool procedure (bool (*proc_func) (struct ccase *, void *aux), void *aux);
-bool procedure_with_splits (void (*begin_func) (void *aux),
-                            bool (*proc_func) (struct ccase *, void *aux),
-                            void (*end_func) (void *aux),
-                            void *aux);
-bool multipass_procedure (bool (*proc_func) (const struct casefile *,
-                                             void *aux),
-                          void *aux);
-bool multipass_procedure_with_splits (bool (*) (const struct casefile *,
-                                                void *),
-                                      void *aux);
-time_t time_of_last_procedure (void);
-\f
-/* Number of cases to lag. */
-extern int n_lag;
-
-struct ccase *lagged_case (int n_before);
-
-#endif /* procedure.h */
index 330d94abc0e36f1402efac75d00f9224549a5585..f86d6c8ca7053f0a18e90213f589244f56924951 100644 (file)
@@ -1,3 +1,14 @@
+Thu May  4 21:50:59 2006  Ben Pfaff  <blp@gnu.org>
+
+       Continue reforming procedure execution.  In this phase, move
+       procedure.c and procedure.h from src to src/data.  Update
+       makefiles and #includes accordingly.
+
+       * automake.mk: (src_ui_terminal_pspp_SOURCES) Remove
+       src/procedure.c and src/procedure.h.
+       (src_ui_terminal_pspp_LDADD) Move libexpressions.a later in list
+       to make the link work.
+
 Wed May  3 23:09:37 2006  Ben Pfaff  <blp@gnu.org>
 
        Continue reforming procedure execution.  In this phase, get rid of
index c137714672f96a9effcc218ca203e32fce0d51ec..105a6b26258e18a85b4b2551b7253dfde78dd380 100644 (file)
@@ -14,17 +14,15 @@ src_ui_terminal_libui_a_SOURCES = \
 
 bin_PROGRAMS += src/ui/terminal/pspp
 
-src_ui_terminal_pspp_SOURCES = \
-       src/procedure.c \
-       src/procedure.h
+src_ui_terminal_pspp_SOURCES =
 
 src_ui_terminal_pspp_LDADD =                                   \
        $(top_builddir)/src/ui/terminal/libui.a \
-       $(top_builddir)/src/language/expressions/libexpressions.a \
        $(top_builddir)/src/language/liblanguage.a \
        $(top_builddir)/src/language/tests/libtests.a \
        $(top_builddir)/src/language/utilities/libutilities.a \
        $(top_builddir)/src/language/control/libcontrol.a \
+       $(top_builddir)/src/language/expressions/libexpressions.a \
        $(top_builddir)/src/language/stats/libstats.a \
        $(top_builddir)/src/language/xforms/libxforms.a \
        $(top_builddir)/src/language/dictionary/libcmddict.a \
index 7560dcfe0d3d2b424e37d7efb37cf62f1775a108..e19dd0c7a5eac5239aa9161a2f9380387d29fd7a 100644 (file)
 #include "command-line.h"
 #include "msg-ui.h"
 #include "progname.h"
-#include "procedure.h"
 #include "read-line.h"
 
 #include <data/dictionary.h>
 #include <data/file-handle-def.h>
 #include <data/file-name.h>
+#include <data/procedure.h>
 #include <data/settings.h>
 #include <data/variable.h>
 #include <gsl/gsl_errno.h>
@@ -42,7 +42,6 @@
 #include <libpspp/version.h>
 #include <math/random.h>
 #include <output/output.h>
-#include <procedure.h>
 
 #if HAVE_FPU_CONTROL_H
 #include <fpu_control.h>