Tracker: style fixes to RegExp (minor)

This commit is contained in:
John Scipione
2014-06-20 21:29:30 -04:00
parent 0c7c3ed429
commit 96d9dde048
2 changed files with 294 additions and 179 deletions
+291 -179
View File
@@ -168,6 +168,7 @@ const char* kMeta = "^$.[()|?+*\\";
const int32 kMaxSize = 32767L; const int32 kMaxSize = 32767L;
// Probably could be 65535L. // Probably could be 65535L.
// Flags to be passed up and down: // Flags to be passed up and down:
enum { enum {
kHasWidth = 01, // Known never to match null string. kHasWidth = 01, // Known never to match null string.
@@ -176,6 +177,7 @@ enum {
kWorst = 0 // Worst case. kWorst = 0 // Worst case.
}; };
const char* kRegExpErrorStringArray[] = { const char* kRegExpErrorStringArray[] = {
"Unmatched parenthesis.", "Unmatched parenthesis.",
"Expression too long.", "Expression too long.",
@@ -194,28 +196,36 @@ const char* kRegExpErrorStringArray[] = {
"Corrupted opcode." "Corrupted opcode."
}; };
#ifdef DEBUG #ifdef DEBUG
int32 regnarrate = 0; int32 regnarrate = 0;
#endif #endif
// #pragma mark - RegExp
RegExp::RegExp() RegExp::RegExp()
: fError(B_OK), :
fRegExp(NULL) fError(B_OK),
fRegExp(NULL)
{ {
} }
RegExp::RegExp(const char* pattern) RegExp::RegExp(const char* pattern)
: fError(B_OK), :
fRegExp(NULL) fError(B_OK),
fRegExp(NULL)
{ {
fRegExp = Compile(pattern); fRegExp = Compile(pattern);
} }
RegExp::RegExp(const BString &pattern) RegExp::RegExp(const BString &pattern)
: fError(B_OK), :
fRegExp(NULL) fError(B_OK),
fRegExp(NULL)
{ {
fRegExp = Compile(pattern.String()); fRegExp = Compile(pattern.String());
} }
@@ -257,7 +267,7 @@ RegExp::SetTo(const BString &pattern)
bool bool
RegExp::Matches(const char* string) const RegExp::Matches(const char* string) const
{ {
if (!fRegExp || !string) if (fRegExp == NULL || string == NULL)
return false; return false;
return RunMatcher(fRegExp, string) == 1; return RunMatcher(fRegExp, string) == 1;
@@ -267,7 +277,7 @@ RegExp::Matches(const char* string) const
bool bool
RegExp::Matches(const BString &string) const RegExp::Matches(const BString &string) const
{ {
if (!fRegExp) if (fRegExp == NULL)
return false; return false;
return RunMatcher(fRegExp, string.String()) == 1; return RunMatcher(fRegExp, string.String()) == 1;
@@ -320,7 +330,7 @@ RegExp::Compile(const char* exp)
r = (regexp*)malloc(sizeof(regexp) + fCodeSize); r = (regexp*)malloc(sizeof(regexp) + fCodeSize);
// Allocate space // Allocate space
if (!r) { if (r == NULL) {
SetError(B_NO_MEMORY); SetError(B_NO_MEMORY);
return NULL; return NULL;
} }
@@ -336,7 +346,8 @@ RegExp::Compile(const char* exp)
} }
// Dig out information for optimizations. // Dig out information for optimizations.
r->regstart = '\0'; // Worst-case defaults. r->regstart = '\0';
// Worst-case defaults.
r->reganch = 0; r->reganch = 0;
r->regmust = NULL; r->regmust = NULL;
r->regmlen = 0; r->regmlen = 0;
@@ -358,15 +369,16 @@ RegExp::Compile(const char* exp)
// the regstart check works with the beginning of the r.e. // the regstart check works with the beginning of the r.e.
// and avoiding duplication strengthens checking. Not a // and avoiding duplication strengthens checking. Not a
// strong reason, but sufficient in the absence of others. // strong reason, but sufficient in the absence of others.
if (flags&kSPStart) { if ((flags & kSPStart) != 0) {
longest = NULL; longest = NULL;
len = 0; len = 0;
for (; scan != NULL; scan = Next((char*)scan)) for (; scan != NULL; scan = Next((char*)scan)) {
if (*scan == kRegExpExactly if (*scan == kRegExpExactly
&& (int32)strlen(Operand(scan)) >= len) { && (int32)strlen(Operand(scan)) >= len) {
longest = Operand(scan); longest = Operand(scan);
len = (int32)strlen(Operand(scan)); len = (int32)strlen(Operand(scan));
} }
}
r->regmust = longest; r->regmust = longest;
r->regmlen = len; r->regmlen = len;
} }
@@ -387,8 +399,9 @@ const char*
RegExp::ErrorString() const RegExp::ErrorString() const
{ {
if (fError >= REGEXP_UNMATCHED_PARENTHESIS if (fError >= REGEXP_UNMATCHED_PARENTHESIS
&& fError <= REGEXP_CORRUPTED_OPCODE) && fError <= REGEXP_CORRUPTED_OPCODE) {
return kRegExpErrorStringArray[fError - B_ERRORS_END]; return kRegExpErrorStringArray[fError - B_ERRORS_END];
}
return strerror(fError); return strerror(fError);
} }
@@ -419,7 +432,8 @@ RegExp::Reg(int32 paren, int32* flagp)
int32 parno = 0; int32 parno = 0;
int32 flags; int32 flags;
*flagp = kHasWidth; // Tentatively. *flagp = kHasWidth;
// Tentatively.
// Make an kRegExpOpen node, if parenthesized. // Make an kRegExpOpen node, if parenthesized.
if (paren) { if (paren) {
@@ -437,21 +451,28 @@ RegExp::Reg(int32 paren, int32* flagp)
br = Branch(&flags); br = Branch(&flags);
if (br == NULL) if (br == NULL)
return NULL; return NULL;
if (ret != NULL)
Tail(ret, br); // kRegExpOpen -> first if (ret != NULL) {
else Tail(ret, br);
// kRegExpOpen -> first
} else
ret = br; ret = br;
if (!(flags & kHasWidth)) if (!(flags & kHasWidth))
*flagp &= ~kHasWidth; *flagp &= ~kHasWidth;
*flagp |= flags&kSPStart; *flagp |= flags&kSPStart;
while (*fInputScanPointer == '|') { while (*fInputScanPointer == '|') {
fInputScanPointer++; fInputScanPointer++;
br = Branch(&flags); br = Branch(&flags);
if (br == NULL) if (br == NULL)
return NULL; return NULL;
Tail(ret, br); // kRegExpBranch -> kRegExpBranch.
Tail(ret, br);
// kRegExpBranch -> kRegExpBranch.
if (!(flags & kHasWidth)) if (!(flags & kHasWidth))
*flagp &= ~kHasWidth; *flagp &= ~kHasWidth;
*flagp |= flags&kSPStart; *flagp |= flags&kSPStart;
} }
@@ -495,7 +516,8 @@ RegExp::Branch(int32* flagp)
char* latest; char* latest;
int32 flags; int32 flags;
*flagp = kWorst; // Tentatively. *flagp = kWorst;
// Tentatively.
ret = Node(kRegExpBranch); ret = Node(kRegExpBranch);
chain = NULL; chain = NULL;
@@ -505,15 +527,21 @@ RegExp::Branch(int32* flagp)
latest = Piece(&flags); latest = Piece(&flags);
if (latest == NULL) if (latest == NULL)
return NULL; return NULL;
*flagp |= flags & kHasWidth; *flagp |= flags & kHasWidth;
if (chain == NULL) // First piece. if (chain == NULL) {
// First piece.
*flagp |= flags & kSPStart; *flagp |= flags & kSPStart;
else } else
Tail(chain, latest); Tail(chain, latest);
chain = latest; chain = latest;
} }
if (chain == NULL) // Loop ran zero times.
if (chain == NULL) {
// Loop ran zero times.
Node(kRegExpNothing); Node(kRegExpNothing);
}
return ret; return ret;
} }
@@ -556,33 +584,47 @@ RegExp::Piece(int32* flagp)
Insert(kRegExpStar, ret); Insert(kRegExpStar, ret);
else if (op == '*') { else if (op == '*') {
// Emit x* as (x&|), where & means "self". // Emit x* as (x&|), where & means "self".
Insert(kRegExpBranch, ret); // Either x Insert(kRegExpBranch, ret);
OpTail(ret, Node(kRegExpBack)); // and loop // Either x
OpTail(ret, ret); // back OpTail(ret, Node(kRegExpBack));
Tail(ret, Node(kRegExpBranch)); // or // and loop
Tail(ret, Node(kRegExpNothing)); // null. OpTail(ret, ret);
// back
Tail(ret, Node(kRegExpBranch));
// or
Tail(ret, Node(kRegExpNothing));
// null.
} else if (op == '+' && (flags & kSimple)) } else if (op == '+' && (flags & kSimple))
Insert(kRegExpPlus, ret); Insert(kRegExpPlus, ret);
else if (op == '+') { else if (op == '+') {
// Emit x+ as x(&|), where & means "self". // Emit x+ as x(&|), where & means "self".
next = Node(kRegExpBranch); // Either next = Node(kRegExpBranch);
// Either
Tail(ret, next); Tail(ret, next);
Tail(Node(kRegExpBack), ret); // loop back Tail(Node(kRegExpBack), ret);
Tail(next, Node(kRegExpBranch)); // or // loop back
Tail(ret, Node(kRegExpNothing)); // null. Tail(next, Node(kRegExpBranch));
// or
Tail(ret, Node(kRegExpNothing));
// null.
} else if (op == '?') { } else if (op == '?') {
// Emit x? as (x|) // Emit x? as (x|)
Insert(kRegExpBranch, ret); // Either x Insert(kRegExpBranch, ret);
Tail(ret, Node(kRegExpBranch)); // or // Either x
next = Node(kRegExpNothing); // null. Tail(ret, Node(kRegExpBranch));
// or
next = Node(kRegExpNothing);
// null.
Tail(ret, next); Tail(ret, next);
OpTail(ret, next); OpTail(ret, next);
} }
fInputScanPointer++; fInputScanPointer++;
if (IsMult(*fInputScanPointer)) { if (IsMult(*fInputScanPointer)) {
SetError(REGEXP_NESTED_STAR_QUESTION_PLUS); SetError(REGEXP_NESTED_STAR_QUESTION_PLUS);
return NULL; return NULL;
} }
return ret; return ret;
} }
@@ -601,77 +643,87 @@ RegExp::Atom(int32* flagp)
char* ret; char* ret;
int32 flags; int32 flags;
*flagp = kWorst; // Tentatively. *flagp = kWorst;
// tentatively
switch (*fInputScanPointer++) { switch (*fInputScanPointer++) {
case '^': case '^':
ret = Node(kRegExpBol); ret = Node(kRegExpBol);
break; break;
case '$': case '$':
ret = Node(kRegExpEol); ret = Node(kRegExpEol);
break; break;
case '.': case '.':
ret = Node(kRegExpAny); ret = Node(kRegExpAny);
*flagp |= kHasWidth|kSimple; *flagp |= kHasWidth|kSimple;
break; break;
case '[':
{
int32 cclass;
int32 classend;
if (*fInputScanPointer == '^') { // Complement of range. case '[':
ret = Node(kRegExpAnyBut); {
fInputScanPointer++; int32 cclass;
} else int32 classend;
ret = Node(kRegExpAnyOf);
if (*fInputScanPointer == ']' || *fInputScanPointer == '-') if (*fInputScanPointer == '^') {
Char(*fInputScanPointer++); // complement of range
while (*fInputScanPointer != '\0' ret = Node(kRegExpAnyBut);
&& *fInputScanPointer != ']') {
if (*fInputScanPointer == '-') {
fInputScanPointer++;
if (*fInputScanPointer == ']'
|| *fInputScanPointer == '\0') {
Char('-');
} else {
cclass = UCharAt(fInputScanPointer - 2) + 1;
classend = UCharAt(fInputScanPointer);
if (cclass > classend + 1) {
SetError(REGEXP_INVALID_BRACKET_RANGE);
return NULL;
}
for (; cclass <= classend; cclass++)
Char((char)cclass);
fInputScanPointer++;
}
} else
Char(*fInputScanPointer++);
}
Char('\0');
if (*fInputScanPointer != ']') {
SetError(REGEXP_UNMATCHED_BRACKET);
return NULL;
}
fInputScanPointer++; fInputScanPointer++;
*flagp |= kHasWidth | kSimple; } else
ret = Node(kRegExpAnyOf);
if (*fInputScanPointer == ']' || *fInputScanPointer == '-')
Char(*fInputScanPointer++);
while (*fInputScanPointer != '\0'
&& *fInputScanPointer != ']') {
if (*fInputScanPointer == '-') {
fInputScanPointer++;
if (*fInputScanPointer == ']'
|| *fInputScanPointer == '\0') {
Char('-');
} else {
cclass = UCharAt(fInputScanPointer - 2) + 1;
classend = UCharAt(fInputScanPointer);
if (cclass > classend + 1) {
SetError(REGEXP_INVALID_BRACKET_RANGE);
return NULL;
}
for (; cclass <= classend; cclass++)
Char((char)cclass);
fInputScanPointer++;
}
} else
Char(*fInputScanPointer++);
} }
Char('\0');
if (*fInputScanPointer != ']') {
SetError(REGEXP_UNMATCHED_BRACKET);
return NULL;
}
fInputScanPointer++;
*flagp |= kHasWidth | kSimple;
break; break;
}
case '(': case '(':
ret = Reg(1, &flags); ret = Reg(1, &flags);
if (ret == NULL) if (ret == NULL)
return NULL; return NULL;
*flagp |= flags & (kHasWidth | kSPStart); *flagp |= flags & (kHasWidth | kSPStart);
break; break;
case '\0': case '\0':
case '|': case '|':
case ')': case ')':
SetError(REGEXP_INTERNAL_ERROR); SetError(REGEXP_INTERNAL_ERROR);
return NULL; // Supposed to be caught earlier. return NULL;
// supposed to be caught earlier
case '?': case '?':
case '+': case '+':
case '*': case '*':
SetError(REGEXP_QUESTION_PLUS_STAR_FOLLOWS_NOTHING); SetError(REGEXP_QUESTION_PLUS_STAR_FOLLOWS_NOTHING);
return NULL; return NULL;
case '\\': case '\\':
if (*fInputScanPointer == '\0') { if (*fInputScanPointer == '\0') {
SetError(REGEXP_TRAILING_BACKSLASH); SetError(REGEXP_TRAILING_BACKSLASH);
@@ -682,6 +734,7 @@ RegExp::Atom(int32* flagp)
Char('\0'); Char('\0');
*flagp |= kHasWidth|kSimple; *flagp |= kHasWidth|kSimple;
break; break;
default: default:
{ {
int32 len; int32 len;
@@ -695,8 +748,10 @@ RegExp::Atom(int32* flagp)
} }
ender = *(fInputScanPointer + len); ender = *(fInputScanPointer + len);
if (len > 1 && IsMult(ender)) if (len > 1 && IsMult(ender)) {
len--; // Back off clear of ?+* operand. // Back off clear of ?+* operand.
len--;
}
*flagp |= kHasWidth; *flagp |= kHasWidth;
if (len == 1) if (len == 1)
@@ -720,7 +775,9 @@ RegExp::Atom(int32* flagp)
// //
// - Node - emit a node // - Node - emit a node
// //
char* // Location. // Returns location.
//
char*
RegExp::Node(char op) RegExp::Node(char op)
{ {
char* ret; char* ret;
@@ -734,7 +791,8 @@ RegExp::Node(char op)
ptr = ret; ptr = ret;
*ptr++ = op; *ptr++ = op;
*ptr++ = '\0'; // Null "next" pointer. *ptr++ = '\0';
// Null "next" pointer.
*ptr++ = '\0'; *ptr++ = '\0';
fCodeEmitPointer = ptr; fCodeEmitPointer = ptr;
@@ -778,7 +836,8 @@ RegExp::Insert(char op, char* opnd)
while (src > opnd) while (src > opnd)
*--dst = *--src; *--dst = *--src;
place = opnd; // Op node, where operand used to be. place = opnd;
// Op node, where operand used to be.
*place++ = op; *place++ = op;
*place++ = '\0'; *place++ = '\0';
*place++ = '\0'; *place++ = '\0';
@@ -826,6 +885,7 @@ RegExp::OpTail(char* p, char* val)
// "Operandless" and "op != kRegExpBranch" are synonymous in practice. // "Operandless" and "op != kRegExpBranch" are synonymous in practice.
if (p == NULL || p == &fDummy || *p != kRegExpBranch) if (p == NULL || p == &fDummy || *p != kRegExpBranch)
return; return;
Tail(Operand(p), val); Tail(Operand(p), val);
} }
@@ -842,54 +902,59 @@ RegExp::RunMatcher(regexp* prog, const char* string) const
{ {
const char* s; const char* s;
// Be paranoid... // be paranoid...
if (prog == NULL || string == NULL) { if (prog == NULL || string == NULL) {
SetError(B_BAD_VALUE); SetError(B_BAD_VALUE);
return 0; return 0;
} }
// Check validity of program. // check validity of program
if (UCharAt(prog->program) != kRegExpMagic) { if (UCharAt(prog->program) != kRegExpMagic) {
SetError(REGEXP_CORRUPTED_PROGRAM); SetError(REGEXP_CORRUPTED_PROGRAM);
return 0; return 0;
} }
// If there is a "must appear" string, look for it. // if there is a "must appear" string, look for it
if (prog->regmust != NULL) { if (prog->regmust != NULL) {
s = string; s = string;
while ((s = strchr(s, prog->regmust[0])) != NULL) { while ((s = strchr(s, prog->regmust[0])) != NULL) {
if (strncmp(s, prog->regmust, (size_t)prog->regmlen) == 0) if (strncmp(s, prog->regmust, (size_t)prog->regmlen) == 0) {
break; // Found it. // found it
break;
}
s++; s++;
} }
if (s == NULL) // Not present. if (s == NULL) {
// not present
return 0; return 0;
}
} }
// Mark beginning of line for ^ . // mark beginning of line for ^
fRegBol = string; fRegBol = string;
// Simplest case: anchored match need be tried only once. // simplest case: anchored match need be tried only once
if (prog->reganch) if (prog->reganch)
return Try(prog, (char*)string); return Try(prog, (char*)string);
// Messy cases: unanchored match. // messy cases: unanchored match
s = string; s = string;
if (prog->regstart != '\0') if (prog->regstart != '\0') {
// We know what char it must start with. // we know what char it must start with
while ((s = strchr(s, prog->regstart)) != NULL) { while ((s = strchr(s, prog->regstart)) != NULL) {
if (Try(prog, (char*)s)) if (Try(prog, (char*)s))
return 1; return 1;
s++; s++;
} }
else } else {
// We don't -- general case. // we don't -- general case.
do { do {
if (Try(prog, (char*)s)) if (Try(prog, (char*)s))
return 1; return 1;
} while (*s++ != '\0'); } while (*s++ != '\0');
}
// Failure. // failure
return 0; return 0;
} }
@@ -897,7 +962,9 @@ RegExp::RunMatcher(regexp* prog, const char* string) const
// //
// - Try - try match at specific point // - Try - try match at specific point
// //
int32 // 0 failure, 1 success // Returns 0 on failure, 1 on success.
//
int32
RegExp::Try(regexp* prog, const char* string) const RegExp::Try(regexp* prog, const char* string) const
{ {
int32 i; int32 i;
@@ -932,8 +999,10 @@ RegExp::Try(regexp* prog, const char* string) const
// recursion, in particular by going through "ordinary" nodes (that don't // recursion, in particular by going through "ordinary" nodes (that don't
// need to know whether the rest of the match failed) by a loop instead of // need to know whether the rest of the match failed) by a loop instead of
// by recursion. // by recursion.
/// //
int32 // 0 failure, 1 success // Returns 0 on failure, 1 on success.
//
int32
RegExp::Match(const char* prog) const RegExp::Match(const char* prog) const
{ {
const char* scan; // Current node. const char* scan; // Current node.
@@ -956,47 +1025,57 @@ RegExp::Match(const char* prog) const
if (fStringInputPointer != fRegBol) if (fStringInputPointer != fRegBol)
return 0; return 0;
break; break;
case kRegExpEol: case kRegExpEol:
if (*fStringInputPointer != '\0') if (*fStringInputPointer != '\0')
return 0; return 0;
break; break;
case kRegExpAny: case kRegExpAny:
if (*fStringInputPointer == '\0') if (*fStringInputPointer == '\0')
return 0; return 0;
fStringInputPointer++; fStringInputPointer++;
break; break;
case kRegExpExactly: case kRegExpExactly:
{ {
const char* opnd = Operand(scan); const char* opnd = Operand(scan);
// Inline the first character, for speed. // Inline the first character, for speed.
if (*opnd != *fStringInputPointer) if (*opnd != *fStringInputPointer)
return 0; return 0;
uint32 len = strlen(opnd); uint32 len = strlen(opnd);
if (len > 1 if (len > 1
&& strncmp(opnd, fStringInputPointer, len) != 0) { && strncmp(opnd, fStringInputPointer, len) != 0) {
return 0; return 0;
}
fStringInputPointer += len;
} }
break;
fStringInputPointer += len;
}
break;
case kRegExpAnyOf: case kRegExpAnyOf:
if (*fStringInputPointer == '\0' if (*fStringInputPointer == '\0'
|| strchr(Operand(scan), *fStringInputPointer) == NULL) || strchr(Operand(scan), *fStringInputPointer) == NULL) {
return 0; return 0;
}
fStringInputPointer++; fStringInputPointer++;
break; break;
case kRegExpAnyBut: case kRegExpAnyBut:
if (*fStringInputPointer == '\0' if (*fStringInputPointer == '\0'
|| strchr(Operand(scan), *fStringInputPointer) != NULL) || strchr(Operand(scan), *fStringInputPointer) != NULL) {
return 0; return 0;
}
fStringInputPointer++; fStringInputPointer++;
break; break;
case kRegExpNothing: case kRegExpNothing:
break; break;
case kRegExpBack: case kRegExpBack:
break; break;
case kRegExpOpen + 1: case kRegExpOpen + 1:
case kRegExpOpen + 2: case kRegExpOpen + 2:
case kRegExpOpen + 3: case kRegExpOpen + 3:
@@ -1006,26 +1085,27 @@ RegExp::Match(const char* prog) const
case kRegExpOpen + 7: case kRegExpOpen + 7:
case kRegExpOpen + 8: case kRegExpOpen + 8:
case kRegExpOpen + 9: case kRegExpOpen + 9:
{ {
int32 no; int32 no;
const char* save; const char* save;
no = *scan - kRegExpOpen; no = *scan - kRegExpOpen;
save = fStringInputPointer; save = fStringInputPointer;
if (Match(next)) {
//
// Don't set startp if some later
// invocation of the same parentheses
// already has.
//
if (fStartPArrayPointer[no] == NULL)
fStartPArrayPointer[no] = save;
return 1;
} else
return 0;
}
break;
if (Match(next)) {
//
// Don't set startp if some later
// invocation of the same parentheses
// already has.
//
if (fStartPArrayPointer[no] == NULL)
fStartPArrayPointer[no] = save;
return 1;
} else
return 0;
}
break;
case kRegExpClose + 1: case kRegExpClose + 1:
case kRegExpClose + 2: case kRegExpClose + 2:
case kRegExpClose + 3: case kRegExpClose + 3:
@@ -1035,45 +1115,49 @@ RegExp::Match(const char* prog) const
case kRegExpClose + 7: case kRegExpClose + 7:
case kRegExpClose + 8: case kRegExpClose + 8:
case kRegExpClose + 9: case kRegExpClose + 9:
{ {
int32 no; int32 no;
const char* save; const char* save;
no = *scan - kRegExpClose; no = *scan - kRegExpClose;
save = fStringInputPointer; save = fStringInputPointer;
if (Match(next)) {
//
// Don't set endp if some later
// invocation of the same parentheses
// already has.
//
if (fEndPArrayPointer[no] == NULL)
fEndPArrayPointer[no] = save;
return 1;
} else
return 0;
}
break;
if (Match(next)) {
//
// Don't set endp if some later
// invocation of the same parentheses
// already has.
//
if (fEndPArrayPointer[no] == NULL)
fEndPArrayPointer[no] = save;
return 1;
} else
return 0;
}
break;
case kRegExpBranch: case kRegExpBranch:
{ {
const char* save; const char* save;
if (*next != kRegExpBranch) // No choice. if (*next != kRegExpBranch) {
next = Operand(scan); // Avoid recursion. // no choice
else { next = Operand(scan);
do { // avoid recursion
save = fStringInputPointer; } else {
if (Match(Operand(scan))) do {
return 1; save = fStringInputPointer;
fStringInputPointer = save; if (Match(Operand(scan)))
scan = Next(scan); return 1;
} while (scan != NULL && *scan == kRegExpBranch); fStringInputPointer = save;
return 0; scan = Next(scan);
// NOTREACHED/ } while (scan != NULL && *scan == kRegExpBranch);
} return 0;
// NOTREACHED
} }
break; }
break;
case kRegExpStar: case kRegExpStar:
case kRegExpPlus: case kRegExpPlus:
{ {
@@ -1083,7 +1167,7 @@ RegExp::Match(const char* prog) const
int32 min; int32 min;
// //
//Lookahead to avoid useless match attempts // Lookahead to avoid useless match attempts
// when we know what character comes next. // when we know what character comes next.
// //
nextch = '\0'; nextch = '\0';
@@ -1093,19 +1177,22 @@ RegExp::Match(const char* prog) const
save = fStringInputPointer; save = fStringInputPointer;
no = Repeat(Operand(scan)); no = Repeat(Operand(scan));
while (no >= min) { while (no >= min) {
// If it could work, try it. // if it could work, try it
if (nextch == '\0' || *fStringInputPointer == nextch) if (nextch == '\0' || *fStringInputPointer == nextch) {
if (Match(next)) if (Match(next))
return 1; return 1;
// Couldn't or didn't -- back up. }
// couldn't or didn't, back up
no--; no--;
fStringInputPointer = save + no; fStringInputPointer = save + no;
} }
return 0; return 0;
} }
break; break;
case kRegExpEnd: case kRegExpEnd:
return 1; // Success! return 1;
// Success!
default: default:
SetError(REGEXP_MEMORY_CORRUPTION); SetError(REGEXP_MEMORY_CORRUPTION);
@@ -1120,6 +1207,7 @@ RegExp::Match(const char* prog) const
// the terminating point. // the terminating point.
// //
SetError(REGEXP_CORRUPTED_POINTERS); SetError(REGEXP_CORRUPTED_POINTERS);
return 0; return 0;
} }
@@ -1163,9 +1251,11 @@ RegExp::Repeat(const char* p) const
} }
break; break;
default: // Oh dear. Called inappropriately. default:
// oh dear, called inappropriately
SetError(REGEXP_INTERNAL_ERROR); SetError(REGEXP_INTERNAL_ERROR);
count = 0; // Best compromise. count = 0;
// best compromise
break; break;
} }
fStringInputPointer = scan; fStringInputPointer = scan;
@@ -1253,22 +1343,27 @@ void
RegExp::Dump() RegExp::Dump()
{ {
const char* s; const char* s;
char op = kRegExpExactly; // Arbitrary non-kRegExpEnd op. char op = kRegExpExactly;
// Arbitrary non-kRegExpEnd op.
const char* next; const char* next;
s = fRegExp->program + 1; s = fRegExp->program + 1;
while (op != kRegExpEnd) { // While that wasn't kRegExpEnd last time... while (op != kRegExpEnd) {
// While that wasn't kRegExpEnd last time...
op = *s; op = *s;
printf("%2ld%s", s - fRegExp->program, Prop(s)); // Where, what. printf("%2ld%s", s - fRegExp->program, Prop(s));
// Where, what.
next = Next(s); next = Next(s);
if (next == NULL) // Next ptr. if (next == NULL) {
// next ptr
printf("(0)"); printf("(0)");
else } else
printf("(%ld)", (s - fRegExp->program) + (next - s)); printf("(%ld)", (s - fRegExp->program) + (next - s));
s += 3; s += 3;
if (op == kRegExpAnyOf || op == kRegExpAnyBut if (op == kRegExpAnyOf || op == kRegExpAnyBut
|| op == kRegExpExactly) { || op == kRegExpExactly) {
// Literal string, where present. // literal string, where present
while (*s != '\0') { while (*s != '\0') {
putchar(*s); putchar(*s);
s++; s++;
@@ -1278,13 +1373,16 @@ RegExp::Dump()
putchar('\n'); putchar('\n');
} }
// Header fields of interest. // header fields of interest
if (fRegExp->regstart != '\0') if (fRegExp->regstart != '\0')
printf("start `%c' ", fRegExp->regstart); printf("start `%c' ", fRegExp->regstart);
if (fRegExp->reganch) if (fRegExp->reganch)
printf("anchored "); printf("anchored ");
if (fRegExp->regmust != NULL) if (fRegExp->regmust != NULL)
printf("must have \"%s\"", fRegExp->regmust); printf("must have \"%s\"", fRegExp->regmust);
printf("\n"); printf("\n");
} }
@@ -1298,39 +1396,49 @@ RegExp::Prop(const char* op) const
const char* p = NULL; const char* p = NULL;
static char buf[50]; static char buf[50];
(void) strcpy(buf, ":"); strcpy(buf, ":");
switch (*op) { switch (*op) {
case kRegExpBol: case kRegExpBol:
p = "kRegExpBol"; p = "kRegExpBol";
break; break;
case kRegExpEol: case kRegExpEol:
p = "kRegExpEol"; p = "kRegExpEol";
break; break;
case kRegExpAny: case kRegExpAny:
p = "kRegExpAny"; p = "kRegExpAny";
break; break;
case kRegExpAnyOf: case kRegExpAnyOf:
p = "kRegExpAnyOf"; p = "kRegExpAnyOf";
break; break;
case kRegExpAnyBut: case kRegExpAnyBut:
p = "kRegExpAnyBut"; p = "kRegExpAnyBut";
break; break;
case kRegExpBranch: case kRegExpBranch:
p = "kRegExpBranch"; p = "kRegExpBranch";
break; break;
case kRegExpExactly: case kRegExpExactly:
p = "kRegExpExactly"; p = "kRegExpExactly";
break; break;
case kRegExpNothing: case kRegExpNothing:
p = "kRegExpNothing"; p = "kRegExpNothing";
break; break;
case kRegExpBack: case kRegExpBack:
p = "kRegExpBack"; p = "kRegExpBack";
break; break;
case kRegExpEnd: case kRegExpEnd:
p = "kRegExpEnd"; p = "kRegExpEnd";
break; break;
case kRegExpOpen + 1: case kRegExpOpen + 1:
case kRegExpOpen + 2: case kRegExpOpen + 2:
case kRegExpOpen + 3: case kRegExpOpen + 3:
@@ -1343,6 +1451,7 @@ RegExp::Prop(const char* op) const
sprintf(buf + strlen(buf), "kRegExpOpen%d", *op - kRegExpOpen); sprintf(buf + strlen(buf), "kRegExpOpen%d", *op - kRegExpOpen);
p = NULL; p = NULL;
break; break;
case kRegExpClose + 1: case kRegExpClose + 1:
case kRegExpClose + 2: case kRegExpClose + 2:
case kRegExpClose + 3: case kRegExpClose + 3:
@@ -1355,12 +1464,15 @@ RegExp::Prop(const char* op) const
sprintf(buf + strlen(buf), "kRegExpClose%d", *op - kRegExpClose); sprintf(buf + strlen(buf), "kRegExpClose%d", *op - kRegExpClose);
p = NULL; p = NULL;
break; break;
case kRegExpStar: case kRegExpStar:
p = "kRegExpStar"; p = "kRegExpStar";
break; break;
case kRegExpPlus: case kRegExpPlus:
p = "kRegExpPlus"; p = "kRegExpPlus";
break; break;
default: default:
RegExpError("corrupted opcode"); RegExpError("corrupted opcode");
break; break;
@@ -1379,4 +1491,4 @@ RegExp::RegExpError(const char*) const
// does nothing now, perhaps it should printf? // does nothing now, perhaps it should printf?
} }
#endif #endif // DEBUG
+3
View File
@@ -89,8 +89,10 @@ enum {
REGEXP_CORRUPTED_OPCODE REGEXP_CORRUPTED_OPCODE
}; };
const int32 kSubExpressionMax = 10; const int32 kSubExpressionMax = 10;
struct regexp { struct regexp {
const char* startp[kSubExpressionMax]; const char* startp[kSubExpressionMax];
const char* endp[kSubExpressionMax]; const char* endp[kSubExpressionMax];
@@ -183,4 +185,5 @@ private:
using namespace BPrivate; using namespace BPrivate;
#endif // _REG_EXP_H #endif // _REG_EXP_H