Work on getting rid of trns_chain_finalize().
[pspp] / src / data / dataset.c
index 26c3a49244783f4ff84a734d8c024d8470a2b6d0..afab39dc0c5e63a4bdfa2a6ba4d49b6b37c65137 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 1997-9, 2000, 2006, 2007, 2009, 2010, 2011 Free Software Foundation, Inc.
+   Copyright (C) 1997-9, 2000, 2006, 2007, 2009, 2010, 2011, 2013 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -30,6 +30,7 @@
 #include "data/casereader-provider.h"
 #include "data/casereader-shim.h"
 #include "data/casewriter.h"
+#include "data/control-stack.h"
 #include "data/dictionary.h"
 #include "data/file-handle-def.h"
 #include "data/session.h"
@@ -201,6 +202,7 @@ dataset_destroy (struct dataset *ds)
       dataset_clear (ds);
       dict_destroy (ds->dict);
       caseinit_destroy (ds->caseinit);
+      ctl_stack_clear ();
       trns_chain_destroy (ds->permanent_trns_chain);
       dataset_transformations_changed__ (ds, false);
       free (ds->name);
@@ -426,7 +428,7 @@ proc_open_filtering (struct dataset *ds, bool filter)
   add_case_limit_trns (ds);
   if (filter)
     add_filter_trns (ds);
-  trns_chain_finalize (ds->cur_trns_chain);
+  ctl_stack_clear ();
 
   /* Make permanent_dict refer to the dictionary right before
      data reaches the sink. */
@@ -691,22 +693,7 @@ proc_capture_transformations (struct dataset *ds)
 void
 add_transformation (struct dataset *ds, trns_proc_func *proc, trns_free_func *free, void *aux)
 {
-  trns_chain_append (ds->cur_trns_chain, NULL, proc, free, aux);
-  dataset_transformations_changed__ (ds, true);
-}
-
-/* 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 (struct dataset *ds,
-                                  trns_finalize_func *finalize,
-                                   trns_proc_func *proc,
-                                   trns_free_func *free, void *aux)
-{
-  trns_chain_append (ds->cur_trns_chain, finalize, proc, free, aux);
+  trns_chain_append (ds->cur_trns_chain, proc, free, aux);
   dataset_transformations_changed__ (ds, true);
 }
 
@@ -740,25 +727,31 @@ proc_start_temporary_transformations (struct dataset *ds)
 
       ds->permanent_dict = dict_clone (ds->dict);
 
-      trns_chain_finalize (ds->permanent_trns_chain);
+      ctl_stack_clear ();
       ds->temporary_trns_chain = ds->cur_trns_chain = trns_chain_create ();
       dataset_transformations_changed__ (ds, true);
     }
 }
 
-/* Converts all the temporary transformations, if any, to
-   permanent transformations.  Further transformations will be
-   permanent.
+/* Converts all the temporary transformations, if any, to permanent
+   transformations.  Further transformations will be permanent.
+
+   The FILTER command is implemented as a temporary transformation, so a
+   procedure that uses this function should usually use proc_open_filtering()
+   with FILTER false, instead of plain proc_open().
+
    Returns true if anything changed, false otherwise. */
 bool
 proc_make_temporary_transformations_permanent (struct dataset *ds)
 {
   if (proc_in_temporary_transformations (ds))
     {
-      trns_chain_finalize (ds->temporary_trns_chain);
+      ctl_stack_clear ();
       trns_chain_splice (ds->permanent_trns_chain, ds->temporary_trns_chain);
       ds->temporary_trns_chain = NULL;
 
+      ds->cur_trns_chain = ds->permanent_trns_chain;
+
       dict_destroy (ds->permanent_dict);
       ds->permanent_dict = NULL;
 
@@ -780,6 +773,7 @@ proc_cancel_temporary_transformations (struct dataset *ds)
       ds->dict = ds->permanent_dict;
       ds->permanent_dict = NULL;
 
+      ctl_stack_clear ();
       trns_chain_destroy (ds->temporary_trns_chain);
       ds->temporary_trns_chain = NULL;
       dataset_transformations_changed__ (
@@ -797,6 +791,7 @@ proc_cancel_all_transformations (struct dataset *ds)
 {
   bool ok;
   assert (ds->proc_state == PROC_COMMITTED);
+  ctl_stack_clear ();
   ok = trns_chain_destroy (ds->permanent_trns_chain);
   ok = trns_chain_destroy (ds->temporary_trns_chain) && ok;
   ds->permanent_trns_chain = ds->cur_trns_chain = trns_chain_create ();
@@ -805,6 +800,39 @@ proc_cancel_all_transformations (struct dataset *ds)
 
   return ok;
 }
+
+static int
+store_case_num (void *var_, struct ccase **cc, casenumber case_num)
+{
+  struct variable *var = var_;
+
+  *cc = case_unshare (*cc);
+  case_data_rw (*cc, var)->f = case_num;
+
+  return TRNS_CONTINUE;
+}
+
+/* Add a variable which we can sort by to get back the original order. */
+struct variable *
+add_permanent_ordering_transformation (struct dataset *ds)
+{
+  struct variable *temp_var;
+
+  temp_var = dict_create_var_assert (ds->dict, "$ORDER", 0);
+  if (proc_in_temporary_transformations (ds))
+    {
+      struct variable *perm_var;
+
+      perm_var = dict_clone_var_in_place_assert (ds->permanent_dict, temp_var);
+      trns_chain_append (ds->permanent_trns_chain, NULL, store_case_num,
+                         NULL, perm_var);
+      trns_chain_finalize (ds->permanent_trns_chain);
+    }
+  else
+    add_transformation (ds, store_case_num, NULL, temp_var);
+
+  return temp_var;
+}
 \f
 /* Causes output from the next procedure to be discarded, instead
    of being preserved for use as input for the next procedure. */