Beginning of VFM cleanup.
[pspp-builds.git] / src / aggregate.c
index 67f4985a71001f0b6a7bdba064ddb1fece8c1e1b..0c274c4b3b644e16381d5005411af69593c499b0 100644 (file)
@@ -26,6 +26,7 @@
 #include "file-handle.h"
 #include "lexer.h"
 #include "misc.h"
+#include "pool.h"
 #include "settings.h"
 #include "sfm.h"
 #include "sort.h"
@@ -76,7 +77,7 @@ struct agr_func
   };
 
 /* Attributes of aggregation functions. */
-static struct agr_func agr_func_tab[] = 
+static const struct agr_func agr_func_tab[] = 
   {
     {"<NONE>",  0, -1,      {0, 0, 0}},
     {"SUM",     0, -1,      {FMT_F, 8, 2}},
@@ -116,6 +117,9 @@ enum
 /* ITEMWISE or COLUMNWISE. */
 static int missing;
 
+/* Sort program. */
+static struct sort_cases_pgm *sort;
+
 /* Aggregate variables. */
 static struct agr_var *agr_first, *agr_next;
 
@@ -141,11 +145,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);
@@ -157,15 +161,12 @@ static void debug_print (int flags);
 int
 cmd_aggregate (void)
 {
-  /* From sort.c. */
-  int parse_sort_variables (void);
-  
   /* Have we seen these subcommands? */
   unsigned seen = 0;
 
   outfile = NULL;
   missing = ITEMWISE;
-  v_sort = NULL;
+  sort = NULL;
   prev_case = NULL;
   
   agr_dict = dict_create ();
@@ -183,9 +184,9 @@ cmd_aggregate (void)
        {
          if (seen & 1)
            {
-             free (v_sort);
+             destroy_sort_cases_pgm (sort);
              dict_destroy (agr_dict);
-             msg (SE, _("OUTFILE specified multiple times."));
+             msg (SE, _("%s subcommand given multiple times."),"OUTFILE");
              return CMD_FAILURE;
            }
          seen |= 1;
@@ -198,7 +199,7 @@ cmd_aggregate (void)
              outfile = fh_parse_file_handle ();
              if (outfile == NULL)
                {
-                 free (v_sort);
+                 destroy_sort_cases_pgm (sort);
                  dict_destroy (agr_dict);
                  return CMD_FAILURE;
                }
@@ -209,7 +210,7 @@ cmd_aggregate (void)
          lex_match ('=');
          if (!lex_match_id ("COLUMNWISE"))
            {
-             free (v_sort);
+             destroy_sort_cases_pgm (sort);
              dict_destroy (agr_dict);
              lex_error (_("while expecting COLUMNWISE"));
              return CMD_FAILURE;
@@ -224,15 +225,16 @@ cmd_aggregate (void)
        {
          if (seen & 8)
            {
-             free (v_sort);
+             destroy_sort_cases_pgm (sort);
              dict_destroy (agr_dict);
-             msg (SE, _("BREAK specified multiple times."));
+             msg (SE, _("%s subcommand given multiple times."),"BREAK");
              return CMD_FAILURE;
            }
          seen |= 8;
 
          lex_match ('=');
-         if (!parse_sort_variables ())
+          sort = parse_sort ();
+          if (sort == NULL)
            {
              dict_destroy (agr_dict);
              return CMD_FAILURE;
@@ -241,11 +243,11 @@ cmd_aggregate (void)
          {
            int i;
            
-           for (i = 0; i < nv_sort; i++)
+           for (i = 0; i < sort->var_cnt; i++)
              {
                struct variable *v;
              
-               v = dict_clone_var (agr_dict, v_sort[i], v_sort[i]->name);
+               v = dict_clone_var (agr_dict, sort->vars[i], sort->vars[i]->name);
                assert (v != NULL);
              }
          }
@@ -261,7 +263,7 @@ cmd_aggregate (void)
   if (!parse_aggregate_functions ())
     {
       free_aggregate_functions ();
-      free (v_sort);
+      destroy_sort_cases_pgm (sort);
       return CMD_FAILURE;
     }
 
@@ -312,7 +314,7 @@ cmd_aggregate (void)
 
     if (outfile != NULL)
       type |= 4;
-    if (nv_sort != 0 && (seen & 4) == 0)
+    if (sort != NULL && (seen & 4) == 0)
       type |= 2;
     if (temporary)
       type |= 1;
@@ -323,7 +325,7 @@ cmd_aggregate (void)
        cancel_temporary ();
        /* fall through */
       case 2:
-       sort_cases (0);
+       sort_cases (sort, 0);
        goto case0;
          
       case 1:
@@ -343,7 +345,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 +361,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;
@@ -367,16 +369,16 @@ cmd_aggregate (void)
          
       case 6:
       case 7:
-       sort_cases (1);
+       sort_cases (sort, 1);
        
        if (!create_sysfile ())
          goto lossage;
-       read_sort_output (agr_11x_func);
+       read_sort_output (sort, 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;
        }
        
@@ -391,7 +393,7 @@ cmd_aggregate (void)
   free (buf_1xx);
   
   /* Clean up. */
-  free (v_sort);
+  destroy_sort_cases_pgm (sort);
   free_aggregate_functions ();
   free (prev_case);
   
@@ -399,7 +401,7 @@ cmd_aggregate (void)
 
 lossage:
   /* Clean up. */
-  free (v_sort);
+  destroy_sort_cases_pgm (sort);
   free_aggregate_functions ();
   free (prev_case);
 
@@ -418,15 +420,13 @@ create_sysfile (void)
   if (!sfm_write_dictionary (&w))
     {
       free_aggregate_functions ();
-      free (v_sort);
+      destroy_sort_cases_pgm (sort);
       dict_destroy (agr_dict);
       return 0;
     }
     
   buf64_1xx = xmalloc (sizeof *buf64_1xx * w.case_size);
-  buf_1xx = xmalloc (sizeof (struct ccase)
-                     + (sizeof (union value)
-                        * (dict_get_value_cnt (agr_dict) - 1)));
+  buf_1xx = xmalloc (dict_get_case_size (agr_dict));
 
   return 1;
 }
@@ -445,7 +445,7 @@ parse_aggregate_functions (void)
       int n_dest;
 
       int include_missing;
-      struct agr_func *function;
+      const struct agr_func *function;
       int func_index;
 
       union value arg[2];
@@ -664,6 +664,7 @@ parse_aggregate_functions (void)
              }
 
            free (dest[i]);
+            destvar->init = 0;
            if (dest_label[i])
              {
                destvar->label = dest_label[i];
@@ -782,8 +783,8 @@ aggregate_single_case (struct ccase *input, struct ccase *output)
       {
        int i;
 
-       for (i = 0; i < nv_sort; i++)
-         n_elem += v_sort[i]->nv;
+       for (i = 0; i < sort->var_cnt; i++)
+         n_elem += sort->vars[i]->nv;
       }
       
       prev_case = xmalloc (sizeof *prev_case * n_elem);
@@ -793,9 +794,9 @@ aggregate_single_case (struct ccase *input, struct ccase *output)
        union value *iter = prev_case;
        int i;
 
-       for (i = 0; i < nv_sort; i++)
+       for (i = 0; i < sort->var_cnt; i++)
          {
-           struct variable *v = v_sort[i];
+           struct variable *v = sort->vars[i];
            
            if (v->type == NUMERIC)
              (iter++)->f = input->data[v->fv].f;
@@ -818,9 +819,9 @@ aggregate_single_case (struct ccase *input, struct ccase *output)
     union value *iter = prev_case;
     int i;
     
-    for (i = 0; i < nv_sort; i++)
+    for (i = 0; i < sort->var_cnt; i++)
       {
-       struct variable *v = v_sort[i];
+       struct variable *v = sort->vars[i];
       
        switch (v->type)
          {
@@ -857,9 +858,9 @@ not_equal:
     union value *iter = prev_case;
     int i;
 
-    for (i = 0; i < nv_sort; i++)
+    for (i = 0; i < sort->var_cnt; i++)
       {
-       struct variable *v = v_sort[i];
+       struct variable *v = sort->vars[i];
            
        if (v->type == NUMERIC)
          (iter++)->f = input->data[v->fv].f;
@@ -1051,8 +1052,8 @@ dump_aggregate_info (struct ccase *output)
     {
       int i;
 
-      for (i = 0; i < nv_sort; i++)
-       n_elem += v_sort[i]->nv;
+      for (i = 0; i < sort->var_cnt; i++)
+       n_elem += sort->vars[i]->nv;
     }
     debug_printf (("n_elem=%d:", n_elem));
     memcpy (output->data, prev_case, sizeof (union value) * n_elem);
@@ -1195,7 +1196,7 @@ initialize_aggregate_info (void)
 /* Aggregate each case as it comes through.  Cases which aren't needed
    are dropped. */
 static int
-agr_00x_trns_proc (struct trns_header *h unused, struct ccase *c)
+agr_00x_trns_proc (struct trns_header *h UNUSED, struct ccase *c)
 {
   int code = aggregate_single_case (c, compaction_case);
   debug_printf (("%d ", code));
@@ -1207,13 +1208,13 @@ 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. */
   dump_aggregate_info (compaction_case);
   vfm_sink_info.ncases++;
-  vfm_sink->write ();
+  vfm_sink->class->write (vfm_sink, temp_case);
 }
 
 /* Transform the aggregate case buf_1xx, in internal format, to system
@@ -1252,7 +1253,7 @@ write_case_to_sfm (void)
 /* Aggregate the current case and output it if we passed a
    breakpoint. */
 static int
-agr_10x_trns_proc (struct trns_header *h unused, struct ccase *c)
+agr_10x_trns_proc (struct trns_header *h UNUSED, struct ccase *c)
 {
   int code = aggregate_single_case (c, buf_1xx);
 
@@ -1264,7 +1265,7 @@ agr_10x_trns_proc (struct trns_header *h unused, struct ccase *c)
 
 /* Close the system file now that we're done with it.  */
 static void
-agr_10x_trns_free (struct trns_header *h unused)
+agr_10x_trns_free (struct trns_header *h UNUSED)
 {
   fh_close_handle (outfile);
 }
@@ -1272,7 +1273,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 +1284,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)
     {
@@ -1326,9 +1327,9 @@ debug_print (int flags)
     int i;
 
     printf (" /BREAK=");
-    for (i = 0; i < nv_sort; i++)
-      printf ("%s(%c) ", v_sort[i]->name,
-             v_sort[i]->p.srt.order == SRT_ASCEND ? 'A' : 'D');
+    for (i = 0; i < sort->var_cnt; i++)
+      printf ("%s(%c) ", sort->vars[i]->name,
+             sort->vars[i]->p.srt.order == SRT_ASCEND ? 'A' : 'D');
     putc ('\n', stdout);
   }