+static const struct ctables_cat_value *
+ctables_categories_match (const struct ctables_categories *cats,
+ const union value *v, const struct variable *var)
+{
+ const struct ctables_cat_value *othernm = NULL;
+ for (size_t i = cats->n_values; i-- > 0; )
+ {
+ const struct ctables_cat_value *cv = &cats->values[i];
+ switch (cv->type)
+ {
+ case CCVT_NUMBER:
+ if (cv->number == v->f)
+ return cv;
+ break;
+
+ case CCVT_STRING:
+ NOT_REACHED ();
+
+ case CCVT_RANGE:
+ if ((cv->range[0] == -DBL_MAX || v->f >= cv->range[0])
+ && (cv->range[1] == DBL_MAX || v->f <= cv->range[1]))
+ return cv;
+ break;
+
+ case CCVT_MISSING:
+ if (var_is_value_missing (var, v))
+ return cv;
+ break;
+
+ case CCVT_OTHERNM:
+ if (!othernm)
+ othernm = cv;
+ break;
+
+ case CCVT_SUBTOTAL:
+ case CCVT_HSUBTOTAL:
+ break;
+ }
+ }
+
+ return var_is_value_missing (var, v) ? NULL : othernm;
+}
+