Fix change log.
[pspp-builds.git] / src / procedure.c
index c6209af266451267a8de102df4131b22f40c40b5..67f22c5c0dfca5a0e0442feb0a8888973bd222a1 100644 (file)
    02110-1301, USA. */
 
 #include <config.h>
+
 #include <procedure.h>
-#include <libpspp/message.h>
+
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
-#if HAVE_UNISTD_H
-#include <unistd.h>    /* Required by SunOS4. */
-#endif
-#include <libpspp/alloc.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 <language/command.h>
 #include <data/dictionary.h>
+#include <data/file-handle-def.h>
+#include <data/settings.h>
+#include <data/storage-stream.h>
+#include <data/value-labels.h>
+#include <data/variable.h>
 #include <language/control/control-stack.h>
+#include <libpspp/alloc.h>
 #include <libpspp/message.h>
-#include "expressions/public.h"
-#include <data/file-handle-def.h>
 #include <libpspp/misc.h>
-#include <data/settings.h>
+#include <libpspp/str.h>
 #include <output/manager.h>
 #include <output/table.h>
-#include <libpspp/str.h>
-#include <data/variable.h>
-#include <data/value-labels.h>
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
@@ -82,6 +84,10 @@ static struct dict_compactor *compactor;
 /* Time at which vfm was last invoked. */
 static time_t last_vfm_invocation;
 
+/* Whether we're inside a procedure.
+   For debugging purposes only. */
+static bool in_procedure;
+
 /* Lag queue. */
 int n_lag;                     /* Number of cases to lag. */
 static int lag_count;          /* Number of cases in lag_queue so far. */
@@ -111,7 +117,7 @@ static bool close_active_file (void);
 
 /* Returns the last time the data was read. */
 time_t
-vfm_last_invocation (void) 
+time_of_last_procedure (void) 
 {
   if (last_vfm_invocation == 0)
     update_last_vfm_invocation ();
@@ -175,12 +181,9 @@ procedure (bool (*proc_func) (struct ccase *, void *), void *aux)
 static bool
 internal_procedure (bool (*proc_func) (struct ccase *, void *), void *aux) 
 {
-  static int recursive_call;
   struct write_case_data wc_data;
   bool ok;
 
-  assert (++recursive_call == 1);
-
   wc_data.proc_func = proc_func;
   wc_data.aux = aux;
   create_trns_case (&wc_data.trns_case, default_dict);
@@ -197,8 +200,6 @@ internal_procedure (bool (*proc_func) (struct ccase *, void *), void *aux)
   case_destroy (&wc_data.sink_case);
   case_destroy (&wc_data.trns_case);
 
-  assert (--recursive_call == 0);
-
   return ok;
 }
 
@@ -225,7 +226,7 @@ create_trns_case (struct ccase *trns_case, struct dictionary *dict)
       union value *value = case_data_rw (trns_case, v->fv);
 
       if (v->type == NUMERIC)
-        value->f = v->reinit ? 0.0 : SYSMIS;
+        value->f = v->leave ? 0.0 : SYSMIS;
       else
         memset (value->s, ' ', v->width);
     }
@@ -236,6 +237,9 @@ create_trns_case (struct ccase *trns_case, struct dictionary *dict)
 static void
 open_active_file (void)
 {
+  assert (!in_procedure);
+  in_procedure = true;
+
   /* Make temp_dict refer to the dictionary right before data
      reaches the sink */
   if (!temporary)
@@ -272,9 +276,9 @@ open_active_file (void)
 }
 
 /* Transforms trns_case and writes it to the replacement active
-   file if advisable.  Returns nonzero if more cases can be
-   accepted, zero otherwise.  Do not call this function again
-   after it has returned zero once.  */
+   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)
 {
@@ -378,7 +382,7 @@ execute_transformations (struct ccase *c,
 }
 
 /* Returns nonzero if case C with case number CASE_NUM should be
-   exclude as specified on FILTER or PROCESS IF, otherwise
+   excluded as specified on FILTER or PROCESS IF, otherwise
    zero. */
 static int
 filter_case (const struct ccase *c, int case_idx)
@@ -423,7 +427,7 @@ clear_case (struct ccase *c)
   for (i = 0; i < var_cnt; i++) 
     {
       struct variable *v = dict_get_var (default_dict, i);
-      if (v->init && v->reinit
+      if (!v->leave
         {
           if (v->type == NUMERIC)
             case_data_rw (c, v->fv)->f = SYSMIS;
@@ -480,163 +484,13 @@ close_active_file (void)
   process_if_expr = NULL;
   dict_set_case_limit (default_dict, 0);
   dict_clear_vectors (default_dict);
-  return cancel_transformations ();
-}
-\f
-/* Storage case stream. */
-
-/* Information about storage sink or source. */
-struct storage_stream_info 
-  {
-    struct casefile *casefile;  /* Storage. */
-  };
-
-/* Initializes a storage sink. */
-static void
-storage_sink_open (struct case_sink *sink)
-{
-  struct storage_stream_info *info;
-
-  sink->aux = info = xmalloc (sizeof *info);
-  info->casefile = casefile_create (sink->value_cnt);
-}
-
-/* Destroys storage stream represented by INFO. */
-static void
-destroy_storage_stream_info (struct storage_stream_info *info) 
-{
-  if (info != NULL) 
-    {
-      casefile_destroy (info->casefile);
-      free (info); 
-    }
-}
-
-/* Writes case C to the storage sink SINK.
-   Returns true if successful, false if an I/O error occurred. */
-static bool
-storage_sink_write (struct case_sink *sink, const struct ccase *c)
-{
-  struct storage_stream_info *info = sink->aux;
-
-  return casefile_append (info->casefile, c);
-}
-
-/* Destroys internal data in SINK. */
-static void
-storage_sink_destroy (struct case_sink *sink)
-{
-  destroy_storage_stream_info (sink->aux);
-}
-
-/* Closes the sink and returns a storage source to read back the
-   written data. */
-static struct case_source *
-storage_sink_make_source (struct case_sink *sink) 
-{
-  struct case_source *source
-    = create_case_source (&storage_source_class, sink->aux);
-  sink->aux = NULL;
-  return source;
-}
-
-/* Storage sink. */
-const struct case_sink_class storage_sink_class = 
-  {
-    "storage",
-    storage_sink_open,
-    storage_sink_write,
-    storage_sink_destroy,
-    storage_sink_make_source,
-  };
-\f
-/* Storage source. */
-
-/* Returns the number of cases that will be read by
-   storage_source_read(). */
-static int
-storage_source_count (const struct case_source *source) 
-{
-  struct storage_stream_info *info = source->aux;
-
-  return casefile_get_case_cnt (info->casefile);
-}
 
-/* Reads all cases from the storage source and passes them one by one to
-   write_case(). */
-static bool
-storage_source_read (struct case_source *source,
-                     struct ccase *output_case,
-                     write_case_func *write_case, write_case_data wc_data)
-{
-  struct storage_stream_info *info = source->aux;
-  struct ccase casefile_case;
-  struct casereader *reader;
-  bool ok = true;
+  assert (in_procedure);
+  in_procedure = false;
 
-  for (reader = casefile_get_reader (info->casefile);
-       ok && casereader_read (reader, &casefile_case);
-       case_destroy (&casefile_case))
-    {
-      case_copy (output_case, 0,
-                 &casefile_case, 0,
-                 casefile_get_value_cnt (info->casefile));
-      ok = write_case (wc_data);
-    }
-  casereader_destroy (reader);
-
-  return ok;
-}
-
-/* Destroys the source's internal data. */
-static void
-storage_source_destroy (struct case_source *source)
-{
-  destroy_storage_stream_info (source->aux);
-}
-
-/* Storage source. */
-const struct case_source_class storage_source_class = 
-  {
-    "storage",
-    storage_source_count,
-    storage_source_read,
-    storage_source_destroy,
-  };
-
-struct casefile *
-storage_source_get_casefile (struct case_source *source) 
-{
-  struct storage_stream_info *info = source->aux;
-
-  assert (source->class == &storage_source_class);
-  return info->casefile;
-}
-
-struct case_source *
-storage_source_create (struct casefile *cf)
-{
-  struct storage_stream_info *info;
-
-  info = xmalloc (sizeof *info);
-  info->casefile = cf;
-
-  return create_case_source (&storage_source_class, info);
+  return cancel_transformations ();
 }
 \f
-/* Null sink.  Used by a few procedures that keep track of output
-   themselves and would throw away anything that the sink
-   contained anyway. */
-
-const struct case_sink_class null_sink_class = 
-  {
-    "null",
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-  };
-\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 *
@@ -662,6 +516,9 @@ void
 add_transformation (trns_proc_func *proc, trns_free_func *free, void *private)
 {
   struct transformation *trns;
+
+  assert (!in_procedure);
+
   if (n_trns >= m_trns)
     t_trns = x2nrealloc (t_trns, &m_trns, sizeof *t_trns);
   trns = &t_trns[n_trns++];
@@ -703,73 +560,6 @@ cancel_transformations (void)
   return ok;
 }
 \f
-/* Creates a case source with class CLASS and auxiliary data AUX
-   and based on dictionary DICT. */
-struct case_source *
-create_case_source (const struct case_source_class *class,
-                    void *aux) 
-{
-  struct case_source *source = xmalloc (sizeof *source);
-  source->class = class;
-  source->aux = aux;
-  return source;
-}
-
-/* Destroys case source SOURCE.  It is the caller's responsible to
-   call the source's destroy function, if any. */
-void
-free_case_source (struct case_source *source) 
-{
-  if (source != NULL) 
-    {
-      if (source->class->destroy != NULL)
-        source->class->destroy (source);
-      free (source);
-    }
-}
-
-/* Returns nonzero if a case source is "complex". */
-int
-case_source_is_complex (const struct case_source *source) 
-{
-  return source != NULL && (source->class == &input_program_source_class
-                            || source->class == &file_type_source_class);
-}
-
-/* Returns nonzero if CLASS is the class of SOURCE. */
-int
-case_source_is_class (const struct case_source *source,
-                      const struct case_source_class *class) 
-{
-  return source != NULL && source->class == class;
-}
-
-/* Creates a case sink to accept cases from the given DICT with
-   class CLASS and auxiliary data AUX. */
-struct case_sink *
-create_case_sink (const struct case_sink_class *class,
-                  const struct dictionary *dict,
-                  void *aux) 
-{
-  struct case_sink *sink = xmalloc (sizeof *sink);
-  sink->class = class;
-  sink->value_cnt = dict_get_compacted_value_cnt (dict);
-  sink->aux = aux;
-  return sink;
-}
-
-/* Destroys case sink SINK.  */
-void
-free_case_sink (struct case_sink *sink) 
-{
-  if (sink != NULL) 
-    {
-      if (sink->class->destroy != NULL)
-        sink->class->destroy (sink);
-      free (sink); 
-    }
-}
-\f
 /* Represents auxiliary data for handling SPLIT FILE. */
 struct split_aux_data 
   {
@@ -883,8 +673,8 @@ dump_splits (struct ccase *c)
 
   t = tab_create (3, split_cnt + 1, 0);
   tab_dim (t, tab_natural_dimensions);
-  tab_vline (t, TAL_1 | TAL_SPACING, 1, 0, split_cnt);
-  tab_vline (t, TAL_1 | TAL_SPACING, 2, 0, split_cnt);
+  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"));
@@ -1014,6 +804,4 @@ discard_variables (void)
   process_if_expr = NULL;
 
   cancel_temporary ();
-
-  pgm_state = STATE_INIT;
 }