dataset: Remove unused types and useless struct forward declaration.
[pspp-builds.git] / src / data / procedure.c
index 5e013a14af767d80a097a4c46f577ed77c4c3210..a45f497afd1268012a77064a5d49b33839c974f8 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 1997-9, 2000, 2006, 2007, 2009 Free Software Foundation, Inc.
+   Copyright (C) 1997-9, 2000, 2006, 2007, 2009, 2010 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
 
 #include <config.h>
 
+#include "data/procedure.h"
+
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 
-#include <data/case.h>
-#include <data/case-map.h>
-#include <data/caseinit.h>
-#include <data/casereader.h>
-#include <data/casereader-provider.h>
-#include <data/casewriter.h>
-#include <data/dictionary.h>
-#include <data/file-handle-def.h>
-#include <data/procedure.h>
-#include <data/transformations.h>
-#include <data/variable.h>
-#include <libpspp/deque.h>
-#include <libpspp/misc.h>
-#include <libpspp/str.h>
-#include <libpspp/taint.h>
-#include <libpspp/i18n.h>
-
-#include "minmax.h"
-#include "xalloc.h"
+#include "data/case.h"
+#include "data/case-map.h"
+#include "data/caseinit.h"
+#include "data/casereader.h"
+#include "data/casereader-provider.h"
+#include "data/casereader-shim.h"
+#include "data/casewriter.h"
+#include "data/dictionary.h"
+#include "data/file-handle-def.h"
+#include "data/transformations.h"
+#include "data/variable.h"
+#include "libpspp/deque.h"
+#include "libpspp/misc.h"
+#include "libpspp/str.h"
+#include "libpspp/taint.h"
+#include "libpspp/i18n.h"
+
+#include "gl/minmax.h"
+#include "gl/xalloc.h"
 
 struct dataset {
   /* Cases are read from source,
@@ -92,12 +94,15 @@ struct dataset {
                                    but proc_commit not yet called. */
     }
   proc_state;
-  casenumber cases_written;       /* Cases output so far. */
-  bool ok;                    /* Error status. */
+  casenumber cases_written;     /* Cases output so far. */
+  bool ok;                      /* Error status. */
+  struct casereader_shim *shim; /* Shim on proc_open() casereader. */
 
   void (*callback) (void *); /* Callback for when the dataset changes */
   void *cb_data;
 
+  /* Default encoding for reading syntax files. */
+  char *syntax_encoding;
 }; /* struct dataset */
 
 
@@ -122,6 +127,18 @@ dataset_set_callback (struct dataset *ds, void (*cb) (void *), void *cb_data)
   ds->cb_data = cb_data;
 }
 
+void
+dataset_set_default_syntax_encoding (struct dataset *ds, const char *encoding)
+{
+  free (ds->syntax_encoding);
+  ds->syntax_encoding = xstrdup (encoding);
+}
+
+const char *
+dataset_get_default_syntax_encoding (const struct dataset *ds)
+{
+  return ds->syntax_encoding;
+}
 
 /* Returns the last time the data was read. */
 time_t
@@ -160,11 +177,17 @@ proc_execute (struct dataset *ds)
 
 static const struct casereader_class proc_casereader_class;
 
-/* Opens dataset DS for reading cases with proc_read.
+/* Opens dataset DS for reading cases with proc_read.  If FILTER is true, then
+   cases filtered out with FILTER BY will not be included in the casereader
+   (which is usually desirable).  If FILTER is false, all cases will be
+   included regardless of FILTER BY settings.
+
    proc_commit must be called when done. */
 struct casereader *
-proc_open (struct dataset *ds)
+proc_open_filtering (struct dataset *ds, bool filter)
 {
+  struct casereader *reader;
+
   assert (ds->source != NULL);
   assert (ds->proc_state == PROC_COMMITTED);
 
@@ -174,7 +197,8 @@ proc_open (struct dataset *ds)
 
   /* Finish up the collection of transformations. */
   add_case_limit_trns (ds);
-  add_filter_trns (ds);
+  if (filter)
+    add_filter_trns (ds);
   trns_chain_finalize (ds->cur_trns_chain);
 
   /* Make permanent_dict refer to the dictionary right before
@@ -217,9 +241,27 @@ proc_open (struct dataset *ds)
   /* FIXME: use taint in dataset in place of `ok'? */
   /* FIXME: for trivial cases we can just return a clone of
      ds->source? */
-  return casereader_create_sequential (NULL, dict_get_proto (ds->dict),
-                                       CASENUMBER_MAX,
-                                       &proc_casereader_class, ds);
+
+  /* Create casereader and insert a shim on top.  The shim allows us to
+     arbitrarily extend the casereader's lifetime, by slurping the cases into
+     the shim's buffer in proc_commit().  That is especially useful when output
+     table_items are generated directly from the procedure casereader (e.g. by
+     the LIST procedure) when we are using an output driver that keeps a
+     reference to the output items passed to it (e.g. the GUI output driver in
+     PSPPIRE). */
+  reader = casereader_create_sequential (NULL, dict_get_proto (ds->dict),
+                                         CASENUMBER_MAX,
+                                         &proc_casereader_class, ds);
+  ds->shim = casereader_shim_insert (reader);
+  return reader;
+}
+
+/* Opens dataset DS for reading cases with proc_read.
+   proc_commit must be called when done. */
+struct casereader *
+proc_open (struct dataset *ds)
+{
+  return proc_open_filtering (ds, true);
 }
 
 /* Returns true if a procedure is in progress, that is, if
@@ -298,6 +340,11 @@ proc_casereader_destroy (struct casereader *reader, void *ds_)
   struct dataset *ds = ds_;
   struct ccase *c;
 
+  /* We are always the subreader for a casereader_buffer, so if we're being
+     destroyed then it's because the casereader_buffer has read all the cases
+     that it ever will. */
+  ds->shim = NULL;
+
   /* Make sure transformations happen for every input case, in
      case they have side effects, and ensure that the replacement
      active file gets all the cases it should. */
@@ -318,6 +365,9 @@ proc_casereader_destroy (struct casereader *reader, void *ds_)
 bool
 proc_commit (struct dataset *ds)
 {
+  if (ds->shim != NULL)
+    casereader_shim_slurp (ds->shim);
+
   assert (ds->proc_state == PROC_CLOSED);
   ds->proc_state = PROC_COMMITTED;
 
@@ -561,6 +611,9 @@ create_dataset (void)
 
   ds->caseinit = caseinit_create ();
   proc_cancel_all_transformations (ds);
+
+  ds->syntax_encoding = xstrdup ("Auto");
+
   return ds;
 }
 
@@ -585,6 +638,8 @@ destroy_dataset (struct dataset *ds)
 
   if ( ds->xform_callback)
     ds->xform_callback (false, ds->xform_callback_aux);
+
+  free (ds->syntax_encoding);
   free (ds);
 }