Tracker: style fixes to RegExp (minor)
This commit is contained in:
+291
-179
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user