summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAntti-Juhani Kaijanaho <ajk@debian.org>2011-10-20 00:24:49 +0300
committerAntti-Juhani Kaijanaho <ajk@debian.org>2011-10-20 00:24:49 +0300
commit0705462df7b3d490ede928a45586cd1159798e0e (patch)
tree89cc6201458e5e812b3565876594eb66cdd13b1a /lib
parente2bc8ea39ff764734e2c6be383de9a45373bf693 (diff)
downloaddctrl-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.h4
-rw-r--r--lib/predicate.c212
-rw-r--r--lib/predicate.h40
3 files changed, 154 insertions, 102 deletions
diff --git a/lib/msg.h b/lib/msg.h
index e61b3a4..cfabc7f 100644
--- a/lib/msg.h
+++ b/lib/msg.h
@@ -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 */