Beginning of VFM cleanup.
[pspp-builds.git] / src / aggregate.c
index d49ebf9e520a51c86c13eee2fb73d95fb7b79c2f..0c274c4b3b644e16381d5005411af69593c499b0 100644 (file)
 #include <assert.h>
 #include <stdlib.h>
 #include "alloc.h"
-#include "approx.h"
 #include "command.h"
 #include "error.h"
 #include "file-handle.h"
 #include "lexer.h"
 #include "misc.h"
+#include "pool.h"
 #include "settings.h"
 #include "sfm.h"
 #include "sort.h"
@@ -36,8 +36,6 @@
 #include "vfm.h"
 #include "vfmP.h"
 
-#undef DEBUGGING
-/*#define DEBUGGING 1*/
 #include "debug-print.h"
 
 /* Specifies how to make an aggregate variable. */
@@ -67,8 +65,6 @@ enum
     N_AGR_FUNCS, N_NO_VARS, NU_NO_VARS,
     FUNC = 0x1f, /* Function mask. */
     FSTRING = 1<<5, /* String function bit. */
-    FWEIGHT = 1<<6, /* Weighted function bit. */
-    FOPTIONS = FSTRING | FWEIGHT /* Function options mask. */
   };
 
 /* Attributes of an aggregation function. */
@@ -81,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}},
@@ -121,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;
 
@@ -146,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);
@@ -162,18 +161,17 @@ 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 = new_dictionary (1);
+  agr_dict = dict_create ();
+  dict_set_label (agr_dict, dict_get_label (default_dict));
+  dict_set_documents (agr_dict, dict_get_documents (default_dict));
   
   lex_match_id ("AGGREGATE");
 
@@ -186,9 +184,9 @@ cmd_aggregate (void)
        {
          if (seen & 1)
            {
-             free (v_sort);
-             free_dictionary (agr_dict);
-             msg (SE, _("OUTFILE specified multiple times."));
+             destroy_sort_cases_pgm (sort);
+             dict_destroy (agr_dict);
+             msg (SE, _("%s subcommand given multiple times."),"OUTFILE");
              return CMD_FAILURE;
            }
          seen |= 1;
@@ -201,8 +199,8 @@ cmd_aggregate (void)
              outfile = fh_parse_file_handle ();
              if (outfile == NULL)
                {
-                 free (v_sort);
-                 free_dictionary (agr_dict);
+                 destroy_sort_cases_pgm (sort);
+                 dict_destroy (agr_dict);
                  return CMD_FAILURE;
                }
            }
@@ -212,8 +210,8 @@ cmd_aggregate (void)
          lex_match ('=');
          if (!lex_match_id ("COLUMNWISE"))
            {
-             free (v_sort);
-             free_dictionary (agr_dict);
+             destroy_sort_cases_pgm (sort);
+             dict_destroy (agr_dict);
              lex_error (_("while expecting COLUMNWISE"));
              return CMD_FAILURE;
            }
@@ -227,28 +225,29 @@ cmd_aggregate (void)
        {
          if (seen & 8)
            {
-             free (v_sort);
-             free_dictionary (agr_dict);
-             msg (SE, _("BREAK specified multiple times."));
+             destroy_sort_cases_pgm (sort);
+             dict_destroy (agr_dict);
+             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)
            {
-             free_dictionary (agr_dict);
+             dict_destroy (agr_dict);
              return CMD_FAILURE;
            }
          
          {
            int i;
            
-           for (i = 0; i < nv_sort; i++)
+           for (i = 0; i < sort->var_cnt; i++)
              {
                struct variable *v;
              
-               v = dup_variable (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);
              }
          }
@@ -264,22 +263,16 @@ cmd_aggregate (void)
   if (!parse_aggregate_functions ())
     {
       free_aggregate_functions ();
-      free (v_sort);
+      destroy_sort_cases_pgm (sort);
       return CMD_FAILURE;
     }
 
   /* Delete documents. */
   if (!(seen & 2))
-    {
-      free (agr_dict->documents);
-      agr_dict->documents = NULL;
-      agr_dict->n_documents = 0;
-    }
+    dict_set_documents (agr_dict, NULL);
 
   /* Cancel SPLIT FILE. */
-  default_dict.n_splits = 0;
-  free (default_dict.splits);
-  default_dict.splits = NULL;
+  dict_set_split_vars (agr_dict, NULL, 0);
   
 #if DEBUGGING
   debug_print (seen);
@@ -321,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;
@@ -332,7 +325,7 @@ cmd_aggregate (void)
        cancel_temporary ();
        /* fall through */
       case 2:
-       sort_cases (0);
+       sort_cases (sort, 0);
        goto case0;
          
       case 1:
@@ -352,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;
        }
 
@@ -368,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;
@@ -376,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;
        }
        
@@ -400,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);
   
@@ -408,7 +401,7 @@ cmd_aggregate (void)
 
 lossage:
   /* Clean up. */
-  free (v_sort);
+  destroy_sort_cases_pgm (sort);
   free_aggregate_functions ();
   free (prev_case);
 
@@ -427,13 +420,13 @@ create_sysfile (void)
   if (!sfm_write_dictionary (&w))
     {
       free_aggregate_functions ();
-      free (v_sort);
-      free_dictionary (agr_dict);
+      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) * (agr_dict->nval - 1));
+  buf_1xx = xmalloc (dict_get_case_size (agr_dict));
 
   return 1;
 }
@@ -444,9 +437,6 @@ parse_aggregate_functions (void)
 {
   agr_first = agr_next = NULL;
 
-  /* Anticipate weighting for optimization later. */
-  update_weighting (&default_dict);
-  
   /* Parse everything. */
   for (;;)
     {
@@ -455,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];
@@ -545,7 +535,7 @@ parse_aggregate_functions (void)
            else if (function->n_args)
              pv_opts |= PV_SAME_TYPE;
 
-           if (!parse_variables (&default_dict, &src, &n_src, pv_opts))
+           if (!parse_variables (default_dict, &src, &n_src, pv_opts))
              goto lossage;
          }
 
@@ -626,7 +616,7 @@ parse_aggregate_functions (void)
 
            if (src)
              {
-               int output_type;
+               int output_width;
 
                agr_next->src = src[i];
                
@@ -636,23 +626,19 @@ parse_aggregate_functions (void)
                    agr_next->string = xmalloc (src[i]->width);
                  }
                
-               if (default_dict.weight_index != -1)
-                 agr_next->function |= FWEIGHT;
-
-               if (agr_next->src->type == NUMERIC)
-                 output_type = NUMERIC;
+               if (agr_next->src->type == NUMERIC || function->alpha_type == NUMERIC)
+                 output_width = 0;
                else
-                 output_type = function->alpha_type;
+                 output_width = agr_next->src->width;
 
                if (function->alpha_type == ALPHA)
-                 destvar = dup_variable (agr_dict, agr_next->src, dest[i]);
+                 destvar = dict_clone_var (agr_dict, agr_next->src, dest[i]);
                else
                  {
-                   destvar = create_variable (agr_dict, dest[i], output_type,
-                                              agr_next->src->width);
-                   if (output_type == NUMERIC)
+                   destvar = dict_create_var (agr_dict, dest[i], output_width);
+                   if (output_width == 0)
                      destvar->print = destvar->write = function->format;
-                   if (output_type == NUMERIC && default_dict.weight_index != -1
+                   if (output_width == 0 && dict_get_weight (default_dict) != NULL
                        && (func_index == N || func_index == N_NO_VARS
                            || func_index == NU || func_index == NU_NO_VARS))
                      {
@@ -663,7 +649,7 @@ parse_aggregate_functions (void)
                  }
              } else {
                agr_next->src = NULL;
-               destvar = create_variable (agr_dict, dest[i], NUMERIC, 0);
+               destvar = dict_create_var (agr_dict, dest[i], 0);
              }
          
            if (!destvar)
@@ -678,6 +664,7 @@ parse_aggregate_functions (void)
              }
 
            free (dest[i]);
+            destvar->init = 0;
            if (dest_label[i])
              {
                destvar->label = dest_label[i];
@@ -754,7 +741,7 @@ free_aggregate_functions (void)
   struct agr_var *iter, *next;
 
   if (agr_dict)
-    free_dictionary (agr_dict);
+    dict_destroy (agr_dict);
   for (iter = agr_first; iter; iter = next)
     {
       next = iter->next;
@@ -796,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);
@@ -807,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;
@@ -832,14 +819,14 @@ 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)
          {
          case NUMERIC:
-           if (approx_ne (input->data[v->fv].f, iter->f))
+           if (input->data[v->fv].f != iter->f)
              goto not_equal;
            iter++;
            break;
@@ -871,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;
@@ -893,8 +880,9 @@ static void
 accumulate_aggregate_info (struct ccase *input)
 {
   struct agr_var *iter;
+  double weight;
 
-#define WEIGHT (input->data[default_dict.weight_index].f)
+  weight = dict_get_case_weight (default_dict, input);
 
   for (iter = agr_first; iter; iter = iter->next)
     if (iter->src)
@@ -907,12 +895,10 @@ accumulate_aggregate_info (struct ccase *input)
          {
            switch (iter->function)
              {
-             case NMISS | FWEIGHT:
-               iter->dbl[0] += WEIGHT;
-               break;
              case NMISS:
+               iter->dbl[0] += weight;
+                break;
              case NUMISS:
-             case NUMISS | FWEIGHT:
                iter->int1++;
                break;
              }
@@ -924,190 +910,95 @@ accumulate_aggregate_info (struct ccase *input)
        switch (iter->function)
          {
          case SUM:
-         case SUM | FWEIGHT:
            iter->dbl[0] += v->f;
            break;
          case MEAN:
-           iter->dbl[0] += v->f;
-           iter->int1++;
-           break;
-         case MEAN | FWEIGHT:
-           {
-             double w = WEIGHT;
-             iter->dbl[0] += v->f * w;
-             iter->dbl[1] += w;
-             break;
-           }
-         case SD:
-           iter->dbl[0] += v->f;
-           iter->dbl[1] += v->f * v->f;
-           iter->int1++;
-           break;
-         case SD | FWEIGHT:
-           {
-             double w = WEIGHT;
-             double product = v->f * w;
-             iter->dbl[0] += product;
-             iter->dbl[1] += product * v->f;
-             iter->dbl[2] += w;
-             break;
-           }
+            iter->dbl[0] += v->f * weight;
+            iter->dbl[1] += weight;
+            break;
+         case SD: 
+            {
+              double product = v->f * weight;
+              iter->dbl[0] += product;
+              iter->dbl[1] += product * v->f;
+              iter->dbl[2] += weight;
+              break; 
+            }
          case MAX:
-         case MAX | FWEIGHT:
            iter->dbl[0] = max (iter->dbl[0], v->f);
            iter->int1 = 1;
            break;
          case MAX | FSTRING:
-         case MAX | FSTRING | FWEIGHT:
            if (memcmp (iter->string, v->s, iter->src->width) < 0)
              memcpy (iter->string, v->s, iter->src->width);
            iter->int1 = 1;
            break;
          case MIN:
-         case MIN | FWEIGHT:
            iter->dbl[0] = min (iter->dbl[0], v->f);
            iter->int1 = 1;
            break;
          case MIN | FSTRING:
-         case MIN | FSTRING | FWEIGHT:
            if (memcmp (iter->string, v->s, iter->src->width) > 0)
              memcpy (iter->string, v->s, iter->src->width);
            iter->int1 = 1;
            break;
          case FGT:
          case PGT:
-           if (approx_gt (v->f, iter->arg[0].f))
-             iter->int1++;
-           iter->int2++;
-           break;
-         case FGT | FWEIGHT:
-         case PGT | FWEIGHT:
-           {
-             double w = WEIGHT;
-             if (approx_gt (v->f, iter->arg[0].f))
-               iter->dbl[0] += w;
-             iter->dbl[1] += w;
-             break;
-           }
+            if (v->f > iter->arg[0].f)
+              iter->dbl[0] += weight;
+            iter->dbl[1] += weight;
+            break;
          case FGT | FSTRING:
          case PGT | FSTRING:
-           if (memcmp (iter->arg[0].c, v->s, iter->src->width) < 0)
-             iter->int1++;
-           iter->int2++;
-           break;
-         case FGT | FSTRING | FWEIGHT:
-         case PGT | FSTRING | FWEIGHT:
-           {
-             double w = WEIGHT;
-             if (memcmp (iter->arg[0].c, v->s, iter->src->width) < 0)
-               iter->dbl[0] += w;
-             iter->dbl[1] += w;
-             break;
-           }
+            if (memcmp (iter->arg[0].c, v->s, iter->src->width) < 0)
+              iter->dbl[0] += weight;
+            iter->dbl[1] += weight;
+            break;
          case FLT:
          case PLT:
-           if (approx_lt (v->f, iter->arg[0].f))
-             iter->int1++;
-           iter->int2++;
-           break;
-         case FLT | FWEIGHT:
-         case PLT | FWEIGHT:
-           {
-             double w = WEIGHT;
-             if (approx_lt (v->f, iter->arg[0].f))
-               iter->dbl[0] += w;
-             iter->dbl[1] += w;
-             break;
-           }
+            if (v->f < iter->arg[0].f)
+              iter->dbl[0] += weight;
+            iter->dbl[1] += weight;
+            break;
          case FLT | FSTRING:
          case PLT | FSTRING:
-           if (memcmp (iter->arg[0].c, v->s, iter->src->width) > 0)
-             iter->int1++;
-           iter->int2++;
-           break;
-         case FLT | FSTRING | FWEIGHT:
-         case PLT | FSTRING | FWEIGHT:
-           {
-             double w = WEIGHT;
-             if (memcmp (iter->arg[0].c, v->s, iter->src->width) > 0)
-               iter->dbl[0] += w;
-             iter->dbl[1] += w;
-             break;
-           }
+            if (memcmp (iter->arg[0].c, v->s, iter->src->width) > 0)
+              iter->dbl[0] += weight;
+            iter->dbl[1] += weight;
+            break;
          case FIN:
          case PIN:
-           if (approx_in_range (v->f, iter->arg[0].f, iter->arg[1].f))
-             iter->int1++;
-           iter->int2++;
-           break;
-         case FIN | FWEIGHT:
-         case PIN | FWEIGHT:
-           {
-             double w = WEIGHT;
-             if (approx_in_range (v->f, iter->arg[0].f, iter->arg[1].f))
-               iter->dbl[0] += w;
-             iter->dbl[1] += w;
-             break;
-           }
+            if (iter->arg[0].f <= v->f && v->f <= iter->arg[1].f)
+              iter->dbl[0] += weight;
+            iter->dbl[1] += weight;
+            break;
          case FIN | FSTRING:
          case PIN | FSTRING:
-           if (memcmp (iter->arg[0].c, v->s, iter->src->width) <= 0
-               && memcmp (iter->arg[1].c, v->s, iter->src->width) >= 0)
-             iter->int1++;
-           iter->int2++;
-           break;
-         case FIN | FSTRING | FWEIGHT:
-         case PIN | FSTRING | FWEIGHT:
-           {
-             double w = WEIGHT;
-             if (memcmp (iter->arg[0].c, v->s, iter->src->width) <= 0
-                 && memcmp (iter->arg[1].c, v->s, iter->src->width) >= 0)
-               iter->dbl[0] += w;
-             iter->dbl[1] += w;
-             break;
-           }
+            if (memcmp (iter->arg[0].c, v->s, iter->src->width) <= 0
+                && memcmp (iter->arg[1].c, v->s, iter->src->width) >= 0)
+              iter->dbl[0] += weight;
+            iter->dbl[1] += weight;
+            break;
          case FOUT:
          case POUT:
-           if (!approx_in_range (v->f, iter->arg[0].f, iter->arg[1].f))
-             iter->int1++;
-           iter->int2++;
-           break;
-         case FOUT | FWEIGHT:
-         case POUT | FWEIGHT:
-           {
-             double w = WEIGHT;
-             if (!approx_in_range (v->f, iter->arg[0].f, iter->arg[1].f))
-               iter->dbl[0] += w;
-             iter->dbl[1] += w;
-             break;
-           }
+            if (iter->arg[0].f > v->f || v->f > iter->arg[1].f)
+              iter->dbl[0] += weight;
+            iter->dbl[1] += weight;
+            break;
          case FOUT | FSTRING:
          case POUT | FSTRING:
-           if (memcmp (iter->arg[0].c, v->s, iter->src->width) > 0
-               && memcmp (iter->arg[1].c, v->s, iter->src->width) < 0)
-             iter->int1++;
-           iter->int2++;
-           break;
-         case FOUT | FSTRING | FWEIGHT:
-         case POUT | FSTRING | FWEIGHT:
-           {
-             double w = WEIGHT;
-             if (memcmp (iter->arg[0].c, v->s, iter->src->width) > 0
-                 && memcmp (iter->arg[1].c, v->s, iter->src->width) < 0)
-               iter->dbl[0] += w;
-             iter->dbl[1] += w;
-             break;
-           }
-         case N | FWEIGHT:
-           iter->dbl[0] += WEIGHT;
-           break;
+            if (memcmp (iter->arg[0].c, v->s, iter->src->width) > 0
+                && memcmp (iter->arg[1].c, v->s, iter->src->width) < 0)
+              iter->dbl[0] += weight;
+            iter->dbl[1] += weight;
+            break;
          case N:
+           iter->dbl[0] += weight;
+           break;
          case NU:
-         case NU | FWEIGHT:
            iter->int1++;
            break;
          case FIRST:
-         case FIRST | FWEIGHT:
            if (iter->int1 == 0)
              {
                iter->dbl[0] = v->f;
@@ -1115,7 +1006,6 @@ accumulate_aggregate_info (struct ccase *input)
              }
            break;
          case FIRST | FSTRING:
-         case FIRST | FSTRING | FWEIGHT:
            if (iter->int1 == 0)
              {
                memcpy (iter->string, v->s, iter->src->width);
@@ -1123,12 +1013,10 @@ accumulate_aggregate_info (struct ccase *input)
              }
            break;
          case LAST:
-         case LAST | FWEIGHT:
            iter->dbl[0] = v->f;
            iter->int1 = 1;
            break;
          case LAST | FSTRING:
-         case LAST | FSTRING | FWEIGHT:
            memcpy (iter->string, v->s, iter->src->width);
            iter->int1 = 1;
            break;
@@ -1138,12 +1026,10 @@ accumulate_aggregate_info (struct ccase *input)
     } else {
       switch (iter->function)
        {
-       case N_NO_VARS | FWEIGHT:
-         iter->dbl[0] += WEIGHT;
-         break;
        case N_NO_VARS:
+         iter->dbl[0] += weight;
+         break;
        case NU_NO_VARS:
-       case NU_NO_VARS | FWEIGHT:
          iter->int1++;
          break;
        default:
@@ -1166,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);
@@ -1196,58 +1082,37 @@ dump_aggregate_info (struct ccase *output)
        switch (i->function)
          {
          case SUM:
-         case SUM | FWEIGHT:
            v->f = i->dbl[0];
            break;
          case MEAN:
-           v->f = i->int1 ? i->dbl[0] / i->int1 : SYSMIS;
-           break;
-         case MEAN | FWEIGHT:
            v->f = i->dbl[1] != 0.0 ? i->dbl[0] / i->dbl[1] : SYSMIS;
            break;
          case SD:
-           v->f = ((i->int1 > 1)
-                   ? calc_stddev (calc_variance (i->dbl, i->int1))
-                   : SYSMIS);
-           break;
-         case SD | FWEIGHT:
            v->f = ((i->dbl[2] > 1.0)
                    ? calc_stddev (calc_variance (i->dbl, i->dbl[2]))
                    : SYSMIS);
            break;
          case MAX:
-         case MAX | FWEIGHT:
          case MIN:
-         case MIN | FWEIGHT:
            v->f = i->int1 ? i->dbl[0] : SYSMIS;
            break;
          case MAX | FSTRING:
-         case MAX | FSTRING | FWEIGHT:
          case MIN | FSTRING:
-         case MIN | FSTRING | FWEIGHT:
            if (i->int1)
              memcpy (v->s, i->string, i->dest->width);
            else
              memset (v->s, ' ', i->dest->width);
            break;
-         case FGT:
          case FGT | FSTRING:
-         case FLT:
          case FLT | FSTRING:
-         case FIN:
          case FIN | FSTRING:
-         case FOUT:
          case FOUT | FSTRING:
            v->f = i->int2 ? (double) i->int1 / (double) i->int2 : SYSMIS;
            break;
-         case FGT | FWEIGHT:
-         case FGT | FSTRING | FWEIGHT:
-         case FLT | FWEIGHT:
-         case FLT | FSTRING | FWEIGHT:
-         case FIN | FWEIGHT:
-         case FIN | FSTRING | FWEIGHT:
-         case FOUT | FWEIGHT:
-         case FOUT | FSTRING | FWEIGHT:
+         case FGT:
+         case FLT:
+         case FIN:
+         case FOUT:
            v->f = i->dbl[1] ? i->dbl[0] / i->dbl[1] : SYSMIS;
            break;
          case PGT:
@@ -1258,56 +1123,35 @@ dump_aggregate_info (struct ccase *output)
          case PIN | FSTRING:
          case POUT:
          case POUT | FSTRING:
-           v->f = (i->int2
-                   ? (double) i->int1 / (double) i->int2 * 100.0
-                   : SYSMIS);
-           break;
-         case PGT | FWEIGHT:
-         case PGT | FSTRING | FWEIGHT:
-         case PLT | FWEIGHT:
-         case PLT | FSTRING | FWEIGHT:
-         case PIN | FWEIGHT:
-         case PIN | FSTRING | FWEIGHT:
-         case POUT | FWEIGHT:
-         case POUT | FSTRING | FWEIGHT:
            v->f = i->dbl[1] ? i->dbl[0] / i->dbl[1] * 100.0 : SYSMIS;
            break;
-         case N | FWEIGHT:
-           v->f = i->dbl[0];
          case N:
+           v->f = i->dbl[0];
+            break;
          case NU:
-         case NU | FWEIGHT:
            v->f = i->int1;
            break;
          case FIRST:
-         case FIRST | FWEIGHT:
          case LAST:
-         case LAST | FWEIGHT:
            v->f = i->int1 ? i->dbl[0] : SYSMIS;
            break;
          case FIRST | FSTRING:
-         case FIRST | FSTRING | FWEIGHT:
          case LAST | FSTRING:
-         case LAST | FSTRING | FWEIGHT:
            if (i->int1)
              memcpy (v->s, i->string, i->dest->width);
            else
              memset (v->s, ' ', i->dest->width);
            break;
-         case N_NO_VARS | FWEIGHT:
+         case N_NO_VARS:
            v->f = i->dbl[0];
            break;
-         case N_NO_VARS:
          case NU_NO_VARS:
-         case NU_NO_VARS | FWEIGHT:
            v->f = i->int1;
            break;
-         case NMISS | FWEIGHT:
+         case NMISS:
            v->f = i->dbl[0];
            break;
-         case NMISS:
          case NUMISS:
-         case NUMISS | FWEIGHT:
            v->f = i->int1;
            break;
          default:
@@ -1326,10 +1170,8 @@ initialize_aggregate_info (void)
 
   for (iter = agr_first; iter; iter = iter->next)
     {
-      int plain_function = iter->function & ~FWEIGHT;
-
       iter->missing = 0;
-      switch (plain_function)
+      switch (iter->function)
        {
        case MIN:
          iter->dbl[0] = DBL_MAX;
@@ -1354,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));
@@ -1366,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
@@ -1384,9 +1226,9 @@ write_case_to_sfm (void)
   flt64 *p = buf64_1xx;
   int i;
 
-  for (i = 0; i < agr_dict->nvar; i++)
+  for (i = 0; i < dict_get_var_cnt (agr_dict); i++)
     {
-      struct variable *v = agr_dict->var[i];
+      struct variable *v = dict_get_var (agr_dict, i);
       
       if (v->type == NUMERIC)
        {
@@ -1411,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);
 
@@ -1423,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);
 }
@@ -1431,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 ();
@@ -1442,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)
     {
@@ -1485,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);
   }