diff options
author | Antti-Juhani Kaijanaho <ajk@debian.org> | 2011-10-20 00:24:49 +0300 |
---|---|---|
committer | Antti-Juhani Kaijanaho <ajk@debian.org> | 2011-10-20 00:24:49 +0300 |
commit | 0705462df7b3d490ede928a45586cd1159798e0e (patch) | |
tree | 89cc6201458e5e812b3565876594eb66cdd13b1a /lib | |
parent | e2bc8ea39ff764734e2c6be383de9a45373bf693 (diff) | |
download | dctrl-tools-0705462df7b3d490ede928a45586cd1159798e0e.tar.gz |
Rewrite the paragraph logic to use a tree structure.
Signed-off-by: Antti-Juhani Kaijanaho <ajk@debian.org>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/msg.h | 4 | ||||
-rw-r--r-- | lib/predicate.c | 212 | ||||
-rw-r--r-- | lib/predicate.h | 40 |
3 files changed, 154 insertions, 102 deletions
@@ -1,5 +1,5 @@ /* dctrl-tools - Debian control file inspection tools - Copyright © 1999, 2008 Antti-Juhani Kaijanaho + Copyright © 1999, 2008, 2011 Antti-Juhani Kaijanaho 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 @@ -27,6 +27,8 @@ #include <string.h> #include "i18n.h" +static void fail(void) __attribute__((noreturn)); + static inline void fail(void) { exit(2); } diff --git a/lib/predicate.c b/lib/predicate.c index cf78796..5d10b5d 100644 --- a/lib/predicate.c +++ b/lib/predicate.c @@ -28,85 +28,161 @@ #include "strutil.h" #include "version.h" -void init_predicate(struct predicate * p) +typedef bool (*eval_t)(struct predicate *, para_t * para); + +struct predicate_vtbl { + bool (*eval)(struct predicate *, para_t *); + void (*print)(struct predicate *, size_t indent); +}; + +struct predicate { + const struct predicate_vtbl *vtbl; +}; + +static void print(struct predicate *p, size_t indent) +{ + p->vtbl->print(p, indent); +} + +struct unary_predicate { + struct predicate super; + struct predicate *rand; +}; + +struct binary_predicate { + struct predicate super; + struct predicate *lrand; + struct predicate *rrand; +}; + +struct atomary_predicate { + struct predicate super; + struct atom *atom; +}; + +static bool eval_AND(struct predicate *base_p, para_t * para) +{ + struct binary_predicate *p = (struct binary_predicate *)base_p; + if (!does_para_satisfy(p->lrand, para)) return false; + return does_para_satisfy(p->rrand, para); +} + +static void print_AND(struct predicate *base_p, size_t indent) +{ + struct binary_predicate *p = (struct binary_predicate *)base_p; + for (int i = 0; i < indent; i++) putchar(' '); + puts("AND"); + print(p->lrand, indent+1); + print(p->rrand, indent+1); +} + +static bool eval_OR(struct predicate *base_p, para_t * para) +{ + struct binary_predicate *p = (struct binary_predicate *)base_p; + if (does_para_satisfy(p->lrand, para)) return true; + return does_para_satisfy(p->rrand, para); +} + +static void print_OR(struct predicate *base_p, size_t indent) +{ + struct binary_predicate *p = (struct binary_predicate *)base_p; + for (int i = 0; i < indent; i++) putchar(' '); + puts("OR"); + print(p->lrand, indent+1); + print(p->rrand, indent+1); +} + +static bool eval_NOT(struct predicate *base_p, para_t * para) { - p->num_atoms = 0; - p->proglen = 0; - p->atoms = malloc(MAX_ATOMS * sizeof p->atoms[0]); - if (p->atoms == 0) enomem(0); + struct unary_predicate *p = (struct unary_predicate *)base_p; + return !does_para_satisfy(p->rand, para); } -void addinsn(struct predicate * p, int insn) +static void print_NOT(struct predicate *base_p, size_t indent) { - if (insn == I_NOP) return; - if (p->proglen >= MAX_OPS) { - message(L_FATAL, 0, _("predicate is too complex")); - fail(); - } - p->program[p->proglen++] = insn; + struct unary_predicate *p = (struct unary_predicate *)base_p; + for (int i = 0; i < indent; i++) putchar(' '); + puts("NOT"); + print(p->rand, indent+1); +} + + +static bool eval_ATOM(struct predicate *base_p, para_t * para) +{ + struct atomary_predicate *p = (struct atomary_predicate *)base_p; + return atom_verify(p->atom, para); +} + +static void print_ATOM(struct predicate *base_p, size_t indent) +{ + struct atomary_predicate *p = (struct atomary_predicate *)base_p; + char ind[indent+1]; + for (int i = 0; i < indent; i++) ind[i] = ' '; + ind[indent] = '\0'; + printf("%sATOM", ind); + printf("%s field_name = %s\n", ind, p->atom->field_name); + printf("%s mode = %i\n", ind, p->atom->mode); + printf("%s ignore_case = %i\n", ind, p->atom->ignore_case); + printf("%s whole_pkg = %i\n", ind, p->atom->whole_pkg); + printf("%s pat = %s\n", ind, p->atom->pat); +} + +struct predicate *binary_predicate(const struct predicate_vtbl *vtbl, + struct predicate *pl, struct predicate *pr){ + struct binary_predicate *rv = malloc(sizeof *rv); + if (rv == 0) enomem(0); + rv->super.vtbl = vtbl; + rv->lrand= pl; + rv->rrand = pr; + return &rv->super; +} +struct predicate *predicate_AND(struct predicate *pl, struct predicate *pr) +{ + static const struct predicate_vtbl vtbl = + { .eval = eval_AND, .print = print_AND }; + return binary_predicate(&vtbl, pl, pr); +} +struct predicate *predicate_OR(struct predicate *pl, struct predicate *pr) +{ + static const struct predicate_vtbl vtbl = + { .eval = eval_OR, .print = print_OR }; + return binary_predicate(&vtbl, pl, pr); +} +struct predicate *predicate_NOT(struct predicate *p) +{ + static const struct predicate_vtbl vtbl = + { .eval = eval_NOT, .print = print_NOT }; + struct unary_predicate *rv = malloc(sizeof *rv); + if (rv == 0) enomem(0); + rv->super.vtbl = &vtbl; + rv->rand = p; + return &rv->super; +} +struct predicate *predicate_ATOM(struct atom *at) +{ + static const struct predicate_vtbl vtbl = + { .eval = eval_ATOM, .print = print_ATOM }; + struct atomary_predicate *rv = malloc(sizeof *rv); + if (rv == 0) enomem(0); + rv->super.vtbl = &vtbl; + rv->atom = at; + return &rv->super; } bool check_predicate(struct predicate * p) { - size_t sp = 0; - /* Simulate the program. */ - for (size_t i = 0; i < p->proglen; i++) { - switch (p->program[i]) { - case I_NOP: break; - case I_NEG: - if (sp == 0) return false; - break; - case I_AND: case I_OR: - if (sp < 2) return false; - --sp; - break; - default: - ++sp; - } - } - if (sp != 1) return false; - return true; + // static checking of predicate + // currently no operation + return true; } bool does_para_satisfy(struct predicate * p, para_t * para) { - bool sat_atom[MAX_ATOMS]; - bool stack[MAX_OPS]; - size_t sp = 0; - - /* Verify atoms. */ - for (size_t i = 0; i < p->num_atoms; i++) { - sat_atom[i] = atom_verify(&p->atoms[i], para); - } - - /* Run the program. */ - for (size_t i = 0; i < p->proglen; i++) { - switch (p->program[i]) { - case I_NOP: break; - case I_NEG: - assert(sp >= 1); - stack[sp-1] = !stack[sp-1]; - break; - case I_AND: - assert(sp >= 2); - stack[sp-2] = stack[sp-2] && stack[sp-1]; - --sp; - break; - case I_OR: - assert(sp >= 2); - stack[sp-2] = stack[sp-2] || stack[sp-1]; - --sp; - break; - default: - { - int atom = p->program[i] - I_PUSH(0); - assert(atom <= p->num_atoms); - stack[sp] = sat_atom[atom]; - ++sp; - } - } - } - assert(sp == 1); - return stack[0]; + return p->vtbl->eval(p, para); +} + +void predicate_print(struct predicate *p) +{ + print(p, 0); } diff --git a/lib/predicate.h b/lib/predicate.h index 47d700c..82bf76d 100644 --- a/lib/predicate.h +++ b/lib/predicate.h @@ -21,44 +21,18 @@ #include "paragraph.h" -#define MAX_OPS 4096 -#define MAX_ATOMS 4096 - -#define I_NOP 0 -#define I_NEG 1 /* --not; 1-1 */ -#define I_AND 2 /* --and; 2-1 */ -#define I_OR 3 /* --or; 2-1 */ -#define I_PUSH(n) (4+(n)) /* push result of nth atomic proposition */ - struct atom; +struct predicate; -/* A predicate is represented as a set of atomic predicates and a - * program - a sequence of stack-based "bytecode" instructions - that - * specifies the structure of the combined predicate. */ -struct predicate { - /* Number of atomic predicates. */ - size_t num_atoms; - /* Length of the program */ - size_t proglen; - /* The program */ - int program[MAX_OPS]; - /* The atomic predicates */ - struct atom *atoms; -}; - -void init_predicate(struct predicate * p); - -static inline -struct atom * get_current_atom(struct predicate * p) -{ - assert(p->num_atoms > 0); - return &p->atoms[p->num_atoms-1]; -} - -void addinsn(struct predicate * p, int insn); +struct predicate *predicate_AND(struct predicate *, struct predicate *); +struct predicate *predicate_OR(struct predicate *, struct predicate *); +struct predicate *predicate_NOT(struct predicate *); +struct predicate *predicate_ATOM(struct atom *); bool does_para_satisfy(struct predicate * p, para_t *); bool check_predicate(struct predicate * p); +void predicate_print(struct predicate *p); + #endif /* PREDICATE_H */ |