Continue reforming procedure execution. In this phase, remove PROCESS
[pspp-builds.git] / src / data / procedure.c
index 2abe53a16682b924e045d0166792e20c5e6fe1a4..4cbb55204959411a9f8132bce4a38a375bc7acb7 100644 (file)
 #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):
@@ -60,8 +51,8 @@
 struct write_case_data
   {
     /* Function to call for each case. */
-    bool (*case_func) (struct ccase *, void *); /* Function. */
-    void *aux;                                 /* Auxiliary data. */ 
+    bool (*case_func) (const struct ccase *, void *);
+    void *aux;
 
     struct ccase trns_case;     /* Case used for transformations. */
     struct ccase sink_case;     /* Case written to sink, if
@@ -102,9 +93,9 @@ 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 (*case_func) (struct ccase *, void *),
+static bool internal_procedure (bool (*case_func) (const struct ccase *,
+                                                   void *),
                                 bool (*end_func) (void *),
                                 void *aux);
 static void update_last_vfm_invocation (void);
@@ -144,7 +135,7 @@ time_of_last_procedure (void)
 
    Returns true if successful, false if an I/O error occurred. */
 bool
-procedure (bool (*proc_func) (struct ccase *, void *), void *aux)
+procedure (bool (*proc_func) (const struct ccase *, void *), void *aux)
 {
   return internal_procedure (proc_func, NULL, aux);
 }
@@ -161,7 +152,7 @@ struct multipass_aux_data
 
 /* Case processing function for multipass_procedure(). */
 static bool
-multipass_case_func (struct ccase *c, void *aux_data_) 
+multipass_case_func (const struct ccase *c, void *aux_data_) 
 {
   struct multipass_aux_data *aux_data = aux_data_;
   return casefile_append (aux_data->casefile, c);
@@ -206,7 +197,7 @@ multipass_procedure (bool (*proc_func) (const struct casefile *, void *aux),
    Returns true if successful, false if an I/O error occurred (or
    if CASE_FUNC or END_FUNC ever returned false). */
 static bool
-internal_procedure (bool (*case_func) (struct ccase *, void *),
+internal_procedure (bool (*case_func) (const struct ccase *, void *),
                     bool (*end_func) (void *),
                     void *aux) 
 {
@@ -227,8 +218,6 @@ internal_procedure (bool (*case_func) (struct ccase *, void *),
       && trns_chain_is_empty (permanent_trns_chain))
     {
       n_lag = 0;
-      expr_free (process_if_expr);
-      process_if_expr = NULL;
       dict_set_case_limit (default_dict, 0);
       dict_clear_vectors (default_dict);
       return true;
@@ -292,7 +281,6 @@ open_active_file (void)
 {
   add_case_limit_trns ();
   add_filter_trns ();
-  add_process_if_trns ();
 
   /* Finalize transformations. */
   trns_chain_finalize (cur_trns_chain);
@@ -450,8 +438,6 @@ close_active_file (void)
   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 ();
@@ -484,22 +470,23 @@ 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. */ 
+    /* Callback functions. */
+    void (*begin_func) (const struct ccase *, void *);
+    bool (*proc_func) (const struct ccase *, void *);
+    void (*end_func) (void *);
+    void *func_aux;
   };
 
 static int equal_splits (const struct ccase *, const struct ccase *);
-static bool split_procedure_case_func (struct ccase *c, void *split_aux_);
-static bool split_procedure_end_func (void *split_aux_);
-static void dump_splits (struct ccase *);
+static bool split_procedure_case_func (const struct ccase *c, void *);
+static bool split_procedure_end_func (void *);
 
 /* 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.  
+   identical SPLIT FILE variable values, BEGIN_FUNC is called
+   with the first case in the group.
+   Then PROC_FUNC is called for each case in the group (including
+   the first).
    END_FUNC is called when the group is finished.  FUNC_AUX is
    passed to each of the functions as auxiliary data.
 
@@ -512,8 +499,8 @@ static void dump_splits (struct ccase *);
    
    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),
+procedure_with_splits (void (*begin_func) (const struct ccase *, void *aux),
+                       bool (*proc_func) (const struct ccase *, void *aux),
                        void (*end_func) (void *aux),
                        void *func_aux) 
 {
@@ -537,7 +524,7 @@ procedure_with_splits (void (*begin_func) (void *aux),
 
 /* Case callback used by procedure_with_splits(). */
 static bool
-split_procedure_case_func (struct ccase *c, void *split_aux_) 
+split_procedure_case_func (const struct ccase *c, void *split_aux_) 
 {
   struct split_aux_data *split_aux = split_aux_;
 
@@ -548,12 +535,11 @@ split_procedure_case_func (struct ccase *c, void *split_aux_)
       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->begin_func (&split_aux->prev_case, split_aux->func_aux);
     }
 
   split_aux->case_count++;
@@ -581,49 +567,6 @@ equal_splits (const struct ccase *a, const struct ccase *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
 /* Multipass procedure that separates the data into SPLIT FILE
    groups. */
@@ -636,19 +579,21 @@ struct multipass_split_aux_data
     struct casefile *casefile;  /* Accumulates data for a split. */
 
     /* Function to call with the accumulated data. */
-    bool (*split_func) (const struct casefile *, void *);
+    bool (*split_func) (const struct ccase *first, const struct casefile *,
+                        void *);
     void *func_aux;                            /* Auxiliary data. */ 
   };
 
-static bool multipass_split_case_func (struct ccase *c, void *aux_);
+static bool multipass_split_case_func (const struct ccase *c, void *aux_);
 static bool multipass_split_end_func (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) 
+multipass_procedure_with_splits (bool (*split_func) (const struct ccase *first,
+                                                     const struct casefile *,
+                                                     void *aux),
+                                 void *func_aux)
 {
   struct multipass_split_aux_data aux;
   bool ok;
@@ -667,7 +612,7 @@ multipass_procedure_with_splits (bool (*split_func) (const struct casefile *,
 
 /* Case callback used by multipass_procedure_with_splits(). */
 static bool
-multipass_split_case_func (struct ccase *c, void *aux_)
+multipass_split_case_func (const struct ccase *c, void *aux_)
 {
   struct multipass_split_aux_data *aux = aux_;
   bool ok = true;
@@ -675,17 +620,16 @@ multipass_split_case_func (struct ccase *c, void *aux_)
   /* Start a new series if needed. */
   if (aux->casefile == NULL || !equal_splits (c, &aux->prev_case))
     {
+      /* Record split values. */
+      case_destroy (&aux->prev_case);
+      case_clone (&aux->prev_case, c);
+
       /* 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;
@@ -705,7 +649,7 @@ multipass_split_output (struct multipass_split_aux_data *aux)
   bool ok;
   
   assert (aux->casefile != NULL);
-  ok = aux->split_func (aux->casefile, aux->func_aux);
+  ok = aux->split_func (&aux->prev_case, aux->casefile, aux->func_aux);
   casefile_destroy (aux->casefile);
   aux->casefile = NULL;
 
@@ -726,11 +670,6 @@ discard_variables (void)
   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,
@@ -992,40 +931,4 @@ filter_trns_proc (void *filter_var_,
   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;
-}