Add auxiliary argument to procedure() interface. Associated small
authorBen Pfaff <blp@gnu.org>
Fri, 13 Feb 2004 08:01:45 +0000 (08:01 +0000)
committerBen Pfaff <blp@gnu.org>
Fri, 13 Feb 2004 08:01:45 +0000 (08:01 +0000)
clean-ups of vfm interface.

22 files changed:
src/ChangeLog
src/aggregate.c
src/autorecode.c
src/command.c
src/crosstabs.q
src/data-list.c
src/data-list.h [new file with mode: 0644]
src/descript.q
src/dfm.c
src/file-type.c
src/flip.c
src/frequencies.q
src/get.c
src/inpt-pgm.c
src/list.q
src/matrix-data.c
src/modify-vars.c
src/sort.c
src/sort.h
src/t-test.q
src/vfm.c
src/vfm.h

index d463a5139e8681c8b37c0a39113eda146f473b92..0c7b9fb1d7acabc7267ce892b165df29bd9f7eae 100644 (file)
@@ -1,3 +1,58 @@
+Thu Feb 12 23:35:15 2004  Ben Pfaff  <blp@gnu.org>
+
+       Add auxiliary argument to procedure() interface.  Associated small
+       clean-ups of vfm interface.
+       
+       * Updated every caller of procedure() and process_active_file() to
+       reflect modified interface.  Simple, ordinary changes not listed
+       otherwise below.
+
+       * Updated every function that implements struct case_stream's
+       `read' function to take a write_case_func and a write_case_data.
+       Also updated every caller of write_case() to instead call them
+       through these arguments.  In some cases this meant that the extra
+       args had to be threaded through a couple of extra levels.  This
+       wasn't difficult or interesting so the details won't be given.
+
+       * data-list.c: (struct repeating_data_trns) Add members
+       `write_case', `wc_data' as kluge.
+       (read_one_set_of_repetitions) Rename repeating_data_trns_proc and
+       make non-static.
+       (repeating_data_set_write_case) New function.
+
+       * data-list.h: New file to declare repeating_data_trns_proc() and
+       repeating_data_set_write_case().
+
+       * inpt-pgm.c: (input_program_source_read) Call
+       repeating_data_set_write_case() for all the REPEATING DATA
+       transformations, so that they know where to send their cases.
+       It's a big kluge.  Also kluge in END CASE.
+       (end_case_trns_proc) Never called anymore, but we still need it,
+       so just assert(0).
+
+       * sort.c: (read_sort_output) Update to match struct case_stream
+       `read' member.
+
+       * vfm.c: (struct write_case_data) New structure.
+       (proc_func) Removed.
+       (virt_proc_func) Removed.
+       (begin_func) Removed.
+       (virt_begin_func) Removed.
+       (end_func) Removed.
+       (write_case) Removed.
+       (procedure) Added an auxiliary parameter to each function pointer
+       argument's prototype.  Added an auxiliary data parameter.
+       Rewrote.
+       (process_active_file) Ditto.
+       (process_active_file_write_case) Pass aux data along.
+       (close_active_file) Ditto.
+       (procedure_write_case) Ditto.
+       (SPLIT_FILE_procfunc) Ditto.
+
+       * vfm.h: (typedef write_case_data) New.
+       (typedef write_case_func) New.
+       (struct case_stream) Add parameters to `read' member prototype.
+       
 Thu Feb 12 19:24:53 WST 2004 John Darrington <john@darrington.wattle.id.au>
 
        * t-test.q:  Added calculations for independent samples. (But no Levene
index 1c885b1be54bfe6e8e837f8603bed9d3dc78b281..2a564167fefab35ca615f435df31414d1eebd6e0 100644 (file)
@@ -141,11 +141,11 @@ static int aggregate_single_case (struct ccase *input, struct ccase *output);
 static int create_sysfile (void);
 
 static int agr_00x_trns_proc (struct trns_header *, struct ccase *);
-static void agr_00x_end_func (void);
+static void agr_00x_end_func (void *);
 static int agr_10x_trns_proc (struct trns_header *, struct ccase *);
 static void agr_10x_trns_free (struct trns_header *);
-static void agr_10x_end_func (void);
-static int agr_11x_func (void);
+static void agr_10x_end_func (void *);
+static int agr_11x_func (write_case_data);
 
 #if DEBUGGING
 static void debug_print (int flags);
@@ -343,7 +343,7 @@ cmd_aggregate (void)
          
          agr_dict = NULL;
 
-         procedure (NULL, NULL, agr_00x_end_func);
+         procedure (NULL, NULL, agr_00x_end_func, NULL);
          break;
        }
 
@@ -359,7 +359,7 @@ cmd_aggregate (void)
            t->free = agr_10x_trns_free;
            add_transformation (t);
 
-           procedure (NULL, NULL, agr_10x_end_func);
+           procedure (NULL, NULL, agr_10x_end_func, NULL);
          }
          
          break;
@@ -371,12 +371,12 @@ cmd_aggregate (void)
        
        if (!create_sysfile ())
          goto lossage;
-       read_sort_output (agr_11x_func);
+       read_sort_output (agr_11x_func, NULL);
        
        {
          struct ccase *save_temp_case = temp_case;
          temp_case = NULL;
-         agr_11x_func ();
+         agr_11x_func (NULL);
          temp_case = save_temp_case;
        }
        
@@ -1207,7 +1207,7 @@ agr_00x_trns_proc (struct trns_header *h UNUSED, struct ccase *c)
    the cases have been output; very little has been cleaned up at this
    point. */
 static void
-agr_00x_end_func (void)
+agr_00x_end_func (void *aux UNUSED)
 {
   /* Ensure that info for the last break group gets written to the
      active file. */
@@ -1272,7 +1272,7 @@ agr_10x_trns_free (struct trns_header *h UNUSED)
 /* Ensure that info for the last break group gets written to the
    system file. */
 static void
-agr_10x_end_func (void)
+agr_10x_end_func (void *aux UNUSED)
 {
   dump_aggregate_info (buf_1xx);
   write_case_to_sfm ();
@@ -1283,7 +1283,7 @@ agr_10x_end_func (void)
    appropriate.  If temp_case is NULL, finishes up writing the last
    case if necessary. */
 static int
-agr_11x_func (void)
+agr_11x_func (write_case_data wc_data UNUSED)
 {
   if (temp_case != NULL)
     {
index c487255ffe6048d2f858c9632129eca90cfc26d3..edc07701b2bf59a4f275101101819cb1684a5583 100644 (file)
@@ -76,7 +76,7 @@ static int print;
 
 static int autorecode_trns_proc (struct trns_header *, struct ccase *);
 static void autorecode_trns_free (struct trns_header *);
-static int autorecode_proc_func (struct ccase *);
+static int autorecode_proc_func (struct ccase *, void *);
 static hsh_compare_func compare_alpha_value, compare_numeric_value;
 static hsh_hash_func hash_alpha_value, hash_numeric_value;
 static void recode (void);
@@ -153,7 +153,7 @@ cmd_autorecode (void)
       h_trans[i] = hsh_create (10, compare_numeric_value,
                               hash_numeric_value, NULL, NULL);
 
-  procedure (NULL, autorecode_proc_func, NULL);
+  procedure (NULL, autorecode_proc_func, NULL, NULL);
 
   for (i = 0; i < nv_dest; i++)
     {
@@ -309,7 +309,7 @@ hash_numeric_value (const void *a_, void *foo UNUSED)
 }
 
 static int
-autorecode_proc_func (struct ccase * c)
+autorecode_proc_func (struct ccase *c, void *aux UNUSED)
 {
   int i;
 
index f4c76c33b32bde5d8cb9ed67f1cafad17c8ed5a3..b386317a2c1052f07617f51f48ef022328b73339 100644 (file)
@@ -561,7 +561,7 @@ int
 cmd_execute (void)
 {
   lex_match_id ("EXECUTE");
-  procedure (NULL, NULL, NULL);
+  procedure (NULL, NULL, NULL, NULL);
   return lex_end_of_command ();
 }
 
index 7502259a4ad6fdd476a50cc58d53f271d30ad7a9..11f3832dd7ef2fe2c20c72271976768ff8636feb 100644 (file)
@@ -148,10 +148,10 @@ static struct pool *pl_tc;        /* For table cells. */
 static struct pool *pl_col;    /* For column data. */
 
 static int internal_cmd_crosstabs (void);
-static void precalc (void);
-static int calc_general (struct ccase *);
-static int calc_integer (struct ccase *);
-static void postcalc (void);
+static void precalc (void *);
+static int calc_general (struct ccase *, void *);
+static int calc_integer (struct ccase *, void *);
+static void postcalc (void *);
 static void submit (struct tab_table *);
 
 #if DEBUGGING
@@ -277,7 +277,8 @@ internal_cmd_crosstabs (void)
   else
     write = CRS_WR_NONE;
 
-  procedure (precalc, mode == GENERAL ? calc_general : calc_integer, postcalc);
+  procedure (precalc, mode == GENERAL ? calc_general : calc_integer, postcalc,
+             NULL);
 
   return CMD_SUCCESS;
 }
@@ -515,7 +516,7 @@ static unsigned hash_table_entry (const void *, void *);
 
 /* Set up the crosstabulation tables for processing. */
 static void
-precalc (void)
+precalc (void *aux UNUSED)
 {
   if (mode == GENERAL)
     {
@@ -584,7 +585,7 @@ precalc (void)
 
 /* Form crosstabulations for general mode. */
 static int
-calc_general (struct ccase *c)
+calc_general (struct ccase *c, void *aux UNUSED)
 {
   /* Case weight. */
   double weight = dict_get_case_weight (default_dict, c);
@@ -654,7 +655,7 @@ calc_general (struct ccase *c)
 }
 
 static int
-calc_integer (struct ccase *c)
+calc_integer (struct ccase *c, void *aux UNUSED)
 {
   /* Case weight. */
   double weight = dict_get_case_weight (default_dict, c);
@@ -807,7 +808,7 @@ static void output_pivot_table (struct table_entry **, struct table_entry **,
 static void make_summary_table (void);
 
 static void
-postcalc (void)
+postcalc (void *aux UNUSED)
 {
   if (mode == GENERAL)
     {
index 1a6b9af89f0699417055f34ce65bc7518e170792..7512a8e18f156847a1b1c4f180d1f2ce945f3a78 100644 (file)
@@ -18,6 +18,7 @@
    02111-1307, USA. */
 
 #include <config.h>
+#include "data-list.h"
 #include <assert.h>
 #include <ctype.h>
 #include <float.h>
@@ -967,14 +968,13 @@ cut_field (char **ret_cp, int *ret_len)
 static int read_from_data_list_fixed (void);
 static int read_from_data_list_free (void);
 static int read_from_data_list_list (void);
-static int do_reading (int flag);
 
 /* FLAG==0: reads any number of cases into temp_case and calls
    write_case() for each one, returns garbage.  FLAG!=0: reads one
    case into temp_case and returns -2 on eof, -1 otherwise.
    Uses dlsp as the relevant parsing description. */
 static int
-do_reading (int flag)
+do_reading (int flag, write_case_func *write_case, write_case_data wc_data)
 {
   int (*func) (void);
 
@@ -1030,7 +1030,7 @@ do_reading (int flag)
   else
     {
       while (func () != -2)
-       if (!write_case ())
+       if (!write_case (wc_data))
          {
            debug_printf ((_("abort in write_case()\n")));
            break;
@@ -1202,16 +1202,16 @@ static int
 read_one_case (struct trns_header *t, struct ccase *c UNUSED)
 {
   dlsp = (struct data_list_pgm *) t;
-  return do_reading (1);
+  return do_reading (1, NULL, NULL);
 }
 \f
 /* Reads all the records from the data file and passes them to
    write_case(). */
 static void
-data_list_source_read (void)
+data_list_source_read (write_case_func *write_case, write_case_data wc_data)
 {
   dlsp = &dls;
-  do_reading (0);
+  do_reading (0, write_case, wc_data);
 }
 
 /* Destroys the source's internal data. */
@@ -1258,12 +1258,14 @@ struct repeating_data_trns
     int id_beg, id_end;                        /* ID subcommand, beginning & end columns. */
     struct variable *id_var;           /* ID subcommand, DATA LIST variable. */
     struct fmt_spec id_spec;           /* ID subcommand, input format spec. */
+    write_case_func *write_case;
+    write_case_data wc_data;
   };
 
 /* Information about the transformation being parsed. */
 static struct repeating_data_trns rpd;
 
-static int read_one_set_of_repetitions (struct trns_header *, struct ccase *);
+int repeating_data_trns_proc (struct trns_header *, struct ccase *);
 static int parse_num_or_var (struct rpd_num_or_var *, const char *);
 static int parse_repeating_data (void);
 static void find_variable_input_spec (struct variable *v,
@@ -1523,7 +1525,7 @@ cmd_repeating_data (void)
   {
     struct repeating_data_trns *new_trns;
 
-    rpd.h.proc = read_one_set_of_repetitions;
+    rpd.h.proc = repeating_data_trns_proc;
     rpd.h.free = destroy_dls;
 
     new_trns = xmalloc (sizeof *new_trns);
@@ -1787,7 +1789,7 @@ rpd_parse_record (int beg, int end, int ofs, struct ccase *c,
 
        cur += ofs;
 
-       if (!write_case ())
+       if (!t->write_case (t->wc_data))
          return 0;
       }
   }
@@ -1798,8 +1800,8 @@ rpd_parse_record (int beg, int end, int ofs, struct ccase *c,
 /* Analogous to read_one_case; reads one set of repetitions of the
    elements in the REPEATING DATA structure.  Returns -1 on success,
    -2 on end of file or on failure. */
-static int
-read_one_set_of_repetitions (struct trns_header *trns, struct ccase *c)
+int
+repeating_data_trns_proc (struct trns_header *trns, struct ccase *c)
 {
   dfm_push (dlsp->handle);
   
@@ -1932,3 +1934,19 @@ read_one_set_of_repetitions (struct trns_header *trns, struct ccase *c)
      transformations. */
   return -3;
 }
+
+/* This is a kluge.  It is only here until I have more time
+   tocome up with something better.  It lets
+   repeating_data_trns_proc() know how to write the cases that it
+   composes. */
+void
+repeating_data_set_write_case (struct trns_header *trns,
+                               write_case_func *write_case,
+                               write_case_data wc_data) 
+{
+  struct repeating_data_trns *t = (struct repeating_data_trns *) trns;
+
+  assert (trns->proc == repeating_data_trns_proc);
+  t->write_case = write_case;
+  t->wc_data = wc_data;
+}
diff --git a/src/data-list.h b/src/data-list.h
new file mode 100644 (file)
index 0000000..736d2a5
--- /dev/null
@@ -0,0 +1,33 @@
+/* PSPP - computes sample statistics.
+   Copyright (C) 2004 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., 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA. */
+
+#ifndef INCLUDED_DATA_LIST_H
+#define INCLUDED_DATA_LIST_H
+
+/* FIXME: This header is a kluge and should go away when we come
+   up with a less-klugy solution. */
+
+#include "var.h"
+#include "vfm.h"
+
+int repeating_data_trns_proc (struct trns_header *, struct ccase *);
+void repeating_data_set_write_case (struct trns_header *,
+                                    write_case_func *, write_case_data);
+
+#endif /* data-list.h */
index 6ccec2a44a4f361747c58813bd051a762cfacfc5..84bc16c5fabc956d978135b4c3b3cbc8a2477586 100644 (file)
@@ -178,9 +178,9 @@ static void dump_z_table (void);
 static void run_z_pass (void);
 
 /* Procedure execution functions. */
-static int calc (struct ccase *);
-static void precalc (void);
-static void postcalc (void);
+static int calc (struct ccase *, void *);
+static void precalc (void *);
+static void postcalc (void *);
 static void display (void);
 \f
 /* Parser and outline. */
@@ -289,7 +289,7 @@ cmd_descriptives (void)
 
   /* Data pass! */
   bad_weight = 0;
-  procedure (precalc, calc, postcalc);
+  procedure (precalc, calc, postcalc, NULL);
 
   if (bad_weight)
     msg (SW, _("At least one case in the data file had a weight value "
@@ -569,7 +569,7 @@ run_z_pass (void)
 /* Statistical calculation. */
 
 static void
-precalc (void)
+precalc (void *aux UNUSED)
 {
   int i;
 
@@ -593,7 +593,7 @@ precalc (void)
 }
 
 static int
-calc (struct ccase * c)
+calc (struct ccase * c, void *aux UNUSED)
 {
   int i;
 
@@ -685,7 +685,7 @@ iterate:
 }
 
 static void
-postcalc (void)
+postcalc (void *aux UNUSED)
 {
   int i;
 
index b5023a82ef9caeeb0c6af468d6c90ea27ec9051d..9905b6b3e25f8cc8c688a1bde3b268dbf2b61457 100644 (file)
--- a/src/dfm.c
+++ b/src/dfm.c
@@ -669,7 +669,7 @@ cmd_begin_data (void)
   /* We don't actually read from the inline file.  The input procedure
      is what reads from it. */
   getl_prompt = GETL_PRPT_DATA;
-  procedure (NULL, NULL, NULL);
+  procedure (NULL, NULL, NULL, NULL);
 
   ext = inline_file->ext;
 
index 4181538f786dc6c80fa9e4bde68c0be8443c1cd2..44aa9bd95c29bbec3aac6f3f8262f7ba673ff25b 100644 (file)
@@ -610,7 +610,8 @@ cmd_end_file_type (void)
 /* Reads any number of cases into temp_case and calls write_case() for
    each one.  Compare data-list.c:read_from_data_list. */
 static void
-file_type_source_read (void)
+file_type_source_read (write_case_func *write_case UNUSED,
+                       write_case_data wc_data UNUSED)
 {
   char *line;
   int len;
index de02119eb485166e7b45d57b2bc89880b59acd5b..c4bb5fdc9b930ef27ec4249d75483da63d58a036 100644 (file)
@@ -100,7 +100,7 @@ cmd_flip (void)
   temp_trns = temporary = 0;
   vfm_sink = &flip_stream;
   new_names_tail = NULL;
-  procedure (NULL, NULL, NULL);
+  procedure (NULL, NULL, NULL, NULL);
 
   dict_clear (default_dict);
   if (!build_dictionary ())
@@ -258,7 +258,7 @@ flip_stream_init (void)
 
 /* Reads the FLIP stream and passes it to write_case(). */
 static void
-flip_stream_read (void)
+flip_stream_read (write_case_func *write_case, write_case_data wc_data)
 {
   if (src || (src == NULL && src_file == NULL))
     {
@@ -276,7 +276,7 @@ flip_stream_read (void)
          for (iter = src, j = 1; iter; iter = iter->next, j++)
            temp_case->data[j].f = iter->v[i];
 
-         if (!write_case ())
+         if (!write_case (wc_data))
            return;
        }
     }
@@ -295,7 +295,7 @@ flip_stream_read (void)
            msg (FE, _("Error reading FLIP source file: %s."),
                 strerror (errno));
 
-         if (!write_case ())
+         if (!write_case (wc_data))
            return;
        }
     }
index d1a75f72e347046c4c272f3aba410a61c3e4aff2..850beda2bc495d22a7a29dd516e3165892359da8 100644 (file)
@@ -160,9 +160,9 @@ static struct pool *gen_pool;       /* General mode. */
 
 static void determine_charts (void);
 
-static void precalc (void);
-static int calc (struct ccase *);
-static void postcalc (void);
+static void precalc (void *);
+static int calc (struct ccase *, void *);
+static void postcalc (void *);
 
 static void postprocess_freq_tab (struct variable *);
 static void dump_full (struct variable *);
@@ -246,7 +246,7 @@ internal_cmd_frequencies (void)
     cmd.sort = FRQ_AVALUE;
 
   /* Do it! */
-  procedure (precalc, calc, postcalc);
+  procedure (precalc, calc, postcalc, NULL);
 
   return CMD_SUCCESS;
 }
@@ -355,7 +355,7 @@ determine_charts (void)
 
 /* Add data from case C to the frequency table. */
 static int
-calc (struct ccase *c)
+calc (struct ccase *c, void *aux UNUSED)
 {
   double weight;
   int i;
@@ -408,7 +408,7 @@ calc (struct ccase *c)
 /* Prepares each variable that is the target of FREQUENCIES by setting
    up its hash table. */
 static void
-precalc (void)
+precalc (void *aux UNUSED)
 {
   int i;
 
@@ -451,7 +451,7 @@ precalc (void)
 /* Finishes up with the variables after frequencies have been
    calculated.  Displays statistics, percentiles, ... */
 static void
-postcalc (void)
+postcalc (void *aux UNUSED)
 {
   int i;
 
index 72c49833debcc33d03b94ca9c880e3df16d4b129..182ef0e748cbf864811cab64cc8e3f6269132b71 100644 (file)
--- a/src/get.c
+++ b/src/get.c
@@ -61,7 +61,7 @@ static struct file_handle *get_file;
 static struct save_trns *trns;
 
 static int trim_dictionary (struct dictionary * dict, int *options);
-static int save_write_case_func (struct ccase *);
+static int save_write_case_func (struct ccase *, void *);
 static int save_trns_proc (struct trns_header *, struct ccase *);
 static void save_trns_free (struct trns_header *);
 
@@ -192,7 +192,7 @@ cmd_save_internal (int xsave)
   if (xsave == 0)
     /* SAVE. */
     {
-      procedure (NULL, save_write_case_func, NULL);
+      procedure (NULL, save_write_case_func, NULL, NULL);
       save_trns_free (&t->h);
     }
   else
@@ -217,7 +217,7 @@ cmd_xsave (void)
 }
 
 static int
-save_write_case_func (struct ccase * c)
+save_write_case_func (struct ccase * c, void *aux UNUSED)
 {
   save_trns_proc (&trns->h, c);
   return 1;
@@ -477,10 +477,10 @@ get_source_destroy_source (void)
 /* Reads all the cases from the data file and passes them to
    write_case(). */
 static void
-get_source_read (void)
+get_source_read (write_case_func *write_case, write_case_data wc_data)
 {
   while (sfm_read_case (get_file, temp_case->data, default_dict)
-        && write_case ())
+        && write_case (wc_data))
     ;
   get_source_destroy_source ();
 }
@@ -546,9 +546,9 @@ static void mtf_free_file (struct mtf_file *file);
 static int mtf_merge_dictionary (struct mtf_file *f);
 static void mtf_delete_file_in_place (struct mtf_file **file);
 
-static void mtf_read_nonactive_records (void);
-static void mtf_processing_finish (void);
-static int mtf_processing (struct ccase *);
+static void mtf_read_nonactive_records (void *);
+static void mtf_processing_finish (void *);
+static int mtf_processing (struct ccase *, void *);
 
 static char *var_type_description (struct variable *);
 
@@ -857,7 +857,7 @@ cmd_match_files (void)
           dict_get_var_cnt (mtf_master) * sizeof *mtf_seq_nums);
 
   process_active_file (mtf_read_nonactive_records, mtf_processing,
-                      mtf_processing_finish);
+                      mtf_processing_finish, NULL);
   mtf_master = NULL;
   
   mtf_free ();
@@ -870,7 +870,7 @@ lossage:
 
 /* Repeats 2...8 an arbitrary number of times. */
 static void
-mtf_processing_finish (void)
+mtf_processing_finish (void *aux UNUSED)
 {
   /* Find the active file and delete it. */
   {
@@ -885,7 +885,7 @@ mtf_processing_finish (void)
   }
   
   while (mtf_head && mtf_head->type == MTF_FILE)
-    if (!mtf_processing (temp_case))
+    if (!mtf_processing (temp_case, NULL))
       break;
 }
 
@@ -980,7 +980,7 @@ mtf_delete_file_in_place (struct mtf_file **file)
 
 /* Read a record from every input file except the active file. */
 static void
-mtf_read_nonactive_records (void)
+mtf_read_nonactive_records (void *aux UNUSED)
 {
   struct mtf_file *iter;
 
@@ -1046,7 +1046,7 @@ mtf_compare_BY_values (struct mtf_file *a, struct mtf_file *b)
 
 /* Perform one iteration of steps 3...7 above. */
 static int
-mtf_processing (struct ccase *c UNUSED)
+mtf_processing (struct ccase *c UNUSED, void *aux UNUSED)
 {
   /* List of files with minimum BY values. */
   struct mtf_file *min_head, *min_tail;
@@ -1412,10 +1412,10 @@ cmd_import (void)
 /* Reads all the cases from the data file and passes them to
    write_case(). */
 static void
-import_source_read (void)
+import_source_read (write_case_func *write_case, write_case_data wc_data)
 {
   while (pfm_read_case (get_file, temp_case->data, default_dict)
-        && write_case ())
+        && write_case (wc_data))
     ;
   get_source_destroy_source ();
 }
@@ -1431,7 +1431,7 @@ struct case_stream import_source =
     "IMPORT",
   };
 \f
-static int export_write_case_func (struct ccase *c);
+static int export_write_case_func (struct ccase *c, void *);
      
 /* Parses the EXPORT command.  */
 /* FIXME: same as cmd_save_internal(). */
@@ -1492,14 +1492,14 @@ cmd_export (void)
   t->case_buf = xmalloc (sizeof *t->case_buf * t->nvar);
   dict_destroy (dict);
 
-  procedure (NULL, export_write_case_func, NULL);
+  procedure (NULL, export_write_case_func, NULL, NULL);
   save_trns_free (&t->h);
 
   return CMD_SUCCESS;
 }
 
 static int
-export_write_case_func (struct ccase *c)
+export_write_case_func (struct ccase *c, void *aux UNUSED)
 {
   union value *p = (union value *) trns->case_buf;
   int i;
index 7ef6904bbe7599cb5e6735bc1505cf1df56fb384..144aceb51caa777aca723edcd724e6e9a65a71f5 100644 (file)
@@ -23,6 +23,7 @@
 #include <stdlib.h>
 #include "alloc.h"
 #include "command.h"
+#include "data-list.h"
 #include "dfm.h"
 #include "error.h"
 #include "expr.h"
@@ -168,7 +169,8 @@ clear_case (void)
    file.  -1 means go on to the next transformation.  Otherwise the
    return value is the index of the transformation to go to next. */
 static void
-input_program_source_read (void)
+input_program_source_read (write_case_func *write_case,
+                           write_case_data wc_data)
 {
   int i;
 
@@ -182,6 +184,12 @@ input_program_source_read (void)
     if (t_trns[i]->proc == end_case_trns_proc)
       end_case = 1;
 
+  /* FIXME: This code should not be necessary.  It is an ugly
+     kluge. */
+  for (i = 0; i < f_trns; i++)
+    if (t_trns[i]->proc == repeating_data_trns_proc)
+      repeating_data_set_write_case (t_trns[i], write_case, wc_data);
+
   init_case ();
   for (;;)
     {
@@ -201,6 +209,16 @@ input_program_source_read (void)
          if (t_trns[i]->proc == end_case_trns_proc)
            printf ("\n");
 #endif
+
+          if (t_trns[i]->proc == end_case_trns_proc) 
+            {
+              if (!write_case (wc_data))
+                return;
+              clear_case ();
+              i++;
+              continue;
+            }
+
          code = t_trns[i]->proc (t_trns[i], temp_case);
          switch (code)
            {
@@ -224,7 +242,7 @@ input_program_source_read (void)
 
       /* Write the case if appropriate. */
       if (!end_case)
-       if (!write_case ())
+       if (!write_case (wc_data))
          return;
 
       /* Blank out the case for the next iteration. */
@@ -278,13 +296,7 @@ cmd_end_case (void)
 int
 end_case_trns_proc (struct trns_header *t UNUSED, struct ccase * c UNUSED)
 {
-#if DEBUGGING
-  printf ("END CASE\n");
-#endif
-  if (!write_case ())
-    return -2;
-  clear_case ();
-  return -1;
+  assert (0);
 }
 
 /* REREAD transformation. */
index 952283bc7b899c8f18f94589e39aabe12c380511..5e312f81e9eea28e620ffc9c4b42da608534a78d 100644 (file)
@@ -77,11 +77,11 @@ static int n_chars_width (struct outp_driver *d);
 static void write_line (struct outp_driver *d, char *s);
 
 /* Other functions. */
-static int list_cases (struct ccase *);
+static int list_cases (struct ccase *, void *);
 static void determine_layout (void);
 static void clean_up (void);
 static void write_header (struct outp_driver *);
-static void write_all_headers (void);
+static void write_all_headers (void *);
 
 /* Returns the number of text lines that can fit on the remainder of
    the page. */
@@ -227,7 +227,7 @@ cmd_list (void)
   determine_layout ();
 
   case_num = 0;
-  procedure (write_all_headers, list_cases, NULL);
+  procedure (write_all_headers, list_cases, NULL, NULL);
   free (line_buf);
 
   clean_up ();
@@ -238,7 +238,7 @@ cmd_list (void)
 /* Writes headers to all devices.  This is done at the beginning of
    each SPLIT FILE group. */
 static void
-write_all_headers (void)
+write_all_headers (void *aux UNUSED)
 {
   struct outp_driver *d;
 
@@ -618,7 +618,7 @@ determine_layout (void)
 }
 
 static int
-list_cases (struct ccase *c)
+list_cases (struct ccase *c, void *aux UNUSED)
 {
   struct outp_driver *d;
   
index 4af89083491752b7d8f543db59ae63ba176f80e7..fd3d3807671c96fda81a872e48f90f0de18c8190 100644 (file)
@@ -1029,8 +1029,9 @@ static double *split_values;
 
 static int nr_read_splits (int compare);
 static int nr_read_factors (int cell);
-static void nr_output_data (void);
-static int matrix_data_read_without_rowtype (void);
+static void nr_output_data (write_case_func *, write_case_data);
+static void matrix_data_read_without_rowtype (write_case_func *,
+                                              write_case_data);
 
 /* Read from the data file and write it to the active file. */
 static void
@@ -1045,10 +1046,10 @@ read_matrices_without_rowtype (void)
   nr_factor_values = xmalloc (sizeof *nr_factor_values * n_factors * cells);
   max_cell_index = 0;
 
-  matrix_data_source.read = (void (*)(void)) matrix_data_read_without_rowtype;
+  matrix_data_source.read = matrix_data_read_without_rowtype;
   vfm_source = &matrix_data_source;
   
-  procedure (NULL, NULL, NULL);
+  procedure (NULL, NULL, NULL, NULL);
 
   free (split_values);
   free (nr_factor_values);
@@ -1213,8 +1214,9 @@ nr_read_data_lines (int per_factor, int cell, int content, int compare)
 
 /* When ROWTYPE_ does not appear in the data, reads the matrices and
    writes them to the output file.  Returns success. */
-static int
-matrix_data_read_without_rowtype (void)
+static void
+matrix_data_read_without_rowtype (write_case_func *write_case,
+                                  write_case_data wc_data)
 {
   {
     int *cp;
@@ -1257,7 +1259,7 @@ matrix_data_read_without_rowtype (void)
       int *bp, *ep, *np;
       
       if (!nr_read_splits (0))
-       return 0;
+       return;
       
       for (bp = contents; *bp != EOC; bp = np)
        {
@@ -1292,15 +1294,15 @@ matrix_data_read_without_rowtype (void)
 
                for (cp = bp; cp < ep; cp++) 
                  if (!nr_read_data_lines (per_factor, i, *cp, cp != bp))
-                   return 0;
+                   return;
              }
          }
        }
 
-      nr_output_data ();
+      nr_output_data (write_case, wc_data);
 
       if (dict_get_split_cnt (default_dict) == 0 || !another_token ())
-       return 1;
+       return;
     }
 }
 
@@ -1411,7 +1413,8 @@ nr_read_factors (int cell)
 /* Write the contents of a cell having content type CONTENT and data
    CP to the active file. */
 static void
-dump_cell_content (int content, double *cp)
+dump_cell_content (int content, double *cp,
+                   write_case_func *write_case, write_case_data wc_data)
 {
   int type = content_type[content];
 
@@ -1442,14 +1445,14 @@ dump_cell_content (int content, double *cp)
                             dict_get_var (default_dict,
                                           first_continuous + i)->name,
                            8);
-       write_case ();
+       write_case (wc_data);
       }
   }
 }
 
 /* Finally dump out everything from nr_data[] to the output file. */
 static void
-nr_output_data (void)
+nr_output_data (write_case_func *write_case, write_case_data wc_data)
 {
   {
     struct variable *const *split;
@@ -1487,7 +1490,8 @@ nr_output_data (void)
                  assert (nr_data[content] != NULL
                          && nr_data[content][cell] != NULL);
 
-                 dump_cell_content (content, nr_data[content][cell]);
+                 dump_cell_content (content, nr_data[content][cell],
+                                     write_case, wc_data);
                }
          }
        }
@@ -1505,7 +1509,8 @@ nr_output_data (void)
     
     for (content = 0; content <= PROX; content++)
       if (!is_per_factor[content] && nr_data[content] != NULL)
-       dump_cell_content (content, nr_data[content][0]);
+       dump_cell_content (content, nr_data[content][0],
+                           write_case, wc_data);
   }
 }
 \f
@@ -1529,12 +1534,13 @@ struct factor_data *wr_data;
 /* Current factor. */
 struct factor_data *wr_current;
 
-static int wr_read_splits (void);
-static int wr_output_data (void);
+static int wr_read_splits (write_case_func *, write_case_data);
+static int wr_output_data (write_case_func *, write_case_data);
 static int wr_read_rowtype (void);
 static int wr_read_factors (void);
 static int wr_read_indeps (void);
-static int matrix_data_read_with_rowtype (void);
+static void matrix_data_read_with_rowtype (write_case_func *,
+                                           write_case_data);
 
 /* When ROWTYPE_ appears in the data, reads the matrices and writes
    them to the output file. */
@@ -1546,40 +1552,40 @@ read_matrices_with_rowtype (void)
   split_values = NULL;
   cells = 0;
 
-  matrix_data_source.read = (void (*)(void)) matrix_data_read_with_rowtype;
+  matrix_data_source.read = matrix_data_read_with_rowtype;
   vfm_source = &matrix_data_source;
   
-  procedure (NULL, NULL, NULL);
+  procedure (NULL, NULL, NULL, NULL);
 
   free (split_values);
   fh_close_handle (data_file);
 }
 
 /* Read from the data file and write it to the active file. */
-static int
-matrix_data_read_with_rowtype (void)
+static void
+matrix_data_read_with_rowtype (write_case_func *write_case,
+                               write_case_data wc_data)
 {
   do
     {
-      if (!wr_read_splits ())
-       return 0;
+      if (!wr_read_splits (write_case, wc_data))
+       return;
 
       if (!wr_read_factors ())
-       return 0;
+       return;
 
       if (!wr_read_indeps ())
-       return 0;
+       return;
     }
   while (another_token ());
 
-  wr_output_data ();
-  return 1;
+  wr_output_data (write_case, wc_data);
 }
 
 /* Read the split file variables.  If they differ from the previous
    set of split variables then output the data.  Returns success. */
 static int 
-wr_read_splits (void)
+wr_read_splits (write_case_func *write_case, write_case_data wc_data)
 {
   int compare;
   size_t split_cnt;
@@ -1614,7 +1620,7 @@ wr_read_splits (void)
 
        if (compare && split_values[i] != mtokval && !different)
          {
-           if (!wr_output_data ())
+           if (!wr_output_data (write_case, wc_data))
              return 0;
            different = 1;
            cells = 0;
@@ -1664,7 +1670,7 @@ compare_factors (const void *a_, const void *b_)
 /* Write out the data for the current split file to the active
    file. */
 static int 
-wr_output_data (void)
+wr_output_data (write_case_func *write_case, write_case_data wc_data)
 {
   {
     struct variable *const *split;
@@ -1742,7 +1748,8 @@ wr_output_data (void)
 
              fill_matrix (content, iter->data[content]);
 
-             dump_cell_content (content, iter->data[content]);
+             dump_cell_content (content, iter->data[content],
+                                 write_case, wc_data);
            }
        }
       }
index bce6ea1bb337daef2736bba4de9c761f0ed4bbeb..c68941a39dce48e290faa034cdf0cf02656785b5 100644 (file)
@@ -309,7 +309,7 @@ cmd_modify_vars (void)
   if (already_encountered & (1 | 4))
     {
       /* Read the data. */
-      procedure (NULL, NULL, NULL);
+      procedure (NULL, NULL, NULL, NULL);
     }
 
   if (!rearrange_dict (default_dict, &vm))
index de3ff977aa86af822e78cee258e69ea8d7dbabe2..d17075ade2a132091a40d97ce64a0bfaf0aa03dd 100644 (file)
@@ -62,7 +62,7 @@ static int compare_case_lists (const void *, const void *);
 static int do_internal_sort (int separate);
 static int do_external_sort (int separate);
 int parse_sort_variables (void);
-void read_sort_output (int (*write_case) (void));
+void read_sort_output (write_case_func *write_case, write_case_data wc_data);
 
 /* Performs the SORT CASES procedures. */
 int
@@ -154,7 +154,7 @@ sort_cases (int separate)
 
   /* Not sure this is necessary but it's good to be safe. */
   if (separate && vfm_source == &sort_stream)
-    procedure (NULL, NULL, NULL);
+    procedure (NULL, NULL, NULL, NULL);
   
   /* SORT CASES cancels PROCESS IF. */
   expr_free (process_if_expr);
@@ -175,7 +175,7 @@ do_internal_sort (int separate)
   if (vfm_source != &vfm_disk_stream)
     {
       if (vfm_source != &vfm_memory_stream)
-       procedure (NULL, NULL, NULL);
+       procedure (NULL, NULL, NULL, NULL);
       if (vfm_source == &vfm_memory_stream)
        {
          struct case_list **case_tab = malloc (sizeof *case_tab
@@ -745,7 +745,7 @@ write_initial_runs (int separate)
        vfm_sink->destroy_sink ();
       vfm_sink = &sort_stream;
     }
-  procedure (NULL, NULL, NULL);
+  procedure (NULL, NULL, NULL, NULL);
 
   /* Final iterations of steps R4, R5, R6, R7, R2, R3, ... */
   for (;;)
@@ -1221,16 +1221,16 @@ lossage:
 /* Reads all the records from the source stream and passes them
    to write_case(). */
 static void
-sort_stream_read (void)
+sort_stream_read (write_case_func *write_case, write_case_data wc_data)
 {
-  read_sort_output (write_case);
+  read_sort_output (write_case, wc_data);
 }
 
 /* Reads all the records from the output stream and passes them to the
    function provided, which must have an interface identical to
    write_case(). */
 void
-read_sort_output (int (*write_case) (void))
+read_sort_output (write_case_func *write_case, write_case_data wc_data)
 {
   int i;
   FILE *f;
@@ -1243,7 +1243,7 @@ read_sort_output (int (*write_case) (void))
       for (p = separate_case_tab; *p; p++)
        {
          temp_case = &(*p)->c;
-         write_case ();
+         write_case (wc_data);
        }
       
       free (separate_case_tab);
@@ -1275,7 +1275,7 @@ read_sort_output (int (*write_case) (void))
              break;
            }
 
-         if (!write_case ())
+         if (!write_case (wc_data))
            break;
        }
 
index e6c9fed9df4c2046d4a9a51c25fd38b66e72e0b1..15a5b2db25d71f6f3a7d554e63426021ca52504d 100644 (file)
 #if !sort_h
 #define sort_h 1
 
+#include "vfm.h"
+
 /* SORT CASES programmatic interface. */
 int sort_cases (int separate);
-void read_sort_output (int (*write_case)(void));
+void read_sort_output (write_case_func *, write_case_data);
 
 /* Variables to sort. */
 extern struct variable **v_sort;
index e673395b6ac39f979fd43d27c3a0cc6dad7b52e2..69d658aea001f1d211ef17c66908be9de4718e16 100644 (file)
@@ -164,21 +164,21 @@ enum {
 };
 
 
-static int common_calc (struct ccase *);
-static void common_precalc (void);
-static void common_postcalc (void);
+static int common_calc (struct ccase *, void *);
+static void common_precalc (void *);
+static void common_postcalc (void *);
 
-static int one_sample_calc (struct ccase *);
-static void one_sample_precalc (void);
-static void one_sample_postcalc (void);
+static int one_sample_calc (struct ccase *, void *);
+static void one_sample_precalc (void *);
+static void one_sample_postcalc (void *);
 
-static int  paired_calc (struct ccase *);
-static void paired_precalc (void);
-static void paired_postcalc (void);
+static int  paired_calc (struct ccase *, void *);
+static void paired_precalc (void *);
+static void paired_postcalc (void *);
 
-static void group_precalc (void);
-static int  group_calc (struct ccase *);
-static void group_postcalc (void);
+static void group_precalc (void *);
+static int  group_calc (struct ccase *, void *);
+static void group_postcalc (void *);
 
 
 static int compare_var_name (const void *a_, const void *b_, void *v_ UNUSED);
@@ -269,18 +269,18 @@ cmd_t_test(void)
     }
 
 
-  procedure(common_precalc,common_calc,common_postcalc);
+  procedure(common_precalc,common_calc,common_postcalc, NULL);
 
   switch(mode)
     {
     case T_1_SAMPLE:
-      procedure(one_sample_precalc,one_sample_calc,one_sample_postcalc);
+      procedure(one_sample_precalc,one_sample_calc,one_sample_postcalc, NULL);
       break;
     case T_PAIRED:
-      procedure(paired_precalc,paired_calc,paired_postcalc);
+      procedure(paired_precalc,paired_calc,paired_postcalc, NULL);
       break;
     case T_IND_SAMPLES:
-      procedure(group_precalc,group_calc,group_postcalc);
+      procedure(group_precalc,group_calc,group_postcalc, NULL);
       break;
 
     }
@@ -1347,7 +1347,7 @@ pscbox(void)
 
 /* Per case calculations common to all variants of the T test */
 static int 
-common_calc (struct ccase *c)
+common_calc (struct ccase *c, void *aux UNUSED)
 {
   int i;
 
@@ -1373,7 +1373,7 @@ common_calc (struct ccase *c)
 
 /* Pre calculations common to all variants of the T test */
 static void 
-common_precalc (void)
+common_precalc (void *aux UNUSED)
 {
   int i=0;
 
@@ -1391,7 +1391,7 @@ common_precalc (void)
 
 /* Post calculations common to all variants of the T test */
 void 
-common_postcalc (void)
+common_postcalc (void *aux UNUSED)
 {
   int i=0;
 
@@ -1417,7 +1417,7 @@ common_postcalc (void)
 
 /* Per case calculations for one sample t test  */
 static int 
-one_sample_calc (struct ccase *c)
+one_sample_calc (struct ccase *c, void *aux UNUSED)
 {
   int i;
 
@@ -1440,7 +1440,7 @@ one_sample_calc (struct ccase *c)
 
 /* Pre calculations for one sample t test */
 static void 
-one_sample_precalc (void)
+one_sample_precalc (void *aux UNUSED)
 {
   int i=0;
   
@@ -1455,7 +1455,7 @@ one_sample_precalc (void)
 
 /* Post calculations for one sample t test */
 static void 
-one_sample_postcalc (void)
+one_sample_postcalc (void *aux UNUSED)
 {
   int i=0;
   
@@ -1490,7 +1490,7 @@ hash_var_name (const void *a_, void *v_ UNUSED)
 
 
 static void 
-paired_precalc (void)
+paired_precalc (void *aux UNUSED)
 {
   int i;
 
@@ -1504,7 +1504,7 @@ paired_precalc (void)
 }
 
 static int  
-paired_calc (struct ccase *c)
+paired_calc (struct ccase *c, void *aux UNUSED)
 {
   int i;
 
@@ -1530,7 +1530,7 @@ paired_calc (struct ccase *c)
 }
 
 static void 
-paired_postcalc (void)
+paired_postcalc (void *aux UNUSED)
 {
   int i;
 
@@ -1582,7 +1582,7 @@ get_group(const union value *val, struct variable *var)
 
 
 static void 
-group_precalc (void)
+group_precalc (void *aux UNUSED)
 {
   int i;
   int j;
@@ -1602,7 +1602,7 @@ group_precalc (void)
 }
 
 static int  
-group_calc (struct ccase *c)
+group_calc (struct ccase *c, void *aux UNUSED)
 {
   int i;
   union value *gv = &c->data[groups->fv];
@@ -1626,7 +1626,7 @@ group_calc (struct ccase *c)
 }
 
 static void 
-group_postcalc (void)
+group_postcalc (void *aux UNUSED)
 {
   int i;
   int j;
index 84efc3e0004ea4062735ba13dd24f123abed3e0e..173bbb0f4a00cb33f8c0f9b44084d251bce809ba 100644 (file)
--- a/src/vfm.c
+++ b/src/vfm.c
 
 #include "debug-print.h"
 
+/* Procedure execution data. */
+struct write_case_data
+  {
+    void (*beginfunc) (void *);
+    int (*procfunc) (struct ccase *, void *);
+    void (*endfunc) (void *);
+    void *aux;
+  };
+
 /* This is used to read from the active file. */
 struct case_stream *vfm_source;
 
@@ -98,14 +107,6 @@ static int paging = 0;
 /* Time at which vfm was last invoked. */
 time_t last_vfm_invocation;
 
-/* Functions called during procedure processing. */
-static int (*proc_func) (struct ccase *);      /* Called for each case. */
-static int (*virt_proc_func) (struct ccase *); /* From SPLIT_FILE_procfunc. */
-static void (*begin_func) (void);      /* Called at beginning of a series. */
-static void (*virt_begin_func) (void); /* Called by SPLIT_FILE_procfunc. */
-static void (*end_func) (void);        /* Called after end of a series. */
-int (*write_case) (void);
-
 /* Number of cases passed to proc_func(). */
 static int case_count;
 
@@ -116,53 +117,66 @@ static int lag_head;              /* Index where next case will be added. */
 static struct ccase **lag_queue; /* Array of n_lag ccase * elements. */
 
 static void open_active_file (void);
-static void close_active_file (void);
-static int SPLIT_FILE_procfunc (struct ccase *);
+static void close_active_file (struct write_case_data *);
+static int SPLIT_FILE_procfunc (struct ccase *, void *);
 static void finish_compaction (void);
 static void lag_case (void);
-static int procedure_write_case (void);
+static int procedure_write_case (struct write_case_data *);
 \f
 /* Public functions. */
 
-/* Reads all the cases from the active file, transforms them by the
-   active set of transformations, calls PROCFUNC with CURCASE set to
-   the case and CASENUM set to the case number, and writes them to a
-   new active file.
+/* Reads all the cases from the active file, transforms them by
+   the active set of transformations, calls PROCFUNC with CURCASE
+   set to the case , and writes them to a new active file.
 
    Divides the active file into zero or more series of one or more
    cases each.  BEGINFUNC is called before each series.  ENDFUNC is
-   called after each series. */
+   called after each series.
+
+   Arbitrary user-specified data AUX is passed to BEGINFUNC,
+   PROCFUNC, and ENDFUNC as auxiliary data. */
 void
-procedure (void (*beginfunc) (void),
-          int (*procfunc) (struct ccase *curcase),
-          void (*endfunc) (void))
+procedure (void (*beginfunc) (void *),
+          int (*procfunc) (struct ccase *curcase, void *),
+          void (*endfunc) (void *),
+           void *aux)
 {
-  end_func = endfunc;
-  write_case = procedure_write_case;
+  struct write_case_data procedure_write_data;
+  struct write_case_data split_file_data;
 
-  if (dict_get_split_cnt (default_dict) != 0 && procfunc != NULL)
+  if (dict_get_split_cnt (default_dict) == 0) 
     {
-      virt_proc_func = procfunc;
-      proc_func = SPLIT_FILE_procfunc;
-      
-      virt_begin_func = beginfunc;
-      begin_func = NULL;
-    } else {
-      begin_func = beginfunc;
-      proc_func = procfunc;
+      /* Normally we just use the data passed by the user. */
+      procedure_write_data.beginfunc = beginfunc;
+      procedure_write_data.procfunc = procfunc;
+      procedure_write_data.endfunc = endfunc;
+      procedure_write_data.aux = aux;
+    }
+  else
+    {
+      /* Under SPLIT FILE, we add a layer of indirection. */
+      procedure_write_data.beginfunc = NULL;
+      procedure_write_data.procfunc = SPLIT_FILE_procfunc;
+      procedure_write_data.endfunc = endfunc;
+      procedure_write_data.aux = &split_file_data;
+
+      split_file_data.beginfunc = beginfunc;
+      split_file_data.procfunc = procfunc;
+      split_file_data.endfunc = endfunc;
+      split_file_data.aux = aux;
     }
 
   last_vfm_invocation = time (NULL);
 
   open_active_file ();
-  vfm_source->read ();
-  close_active_file ();
+  vfm_source->read (procedure_write_case, &procedure_write_data);
+  close_active_file (&procedure_write_data);
 }
 \f
 /* Active file processing support.  Subtly different semantics from
    procedure(). */
 
-static int process_active_file_write_case (void);
+static int process_active_file_write_case (struct write_case_data *data);
 
 /* The casefunc might want us to stop calling it. */
 static int not_canceled;
@@ -175,28 +189,35 @@ static int not_canceled;
 
    process_active_file() ignores TEMPORARY, SPLIT FILE, and N. */
 void
-process_active_file (void (*beginfunc) (void),
-                    int (*casefunc) (struct ccase *curcase),
-                    void (*endfunc) (void))
+process_active_file (void (*beginfunc) (void *),
+                    int (*casefunc) (struct ccase *curcase, void *),
+                    void (*endfunc) (void *),
+                     void *aux)
 {
-  proc_func = casefunc;
-  write_case = process_active_file_write_case;
+  struct write_case_data process_active_write_data;
+
+  process_active_write_data.beginfunc = beginfunc;
+  process_active_write_data.procfunc = casefunc;
+  process_active_write_data.endfunc = endfunc;
+  process_active_write_data.aux = aux;
+
   not_canceled = 1;
 
   open_active_file ();
-  beginfunc ();
+  beginfunc (aux);
   
   /* There doesn't necessarily need to be an active file. */
   if (vfm_source)
-    vfm_source->read ();
+    vfm_source->read (process_active_file_write_case,
+                      &process_active_write_data);
   
-  endfunc ();
-  close_active_file ();
+  endfunc (aux);
+  close_active_file (&process_active_write_data);
 }
 
 /* Pass the current case to casefunc. */
 static int
-process_active_file_write_case (void)
+process_active_file_write_case (struct write_case_data *data)
 {
   /* Index of current transformation. */
   int cur_trns;
@@ -230,7 +251,7 @@ process_active_file_write_case (void)
       && !FILTERED
       && (process_if_expr == NULL ||
          expr_evaluate (process_if_expr, temp_case, NULL) == 1.0))
-    not_canceled = proc_func (temp_case);
+    not_canceled = data->procfunc (temp_case, data->aux);
   
   case_count++;
   
@@ -515,11 +536,11 @@ open_active_file (void)
 \f
 /* Closes the active file. */
 static void
-close_active_file (void)
+close_active_file (struct write_case_data *data)
 {
   /* Close the current case group. */
-  if (case_count && end_func != NULL)
-    end_func ();
+  if (case_count && data->endfunc != NULL)
+    data->endfunc (data->aux);
 
   /* Stop lagging (catch up?). */
   if (n_lag)
@@ -619,7 +640,7 @@ disk_stream_init (void)
 /* Reads all cases from the disk source and passes them one by one to
    write_case(). */
 static void
-disk_stream_read (void)
+disk_stream_read (write_case_func *write_case, write_case_data wc_data)
 {
   int i;
 
@@ -634,7 +655,7 @@ disk_stream_read (void)
          return;
        }
 
-      if (!write_case ())
+      if (!write_case (wc_data))
        return;
     }
 }
@@ -738,7 +759,7 @@ memory_stream_init (void)
 
 /* Reads the case stream from memory and passes it to write_case(). */
 static void
-memory_stream_read (void)
+memory_stream_read (write_case_func *write_case, write_case_data wc_data)
 {
   while (memory_source_cases != NULL)
     {
@@ -750,7 +771,7 @@ memory_stream_read (void)
        free (current);
       }
       
-      if (!write_case ())
+      if (!write_case (wc_data))
        return;
     }
 }
@@ -954,7 +975,7 @@ lagged_case (int n_before)
    otherwise.  Do not call this function again after it has returned
    zero once.  */
 int
-procedure_write_case (void)
+procedure_write_case (write_case_data wc_data)
 {
   /* Index of current transformation. */
   int cur_trns;
@@ -1012,16 +1033,16 @@ procedure_write_case (void)
     }
 
   /* Call the beginning of group function. */
-  if (!case_count && begin_func != NULL)
-    begin_func ();
+  if (!case_count && wc_data->beginfunc != NULL)
+    wc_data->beginfunc (wc_data->aux);
 
   /* Call the procedure if there is one and FILTER and PROCESS IF
      don't prohibit it. */
-  if (proc_func != NULL
+  if (wc_data->procfunc != NULL
       && !FILTERED
       && (process_if_expr == NULL ||
          expr_evaluate (process_if_expr, temp_case, NULL) == 1.0))
-    proc_func (temp_case);
+    wc_data->procfunc (temp_case, wc_data->aux);
 
   case_count++;
   
@@ -1125,8 +1146,9 @@ dump_splits (struct ccase *c)
    SPLIT FILE is active.  This function forms a wrapper around that
    procfunc by dividing the input into series. */
 static int
-SPLIT_FILE_procfunc (struct ccase *c)
+SPLIT_FILE_procfunc (struct ccase *c, void *data_)
 {
+  struct write_case_data *data = data_;
   static struct ccase *prev_case;
   struct variable *const *split;
   size_t split_cnt;
@@ -1142,10 +1164,10 @@ SPLIT_FILE_procfunc (struct ccase *c)
       memcpy (prev_case, c, vfm_sink_info.case_size);
 
       dump_splits (c);
-      if (virt_begin_func != NULL)
-       virt_begin_func ();
+      if (data->beginfunc != NULL)
+       data->beginfunc (data->aux);
       
-      return virt_proc_func (c);
+      return data->procfunc (c, data->aux);
     }
 
   /* Compare the value of each SPLIT FILE variable to the values on
@@ -1170,19 +1192,19 @@ SPLIT_FILE_procfunc (struct ccase *c)
          assert (0);
        }
     }
-  return virt_proc_func (c);
+  return data->procfunc (c, data->aux);
   
 not_equal:
   /* The values of the SPLIT FILE variable are different from the
      values on the previous case.  That means that it's time to begin
      a new series. */
-  if (end_func != NULL)
-    end_func ();
+  if (data->endfunc != NULL)
+    data->endfunc (data->aux);
   dump_splits (c);
-  if (virt_begin_func != NULL)
-    virt_begin_func ();
+  if (data->beginfunc != NULL)
+    data->beginfunc (data->aux);
   memcpy (prev_case, c, vfm_sink_info.case_size);
-  return virt_proc_func (c);
+  return data->procfunc (c, data->aux);
 }
 \f
 /* Case compaction. */
index b2a1e6efd2fb149267e7b87bc5937314ba13e9d9..27cac23549f555418dfe1a0a00a1c626e88ec357 100644 (file)
--- a/src/vfm.h
+++ b/src/vfm.h
@@ -35,14 +35,18 @@ extern struct long_vec reinit_blanks;       /* Blanks for every case. */
 extern struct long_vec init_zero;      /* Zero for first case only. */
 extern struct long_vec init_blanks;    /* Blanks for first case only. */
 
+typedef struct write_case_data *write_case_data;
+typedef int write_case_func (write_case_data);
+
 /* A case stream: either a source or a sink, depending on context. */
 struct case_stream
   {
     /* Initializes sink. */
     void (*init) (void);
     
-    /* Reads all the cases and passes them to WRITE_CASE. */
-    void (*read) (void);
+    /* Reads all the cases and calls WRITE_CASE passing the given
+       AUX data for each one. */
+    void (*read) (write_case_func *, write_case_data);
 
     /* Writes a single case, temp_case. */
     void (*write) (void);
@@ -83,18 +87,18 @@ extern struct case_stream matrix_data_source;
 /* Number of cases to lag. */
 extern int n_lag;
 
-extern int (*write_case) (void);
-
-void procedure (void (*beginfunc) (void),
-               int (*procfunc) (struct ccase *curcase),
-               void (*endfunc) (void));
+void procedure (void (*beginfunc) (void *aux),
+               int (*procfunc) (struct ccase *curcase, void *aux),
+               void (*endfunc) (void *aux),
+                void *aux);
 struct ccase *lagged_case (int n_before);
 void compact_case (struct ccase *dest, const struct ccase *src);
 void page_to_disk (void);
 
-void process_active_file (void (*beginfunc) (void),
-                         int (*casefunc) (struct ccase *curcase),
-                         void (*endfunc) (void));
+void process_active_file (void (*beginfunc) (void *),
+                         int (*casefunc) (struct ccase *curcase, void *),
+                         void (*endfunc) (void *),
+                          void *aux);
 void process_active_file_output_case (void);
 
 #endif /* !vfm_h */