]> sourceware.org Git - lvm2.git/commitdiff
o First pass at the regex code. lib/regex/matcher takes an array of regex's
authorJoe Thornber <thornber@redhat.com>
Fri, 19 Oct 2001 14:36:57 +0000 (14:36 +0000)
committerJoe Thornber <thornber@redhat.com>
Fri, 19 Oct 2001 14:36:57 +0000 (14:36 +0000)
  and builds a *very* efficient engine that will tell you which regex a string
  matches with only a single pass through the string.  To be used in the config
  file when specifying devices.

o Anchor's aren't supported yet (^ and $) but that won't take long.

o Also when we get some realistic config files we may want to consider adding an
  extra level of indirection to the dfa state in order to compress the table.
  It all depends on how large typical tables get.

18 files changed:
configure
configure.in
include/.symlinks
lib/Makefile.in
lib/datastruct/bitset.c [new file with mode: 0644]
lib/datastruct/bitset.h [new file with mode: 0644]
lib/regex/matcher.c [new file with mode: 0644]
lib/regex/matcher.h [new file with mode: 0644]
lib/regex/parse_rx.c [new file with mode: 0644]
lib/regex/parse_rx.h [new file with mode: 0644]
lib/regex/ttree.c [new file with mode: 0644]
lib/regex/ttree.h [new file with mode: 0644]
old-tests/format1/read_vg_t.c
old-tests/regex/Makefile.in [new file with mode: 0644]
old-tests/regex/dev_patterns [new file with mode: 0644]
old-tests/regex/devices.list [new file with mode: 0644]
old-tests/regex/matcher_t.c [new file with mode: 0644]
old-tests/regex/parse_t.c [new file with mode: 0644]

index 3368518313056167aa3f5b0efd47b1fd2ec18b67..c59e4089f9f24ce47447ae8f5da7cf27b93d51c2 100755 (executable)
--- a/configure
+++ b/configure
@@ -2162,6 +2162,7 @@ tools/Makefile                                                            \
 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
@@ -2260,6 +2261,7 @@ tools/Makefile                                                            \
 test/mm/Makefile                                                       \
 test/device/Makefile                                                   \
 test/format1/Makefile                                                  \
+test/regex/Makefile                                                     \
 "}
 EOF
 cat >> $CONFIG_STATUS <<\EOF
index 9968b1ccf7ebfe23452621fce2c2e67645a4d742..7365ecb6a4b3e80a423da1372e9650e224a5885c 100644 (file)
@@ -138,4 +138,5 @@ tools/Makefile                                                              \
 test/mm/Makefile                                                       \
 test/device/Makefile                                                   \
 test/format1/Makefile                                                  \
+test/regex/Makefile                                                     \
 )
index 486f9e1d5e7185764176c1e58dda3dd5d1cfdc85..4193c2888120ee0832a9497c9d01bf7e3d8b8457 100644 (file)
@@ -1,5 +1,6 @@
 ../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
@@ -13,4 +14,5 @@
 ../lib/mm/dbg_malloc.h
 ../lib/mm/pool.h
 ../lib/mm/xlate.h
+../lib/regex/matcher.h
 ../lib/uuid/uuid.h
index 3676762e0730da9e635d5dead83915873a368b00..4ef950ae3fcfceea27bc078609d0aa5f32b2bcd5 100644 (file)
@@ -11,11 +11,11 @@ VPATH = @srcdir@
 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 \
@@ -26,6 +26,9 @@ SOURCES=\
        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
diff --git a/lib/datastruct/bitset.c b/lib/datastruct/bitset.c
new file mode 100644 (file)
index 0000000..707a51d
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * 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);
+}
diff --git a/lib/datastruct/bitset.h b/lib/datastruct/bitset.h
new file mode 100644 (file)
index 0000000..93f1c13
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * 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
diff --git a/lib/regex/matcher.c b/lib/regex/matcher.c
new file mode 100644 (file)
index 0000000..94fd526
--- /dev/null
@@ -0,0 +1,349 @@
+/*
+ * 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);
+}
diff --git a/lib/regex/matcher.h b/lib/regex/matcher.h
new file mode 100644 (file)
index 0000000..40b68f7
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * 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
diff --git a/lib/regex/parse_rx.c b/lib/regex/parse_rx.c
new file mode 100644 (file)
index 0000000..fc750fa
--- /dev/null
@@ -0,0 +1,363 @@
+/*
+ * 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));
+}
diff --git a/lib/regex/parse_rx.h b/lib/regex/parse_rx.h
new file mode 100644 (file)
index 0000000..f75c995
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * 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
diff --git a/lib/regex/ttree.c b/lib/regex/ttree.c
new file mode 100644 (file)
index 0000000..38e6ba2
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * 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;
+}
diff --git a/lib/regex/ttree.h b/lib/regex/ttree.h
new file mode 100644 (file)
index 0000000..06e116f
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * 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
index a5c93a2a6afcd3f589e210d9d0ee637b89e00329..8ce0c49fe347cac36f315e419f411f0e561978d0 100644 (file)
@@ -65,3 +65,4 @@ int main(int argc, char **argv)
        fin_log();
        return 0;
 }
+
diff --git a/old-tests/regex/Makefile.in b/old-tests/regex/Makefile.in
new file mode 100644 (file)
index 0000000..c1be292
--- /dev/null
@@ -0,0 +1,26 @@
+#
+# 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
+
diff --git a/old-tests/regex/dev_patterns b/old-tests/regex/dev_patterns
new file mode 100644 (file)
index 0000000..34459ba
--- /dev/null
@@ -0,0 +1,2 @@
+"loop/[0-9]+"
+"hd[a-d][0-5]+"
diff --git a/old-tests/regex/devices.list b/old-tests/regex/devices.list
new file mode 100644 (file)
index 0000000..91af305
--- /dev/null
@@ -0,0 +1,880 @@
+/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
diff --git a/old-tests/regex/matcher_t.c b/old-tests/regex/matcher_t.c
new file mode 100644 (file)
index 0000000..00deea9
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * 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], &regex, &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;
+}
+
diff --git a/old-tests/regex/parse_t.c b/old-tests/regex/parse_t.c
new file mode 100644 (file)
index 0000000..25bf7f9
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * 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;
+}
This page took 0.096506 seconds and 5 git commands to generate.