We've had a mix of min, max from libpspp/misc.h and MIN, MAX from
[pspp-builds.git] / src / language / stats / crosstabs.q
index e7466d7239e50256b0627c64af16bf1d7f1e6831..00ec61369cfc04edc9e48846d04fb1152027a21d 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - computes sample statistics.
-   Copyright (C) 1997-9, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
    Written by Ben Pfaff <blp@gnu.org>.
 
    This program is free software; you can redistribute it and/or
@@ -37,6 +37,7 @@
 #include <stdio.h>
 
 #include <data/case.h>
+#include <data/data-out.h>
 #include <data/dictionary.h>
 #include <data/procedure.h>
 #include <data/value-labels.h>
@@ -59,6 +60,8 @@
 #include <output/output.h>
 #include <output/table.h>
 
+#include "minmax.h"
+
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
 #define N_(msgid) msgid
@@ -175,11 +178,11 @@ static struct cmd_crosstabs cmd;
 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 (const struct ccase *, void *);
-static bool calc_general (const struct ccase *, void *);
-static bool calc_integer (const struct ccase *, void *);
-static void postcalc (void *);
+static int internal_cmd_crosstabs (struct lexer *lexer, struct dataset *ds);
+static void precalc (const struct ccase *, void *, const struct dataset *);
+static bool calc_general (const struct ccase *, void *, const struct dataset *);
+static bool calc_integer (const struct ccase *, void *, const struct dataset *);
+static bool postcalc (void *, const struct dataset *);
 static void submit (struct tab_table *);
 
 static void format_short (char *s, const struct fmt_spec *fp,
@@ -187,9 +190,9 @@ static void format_short (char *s, const struct fmt_spec *fp,
 
 /* Parse and execute CROSSTABS, then clean up. */
 int
-cmd_crosstabs (void)
+cmd_crosstabs (struct lexer *lexer, struct dataset *ds)
 {
-  int result = internal_cmd_crosstabs ();
+  int result = internal_cmd_crosstabs (lexer, ds);
 
   free (variables);
   pool_destroy (pl_tc);
@@ -200,7 +203,7 @@ cmd_crosstabs (void)
 
 /* Parses and executes the CROSSTABS procedure. */
 static int
-internal_cmd_crosstabs (void)
+internal_cmd_crosstabs (struct lexer *lexer, struct dataset *ds)
 {
   int i;
   bool ok;
@@ -212,7 +215,7 @@ internal_cmd_crosstabs (void)
   pl_tc = pool_create ();
   pl_col = pool_create ();
 
-  if (!parse_crosstabs (&cmd, NULL))
+  if (!parse_crosstabs (lexer, ds, &cmd, NULL))
     return CMD_FAILURE;
 
   mode = variables ? INTEGER : GENERAL;
@@ -293,7 +296,7 @@ internal_cmd_crosstabs (void)
   else
     write = CRS_WR_NONE;
 
-  ok = procedure_with_splits (current_dataset, precalc,
+  ok = procedure_with_splits (ds, precalc,
                               mode == GENERAL ? calc_general : calc_integer,
                               postcalc, NULL);
 
@@ -302,7 +305,7 @@ internal_cmd_crosstabs (void)
 
 /* Parses the TABLES subcommand. */
 static int
-crs_custom_tables (struct cmd_crosstabs *cmd UNUSED, void *aux UNUSED)
+crs_custom_tables (struct lexer *lexer, struct dataset *ds, struct cmd_crosstabs *cmd UNUSED, void *aux UNUSED)
 {
   struct var_set *var_set;
   int n_by;
@@ -312,23 +315,23 @@ crs_custom_tables (struct cmd_crosstabs *cmd UNUSED, void *aux UNUSED)
   int success = 0;
 
   /* Ensure that this is a TABLES subcommand. */
-  if (!lex_match_id ("TABLES")
-      && (token != T_ID || dict_lookup_var (dataset_dict (current_dataset), tokid) == NULL)
-      && token != T_ALL)
+  if (!lex_match_id (lexer, "TABLES")
+      && (lex_token (lexer) != T_ID || dict_lookup_var (dataset_dict (ds), lex_tokid (lexer)) == NULL)
+      && lex_token (lexer) != T_ALL)
     return 2;
-  lex_match ('=');
+  lex_match (lexer, '=');
 
   if (variables != NULL)
     var_set = var_set_create_from_array (variables, variables_cnt);
   else
-    var_set = var_set_create_from_dict (dataset_dict (current_dataset));
+    var_set = var_set_create_from_dict (dataset_dict (ds));
   assert (var_set != NULL);
   
   for (n_by = 0; ;)
     {
       by = xnrealloc (by, n_by + 1, sizeof *by);
       by_nvar = xnrealloc (by_nvar, n_by + 1, sizeof *by_nvar);
-      if (!parse_var_set_vars (var_set, &by[n_by], &by_nvar[n_by],
+      if (!parse_var_set_vars (lexer, var_set, &by[n_by], &by_nvar[n_by],
                                PV_NO_DUPLICATE | PV_NO_SCRATCH))
        goto done;
       if (xalloc_oversized (nx, by_nvar[n_by])) 
@@ -339,11 +342,11 @@ crs_custom_tables (struct cmd_crosstabs *cmd UNUSED, void *aux UNUSED)
       nx *= by_nvar[n_by];
       n_by++;
 
-      if (!lex_match (T_BY))
+      if (!lex_match (lexer, T_BY))
        {
          if (n_by < 2)
            {
-             lex_error (_("expecting BY"));
+             lex_error (lexer, _("expecting BY"));
              goto done;
            }
          else 
@@ -406,7 +409,7 @@ crs_custom_tables (struct cmd_crosstabs *cmd UNUSED, void *aux UNUSED)
 
 /* Parses the VARIABLES subcommand. */
 static int
-crs_custom_variables (struct cmd_crosstabs *cmd UNUSED, void *aux UNUSED)
+crs_custom_variables (struct lexer *lexer, struct dataset *ds, struct cmd_crosstabs *cmd UNUSED, void *aux UNUSED)
 {
   if (nxtab)
     {
@@ -414,7 +417,7 @@ crs_custom_variables (struct cmd_crosstabs *cmd UNUSED, void *aux UNUSED)
       return 0;
     }
 
-  lex_match ('=');
+  lex_match (lexer, '=');
   
   for (;;)
     {
@@ -423,42 +426,43 @@ crs_custom_variables (struct cmd_crosstabs *cmd UNUSED, void *aux UNUSED)
 
       long min, max;
       
-      if (!parse_variables (dataset_dict (current_dataset), &variables, &variables_cnt,
+      if (!parse_variables (lexer, dataset_dict (ds), 
+                           &variables, &variables_cnt,
                            (PV_APPEND | PV_NUMERIC
                             | PV_NO_DUPLICATE | PV_NO_SCRATCH)))
        return 0;
 
-      if (token != '(')
+      if (lex_token (lexer) != '(')
        {
-         lex_error ("expecting `('");
+         lex_error (lexer, "expecting `('");
          goto lossage;
        }
-      lex_get ();
+      lex_get (lexer);
 
-      if (!lex_force_int ())
+      if (!lex_force_int (lexer))
        goto lossage;
-      min = lex_integer ();
-      lex_get ();
+      min = lex_integer (lexer);
+      lex_get (lexer);
 
-      lex_match (',');
+      lex_match (lexer, ',');
 
-      if (!lex_force_int ())
+      if (!lex_force_int (lexer))
        goto lossage;
-      max = lex_integer ();
+      max = lex_integer (lexer);
       if (max < min)
        {
          msg (SE, _("Maximum value (%ld) less than minimum value (%ld)."),
               max, min);
          goto lossage;
        }
-      lex_get ();
+      lex_get (lexer);
 
-      if (token != ')')
+      if (lex_token (lexer) != ')')
        {
-         lex_error ("expecting `)'");
+         lex_error (lexer, "expecting `)'");
          goto lossage;
        }
-      lex_get ();
+      lex_get (lexer);
       
       for (i = orig_nv; i < variables_cnt; i++) 
         {
@@ -469,7 +473,7 @@ crs_custom_variables (struct cmd_crosstabs *cmd UNUSED, void *aux UNUSED)
           var_attach_aux (variables[i], vr, var_dtor_free);
        }
       
-      if (token == '/')
+      if (lex_token (lexer) == '/')
        break;
     }
   
@@ -483,14 +487,14 @@ crs_custom_variables (struct cmd_crosstabs *cmd UNUSED, void *aux UNUSED)
 \f
 /* Data file processing. */
 
-static int compare_table_entry (const void *, const void *, void *);
-static unsigned hash_table_entry (const void *, void *);
+static int compare_table_entry (const void *, const void *, const void *);
+static unsigned hash_table_entry (const void *, const void *);
 
 /* Set up the crosstabulation tables for processing. */
 static  void
-precalc (const struct ccase *first, void *aux UNUSED)
+precalc (const struct ccase *first, void *aux UNUSED, const struct dataset *ds)
 {
-  output_split_file_values (first);
+  output_split_file_values (ds, first);
   if (mode == GENERAL)
     {
       gen_tab = hsh_create (512, compare_table_entry, hash_table_entry,
@@ -563,12 +567,12 @@ precalc (const struct ccase *first, void *aux UNUSED)
 
 /* Form crosstabulations for general mode. */
 static bool
-calc_general (const struct ccase *c, void *aux UNUSED)
+calc_general (const struct ccase *c, void *aux UNUSED, const struct dataset *ds)
 {
   bool bad_warn = true;
 
   /* Case weight. */
-  double weight = dict_get_case_weight (dataset_dict (current_dataset), c, &bad_warn);
+  double weight = dict_get_case_weight (dataset_dict (ds), c, &bad_warn);
 
   /* Flattened current table index. */
   int t;
@@ -637,12 +641,12 @@ calc_general (const struct ccase *c, void *aux UNUSED)
 }
 
 static bool
-calc_integer (const struct ccase *c, void *aux UNUSED)
+calc_integer (const struct ccase *c, void *aux UNUSED, const struct dataset *ds)
 {
   bool bad_warn = true;
 
   /* Case weight. */
-  double weight = dict_get_case_weight (dataset_dict (current_dataset), c, &bad_warn);
+  double weight = dict_get_case_weight (dataset_dict (ds), c, &bad_warn);
   
   /* Flattened current table index. */
   int t;
@@ -697,7 +701,7 @@ calc_integer (const struct ccase *c, void *aux UNUSED)
 /* Compare the table_entry's at A and B and return a strcmp()-type
    result. */
 static int 
-compare_table_entry (const void *a_, const void *b_, void *foo UNUSED)
+compare_table_entry (const void *a_, const void *b_, const void *aux UNUSED)
 {
   const struct table_entry *a = a_;
   const struct table_entry *b = b_;
@@ -737,7 +741,7 @@ compare_table_entry (const void *a_, const void *b_, void *foo UNUSED)
 
 /* Calculate a hash value from table_entry A. */
 static unsigned
-hash_table_entry (const void *a_, void *foo UNUSED)
+hash_table_entry (const void *a_, const void *aux UNUSED)
 {
   const struct table_entry *a = a_;
   unsigned long hash;
@@ -762,8 +766,8 @@ static void output_pivot_table (struct table_entry **, struct table_entry **,
                                int *, int *, int *);
 static void make_summary_table (void);
 
-static void
-postcalc (void *aux UNUSED)
+static bool
+postcalc (void *aux UNUSED, const struct dataset *ds UNUSED)
 {
   if (mode == GENERAL)
     {
@@ -799,6 +803,8 @@ postcalc (void *aux UNUSED)
   }
   
   hsh_destroy (gen_tab);
+
+  return true;
 }
 
 static void insert_summary (struct tab_table *, int tab_index, double valid);
@@ -1218,7 +1224,7 @@ output_pivot_table (struct table_entry **pb, struct table_entry **pe,
       /* Allocate table space for the matrix. */
       if (table && tab_row (table) + (n_rows + 1) * num_cells > tab_nr (table))
        tab_realloc (table, -1,
-                    max (tab_nr (table) + (n_rows + 1) * num_cells,
+                    MAX (tab_nr (table) + (n_rows + 1) * num_cells,
                          tab_nr (table) * (pe - pb) / (te - tb)));
 
       if (mode == GENERAL)
@@ -1608,7 +1614,7 @@ find_pivot_extent_integer (struct table_entry **tp, int *cnt, int pivot)
    result.  WIDTH_ points to an int which is either 0 for a
    numeric value or a string width for a string value. */
 static int
-compare_value (const void *a_, const void *b_, void *width_)
+compare_value (const void *a_, const void *b_, const void *width_)
 {
   const union value *a = a_;
   const union value *b = b_;
@@ -1716,7 +1722,7 @@ format_cell_entry (struct tab_table *table, int c, int r, double value,
   s.length = 10;
   s.string = tab_alloc (table, 16);
   v.f = value;
-  data_out (s.string, &f, &v);
+  data_out (&v, &f, s.string);
   while (*s.string == ' ')
     {
       s.length--;
@@ -2273,9 +2279,9 @@ calc_fisher (int a, int b, int c, int d, double *fisher1, double *fisher2)
 {
   int x;
   
-  if (min (c, d) < min (a, b))
+  if (MIN (c, d) < MIN (a, b))
     swap (&a, &c), swap (&b, &d);
-  if (min (b, d) < min (a, c))
+  if (MIN (b, d) < MIN (a, c))
     swap (&a, &b), swap (&c, &d);
   if (b * c < a * d)
     {
@@ -2467,7 +2473,7 @@ static int
 calc_symmetric (double v[N_SYMMETRIC], double ase[N_SYMMETRIC],
                double t[N_SYMMETRIC])
 {
-  int q = min (ns_rows, ns_cols);
+  int q = MIN (ns_rows, ns_cols);
   
   if (q <= 1)
     return 0;
@@ -3184,22 +3190,22 @@ format_short (char *s, const struct fmt_spec *fp, const union value *v)
   struct fmt_spec fmt_subst;
 
   /* Limit to short string width. */
-  if (formats[fp->type].cat & FCAT_STRING
+  if (fmt_is_string (fp->type)
     {
       fmt_subst = *fp;
 
       assert (fmt_subst.type == FMT_A || fmt_subst.type == FMT_AHEX);
       if (fmt_subst.type == FMT_A)
-        fmt_subst.w = min (8, fmt_subst.w);
+        fmt_subst.w = MIN (8, fmt_subst.w);
       else
-        fmt_subst.w = min (16, fmt_subst.w);
+        fmt_subst.w = MIN (16, fmt_subst.w);
 
       fp = &fmt_subst;
     }
 
   /* Format. */
-  data_out (s, fp, v);
-  
+  data_out (v, fp, s);
+    
   /* Null terminate. */
   s[fp->w] = '\0';
 }