Change license from GPLv2+ to GPLv3+.
[pspp-builds.git] / src / language / stats / examine.q
index e2bd897a5200f20838959727368e74c691cda686..d9b9bece6fbc79dca18519859325beae4332052b 100644 (file)
@@ -1,22 +1,18 @@
-/* PSPP - EXAMINE data for normality . -*-c-*-
+/* PSPP - a program for statistical analysis.
+   Copyright (C) 2004 Free Software Foundation, Inc.
 
-Copyright (C) 2004 Free Software Foundation, Inc.
-Author: John Darrington 2004
+   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 3 of the License, or
+   (at your option) any later version.
 
-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.
 
-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., 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA. */
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
 #include <config.h>
 
@@ -27,7 +23,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 #include <stdlib.h>
 
 #include <data/case.h>
-#include <data/casefile.h>
+#include <data/casegrouper.h>
+#include <data/casereader.h>
 #include <data/dictionary.h>
 #include <data/procedure.h>
 #include <data/value-labels.h>
@@ -50,6 +47,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 #include <output/manager.h>
 #include <output/table.h>
 
+#include "minmax.h"
+
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
 #define N_(msgid) msgid
@@ -64,9 +63,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    *^variables=custom;
    +total=custom;
    +nototal=custom;
-   +missing=miss:pairwise/!listwise,
-   rep:report/!noreport,
-   incl:include/!exclude;
+   missing=miss:pairwise/!listwise,
+           rep:report/!noreport,
+           incl:include/!exclude;
    +compare=cmp:variables/!groups;
    +percentiles=custom;
    +id=var;
@@ -83,12 +82,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 
 static struct cmd_examine cmd;
 
-static struct variable **dependent_vars;
+static const struct variable **dependent_vars;
 
 static size_t n_dependent_vars;
 
 
-struct factor 
+struct factor
 {
   /* The independent variable */
   struct variable *indep_var[2];
@@ -105,81 +104,80 @@ struct factor
 };
 
 /* Linked list of factors */
-static struct factor *factors=0;
+static struct factor *factors = 0;
 
-static struct metrics *totals=0;
+static struct metrics *totals = 0;
 
 /* Parse the clause specifying the factors */
-static int examine_parse_independent_vars(struct cmd_examine *cmd);
+static int examine_parse_independent_vars (struct lexer *lexer, const struct dictionary *dict, struct cmd_examine *cmd);
 
 
 
 /* Output functions */
-static void show_summary(struct variable **dependent_var, int n_dep_var, 
+static void show_summary (const struct variable **dependent_var, int n_dep_var,
                         const struct factor *f);
 
-static void show_extremes(struct variable **dependent_var, 
-                         int n_dep_var, 
+static void show_extremes (const struct variable **dependent_var,
+                         int n_dep_var,
                          const struct factor *factor,
                          int n_extremities);
 
-static void show_descriptives(struct variable **dependent_var, 
-                             int n_dep_var, 
+static void show_descriptives (const struct variable **dependent_var,
+                             int n_dep_var,
                              struct factor *factor);
 
-static void show_percentiles(struct variable **dependent_var, 
-                            int n_dep_var, 
+static void show_percentiles (const struct variable **dependent_var,
+                            int n_dep_var,
                             struct factor *factor);
 
 
 
 
-void np_plot(const struct metrics *m, const char *factorname);
+void np_plot (const struct metrics *m, const char *factorname);
 
 
-void box_plot_group(const struct factor *fctr, 
+void box_plot_group (const struct factor *fctr,
                    const struct variable **vars, int n_vars,
                    const struct variable *id
                    ) ;
 
 
-void box_plot_variables(const struct factor *fctr, 
-                       const struct variable **vars, int n_vars, 
+void box_plot_variables (const struct factor *fctr,
+                       const struct variable **vars, int n_vars,
                        const struct variable *id
                        );
 
 
 
 /* Per Split function */
-static bool run_examine(const struct ccase *,
-                        const struct casefile *cf, void *cmd_);
+static void run_examine (struct cmd_examine *, struct casereader *,
+                         struct dataset *);
 
-static void output_examine(void);
+static void output_examine (void);
 
 
-void factor_calc(struct ccase *c, int case_no, 
-                double weight, int case_missing);
+void factor_calc (const struct ccase *c, int case_no,
+                 double weight, int case_missing);
 
 
 /* Represent a factor as a string, so it can be
    printed in a human readable fashion */
-const char * factor_to_string(const struct factor *fctr, 
-                             struct factor_statistics *fs,
-                             const struct variable *var);
+const char * factor_to_string (const struct factor *fctr,
+                              const struct factor_statistics *fs,
+                              const struct variable *var);
 
 
 /* Represent a factor as a string, so it can be
    printed in a human readable fashion,
    but sacrificing some readablility for the sake of brevity */
-const char *factor_to_string_concise(const struct factor *fctr, 
+const char *factor_to_string_concise (const struct factor *fctr,
                                     struct factor_statistics *fs);
 
 
 
 
-/* Function to use for testing for missing values */
-static is_missing_func *value_is_missing;
-
+/* Categories of missing values to exclude. */
+static enum mv_class exclude_values;
 
 /* PERCENTILES */
 
@@ -191,50 +189,56 @@ static short sbc_percentile;
 
 
 int
-cmd_examine(void)
+cmd_examine (struct lexer *lexer, struct dataset *ds)
 {
+  struct casegrouper *grouper;
+  struct casereader *group;
   bool ok;
 
-  subc_list_double_create(&percentile_list);
+  subc_list_double_create (&percentile_list);
   percentile_algorithm = PC_HAVERAGE;
 
-  if ( !parse_examine(&cmd) )
-    return CMD_FAILURE;
+  if ( !parse_examine (lexer, ds, &cmd, NULL) )
+    {
+      subc_list_double_destroy (&percentile_list);
+      return CMD_FAILURE;
+    }
 
   /* If /MISSING=INCLUDE is set, then user missing values are ignored */
-  if (cmd.incl == XMN_INCLUDE ) 
-    value_is_missing = mv_is_value_system_missing;
-  else
-    value_is_missing = mv_is_value_missing;
+  exclude_values = cmd.incl == XMN_INCLUDE ? MV_SYSTEM : MV_ANY;
 
-  if ( cmd.st_n == SYSMIS ) 
+  if ( cmd.st_n == SYSMIS )
     cmd.st_n = 5;
 
-  if ( ! cmd.sbc_cinterval) 
+  if ( ! cmd.sbc_cinterval)
     cmd.n_cinterval[0] = 95.0;
 
-  /* If descriptives have been requested, make sure the 
+  /* If descriptives have been requested, make sure the
      quartiles are calculated */
   if ( cmd.a_statistics[XMN_ST_DESCRIPTIVES] )
     {
-      subc_list_double_push(&percentile_list, 25);
-      subc_list_double_push(&percentile_list, 50);
-      subc_list_double_push(&percentile_list, 75);
+      subc_list_double_push (&percentile_list, 25);
+      subc_list_double_push (&percentile_list, 50);
+      subc_list_double_push (&percentile_list, 75);
     }
 
-  ok = multipass_procedure_with_splits (run_examine, &cmd);
+  grouper = casegrouper_create_splits (proc_open (ds), dataset_dict (ds));
+  while (casegrouper_get_next_group (grouper, &group))
+    run_examine (&cmd, group, ds);
+  ok = casegrouper_destroy (grouper);
+  ok = proc_commit (ds) && ok;
 
-  if ( totals ) 
+  if ( totals )
     {
-      free( totals );
+      free ( totals );
     }
-  
-  if ( dependent_vars ) 
+
+  if ( dependent_vars )
     free (dependent_vars);
 
   {
     struct factor *f = factors ;
-    while ( f ) 
+    while ( f )
       {
        struct factor *ff = f;
 
@@ -246,7 +250,7 @@ cmd_examine(void)
     factors = 0;
   }
 
-  subc_list_double_destroy(&percentile_list);
+  subc_list_double_destroy (&percentile_list);
 
   return ok ? CMD_SUCCESS : CMD_CASCADING_FAILURE;
 };
@@ -255,39 +259,45 @@ cmd_examine(void)
 
 /* Show all the appropriate tables */
 static void
-output_examine(void)
+output_examine (void)
 {
   struct factor *fctr;
 
   /* Show totals if appropriate */
   if ( ! cmd.sbc_nototal || factors == 0 )
     {
-      show_summary(dependent_vars, n_dependent_vars, 0);
+      show_summary (dependent_vars, n_dependent_vars, 0);
 
-      if ( cmd.sbc_statistics ) 
+      if ( cmd.sbc_statistics )
        {
-         if ( cmd.a_statistics[XMN_ST_EXTREME]) 
-           show_extremes(dependent_vars, n_dependent_vars, 0, cmd.st_n);
+         if ( cmd.a_statistics[XMN_ST_EXTREME])
+           show_extremes (dependent_vars, n_dependent_vars, 0, cmd.st_n);
 
-         if ( cmd.a_statistics[XMN_ST_DESCRIPTIVES]) 
-           show_descriptives(dependent_vars, n_dependent_vars, 0);
+         if ( cmd.a_statistics[XMN_ST_DESCRIPTIVES])
+           show_descriptives (dependent_vars, n_dependent_vars, 0);
 
        }
-      if ( sbc_percentile ) 
-       show_percentiles(dependent_vars, n_dependent_vars, 0);
+      if ( sbc_percentile )
+       show_percentiles (dependent_vars, n_dependent_vars, 0);
 
-      if ( cmd.sbc_plot) 
+      if ( cmd.sbc_plot)
        {
          int v;
-         if ( cmd.a_plot[XMN_PLT_NPPLOT] ) 
+         if ( cmd.a_plot[XMN_PLT_STEMLEAF] )
+           msg (SW, _ ("%s is not currently supported."), "STEMLEAF");
+
+         if ( cmd.a_plot[XMN_PLT_SPREADLEVEL] )
+           msg (SW, _ ("%s is not currently supported."), "SPREADLEVEL");
+
+         if ( cmd.a_plot[XMN_PLT_NPPLOT] )
            {
-             for ( v = 0 ; v < n_dependent_vars; ++v ) 
-               np_plot(&totals[v], var_to_string(dependent_vars[v]));
+             for ( v = 0 ; v < n_dependent_vars; ++v )
+               np_plot (&totals[v], var_to_string (dependent_vars[v]));
            }
 
-         if ( cmd.a_plot[XMN_PLT_BOXPLOT] ) 
+         if ( cmd.a_plot[XMN_PLT_BOXPLOT] )
            {
-             if ( cmd.cmp == XMN_GROUPS ) 
+             if ( cmd.cmp == XMN_GROUPS )
                {
                  box_plot_group (0, (const struct variable **) dependent_vars,
                                   n_dependent_vars, cmd.v_id);
@@ -298,18 +308,18 @@ output_examine(void)
                                     n_dependent_vars, cmd.v_id);
            }
 
-         if ( cmd.a_plot[XMN_PLT_HISTOGRAM] ) 
+         if ( cmd.a_plot[XMN_PLT_HISTOGRAM] )
            {
-             for ( v = 0 ; v < n_dependent_vars; ++v ) 
+             for ( v = 0 ; v < n_dependent_vars; ++v )
                {
                  struct normal_curve normal;
 
                  normal.N      = totals[v].n;
                  normal.mean   = totals[v].mean;
                  normal.stddev = totals[v].stddev;
-                 
-                 histogram_plot(totals[v].histogram, 
-                                var_to_string(dependent_vars[v]),
+
+                 histogram_plot (totals[v].histogram,
+                                var_to_string (dependent_vars[v]),
                                 &normal, 0);
                }
            }
@@ -321,24 +331,24 @@ output_examine(void)
 
   /* Show grouped statistics  as appropriate */
   fctr = factors;
-  while ( fctr ) 
+  while ( fctr )
     {
-      show_summary(dependent_vars, n_dependent_vars, fctr);
+      show_summary (dependent_vars, n_dependent_vars, fctr);
 
-      if ( cmd.sbc_statistics ) 
+      if ( cmd.sbc_statistics )
        {
-         if ( cmd.a_statistics[XMN_ST_EXTREME]) 
-           show_extremes(dependent_vars, n_dependent_vars, fctr, cmd.st_n);
+         if ( cmd.a_statistics[XMN_ST_EXTREME])
+           show_extremes (dependent_vars, n_dependent_vars, fctr, cmd.st_n);
 
-         if ( cmd.a_statistics[XMN_ST_DESCRIPTIVES]) 
-           show_descriptives(dependent_vars, n_dependent_vars, fctr);
+         if ( cmd.a_statistics[XMN_ST_DESCRIPTIVES])
+           show_descriptives (dependent_vars, n_dependent_vars, fctr);
        }
 
-      if ( sbc_percentile ) 
-       show_percentiles(dependent_vars, n_dependent_vars, fctr);
+      if ( sbc_percentile )
+       show_percentiles (dependent_vars, n_dependent_vars, fctr);
 
 
-      if ( cmd.sbc_plot) 
+      if ( cmd.sbc_plot)
        {
          size_t v;
 
@@ -346,7 +356,7 @@ output_examine(void)
 
          if ( cmd.a_plot[XMN_PLT_BOXPLOT] )
            {
-             if ( cmd.cmp == XMN_VARIABLES ) 
+             if ( cmd.cmp == XMN_VARIABLES )
                box_plot_variables (fctr,
                                     (const struct variable **) dependent_vars,
                                     n_dependent_vars, cmd.v_id);
@@ -359,25 +369,25 @@ output_examine(void)
          for ( v = 0 ; v < n_dependent_vars; ++v )
            {
 
-             for ( fs = fctr->fs ; *fs ; ++fs ) 
+             for ( fs = fctr->fs ; *fs ; ++fs )
                {
-                 const char *s = factor_to_string(fctr, *fs, dependent_vars[v]);
+                 const char *s = factor_to_string (fctr, *fs, dependent_vars[v]);
 
-                 if ( cmd.a_plot[XMN_PLT_NPPLOT] ) 
-                   np_plot(&(*fs)->m[v], s);
+                 if ( cmd.a_plot[XMN_PLT_NPPLOT] )
+                   np_plot (& (*fs)->m[v], s);
 
-                 if ( cmd.a_plot[XMN_PLT_HISTOGRAM] ) 
+                 if ( cmd.a_plot[XMN_PLT_HISTOGRAM] )
                    {
                      struct normal_curve normal;
 
                      normal.N      = (*fs)->m[v].n;
                      normal.mean   = (*fs)->m[v].mean;
                      normal.stddev = (*fs)->m[v].stddev;
-                 
-                     histogram_plot((*fs)->m[v].histogram, 
+
+                     histogram_plot ((*fs)->m[v].histogram,
                                     s,  &normal, 0);
                    }
-                 
+
                } /* for ( fs .... */
 
            } /* for ( v = 0 ..... */
@@ -393,27 +403,27 @@ output_examine(void)
 /* Create a hash table of percentiles and their values from the list of
    percentiles */
 static struct hsh_table *
-list_to_ptile_hash(const subc_list_double *l)
+list_to_ptile_hash (const subc_list_double *l)
 {
   int i;
-  
-  struct hsh_table *h ; 
 
-  h = hsh_create(subc_list_double_count(l), 
+  struct hsh_table *h ;
+
+  h = hsh_create (subc_list_double_count (l),
                 (hsh_compare_func *) ptile_compare,
-                (hsh_hash_func *) ptile_hash, 
+                (hsh_hash_func *) ptile_hash,
                 (hsh_free_func *) free,
                 0);
 
 
-  for ( i = 0 ; i < subc_list_double_count(l) ; ++i )
+  for ( i = 0 ; i < subc_list_double_count (l) ; ++i )
     {
       struct percentile *p = xmalloc (sizeof *p);
-      
-      p->p = subc_list_double_at(l,i);
+
+      p->p = subc_list_double_at (l,i);
       p->v = SYSMIS;
 
-      hsh_insert(h, p);
+      hsh_insert (h, p);
 
     }
 
@@ -423,54 +433,55 @@ list_to_ptile_hash(const subc_list_double *l)
 
 /* Parse the PERCENTILES subcommand */
 static int
-xmn_custom_percentiles(struct cmd_examine *p UNUSED)
+xmn_custom_percentiles (struct lexer *lexer, struct dataset *ds UNUSED,
+                      struct cmd_examine *p UNUSED, void *aux UNUSED)
 {
   sbc_percentile = 1;
 
-  lex_match('=');
+  lex_match (lexer, '=');
 
-  lex_match('(');
+  lex_match (lexer, '(');
 
-  while ( lex_is_number() ) 
+  while ( lex_is_number (lexer) )
     {
-      subc_list_double_push(&percentile_list,lex_number());
+      subc_list_double_push (&percentile_list, lex_number (lexer));
 
-      lex_get();
+      lex_get (lexer);
 
-      lex_match(',') ;
+      lex_match (lexer, ',') ;
     }
-  lex_match(')');
+  lex_match (lexer, ')');
 
-  lex_match('=');
+  lex_match (lexer, '=');
 
-  if ( lex_match_id("HAVERAGE"))
-    percentile_algorithm = PC_HAVERAGE; 
+  if ( lex_match_id (lexer, "HAVERAGE"))
+    percentile_algorithm = PC_HAVERAGE;
 
-  else if ( lex_match_id("WAVERAGE"))
-    percentile_algorithm = PC_WAVERAGE; 
+  else if ( lex_match_id (lexer, "WAVERAGE"))
+    percentile_algorithm = PC_WAVERAGE;
 
-  else if ( lex_match_id("ROUND"))
+  else if ( lex_match_id (lexer, "ROUND"))
     percentile_algorithm = PC_ROUND;
 
-  else if ( lex_match_id("EMPIRICAL"))
+  else if ( lex_match_id (lexer, "EMPIRICAL"))
     percentile_algorithm = PC_EMPIRICAL;
 
-  else if ( lex_match_id("AEMPIRICAL"))
-    percentile_algorithm = PC_AEMPIRICAL; 
+  else if ( lex_match_id (lexer, "AEMPIRICAL"))
+    percentile_algorithm = PC_AEMPIRICAL;
 
-  else if ( lex_match_id("NONE"))
-    percentile_algorithm = PC_NONE; 
+  else if ( lex_match_id (lexer, "NONE"))
+    percentile_algorithm = PC_NONE;
 
 
-  if ( 0 == subc_list_double_count(&percentile_list))
+  if ( 0 == subc_list_double_count (&percentile_list))
     {
-      subc_list_double_push(&percentile_list, 5);
-      subc_list_double_push(&percentile_list, 10);
-      subc_list_double_push(&percentile_list, 25);
-      subc_list_double_push(&percentile_list, 50);
-      subc_list_double_push(&percentile_list, 75);
-      subc_list_double_push(&percentile_list, 90);
-      subc_list_double_push(&percentile_list, 95);
+      subc_list_double_push (&percentile_list, 5);
+      subc_list_double_push (&percentile_list, 10);
+      subc_list_double_push (&percentile_list, 25);
+      subc_list_double_push (&percentile_list, 50);
+      subc_list_double_push (&percentile_list, 75);
+      subc_list_double_push (&percentile_list, 90);
+      subc_list_double_push (&percentile_list, 95);
     }
 
   return 1;
@@ -478,11 +489,11 @@ xmn_custom_percentiles(struct cmd_examine *p UNUSED)
 
 /* TOTAL and NOTOTAL are simple, mutually exclusive flags */
 static int
-xmn_custom_total(struct cmd_examine *p)
+xmn_custom_total (struct lexer *lexer UNUSED, struct dataset *ds UNUSED, struct cmd_examine *p, void *aux UNUSED)
 {
-  if ( p->sbc_nototal ) 
+  if ( p->sbc_nototal )
     {
-      msg (SE, _("%s and %s are mutually exclusive"),"TOTAL","NOTOTAL");
+      msg (SE, _ ("%s and %s are mutually exclusive"),"TOTAL","NOTOTAL");
       return 0;
     }
 
@@ -490,11 +501,12 @@ xmn_custom_total(struct cmd_examine *p)
 }
 
 static int
-xmn_custom_nototal(struct cmd_examine *p)
+xmn_custom_nototal (struct lexer *lexer UNUSED, struct dataset *ds UNUSED,
+                   struct cmd_examine *p, void *aux UNUSED)
 {
-  if ( p->sbc_total ) 
+  if ( p->sbc_total )
     {
-      msg (SE, _("%s and %s are mutually exclusive"),"TOTAL","NOTOTAL");
+      msg (SE, _ ("%s and %s are mutually exclusive"),"TOTAL","NOTOTAL");
       return 0;
     }
 
@@ -503,37 +515,38 @@ xmn_custom_nototal(struct cmd_examine *p)
 
 
 
-/* Parser for the variables sub command  
+/* Parser for the variables sub command
    Returns 1 on success */
 static int
-xmn_custom_variables(struct cmd_examine *cmd )
+xmn_custom_variables (struct lexer *lexer, struct dataset *ds, struct cmd_examine *cmd, void *aux UNUSED)
 {
-  lex_match('=');
+  const struct dictionary *dict = dataset_dict (ds);
+  lex_match (lexer, '=');
 
-  if ((token != T_ID || dict_lookup_var (default_dict, tokid) == NULL)
-      && token != T_ALL)
+  if ( (lex_token (lexer) != T_ID || dict_lookup_var (dict, lex_tokid (lexer)) == NULL)
+      && lex_token (lexer) != T_ALL)
     {
       return 2;
     }
-  
-  if (!parse_variables (default_dict, &dependent_vars, &n_dependent_vars,
+
+  if (!parse_variables_const (lexer, dict, &dependent_vars, &n_dependent_vars,
                        PV_NO_DUPLICATE | PV_NUMERIC | PV_NO_SCRATCH) )
     {
       free (dependent_vars);
       return 0;
     }
 
-  assert(n_dependent_vars);
+  assert (n_dependent_vars);
 
   totals = xnmalloc (n_dependent_vars, sizeof *totals);
 
-  if ( lex_match(T_BY))
+  if ( lex_match (lexer, T_BY))
     {
-      int success ; 
-      success =  examine_parse_independent_vars(cmd);
+      int success ;
+      success =  examine_parse_independent_vars (lexer, dict, cmd);
       if ( success != 1 ) {
         free (dependent_vars);
-       free (totals) ; 
+       free (totals) ;
       }
       return success;
     }
@@ -545,40 +558,40 @@ xmn_custom_variables(struct cmd_examine *cmd )
 
 /* Parse the clause specifying the factors */
 static int
-examine_parse_independent_vars(struct cmd_examine *cmd)
+examine_parse_independent_vars (struct lexer *lexer, const struct dictionary *dict, struct cmd_examine *cmd)
 {
   int success;
   struct factor *sf = xmalloc (sizeof *sf);
 
-  if ((token != T_ID || dict_lookup_var (default_dict, tokid) == NULL)
-      && token != T_ALL)
+  if ( (lex_token (lexer) != T_ID || dict_lookup_var (dict, lex_tokid (lexer)) == NULL)
+      && lex_token (lexer) != T_ALL)
     {
       free ( sf ) ;
       return 2;
     }
 
 
-  sf->indep_var[0] = parse_variable();
+  sf->indep_var[0] = parse_variable (lexer, dict);
   sf->indep_var[1] = 0;
 
-  if ( token == T_BY ) 
+  if ( lex_token (lexer) == T_BY )
     {
 
-      lex_match(T_BY);
+      lex_match (lexer, T_BY);
 
-      if ((token != T_ID || dict_lookup_var (default_dict, tokid) == NULL)
-         && token != T_ALL)
+      if ( (lex_token (lexer) != T_ID || dict_lookup_var (dict, lex_tokid (lexer)) == NULL)
+         && lex_token (lexer) != T_ALL)
        {
          free ( sf ) ;
          return 2;
        }
 
-      sf->indep_var[1] = parse_variable();
+      sf->indep_var[1] = parse_variable (lexer, dict);
 
     }
 
 
-  sf->fstats = hsh_create(4,
+  sf->fstats = hsh_create (4,
                          (hsh_compare_func *) factor_statistics_compare,
                          (hsh_hash_func *) factor_statistics_hash,
                          (hsh_free_func *) factor_statistics_free,
@@ -586,16 +599,16 @@ examine_parse_independent_vars(struct cmd_examine *cmd)
 
   sf->next = factors;
   factors = sf;
-  
-  lex_match(',');
 
-  if ( token == '.' || token == '/' ) 
+  lex_match (lexer, ',');
+
+  if ( lex_token (lexer) == '.' || lex_token (lexer) == '/' )
     return 1;
 
-  success =  examine_parse_independent_vars(cmd);
-  
-  if ( success != 1 ) 
-    free ( sf ) ; 
+  success =  examine_parse_independent_vars (lexer, dict, cmd);
+
+  if ( success != 1 )
+    free ( sf ) ;
 
   return success;
 }
@@ -603,183 +616,211 @@ examine_parse_independent_vars(struct cmd_examine *cmd)
 
 
 
-void populate_percentiles(struct tab_table *tbl, int col, int row, 
+void populate_percentiles (struct tab_table *tbl, int col, int row,
                          const struct metrics *m);
 
-void populate_descriptives(struct tab_table *t, int col, int row, 
+void populate_descriptives (struct tab_table *t, int col, int row,
                           const struct metrics *fs);
 
-void populate_extremes(struct tab_table *t, int col, int row, int n, 
+void populate_extremes (struct tab_table *t, int col, int row, int n,
                       const struct metrics *m);
 
-void populate_summary(struct tab_table *t, int col, int row,
+void populate_summary (struct tab_table *t, int col, int row,
                      const struct metrics *m);
 
 
 
 
-static int bad_weight_warn = 1;
-
-
 /* Perform calculations for the sub factors */
 void
-factor_calc(struct ccase *c, int case_no, double weight, int case_missing)
+factor_calc (const struct ccase *c, int case_no, double weight,
+            int case_missing)
 {
   size_t v;
   struct factor *fctr = factors;
 
-  while ( fctr) 
+  while ( fctr)
     {
       struct factor_statistics **foo ;
-      union value indep_vals[2] ;
+      union value *indep_vals[2] ;
 
-      indep_vals[0] = * case_data(c, fctr->indep_var[0]->fv);
+      indep_vals[0] = value_dup (
+                                case_data (c, fctr->indep_var[0]),
+                                var_get_width (fctr->indep_var[0])
+                                );
 
-      if ( fctr->indep_var[1] ) 
-       indep_vals[1] = * case_data(c, fctr->indep_var[1]->fv);
+      if ( fctr->indep_var[1] )
+       indep_vals[1] = value_dup (
+                                  case_data (c, fctr->indep_var[1]),
+                                  var_get_width (fctr->indep_var[1])
+                                  );
       else
-       indep_vals[1].f = SYSMIS;
+       {
+         const union value sm = {SYSMIS};
+         indep_vals[1] = value_dup (&sm, 0);
+       }
 
-      assert(fctr->fstats);
+      assert (fctr->fstats);
 
-      foo = ( struct factor_statistics ** ) 
-       hsh_probe(fctr->fstats, (void *) &indep_vals);
+      foo = ( struct factor_statistics ** )
+       hsh_probe (fctr->fstats, (void *) &indep_vals);
 
-      if ( !*foo ) 
+      if ( !*foo )
        {
 
-         *foo = create_factor_statistics(n_dependent_vars, 
-                                         &indep_vals[0],
-                                         &indep_vals[1]);
+         *foo = create_factor_statistics (n_dependent_vars,
+                                         indep_vals[0],
+                                         indep_vals[1]);
 
-         for ( v =  0 ; v  < n_dependent_vars ; ++v ) 
+         for ( v =  0 ; v  < n_dependent_vars ; ++v )
            {
-             metrics_precalc( &(*foo)->m[v] );
+             metrics_precalc ( & (*foo)->m[v] );
            }
 
        }
+      else
+       {
+         free (indep_vals[0]);
+         free (indep_vals[1]);
+       }
 
-      for ( v =  0 ; v  < n_dependent_vars ; ++v ) 
+      for ( v =  0 ; v  < n_dependent_vars ; ++v )
        {
          const struct variable *var = dependent_vars[v];
-         const union value *val = case_data (c, var->fv);
+         union value *val = value_dup (
+                                       case_data (c, var),
+                                       var_get_width (var)
+                                       );
+
+         if (case_missing || var_is_value_missing (var, val, exclude_values))
+           {
+             free (val);
+             continue;
+           }
 
-         if ( value_is_missing (&var->miss, val) || case_missing ) 
-           val = 0;
-         
-         metrics_calc( &(*foo)->m[v], val, weight, case_no);
-         
+         metrics_calc ( & (*foo)->m[v], val, weight, case_no);
+
+         free (val);
        }
 
       fctr = fctr->next;
     }
-
-
 }
 
-static bool 
-run_examine(const struct ccase *first, const struct casefile *cf, void *cmd_ )
+static void
+run_examine (struct cmd_examine *cmd, struct casereader *input,
+             struct dataset *ds)
 {
-  struct casereader *r;
+  struct dictionary *dict = dataset_dict (ds);
+  casenumber case_no;
   struct ccase c;
   int v;
-
-  const struct cmd_examine *cmd = (struct cmd_examine *) cmd_;
+  bool ok;
 
   struct factor *fctr;
 
-  output_split_file_values (first);
+  if (!casereader_peek (input, 0, &c))
+    return;
+  output_split_file_values (ds, &c);
+  case_destroy (&c);
 
-  /* Make sure we haven't got rubbish left over from a 
-     previous split */
+  input = casereader_create_filter_weight (input, dict, NULL, NULL);
+  input = casereader_create_counter (input, &case_no, 0);
+
+  /* Make sure we haven't got rubbish left over from a
+     previous split. */
   fctr = factors;
-  while (fctr) 
+  while (fctr)
     {
       struct factor *next = fctr->next;
 
-      hsh_clear(fctr->fstats);
+      hsh_clear (fctr->fstats);
 
       fctr->fs = 0;
 
       fctr = next;
     }
 
+  for ( v = 0 ; v < n_dependent_vars ; ++v )
+    metrics_precalc (&totals[v]);
 
-
-  for ( v = 0 ; v < n_dependent_vars ; ++v ) 
-    metrics_precalc(&totals[v]);
-
-  for(r = casefile_get_reader (cf);
-      casereader_read (r, &c) ;
-      case_destroy (&c) ) 
+  for (; casereader_read (input, &c); case_destroy (&c))
     {
-      int case_missing=0;
-      const int case_no = casereader_cnum(r);
-
-      const double weight = 
-       dict_get_case_weight(default_dict, &c, &bad_weight_warn);
+      int case_missing = 0;
+      const double weight = dict_get_case_weight (dict, &c, NULL);
 
-      if ( cmd->miss == XMN_LISTWISE ) 
+      if ( cmd->miss == XMN_LISTWISE )
        {
-         for ( v = 0 ; v < n_dependent_vars ; ++v ) 
+         for ( v = 0 ; v < n_dependent_vars ; ++v )
            {
              const struct variable *var = dependent_vars[v];
-             const union value *val = case_data (&c, var->fv);
+             union value *val = value_dup (
+                                                 case_data (&c, var),
+                                                 var_get_width (var)
+                                                 );
 
-             if ( value_is_missing(&var->miss, val))
+             if ( var_is_value_missing (var, val, exclude_values))
                case_missing = 1;
-                  
+
+             free (val);
            }
        }
 
-      for ( v = 0 ; v < n_dependent_vars ; ++v ) 
+      for ( v = 0 ; v < n_dependent_vars ; ++v )
        {
          const struct variable *var = dependent_vars[v];
-         const union value *val = case_data (&c, var->fv);
+         union value *val = value_dup (
+                                       case_data (&c, var),
+                                       var_get_width (var)
+                                       );
 
-         if ( value_is_missing(&var->miss, val) || case_missing ) 
-           val = 0;
+         if ( var_is_value_missing (var, val, exclude_values)
+               || case_missing )
+           {
+             free (val) ;
+             continue ;
+           }
 
-         metrics_calc(&totals[v], val, weight, case_no);
-    
-       }
+         metrics_calc (&totals[v], val, weight, case_no);
 
-      factor_calc(&c, case_no, weight, case_missing);
+         free (val);
+       }
 
+      factor_calc (&c, case_no, weight, case_missing);
     }
-
+  ok = casereader_destroy (input);
 
   for ( v = 0 ; v < n_dependent_vars ; ++v)
     {
       fctr = factors;
-      while ( fctr ) 
+      while ( fctr )
        {
          struct hsh_iterator hi;
          struct factor_statistics *fs;
 
-         for ( fs = hsh_first(fctr->fstats, &hi);
+         for ( fs = hsh_first (fctr->fstats, &hi);
                fs != 0 ;
-               fs = hsh_next(fctr->fstats, &hi))
+               fs = hsh_next (fctr->fstats, &hi))
            {
-             
-             fs->m[v].ptile_hash = list_to_ptile_hash(&percentile_list);
+
+             fs->m[v].ptile_hash = list_to_ptile_hash (&percentile_list);
              fs->m[v].ptile_alg = percentile_algorithm;
-             metrics_postcalc(&fs->m[v]);
+             metrics_postcalc (&fs->m[v]);
            }
 
          fctr = fctr->next;
        }
 
-      totals[v].ptile_hash = list_to_ptile_hash(&percentile_list);
+      totals[v].ptile_hash = list_to_ptile_hash (&percentile_list);
       totals[v].ptile_alg = percentile_algorithm;
-      metrics_postcalc(&totals[v]);
+      metrics_postcalc (&totals[v]);
     }
 
 
   /* Make sure that the combination of factors are complete */
 
   fctr = factors;
-  while ( fctr ) 
+  while ( fctr )
     {
       struct hsh_iterator hi;
       struct hsh_iterator hi0;
@@ -790,84 +831,83 @@ run_examine(const struct ccase *first, const struct casefile *cf, void *cmd_ )
       struct hsh_table *idh1=0;
       union value *val0;
       union value *val1;
-         
-      idh0 = hsh_create(4, (hsh_compare_func *) compare_values,
-                       (hsh_hash_func *) hash_value,
+
+      idh0 = hsh_create (4, (hsh_compare_func *) compare_values,
+                        (hsh_hash_func *) hash_value,
                        0,0);
 
-      idh1 = hsh_create(4, (hsh_compare_func *) compare_values,
-                       (hsh_hash_func *) hash_value,
+      idh1 = hsh_create (4, (hsh_compare_func *) compare_values,
+                        (hsh_hash_func *) hash_value,
                        0,0);
 
 
-      for ( fs = hsh_first(fctr->fstats, &hi);
+      for ( fs = hsh_first (fctr->fstats, &hi);
            fs != 0 ;
-           fs = hsh_next(fctr->fstats, &hi))
+           fs = hsh_next (fctr->fstats, &hi))
        {
-         hsh_insert(idh0,(void *) &fs->id[0]);
-         hsh_insert(idh1,(void *) &fs->id[1]);
+         hsh_insert (idh0, (void *) &fs->id[0]);
+         hsh_insert (idh1, (void *) &fs->id[1]);
        }
 
       /* Ensure that the factors combination is complete */
-      for ( val0 = hsh_first(idh0, &hi0);
+      for ( val0 = hsh_first (idh0, &hi0);
            val0 != 0 ;
-           val0 = hsh_next(idh0, &hi0))
+           val0 = hsh_next (idh0, &hi0))
        {
-         for ( val1 = hsh_first(idh1, &hi1);
+         for ( val1 = hsh_first (idh1, &hi1);
                val1 != 0 ;
-               val1 = hsh_next(idh1, &hi1))
+               val1 = hsh_next (idh1, &hi1))
            {
              struct factor_statistics **ffs;
              union value key[2];
              key[0] = *val0;
              key[1] = *val1;
-                 
-             ffs = (struct factor_statistics **) 
-               hsh_probe(fctr->fstats, (void *) &key );
+
+             ffs = (struct factor_statistics **)
+               hsh_probe (fctr->fstats, (void *) &key );
 
              if ( !*ffs ) {
                size_t i;
-               (*ffs) = create_factor_statistics (n_dependent_vars,
+                (*ffs) = create_factor_statistics (n_dependent_vars,
                                                   &key[0], &key[1]);
-               for ( i = 0 ; i < n_dependent_vars ; ++i ) 
-                 metrics_precalc( &(*ffs)->m[i]);
+               for ( i = 0 ; i < n_dependent_vars ; ++i )
+                 metrics_precalc ( & (*ffs)->m[i]);
              }
            }
        }
 
-      hsh_destroy(idh0);
-      hsh_destroy(idh1);
+      hsh_destroy (idh0);
+      hsh_destroy (idh1);
 
-      fctr->fs = (struct factor_statistics **) hsh_sort_copy(fctr->fstats);
+      fctr->fs = (struct factor_statistics **) hsh_sort_copy (fctr->fstats);
 
       fctr = fctr->next;
     }
 
-  output_examine();
+  if (ok)
+    output_examine ();
 
 
-  if ( totals ) 
+  if ( totals )
     {
       size_t i;
-      for ( i = 0 ; i < n_dependent_vars ; ++i ) 
+      for ( i = 0 ; i < n_dependent_vars ; ++i )
        {
-         metrics_destroy(&totals[i]);
+         metrics_destroy (&totals[i]);
        }
     }
-
-  return true;
 }
 
 
 static void
-show_summary(struct variable **dependent_var, int n_dep_var, 
+show_summary (const struct variable **dependent_var, int n_dep_var,
             const struct factor *fctr)
 {
   static const char *subtitle[]=
     {
-      N_("Valid"),
-      N_("Missing"),
-      N_("Total")
+      N_ ("Valid"),
+      N_ ("Missing"),
+      N_ ("Total")
     };
 
   int i;
@@ -882,7 +922,7 @@ show_summary(struct variable **dependent_var, int n_dep_var,
   if ( fctr )
     {
       heading_columns = 2;
-      n_factors = hsh_count(fctr->fstats);
+      n_factors = hsh_count (fctr->fstats);
       n_rows = n_dep_var * n_factors ;
 
       if ( fctr->indep_var[1] )
@@ -902,16 +942,16 @@ show_summary(struct variable **dependent_var, int n_dep_var,
   tab_headers (tbl, heading_columns, 0, heading_rows, 0);
 
   tab_dim (tbl, tab_natural_dimensions);
-  
+
   /* Outline the box */
-  tab_box (tbl, 
+  tab_box (tbl,
           TAL_2, TAL_2,
           -1, -1,
           0, 0,
           n_cols - 1, n_rows - 1);
 
   /* Vertical lines for the data only */
-  tab_box (tbl, 
+  tab_box (tbl,
           -1, -1,
           -1, TAL_1,
           heading_columns, 0,
@@ -925,30 +965,30 @@ show_summary(struct variable **dependent_var, int n_dep_var,
   tab_vline (tbl, TAL_2, heading_columns, 0, n_rows - 1);
 
 
-  tab_title (tbl, _("Case Processing Summary"));
-  
+  tab_title (tbl, _ ("Case Processing Summary"));
+
 
-  tab_joint_text(tbl, heading_columns, 0, 
+  tab_joint_text (tbl, heading_columns, 0,
                 n_cols -1, 0,
                 TAB_CENTER | TAT_TITLE,
-                _("Cases"));
+                _ ("Cases"));
 
   /* Remove lines ... */
-  tab_box (tbl, 
+  tab_box (tbl,
           -1, -1,
           TAL_0, TAL_0,
           heading_columns, 0,
           n_cols - 1, 0);
 
-  for ( i = 0 ; i < 3 ; ++i ) 
+  for ( i = 0 ; i < 3 ; ++i )
     {
-      tab_text (tbl, heading_columns + i*2 , 2, TAB_CENTER | TAT_TITLE, 
-               _("N"));
+      tab_text (tbl, heading_columns + i*2 , 2, TAB_CENTER | TAT_TITLE,
+               _ ("N"));
 
-      tab_text (tbl, heading_columns + i*2 + 1, 2, TAB_CENTER | TAT_TITLE, 
-               _("Percent"));
+      tab_text (tbl, heading_columns + i*2 + 1, 2, TAB_CENTER | TAT_TITLE,
+               _ ("Percent"));
 
-      tab_joint_text(tbl, heading_columns + i*2 , 1,
+      tab_joint_text (tbl, heading_columns + i*2 , 1,
                     heading_columns + i*2 + 1, 1,
                     TAB_CENTER | TAT_TITLE,
                     subtitle[i]);
@@ -962,39 +1002,39 @@ show_summary(struct variable **dependent_var, int n_dep_var,
 
 
   /* Titles for the independent variables */
-  if ( fctr ) 
+  if ( fctr )
     {
-      tab_text (tbl, 1, heading_rows - 1, TAB_CENTER | TAT_TITLE, 
-               var_to_string(fctr->indep_var[0]));
+      tab_text (tbl, 1, heading_rows - 1, TAB_CENTER | TAT_TITLE,
+               var_to_string (fctr->indep_var[0]));
 
-      if ( fctr->indep_var[1] ) 
+      if ( fctr->indep_var[1] )
        {
-         tab_text (tbl, 2, heading_rows - 1, TAB_CENTER | TAT_TITLE, 
-                   var_to_string(fctr->indep_var[1]));
+         tab_text (tbl, 2, heading_rows - 1, TAB_CENTER | TAT_TITLE,
+                   var_to_string (fctr->indep_var[1]));
        }
-               
+
     }
 
 
-  for ( i = 0 ; i < n_dep_var ; ++i ) 
+  for ( i = 0 ; i < n_dep_var ; ++i )
     {
       int n_factors = 1;
-      if ( fctr ) 
-       n_factors = hsh_count(fctr->fstats);
-      
-
-      if ( i > 0 ) 
-       tab_hline(tbl, TAL_1, 0, n_cols -1 , i * n_factors + heading_rows);
-      
-      tab_text (tbl, 
+      if ( fctr )
+       n_factors = hsh_count (fctr->fstats);
+
+
+      if ( i > 0 )
+       tab_hline (tbl, TAL_1, 0, n_cols -1 , i * n_factors + heading_rows);
+
+      tab_text (tbl,
                0, i * n_factors + heading_rows,
-               TAB_LEFT | TAT_TITLE, 
-               var_to_string(dependent_var[i])
+               TAB_LEFT | TAT_TITLE,
+               var_to_string (dependent_var[i])
                );
 
 
-      if ( !fctr ) 
-       populate_summary(tbl, heading_columns, 
+      if ( !fctr )
+       populate_summary (tbl, heading_columns,
                         (i * n_factors) + heading_rows,
                         &totals[i]);
 
@@ -1003,46 +1043,47 @@ show_summary(struct variable **dependent_var, int n_dep_var,
        {
          struct factor_statistics **fs = fctr->fs;
          int count = 0 ;
+         const union value *prev = NULL;
 
-         while (*fs) 
+         while (*fs)
            {
-             static union value prev;
-             
-             if ( 0 != compare_values(&prev, &(*fs)->id[0], 
-                                      fctr->indep_var[0]->width))
+             if ( !prev ||
+                  0 != compare_values (prev, (*fs)->id[0],
+                                  var_get_width (fctr->indep_var[0])))
                {
-                 tab_text (tbl, 
+                 tab_text (tbl,
                            1,
-                           (i * n_factors ) + count + 
+                           (i * n_factors ) + count +
                            heading_rows,
-                           TAB_LEFT | TAT_TITLE, 
-                           value_to_string(&(*fs)->id[0], fctr->indep_var[0])
+                           TAB_LEFT | TAT_TITLE,
+                           var_get_value_name (fctr->indep_var[0],
+                                                (*fs)->id[0])
                            );
 
-                 if (fctr->indep_var[1] && count > 0 ) 
-                   tab_hline(tbl, TAL_1, 1, n_cols - 1, 
+                 if (fctr->indep_var[1] && count > 0 )
+                   tab_hline (tbl, TAL_1, 1, n_cols - 1,
                              (i * n_factors ) + count + heading_rows);
 
                }
-             
+
              prev = (*fs)->id[0];
 
 
-             if ( fctr->indep_var[1]) 
-               tab_text (tbl, 
+             if ( fctr->indep_var[1])
+               tab_text (tbl,
                          2,
-                         (i * n_factors ) + count + 
+                         (i * n_factors ) + count +
                          heading_rows,
-                         TAB_LEFT | TAT_TITLE, 
-                         value_to_string(&(*fs)->id[1], fctr->indep_var[1])
+                         TAB_LEFT | TAT_TITLE,
+                         var_get_value_name (fctr->indep_var[1], (*fs)->id[1])
                          );
 
-             populate_summary(tbl, heading_columns, 
-                              (i * n_factors) + count 
+             populate_summary (tbl, heading_columns,
+                              (i * n_factors) + count
                               + heading_rows,
-                              &(*fs)->m[i]);
+                              & (*fs)->m[i]);
 
-             count++ ; 
+             count++ ;
              fs++;
            }
        }
@@ -1052,39 +1093,39 @@ show_summary(struct variable **dependent_var, int n_dep_var,
 }
 
 
-void 
-populate_summary(struct tab_table *t, int col, int row,
+void
+populate_summary (struct tab_table *t, int col, int row,
                 const struct metrics *m)
 
 {
-  const double total = m->n + m->n_missing ; 
+  const double total = m->n + m->n_missing ;
 
-  tab_float(t, col + 0, row + 0, TAB_RIGHT, m->n, 8, 0);
-  tab_float(t, col + 2, row + 0, TAB_RIGHT, m->n_missing, 8, 0);
-  tab_float(t, col + 4, row + 0, TAB_RIGHT, total, 8, 0);
+  tab_float (t, col + 0, row + 0, TAB_RIGHT, m->n, 8, 0);
+  tab_float (t, col + 2, row + 0, TAB_RIGHT, m->n_missing, 8, 0);
+  tab_float (t, col + 4, row + 0, TAB_RIGHT, total, 8, 0);
 
 
   if ( total > 0 ) {
-    tab_text (t, col + 1, row + 0, TAB_RIGHT | TAT_PRINTF, "%2.0f%%", 
+    tab_text (t, col + 1, row + 0, TAB_RIGHT | TAT_PRINTF, "%2.0f%%",
              100.0 * m->n / total );
 
-    tab_text (t, col + 3, row + 0, TAB_RIGHT | TAT_PRINTF, "%2.0f%%", 
+    tab_text (t, col + 3, row + 0, TAB_RIGHT | TAT_PRINTF, "%2.0f%%",
              100.0 * m->n_missing / total );
 
     /* This seems a bit pointless !!! */
-    tab_text (t, col + 5, row + 0, TAB_RIGHT | TAT_PRINTF, "%2.0f%%", 
+    tab_text (t, col + 5, row + 0, TAB_RIGHT | TAT_PRINTF, "%2.0f%%",
              100.0 * total / total );
 
 
   }
 
 
-}  
+}
 
 
 
-static void 
-show_extremes(struct variable **dependent_var, int n_dep_var, 
+static void
+show_extremes (const struct variable **dependent_var, int n_dep_var,
              const struct factor *fctr, int n_extremities)
 {
   int i;
@@ -1099,7 +1140,7 @@ show_extremes(struct variable **dependent_var, int n_dep_var,
   if ( fctr )
     {
       heading_columns = 2;
-      n_factors = hsh_count(fctr->fstats);
+      n_factors = hsh_count (fctr->fstats);
 
       n_rows = n_dep_var * 2 * n_extremities * n_factors;
 
@@ -1121,9 +1162,9 @@ show_extremes(struct variable **dependent_var, int n_dep_var,
   tab_headers (tbl, heading_columns, 0, heading_rows, 0);
 
   tab_dim (tbl, tab_natural_dimensions);
-  
+
   /* Outline the box, No internal lines*/
-  tab_box (tbl, 
+  tab_box (tbl,
           TAL_2, TAL_2,
           -1, -1,
           0, 0,
@@ -1131,40 +1172,40 @@ show_extremes(struct variable **dependent_var, int n_dep_var,
 
   tab_hline (tbl, TAL_2, 0, n_cols - 1, heading_rows );
 
-  tab_title (tbl, _("Extreme Values"));
+  tab_title (tbl, _ ("Extreme Values"));
 
   tab_vline (tbl, TAL_2, n_cols - 2, 0, n_rows -1);
   tab_vline (tbl, TAL_1, n_cols - 1, 0, n_rows -1);
 
-  if ( fctr ) 
+  if ( fctr )
     {
-      tab_text (tbl, 1, heading_rows - 1, TAB_CENTER | TAT_TITLE, 
-               var_to_string(fctr->indep_var[0]));
+      tab_text (tbl, 1, heading_rows - 1, TAB_CENTER | TAT_TITLE,
+               var_to_string (fctr->indep_var[0]));
 
-      if ( fctr->indep_var[1] ) 
-       tab_text (tbl, 2, heading_rows - 1, TAB_CENTER | TAT_TITLE, 
-                 var_to_string(fctr->indep_var[1]));
+      if ( fctr->indep_var[1] )
+       tab_text (tbl, 2, heading_rows - 1, TAB_CENTER | TAT_TITLE,
+                 var_to_string (fctr->indep_var[1]));
     }
 
-  tab_text (tbl, n_cols - 1, 0, TAB_CENTER | TAT_TITLE, _("Value"));
-  tab_text (tbl, n_cols - 2, 0, TAB_CENTER | TAT_TITLE, _("Case Number"));
+  tab_text (tbl, n_cols - 1, 0, TAB_CENTER | TAT_TITLE, _ ("Value"));
+  tab_text (tbl, n_cols - 2, 0, TAB_CENTER | TAT_TITLE, _ ("Case Number"));
 
-  for ( i = 0 ; i < n_dep_var ; ++i ) 
+  for ( i = 0 ; i < n_dep_var ; ++i )
     {
 
-      if ( i > 0 ) 
-       tab_hline(tbl, TAL_1, 0, n_cols -1 , 
+      if ( i > 0 )
+       tab_hline (tbl, TAL_1, 0, n_cols -1 ,
                  i * 2 * n_extremities * n_factors + heading_rows);
-      
+
       tab_text (tbl, 0,
                i * 2 * n_extremities * n_factors  + heading_rows,
-               TAB_LEFT | TAT_TITLE, 
-               var_to_string(dependent_var[i])
+               TAB_LEFT | TAT_TITLE,
+               var_to_string (dependent_var[i])
                );
 
 
-      if ( !fctr ) 
-       populate_extremes(tbl, heading_columns - 2, 
+      if ( !fctr )
+       populate_extremes (tbl, heading_columns - 2,
                          i * 2 * n_extremities * n_factors  + heading_rows,
                          n_extremities, &totals[i]);
 
@@ -1172,87 +1213,87 @@ show_extremes(struct variable **dependent_var, int n_dep_var,
        {
          struct factor_statistics **fs = fctr->fs;
          int count = 0 ;
+         const union value *prev  = NULL;
 
-         while (*fs) 
+         while (*fs)
            {
-             static union value prev ;
-
-             const int row = heading_rows + ( 2 * n_extremities )  * 
-               ( ( i  * n_factors  ) +  count );
+             const int row = heading_rows + ( 2 * n_extremities )  *
+                ( ( i  * n_factors  ) +  count );
 
 
-             if ( 0 != compare_values(&prev, &(*fs)->id[0], 
-                                      fctr->indep_var[0]->width))
+             if ( !prev || 0 != compare_values (prev, (*fs)->id[0],
+                                        var_get_width (fctr->indep_var[0])))
                {
-                 
-                 if ( count > 0 ) 
+
+                 if ( count > 0 )
                    tab_hline (tbl, TAL_1, 1, n_cols - 1, row);
 
-                 tab_text (tbl, 
+                 tab_text (tbl,
                            1, row,
-                           TAB_LEFT | TAT_TITLE, 
-                           value_to_string(&(*fs)->id[0], fctr->indep_var[0])
+                           TAB_LEFT | TAT_TITLE,
+                           var_get_value_name (fctr->indep_var[0],
+                                                (*fs)->id[0])
                            );
                }
 
              prev = (*fs)->id[0];
 
-             if (fctr->indep_var[1] && count > 0 ) 
-               tab_hline(tbl, TAL_1, 2, n_cols - 1, row);
+             if (fctr->indep_var[1] && count > 0 )
+               tab_hline (tbl, TAL_1, 2, n_cols - 1, row);
 
-             if ( fctr->indep_var[1]) 
+             if ( fctr->indep_var[1])
                tab_text (tbl, 2, row,
-                         TAB_LEFT | TAT_TITLE, 
-                         value_to_string(&(*fs)->id[1], fctr->indep_var[1])
+                         TAB_LEFT | TAT_TITLE,
+                         var_get_value_name (fctr->indep_var[1], (*fs)->id[1])
                          );
 
-             populate_extremes(tbl, heading_columns - 2, 
+             populate_extremes (tbl, heading_columns - 2,
                                row, n_extremities,
-                               &(*fs)->m[i]);
+                               & (*fs)->m[i]);
 
-             count++ ; 
+             count++ ;
              fs++;
            }
        }
     }
 
-  tab_submit(tbl);
+  tab_submit (tbl);
 }
 
 
 
 /* Fill in the extremities table */
-void 
-populate_extremes(struct tab_table *t, 
+void
+populate_extremes (struct tab_table *t,
                  int col, int row, int n, const struct metrics *m)
 {
   int extremity;
   int idx=0;
 
 
-  tab_text(t, col, row,
+  tab_text (t, col, row,
           TAB_RIGHT | TAT_TITLE ,
-          _("Highest")
+          _ ("Highest")
           );
 
-  tab_text(t, col, row + n ,
+  tab_text (t, col, row + n ,
           TAB_RIGHT | TAT_TITLE ,
-          _("Lowest")
+          _ ("Lowest")
           );
 
 
-  tab_hline(t, TAL_1, col, col + 3, row + n );
-           
-  for (extremity = 0; extremity < n ; ++extremity ) 
+  tab_hline (t, TAL_1, col, col + 3, row + n );
+
+  for (extremity = 0; extremity < n ; ++extremity )
     {
       /* Highest */
-      tab_float(t, col + 1, row + extremity,
+      tab_float (t, col + 1, row + extremity,
                TAB_RIGHT,
                extremity + 1, 8, 0);
 
 
       /* Lowest */
-      tab_float(t, col + 1, row + extremity + n,
+      tab_float (t, col + 1, row + extremity + n,
                TAB_RIGHT,
                extremity + 1, 8, 0);
 
@@ -1260,27 +1301,27 @@ populate_extremes(struct tab_table *t,
 
 
   /* Lowest */
-  for (idx = 0, extremity = 0; extremity < n && idx < m->n_data ; ++idx ) 
+  for (idx = 0, extremity = 0; extremity < n && idx < m->n_data ; ++idx )
     {
       int j;
       const struct weighted_value *wv = m->wvp[idx];
       struct case_node *cn = wv->case_nos;
 
-      
+
       for (j = 0 ; j < wv->w ; ++j  )
        {
-         if ( extremity + j >= n ) 
+         if ( extremity + j >= n )
            break ;
 
-         tab_float(t, col + 3, row + extremity + j  + n,
+         tab_float (t, col + 3, row + extremity + j  + n,
                    TAB_RIGHT,
                    wv->v.f, 8, 2);
 
-         tab_float(t, col + 2, row + extremity + j  + n,
+         tab_float (t, col + 2, row + extremity + j  + n,
                    TAB_RIGHT,
                    cn->num, 8, 0);
 
-         if ( cn->next ) 
+         if ( cn->next )
            cn = cn->next;
 
        }
@@ -1290,7 +1331,7 @@ populate_extremes(struct tab_table *t,
 
 
   /* Highest */
-  for (idx = m->n_data - 1, extremity = 0; extremity < n && idx >= 0; --idx ) 
+  for (idx = m->n_data - 1, extremity = 0; extremity < n && idx >= 0; --idx )
     {
       int j;
       const struct weighted_value *wv = m->wvp[idx];
@@ -1298,18 +1339,18 @@ populate_extremes(struct tab_table *t,
 
       for (j = 0 ; j < wv->w ; ++j  )
        {
-         if ( extremity + j >= n ) 
+         if ( extremity + j >= n )
            break ;
 
-         tab_float(t, col + 3, row + extremity + j,
+         tab_float (t, col + 3, row + extremity + j,
                    TAB_RIGHT,
                    wv->v.f, 8, 2);
 
-         tab_float(t, col + 2, row + extremity + j,
+         tab_float (t, col + 2, row + extremity + j,
                    TAB_RIGHT,
                    cn->num, 8, 0);
 
-         if ( cn->next ) 
+         if ( cn->next )
            cn = cn->next;
 
        }
@@ -1321,8 +1362,8 @@ populate_extremes(struct tab_table *t,
 
 /* Show the descriptives table */
 void
-show_descriptives(struct variable **dependent_var, 
-                 int n_dep_var, 
+show_descriptives (const struct variable **dependent_var,
+                 int n_dep_var,
                  struct factor *fctr)
 {
   int i;
@@ -1340,7 +1381,7 @@ show_descriptives(struct variable **dependent_var,
   if ( fctr )
     {
       heading_columns = 4;
-      n_factors = hsh_count(fctr->fstats);
+      n_factors = hsh_count (fctr->fstats);
 
       n_rows = n_dep_var * n_stat_rows * n_factors;
 
@@ -1365,7 +1406,7 @@ show_descriptives(struct variable **dependent_var,
   tab_dim (tbl, tab_natural_dimensions);
 
   /* Outline the box and have no internal lines*/
-  tab_box (tbl, 
+  tab_box (tbl,
           TAL_2, TAL_2,
           -1, -1,
           0, 0,
@@ -1377,192 +1418,188 @@ show_descriptives(struct variable **dependent_var,
   tab_vline (tbl, TAL_2, n_cols - 2, 0, n_rows - 1);
   tab_vline (tbl, TAL_1, n_cols - 1, 0, n_rows - 1);
 
-  tab_text (tbl, n_cols - 2, 0, TAB_CENTER | TAT_TITLE, _("Statistic"));
-  tab_text (tbl, n_cols - 1, 0, TAB_CENTER | TAT_TITLE, _("Std. Error"));
+  tab_text (tbl, n_cols - 2, 0, TAB_CENTER | TAT_TITLE, _ ("Statistic"));
+  tab_text (tbl, n_cols - 1, 0, TAB_CENTER | TAT_TITLE, _ ("Std. Error"));
 
-  tab_title (tbl, _("Descriptives"));
+  tab_title (tbl, _ ("Descriptives"));
 
 
-  for ( i = 0 ; i < n_dep_var ; ++i ) 
+  for ( i = 0 ; i < n_dep_var ; ++i )
     {
       const int row = heading_rows + i * n_stat_rows * n_factors ;
 
       if ( i > 0 )
-       tab_hline(tbl, TAL_1, 0, n_cols - 1, row );
+       tab_hline (tbl, TAL_1, 0, n_cols - 1, row );
 
       tab_text (tbl, 0,
                i * n_stat_rows * n_factors  + heading_rows,
-               TAB_LEFT | TAT_TITLE, 
-               var_to_string(dependent_var[i])
+               TAB_LEFT | TAT_TITLE,
+               var_to_string (dependent_var[i])
                );
 
 
       if ( fctr  )
        {
+         const union value *prev = NULL;
+
          struct factor_statistics **fs = fctr->fs;
          int count = 0;
 
-         tab_text (tbl, 1, heading_rows - 1, TAB_CENTER | TAT_TITLE, 
-                   var_to_string(fctr->indep_var[0]));
+         tab_text (tbl, 1, heading_rows - 1, TAB_CENTER | TAT_TITLE,
+                   var_to_string (fctr->indep_var[0]));
 
 
          if ( fctr->indep_var[1])
-           tab_text (tbl, 2, heading_rows - 1, TAB_CENTER | TAT_TITLE, 
-                     var_to_string(fctr->indep_var[1]));
+           tab_text (tbl, 2, heading_rows - 1, TAB_CENTER | TAT_TITLE,
+                     var_to_string (fctr->indep_var[1]));
 
-         while( *fs ) 
+         while ( *fs )
            {
+             const int row = heading_rows + n_stat_rows  *
+                ( ( i  * n_factors  ) +  count );
 
-             static union value prev ;
-
-             const int row = heading_rows + n_stat_rows  * 
-               ( ( i  * n_factors  ) +  count );
 
-
-             if ( 0 != compare_values(&prev, &(*fs)->id[0], 
-                                      fctr->indep_var[0]->width))
+             if ( !prev || 0 != compare_values (prev, (*fs)->id[0],
+                                        var_get_width (fctr->indep_var[0])))
                {
-                 
-                 if ( count > 0 ) 
+
+                 if ( count > 0 )
                    tab_hline (tbl, TAL_1, 1, n_cols - 1, row);
 
-                 tab_text (tbl, 
+                 tab_text (tbl,
                            1, row,
-                           TAB_LEFT | TAT_TITLE, 
-                           value_to_string(&(*fs)->id[0], fctr->indep_var[0])
+                           TAB_LEFT | TAT_TITLE,
+                           var_get_value_name (fctr->indep_var[0],
+                                                (*fs)->id[0])
                            );
                }
 
              prev = (*fs)->id[0];
 
-             if (fctr->indep_var[1] && count > 0 ) 
-               tab_hline(tbl, TAL_1, 2, n_cols - 1, row);
+             if (fctr->indep_var[1] && count > 0 )
+               tab_hline (tbl, TAL_1, 2, n_cols - 1, row);
 
-             if ( fctr->indep_var[1]) 
+             if ( fctr->indep_var[1])
                tab_text (tbl, 2, row,
-                         TAB_LEFT | TAT_TITLE, 
-                         value_to_string(&(*fs)->id[1], fctr->indep_var[1])
+                         TAB_LEFT | TAT_TITLE,
+                         var_get_value_name (fctr->indep_var[1], (*fs)->id[1])
                          );
 
-             populate_descriptives(tbl, heading_columns - 2, 
-                                   row, &(*fs)->m[i]);
+             populate_descriptives (tbl, heading_columns - 2,
+                                   row, & (*fs)->m[i]);
 
-             count++ ; 
+             count++ ;
              fs++;
            }
 
        }
 
-      else 
+      else
        {
-         
-         populate_descriptives(tbl, heading_columns - 2, 
+
+         populate_descriptives (tbl, heading_columns - 2,
                                i * n_stat_rows * n_factors  + heading_rows,
                                &totals[i]);
        }
     }
 
-  tab_submit(tbl);
+  tab_submit (tbl);
 
 }
 
 
-
-
 /* Fill in the descriptives data */
 void
-populate_descriptives(struct tab_table *tbl, int col, int row, 
+populate_descriptives (struct tab_table *tbl, int col, int row,
                      const struct metrics *m)
 {
-
-  const double t = gsl_cdf_tdist_Qinv(1 - cmd.n_cinterval[0]/100.0/2.0, \
+  const double t = gsl_cdf_tdist_Qinv ((1 - cmd.n_cinterval[0] / 100.0)/2.0,
                                      m->n -1);
 
-
-  tab_text (tbl, col, 
+  tab_text (tbl, col,
            row,
            TAB_LEFT | TAT_TITLE,
-           _("Mean"));
+           _ ("Mean"));
 
   tab_float (tbl, col + 2,
             row,
             TAB_CENTER,
             m->mean,
             8,2);
-  
+
   tab_float (tbl, col + 3,
             row,
             TAB_CENTER,
             m->se_mean,
             8,3);
-  
 
-  tab_text (tbl, col, 
+
+  tab_text (tbl, col,
            row + 1,
            TAB_LEFT | TAT_TITLE | TAT_PRINTF,
-           _("%g%% Confidence Interval for Mean"), cmd.n_cinterval[0]);
+           _ ("%g%% Confidence Interval for Mean"), cmd.n_cinterval[0]);
 
 
-  tab_text (tbl, col + 1, 
+  tab_text (tbl, col + 1,
            row  + 1,
            TAB_LEFT | TAT_TITLE,
-           _("Lower Bound"));
+           _ ("Lower Bound"));
 
   tab_float (tbl, col + 2,
             row + 1,
             TAB_CENTER,
-            m->mean - t * m->se_mean, 
+            m->mean - t * m->se_mean,
             8,3);
 
-  tab_text (tbl, col + 1,  
+  tab_text (tbl, col + 1,
            row + 2,
            TAB_LEFT | TAT_TITLE,
-           _("Upper Bound"));
+           _ ("Upper Bound"));
 
 
   tab_float (tbl, col + 2,
             row + 2,
             TAB_CENTER,
-            m->mean + t * m->se_mean, 
+            m->mean + t * m->se_mean,
             8,3);
 
-  tab_text (tbl, col, 
+  tab_text (tbl, col,
            row + 3,
            TAB_LEFT | TAT_TITLE | TAT_PRINTF,
-           _("5%% Trimmed Mean"));
+           _ ("5%% Trimmed Mean"));
 
-  tab_float (tbl, col + 2, 
+  tab_float (tbl, col + 2,
             row + 3,
             TAB_CENTER,
             m->trimmed_mean,
             8,2);
 
-  tab_text (tbl, col, 
+  tab_text (tbl, col,
            row + 4,
            TAB_LEFT | TAT_TITLE,
-           _("Median"));
+           _ ("Median"));
 
   {
     struct percentile *p;
     double d = 50;
-    
-    p = hsh_find(m->ptile_hash, &d);
-    
-    assert(p);
 
+    p = hsh_find (m->ptile_hash, &d);
 
-    tab_float (tbl, col + 2, 
+    assert (p);
+
+
+    tab_float (tbl, col + 2,
               row + 4,
               TAB_CENTER,
               p->v,
               8, 2);
   }
-    
 
-  tab_text (tbl, col, 
+
+  tab_text (tbl, col,
            row + 5,
            TAB_LEFT | TAT_TITLE,
-           _("Variance"));
+           _ ("Variance"));
 
   tab_float (tbl, col + 2,
             row + 5,
@@ -1571,10 +1608,10 @@ populate_descriptives(struct tab_table *tbl, int col, int row,
             8,3);
 
 
-  tab_text (tbl, col, 
+  tab_text (tbl, col,
            row + 6,
            TAB_LEFT | TAT_TITLE,
-           _("Std. Deviation"));
+           _ ("Std. Deviation"));
 
 
   tab_float (tbl, col + 2,
@@ -1583,11 +1620,11 @@ populate_descriptives(struct tab_table *tbl, int col, int row,
             m->stddev,
             8,3);
 
-  
-  tab_text (tbl, col, 
+
+  tab_text (tbl, col,
            row + 7,
            TAB_LEFT | TAT_TITLE,
-           _("Minimum"));
+           _ ("Minimum"));
 
   tab_float (tbl, col + 2,
             row + 7,
@@ -1595,10 +1632,10 @@ populate_descriptives(struct tab_table *tbl, int col, int row,
             m->min,
             8,3);
 
-  tab_text (tbl, col, 
+  tab_text (tbl, col,
            row + 8,
            TAB_LEFT | TAT_TITLE,
-           _("Maximum"));
+           _ ("Maximum"));
 
   tab_float (tbl, col + 2,
             row + 8,
@@ -1607,10 +1644,10 @@ populate_descriptives(struct tab_table *tbl, int col, int row,
             8,3);
 
 
-  tab_text (tbl, col, 
+  tab_text (tbl, col,
            row + 9,
            TAB_LEFT | TAT_TITLE,
-           _("Range"));
+           _ ("Range"));
 
 
   tab_float (tbl, col + 2,
@@ -1619,25 +1656,25 @@ populate_descriptives(struct tab_table *tbl, int col, int row,
             m->max - m->min,
             8,3);
 
-  tab_text (tbl, col, 
+  tab_text (tbl, col,
            row + 10,
            TAB_LEFT | TAT_TITLE,
-           _("Interquartile Range"));
+           _ ("Interquartile Range"));
 
   {
     struct percentile *p1;
     struct percentile *p2;
 
     double d = 75;
-    p1 = hsh_find(m->ptile_hash, &d);
+    p1 = hsh_find (m->ptile_hash, &d);
 
     d = 25;
-    p2 = hsh_find(m->ptile_hash, &d);
+    p2 = hsh_find (m->ptile_hash, &d);
 
-    assert(p1);
-    assert(p2);
+    assert (p1);
+    assert (p2);
 
-    tab_float (tbl, col + 2, 
+    tab_float (tbl, col + 2,
               row + 10,
               TAB_CENTER,
               p1->v - p2->v,
@@ -1646,10 +1683,10 @@ populate_descriptives(struct tab_table *tbl, int col, int row,
 
 
 
-  tab_text (tbl, col, 
+  tab_text (tbl, col,
            row + 11,
            TAB_LEFT | TAT_TITLE,
-           _("Skewness"));
+           _ ("Skewness"));
 
 
   tab_float (tbl, col + 2,
@@ -1662,14 +1699,14 @@ populate_descriptives(struct tab_table *tbl, int col, int row,
   tab_float (tbl, col + 3,
             row + 11,
             TAB_CENTER,
-            calc_seskew(m->n),
+            calc_seskew (m->n),
             8,3);
 
 
-  tab_text (tbl, col, 
+  tab_text (tbl, col,
            row + 12,
            TAB_LEFT | TAT_TITLE,
-           _("Kurtosis"));
+           _ ("Kurtosis"));
 
 
   tab_float (tbl, col + 2,
@@ -1682,7 +1719,7 @@ populate_descriptives(struct tab_table *tbl, int col, int row,
   tab_float (tbl, col + 3,
             row + 12,
             TAB_CENTER,
-            calc_sekurt(m->n),
+            calc_sekurt (m->n),
             8,3);
 
 
@@ -1691,55 +1728,55 @@ populate_descriptives(struct tab_table *tbl, int col, int row,
 
 
 void
-box_plot_variables(const struct factor *fctr, 
-                  const struct variable **vars, int n_vars, 
+box_plot_variables (const struct factor *fctr,
+                  const struct variable **vars, int n_vars,
                   const struct variable *id)
 {
 
   int i;
   struct factor_statistics **fs ;
 
-  if ( ! fctr ) 
+  if ( ! fctr )
     {
-      box_plot_group(fctr, vars, n_vars, id);
+      box_plot_group (fctr, vars, n_vars, id);
       return;
     }
 
-  for ( fs = fctr->fs ; *fs ; ++fs ) 
+  for ( fs = fctr->fs ; *fs ; ++fs )
     {
       double y_min = DBL_MAX;
       double y_max = -DBL_MAX;
-      struct chart *ch = chart_create();
-      const char *s = factor_to_string(fctr, *fs, 0 );
+      struct chart *ch = chart_create ();
+      const char *s = factor_to_string (fctr, *fs, 0 );
 
-      chart_write_title(ch, s);
+      chart_write_title (ch, s);
 
-      for ( i = 0 ; i < n_vars ; ++i ) 
+      for ( i = 0 ; i < n_vars ; ++i )
        {
-         y_max = max(y_max, (*fs)->m[i].max);
-         y_min = min(y_min, (*fs)->m[i].min);
+         y_max = MAX (y_max, (*fs)->m[i].max);
+         y_min = MIN (y_min, (*fs)->m[i].min);
        }
-      
-      boxplot_draw_yscale(ch, y_max, y_min);
-         
-      for ( i = 0 ; i < n_vars ; ++i ) 
+
+      boxplot_draw_yscale (ch, y_max, y_min);
+
+      for ( i = 0 ; i < n_vars ; ++i )
        {
 
-         const double box_width = (ch->data_right - ch->data_left) 
+         const double box_width = (ch->data_right - ch->data_left)
            / (n_vars * 2.0 ) ;
 
-         const double box_centre = ( i * 2 + 1) * box_width 
+         const double box_centre = ( i * 2 + 1) * box_width
            + ch->data_left;
-             
-         boxplot_draw_boxplot(ch,
+
+         boxplot_draw_boxplot (ch,
                               box_centre, box_width,
-                              &(*fs)->m[i],
-                              var_to_string(vars[i]));
+                              & (*fs)->m[i],
+                              var_to_string (vars[i]));
 
 
        }
 
-      chart_submit(ch);
+      chart_submit (ch);
 
     }
 }
@@ -1750,47 +1787,47 @@ box_plot_variables(const struct factor *fctr,
    each dependent variable has its own plot.
 */
 void
-box_plot_group(const struct factor *fctr, 
-              const struct variable **vars, 
+box_plot_group (const struct factor *fctr,
+              const struct variable **vars,
               int n_vars,
               const struct variable *id UNUSED)
 {
 
   int i;
 
-  for ( i = 0 ; i < n_vars ; ++i ) 
+  for ( i = 0 ; i < n_vars ; ++i )
     {
       struct factor_statistics **fs ;
       struct chart *ch;
 
-      ch = chart_create();
+      ch = chart_create ();
 
-      boxplot_draw_yscale(ch, totals[i].max, totals[i].min);
+      boxplot_draw_yscale (ch, totals[i].max, totals[i].min);
 
-      if ( fctr ) 
+      if ( fctr )
        {
          int n_factors = 0;
          int f=0;
-         for ( fs = fctr->fs ; *fs ; ++fs ) 
+         for ( fs = fctr->fs ; *fs ; ++fs )
            ++n_factors;
 
-         chart_write_title(ch, _("Boxplot of %s vs. %s"), 
-                           var_to_string(vars[i]), var_to_string(fctr->indep_var[0]) );
+         chart_write_title (ch, _ ("Boxplot of %s vs. %s"),
+                           var_to_string (vars[i]), var_to_string (fctr->indep_var[0]) );
 
-         for ( fs = fctr->fs ; *fs ; ++fs ) 
+         for ( fs = fctr->fs ; *fs ; ++fs )
            {
-             
-             const char *s = factor_to_string_concise(fctr, *fs);
 
-             const double box_width = (ch->data_right - ch->data_left) 
+             const char *s = factor_to_string_concise (fctr, *fs);
+
+             const double box_width = (ch->data_right - ch->data_left)
                / (n_factors * 2.0 ) ;
 
-             const double box_centre = ( f++ * 2 + 1) * box_width 
+             const double box_centre = ( f++ * 2 + 1) * box_width
                + ch->data_left;
-             
-             boxplot_draw_boxplot(ch,
+
+             boxplot_draw_boxplot (ch,
                                   box_centre, box_width,
-                                  &(*fs)->m[i],
+                                  & (*fs)->m[i],
                                   s);
            }
        }
@@ -1799,16 +1836,16 @@ box_plot_group(const struct factor *fctr,
          const double box_width = (ch->data_right - ch->data_left) / 3.0;
          const double box_centre = (ch->data_right + ch->data_left) / 2.0;
 
-         chart_write_title(ch, _("Boxplot"));
+         chart_write_title (ch, _ ("Boxplot"));
 
-         boxplot_draw_boxplot(ch,
-                              box_centre,    box_width, 
+         boxplot_draw_boxplot (ch,
+                              box_centre,    box_width,
                               &totals[i],
-                              var_to_string(vars[i]) );
-         
+                              var_to_string (vars[i]) );
+
        }
 
-      chart_submit(ch);
+      chart_submit (ch);
     }
 }
 
@@ -1816,7 +1853,7 @@ box_plot_group(const struct factor *fctr,
 /* Plot the normal and detrended normal plots for m
    Label the plots with factorname */
 void
-np_plot(const struct metrics *m, const char *factorname)
+np_plot (const struct metrics *m, const char *factorname)
 {
   int i;
   double yfirst=0, ylast=0;
@@ -1832,24 +1869,24 @@ np_plot(const struct metrics *m, const char *factorname)
   const double intercept = - m->mean / m->stddev;
 
   /* Cowardly refuse to plot an empty data set */
-  if ( m->n_data == 0 ) 
-    return ; 
+  if ( m->n_data == 0 )
+    return ;
 
-  np_chart = chart_create();
-  dnp_chart = chart_create();
+  np_chart = chart_create ();
+  dnp_chart = chart_create ();
 
-  if ( !np_chart || ! dnp_chart ) 
+  if ( !np_chart || ! dnp_chart )
     return ;
 
-  chart_write_title(np_chart, _("Normal Q-Q Plot of %s"), factorname);
-  chart_write_xlabel(np_chart, _("Observed Value"));
-  chart_write_ylabel(np_chart, _("Expected Normal"));
+  chart_write_title (np_chart, _ ("Normal Q-Q Plot of %s"), factorname);
+  chart_write_xlabel (np_chart, _ ("Observed Value"));
+  chart_write_ylabel (np_chart, _ ("Expected Normal"));
 
 
-  chart_write_title(dnp_chart, _("Detrended Normal Q-Q Plot of %s"), 
+  chart_write_title (dnp_chart, _ ("Detrended Normal Q-Q Plot of %s"),
                    factorname);
-  chart_write_xlabel(dnp_chart, _("Observed Value"));
-  chart_write_ylabel(dnp_chart, _("Dev from Normal"));
+  chart_write_xlabel (dnp_chart, _ ("Observed Value"));
+  chart_write_ylabel (dnp_chart, _ ("Dev from Normal"));
 
   yfirst = gsl_cdf_ugaussian_Pinv (m->wvp[0]->rank / ( m->n + 1));
   ylast =  gsl_cdf_ugaussian_Pinv (m->wvp[m->n_data-1]->rank / ( m->n + 1));
@@ -1858,48 +1895,48 @@ np_plot(const struct metrics *m, const char *factorname)
   {
     /* Need to make sure that both the scatter plot and the ideal fit into the
        plot */
-    double x_lower = min(m->min, (yfirst - intercept) / slope) ;
-    double x_upper = max(m->max, (ylast  - intercept) / slope) ;
+    double x_lower = MIN (m->min, (yfirst - intercept) / slope) ;
+    double x_upper = MAX (m->max, (ylast  - intercept) / slope) ;
     double slack = (x_upper - x_lower)  * 0.05 ;
 
-    chart_write_xscale(np_chart, x_lower - slack, x_upper + slack, 5);
+    chart_write_xscale (np_chart, x_lower - slack, x_upper + slack, 5);
 
-    chart_write_xscale(dnp_chart, m->min, m->max, 5);
+    chart_write_xscale (dnp_chart, m->min, m->max, 5);
 
   }
 
-  chart_write_yscale(np_chart, yfirst, ylast, 5);
+  chart_write_yscale (np_chart, yfirst, ylast, 5);
 
   {
-    /* We have to cache the detrended data, beacause we need to 
+    /* We have to cache the detrended data, beacause we need to
        find its limits before we can plot it */
     double *d_data = xnmalloc (m->n_data, sizeof *d_data);
     double d_max = -DBL_MAX;
     double d_min = DBL_MAX;
-    for ( i = 0 ; i < m->n_data; ++i ) 
+    for ( i = 0 ; i < m->n_data; ++i )
       {
        const double ns = gsl_cdf_ugaussian_Pinv (m->wvp[i]->rank / ( m->n + 1));
 
-       chart_datum(np_chart, 0, m->wvp[i]->v.f, ns);
+       chart_datum (np_chart, 0, m->wvp[i]->v.f, ns);
 
        d_data[i] = (m->wvp[i]->v.f - m->mean) / m->stddev  - ns;
-   
+
        if ( d_data[i] < d_min ) d_min = d_data[i];
        if ( d_data[i] > d_max ) d_max = d_data[i];
       }
-    chart_write_yscale(dnp_chart, d_min, d_max, 5);
+    chart_write_yscale (dnp_chart, d_min, d_max, 5);
 
-    for ( i = 0 ; i < m->n_data; ++i ) 
-      chart_datum(dnp_chart, 0, m->wvp[i]->v.f, d_data[i]);
+    for ( i = 0 ; i < m->n_data; ++i )
+      chart_datum (dnp_chart, 0, m->wvp[i]->v.f, d_data[i]);
 
-    free(d_data);
+    free (d_data);
   }
 
-  chart_line(np_chart, slope, intercept, yfirst, ylast , CHART_DIM_Y);
-  chart_line(dnp_chart, 0, 0, m->min, m->max , CHART_DIM_X);
+  chart_line (np_chart, slope, intercept, yfirst, ylast , CHART_DIM_Y);
+  chart_line (dnp_chart, 0, 0, m->min, m->max , CHART_DIM_X);
 
-  chart_submit(np_chart);
-  chart_submit(dnp_chart);
+  chart_submit (np_chart);
+  chart_submit (dnp_chart);
 }
 
 
@@ -1907,13 +1944,13 @@ np_plot(const struct metrics *m, const char *factorname)
 
 /* Show the percentiles */
 void
-show_percentiles(struct variable **dependent_var, 
-                int n_dep_var, 
+show_percentiles (const struct variable **dependent_var,
+                int n_dep_var,
                 struct factor *fctr)
 {
   struct tab_table *tbl;
   int i;
-  
+
   int n_cols, n_rows;
   int n_factors;
 
@@ -1927,9 +1964,9 @@ show_percentiles(struct variable **dependent_var,
 
   if ( fctr )
     {
-      struct factor_statistics **fs = fctr->fs ; 
+      struct factor_statistics **fs = fctr->fs ;
       n_heading_columns = 3;
-      n_factors = hsh_count(fctr->fstats);
+      n_factors = hsh_count (fctr->fstats);
 
       ptiles = (*fs)->m[0].ptile_hash;
 
@@ -1944,11 +1981,11 @@ show_percentiles(struct variable **dependent_var,
       ptiles = totals[0].ptile_hash;
     }
 
-  n_ptiles = hsh_count(ptiles);
+  n_ptiles = hsh_count (ptiles);
 
   n_rows = n_heading_rows + n_dep_var * n_stat_rows * n_factors;
 
-  n_cols = n_heading_columns + n_ptiles ; 
+  n_cols = n_heading_columns + n_ptiles ;
 
   tbl = tab_create (n_cols, n_rows, 0);
 
@@ -1957,7 +1994,7 @@ show_percentiles(struct variable **dependent_var,
   tab_dim (tbl, tab_natural_dimensions);
 
   /* Outline the box and have no internal lines*/
-  tab_box (tbl, 
+  tab_box (tbl,
           TAL_2, TAL_2,
           -1, -1,
           0, 0,
@@ -1968,96 +2005,95 @@ show_percentiles(struct variable **dependent_var,
   tab_vline (tbl, TAL_2, n_heading_columns, 0, n_rows - 1);
 
 
-  tab_title (tbl, _("Percentiles"));
+  tab_title (tbl, _ ("Percentiles"));
 
 
   tab_hline (tbl, TAL_1, n_heading_columns, n_cols - 1, 1 );
 
 
-  tab_box (tbl, 
+  tab_box (tbl,
           -1, -1,
           -1, TAL_1,
           0, n_heading_rows,
           n_heading_columns - 1, n_rows - 1);
 
 
-  tab_box (tbl, 
+  tab_box (tbl,
           -1, -1,
           -1, TAL_1,
           n_heading_columns, n_heading_rows - 1,
           n_cols - 1, n_rows - 1);
 
-  tab_joint_text(tbl, n_heading_columns + 1, 0,
+  tab_joint_text (tbl, n_heading_columns + 1, 0,
                 n_cols - 1 , 0,
                 TAB_CENTER | TAT_TITLE ,
-                _("Percentiles"));
+                _ ("Percentiles"));
 
 
   {
     /* Put in the percentile break points as headings */
 
-    struct percentile **p = (struct percentile **) hsh_sort(ptiles);
+    struct percentile **p = (struct percentile **) hsh_sort (ptiles);
 
     i = 0;
-    while ( (*p)  ) 
+    while ( (*p)  )
       {
-       tab_float(tbl, n_heading_columns + i++ , 1, 
+       tab_float (tbl, n_heading_columns + i++ , 1,
                  TAB_CENTER,
                  (*p)->p, 8, 0);
-       
+
        p++;
       }
 
   }
 
-  for ( i = 0 ; i < n_dep_var ; ++i ) 
+  for ( i = 0 ; i < n_dep_var ; ++i )
     {
       const int n_stat_rows = 2;
       const int row = n_heading_rows + i * n_stat_rows * n_factors ;
 
       if ( i > 0 )
-       tab_hline(tbl, TAL_1, 0, n_cols - 1, row );
+       tab_hline (tbl, TAL_1, 0, n_cols - 1, row );
 
       tab_text (tbl, 0,
                i * n_stat_rows * n_factors  + n_heading_rows,
-               TAB_LEFT | TAT_TITLE, 
-               var_to_string(dependent_var[i])
+               TAB_LEFT | TAT_TITLE,
+               var_to_string (dependent_var[i])
                );
 
       if ( fctr  )
        {
+         const union value *prev  = NULL ;
          struct factor_statistics **fs = fctr->fs;
          int count = 0;
 
-         tab_text (tbl, 1, n_heading_rows - 1, 
-                   TAB_CENTER | TAT_TITLE, 
-                   var_to_string(fctr->indep_var[0]));
+         tab_text (tbl, 1, n_heading_rows - 1,
+                   TAB_CENTER | TAT_TITLE,
+                   var_to_string (fctr->indep_var[0]));
 
 
          if ( fctr->indep_var[1])
-           tab_text (tbl, 2, n_heading_rows - 1, TAB_CENTER | TAT_TITLE, 
-                     var_to_string(fctr->indep_var[1]));
+           tab_text (tbl, 2, n_heading_rows - 1, TAB_CENTER | TAT_TITLE,
+                     var_to_string (fctr->indep_var[1]));
 
-         while( *fs ) 
+         while ( *fs )
            {
+             const int row = n_heading_rows + n_stat_rows  *
+                ( ( i  * n_factors  ) +  count );
 
-             static union value prev ;
-
-             const int row = n_heading_rows + n_stat_rows  * 
-               ( ( i  * n_factors  ) +  count );
 
-
-             if ( 0 != compare_values(&prev, &(*fs)->id[0], 
-                                      fctr->indep_var[0]->width))
+             if ( !prev || 0 != compare_values (prev, (*fs)->id[0],
+                                        var_get_width (fctr->indep_var[0])))
                {
-                 
-                 if ( count > 0 ) 
+
+                 if ( count > 0 )
                    tab_hline (tbl, TAL_1, 1, n_cols - 1, row);
 
-                 tab_text (tbl, 
+                 tab_text (tbl,
                            1, row,
-                           TAB_LEFT | TAT_TITLE, 
-                           value_to_string(&(*fs)->id[0], fctr->indep_var[0])
+                           TAB_LEFT | TAT_TITLE,
+                           var_get_value_name (fctr->indep_var[0],
+                                                (*fs)->id[0])
                            );
 
 
@@ -2065,29 +2101,29 @@ show_percentiles(struct variable **dependent_var,
 
              prev = (*fs)->id[0];
 
-             if (fctr->indep_var[1] && count > 0 ) 
-               tab_hline(tbl, TAL_1, 2, n_cols - 1, row);
+             if (fctr->indep_var[1] && count > 0 )
+               tab_hline (tbl, TAL_1, 2, n_cols - 1, row);
 
-             if ( fctr->indep_var[1]) 
+             if ( fctr->indep_var[1])
                tab_text (tbl, 2, row,
-                         TAB_LEFT | TAT_TITLE, 
-                         value_to_string(&(*fs)->id[1], fctr->indep_var[1])
+                         TAB_LEFT | TAT_TITLE,
+                         var_get_value_name (fctr->indep_var[1], (*fs)->id[1])
                          );
 
 
-             populate_percentiles(tbl, n_heading_columns - 1, 
-                                  row, &(*fs)->m[i]);
+             populate_percentiles (tbl, n_heading_columns - 1,
+                                  row, & (*fs)->m[i]);
 
 
-             count++ ; 
+             count++ ;
              fs++;
            }
 
 
        }
-      else 
+      else
        {
-         populate_percentiles(tbl, n_heading_columns - 1, 
+         populate_percentiles (tbl, n_heading_columns - 1,
                               i * n_stat_rows * n_factors  + n_heading_rows,
                               &totals[i]);
        }
@@ -2096,7 +2132,7 @@ show_percentiles(struct variable **dependent_var,
     }
 
 
-  tab_submit(tbl);
+  tab_submit (tbl);
 
 
 }
@@ -2105,44 +2141,44 @@ show_percentiles(struct variable **dependent_var,
 
 
 void
-populate_percentiles(struct tab_table *tbl, int col, int row, 
+populate_percentiles (struct tab_table *tbl, int col, int row,
                     const struct metrics *m)
 {
   int i;
 
-  struct percentile **p = (struct percentile **) hsh_sort(m->ptile_hash);
-  
-  tab_text (tbl, 
+  struct percentile **p = (struct percentile **) hsh_sort (m->ptile_hash);
+
+  tab_text (tbl,
            col, row + 1,
-           TAB_LEFT | TAT_TITLE, 
-           _("Tukey\'s Hinges")
+           TAB_LEFT | TAT_TITLE,
+           _ ("Tukey\'s Hinges")
            );
 
-  tab_text (tbl, 
-           col, row, 
-           TAB_LEFT | TAT_TITLE, 
+  tab_text (tbl,
+           col, row,
+           TAB_LEFT | TAT_TITLE,
            ptile_alg_desc[m->ptile_alg]
            );
 
 
   i = 0;
-  while ( (*p)  ) 
+  while ( (*p)  )
     {
-      tab_float(tbl, col + i + 1 , row, 
+      tab_float (tbl, col + i + 1 , row,
                TAB_CENTER,
-               (*p)->v, 8, 2);
-      if ( (*p)->p == 25 ) 
-       tab_float(tbl, col + i + 1 , row + 1, 
+                (*p)->v, 8, 2);
+      if ( (*p)->p == 25 )
+       tab_float (tbl, col + i + 1 , row + 1,
                  TAB_CENTER,
                  m->hinge[0], 8, 2);
 
-      if ( (*p)->p == 50 ) 
-       tab_float(tbl, col + i + 1 , row + 1, 
+      if ( (*p)->p == 50 )
+       tab_float (tbl, col + i + 1 , row + 1,
                  TAB_CENTER,
                  m->hinge[1], 8, 2);
 
-      if ( (*p)->p == 75 ) 
-       tab_float(tbl, col + i + 1 , row + 1, 
+      if ( (*p)->p == 75 )
+       tab_float (tbl, col + i + 1 , row + 1,
                  TAB_CENTER,
                  m->hinge[2], 8, 2);
 
@@ -2157,38 +2193,37 @@ populate_percentiles(struct tab_table *tbl, int col, int row,
 
 
 const char *
-factor_to_string(const struct factor *fctr, 
-                struct factor_statistics *fs,
-                const struct variable *var)
+factor_to_string (const struct factor *fctr,
+                 const struct factor_statistics *fs,
+                 const struct variable *var)
 {
 
   static char buf1[100];
   char buf2[100];
 
-  strcpy(buf1,"");
+  strcpy (buf1,"");
 
   if (var)
-    sprintf(buf1, "%s (",var_to_string(var) );
-
-                     
-  snprintf(buf2, 100, "%s = %s",
-          var_to_string(fctr->indep_var[0]),
-          value_to_string(&fs->id[0],fctr->indep_var[0]));
-                     
-  strcat(buf1, buf2);
-                     
-  if ( fctr->indep_var[1] ) 
+    sprintf (buf1, "%s (",var_to_string (var) );
+
+
+  snprintf (buf2, 100, "%s = %s",
+          var_to_string (fctr->indep_var[0]),
+           var_get_value_name (fctr->indep_var[0], fs->id[0]));
+
+  strcat (buf1, buf2);
+
+  if ( fctr->indep_var[1] )
     {
-      sprintf(buf2, "; %s = %s)",
-             var_to_string(fctr->indep_var[1]),
-             value_to_string(&fs->id[1],
-                             fctr->indep_var[1]));
-      strcat(buf1, buf2);
+      sprintf (buf2, "; %s = %s)",
+             var_to_string (fctr->indep_var[1]),
+              var_get_value_name (fctr->indep_var[1], fs->id[1]));
+      strcat (buf1, buf2);
     }
   else
     {
-      if ( var ) 
-       strcat(buf1, ")");
+      if ( var )
+       strcat (buf1, ")");
     }
 
   return buf1;
@@ -2197,7 +2232,7 @@ factor_to_string(const struct factor *fctr,
 
 
 const char *
-factor_to_string_concise(const struct factor *fctr, 
+factor_to_string_concise (const struct factor *fctr,
                         struct factor_statistics *fs)
 
 {
@@ -2206,15 +2241,22 @@ factor_to_string_concise(const struct factor *fctr,
 
   char buf2[100];
 
-  snprintf(buf, 100, "%s",
-          value_to_string(&fs->id[0], fctr->indep_var[0]));
-                     
-  if ( fctr->indep_var[1] ) 
+  snprintf (buf, 100, "%s",
+            var_get_value_name (fctr->indep_var[0], fs->id[0]));
+
+  if ( fctr->indep_var[1] )
     {
-      sprintf(buf2, ",%s)", value_to_string(&fs->id[1], fctr->indep_var[1]) );
-      strcat(buf, buf2);
+      sprintf (buf2, ",%s)", var_get_value_name (fctr->indep_var[1],
+                                                 fs->id[1]) );
+      strcat (buf, buf2);
     }
 
 
   return buf;
 }
+
+/*
+  Local Variables:
+  mode: c
+  End:
+*/