diff options
author | Steve Bennett <steveb@workware.net.au> | 2011-11-09 10:05:10 +1000 |
---|---|---|
committer | Steve Bennett <steveb@workware.net.au> | 2011-11-10 07:40:04 +1000 |
commit | 87507cd2fc4106bb77a487443ea20abf82a92502 (patch) | |
tree | 1c81018a0a0aae1384dc947c5203d7efbc2291eb | |
parent | c337e92c74561ffa788dcea71cc45dc85da17817 (diff) | |
download | jimtcl-87507cd2fc4106bb77a487443ea20abf82a92502.zip jimtcl-87507cd2fc4106bb77a487443ea20abf82a92502.tar.gz jimtcl-87507cd2fc4106bb77a487443ea20abf82a92502.tar.bz2 |
regex: counts were not all being cleared
If a cached regex containing counts was reused, the result
may have been incorrect.
Signed-off-by: Steve Bennett <steveb@workware.net.au>
-rw-r--r-- | jimregexp.c | 31 | ||||
-rw-r--r-- | tests/regcount.test | 6 |
2 files changed, 31 insertions, 6 deletions
diff --git a/jimregexp.c b/jimregexp.c index dbb49e9..0c5a4dd 100644 --- a/jimregexp.c +++ b/jimregexp.c @@ -191,7 +191,7 @@ static int prefix_cmp(const int *prog, int proglen, const char *string, int noca /*#define DEBUG*/ #ifdef DEBUG -int regnarrate = 0; +static int regnarrate = 0; static void regdump(regex_t *preg); static const char *regprop( int op ); #endif @@ -246,13 +246,11 @@ int regcomp(regex_t *preg, const char *exp, int cflags) preg->program = NULL; preg->proglen = 0; -#if 1 /* Allocate space. */ preg->proglen = (strlen(exp) + 1) * 5; preg->program = malloc(preg->proglen * sizeof(int)); if (preg->program == NULL) FAIL(preg, REG_ERR_NOMEM); -#endif /* Note that since we store a magic value as the first item in the program, * program offsets will never be 0 @@ -1031,13 +1029,30 @@ int regexec(regex_t *preg, const char *string, size_t nmatch, regmatch_t pmat preg->start = string; /* All offsets are computed from here */ /* Must clear out the embedded repeat counts */ - for (scan = OPERAND(1); scan != 0; scan = regnext(preg, scan)) { + for (scan = OPERAND(1); scan != 0; ) { switch (OP(preg, scan)) { case REP: case REPMIN: case REPX: case REPXMIN: preg->program[scan + 4] = 0; + scan += 5; + break; + + case ANYOF: + case ANYBUT: + case EXACTLY: + scan += 2; + while (preg->program[scan++]) { + } + break; + + case END: + scan = 0; + break; + + default: + scan += 2; break; } } @@ -1598,8 +1613,8 @@ static void regdump(regex_t *preg) int i; for (i = 1; i < preg->p; i++) { - printf("%02x ", preg->program[i]); - if (i % 16 == 15) { + printf("%02x ", (unsigned char)preg->program[i]); + if (i % 16 == 0) { printf("\n"); } } @@ -1715,6 +1730,10 @@ static const char *regprop( int op ) return "WORDA"; case WORDZ: return "WORDZ"; + case OPENNC: + return "OPEN"; + case CLOSENC: + return "CLOSE"; default: if (op >= OPEN && op < CLOSE) { snprintf(buf, sizeof(buf), "OPEN%d", op-OPEN); diff --git a/tests/regcount.test b/tests/regcount.test index 6b05686..96f4ddd 100644 --- a/tests/regcount.test +++ b/tests/regcount.test @@ -103,4 +103,10 @@ foreach {pat str exp} { test regcount-1.[incr n] "Test: regexp $pat $str" [list regexp -inline -- $pat $str] $exp } +test regcount-2.1 "regexp counts cleared" { + set re "((a|b){1,2}(c{2,3}))" + regexp -inline $re xabcccce + regexp -inline $re xabcccce +} {abccc abccc b ccc} + testreport |