size_t n_tables;
};
+static struct ctables_postcompute *ctables_find_postcompute (struct ctables *,
+ const char *name);
+
struct ctables_postcompute
{
struct hmap_node hmap_node; /* In struct ctables's 'pcompute' hmap. */
CCT_RANGE,
CCT_MISSING,
CCT_OTHERNM,
+ CCT_POSTCOMPUTE,
/* Totals and subtotals. */
CCT_SUBTOTAL,
double number; /* CCT_NUMBER. */
char *string; /* CCT_STRING. */
double range[2]; /* CCT_RANGE. */
- char *total_label; /* CCT_SUBTOTAL, CCT_HSUBTOTAL, CCT_TOTAL. */
+ char *total_label; /* CCT_SUBTOTAL, CCT_HSUBTOTAL, CCT_TOTAL. */
+ const struct ctables_postcompute *pc; /* CCT_POSTCOMPUTE. */
/* CCT_VALUE, CCT_LABEL, CCT_FUNCTION. */
struct
case CCT_RANGE:
case CCT_MISSING:
case CCT_OTHERNM:
+ case CCT_POSTCOMPUTE:
break;
case CCT_STRING:
case CCT_OTHERNM:
return true;
+ case CCT_POSTCOMPUTE:
+ return a->pc == b->pc;
+
case CCT_SUBTOTAL:
case CCT_HSUBTOTAL:
case CCT_TOTAL:
static bool
ctables_table_parse_categories (struct lexer *lexer, struct dictionary *dict,
- struct ctables_table *t)
+ struct ctables *ct, struct ctables_table *t)
{
if (!lex_match_id (lexer, "VARIABLES"))
return false;
};
lex_get (lexer);
}
+ else if (lex_match (lexer, T_AND))
+ {
+ if (!lex_force_id (lexer))
+ return false;
+ struct ctables_postcompute *pc = ctables_find_postcompute (
+ ct, lex_tokcstr (lexer));
+ if (!pc)
+ {
+ struct msg_location *loc = lex_get_location (lexer, -1, 0);
+ msg_at (SE, loc, _("Unknown postcompute &%s."),
+ lex_tokcstr (lexer));
+ msg_location_destroy (loc);
+ return false;
+ }
+ lex_get (lexer);
+
+ *cat = (struct ctables_category) {
+ .type = CCT_POSTCOMPUTE,
+ .pc = pc,
+ };
+ }
else
{
lex_error (lexer, NULL);
cat->subtotal = subtotal;
break;
+ case CCT_POSTCOMPUTE:
+ break;
+
case CCT_SUBTOTAL:
case CCT_HSUBTOTAL:
subtotal = cat;
case CCT_SUBTOTAL:
case CCT_HSUBTOTAL:
case CCT_TOTAL:
+ case CCT_POSTCOMPUTE:
/* Must be equal. */
continue;
return cat;
break;
+ case CCT_POSTCOMPUTE:
+ break;
+
case CCT_OTHERNM:
if (!othernm)
othernm = cat;
ctables_add_occurrence (var, &vl->value, occurrences);
break;
+ case CCT_POSTCOMPUTE:
+ break;
+
case CCT_SUBTOTAL:
case CCT_HSUBTOTAL:
case CCT_TOTAL:
}
else if (lex_match_id (lexer, "CATEGORIES"))
{
- if (!ctables_table_parse_categories (lexer, dataset_dict (ds), t))
+ if (!ctables_table_parse_categories (lexer, dataset_dict (ds),
+ ct, t))
goto error;
}
else if (lex_match_id (lexer, "TITLES"))