Encapsulated the static data of procedure.[ch] into a single object, to be
[pspp-builds.git] / src / language / stats / aggregate.c
index a0887e3b2c0877123fbcfa7c3072dbb8d9dee99f..a388b2d948a45d955b3e7b2b4cddae3b6db7e63f 100644 (file)
@@ -27,6 +27,7 @@
 #include <data/casefile.h>
 #include <data/dictionary.h>
 #include <data/file-handle-def.h>
+#include <data/procedure.h>
 #include <data/settings.h>
 #include <data/storage-stream.h>
 #include <data/sys-file-writer.h>
 #include <language/command.h>
 #include <language/data-io/file-handle.h>
 #include <language/lexer/lexer.h>
+#include <language/lexer/variable-parser.h>
 #include <language/stats/sort-criteria.h>
 #include <libpspp/alloc.h>
-#include <libpspp/message.h>
+#include <libpspp/assertion.h>
 #include <libpspp/message.h>
 #include <libpspp/misc.h>
 #include <libpspp/pool.h>
 #include <libpspp/str.h>
 #include <math/moments.h>
 #include <math/sort.h>
-#include <procedure.h>
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
 
+/* Argument for AGGREGATE function. */
+union agr_argument
+  {
+    double f;                           /* Numeric. */
+    char *c;                            /* Short or long string. */
+  };
+
 /* Specifies how to make an aggregate variable. */
 struct agr_var
   {
@@ -58,7 +66,7 @@ struct agr_var
     struct variable *dest;     /* Target variable. */
     int function;              /* Function. */
     int include_missing;       /* 1=Include user-missing values. */
-    union value arg[2];                /* Arguments. */
+    union agr_argument arg[2]; /* Arguments. */
 
     /* Accumulated during AGGREGATE execution. */
     double dbl[3];
@@ -146,18 +154,18 @@ static void initialize_aggregate_info (struct agr_proc *,
                                        const struct ccase *);
 
 /* Prototypes. */
-static int parse_aggregate_functions (struct agr_proc *);
+static bool parse_aggregate_functions (struct agr_proc *);
 static void agr_destroy (struct agr_proc *);
-static int aggregate_single_case (struct agr_proc *agr,
+static bool aggregate_single_case (struct agr_proc *agr,
                                   const struct ccase *input,
                                   struct ccase *output);
 static void dump_aggregate_info (struct agr_proc *agr, struct ccase *output);
 
 /* Aggregating to the active file. */
-static bool agr_to_active_file (struct ccase *, void *aux);
+static bool agr_to_active_file (const struct ccase *, void *aux);
 
 /* Aggregating to a system file. */
-static bool presorted_agr_to_sysfile (struct ccase *, void *aux);
+static bool presorted_agr_to_sysfile (const struct ccase *, void *aux);
 \f
 /* Parsing. */
 
@@ -177,8 +185,8 @@ cmd_aggregate (void)
   case_nullify (&agr.break_case);
   
   agr.dict = dict_create ();
-  dict_set_label (agr.dict, dict_get_label (default_dict));
-  dict_set_documents (agr.dict, dict_get_documents (default_dict));
+  dict_set_label (agr.dict, dict_get_label (dataset_dict (current_dataset)));
+  dict_set_documents (agr.dict, dict_get_documents (dataset_dict (current_dataset)));
 
   /* OUTFILE subcommand must be first. */
   if (!lex_force_match_id ("OUTFILE"))
@@ -215,7 +223,7 @@ cmd_aggregate (void)
           int i;
 
          lex_match ('=');
-          agr.sort = sort_parse_criteria (default_dict,
+          agr.sort = sort_parse_criteria (dataset_dict (current_dataset),
                                           &agr.break_vars, &agr.break_var_cnt,
                                           &saw_direction, NULL);
           if (agr.sort == NULL)
@@ -260,7 +268,7 @@ cmd_aggregate (void)
     {
       /* The active file will be replaced by the aggregated data,
          so TEMPORARY is moot. */
-      cancel_temporary ();
+      proc_cancel_temporary_transformations (current_dataset);
 
       if (agr.sort != NULL && !presorted) 
         {
@@ -271,8 +279,10 @@ cmd_aggregate (void)
       agr.sink = create_case_sink (&storage_sink_class, agr.dict, NULL);
       if (agr.sink->class->open != NULL)
         agr.sink->class->open (agr.sink);
-      vfm_sink = create_case_sink (&null_sink_class, default_dict, NULL);
-      if (!procedure (agr_to_active_file, &agr))
+      proc_set_sink (current_dataset, 
+                    create_case_sink (&null_sink_class, 
+                                      dataset_dict (current_dataset), NULL));
+      if (!procedure (current_dataset,agr_to_active_file, &agr))
         goto error;
       if (agr.case_cnt > 0) 
         {
@@ -280,10 +290,12 @@ cmd_aggregate (void)
           if (!agr.sink->class->write (agr.sink, &agr.agr_case))
             goto error;
         }
-      dict_destroy (default_dict);
-      default_dict = agr.dict;
+      discard_variables (current_dataset);
+      dict_destroy (dataset_dict (current_dataset));
+      dataset_set_dict (current_dataset, agr.dict);
       agr.dict = NULL;
-      vfm_source = agr.sink->class->make_source (agr.sink);
+      proc_set_source (current_dataset, 
+                      agr.sink->class->make_source (agr.sink));
       free_case_sink (agr.sink);
     }
   else
@@ -320,7 +332,7 @@ cmd_aggregate (void)
       else 
         {
           /* Active file is already sorted. */
-          if (!procedure (presorted_agr_to_sysfile, &agr))
+          if (!procedure (current_dataset,presorted_agr_to_sysfile, &agr))
             goto error;
         }
       
@@ -342,7 +354,7 @@ error:
 }
 
 /* Parse all the aggregate functions. */
-static int
+static bool
 parse_aggregate_functions (struct agr_proc *agr)
 {
   struct agr_var *tail; /* Tail of linked list starting at agr->vars. */
@@ -359,7 +371,7 @@ parse_aggregate_functions (struct agr_proc *agr)
       const struct agr_func *function;
       int func_index;
 
-      union value arg[2];
+      union agr_argument arg[2];
 
       struct variable **src;
       size_t n_src;
@@ -396,7 +408,7 @@ parse_aggregate_functions (struct agr_proc *agr)
          if (token == T_STRING)
            {
              ds_truncate (&tokstr, 255);
-             dest_label[n_dest - 1] = xstrdup (ds_c_str (&tokstr));
+             dest_label[n_dest - 1] = ds_xstrdup (&tokstr);
              lex_get ();
            }
        }
@@ -450,7 +462,7 @@ parse_aggregate_functions (struct agr_proc *agr)
            else if (function->n_args)
              pv_opts |= PV_SAME_TYPE;
 
-           if (!parse_variables (default_dict, &src, &n_src, pv_opts))
+           if (!parse_variables (dataset_dict (current_dataset), &src, &n_src, pv_opts))
              goto error;
          }
 
@@ -464,7 +476,7 @@ parse_aggregate_functions (struct agr_proc *agr)
                lex_match (',');
                if (token == T_STRING)
                  {
-                   arg[i].c = xstrdup (ds_c_str (&tokstr));
+                   arg[i].c = ds_xstrdup (&tokstr);
                    type = ALPHA;
                  }
                else if (lex_is_number ())
@@ -515,7 +527,7 @@ parse_aggregate_functions (struct agr_proc *agr)
                   || (src[0]->type == ALPHA
                       && str_compare_rpad (arg[0].c, arg[1].c) > 0)))
             {
-              union value t = arg[0];
+              union agr_argument t = arg[0];
               arg[0] = arg[1];
               arg[1] = t;
                   
@@ -568,7 +580,7 @@ parse_aggregate_functions (struct agr_proc *agr)
                     if (destvar != NULL) 
                       {
                         if ((func_index == N || func_index == NMISS)
-                            && dict_get_weight (default_dict) != NULL)
+                            && dict_get_weight (dataset_dict (current_dataset)) != NULL)
                           destvar->print = destvar->write = f8_2; 
                         else
                           destvar->print = destvar->write = function->format;
@@ -578,7 +590,7 @@ parse_aggregate_functions (struct agr_proc *agr)
                v->src = NULL;
                destvar = dict_create_var (agr->dict, dest[i], 0);
                 if (func_index == N_NO_VARS
-                    && dict_get_weight (default_dict) != NULL)
+                    && dict_get_weight (dataset_dict (current_dataset)) != NULL)
                   destvar->print = destvar->write = f8_2; 
                 else
                   destvar->print = destvar->write = function->format;
@@ -633,10 +645,10 @@ parse_aggregate_functions (struct agr_proc *agr)
       if (!lex_match ('/'))
        {
          if (token == '.')
-           return 1;
+           return true;
 
          lex_error ("expecting end of command");
-         return 0;
+         return false;
        }
       continue;
       
@@ -658,7 +670,7 @@ parse_aggregate_functions (struct agr_proc *agr)
          }
       free (src);
        
-      return 0;
+      return false;
     }
 }
 
@@ -704,9 +716,9 @@ static void accumulate_aggregate_info (struct agr_proc *,
 static void dump_aggregate_info (struct agr_proc *, struct ccase *);
 
 /* Processes a single case INPUT for aggregation.  If output is
-   warranted, writes it to OUTPUT and returns nonzero.
-   Otherwise, returns zero and OUTPUT is unmodified. */
-static int
+   warranted, writes it to OUTPUT and returns true.
+   Otherwise, returns false and OUTPUT is unmodified. */
+static bool
 aggregate_single_case (struct agr_proc *agr,
                        const struct ccase *input, struct ccase *output)
 {
@@ -734,9 +746,9 @@ accumulate_aggregate_info (struct agr_proc *agr,
 {
   struct agr_var *iter;
   double weight;
-  int bad_warn = 1;
+  bool bad_warn = true;
 
-  weight = dict_get_case_weight (default_dict, input, &bad_warn);
+  weight = dict_get_case_weight (dataset_dict (current_dataset), input, &bad_warn);
 
   for (iter = agr->agr_vars; iter; iter = iter->next)
     if (iter->src)
@@ -883,7 +895,7 @@ accumulate_aggregate_info (struct agr_proc *agr,
                caught earlier.  Nothing to do. */
             break;
          default:
-           assert (0);
+           NOT_REACHED ();
          }
     } else {
       switch (iter->function)
@@ -895,7 +907,7 @@ accumulate_aggregate_info (struct agr_proc *agr,
          iter->int1++;
          break;
        default:
-         assert (0);
+         NOT_REACHED ();
        }
     }
 }
@@ -1024,7 +1036,7 @@ dump_aggregate_info (struct agr_proc *agr, struct ccase *output)
            v->f = i->int1;
            break;
          default:
-           assert (0);
+           NOT_REACHED ();
          }
       }
   }
@@ -1074,7 +1086,7 @@ initialize_aggregate_info (struct agr_proc *agr, const struct ccase *input)
    are dropped.
    Returns true if successful, false if an I/O error occurred. */
 static bool
-agr_to_active_file (struct ccase *c, void *agr_)
+agr_to_active_file (const struct ccase *c, void *agr_)
 {
   struct agr_proc *agr = agr_;
 
@@ -1087,7 +1099,7 @@ agr_to_active_file (struct ccase *c, void *agr_)
 /* Aggregate the current case and output it if we passed a
    breakpoint. */
 static bool
-presorted_agr_to_sysfile (struct ccase *c, void *agr_) 
+presorted_agr_to_sysfile (const struct ccase *c, void *agr_) 
 {
   struct agr_proc *agr = agr_;