1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-21 13:34:40 +03:00

o First pass at the regex code. lib/regex/matcher takes an array of regex's

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.
This commit is contained in:
Joe Thornber 2001-10-19 14:36:57 +00:00
parent cd77c5a7b7
commit d1b28647ed
18 changed files with 2188 additions and 1 deletions

2
configure vendored
View File

@ -2162,6 +2162,7 @@ tools/Makefile \
test/mm/Makefile \ test/mm/Makefile \
test/device/Makefile \ test/device/Makefile \
test/format1/Makefile \ test/format1/Makefile \
test/regex/Makefile \
" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 " | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
EOF EOF
cat >> $CONFIG_STATUS <<EOF cat >> $CONFIG_STATUS <<EOF
@ -2260,6 +2261,7 @@ tools/Makefile \
test/mm/Makefile \ test/mm/Makefile \
test/device/Makefile \ test/device/Makefile \
test/format1/Makefile \ test/format1/Makefile \
test/regex/Makefile \
"} "}
EOF EOF
cat >> $CONFIG_STATUS <<\EOF cat >> $CONFIG_STATUS <<\EOF

View File

@ -138,4 +138,5 @@ tools/Makefile \
test/mm/Makefile \ test/mm/Makefile \
test/device/Makefile \ test/device/Makefile \
test/format1/Makefile \ test/format1/Makefile \
test/regex/Makefile \
) )

View File

@ -1,5 +1,6 @@
../lib/activate/activate.h ../lib/activate/activate.h
../lib/config/config.h ../lib/config/config.h
../lib/datastruct/bitset.h
../lib/datastruct/hash.h ../lib/datastruct/hash.h
../lib/datastruct/list.h ../lib/datastruct/list.h
../lib/datastruct/lvm-types.h ../lib/datastruct/lvm-types.h
@ -13,4 +14,5 @@
../lib/mm/dbg_malloc.h ../lib/mm/dbg_malloc.h
../lib/mm/pool.h ../lib/mm/pool.h
../lib/mm/xlate.h ../lib/mm/xlate.h
../lib/regex/matcher.h
../lib/uuid/uuid.h ../lib/uuid/uuid.h

View File

@ -11,11 +11,11 @@ VPATH = @srcdir@
SOURCES=\ SOURCES=\
activate/activate.c \ activate/activate.c \
config/config.c \ config/config.c \
datastruct/bitset.c \
datastruct/hash.c \ datastruct/hash.c \
device/dev-cache.c \ device/dev-cache.c \
device/dev-io.c \ device/dev-io.c \
device/device.c \ device/device.c \
display/display.c \
filters/filter.c \ filters/filter.c \
format1/disk-rep.c \ format1/disk-rep.c \
format1/format1.c \ format1/format1.c \
@ -26,6 +26,9 @@ SOURCES=\
metadata/metadata.c \ metadata/metadata.c \
mm/dbg_malloc.c \ mm/dbg_malloc.c \
mm/pool.c \ mm/pool.c \
regex/parse_rx.c \
regex/matcher.c \
regex/ttree.c \
uuid/uuid.c uuid/uuid.c
TARGETS=liblvm.a TARGETS=liblvm.a

79
lib/datastruct/bitset.c Normal file
View File

@ -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);
}

46
lib/datastruct/bitset.h Normal file
View File

@ -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

349
lib/regex/matcher.c Normal file
View File

@ -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);
}

18
lib/regex/matcher.h Normal file
View File

@ -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

363
lib/regex/parse_rx.c Normal file
View File

@ -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));
}

39
lib/regex/parse_rx.h Normal file
View File

@ -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

129
lib/regex/ttree.c Normal file
View File

@ -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;
}

19
lib/regex/ttree.h Normal file
View File

@ -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

View File

@ -65,3 +65,4 @@ int main(int argc, char **argv)
fin_log(); fin_log();
return 0; return 0;
} }

View File

@ -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

View File

@ -0,0 +1,2 @@
"loop/[0-9]+"
"hd[a-d][0-5]+"

View File

@ -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

135
old-tests/regex/matcher_t.c Normal file
View File

@ -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;
}

93
old-tests/regex/parse_t.c Normal file
View File

@ -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;
}