version 1.14, 2007/09/02 15:19:31 |
version 1.15, 2008/10/06 20:38:33 |
|
|
THIS SOFTWARE. |
THIS SOFTWARE. |
****************************************************************/ |
****************************************************************/ |
|
|
/* lasciate ogne speranza, voi ch'entrate. */ |
/* lasciate ogne speranza, voi ch'intrate. */ |
|
|
#define DEBUG |
#define DEBUG |
|
|
|
|
#define parent(v) (v)->nnext |
#define parent(v) (v)->nnext |
|
|
#define LEAF case CCL: case NCCL: case CHAR: case DOT: case FINAL: case ALL: |
#define LEAF case CCL: case NCCL: case CHAR: case DOT: case FINAL: case ALL: |
|
#define ELEAF case EMPTYRE: /* empty string in regexp */ |
#define UNARY case STAR: case PLUS: case QUEST: |
#define UNARY case STAR: case PLUS: case QUEST: |
|
|
/* encoding in tree Nodes: |
/* encoding in tree Nodes: |
leaf (CCL, NCCL, CHAR, DOT, FINAL, ALL): |
leaf (CCL, NCCL, CHAR, DOT, FINAL, ALL, EMPTYRE): |
left is index, right contains value or pointer to value |
left is index, right contains value or pointer to value |
unary (STAR, PLUS, QUEST): left is child, right is null |
unary (STAR, PLUS, QUEST): left is child, right is null |
binary (CAT, OR): left and right are children |
binary (CAT, OR): left and right are children |
|
|
void penter(Node *p) /* set up parent pointers and leaf indices */ |
void penter(Node *p) /* set up parent pointers and leaf indices */ |
{ |
{ |
switch (type(p)) { |
switch (type(p)) { |
|
ELEAF |
LEAF |
LEAF |
info(p) = poscnt; |
info(p) = poscnt; |
poscnt++; |
poscnt++; |
|
|
void freetr(Node *p) /* free parse tree */ |
void freetr(Node *p) /* free parse tree */ |
{ |
{ |
switch (type(p)) { |
switch (type(p)) { |
|
ELEAF |
LEAF |
LEAF |
xfree(p); |
xfree(p); |
break; |
break; |
|
|
continue; |
continue; |
} |
} |
while (c < c2) { |
while (c < c2) { |
if (!adjbuf((char **) &buf, &bufsz, bp-buf+2, 100, (char **) &bp, 0)) |
if (!adjbuf((char **) &buf, &bufsz, bp-buf+2, 100, (char **) &bp, "cclenter1")) |
FATAL("out of space for character class [%.10s...] 2", p); |
FATAL("out of space for character class [%.10s...] 2", p); |
*bp++ = ++c; |
*bp++ = ++c; |
i++; |
i++; |
|
|
continue; |
continue; |
} |
} |
} |
} |
if (!adjbuf((char **) &buf, &bufsz, bp-buf+2, 100, (char **) &bp, 0)) |
if (!adjbuf((char **) &buf, &bufsz, bp-buf+2, 100, (char **) &bp, "cclenter2")) |
FATAL("out of space for character class [%.10s...] 3", p); |
FATAL("out of space for character class [%.10s...] 3", p); |
*bp++ = c; |
*bp++ = c; |
i++; |
i++; |
|
|
int *p; |
int *p; |
|
|
switch (type(v)) { |
switch (type(v)) { |
|
ELEAF |
LEAF |
LEAF |
f->re[info(v)].ltype = type(v); |
f->re[info(v)].ltype = type(v); |
f->re[info(v)].lval.np = right(v); |
f->re[info(v)].lval.np = right(v); |
|
|
} |
} |
|
|
int first(Node *p) /* collects initially active leaves of p into setvec */ |
int first(Node *p) /* collects initially active leaves of p into setvec */ |
/* returns 1 if p matches empty string */ |
/* returns 0 if p matches empty string */ |
{ |
{ |
int b, lp; |
int b, lp; |
|
|
switch (type(p)) { |
switch (type(p)) { |
|
ELEAF |
LEAF |
LEAF |
lp = info(p); /* look for high-water mark of subscripts */ |
lp = info(p); /* look for high-water mark of subscripts */ |
while (setcnt >= maxsetvec || lp >= maxsetvec) { /* guessing here! */ |
while (setcnt >= maxsetvec || lp >= maxsetvec) { /* guessing here! */ |
|
|
if (setvec == 0 || tmpset == 0) |
if (setvec == 0 || tmpset == 0) |
overflo("out of space in first()"); |
overflo("out of space in first()"); |
} |
} |
|
if (type(p) == EMPTYRE) { |
|
setvec[lp] = 0; |
|
return(0); |
|
} |
if (setvec[lp] != 1) { |
if (setvec[lp] != 1) { |
setvec[lp] = 1; |
setvec[lp] = 1; |
setcnt++; |
setcnt++; |
|
|
if (f->out[s]) |
if (f->out[s]) |
return(1); |
return(1); |
do { |
do { |
assert(*p < NCHARS); |
/* assert(*p < NCHARS); */ |
if ((ns = f->gototab[s][*p]) != 0) |
if ((ns = f->gototab[s][*p]) != 0) |
s = ns; |
s = ns; |
else |
else |
|
|
do { |
do { |
if (f->out[s]) /* final state */ |
if (f->out[s]) /* final state */ |
patlen = q-p; |
patlen = q-p; |
assert(*q < NCHARS); |
/* assert(*q < NCHARS); */ |
if ((ns = f->gototab[s][*q]) != 0) |
if ((ns = f->gototab[s][*q]) != 0) |
s = ns; |
s = ns; |
else |
else |
|
|
do { |
do { |
if (f->out[s]) /* final state */ |
if (f->out[s]) /* final state */ |
patlen = q-p; |
patlen = q-p; |
assert(*q < NCHARS); |
/* assert(*q < NCHARS); */ |
if ((ns = f->gototab[s][*q]) != 0) |
if ((ns = f->gototab[s][*q]) != 0) |
s = ns; |
s = ns; |
else |
else |
|
|
lastre = prestr = (uschar *) p; /* prestr points to string to be parsed */ |
lastre = prestr = (uschar *) p; /* prestr points to string to be parsed */ |
rtok = relex(); |
rtok = relex(); |
/* GNU compatibility: an empty regexp matches anything */ |
/* GNU compatibility: an empty regexp matches anything */ |
if (rtok == '\0') |
if (rtok == '\0') { |
/* FATAL("empty regular expression"); previous */ |
/* FATAL("empty regular expression"); previous */ |
return(op2(ALL, NIL, NIL)); |
return(op2(EMPTYRE, NIL, NIL)); |
|
} |
np = regexp(); |
np = regexp(); |
if (rtok != '\0') |
if (rtok != '\0') |
FATAL("syntax error in regular expression %s at %s", lastre, prestr); |
FATAL("syntax error in regular expression %s at %s", lastre, prestr); |
|
|
case ALL: |
case ALL: |
rtok = relex(); |
rtok = relex(); |
return (unary(op2(ALL, NIL, NIL))); |
return (unary(op2(ALL, NIL, NIL))); |
|
case EMPTYRE: |
|
rtok = relex(); |
|
return (unary(op2(ALL, NIL, NIL))); |
case DOT: |
case DOT: |
rtok = relex(); |
rtok = relex(); |
return (unary(op2(DOT, NIL, NIL))); |
return (unary(op2(DOT, NIL, NIL))); |
|
|
Node *concat(Node *np) |
Node *concat(Node *np) |
{ |
{ |
switch (rtok) { |
switch (rtok) { |
case CHAR: case DOT: case ALL: case CCL: case NCCL: case '$': case '(': |
case CHAR: case DOT: case ALL: case EMPTYRE: case CCL: case NCCL: case '$': case '(': |
return (concat(op2(CAT, np, primary()))); |
return (concat(op2(CAT, np, primary()))); |
} |
} |
return (np); |
return (np); |
|
|
else |
else |
cflag = 0; |
cflag = 0; |
n = 2 * strlen((const char *) prestr)+1; |
n = 2 * strlen((const char *) prestr)+1; |
if (!adjbuf((char **) &buf, &bufsz, n, n, (char **) &bp, 0)) |
if (!adjbuf((char **) &buf, &bufsz, n, n, (char **) &bp, "relex1")) |
FATAL("out of space for reg expr %.10s...", lastre); |
FATAL("out of space for reg expr %.10s...", lastre); |
for (; ; ) { |
for (; ; ) { |
if ((c = *prestr++) == '\\') { |
if ((c = *prestr++) == '\\') { |
|
|
prestr[2 + cc->cc_namelen] == ']') { |
prestr[2 + cc->cc_namelen] == ']') { |
prestr += cc->cc_namelen + 3; |
prestr += cc->cc_namelen + 3; |
for (i = 0; i < NCHARS; i++) { |
for (i = 0; i < NCHARS; i++) { |
if (!adjbuf((char **) &buf, &bufsz, bp-buf+1, 100, (char **) &bp, 0)) |
if (!adjbuf((char **) &buf, &bufsz, bp-buf+1, 100, (char **) &bp, "relex2")) |
FATAL("out of space for reg expr %.10s...", lastre); |
FATAL("out of space for reg expr %.10s...", lastre); |
if (cc->cc_func(i)) { |
if (cc->cc_func(i)) { |
*bp++ = i; |
*bp++ = i; |
|
|
if ((k == CHAR && c == ptoi(f->re[p[i]].lval.np)) |
if ((k == CHAR && c == ptoi(f->re[p[i]].lval.np)) |
|| (k == DOT && c != 0 && c != HAT) |
|| (k == DOT && c != 0 && c != HAT) |
|| (k == ALL && c != 0) |
|| (k == ALL && c != 0) |
|
|| (k == EMPTYRE && c != 0) |
|| (k == CCL && member(c, (char *) f->re[p[i]].lval.up)) |
|| (k == CCL && member(c, (char *) f->re[p[i]].lval.up)) |
|| (k == NCCL && !member(c, (char *) f->re[p[i]].lval.up) && c != 0 && c != HAT)) { |
|| (k == NCCL && !member(c, (char *) f->re[p[i]].lval.up) && c != 0 && c != HAT)) { |
q = f->re[p[i]].lfollow; |
q = f->re[p[i]].lfollow; |