test/mm/Makefile \
test/device/Makefile \
test/format1/Makefile \
+test/regex/Makefile \
" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
EOF
cat >> $CONFIG_STATUS <<EOF
test/mm/Makefile \
test/device/Makefile \
test/format1/Makefile \
+test/regex/Makefile \
"}
EOF
cat >> $CONFIG_STATUS <<\EOF
test/mm/Makefile \
test/device/Makefile \
test/format1/Makefile \
+test/regex/Makefile \
)
../lib/activate/activate.h
../lib/config/config.h
+../lib/datastruct/bitset.h
../lib/datastruct/hash.h
../lib/datastruct/list.h
../lib/datastruct/lvm-types.h
../lib/mm/dbg_malloc.h
../lib/mm/pool.h
../lib/mm/xlate.h
+../lib/regex/matcher.h
../lib/uuid/uuid.h
SOURCES=\
activate/activate.c \
config/config.c \
+ datastruct/bitset.c \
datastruct/hash.c \
device/dev-cache.c \
device/dev-io.c \
device/device.c \
- display/display.c \
filters/filter.c \
format1/disk-rep.c \
format1/format1.c \
metadata/metadata.c \
mm/dbg_malloc.c \
mm/pool.c \
+ regex/parse_rx.c \
+ regex/matcher.c \
+ regex/ttree.c \
uuid/uuid.c
TARGETS=liblvm.a
--- /dev/null
+/*
+ * Copyright (C) 2001 Sistina Software (UK) Limited.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "bitset.h"
+#include "dbg_malloc.h"
+
+#include <stdlib.h>
+
+/* FIXME: calculate this. */
+#define INT_SHIFT 5
+
+bitset_t bitset_create(struct pool *mem, unsigned num_bits)
+{
+ int n = (num_bits / BITS_PER_INT) + 2;
+ int size = sizeof(int) * n;
+ unsigned *bs = pool_zalloc(mem, size);
+
+ if (!bs)
+ return NULL;
+
+ *bs = num_bits;
+ return bs;
+}
+
+void bitset_destroy(bitset_t bs)
+{
+ dbg_free(bs);
+}
+
+void bit_union(bitset_t out, bitset_t in1, bitset_t in2)
+{
+ int i;
+ for(i = (in1[0] / BITS_PER_INT) + 1; i; i--)
+ out[i] = in1[i] | in2[i];
+}
+
+/*
+ * FIXME: slow
+ */
+static inline int _test_word(uint32_t test, int bit)
+{
+ while (bit < BITS_PER_INT) {
+ if (test & (0x1 << bit))
+ return bit;
+ bit++;
+ }
+
+ return -1;
+}
+
+int bit_get_next(bitset_t bs, int last_bit)
+{
+ int bit, word;
+ uint32_t test;
+
+ last_bit++; /* otherwise we'll return the same bit again */
+
+ while(last_bit < bs[0]) {
+ word = last_bit >> INT_SHIFT;
+ test = bs[word + 1];
+ bit = last_bit & (BITS_PER_INT - 1);
+
+ if ((bit = _test_word(test, bit)) >= 0)
+ return (word * BITS_PER_INT) + bit;
+
+ last_bit = last_bit - (last_bit & (BITS_PER_INT - 1)) +
+ BITS_PER_INT;
+ }
+
+ return -1;
+}
+
+int bit_get_first(bitset_t bs)
+{
+ return bit_get_next(bs, -1);
+}
--- /dev/null
+/*
+ * Copyright (C) 2001 Sistina Software (UK) Limited.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef _LVM_BITSET_H
+#define _LVM_BITSET_H
+
+#include "lvm-types.h"
+#include "pool.h"
+
+#include <limits.h>
+#include <string.h>
+
+
+typedef uint32_t *bitset_t;
+
+bitset_t bitset_create(struct pool *mem, unsigned num_bits);
+
+void bit_union(bitset_t out, bitset_t in1, bitset_t in2);
+int bit_get_first(bitset_t bs);
+int bit_get_next(bitset_t bs, int last_bit);
+
+
+#define BITS_PER_INT (sizeof(int) * CHAR_BIT)
+
+#define bit(bs, i) \
+ (bs[(i / BITS_PER_INT) + 1] & (0x1 << (i & (BITS_PER_INT - 1))))
+
+#define bit_set(bs, i) \
+ (bs[(i / BITS_PER_INT) + 1] |= (0x1 << (i & (BITS_PER_INT - 1))))
+
+#define bit_clear(bs, i) \
+ (bs[(i / BITS_PER_INT) + 1] &= ~(0x1 << (i & (BITS_PER_INT - 1))))
+
+#define bit_set_all(bs) \
+ memset(bs + 1, -1, ((*bs / BITS_PER_INT) + 1) * sizeof(int))
+
+#define bit_clear_all(bs) \
+ memset(bs + 1, 0, ((*bs / BITS_PER_INT) + 1) * sizeof(int))
+
+#define bit_copy(bs1, bs2) \
+ memcpy(bs1 + 1, bs2 + 1, ((*bs1 / BITS_PER_INT) + 1) * sizeof(int))
+
+#endif
--- /dev/null
+/*
+ * Copyright (C) 2001 Sistina Software (UK) Limited.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "matcher.h"
+#include "parse_rx.h"
+#include "log.h"
+#include "ttree.h"
+#include "bitset.h"
+
+#include <string.h>
+#include <stdio.h>
+#include <assert.h>
+
+struct dfa_state {
+ int final;
+ struct dfa_state *lookup[256];
+};
+
+struct state_queue {
+ struct dfa_state *s;
+ bitset_t bits;
+ struct state_queue *next;
+};
+
+struct matcher { /* Instance variables for the lexer */
+ struct dfa_state *start;
+ int num_nodes, nodes_entered;
+ struct rx_node **nodes;
+ struct pool *scratch, *mem;
+};
+
+#define TARGET_TRANS '\0'
+
+static int _count_nodes(struct rx_node *rx)
+{
+ int r = 1;
+
+ if(rx->left)
+ r += _count_nodes(rx->left);
+
+ if(rx->right)
+ r += _count_nodes(rx->right);
+
+ return r;
+}
+
+static void _fill_table(struct matcher *m, struct rx_node *rx)
+{
+ assert((rx->type != OR) || (rx->left && rx->right));
+
+ if(rx->left)
+ _fill_table(m, rx->left);
+
+ if(rx->right)
+ _fill_table(m, rx->right);
+
+ m->nodes[m->nodes_entered++] = rx;
+}
+
+static void _create_bitsets(struct matcher *m)
+{
+ int i;
+
+ for(i = 0; i < m->num_nodes; i++) {
+ struct rx_node *n = m->nodes[i];
+ n->firstpos = bitset_create(m->scratch, m->num_nodes);
+ n->lastpos = bitset_create(m->scratch, m->num_nodes);
+ n->followpos = bitset_create(m->scratch, m->num_nodes);
+ }
+}
+
+static void _calc_functions(struct matcher *m)
+{
+ int i, j, final = 1;
+ struct rx_node *rx, *c1, *c2;
+
+ for(i = 0; i < m->num_nodes; i++) {
+ rx = m->nodes[i];
+ c1 = rx->left;
+ c2 = rx->right;
+
+ if(bit(rx->charset, TARGET_TRANS))
+ rx->final = final++;
+
+ switch(rx->type) {
+ case CAT:
+ if(c1->nullable)
+ bit_union(rx->firstpos,
+ c1->firstpos, c2->firstpos);
+ else
+ bit_copy(rx->firstpos, c1->firstpos);
+
+ if(c2->nullable)
+ bit_union(rx->lastpos,
+ c1->lastpos, c2->lastpos);
+ else
+ bit_copy(rx->lastpos, c2->lastpos);
+
+ rx->nullable = c1->nullable && c2->nullable;
+ break;
+
+ case PLUS:
+ bit_copy(rx->firstpos, c1->firstpos);
+ bit_copy(rx->lastpos, c1->lastpos);
+ rx->nullable = c1->nullable;
+ break;
+
+ case OR:
+ bit_union(rx->firstpos, c1->firstpos, c2->firstpos);
+ bit_union(rx->lastpos, c1->lastpos, c2->lastpos);
+ rx->nullable = c1->nullable || c2->nullable;
+ break;
+
+ case QUEST:
+ case STAR:
+ bit_copy(rx->firstpos, c1->firstpos);
+ bit_copy(rx->lastpos, c1->lastpos);
+ rx->nullable = 1;
+ break;
+
+ case CHARSET:
+ bit_set(rx->firstpos, i);
+ bit_set(rx->lastpos, i);
+ rx->nullable = 0;
+ break;
+
+ default:
+ log_debug("unknown node type");
+ }
+
+ /*
+ * followpos has it's own switch
+ * because PLUS and STAR do the
+ * same thing.
+ */
+ switch(rx->type) {
+ case CAT:
+ for(j = 0; j < m->num_nodes; j++) {
+ if(bit(c1->lastpos, j)) {
+ struct rx_node *n = m->nodes[j];
+ bit_union(n->followpos,
+ n->followpos, c2->firstpos);
+ }
+ }
+ break;
+
+ case PLUS:
+ case STAR:
+ for(j = 0; j < m->num_nodes; j++) {
+ if(bit(rx->lastpos, j)) {
+ struct rx_node *n = m->nodes[j];
+ bit_union(n->followpos,
+ n->followpos, rx->firstpos);
+ }
+ }
+ break;
+ }
+ }
+}
+
+static inline struct dfa_state *_create_dfa_state(struct pool *mem)
+{
+ return pool_zalloc(mem, sizeof(struct dfa_state));
+}
+
+static struct state_queue *_create_state_queue(struct pool *mem,
+ struct dfa_state *dfa,
+ bitset_t bits)
+{
+ struct state_queue *r = pool_alloc(mem, sizeof(*r));
+
+ if (!r) {
+ stack;
+ return NULL;
+ }
+
+ r->s = dfa;
+ r->bits = bitset_create(mem, bits[0]); /* first element is the size */
+ bit_copy(r->bits, bits);
+ r->next = 0;
+ return r;
+}
+
+static int _calc_states(struct matcher *m, struct rx_node *rx)
+{
+ int iwidth = (m->num_nodes / BITS_PER_INT) + 1;
+ struct ttree *tt = ttree_create(m->scratch, iwidth);
+ struct state_queue *h, *t, *tmp;
+ struct dfa_state *dfa, *ldfa;
+ int i, a, set_bits = 0, count = 0;
+ bitset_t bs = bitset_create(m->scratch, m->num_nodes), dfa_bits;
+
+ if (!tt) {
+ stack;
+ return 0;
+ }
+
+ if (!bs) {
+ stack;
+ return 0;
+ }
+
+ /* create first state */
+ dfa = _create_dfa_state(m->mem);
+ m->start = dfa;
+ ttree_insert(tt, rx->firstpos, dfa);
+
+ /* prime the queue */
+ h = t = _create_state_queue(m->scratch, dfa, rx->firstpos);
+ while(h) {
+ /* pop state off front of the queue */
+ dfa = h->s;
+ dfa_bits = h->bits;
+ h = h->next;
+
+ /* iterate through all the inputs for this state */
+ bit_clear_all(bs);
+ for(a = 0; a < 256; a++) {
+ /* iterate through all the states in firstpos */
+ for(i = bit_get_first(dfa_bits);
+ i >=0;
+ i = bit_get_next(dfa_bits, i)) {
+ if(bit(m->nodes[i]->charset, a)) {
+ if(a == TARGET_TRANS)
+ dfa->final = m->nodes[i]->final;
+
+ bit_union(bs, bs, m->nodes[i]->followpos);
+ set_bits = 1;
+ }
+ }
+
+ if(set_bits) {
+ ldfa = ttree_lookup(tt, bs + 1);
+ if(!ldfa) {
+ /* push */
+ ldfa = _create_dfa_state(m->mem);
+ ttree_insert(tt, bs + 1, ldfa);
+ tmp = _create_state_queue(m->scratch, ldfa, bs);
+ if(!h)
+ h = t = tmp;
+ else {
+ t->next = tmp;
+ t = tmp;
+ }
+
+ count++;
+ }
+
+ dfa->lookup[a] = ldfa;
+ set_bits = 0;
+ bit_clear_all(bs);
+ }
+ }
+ }
+
+ log_debug("Lexer built with %d dfa states", count);
+ return 1;
+}
+
+struct matcher *matcher_create(struct pool *mem,
+ const char **patterns, int num)
+{
+ char *all, *ptr;
+ int i, len = 0;
+ struct rx_node *rx;
+ struct pool *scratch = pool_create(10 * 1024);
+ struct matcher *m;
+
+ if (!scratch) {
+ stack;
+ return NULL;
+ }
+
+ if (!(m = pool_alloc(mem, sizeof(*m)))) {
+ stack;
+ return NULL;
+ }
+
+ memset(m, 0, sizeof(*m));
+
+ /* join the regexps together, delimiting with zero */
+ for(i = 0; i < num; i++)
+ len += strlen(patterns[i]) + 8;
+
+ ptr = all = pool_alloc(scratch, len + 1);
+
+ if (!all) {
+ stack;
+ goto bad;
+ }
+
+ for(i = 0; i < num; i++) {
+ ptr += sprintf(ptr, "(.*(%s)%c)", patterns[i],
+ TARGET_TRANS);
+ if(i < (num - 1))
+ *ptr++ = '|';
+ }
+
+ /* parse this expression */
+ if(!(rx = rx_parse_tok(scratch, all, ptr))) {
+ log_debug("Couldn't parse the regex");
+ goto bad;
+ }
+
+ m->mem = mem;
+ m->scratch = scratch;
+ m->num_nodes = _count_nodes(rx);
+ m->nodes = pool_alloc(scratch, sizeof(*m->nodes) * m->num_nodes);
+
+ if (!m->nodes) {
+ stack;
+ goto bad;
+ }
+
+ _fill_table(m, rx);
+ _create_bitsets(m);
+ _calc_functions(m);
+ _calc_states(m, rx);
+ pool_destroy(scratch);
+ m->scratch = NULL;
+
+ return m;
+
+ bad:
+ pool_destroy(scratch);
+ pool_destroy(mem);
+ return NULL;
+}
+
+int matcher_run(struct matcher *m, const char *b, const char *e)
+{
+ struct dfa_state *cs = m->start;
+ int r = -1;
+
+ for (; b != e; b++) {
+
+ if (!(cs = cs->lookup[(int) (unsigned char) *b]))
+ break;
+
+ if (cs->final)
+ r = cs->final;
+ }
+
+ /* subtract 1 to get back to zero index */
+ return (r < 0) ? r : (r - 1);
+}
--- /dev/null
+/*
+ * Copyright (C) 2001 Sistina Software (UK) Limited.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef _LVM_MATCHER_H
+#define _LVM_MATCHER_H
+
+#include "pool.h"
+
+struct matcher;
+struct matcher *matcher_create(struct pool *mem,
+ const char **patterns, int num);
+
+int matcher_run(struct matcher *m, const char *begin, const char *end);
+
+#endif
--- /dev/null
+/*
+ * Copyright (C) 2001 Sistina Software (UK) Limited.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "parse_rx.h"
+#include "bitset.h"
+#include "log.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+
+struct parse_sp { /* scratch pad for the parsing process */
+ struct pool *mem;
+ int type; /* token type, 0 indicates a charset */
+ bitset_t charset; /* The current charset */
+ const char *cursor; /* where we are in the regex */
+ const char *rx_end; /* 1pte for the expression being parsed */
+};
+
+
+static struct rx_node *_expr(struct parse_sp *ps, struct rx_node *l);
+
+
+/*
+ * Get the next token from the regular expression.
+ * Returns: 1 success, 0 end of input, -1 error.
+ */
+static int _get_token(struct parse_sp *ps)
+{
+ int neg = 0, range = 0;
+ char c, lc = 0;
+ const char *ptr = ps->cursor;
+ if(ptr == ps->rx_end) { /* end of input ? */
+ ps->type = -1;
+ return 0;
+ }
+
+ switch(*ptr) {
+ /* charsets and ncharsets */
+ case '[':
+ ptr++;
+ if(*ptr == '^') {
+ bit_set_all(ps->charset);
+
+ /* never transition on zero */
+ bit_clear(ps->charset, 0);
+ neg = 1;
+ ptr++;
+
+ } else
+ bit_clear_all(ps->charset);
+
+ while((ptr < ps->rx_end) && (*ptr != ']')) {
+ if(*ptr == '\\') {
+ /* an escaped character */
+ ptr++;
+ switch(*ptr) {
+ case 'n': c = '\n'; break;
+ case 'r': c = '\r'; break;
+ case 't': c = '\t'; break;
+ default:
+ c = *ptr;
+ }
+ } else if(*ptr == '-' && lc) {
+ /* we've got a range on our hands */
+ range = 1;
+ ptr++;
+ if(ptr == ps->rx_end) {
+ log_info("incomplete charset "
+ "specification");
+ return -1;
+ }
+ c = *ptr;
+ } else
+ c = *ptr;
+
+ if(range) {
+ /* add lc - c into the bitset */
+ if(lc > c) {
+ char tmp = c;
+ c = lc;
+ lc = tmp;
+ }
+
+ for(; lc <= c; lc++) {
+ if(neg)
+ bit_clear(ps->charset, lc);
+ else
+ bit_set(ps->charset, lc);
+ }
+ range = 0;
+ } else {
+ /* add c into the bitset */
+ if(neg)
+ bit_clear(ps->charset, c);
+ else
+ bit_set(ps->charset, c);
+ }
+ ptr++;
+ lc = c;
+ }
+
+ if(ptr >= ps->rx_end) {
+ ps->type = -1;
+ return -1;
+ }
+
+ ps->type = 0;
+ ps->cursor = ptr + 1;
+ break;
+
+ /* These characters are special, we just return their ASCII
+ codes as the type. Sorted into ascending order to help the
+ compiler */
+ case '(':
+ case ')':
+ case '*':
+ case '+':
+ case '?':
+ case '|':
+ case '^':
+ case '$':
+ ps->type = (int) *ptr;
+ ps->cursor = ptr + 1;
+ break;
+
+ case '.':
+ /* The 'all but newline' character set */
+ ps->type = 0;
+ ps->cursor = ptr + 1;
+ bit_set_all(ps->charset);
+ bit_clear(ps->charset, (int) '\n');
+ bit_clear(ps->charset, (int) '\r');
+ bit_clear(ps->charset, 0);
+ break;
+
+ case '\\':
+ /* escaped character */
+ ptr++;
+ if(ptr >= ps->rx_end) {
+ log_info("badly quoted character at end "
+ "of expression");
+ ps->type = -1;
+ return -1;
+ }
+
+ ps->type = 0;
+ ps->cursor = ptr + 1;
+ bit_clear_all(ps->charset);
+ switch(*ptr) {
+ case 'n': bit_set(ps->charset, (int) '\n'); break;
+ case 'r': bit_set(ps->charset, (int) '\r'); break;
+ case 't': bit_set(ps->charset, (int) '\t'); break;
+ default:
+ bit_set(ps->charset, (int) *ptr);
+ }
+ break;
+
+ default:
+ /* add a single character to the bitset */
+ ps->type = 0;
+ ps->cursor = ptr + 1;
+ bit_clear_all(ps->charset);
+ bit_set(ps->charset, (int) *ptr);
+ break;
+ }
+
+ return 1;
+}
+
+static struct rx_node *_create_node(struct pool *mem, int type,
+ struct rx_node *l, struct rx_node *r)
+{
+ struct rx_node *n = pool_zalloc(mem, sizeof(*n));
+
+ if (n) {
+ if (!(n->charset = bitset_create(mem, 256))) {
+ pool_free(mem, n);
+ return NULL;
+ }
+
+ n->type = type;
+ n->left = l;
+ n->right = r;
+ }
+
+ return n;
+}
+
+static struct rx_node *_term(struct parse_sp *ps)
+{
+ struct rx_node *n;
+
+ switch(ps->type) {
+ case 0:
+ if (!(n = _create_node(ps->mem, CHARSET, NULL, NULL))) {
+ stack;
+ return NULL;
+ }
+
+ bit_copy(n->charset, ps->charset);
+ _get_token(ps); /* match charset */
+ break;
+
+ case '(':
+ _get_token(ps); /* match '(' */
+ n = _expr(ps, 0);
+ if(ps->type != ')') {
+ log_debug("missing ')' in regular expression");
+ return 0;
+ }
+ _get_token(ps); /* match ')' */
+ break;
+
+ default:
+ n = 0;
+ }
+
+ return n;
+}
+
+static struct rx_node *_closure_term(struct parse_sp *ps)
+{
+ struct rx_node *l, *n;
+
+ if(!(l = _term(ps)))
+ return NULL;
+
+ switch(ps->type) {
+ case '*':
+ n = _create_node(ps->mem, STAR, l, NULL);
+ break;
+
+ case '+':
+ n = _create_node(ps->mem, PLUS, l, NULL);
+ break;
+
+ case '?':
+ n = _create_node(ps->mem, QUEST, l, NULL);
+ break;
+
+ default:
+ return l;
+ }
+
+ if (!n) {
+ stack;
+ return NULL;
+ }
+
+ _get_token(ps);
+ return n;
+}
+
+static struct rx_node *_cat_term(struct parse_sp *ps)
+{
+ struct rx_node *l, *r, *n;
+
+ if (!(l = _closure_term(ps)))
+ return NULL;
+
+ if (ps->type == '|')
+ /* bail out */
+ return l;
+
+ /* catenate */
+ if (!(r = _cat_term(ps)))
+ return l;
+
+ if (!(n = _create_node(ps->mem, CAT, l, r))) {
+ stack;
+ return NULL;
+ }
+
+ return n;
+}
+
+static struct rx_node *_expr(struct parse_sp *ps, struct rx_node *l)
+{
+ struct rx_node *n = 0;
+ while((ps->type >= 0) && (ps->type != ')')) {
+
+ if (!(n = _create_node(ps->mem, CAT, l, NULL))) {
+ stack;
+ return NULL;
+ }
+
+ switch(ps->type) {
+ case 0:
+ case '(':
+ /* implicit catenation */
+ if(!l)
+ n = _cat_term(ps);
+ else
+ n->right = _cat_term(ps);
+
+ break;
+
+ case '|':
+ /* 'or' */
+ if(!l) {
+ log_debug("badly formed '|' expression");
+ return 0;
+ }
+ n->type = OR;
+ _get_token(ps); /* match '|' */
+ n->right = _cat_term(ps);
+ break;
+
+ default:
+ log_debug("unexpected token");
+ return 0;
+ }
+
+ if(!n) {
+ log_err("parse error in regex");
+ return NULL;
+ }
+
+ if((n->type != CHARSET) && !n->left) {
+ log_debug("badly formed regex");
+ ps->type = -1;
+ ps->cursor = ps->rx_end;
+ return 0;
+ }
+
+ l = n;
+ }
+
+ return n;
+}
+
+struct rx_node *rx_parse_tok(struct pool *mem,
+ const char *begin, const char *end)
+{
+ struct rx_node *r;
+ struct parse_sp *ps = pool_alloc(mem, sizeof(*ps));
+
+ if (!ps) {
+ stack;
+ return NULL;
+ }
+
+ memset(ps, 0, sizeof(*ps));
+ ps->mem = mem;
+ ps->charset = bitset_create(mem, 256);
+ ps->cursor = begin;
+ ps->rx_end = end;
+ _get_token(ps); /* load the first token */
+ if (!(r = _expr(ps, NULL)))
+ pool_free(mem, ps);
+
+ return r;
+}
+
+struct rx_node *rx_parse_str(struct pool *mem, const char *str)
+{
+ return rx_parse_tok(mem, str, str + strlen(str));
+}
--- /dev/null
+/*
+ * Copyright (C) 2001 Sistina Software (UK) Limited.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef _LVM_PARSE_REGEX_H
+#define _LVM_PARSE_REGEX_H
+
+#include "bitset.h"
+
+enum {
+ CAT,
+ STAR,
+ PLUS,
+ OR,
+ QUEST,
+ CHARSET,
+ HAT,
+ DOLLAR
+};
+
+struct rx_node {
+ int type;
+ bitset_t charset;
+ struct rx_node *left, *right;
+
+ /* used to build the dfa for the toker */
+ int nullable, final;
+ bitset_t firstpos;
+ bitset_t lastpos;
+ bitset_t followpos;
+};
+
+struct rx_node *rx_parse_str(struct pool *mem, const char *str);
+struct rx_node *rx_parse_tok(struct pool *mem,
+ const char *begin, const char *end);
+
+#endif
--- /dev/null
+/*
+ * Copyright (C) 2001 Sistina Software (UK) Limited.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "ttree.h"
+#include "pool.h"
+#include "log.h"
+
+#include <stdlib.h>
+
+struct node {
+ unsigned k;
+ struct node *l, *m, *r;
+ void *data;
+};
+
+struct ttree {
+ int klen;
+ struct pool *mem;
+ struct node *root;
+};
+
+struct ttree *ttree_create(struct pool *mem, unsigned int klen)
+{
+ struct ttree *tt;
+
+ if (!(tt = pool_zalloc(mem, sizeof(*tt)))) {
+ stack;
+ return NULL;
+ }
+
+ tt->klen = klen;
+ tt->mem = mem;
+ return tt;
+}
+
+void *ttree_lookup(struct ttree *tt, unsigned *key)
+{
+ struct node *c = tt->root;
+ int count = tt->klen;
+ unsigned k = *key++;
+
+ while (c) {
+ if (k < c->k)
+ c = c->l;
+
+ else if (k > c->k)
+ c = c->r;
+
+ else {
+ if (!--count)
+ break;
+
+ c = c->m;
+ k = *key++;
+ }
+ }
+
+ return c ? c->data : 0;
+}
+
+void *ttree_insert(struct ttree *tt, unsigned *key, void *data)
+{
+ struct node *c = tt->root, *p = 0;
+ int count = tt->klen, first = 1;
+ unsigned k = *key;
+ void *r = NULL;
+
+ while (c) {
+ p = c;
+ if (k < c->k)
+ c = c->l;
+
+ else if (k > c->k)
+ c = c->r;
+
+ else {
+ c = c->m;
+ if (!--count)
+ break;
+
+ k = *++key;
+ }
+ }
+
+ if (!count) {
+ /* key is already in the tree */
+ r = p->data;
+ p->data = data;
+
+ } else {
+ /* FIXME: put this in seperate function */
+ /* insert new chain of nodes */
+ while (count--) {
+ k = *key++;
+ c = pool_alloc(tt->mem, sizeof(*c));
+
+ if (!c) {
+ stack;
+ return NULL;
+ }
+
+ c->k = k;
+ c->l = c->m = c->r = c->data = 0;
+ if (!p)
+ tt->root = c;
+
+ else if (first) {
+ if (k < p->k)
+ p->l = c;
+
+ else if (k > p->k)
+ p->r = c;
+
+ else
+ p->m = c;
+
+ first = 0;
+ } else
+ p->m = c;
+ p = c;
+ }
+ c->data = data;
+ }
+
+ return r;
+}
--- /dev/null
+/*
+ * Copyright (C) 2001 Sistina Software (UK) Limited.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef _LVM_TTREE_H
+#define _LVM_TTREE_H
+
+#include "pool.h"
+
+struct ttree;
+
+struct ttree *ttree_create(struct pool *mem, unsigned int klen);
+
+void *ttree_lookup(struct ttree *tt, unsigned *key);
+void *ttree_insert(struct ttree *tt, unsigned *key, void *data);
+
+#endif
--- /dev/null
+#
+# Copyright (C) 2001 Sistina Software (UK) Limited
+#
+# This file is released under the GPL.
+#
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+
+SOURCES=\
+ parse_t.c \
+ matcher_t.c
+
+TARGETS=\
+ parse_t \
+ matcher_t
+
+include ../../make.tmpl
+
+parse_t: parse_t.o $(top_srcdir)/lib/liblvm.a
+ $(CC) -o parse_t parse_t.o -L$(top_srcdir)/lib -llvm
+
+matcher_t: matcher_t.o $(top_srcdir)/lib/liblvm.a
+ $(CC) -o matcher_t matcher_t.o -L$(top_srcdir)/lib -llvm
+
--- /dev/null
+"loop/[0-9]+"
+"hd[a-d][0-5]+"
--- /dev/null
+/dev
+/dev/.devfsd
+/dev/cpu
+/dev/cpu/mtrr
+/dev/netlink
+/dev/netlink/route
+/dev/netlink/skip
+/dev/netlink/USERSOCK
+/dev/netlink/fwmonitor
+/dev/netlink/ARPD
+/dev/netlink/ROUTE6
+/dev/netlink/IP6_FW
+/dev/netlink/tap0
+/dev/netlink/tap1
+/dev/netlink/tap2
+/dev/netlink/tap3
+/dev/netlink/tap4
+/dev/netlink/tap5
+/dev/netlink/tap6
+/dev/netlink/tap7
+/dev/netlink/tap8
+/dev/netlink/tap9
+/dev/netlink/tap10
+/dev/netlink/tap11
+/dev/netlink/tap12
+/dev/netlink/tap13
+/dev/netlink/tap14
+/dev/netlink/tap15
+/dev/shm
+/dev/mem
+/dev/kmem
+/dev/null
+/dev/port
+/dev/zero
+/dev/full
+/dev/random
+/dev/urandom
+/dev/tty
+/dev/console
+/dev/vc
+/dev/vc/1
+/dev/vc/2
+/dev/vc/3
+/dev/vc/4
+/dev/vc/5
+/dev/vc/6
+/dev/vc/7
+/dev/vc/8
+/dev/vc/9
+/dev/vc/10
+/dev/vc/11
+/dev/vc/12
+/dev/vc/13
+/dev/vc/14
+/dev/vc/15
+/dev/vc/16
+/dev/vc/17
+/dev/vc/18
+/dev/vc/19
+/dev/vc/20
+/dev/vc/21
+/dev/vc/22
+/dev/vc/23
+/dev/vc/24
+/dev/vc/25
+/dev/vc/26
+/dev/vc/27
+/dev/vc/28
+/dev/vc/29
+/dev/vc/30
+/dev/vc/31
+/dev/vc/32
+/dev/vc/33
+/dev/vc/34
+/dev/vc/35
+/dev/vc/36
+/dev/vc/37
+/dev/vc/38
+/dev/vc/39
+/dev/vc/40
+/dev/vc/41
+/dev/vc/42
+/dev/vc/43
+/dev/vc/44
+/dev/vc/45
+/dev/vc/46
+/dev/vc/47
+/dev/vc/48
+/dev/vc/49
+/dev/vc/50
+/dev/vc/51
+/dev/vc/52
+/dev/vc/53
+/dev/vc/54
+/dev/vc/55
+/dev/vc/56
+/dev/vc/57
+/dev/vc/58
+/dev/vc/59
+/dev/vc/60
+/dev/vc/61
+/dev/vc/62
+/dev/vc/63
+/dev/vc/0
+/dev/ptmx
+/dev/misc
+/dev/misc/psaux
+/dev/pty
+/dev/pty/m0
+/dev/pty/m1
+/dev/pty/m2
+/dev/pty/m3
+/dev/pty/m4
+/dev/pty/m5
+/dev/pty/m6
+/dev/pty/m7
+/dev/pty/m8
+/dev/pty/m9
+/dev/pty/m10
+/dev/pty/m11
+/dev/pty/m12
+/dev/pty/m13
+/dev/pty/m14
+/dev/pty/m15
+/dev/pty/m16
+/dev/pty/m17
+/dev/pty/m18
+/dev/pty/m19
+/dev/pty/m20
+/dev/pty/m21
+/dev/pty/m22
+/dev/pty/m23
+/dev/pty/m24
+/dev/pty/m25
+/dev/pty/m26
+/dev/pty/m27
+/dev/pty/m28
+/dev/pty/m29
+/dev/pty/m30
+/dev/pty/m31
+/dev/pty/m32
+/dev/pty/m33
+/dev/pty/m34
+/dev/pty/m35
+/dev/pty/m36
+/dev/pty/m37
+/dev/pty/m38
+/dev/pty/m39
+/dev/pty/m40
+/dev/pty/m41
+/dev/pty/m42
+/dev/pty/m43
+/dev/pty/m44
+/dev/pty/m45
+/dev/pty/m46
+/dev/pty/m47
+/dev/pty/m48
+/dev/pty/m49
+/dev/pty/m50
+/dev/pty/m51
+/dev/pty/m52
+/dev/pty/m53
+/dev/pty/m54
+/dev/pty/m55
+/dev/pty/m56
+/dev/pty/m57
+/dev/pty/m58
+/dev/pty/m59
+/dev/pty/m60
+/dev/pty/m61
+/dev/pty/m62
+/dev/pty/m63
+/dev/pty/m64
+/dev/pty/m65
+/dev/pty/m66
+/dev/pty/m67
+/dev/pty/m68
+/dev/pty/m69
+/dev/pty/m70
+/dev/pty/m71
+/dev/pty/m72
+/dev/pty/m73
+/dev/pty/m74
+/dev/pty/m75
+/dev/pty/m76
+/dev/pty/m77
+/dev/pty/m78
+/dev/pty/m79
+/dev/pty/m80
+/dev/pty/m81
+/dev/pty/m82
+/dev/pty/m83
+/dev/pty/m84
+/dev/pty/m85
+/dev/pty/m86
+/dev/pty/m87
+/dev/pty/m88
+/dev/pty/m89
+/dev/pty/m90
+/dev/pty/m91
+/dev/pty/m92
+/dev/pty/m93
+/dev/pty/m94
+/dev/pty/m95
+/dev/pty/m96
+/dev/pty/m97
+/dev/pty/m98
+/dev/pty/m99
+/dev/pty/m100
+/dev/pty/m101
+/dev/pty/m102
+/dev/pty/m103
+/dev/pty/m104
+/dev/pty/m105
+/dev/pty/m106
+/dev/pty/m107
+/dev/pty/m108
+/dev/pty/m109
+/dev/pty/m110
+/dev/pty/m111
+/dev/pty/m112
+/dev/pty/m113
+/dev/pty/m114
+/dev/pty/m115
+/dev/pty/m116
+/dev/pty/m117
+/dev/pty/m118
+/dev/pty/m119
+/dev/pty/m120
+/dev/pty/m121
+/dev/pty/m122
+/dev/pty/m123
+/dev/pty/m124
+/dev/pty/m125
+/dev/pty/m126
+/dev/pty/m127
+/dev/pty/m128
+/dev/pty/m129
+/dev/pty/m130
+/dev/pty/m131
+/dev/pty/m132
+/dev/pty/m133
+/dev/pty/m134
+/dev/pty/m135
+/dev/pty/m136
+/dev/pty/m137
+/dev/pty/m138
+/dev/pty/m139
+/dev/pty/m140
+/dev/pty/m141
+/dev/pty/m142
+/dev/pty/m143
+/dev/pty/m144
+/dev/pty/m145
+/dev/pty/m146
+/dev/pty/m147
+/dev/pty/m148
+/dev/pty/m149
+/dev/pty/m150
+/dev/pty/m151
+/dev/pty/m152
+/dev/pty/m153
+/dev/pty/m154
+/dev/pty/m155
+/dev/pty/m156
+/dev/pty/m157
+/dev/pty/m158
+/dev/pty/m159
+/dev/pty/m160
+/dev/pty/m161
+/dev/pty/m162
+/dev/pty/m163
+/dev/pty/m164
+/dev/pty/m165
+/dev/pty/m166
+/dev/pty/m167
+/dev/pty/m168
+/dev/pty/m169
+/dev/pty/m170
+/dev/pty/m171
+/dev/pty/m172
+/dev/pty/m173
+/dev/pty/m174
+/dev/pty/m175
+/dev/pty/m176
+/dev/pty/m177
+/dev/pty/m178
+/dev/pty/m179
+/dev/pty/m180
+/dev/pty/m181
+/dev/pty/m182
+/dev/pty/m183
+/dev/pty/m184
+/dev/pty/m185
+/dev/pty/m186
+/dev/pty/m187
+/dev/pty/m188
+/dev/pty/m189
+/dev/pty/m190
+/dev/pty/m191
+/dev/pty/m192
+/dev/pty/m193
+/dev/pty/m194
+/dev/pty/m195
+/dev/pty/m196
+/dev/pty/m197
+/dev/pty/m198
+/dev/pty/m199
+/dev/pty/m200
+/dev/pty/m201
+/dev/pty/m202
+/dev/pty/m203
+/dev/pty/m204
+/dev/pty/m205
+/dev/pty/m206
+/dev/pty/m207
+/dev/pty/m208
+/dev/pty/m209
+/dev/pty/m210
+/dev/pty/m211
+/dev/pty/m212
+/dev/pty/m213
+/dev/pty/m214
+/dev/pty/m215
+/dev/pty/m216
+/dev/pty/m217
+/dev/pty/m218
+/dev/pty/m219
+/dev/pty/m220
+/dev/pty/m221
+/dev/pty/m222
+/dev/pty/m223
+/dev/pty/m224
+/dev/pty/m225
+/dev/pty/m226
+/dev/pty/m227
+/dev/pty/m228
+/dev/pty/m229
+/dev/pty/m230
+/dev/pty/m231
+/dev/pty/m232
+/dev/pty/m233
+/dev/pty/m234
+/dev/pty/m235
+/dev/pty/m236
+/dev/pty/m237
+/dev/pty/m238
+/dev/pty/m239
+/dev/pty/m240
+/dev/pty/m241
+/dev/pty/m242
+/dev/pty/m243
+/dev/pty/m244
+/dev/pty/m245
+/dev/pty/m246
+/dev/pty/m247
+/dev/pty/m248
+/dev/pty/m249
+/dev/pty/m250
+/dev/pty/m251
+/dev/pty/m252
+/dev/pty/m253
+/dev/pty/m254
+/dev/pty/m255
+/dev/pts
+/dev/pts/0
+/dev/pts/1
+/dev/pts/2
+/dev/pts/3
+/dev/pts/4
+/dev/pts/5
+/dev/pts/6
+/dev/pts/7
+/dev/vcc
+/dev/vcc/0
+/dev/vcc/a
+/dev/vcc/1
+/dev/vcc/a1
+/dev/vcc/2
+/dev/vcc/a2
+/dev/vcc/3
+/dev/vcc/a3
+/dev/vcc/5
+/dev/vcc/a5
+/dev/vcc/4
+/dev/vcc/a4
+/dev/vcc/6
+/dev/vcc/a6
+/dev/vcc/7
+/dev/vcc/a7
+/dev/tts
+/dev/tts/0
+/dev/cua
+/dev/cua/0
+/dev/ide
+/dev/ide/host0
+/dev/ide/host0/bus0
+/dev/ide/host0/bus0/target0
+/dev/ide/host0/bus0/target0/lun0
+/dev/ide/host0/bus0/target0/lun0/disc
+/dev/ide/host0/bus0/target0/lun0/part1
+/dev/ide/host0/bus0/target0/lun0/part2
+/dev/ide/host0/bus0/target0/lun0/part3
+/dev/ide/host0/bus0/target0/lun0/part4
+/dev/ide/host0/bus0/target0/lun0/part5
+/dev/ide/host0/bus0/target0/lun0/part6
+/dev/ide/host0/bus0/target0/lun0/part7
+/dev/ide/host0/bus0/target0/lun0/part8
+/dev/ide/host0/bus0/target1
+/dev/ide/host0/bus0/target1/lun0
+/dev/ide/host0/bus0/target1/lun0/disc
+/dev/ide/host0/bus0/target1/lun0/part1
+/dev/ide/host0/bus1
+/dev/ide/host0/bus1/target0
+/dev/ide/host0/bus1/target0/lun0
+/dev/ide/host0/bus1/target0/lun0/disc
+/dev/ide/host0/bus1/target0/lun0/part1
+/dev/ide/host0/bus1/target1
+/dev/ide/host0/bus1/target1/lun0
+/dev/discs
+/dev/discs/disc0
+/dev/discs/disc1
+/dev/discs/disc2
+/dev/floppy
+/dev/floppy/0u1440
+/dev/floppy/0u1680
+/dev/floppy/0u1722
+/dev/floppy/0u1743
+/dev/floppy/0u1760
+/dev/floppy/0u1920
+/dev/floppy/0u1840
+/dev/floppy/0u1600
+/dev/floppy/0u360
+/dev/floppy/0u720
+/dev/floppy/0u820
+/dev/floppy/0u830
+/dev/floppy/0u1040
+/dev/floppy/0u1120
+/dev/floppy/0u800
+/dev/floppy/0
+/dev/loop
+/dev/loop/0
+/dev/loop/1
+/dev/loop/2
+/dev/loop/3
+/dev/loop/4
+/dev/loop/5
+/dev/loop/6
+/dev/loop/7
+/dev/cdroms
+/dev/sound
+/dev/sound/dsp
+/dev/sound/dsp1
+/dev/sound/mixer
+/dev/sound/midi
+/dev/usb
+/dev/root
+/dev/initctl
+/dev/xconsole
+/dev/fd
+/dev/stdin
+/dev/stdout
+/dev/stderr
+/dev/route
+/dev/skip
+/dev/USERSOCK
+/dev/fwmonitor
+/dev/ARPD
+/dev/ROUTE6
+/dev/IP6_FW
+/dev/tap0
+/dev/tap1
+/dev/tap2
+/dev/tap3
+/dev/tap4
+/dev/tap5
+/dev/tap6
+/dev/tap7
+/dev/tap8
+/dev/tap9
+/dev/tap10
+/dev/tap11
+/dev/tap12
+/dev/tap13
+/dev/tap14
+/dev/tap15
+/dev/tty1
+/dev/tty2
+/dev/tty3
+/dev/tty4
+/dev/tty5
+/dev/tty6
+/dev/tty7
+/dev/tty8
+/dev/tty9
+/dev/tty10
+/dev/tty11
+/dev/tty12
+/dev/tty13
+/dev/tty14
+/dev/tty15
+/dev/tty16
+/dev/tty17
+/dev/tty18
+/dev/tty19
+/dev/tty20
+/dev/tty21
+/dev/tty22
+/dev/tty23
+/dev/tty24
+/dev/tty25
+/dev/tty26
+/dev/tty27
+/dev/tty28
+/dev/tty29
+/dev/tty30
+/dev/tty31
+/dev/tty32
+/dev/tty33
+/dev/tty34
+/dev/tty35
+/dev/tty36
+/dev/tty37
+/dev/tty38
+/dev/tty39
+/dev/tty40
+/dev/tty41
+/dev/tty42
+/dev/tty43
+/dev/tty44
+/dev/tty45
+/dev/tty46
+/dev/tty47
+/dev/tty48
+/dev/tty49
+/dev/tty50
+/dev/tty51
+/dev/tty52
+/dev/tty53
+/dev/tty54
+/dev/tty55
+/dev/tty56
+/dev/tty57
+/dev/tty58
+/dev/tty59
+/dev/tty60
+/dev/tty61
+/dev/tty62
+/dev/tty63
+/dev/tty0
+/dev/psaux
+/dev/ptyp0
+/dev/ptyp1
+/dev/ptyp2
+/dev/ptyp3
+/dev/ptyp4
+/dev/ptyp5
+/dev/ptyp6
+/dev/ptyp7
+/dev/ptyp8
+/dev/ptyp9
+/dev/ptypa
+/dev/ptypb
+/dev/ptypc
+/dev/ptypd
+/dev/ptype
+/dev/ptypf
+/dev/ptyq0
+/dev/ptyq1
+/dev/ptyq2
+/dev/ptyq3
+/dev/ptyq4
+/dev/ptyq5
+/dev/ptyq6
+/dev/ptyq7
+/dev/ptyq8
+/dev/ptyq9
+/dev/ptyqa
+/dev/ptyqb
+/dev/ptyqc
+/dev/ptyqd
+/dev/ptyqe
+/dev/ptyqf
+/dev/ptyr0
+/dev/ptyr1
+/dev/ptyr2
+/dev/ptyr3
+/dev/ptyr4
+/dev/ptyr5
+/dev/ptyr6
+/dev/ptyr7
+/dev/ptyr8
+/dev/ptyr9
+/dev/ptyra
+/dev/ptyrb
+/dev/ptyrc
+/dev/ptyrd
+/dev/ptyre
+/dev/ptyrf
+/dev/ptys0
+/dev/ptys1
+/dev/ptys2
+/dev/ptys3
+/dev/ptys4
+/dev/ptys5
+/dev/ptys6
+/dev/ptys7
+/dev/ptys8
+/dev/ptys9
+/dev/ptysa
+/dev/ptysb
+/dev/ptysc
+/dev/ptysd
+/dev/ptyse
+/dev/ptysf
+/dev/ptyt0
+/dev/ptyt1
+/dev/ptyt2
+/dev/ptyt3
+/dev/ptyt4
+/dev/ptyt5
+/dev/ptyt6
+/dev/ptyt7
+/dev/ptyt8
+/dev/ptyt9
+/dev/ptyta
+/dev/ptytb
+/dev/ptytc
+/dev/ptytd
+/dev/ptyte
+/dev/ptytf
+/dev/ptyu0
+/dev/ptyu1
+/dev/ptyu2
+/dev/ptyu3
+/dev/ptyu4
+/dev/ptyu5
+/dev/ptyu6
+/dev/ptyu7
+/dev/ptyu8
+/dev/ptyu9
+/dev/ptyua
+/dev/ptyub
+/dev/ptyuc
+/dev/ptyud
+/dev/ptyue
+/dev/ptyuf
+/dev/ptyv0
+/dev/ptyv1
+/dev/ptyv2
+/dev/ptyv3
+/dev/ptyv4
+/dev/ptyv5
+/dev/ptyv6
+/dev/ptyv7
+/dev/ptyv8
+/dev/ptyv9
+/dev/ptyva
+/dev/ptyvb
+/dev/ptyvc
+/dev/ptyvd
+/dev/ptyve
+/dev/ptyvf
+/dev/ptyw0
+/dev/ptyw1
+/dev/ptyw2
+/dev/ptyw3
+/dev/ptyw4
+/dev/ptyw5
+/dev/ptyw6
+/dev/ptyw7
+/dev/ptyw8
+/dev/ptyw9
+/dev/ptywa
+/dev/ptywb
+/dev/ptywc
+/dev/ptywd
+/dev/ptywe
+/dev/ptywf
+/dev/ptyx0
+/dev/ptyx1
+/dev/ptyx2
+/dev/ptyx3
+/dev/ptyx4
+/dev/ptyx5
+/dev/ptyx6
+/dev/ptyx7
+/dev/ptyx8
+/dev/ptyx9
+/dev/ptyxa
+/dev/ptyxb
+/dev/ptyxc
+/dev/ptyxd
+/dev/ptyxe
+/dev/ptyxf
+/dev/ptyy0
+/dev/ptyy1
+/dev/ptyy2
+/dev/ptyy3
+/dev/ptyy4
+/dev/ptyy5
+/dev/ptyy6
+/dev/ptyy7
+/dev/ptyy8
+/dev/ptyy9
+/dev/ptyya
+/dev/ptyyb
+/dev/ptyyc
+/dev/ptyyd
+/dev/ptyye
+/dev/ptyyf
+/dev/ptyz0
+/dev/ptyz1
+/dev/ptyz2
+/dev/ptyz3
+/dev/ptyz4
+/dev/ptyz5
+/dev/ptyz6
+/dev/ptyz7
+/dev/ptyz8
+/dev/ptyz9
+/dev/ptyza
+/dev/ptyzb
+/dev/ptyzc
+/dev/ptyzd
+/dev/ptyze
+/dev/ptyzf
+/dev/ptya0
+/dev/ptya1
+/dev/ptya2
+/dev/ptya3
+/dev/ptya4
+/dev/ptya5
+/dev/ptya6
+/dev/ptya7
+/dev/ptya8
+/dev/ptya9
+/dev/ptyaa
+/dev/ptyab
+/dev/ptyac
+/dev/ptyad
+/dev/ptyae
+/dev/ptyaf
+/dev/ptyb0
+/dev/ptyb1
+/dev/ptyb2
+/dev/ptyb3
+/dev/ptyb4
+/dev/ptyb5
+/dev/ptyb6
+/dev/ptyb7
+/dev/ptyb8
+/dev/ptyb9
+/dev/ptyba
+/dev/ptybb
+/dev/ptybc
+/dev/ptybd
+/dev/ptybe
+/dev/ptybf
+/dev/ptyc0
+/dev/ptyc1
+/dev/ptyc2
+/dev/ptyc3
+/dev/ptyc4
+/dev/ptyc5
+/dev/ptyc6
+/dev/ptyc7
+/dev/ptyc8
+/dev/ptyc9
+/dev/ptyca
+/dev/ptycb
+/dev/ptycc
+/dev/ptycd
+/dev/ptyce
+/dev/ptycf
+/dev/ptyd0
+/dev/ptyd1
+/dev/ptyd2
+/dev/ptyd3
+/dev/ptyd4
+/dev/ptyd5
+/dev/ptyd6
+/dev/ptyd7
+/dev/ptyd8
+/dev/ptyd9
+/dev/ptyda
+/dev/ptydb
+/dev/ptydc
+/dev/ptydd
+/dev/ptyde
+/dev/ptydf
+/dev/ptye0
+/dev/ptye1
+/dev/ptye2
+/dev/ptye3
+/dev/ptye4
+/dev/ptye5
+/dev/ptye6
+/dev/ptye7
+/dev/ptye8
+/dev/ptye9
+/dev/ptyea
+/dev/ptyeb
+/dev/ptyec
+/dev/ptyed
+/dev/ptyee
+/dev/ptyef
+/dev/vcs
+/dev/vcsa
+/dev/vcs1
+/dev/vcsa1
+/dev/ttyS0
+/dev/cua0
+/dev/hda
+/dev/hda1
+/dev/hda2
+/dev/hda3
+/dev/hda4
+/dev/hda5
+/dev/hda6
+/dev/hda7
+/dev/hda8
+/dev/hdb
+/dev/hdb1
+/dev/hdc
+/dev/hdc1
+/dev/fd0u1440
+/dev/fd0u1680
+/dev/fd0u1722
+/dev/fd0u1743
+/dev/fd0u1760
+/dev/fd0u1920
+/dev/fd0u1840
+/dev/fd0u1600
+/dev/fd0u360
+/dev/fd0u720
+/dev/fd0u820
+/dev/fd0u830
+/dev/fd0u1040
+/dev/fd0u1120
+/dev/fd0u800
+/dev/fd0
+/dev/loop0
+/dev/loop1
+/dev/loop2
+/dev/loop3
+/dev/loop4
+/dev/loop5
+/dev/loop6
+/dev/loop7
+/dev/dsp
+/dev/dsp1
+/dev/mixer
+/dev/midi
+/dev/lvm
+/dev/vg0
+/dev/vg0/group
+/dev/vg0/packages
+/dev/vg0/photos
+/dev/vg0/music
+/dev/log
+/dev/MAKEDEV
+/dev/printer
+/dev/vcs2
+/dev/vcsa2
+/dev/vcs3
+/dev/vcsa3
+/dev/vcs5
+/dev/vcsa5
+/dev/vcs4
+/dev/vcsa4
+/dev/vcs6
+/dev/vcsa6
+/dev/nvidia0
+/dev/nvidia1
+/dev/nvidia2
+/dev/nvidia3
+/dev/nvidiactl
+/dev/vcs7
+/dev/vcsa7
--- /dev/null
+/*
+ * Copyright (C) 2001 Sistina Software (UK) Limited.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "matcher.h"
+#include "dbg_malloc.h"
+#include "log.h"
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+
+static int _read_spec(const char *file, char ***regex, int *nregex)
+{
+ char buffer[1024], *start, *ptr;
+ FILE *fp = fopen(file, "r");
+ int asize = 100;
+ char **rx = dbg_malloc(sizeof(*rx) * asize);
+ int nr = 0;
+
+ if (!fp)
+ return 0;
+
+ while (fgets(buffer, sizeof(buffer),fp)) {
+
+ /* trim leading whitespace */
+ for (ptr = buffer; *ptr && isspace((int) *ptr); ptr++);
+
+ if (!*ptr || *ptr == '#')
+ continue;
+
+ if (*ptr == '\"') {
+ ptr++;
+ start = ptr;
+ while (*ptr && *ptr != '\"') {
+ if (*ptr == '\\')
+ ptr++;
+ ptr++;
+ }
+
+ if (!*ptr) {
+ fprintf(stderr, "Formatting error : "
+ "No terminating quote\n");
+ return 0;
+ }
+
+ rx[nr] = dbg_malloc((ptr - start) + 1);
+ strncpy(rx[nr], start, ptr - start);
+ rx[nr][ptr - start] = '\0';
+ nr++;
+ } else {
+ fprintf(stderr, "%s", ptr);
+ fprintf(stderr, "Formatting error : \"<regex>\" "
+ "<token_name>\n");
+ return 0;
+ }
+ }
+
+ *regex = rx;
+ *nregex = nr;
+ return 1;
+}
+
+static void _free_regex(char **regex, int nregex)
+{
+ int i;
+ for (i = 0; i < nregex; i++)
+ dbg_free(regex[i]);
+
+ dbg_free(regex);
+}
+
+static void _scan_input(struct matcher *m, char **regex)
+{
+ char buffer[256], *ptr;
+ int r;
+
+ while (fgets(buffer, sizeof(buffer), stdin)) {
+ if ((ptr = strchr(buffer, '\n')))
+ *ptr = '\0';
+
+ r = matcher_run(m, buffer, buffer + strlen(buffer));
+
+ if (r >= 0)
+ printf("%s : %s\n", buffer, regex[r]);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ struct pool *mem;
+ struct matcher *scanner;
+ char **regex;
+ int nregex;
+
+ if (argc < 2) {
+ fprintf(stderr, "Usage : %s <pattern_file>\n", argv[0]);
+ exit(1);
+ }
+
+ init_log(stderr);
+ init_debug(_LOG_DEBUG);
+
+ if (!(mem = pool_create(10 * 1024))) {
+ fprintf(stderr, "Couldn't create pool\n");
+ exit(2);
+ }
+
+ if (!_read_spec(argv[1], ®ex, &nregex)) {
+ fprintf(stderr, "Couldn't read the lex specification\n");
+ exit(3);
+ }
+
+ if (!(scanner = matcher_create(mem, (const char **) regex, nregex))) {
+ fprintf(stderr, "Couldn't build the lexer\n");
+ exit(4);
+ }
+
+ _scan_input(scanner, regex);
+ _free_regex(regex, nregex);
+ pool_destroy(mem);
+
+ dump_memory();
+ fin_log();
+ return 0;
+}
+
--- /dev/null
+/*
+ * Copyright (C) 2001 Sistina Software (UK) Limited.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dbg_malloc.h"
+#include "log.h"
+#include "../../lib/regex/parse_rx.h"
+#include "bitset.h"
+
+#include <stdio.h>
+#include <ctype.h>
+
+static void _pretty_print(struct rx_node *rx, int depth)
+{
+ int i;
+ for (i = 0; i < depth; i++)
+ printf(" ");
+
+ /* display info about the node */
+ switch (rx->type) {
+ case CAT:
+ printf("Cat");
+ break;
+
+ case OR:
+ printf("Or");
+ break;
+
+ case STAR:
+ printf("Star");
+ break;
+
+ case PLUS:
+ printf("Plus");
+ break;
+
+ case QUEST:
+ printf("Quest");
+ break;
+
+ case CHARSET:
+ printf("Charset : ");
+ for (i = 0; i < 256; i++) {
+ if (bit(rx->charset, i) && isprint(i))
+ printf("%c", (char) i);
+ }
+ break;
+
+ default:
+ printf("Unknown type");
+ }
+ printf("\n");
+
+ if (rx->left)
+ _pretty_print(rx->left, depth + 1);
+
+ if (rx->right)
+ _pretty_print(rx->right, depth + 1);
+}
+
+
+int main(int argc, char **argv)
+{
+ struct pool *mem;
+ struct rx_node *rx;
+
+ if (argc != 2) {
+ fprintf(stderr, "Usage : %s <regex>\n", argv[0]);
+ exit(0);
+ }
+
+ init_log(stderr);
+ init_debug(_LOG_INFO);
+
+ if (!(mem = pool_create(1024))) {
+ fprintf(stderr, "Couldn't create pool\n");
+ exit(1);
+ }
+
+ if (!(rx = rx_parse_str(mem, argv[1]))) {
+ fprintf(stderr, "Couldn't parse regex\n");
+ exit(1);
+ }
+
+ _pretty_print(rx, 0);
+ pool_destroy(mem);
+
+ dump_memory();
+ fin_log();
+ return 0;
+}