? mv-class.patch
Index: src/data/ChangeLog
===================================================================
RCS file: /cvsroot/pspp/pspp/src/data/ChangeLog,v
retrieving revision 1.93
diff -u -p -r1.93 ChangeLog
--- src/data/ChangeLog	22 Dec 2006 11:12:14 -0000	1.93
+++ src/data/ChangeLog	22 Dec 2006 22:19:32 -0000
@@ -1,3 +1,46 @@
+Fri Dec 22 13:56:08 2006  Ben Pfaff  <blp@gnu.org>
+
+	Simplify missing value handling.
+
+	* missing-values.h (enum mv_class): New type.
+	(enum mv_type): Moved definition into missing-values.c and renamed
+	each MV_* to MVT_*, to distinguish them from the exposed mv_class
+	enums.  Updated all uses.
+	(struct missing_values): Changed type of `type' from `enum
+	mv_type' to `int' because the definition is no longer exposed.
+	
+	* missing-values.c (mv_is_value_missing): Add new enum mv_class
+	parameter.  Update all callers.
+	(mv_is_num_missing): Ditto.
+	(mv_is_str_missing): Ditto.
+	(mv_is_value_user_missing): Removed.  Changed callers to use
+	mv_is_value_missing.
+	(mv_is_num_user_missing): Removed.  Changed callers to use
+	mv_is_num_missing.
+	(mv_is_str_user_missing): Removed.  Changed callers to use
+	mv_is_str_missing.
+	(mv_is_value_system_missing): Removed.  Changed callers to use
+	mv_is_value_missing.
+	
+	* variable.c (var_is_value_missing): Add new enum mv_class
+	parameter.  Update all callers.
+	(var_is_num_missing): Ditto.
+	(var_is_str_missing): Ditto.
+	(var_is_value_user_missing): Removed.  Changed callers to use
+	var_is_value_missing.
+	(var_is_num_user_missing): Removed.  Changed callers to use
+	var_is_num_missing.
+	(var_is_str_user_missing): Removed.  Changed callers to use
+	var_is_str_missing.
+	(var_is_value_system_missing): Removed.  Changed callers to use
+	var_is_value_missing.
+	
+	* casefilter.c (struct casefilter): Use enum mv_class in place of
+	bool.
+	(casefilter_variable_missing): Adapt to new member.
+	(casefilter_create): Change signature to take enum mv_class,
+	update callers.
+
 Fri Dec 22 20:08:38 WST 2006 John Darrington <john@darrington.wattle.id.au>
 
 	* casefile-factory.h fastfile-factory.c fastfile-factory.h: New files.
Index: src/data/casefilter.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/data/casefilter.c,v
retrieving revision 1.6
diff -u -p -r1.6 casefilter.c
--- src/data/casefilter.c	20 Dec 2006 10:10:51 -0000	1.6
+++ src/data/casefilter.c	22 Dec 2006 22:19:32 -0000
@@ -29,7 +29,7 @@
 
 struct casefilter
  {
-   bool exclude_user_missing;
+   enum mv_class class;
 
    const struct variable **vars;
    int n_vars;
@@ -58,30 +58,21 @@ casefilter_variable_missing (const struc
 			     const struct variable *var)
 {
   const union value *val = case_data (c, var) ;
-
-  if ( var_is_numeric (var) && val->f == SYSMIS )
-    return true;
-
-  if ( filter->exclude_user_missing &&
-       var_is_value_user_missing (var, val) )
-    return true;
-
-  return false;
+  return var_is_value_missing (var, val, filter->class);
 }
 
-/* Create a new casefilter.
-   If EXCL is true, then the filter  user missing values to be missing,
-   otherwise they are considered at their face value.
+/* Create a new casefilter that drops cases in which any of the
+   N_VARS variables in VARS are in the given CLASS of missing values.
    VARS is an array of variables which if *any* of them are missing.
    N_VARS is the size of VARS.
  */
 struct casefilter *
-casefilter_create (bool excl, struct variable **vars, int n_vars)
+casefilter_create (enum mv_class class, struct variable **vars, int n_vars)
 {
   int i;
   struct casefilter * filter = xmalloc (sizeof (*filter)) ;
 
-  filter->exclude_user_missing = excl ;
+  filter->class = class;
   filter->vars = xnmalloc (n_vars, sizeof (*filter->vars) );
 
   for ( i = 0 ; i < n_vars ; ++i )
Index: src/data/casefilter.h
===================================================================
RCS file: /cvsroot/pspp/pspp/src/data/casefilter.h,v
retrieving revision 1.3
diff -u -p -r1.3 casefilter.h
--- src/data/casefilter.h	20 Dec 2006 10:10:51 -0000	1.3
+++ src/data/casefilter.h	22 Dec 2006 22:19:32 -0000
@@ -20,18 +20,19 @@
 #define casefilter_h 1
 
 #include <stdbool.h>
+#include <data/missing-values.h>
 
 struct ccase;
 struct casefilter;
 struct variable ;
 
-/* Create a new casefilter.
-   If EXCL is true, then the filter  user missing values to be missing, 
-   otherwise they are considered at their face value.
+/* Create a new casefilter that drops cases in which any of the
+   N_VARS variables in VARS are missing in the given CLASS.
    VARS is an array of variables which if *any* of them are missing.
    N_VARS is the size of VARS.
  */
-struct casefilter * casefilter_create (bool, struct variable **, int);
+struct casefilter * casefilter_create (enum mv_class class,
+                                       struct variable **, int);
 
 /* Add the variables in VARS to the list of variables for which the
    filter considers. N_VARS is the size of VARS */
Index: src/data/dictionary.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/data/dictionary.c,v
retrieving revision 1.24
diff -u -p -r1.24 dictionary.c
--- src/data/dictionary.c	16 Dec 2006 03:40:41 -0000	1.24
+++ src/data/dictionary.c	22 Dec 2006 22:19:33 -0000
@@ -698,7 +698,7 @@ dict_get_case_weight (const struct dicti
   else 
     {
       double w = case_num (c, d->weight);
-      if (w < 0.0 || var_is_num_missing (d->weight, w))
+      if (w < 0.0 || var_is_num_missing (d->weight, w, MV_ANY))
         w = 0.0;
       if ( w == 0.0 && *warn_on_invalid ) {
 	  *warn_on_invalid = false;
Index: src/data/missing-values.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/data/missing-values.c,v
retrieving revision 1.8
diff -u -p -r1.8 missing-values.c
--- src/data/missing-values.c	16 Dec 2006 03:40:41 -0000	1.8
+++ src/data/missing-values.c	22 Dec 2006 22:19:33 -0000
@@ -24,6 +24,17 @@
 #include "variable.h"
 #include <libpspp/str.h>
 
+/* Types of user-missing values.
+   Invisible--use access functions defined below instead. */
+enum mv_type
+  {
+    MVT_NONE = 0,                /* No user-missing values. */
+    MVT_1 = 1,                   /* One user-missing value. */
+    MVT_2 = 2,                   /* Two user-missing values. */
+    MVT_3 = 3,                   /* Three user-missing values. */
+    MVT_RANGE = 4,               /* A range of user-missing values. */
+    MVT_RANGE_1 = 5              /* A range plus an individual value. */
+  };
 
 /* Initializes MV as a set of missing values for a variable of
    the given WIDTH.  Although only numeric variables and short
@@ -33,17 +44,17 @@ void
 mv_init (struct missing_values *mv, int width) 
 {
   assert (width >= 0 && width <= MAX_STRING);
-  mv->type = MV_NONE;
+  mv->type = MVT_NONE;
   mv->width = width;
 }
 
+/* Removes any missing values from MV. */
 void 
-mv_set_type(struct missing_values *mv, enum mv_type type)
+mv_clear (struct missing_values *mv)
 {
-  mv->type = type;
+  mv->type = MVT_NONE;
 }
 
-
 /* Copies SRC to MV. */
 void
 mv_copy (struct missing_values *mv, const struct missing_values *src) 
@@ -57,7 +68,7 @@ mv_copy (struct missing_values *mv, cons
 bool
 mv_is_empty (const struct missing_values *mv) 
 {
-  return mv->type == MV_NONE;
+  return mv->type == MVT_NONE;
 }
 
 /* Returns the width of the missing values that MV may
@@ -79,16 +90,16 @@ mv_add_value (struct missing_values *mv,
     return false;
   switch (mv->type) 
     {
-    case MV_NONE:
-    case MV_1:
-    case MV_2:
-    case MV_RANGE:
+    case MVT_NONE:
+    case MVT_1:
+    case MVT_2:
+    case MVT_RANGE:
       mv->values[mv->type & 3] = *v;
       mv->type++;
       return true;
 
-    case MV_3:
-    case MV_RANGE_1:
+    case MVT_3:
+    case MVT_RANGE_1:
       return false;
     }
   NOT_REACHED ();
@@ -127,17 +138,17 @@ mv_add_num_range (struct missing_values 
     return false;
   switch (mv->type) 
     {
-    case MV_NONE:
-    case MV_1:
+    case MVT_NONE:
+    case MVT_1:
       mv->values[1].f = low;
       mv->values[2].f = high;
       mv->type |= 4;
       return true;
 
-    case MV_2:
-    case MV_3:
-    case MV_RANGE:
-    case MV_RANGE_1:
+    case MVT_2:
+    case MVT_3:
+    case MVT_RANGE:
+    case MVT_RANGE_1:
       return false;
     }
   NOT_REACHED ();
@@ -150,14 +161,14 @@ mv_has_value (const struct missing_value
 {
   switch (mv->type) 
     {
-    case MV_1:
-    case MV_2:
-    case MV_3:
-    case MV_RANGE_1:
+    case MVT_1:
+    case MVT_2:
+    case MVT_3:
+    case MVT_RANGE_1:
       return true;
       
-    case MV_NONE:
-    case MV_RANGE:
+    case MVT_NONE:
+    case MVT_RANGE:
       return false;
     }
   NOT_REACHED ();
@@ -215,14 +226,14 @@ mv_has_range (const struct missing_value
 {
   switch (mv->type) 
     {
-    case MV_RANGE:
-    case MV_RANGE_1:
+    case MVT_RANGE:
+    case MVT_RANGE_1:
       return true;
       
-    case MV_NONE:
-    case MV_1:
-    case MV_2:
-    case MV_3:
+    case MVT_NONE:
+    case MVT_1:
+    case MVT_2:
+    case MVT_3:
       return false;
     }
   NOT_REACHED ();
@@ -263,17 +274,17 @@ using_element (unsigned type, int idx) 
   
   switch (type) 
     {
-    case MV_NONE:
+    case MVT_NONE:
       return false;
-    case MV_1:
+    case MVT_1:
       return idx < 1;
-    case MV_2:
+    case MVT_2:
       return idx < 2;
-    case MV_3:
+    case MVT_3:
       return true;
-    case MV_RANGE:
+    case MVT_RANGE:
       return idx > 0;
-    case MV_RANGE_1:
+    case MVT_RANGE_1:
       return true;
     }
   NOT_REACHED ();
@@ -308,7 +319,7 @@ mv_is_resizable (const struct missing_va
   if ( var_type_from_width (width) != var_type_from_width (mv->width) )
     return false;
 
-  if (width > MAX_SHORT_STRING && mv->type != MV_NONE)
+  if (width > MAX_SHORT_STRING && mv->type != MVT_NONE)
     return false;
 
   if (width >= mv->width)
@@ -331,7 +342,7 @@ void
 mv_resize (struct missing_values *mv, int width) 
 {
   assert (mv_is_resizable (mv, width));
-  if (width > mv->width && mv->type != MV_NONE) 
+  if (width > mv->width && mv->type != MVT_NONE) 
     {
       int i;
       
@@ -341,65 +352,26 @@ mv_resize (struct missing_values *mv, in
   mv->width = width;
 }
 
-/* Returns true if V is system missing or a missing value in MV,
-   false otherwise. */
-bool
-mv_is_value_missing (const struct missing_values *mv, const union value *v)
-{
-  return (mv->width == 0
-          ? mv_is_num_missing (mv, v->f)
-          : mv_is_str_missing (mv, v->s));
-}
-
-/* Returns true if D is system missing or a missing value in MV,
-   false otherwise.
-   MV must be a set of numeric missing values. */
-bool
-mv_is_num_missing (const struct missing_values *mv, double d)
-{
-  assert (mv->width == 0);
-  return d == SYSMIS || mv_is_num_user_missing (mv, d);
-}
-
-/* Returns true if S[] is a missing value in MV, false otherwise.
-   MV must be a set of string missing values. 
-   S[] must contain exactly as many characters as MV's width. */
-bool
-mv_is_str_missing (const struct missing_values *mv, const char s[])
-{
-  return mv_is_str_user_missing (mv, s);
-}
-
-/* Returns true if V is a missing value in MV, false otherwise. */
-bool
-mv_is_value_user_missing (const struct missing_values *mv,
-                          const union value *v)
-{
-  return (mv->width == 0
-          ? mv_is_num_user_missing (mv, v->f)
-          : mv_is_str_user_missing (mv, v->s));
-}
-
 /* Returns true if D is a missing value in MV, false otherwise.
    MV must be a set of numeric missing values. */
-bool
-mv_is_num_user_missing (const struct missing_values *mv, double d)
+static bool
+is_num_user_missing (const struct missing_values *mv, double d)
 {
   const union value *v = mv->values;
   assert (mv->width == 0);
   switch (mv->type) 
     {
-    case MV_NONE:
+    case MVT_NONE:
       return false;
-    case MV_1:
+    case MVT_1:
       return v[0].f == d;
-    case MV_2:
+    case MVT_2:
       return v[0].f == d || v[1].f == d;
-    case MV_3:
+    case MVT_3:
       return v[0].f == d || v[1].f == d || v[2].f == d;
-    case MV_RANGE:
+    case MVT_RANGE:
       return v[1].f <= d && d <= v[2].f;
-    case MV_RANGE_1:
+    case MVT_RANGE_1:
       return v[0].f == d || (v[1].f <= d && d <= v[2].f);
     }
   NOT_REACHED ();
@@ -408,37 +380,63 @@ mv_is_num_user_missing (const struct mis
 /* Returns true if S[] is a missing value in MV, false otherwise.
    MV must be a set of string missing values. 
    S[] must contain exactly as many characters as MV's width. */
-bool
-mv_is_str_user_missing (const struct missing_values *mv,
+static bool
+is_str_user_missing (const struct missing_values *mv,
                         const char s[])
 {
   const union value *v = mv->values;
   assert (mv->width > 0);
   switch (mv->type) 
     {
-    case MV_NONE:
+    case MVT_NONE:
       return false;
-    case MV_1:
+    case MVT_1:
       return !memcmp (v[0].s, s, mv->width);
-    case MV_2:
+    case MVT_2:
       return (!memcmp (v[0].s, s, mv->width)
               || !memcmp (v[1].s, s, mv->width));
-    case MV_3:
+    case MVT_3:
       return (!memcmp (v[0].s, s, mv->width)
               || !memcmp (v[1].s, s, mv->width)
               || !memcmp (v[2].s, s, mv->width));
-    case MV_RANGE:
-    case MV_RANGE_1:
+    case MVT_RANGE:
+    case MVT_RANGE_1:
       NOT_REACHED ();
     }
   NOT_REACHED ();
 }
 
-/* Returns true if MV is a set of numeric missing values and V is
-   the system missing value. */
+/* Returns true if V is a missing value in the given CLASS in MV,
+   false otherwise. */
 bool
-mv_is_value_system_missing (const struct missing_values *mv,
-                            const union value *v)
+mv_is_value_missing (const struct missing_values *mv, const union value *v,
+                     enum mv_class class)
 {
-  return mv->width == 0 && v->f == SYSMIS;
+  return (mv->width == 0
+          ? mv_is_num_missing (mv, v->f, class)
+          : mv_is_str_missing (mv, v->s, class));
+}
+
+/* Returns true if D is a missing value in the given CLASS in MV,
+   false otherwise.
+   MV must be a set of numeric missing values. */
+bool
+mv_is_num_missing (const struct missing_values *mv, double d,
+                   enum mv_class class)
+{
+  assert (mv->width == 0);
+  return ((class & MV_SYSTEM && d == SYSMIS)
+          || (class & MV_USER && is_num_user_missing (mv, d)));
+}
+
+/* Returns true if S[] is a missing value in the given CLASS in
+   MV, false otherwise.
+   MV must be a set of string missing values. 
+   S[] must contain exactly as many characters as MV's width. */
+bool
+mv_is_str_missing (const struct missing_values *mv, const char s[],
+                   enum mv_class class)
+{
+  assert (mv->width > 0);
+  return class & MV_USER && is_str_user_missing (mv, s);
 }
Index: src/data/missing-values.h
===================================================================
RCS file: /cvsroot/pspp/pspp/src/data/missing-values.h,v
retrieving revision 1.5
diff -u -p -r1.5 missing-values.h
--- src/data/missing-values.h	16 Dec 2006 03:40:41 -0000	1.5
+++ src/data/missing-values.h	22 Dec 2006 22:19:33 -0000
@@ -22,30 +22,26 @@
 #include <stdbool.h>
 #include "value.h"
 
-/* Types of user-missing values.
-   Invisible--use access functions defined below instead. */
-enum mv_type
-  {
-    MV_NONE = 0,                /* No user-missing values. */
-    MV_1 = 1,                   /* One user-missing value. */
-    MV_2 = 2,                   /* Two user-missing values. */
-    MV_3 = 3,                   /* Three user-missing values. */
-    MV_RANGE = 4,               /* A range of user-missing values. */
-    MV_RANGE_1 = 5              /* A range plus an individual value. */
-  };
-
 /* Missing values.
    Opaque--use access functions defined below. */
 struct missing_values
   {
-    enum mv_type type;          /* Number and type of missing values. */
+    int type;                   /* Types of missing values, one of MVT_*. */
     int width;                  /* 0=numeric, otherwise string width. */
     union value values[3];      /* Missing values.  [y,z] are the range. */
   };
 
+/* Classes of missing values. */
+enum mv_class 
+  {
+    MV_NEVER = 0,               /* Never considered missing. */
+    MV_USER = 1,                /* Missing if value is user-missing. */
+    MV_SYSTEM = 2,              /* Missing if value is system-missing. */
+    MV_ANY = MV_USER | MV_SYSTEM /* Missing if it is user or system-missing. */
+  };
 
 void mv_init (struct missing_values *, int width);
-void mv_set_type(struct missing_values *mv, enum mv_type type);
+void mv_clear (struct missing_values *);
 
 void mv_copy (struct missing_values *, const struct missing_values *);
 bool mv_is_empty (const struct missing_values *);
@@ -74,19 +70,11 @@ void mv_resize (struct missing_values *,
 typedef bool mv_is_missing_func (const struct missing_values *,
                                  const union value *);
 
-/* Is a value system or user missing? */
-bool mv_is_value_missing (const struct missing_values *, const union value *);
-bool mv_is_num_missing (const struct missing_values *, double);
-bool mv_is_str_missing (const struct missing_values *, const char[]);
-
-/* Is a value user missing? */
-bool mv_is_value_user_missing (const struct missing_values *,
-                               const union value *);
-bool mv_is_num_user_missing (const struct missing_values *, double);
-bool mv_is_str_user_missing (const struct missing_values *, const char[]);
-
-/* Is a value system missing? */
-bool mv_is_value_system_missing (const struct missing_values *,
-                                 const union value *);
+/* Is a value missing? */
+bool mv_is_value_missing (const struct missing_values *, const union value *,
+                          enum mv_class);
+bool mv_is_num_missing (const struct missing_values *, double, enum mv_class);
+bool mv_is_str_missing (const struct missing_values *, const char[],
+                        enum mv_class);
 
 #endif /* missing-values.h */
Index: src/data/procedure.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/data/procedure.c,v
retrieving revision 1.20
diff -u -p -r1.20 procedure.c
--- src/data/procedure.c	22 Dec 2006 11:12:14 -0000	1.20
+++ src/data/procedure.c	22 Dec 2006 22:19:34 -0000
@@ -978,7 +978,7 @@ filter_trns_proc (void *filter_var_,
 {
   struct variable *filter_var = filter_var_;
   double f = case_num (c, filter_var);
-  return (f != 0.0 && !var_is_num_missing (filter_var, f)
+  return (f != 0.0 && !var_is_num_missing (filter_var, f, MV_ANY)
           ? TRNS_CONTINUE : TRNS_DROP_CASE);
 }
 
Index: src/data/variable.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/data/variable.c,v
retrieving revision 1.20
diff -u -p -r1.20 variable.c
--- src/data/variable.c	20 Dec 2006 10:10:51 -0000	1.20
+++ src/data/variable.c	22 Dec 2006 22:19:34 -0000
@@ -466,64 +466,32 @@ var_has_missing_values (const struct var
   return !mv_is_empty (&v->miss);
 }
 
-/* Returns true if VALUE is system missing or user-missing value
-   for V, false otherwise. */
+/* Returns true if VALUE is in the given CLASS of missing values
+   in V, false otherwise. */
 bool
-var_is_value_missing (const struct variable *v, const union value *value) 
+var_is_value_missing (const struct variable *v, const union value *value,
+                      enum mv_class class) 
 {
-  return mv_is_value_missing (&v->miss, value);
+  return mv_is_value_missing (&v->miss, value, class);
 }
 
-/* Returns true if D is system missing or a missing value in V,
-   false otherwise.
+/* Returns true if D is in the given CLASS of missing values in
+   V, false otherwise.
    V must be a numeric variable. */
 bool
-var_is_num_missing (const struct variable *v, double d) 
+var_is_num_missing (const struct variable *v, double d, enum mv_class class) 
 {
-  return mv_is_num_missing (&v->miss, d);
+  return mv_is_num_missing (&v->miss, d, class);
 }
 
 /* Returns true if S[] is a missing value for V, false otherwise.
    S[] must contain exactly as many characters as V's width.
    V must be a string variable. */
 bool
-var_is_str_missing (const struct variable *v, const char s[]) 
+var_is_str_missing (const struct variable *v, const char s[],
+                    enum mv_class class) 
 {
-  return mv_is_str_missing (&v->miss, s);
-}
-
-/* Returns true if VALUE is a missing value for V, false
-   otherwise. */
-bool
-var_is_value_user_missing (const struct variable *v, const union value *value) 
-{
-  return mv_is_value_user_missing (&v->miss, value);
-}
-
-/* Returns true if D is a user-missing value for V, false
-   otherwise.  V must be a numeric variable. */
-bool
-var_is_num_user_missing (const struct variable *v, double d) 
-{
-  return mv_is_num_user_missing (&v->miss, d);
-}
-
-/* Returns true if S[] is a missing value for V, false otherwise.
-   V must be a string variable. 
-   S[] must contain exactly as many characters as V's width. */
-bool
-var_is_str_user_missing (const struct variable *v, const char s[]) 
-{
-  return mv_is_str_user_missing (&v->miss, s);
-}
-
-/* Returns true if V is a numeric variable and VALUE is the
-   system missing value. */
-bool
-var_is_value_system_missing (const struct variable *v,
-                             const union value *value) 
-{
-  return mv_is_value_system_missing (&v->miss, value);
+  return mv_is_str_missing (&v->miss, s, class);
 }
 
 /* Returns variable V's value labels,
Index: src/data/variable.h
===================================================================
RCS file: /cvsroot/pspp/pspp/src/data/variable.h,v
retrieving revision 1.18
diff -u -p -r1.18 variable.h
--- src/data/variable.h	16 Dec 2006 22:11:08 -0000	1.18
+++ src/data/variable.h	22 Dec 2006 22:19:34 -0000
@@ -20,8 +20,8 @@
 #define variable_h 1
 
 #include <stddef.h>
-#include "config.h"
 #include <stdbool.h>
+#include <data/missing-values.h>
 
 union value;
 
@@ -73,17 +73,10 @@ void var_set_missing_values (struct vari
 void var_clear_missing_values (struct variable *);
 bool var_has_missing_values (const struct variable *);
 
-typedef bool var_is_missing_func (const struct variable *,
-                                  const union value *);
-bool var_is_value_missing (const struct variable *, const union value *);
-bool var_is_num_missing (const struct variable *, double);
-bool var_is_str_missing (const struct variable *, const char[]);
-bool var_is_value_user_missing (const struct variable *,
-                                const union value *);
-bool var_is_num_user_missing (const struct variable *, double);
-bool var_is_str_user_missing (const struct variable *, const char[]);
-bool var_is_value_system_missing (const struct variable *,
-                                  const union value *);
+bool var_is_value_missing (const struct variable *, const union value *,
+                           enum mv_class);
+bool var_is_num_missing (const struct variable *, double, enum mv_class);
+bool var_is_str_missing (const struct variable *, const char[], enum mv_class);
 
 /* Value labels. */
 const struct val_labs *var_get_value_labels (const struct variable *);
Index: src/language/expressions/operations.def
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/expressions/operations.def,v
retrieving revision 1.15
diff -u -p -r1.15 operations.def
--- src/language/expressions/operations.def	16 Dec 2006 20:22:14 -0000	1.15
+++ src/language/expressions/operations.def	22 Dec 2006 22:19:35 -0000
@@ -927,7 +927,7 @@ no_opt operator VEC_ELEM_NUM (idx)
     {
       const struct variable *var = vector_get_var (v, (size_t) idx - 1);
       double value = case_num (c, var);
-      return !var_is_num_user_missing (var, value) ? value : SYSMIS; 
+      return !var_is_num_missing (var, value, MV_USER) ? value : SYSMIS; 
     }
   else
     {
@@ -974,7 +974,7 @@ no_opt operator NUM_VAR ()
      num_var v;
 {
   double d = case_num (c, v);
-  return !var_is_num_user_missing (v, d) ? d : SYSMIS;
+  return !var_is_num_missing (v, d, MV_USER) ? d : SYSMIS;
 }
 
 no_opt string operator STR_VAR ()
@@ -994,7 +994,7 @@ no_opt perm_only function LAG (num_var v
   if (c != NULL)
     {
       double x = case_num (c, v);
-      return !var_is_num_user_missing (v, x) ? x : SYSMIS;
+      return !var_is_num_missing (v, x, MV_USER) ? x : SYSMIS;
     }
   else
     return SYSMIS;
@@ -1007,7 +1007,7 @@ no_opt perm_only function LAG (num_var v
   if (c != NULL)
     {
       double x = case_num (c, v);
-      return !var_is_num_user_missing (v, x) ? x : SYSMIS;
+      return !var_is_num_missing (v, x, MV_USER) ? x : SYSMIS;
     }
   else
     return SYSMIS;
Index: src/language/stats/ChangeLog
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/stats/ChangeLog,v
retrieving revision 1.39
diff -u -p -r1.39 ChangeLog
--- src/language/stats/ChangeLog	22 Dec 2006 10:24:18 -0000	1.39
+++ src/language/stats/ChangeLog	22 Dec 2006 22:19:35 -0000
@@ -1,3 +1,20 @@
+Fri Dec 22 14:04:09 2006  Ben Pfaff  <blp@gnu.org>
+
+	Simplify missing value handling.
+	
+	* aggregate.c (struct agr_var): Remove `bool include_missing', add
+	`enum mv_class exclude'.  Remove `int missing', add `bool
+	saw_missing'.  Update users.
+
+	* descriptives.c (struct dsc_trns): Removed `int
+	include_user_missing', add `enum mv_class exclude'.  Update users.
+	(struct dsc_proc): Ditto.
+
+	* examine.q: (static var value_is_missing): Rename
+	`exclude_values', change type to `enum mv_class'.  Update users.
+
+	* rank.q: Ditto.
+
 Fri Dec 22 19:22:18 WST 2006 John Darrington <john@darrington.wattle.id.au>
 
 	* frequencies.q : Fixed bug #17420, where the table bounds were overun
Index: src/language/stats/aggregate.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/stats/aggregate.c,v
retrieving revision 1.26
diff -u -p -r1.26 aggregate.c
--- src/language/stats/aggregate.c	22 Dec 2006 11:12:14 -0000	1.26
+++ src/language/stats/aggregate.c	22 Dec 2006 22:19:36 -0000
@@ -67,14 +67,14 @@ struct agr_var
     struct variable *src;	/* Source variable. */
     struct variable *dest;	/* Target variable. */
     int function;		/* Function. */
-    int include_missing;	/* 1=Include user-missing values. */
+    enum mv_class exclude;      /* Classes of missing values to exclude. */
     union agr_argument arg[2];	/* Arguments. */
 
     /* Accumulated during AGGREGATE execution. */
     double dbl[3];
     int int1, int2;
     char *string;
-    int missing;
+    bool saw_missing;
     struct moments1 *moments;
   };
 
@@ -391,7 +391,7 @@ parse_aggregate_functions (struct lexer 
       size_t n_dest;
       struct string function_name;
 
-      int include_missing;
+      enum mv_class exclude;
       const struct agr_func *function;
       int func_index;
 
@@ -450,14 +450,14 @@ parse_aggregate_functions (struct lexer 
 	  goto error;
 	}
 
-      include_missing = 0;
+      exclude = MV_ANY;
 
       ds_init_string (&function_name, lex_tokstr (lexer));
 
       ds_chomp (&function_name, '.');
 
       if (lex_tokid(lexer)[strlen (lex_tokid (lexer)) - 1] == '.')
-	  include_missing = 1;
+        exclude = MV_SYSTEM;
 
       for (function = agr_func_tab; function->name; function++)
 	if (!strcasecmp (function->name, ds_cstr (&function_name)))
@@ -652,7 +652,7 @@ parse_aggregate_functions (struct lexer 
 	    v->dest = destvar;
 	  }
 	  
-	  v->include_missing = include_missing;
+	  v->exclude = exclude;
 
 	  if (v->src != NULL)
 	    {
@@ -793,9 +793,7 @@ accumulate_aggregate_info (struct agr_pr
 	const union value *v = case_data (input, iter->src);
         int src_width = var_get_width (iter->src);
 
-	if (iter->include_missing
-            ? var_is_numeric (iter->src) && v->f == SYSMIS
-            : var_is_value_missing (iter->src, v))
+        if (var_is_value_missing (iter->src, v, iter->exclude))
 	  {
 	    switch (iter->function)
 	      {
@@ -808,7 +806,7 @@ accumulate_aggregate_info (struct agr_pr
 		iter->int1++;
 		break;
 	      }
-	    iter->missing = 1;
+	    iter->saw_missing = true;
 	    continue;
 	  }
 	
@@ -977,7 +975,7 @@ dump_aggregate_info (struct agr_proc *ag
       {
 	union value *v = case_data_rw (output, i->dest);
 
-	if (agr->missing == COLUMNWISE && i->missing != 0
+	if (agr->missing == COLUMNWISE && i->saw_missing
 	    && (i->function & FUNC) != N && (i->function & FUNC) != NU
 	    && (i->function & FUNC) != NMISS && (i->function & FUNC) != NUMISS)
 	  {
@@ -1091,7 +1089,7 @@ initialize_aggregate_info (struct agr_pr
 
   for (iter = agr->agr_vars; iter; iter = iter->next)
     {
-      iter->missing = 0;
+      iter->saw_missing = false;
       iter->dbl[0] = iter->dbl[1] = iter->dbl[2] = 0.0;
       iter->int1 = iter->int2 = 0;
       switch (iter->function)
Index: src/language/stats/crosstabs.q
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/stats/crosstabs.q,v
retrieving revision 1.26
diff -u -p -r1.26 crosstabs.q
--- src/language/stats/crosstabs.q	15 Dec 2006 00:16:02 -0000	1.26
+++ src/language/stats/crosstabs.q	22 Dec 2006 22:19:40 -0000
@@ -569,6 +569,11 @@ calc_general (const struct ccase *c, voi
 {
   bool bad_warn = true;
 
+  /* Missing values to exclude. */
+  enum mv_class exclude = (cmd.miss == CRS_TABLE ? MV_ANY
+                           : cmd.miss == CRS_INCLUDE ? MV_SYSTEM
+                           : MV_NEVER);
+
   /* Case weight. */
   double weight = dict_get_case_weight (dataset_dict (ds), c, &bad_warn);
 
@@ -591,9 +596,7 @@ calc_general (const struct ccase *c, voi
 	for (j = 0; j < x->nvar; j++)
 	  {
             const union value *v = case_data (c, x->vars[j]);
-	    if ((cmd.miss == CRS_TABLE && var_is_value_missing (x->vars[j], v))
-		|| (cmd.miss == CRS_INCLUDE
-		    && var_is_value_system_missing (x->vars[j], v)))
+            if (var_is_value_missing (x->vars[j], v, exclude))
 	      {
 		x->missing += weight;
 		goto next_crosstab;
@@ -663,7 +666,8 @@ calc_integer (const struct ccase *c, voi
 	  
 	  /* Note that the first test also rules out SYSMIS. */
 	  if ((value < vr->min || value >= vr->max)
-	      || (cmd.miss == CRS_TABLE && var_is_num_user_missing (v, value)))
+	      || (cmd.miss == CRS_TABLE
+                  && var_is_num_missing (v, value, MV_USER)))
 	    {
 	      x->missing += weight;
 	      goto next_crosstab;
@@ -1421,7 +1425,7 @@ delete_missing (void)
     int r;
 
     for (r = 0; r < n_rows; r++)
-      if (var_is_num_user_missing (x->vars[ROW_VAR], rows[r].f))
+      if (var_is_num_missing (x->vars[ROW_VAR], rows[r].f, MV_USER))
 	{
 	  int c;
 
@@ -1435,7 +1439,7 @@ delete_missing (void)
     int c;
 
     for (c = 0; c < n_cols; c++)
-      if (var_is_num_user_missing (x->vars[COL_VAR], cols[c].f))
+      if (var_is_num_missing (x->vars[COL_VAR], cols[c].f, MV_USER))
 	{
 	  int r;
 
@@ -1675,7 +1679,7 @@ table_value_missing (struct tab_table *t
   s.string = tab_alloc (table, print->w);
   format_short (s.string, print, v);
   s.length = strlen (s.string);
-  if (cmd.miss == CRS_REPORT && var_is_num_user_missing (var, v->f))
+  if (cmd.miss == CRS_REPORT && var_is_num_missing (var, v->f, MV_USER))
     s.string[s.length++] = 'M';
   while (s.length && *s.string == ' ')
     {
@@ -1758,8 +1762,9 @@ display_crosstabulation (void)
             bool mark_missing = false;
             double expected_value = row_tot[r] * col_tot[c] / W;
             if (cmd.miss == CRS_REPORT
-                && (var_is_num_user_missing (x->vars[COL_VAR], cols[c].f)
-                    || var_is_num_user_missing (x->vars[ROW_VAR], rows[r].f)))
+                && (var_is_num_missing (x->vars[COL_VAR], cols[c].f, MV_USER)
+                    || var_is_num_missing (x->vars[ROW_VAR], rows[r].f,
+                                           MV_USER)))
               mark_missing = true;
 	    for (i = 0; i < num_cells; i++)
 	      {
@@ -1823,7 +1828,7 @@ display_crosstabulation (void)
         bool mark_missing = false;
 
         if (cmd.miss == CRS_REPORT
-            && var_is_num_user_missing (x->vars[ROW_VAR], rows[r].f))
+            && var_is_num_missing (x->vars[ROW_VAR], rows[r].f, MV_USER))
           mark_missing = true;
 
         for (i = 0; i < num_cells; i++)
@@ -1878,7 +1883,7 @@ display_crosstabulation (void)
         int i;
 	    
         if (cmd.miss == CRS_REPORT && c < n_cols 
-            && var_is_num_user_missing (x->vars[COL_VAR], cols[c].f))
+            && var_is_num_missing (x->vars[COL_VAR], cols[c].f, MV_USER))
           mark_missing = true;
 
         for (i = 0; i < num_cells; i++)
Index: src/language/stats/descriptives.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/stats/descriptives.c,v
retrieving revision 1.20
diff -u -p -r1.20 descriptives.c
--- src/language/stats/descriptives.c	15 Dec 2006 00:16:02 -0000	1.20
+++ src/language/stats/descriptives.c	22 Dec 2006 22:19:40 -0000
@@ -77,7 +77,7 @@ struct dsc_trns
     struct variable **vars;     /* Variables for listwise missing checks. */
     size_t var_cnt;             /* Number of variables. */
     enum dsc_missing_type missing_type; /* Treatment of missing values. */
-    int include_user_missing;   /* Nonzero to include user-missing values. */
+    enum mv_class exclude;      /* Classes of missing values to exclude. */
   };
 
 /* Statistics.  Used as bit indexes, so must be 32 or fewer. */
@@ -150,7 +150,7 @@ struct dsc_proc 
 
     /* User options. */
     enum dsc_missing_type missing_type; /* Treatment of missing values. */
-    int include_user_missing;   /* Nonzero to include user-missing values. */
+    enum mv_class exclude;      /* Classes of missing values to exclude. */
     int show_var_labels;        /* Nonzero to show variable labels. */
     int show_index;             /* Nonzero to show variable index. */
     enum dsc_format format;     /* Output format. */
@@ -205,7 +205,7 @@ cmd_descriptives (struct lexer *lexer, s
   dsc->vars = NULL;
   dsc->var_cnt = 0;
   dsc->missing_type = DSC_VARIABLE;
-  dsc->include_user_missing = 0;
+  dsc->exclude = MV_ANY;
   dsc->show_var_labels = 1;
   dsc->show_index = 0;
   dsc->format = DSC_LINE;
@@ -229,7 +229,7 @@ cmd_descriptives (struct lexer *lexer, s
               else if (lex_match_id (lexer, "LISTWISE"))
                 dsc->missing_type = DSC_LISTWISE;
               else if (lex_match_id (lexer, "INCLUDE"))
-                dsc->include_user_missing = 1;
+                dsc->exclude = MV_SYSTEM;
               else
                 {
                   lex_error (lexer, NULL);
@@ -595,9 +595,7 @@ descriptives_trns_proc (void *trns_, str
       for (vars = t->vars; vars < t->vars + t->var_cnt; vars++)
 	{
 	  double score = case_num (c, *vars);
-	  if ( score == SYSMIS
-               || (!t->include_user_missing 
-                   && var_is_num_user_missing (*vars, score)))
+	  if (var_is_num_missing (*vars, score, t->exclude))
 	    {
 	      all_sysmis = 1;
 	      break;
@@ -610,10 +608,8 @@ descriptives_trns_proc (void *trns_, str
       double input = case_num (c, z->src_var);
       double *output = &case_data_rw (c, z->z_var)->f;
 
-      if (z->mean == SYSMIS || z->std_dev == SYSMIS 
-	  || all_sysmis || input == SYSMIS 
-	  || (!t->include_user_missing
-              && var_is_num_user_missing (z->src_var, input)))
+      if (z->mean == SYSMIS || z->std_dev == SYSMIS || all_sysmis
+          || var_is_num_missing (z->src_var, input, t->exclude))
 	*output = SYSMIS;
       else
 	*output = (input - z->mean) / z->std_dev;
@@ -648,7 +644,7 @@ setup_z_trns (struct dsc_proc *dsc, stru
   t->z_scores = xnmalloc (cnt, sizeof *t->z_scores);
   t->z_score_cnt = cnt;
   t->missing_type = dsc->missing_type;
-  t->include_user_missing = dsc->include_user_missing;
+  t->exclude = dsc->exclude;
   if ( t->missing_type == DSC_LISTWISE )
     {
       t->var_cnt = dsc->var_cnt;
@@ -741,9 +737,7 @@ calc_descriptives (const struct ccase *f
           double x = case_num (&c, dv->v);
           
           if (dsc->missing_type != DSC_LISTWISE
-              && (x == SYSMIS
-                  || (!dsc->include_user_missing
-                      && var_is_num_user_missing (dv->v, x))))
+              && var_is_num_missing (dv->v, x, dsc->exclude))
             {
               dv->missing += weight;
               continue;
@@ -773,8 +767,7 @@ calc_descriptives (const struct ccase *f
             continue;
       
           /* Check for missing values. */
-          if (listwise_missing (dsc, &c) 
-              && dsc->missing_type == DSC_LISTWISE)
+          if (dsc->missing_type == DSC_LISTWISE && listwise_missing (dsc, &c))
             continue; 
 
           for (i = 0; i < dsc->var_cnt; i++) 
@@ -783,9 +776,7 @@ calc_descriptives (const struct ccase *f
               double x = case_num (&c, dv->v);
           
               if (dsc->missing_type != DSC_LISTWISE
-                  && (x == SYSMIS
-                      || (!dsc->include_user_missing
-                          && var_is_num_user_missing (dv->v, x))))
+                  && var_is_num_missing (dv->v, x, dsc->exclude))
                 continue;
 
               if (dv->moments != NULL)
@@ -849,9 +840,7 @@ listwise_missing (struct dsc_proc *dsc, 
       struct dsc_var *dv = &dsc->vars[i];
       double x = case_num (c, dv->v);
 
-      if (x == SYSMIS
-          || (!dsc->include_user_missing
-              && var_is_num_user_missing (dv->v, x)))
+      if (var_is_num_missing (dv->v, x, dsc->exclude))
         return true;
     }
   return false;
Index: src/language/stats/examine.q
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/stats/examine.q,v
retrieving revision 1.21
diff -u -p -r1.21 examine.q
--- src/language/stats/examine.q	16 Dec 2006 04:26:42 -0000	1.21
+++ src/language/stats/examine.q	22 Dec 2006 22:19:40 -0000
@@ -178,9 +178,8 @@ const char *factor_to_string_concise (co
 
 
 
-/* Function to use for testing for missing values */
-static var_is_missing_func *value_is_missing;
-
+/* Categories of missing values to exclude. */
+static enum mv_class exclude_values;
 
 /* PERCENTILES */
 
@@ -206,10 +205,7 @@ cmd_examine (struct lexer *lexer, struct
     }
 
   /* If /MISSING=INCLUDE is set, then user missing values are ignored */
-  if (cmd.incl == XMN_INCLUDE )
-    value_is_missing = var_is_value_system_missing;
-  else
-    value_is_missing = var_is_value_missing;
+  exclude_values = cmd.incl == XMN_INCLUDE ? MV_SYSTEM : MV_ANY;
 
   if ( cmd.st_n == SYSMIS )
     cmd.st_n = 5;
@@ -695,7 +691,7 @@ factor_calc (const struct ccase *c, int 
 					var_get_width (var)
 					);
 
-	  if ( value_is_missing (var, val) || case_missing )
+	  if (case_missing || var_is_value_missing (var, val, exclude_values))
 	    {
 	      free (val);
 	      continue;
@@ -762,7 +758,7 @@ run_examine (const struct ccase *first, 
 						  var_get_width (var)
 						  );
 
-	      if ( value_is_missing (var, val))
+	      if ( var_is_value_missing (var, val, exclude_values))
 		case_missing = 1;
 
 	      free (val);
@@ -777,7 +773,8 @@ run_examine (const struct ccase *first, 
 					var_get_width (var)
 					);
 
-	  if ( value_is_missing (var, val) || case_missing )
+	  if ( var_is_value_missing (var, val, exclude_values)
+               || case_missing )
 	    {
 	      free (val) ;
 	      continue ;
Index: src/language/stats/frequencies.q
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/stats/frequencies.q,v
retrieving revision 1.28
diff -u -p -r1.28 frequencies.q
--- src/language/stats/frequencies.q	22 Dec 2006 10:24:18 -0000	1.28
+++ src/language/stats/frequencies.q	22 Dec 2006 22:19:41 -0000
@@ -700,7 +700,7 @@ not_missing (const void *f_, const void 
   const struct freq *f = f_;
   const struct variable *v = v_;
 
-  return !var_is_value_missing (v, f->value);
+  return !var_is_value_missing (v, f->value, MV_ANY);
 }
 
 /* Summarizes the frequency table data for variable V. */
@@ -1564,7 +1564,7 @@ freq_tab_to_hist(const struct freq_tab *
   /* Find out the extremes of the x value */
   for ( frq = hsh_first(fh, &hi); frq != 0; frq = hsh_next(fh, &hi) ) 
     {
-      if ( var_is_value_missing(var, frq->value))
+      if (var_is_value_missing(var, frq->value, MV_ANY))
 	continue;
 
       if ( frq->value[0].f < x_min ) x_min = frq->value[0].f ;
Index: src/language/stats/npar.q
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/stats/npar.q,v
retrieving revision 1.1
diff -u -p -r1.1 npar.q
--- src/language/stats/npar.q	20 Dec 2006 10:10:51 -0000	1.1
+++ src/language/stats/npar.q	22 Dec 2006 22:19:41 -0000
@@ -180,7 +180,7 @@ cmd_npar_tests (struct lexer *lexer, str
     }
 
   npar_specs.filter = 
-    casefilter_create (cmd.incl == NPAR_EXCLUDE, 0, 0);
+    casefilter_create (cmd.incl == NPAR_EXCLUDE ? MV_ANY : MV_SYSTEM, 0, 0);
 
   if ( cmd.miss == NPAR_LISTWISE ) 
     casefilter_add_variables (npar_specs.filter, 
Index: src/language/stats/oneway.q
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/stats/oneway.q,v
retrieving revision 1.18
diff -u -p -r1.18 oneway.q
--- src/language/stats/oneway.q	16 Dec 2006 04:26:42 -0000	1.18
+++ src/language/stats/oneway.q	22 Dec 2006 22:19:41 -0000
@@ -900,7 +900,8 @@ run_oneway(const struct ccase *first, co
 
   precalc(cmd);
 
-  filter = casefilter_create ( (cmd->incl != ONEWAY_INCLUDE), 
+  filter = casefilter_create ( (cmd->incl != ONEWAY_INCLUDE
+                                ? MV_ANY : MV_SYSTEM), 
 			       vars, n_vars );
 
   for(r = casefile_get_reader (cf, filter);
Index: src/language/stats/rank.q
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/stats/rank.q,v
retrieving revision 1.24
diff -u -p -r1.24 rank.q
--- src/language/stats/rank.q	22 Dec 2006 11:12:14 -0000	1.24
+++ src/language/stats/rank.q	22 Dec 2006 22:19:42 -0000
@@ -148,8 +148,8 @@ struct rank_spec
 };
 
 
-/* Function to use for testing for missing values */
-static mv_is_missing_func *value_is_missing;
+/* Categories of missing values to exclude. */
+static enum mv_class exclude_values;
 
 static struct rank_spec *rank_specs;
 static size_t n_rank_specs;
@@ -547,7 +547,7 @@ rank_cases (struct casereader *cr,
       casereader_destroy (lookahead);
 
       cc_1 = cc;
-      if ( !value_is_missing (mv, this_value) )
+      if ( !mv_is_value_missing (mv, this_value, exclude_values) )
 	cc += c;
 
       do
@@ -556,7 +556,7 @@ rank_cases (struct casereader *cr,
             {
               const struct variable *dst_var = rs[i].destvars[dest_var_index];
 
-	      if  ( value_is_missing (mv, this_value) )
+	      if  ( mv_is_value_missing (mv, this_value, exclude_values) )
 		case_data_rw (&this_case, dst_var)->f = SYSMIS;
 	      else
 		case_data_rw (&this_case, dst_var)->f = 
@@ -566,7 +566,7 @@ rank_cases (struct casereader *cr,
         }
       while (n-- > 0 && casereader_read_xfer (cr, &this_case));
 
-      if ( !value_is_missing (mv, this_value) )
+      if ( !mv_is_value_missing (mv, this_value, exclude_values) )
 	iter++;
     }
 
@@ -615,7 +615,7 @@ rank_sorted_casefile (struct casefile *c
       double w = 0.0;
       this_value = case_data_idx( &group_case, ultimate_crit->fv);
 
-      if ( !value_is_missing(mv, this_value) )
+      if ( !mv_is_value_missing (mv, this_value, exclude_values) )
 	w = dict_get_case_weight (dict, &group_case, &warn);
 
       while (casereader_read (lookahead, &this_case)) 
@@ -636,7 +636,7 @@ rank_sorted_casefile (struct casefile *c
               case_destroy (&group_case);
               case_move (&group_case, &this_case);
             }
-	  if ( !value_is_missing (mv, this_value) )
+	  if ( !mv_is_value_missing (mv, this_value, exclude_values) )
 	    w += c;
           case_destroy (&this_case);
         }
@@ -773,11 +773,7 @@ cmd_rank (struct lexer *lexer, struct da
     }
 
   /* If /MISSING=INCLUDE is set, then user missing values are ignored */
-  if (cmd.miss == RANK_INCLUDE ) 
-    value_is_missing = mv_is_value_system_missing;
-  else
-    value_is_missing = mv_is_value_missing;
-
+  exclude_values = cmd.miss == RANK_INCLUDE ? MV_SYSTEM : MV_ANY;
 
   /* Default to /RANK if no function subcommands are given */
   if ( !( cmd.sbc_normal  || cmd.sbc_ntiles || cmd.sbc_proportion || 
Index: src/language/stats/regression.q
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/stats/regression.q,v
retrieving revision 1.42
diff -u -p -r1.42 regression.q
--- src/language/stats/regression.q	16 Dec 2006 22:38:01 -0000	1.42
+++ src/language/stats/regression.q	22 Dec 2006 22:19:43 -0000
@@ -978,7 +978,7 @@ mark_missing_cases (const struct casefil
 
       val = case_data (&c, v);
       cat_value_update (v, val);
-      if (var_is_value_missing (v, val))
+      if (var_is_value_missing (v, val, MV_ANY))
 	{
 	  if (!is_missing_case[row])
 	    {
Index: src/language/stats/t-test.q
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/stats/t-test.q,v
retrieving revision 1.18
diff -u -p -r1.18 t-test.q
--- src/language/stats/t-test.q	16 Dec 2006 04:26:42 -0000	1.18
+++ src/language/stats/t-test.q	22 Dec 2006 22:19:44 -0000
@@ -1785,7 +1785,8 @@ calculate(const struct ccase *first, con
 
   struct cmd_t_test *cmd = (struct cmd_t_test *) cmd_;
 
-  struct casefilter *filter = casefilter_create (cmd->miss != TTS_INCLUDE, 
+  struct casefilter *filter = casefilter_create ((cmd->miss != TTS_INCLUDE
+                                                  ? MV_ANY : MV_SYSTEM), 
 						 NULL, 0);
 
   if ( cmd->miss == TTS_LISTWISE ) 
Index: src/language/xforms/count.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/xforms/count.c,v
retrieving revision 1.14
diff -u -p -r1.14 count.c
--- src/language/xforms/count.c	15 Dec 2006 00:16:03 -0000	1.14
+++ src/language/xforms/count.c	22 Dec 2006 22:19:44 -0000
@@ -61,7 +61,7 @@ struct criteria
     struct variable **vars;
     size_t var_cnt;
 
-    /* Count special values?. */
+    /* Count special values? */
     bool count_system_missing;  /* Count system missing? */
     bool count_user_missing;    /* Count user missing? */
 
@@ -277,11 +277,13 @@ count_numeric (struct criteria *crit, st
   for (i = 0; i < crit->var_cnt; i++)
     {
       double x = case_num (c, crit->vars[i]);
-      if (x == SYSMIS)
-        counter += crit->count_system_missing;
-      else if (crit->count_user_missing
-               && var_is_num_user_missing (crit->vars[i], x))
-        counter++;
+      if (var_is_num_missing (crit->vars[i], x, MV_ANY))
+        {
+          if (x == SYSMIS
+              ? crit->count_system_missing
+              : crit->count_user_missing)
+            counter++; 
+        }
       else 
         {
           struct num_value *v;
Index: src/language/xforms/recode.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/language/xforms/recode.c,v
retrieving revision 1.17
diff -u -p -r1.17 recode.c
--- src/language/xforms/recode.c	15 Dec 2006 00:16:03 -0000	1.17
+++ src/language/xforms/recode.c	22 Dec 2006 22:19:45 -0000
@@ -554,7 +554,7 @@ find_src_numeric (struct recode_trns *tr
           match = value == in->x.f;
           break;
         case MAP_MISSING:
-          match = var_is_num_user_missing (v, value);
+          match = var_is_num_missing (v, value, MV_USER);
           break;
         case MAP_RANGE:
           match = value >= in->x.f && value <= in->y.f;
Index: src/math/chart-geometry.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/math/chart-geometry.c,v
retrieving revision 1.2
diff -u -p -r1.2 chart-geometry.c
--- src/math/chart-geometry.c	16 Dec 2006 04:26:43 -0000	1.2
+++ src/math/chart-geometry.c	22 Dec 2006 22:19:45 -0000
@@ -16,7 +16,7 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA. */
 
-
+#include <config.h>
 #include <math.h>
 #include <float.h>
 
Index: src/math/coefficient.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/math/coefficient.c,v
retrieving revision 1.6
diff -u -p -r1.6 coefficient.c
--- src/math/coefficient.c	7 Dec 2006 05:16:33 -0000	1.6
+++ src/math/coefficient.c	22 Dec 2006 22:19:45 -0000
@@ -21,6 +21,7 @@
 /*
   Accessor functions for matching coefficients and variables.
  */
+#include <config.h>
 #include <math/coefficient.h>
 #include <math/linreg/linreg.h>
 #include "src/math/design-matrix.h"
Index: src/math/linreg/linreg.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/math/linreg/linreg.c,v
retrieving revision 1.16
diff -u -p -r1.16 linreg.c
--- src/math/linreg/linreg.c	7 Dec 2006 05:16:33 -0000	1.16
+++ src/math/linreg/linreg.c	22 Dec 2006 22:19:45 -0000
@@ -18,6 +18,7 @@
   Franklin Street, Fifth Floor, Boston, MA 02111-1307, USA.
  */
 
+#include <config.h>
 #include <gsl/gsl_fit.h>
 #include <gsl/gsl_multifit.h>
 
Index: src/math/linreg/predict.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/math/linreg/predict.c,v
retrieving revision 1.11
diff -u -p -r1.11 predict.c
--- src/math/linreg/predict.c	5 Dec 2006 15:10:22 -0000	1.11
+++ src/math/linreg/predict.c	22 Dec 2006 22:19:45 -0000
@@ -18,6 +18,7 @@
    Franklin Street, Fifth Floor, Boston, MA 02111-1307, USA.
  */
 
+#include <config.h>
 #include <math/linreg/linreg.h>
 #include <math/coefficient.h>
 #include <gl/xalloc.h>
Index: src/math/ts/innovations.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/math/ts/innovations.c,v
retrieving revision 1.16
diff -u -p -r1.16 innovations.c
--- src/math/ts/innovations.c	16 Jul 2006 12:49:13 -0000	1.16
+++ src/math/ts/innovations.c	22 Dec 2006 22:19:46 -0000
@@ -28,6 +28,7 @@
   0-387-97429-6. Sections 5.2, 8.3 and 8.4.
  */
 
+#include <config.h>
 #include <gsl/gsl_matrix.h>
 #include <gsl/gsl_vector.h>
 #include <gsl/gsl_math.h>
Index: src/ui/gui/data-sheet.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/ui/gui/data-sheet.c,v
retrieving revision 1.12
diff -u -p -r1.12 data-sheet.c
--- src/ui/gui/data-sheet.c	16 Dec 2006 04:26:43 -0000	1.12
+++ src/ui/gui/data-sheet.c	22 Dec 2006 22:19:46 -0000
@@ -18,6 +18,7 @@
    02110-1301, USA. 
 */
 
+#include <config.h>
 #include <gtk/gtk.h>
 #include <glade/glade.h>
 
Index: src/ui/gui/missing-val-dialog.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/ui/gui/missing-val-dialog.c,v
retrieving revision 1.7
diff -u -p -r1.7 missing-val-dialog.c
--- src/ui/gui/missing-val-dialog.c	16 Dec 2006 04:26:43 -0000	1.7
+++ src/ui/gui/missing-val-dialog.c	22 Dec 2006 22:19:46 -0000
@@ -90,7 +90,7 @@ missing_val_dialog_accept(GtkWidget *w, 
       gint nvals = 0;
       gint badvals = 0;
       gint i;
-      mv_set_type(&dialog->mvl, MV_NONE);
+      mv_clear(&dialog->mvl);
       for(i = 0 ; i < 3 ; ++i ) 
 	{
 	  gchar *text = 
@@ -150,7 +150,7 @@ missing_val_dialog_accept(GtkWidget *w, 
       discrete_text = 
 	g_strdup(gtk_entry_get_text(GTK_ENTRY(dialog->discrete)));
 
-      mv_set_type(&dialog->mvl, MV_NONE);
+      mv_clear(&dialog->mvl);
       mv_add_num_range(&dialog->mvl, low_val.f, high_val.f);
       
       if ( discrete_text && strlen(g_strstrip(discrete_text)) > 0 )
@@ -171,7 +171,7 @@ missing_val_dialog_accept(GtkWidget *w, 
 
   
   if (gtk_toggle_button_get_active(dialog->button_none))
-    mv_set_type(&dialog->mvl, MV_NONE);
+    mv_clear(&dialog->mvl);
 
   var_set_missing_values (dialog->pv, &dialog->mvl);
 
Index: src/ui/gui/psppire-dict.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/ui/gui/psppire-dict.c,v
retrieving revision 1.13
diff -u -p -r1.13 psppire-dict.c
--- src/ui/gui/psppire-dict.c	17 Dec 2006 00:01:05 -0000	1.13
+++ src/ui/gui/psppire-dict.c	22 Dec 2006 22:19:46 -0000
@@ -17,7 +17,7 @@
     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
     02110-1301, USA. */
 
-
+#include <config.h>
 #include <string.h>
 #include <stdlib.h>
 
