mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-28 13:21:28 +00:00
Fixed minor bugs.
This commit is contained in:
parent
d288192dc3
commit
4308f6eb7d
@ -50,7 +50,7 @@ typedef unsigned char uint8;
|
||||
|
||||
|
||||
typedef enum REOp {
|
||||
REOP_EMPTY, /* an empty alternative */
|
||||
REOP_EMPTY, /* an empty alternative */
|
||||
|
||||
REOP_ALT, /* a tree of alternates */
|
||||
REOP_NEXTALT, /* continuation into thereof */
|
||||
@ -111,10 +111,10 @@ typedef struct CharSet {
|
||||
} CharSet;
|
||||
|
||||
typedef struct REContinuationData {
|
||||
REOp op; /* not necessarily the same as node->kind */
|
||||
REOp op; /* not necessarily the same as node->kind */
|
||||
RENode *node;
|
||||
|
||||
REint32 min; /* for quantifiers, record the current limits */
|
||||
REint32 min; /* for quantifiers, record the current limits */
|
||||
REint32 max;
|
||||
|
||||
REuint32 index; /* for assertions, record the match start */
|
||||
@ -229,6 +229,7 @@ REbool parseDisjunction(REParseState *parseState);
|
||||
REbool parseAlternative(REParseState *parseState);
|
||||
REbool parseTerm(REParseState *parseState);
|
||||
|
||||
|
||||
static REbool isASCIIHexDigit(REchar c, REuint32 *digit)
|
||||
{
|
||||
REuint32 cv = c;
|
||||
@ -259,9 +260,9 @@ static RENode *newRENode(REParseState *parseState, REOp kind)
|
||||
return NULL;
|
||||
}
|
||||
if ((parseState->flags & IGNORECASE) && (kind == REOP_FLAT1))
|
||||
result->kind = REOP_FLAT1i;
|
||||
result->kind = REOP_FLAT1i;
|
||||
else
|
||||
result->kind = kind;
|
||||
result->kind = kind;
|
||||
result->next = NULL;
|
||||
result->child = NULL;
|
||||
return result;
|
||||
@ -321,46 +322,46 @@ REbool parseAlternative(REParseState *parseState)
|
||||
free(parseState->result);
|
||||
}
|
||||
else {
|
||||
if ((headTerm->kind == REOP_FLAT1i)
|
||||
&& headTerm->child
|
||||
&& (parseState->result->kind == REOP_FLAT1i)
|
||||
&& (parseState->result->child
|
||||
== (REchar *)(headTerm->child) + 1) ) {
|
||||
headTerm->kind = REOP_FLATNi;
|
||||
headTerm->data.length = 2;
|
||||
free(parseState->result);
|
||||
}
|
||||
else {
|
||||
headTerm->next = parseState->result;
|
||||
tailTerm = parseState->result;
|
||||
}
|
||||
}
|
||||
if ((headTerm->kind == REOP_FLAT1i)
|
||||
&& headTerm->child
|
||||
&& (parseState->result->kind == REOP_FLAT1i)
|
||||
&& (parseState->result->child
|
||||
== (REchar *)(headTerm->child) + 1) ) {
|
||||
headTerm->kind = REOP_FLATNi;
|
||||
headTerm->data.length = 2;
|
||||
free(parseState->result);
|
||||
}
|
||||
else {
|
||||
headTerm->next = parseState->result;
|
||||
tailTerm = parseState->result;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ((headTerm->kind == REOP_FLATN)
|
||||
&& headTerm->child
|
||||
if ((tailTerm->kind == REOP_FLATN)
|
||||
&& tailTerm->child
|
||||
&& (parseState->result->kind == REOP_FLAT1)
|
||||
&& ((REchar *)(parseState->result->child)
|
||||
== (REchar *)(headTerm->child)
|
||||
+ headTerm->data.length) ) {
|
||||
headTerm->data.length++;
|
||||
== (REchar *)(tailTerm->child)
|
||||
+ tailTerm->data.length) ) {
|
||||
tailTerm->data.length++;
|
||||
free(parseState->result);
|
||||
}
|
||||
else {
|
||||
if ((headTerm->kind == REOP_FLATNi)
|
||||
&& headTerm->child
|
||||
&& (parseState->result->kind == REOP_FLAT1i)
|
||||
&& ((REchar *)(parseState->result->child)
|
||||
== (REchar *)(headTerm->child)
|
||||
+ headTerm->data.length) ) {
|
||||
headTerm->data.length++;
|
||||
free(parseState->result);
|
||||
}
|
||||
else {
|
||||
tailTerm->next = parseState->result;
|
||||
tailTerm = tailTerm->next;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ((tailTerm->kind == REOP_FLATNi)
|
||||
&& tailTerm->child
|
||||
&& (parseState->result->kind == REOP_FLAT1i)
|
||||
&& ((REchar *)(parseState->result->child)
|
||||
== (REchar *)(tailTerm->child)
|
||||
+ tailTerm->data.length) ) {
|
||||
tailTerm->data.length++;
|
||||
free(parseState->result);
|
||||
}
|
||||
else {
|
||||
tailTerm->next = parseState->result;
|
||||
tailTerm = tailTerm->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -377,142 +378,142 @@ static REint32 getDecimalValue(REchar c, REParseState *parseState)
|
||||
return value;
|
||||
}
|
||||
|
||||
/* calculate the total size of the bitmap required for a class expression */
|
||||
static REbool calculateBitmapSize(REParseState *pState, RENode *target)
|
||||
{
|
||||
REchar rangeStart;
|
||||
const REchar *src = (const REchar *)(target->child);
|
||||
const REchar *end = target->data.chclass.end;
|
||||
|
||||
REchar c;
|
||||
REuint32 nDigits;
|
||||
REuint32 i;
|
||||
REuint32 max = 0;
|
||||
bool inRange = false;
|
||||
|
||||
CharSet *charSet = (CharSet *)malloc(sizeof(CharSet));
|
||||
if (!charSet) return false;
|
||||
target->data.chclass.charSet = charSet;
|
||||
charSet->length = 0;
|
||||
charSet->bits = NULL;
|
||||
|
||||
if (src == end)
|
||||
return true;
|
||||
|
||||
if (*src == '^')
|
||||
++src;
|
||||
|
||||
while (src != end) {
|
||||
REuint32 localMax = 0;
|
||||
switch (*src) {
|
||||
case '\\':
|
||||
++src;
|
||||
c = *src++;
|
||||
switch (c) {
|
||||
case 'b':
|
||||
localMax = 0x8;
|
||||
break;
|
||||
case 'f':
|
||||
localMax = 0xC;
|
||||
break;
|
||||
case 'n':
|
||||
localMax = 0xA;
|
||||
break;
|
||||
case 'r':
|
||||
localMax = 0xD;
|
||||
break;
|
||||
case 't':
|
||||
localMax = 0x9;
|
||||
break;
|
||||
case 'v':
|
||||
localMax = 0xB;
|
||||
break;
|
||||
case 'c':
|
||||
if (((src + 1) < end) && RE_ISLETTER(src[1]))
|
||||
localMax = (REchar)(*src++ & 0x1F);
|
||||
else
|
||||
localMax = '\\';
|
||||
break;
|
||||
case 'x':
|
||||
nDigits = 2;
|
||||
goto lexHex;
|
||||
case 'u':
|
||||
nDigits = 4;
|
||||
lexHex:
|
||||
{
|
||||
REuint32 n = 0;
|
||||
for (i = 0; (i < nDigits) && (src < end); i++) {
|
||||
REuint32 digit;
|
||||
c = *src++;
|
||||
if (!isASCIIHexDigit(c, &digit)) {
|
||||
/* back off to accepting the original
|
||||
*'\' as a literal
|
||||
*/
|
||||
src -= (i + 1);
|
||||
n = '\\';
|
||||
break;
|
||||
}
|
||||
n = (n << 4) | digit;
|
||||
}
|
||||
localMax = n;
|
||||
}
|
||||
break;
|
||||
case 'd':
|
||||
if (inRange) {
|
||||
reportRegExpError(&pState->error, WRONG_RANGE);
|
||||
return false;
|
||||
}
|
||||
localMax = '9';
|
||||
break;
|
||||
case 'D':
|
||||
case 's':
|
||||
case 'S':
|
||||
case 'w':
|
||||
case 'W':
|
||||
if (inRange) {
|
||||
reportRegExpError(&pState->error, WRONG_RANGE);
|
||||
return false;
|
||||
}
|
||||
charSet->length = 65536;
|
||||
return true;
|
||||
default:
|
||||
localMax = c;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
localMax = *src++;
|
||||
break;
|
||||
}
|
||||
if (inRange) {
|
||||
if (rangeStart > localMax) {
|
||||
reportRegExpError(&pState->error, WRONG_RANGE);
|
||||
return false;
|
||||
}
|
||||
inRange = false;
|
||||
}
|
||||
else {
|
||||
if (src < (end - 1)) {
|
||||
if (*src == '-') {
|
||||
++src;
|
||||
inRange = true;
|
||||
rangeStart = localMax;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pState->flags & IGNORECASE) {
|
||||
c = canonicalize(localMax);
|
||||
if (c > localMax)
|
||||
localMax = c;
|
||||
}
|
||||
if (localMax > max)
|
||||
max = localMax;
|
||||
}
|
||||
charSet->length = max + 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* calculate the total size of the bitmap required for a class expression */
|
||||
static REbool calculateBitmapSize(REParseState *pState, RENode *target)
|
||||
{
|
||||
REchar rangeStart;
|
||||
const REchar *src = (const REchar *)(target->child);
|
||||
const REchar *end = target->data.chclass.end;
|
||||
|
||||
REchar c;
|
||||
REuint32 nDigits;
|
||||
REuint32 i;
|
||||
REuint32 max = 0;
|
||||
bool inRange = false;
|
||||
|
||||
CharSet *charSet = (CharSet *)malloc(sizeof(CharSet));
|
||||
if (!charSet) return false;
|
||||
target->data.chclass.charSet = charSet;
|
||||
charSet->length = 0;
|
||||
charSet->bits = NULL;
|
||||
|
||||
if (src == end)
|
||||
return true;
|
||||
|
||||
if (*src == '^')
|
||||
++src;
|
||||
|
||||
while (src != end) {
|
||||
REuint32 localMax = 0;
|
||||
switch (*src) {
|
||||
case '\\':
|
||||
++src;
|
||||
c = *src++;
|
||||
switch (c) {
|
||||
case 'b':
|
||||
localMax = 0x8;
|
||||
break;
|
||||
case 'f':
|
||||
localMax = 0xC;
|
||||
break;
|
||||
case 'n':
|
||||
localMax = 0xA;
|
||||
break;
|
||||
case 'r':
|
||||
localMax = 0xD;
|
||||
break;
|
||||
case 't':
|
||||
localMax = 0x9;
|
||||
break;
|
||||
case 'v':
|
||||
localMax = 0xB;
|
||||
break;
|
||||
case 'c':
|
||||
if (((src + 1) < end) && RE_ISLETTER(src[1]))
|
||||
localMax = (REchar)(*src++ & 0x1F);
|
||||
else
|
||||
localMax = '\\';
|
||||
break;
|
||||
case 'x':
|
||||
nDigits = 2;
|
||||
goto lexHex;
|
||||
case 'u':
|
||||
nDigits = 4;
|
||||
lexHex:
|
||||
{
|
||||
REuint32 n = 0;
|
||||
for (i = 0; (i < nDigits) && (src < end); i++) {
|
||||
REuint32 digit;
|
||||
c = *src++;
|
||||
if (!isASCIIHexDigit(c, &digit)) {
|
||||
/* back off to accepting the original
|
||||
*'\' as a literal
|
||||
*/
|
||||
src -= (i + 1);
|
||||
n = '\\';
|
||||
break;
|
||||
}
|
||||
n = (n << 4) | digit;
|
||||
}
|
||||
localMax = n;
|
||||
}
|
||||
break;
|
||||
case 'd':
|
||||
if (inRange) {
|
||||
reportRegExpError(&pState->error, WRONG_RANGE);
|
||||
return false;
|
||||
}
|
||||
localMax = '9';
|
||||
break;
|
||||
case 'D':
|
||||
case 's':
|
||||
case 'S':
|
||||
case 'w':
|
||||
case 'W':
|
||||
if (inRange) {
|
||||
reportRegExpError(&pState->error, WRONG_RANGE);
|
||||
return false;
|
||||
}
|
||||
charSet->length = 65536;
|
||||
return true;
|
||||
default:
|
||||
localMax = c;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
localMax = *src++;
|
||||
break;
|
||||
}
|
||||
if (inRange) {
|
||||
if (rangeStart > localMax) {
|
||||
reportRegExpError(&pState->error, WRONG_RANGE);
|
||||
return false;
|
||||
}
|
||||
inRange = false;
|
||||
}
|
||||
else {
|
||||
if (src < (end - 1)) {
|
||||
if (*src == '-') {
|
||||
++src;
|
||||
inRange = true;
|
||||
rangeStart = localMax;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pState->flags & IGNORECASE) {
|
||||
c = canonicalize(localMax);
|
||||
if (c > localMax)
|
||||
localMax = c;
|
||||
}
|
||||
if (localMax > max)
|
||||
max = localMax;
|
||||
}
|
||||
charSet->length = max + 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
REbool parseTerm(REParseState *parseState)
|
||||
{
|
||||
REchar c = *parseState->src++;
|
||||
@ -757,8 +758,8 @@ lexHex:
|
||||
}
|
||||
++parseState->src;
|
||||
}
|
||||
if (!calculateBitmapSize(parseState, parseState->result))
|
||||
return false;
|
||||
if (!calculateBitmapSize(parseState, parseState->result))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case '.':
|
||||
@ -817,8 +818,8 @@ lexHex:
|
||||
max = getDecimalValue(c, parseState);
|
||||
c = *parseState->src;
|
||||
}
|
||||
}
|
||||
else
|
||||
}
|
||||
else
|
||||
max = min;
|
||||
parseState->result->data.quantifier.min = min;
|
||||
parseState->result->data.quantifier.max = max;
|
||||
@ -1118,204 +1119,203 @@ static REState *flatNIMatcher(REGlobalData *globalData, REState *x, REchar *matc
|
||||
return x;
|
||||
}
|
||||
|
||||
/* Add a single character to the CharSet */
|
||||
static void addCharacterToCharSet(CharSet *cs, REchar c)
|
||||
{
|
||||
REuint32 byteIndex = (REuint32)(c / 8);
|
||||
ASSERT(c < cs->length);
|
||||
cs->bits[byteIndex] |= 1 << (c & 0x7);
|
||||
}
|
||||
|
||||
/* Add a character range, c1 to c2 (inclusive) to the CharSet */
|
||||
static void addCharacterRangeToCharSet(CharSet *cs, REchar c1, REchar c2)
|
||||
{
|
||||
REuint32 i;
|
||||
|
||||
REuint32 byteIndex1 = (REuint32)(c1 / 8);
|
||||
REuint32 byteIndex2 = (REuint32)(c2 / 8);
|
||||
|
||||
ASSERT((c2 <= cs->length) && (c1 <= c2));
|
||||
|
||||
c1 &= 0x7;
|
||||
c2 &= 0x7;
|
||||
|
||||
if (byteIndex1 == byteIndex2) {
|
||||
cs->bits[byteIndex1] |= ((uint8)(0xFF) >> (7 - (c2 - c1))) << c1;
|
||||
}
|
||||
else {
|
||||
cs->bits[byteIndex1] |= 0xFF << c1;
|
||||
for (i = byteIndex1 + 1; i < byteIndex2; i++)
|
||||
cs->bits[i] = 0xFF;
|
||||
cs->bits[byteIndex2] |= (uint8)(0xFF) >> (7 - c2);
|
||||
}
|
||||
}
|
||||
/* Add a single character to the CharSet */
|
||||
static void addCharacterToCharSet(CharSet *cs, REchar c)
|
||||
{
|
||||
REuint32 byteIndex = (REuint32)(c / 8);
|
||||
ASSERT(c < cs->length);
|
||||
cs->bits[byteIndex] |= 1 << (c & 0x7);
|
||||
}
|
||||
|
||||
/* Add a character range, c1 to c2 (inclusive) to the CharSet */
|
||||
static void addCharacterRangeToCharSet(CharSet *cs, REchar c1, REchar c2)
|
||||
{
|
||||
REuint32 i;
|
||||
|
||||
REuint32 byteIndex1 = (REuint32)(c1 / 8);
|
||||
REuint32 byteIndex2 = (REuint32)(c2 / 8);
|
||||
|
||||
ASSERT((c2 <= cs->length) && (c1 <= c2));
|
||||
|
||||
c1 &= 0x7;
|
||||
c2 &= 0x7;
|
||||
|
||||
if (byteIndex1 == byteIndex2) {
|
||||
cs->bits[byteIndex1] |= ((uint8)(0xFF) >> (7 - (c2 - c1))) << c1;
|
||||
}
|
||||
else {
|
||||
cs->bits[byteIndex1] |= 0xFF << c1;
|
||||
for (i = byteIndex1 + 1; i < byteIndex2; i++)
|
||||
cs->bits[i] = 0xFF;
|
||||
cs->bits[byteIndex2] |= (uint8)(0xFF) >> (7 - c2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Compile the source of the class into a CharSet */
|
||||
static REbool processCharSet(REGlobalData *globalData, RENode *target)
|
||||
{
|
||||
REchar rangeStart, thisCh;
|
||||
const REchar *src = (const REchar *)(target->child);
|
||||
const REchar *end = target->data.chclass.end;
|
||||
|
||||
REchar c;
|
||||
REint32 nDigits;
|
||||
REint32 i;
|
||||
REuint32 length;
|
||||
CharSet *charSet;
|
||||
bool inRange = false;
|
||||
|
||||
charSet = target->data.chclass.charSet;
|
||||
length = (charSet->length / 8) + 1;
|
||||
charSet->bits = (uint8 *)malloc(length);
|
||||
if (!charSet->bits)
|
||||
return false;
|
||||
memset(charSet->bits, 0, length);
|
||||
|
||||
target->data.chclass.sense = true;
|
||||
|
||||
if (src == end)
|
||||
return true;
|
||||
|
||||
if (*src == '^') {
|
||||
target->data.chclass.sense = false;
|
||||
++src;
|
||||
}
|
||||
while (src != end) {
|
||||
switch (*src) {
|
||||
case '\\':
|
||||
++src;
|
||||
c = *src++;
|
||||
switch (c) {
|
||||
case 'b':
|
||||
thisCh = 0x8;
|
||||
break;
|
||||
case 'f':
|
||||
thisCh = 0xC;
|
||||
addCharacterToCharSet(charSet, 0xC);
|
||||
break;
|
||||
case 'n':
|
||||
thisCh = 0xA;
|
||||
break;
|
||||
case 'r':
|
||||
thisCh = 0xD;
|
||||
break;
|
||||
case 't':
|
||||
thisCh = 0x9;
|
||||
break;
|
||||
case 'v':
|
||||
thisCh = 0xB;
|
||||
break;
|
||||
case 'c':
|
||||
if (((src + 1) < end) && RE_ISLETTER(src[1]))
|
||||
thisCh = (REchar)(*src++ & 0x1F);
|
||||
else {
|
||||
--src;
|
||||
thisCh = '\\';
|
||||
}
|
||||
break;
|
||||
case 'x':
|
||||
nDigits = 2;
|
||||
goto lexHex;
|
||||
case 'u':
|
||||
nDigits = 4;
|
||||
lexHex:
|
||||
{
|
||||
REuint32 n = 0;
|
||||
for (i = 0; (i < nDigits) && (src < end); i++) {
|
||||
REuint32 digit;
|
||||
c = *src++;
|
||||
if (!isASCIIHexDigit(c, &digit)) {
|
||||
/* back off to accepting the original '\'
|
||||
* as a literal
|
||||
*/
|
||||
src -= (i + 1);
|
||||
n = '\\';
|
||||
break;
|
||||
}
|
||||
n = (n << 4) | digit;
|
||||
}
|
||||
thisCh = (REchar)(n);
|
||||
}
|
||||
break;
|
||||
case 'd':
|
||||
addCharacterRangeToCharSet(charSet, '0', '9');
|
||||
continue; /* don't need range processing */
|
||||
case 'D':
|
||||
addCharacterRangeToCharSet(charSet, 0, '0' - 1);
|
||||
addCharacterRangeToCharSet(charSet, (REchar)('9' + 1),
|
||||
(REchar)(charSet->length - 1));
|
||||
continue;
|
||||
case 's':
|
||||
for (i = (REint32)(charSet->length - 1); i >= 0; i--)
|
||||
if (RE_ISWS(i))
|
||||
addCharacterToCharSet(charSet, (REchar)(i));
|
||||
continue;
|
||||
case 'S':
|
||||
for (i = (REint32)(charSet->length - 1); i >= 0; i--)
|
||||
if (!RE_ISWS(i))
|
||||
addCharacterToCharSet(charSet, (REchar)(i));
|
||||
continue;
|
||||
case 'w':
|
||||
for (i = (REint32)(charSet->length - 1); i >= 0; i--)
|
||||
if (RE_ISLETDIG(i))
|
||||
addCharacterToCharSet(charSet, (REchar)(i));
|
||||
continue;
|
||||
case 'W':
|
||||
for (i = (REint32)(charSet->length - 1); i >= 0; i--)
|
||||
if (!RE_ISLETDIG(i))
|
||||
addCharacterToCharSet(charSet, (REchar)(i));
|
||||
continue;
|
||||
default:
|
||||
thisCh = c;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
thisCh = *src++;
|
||||
break;
|
||||
}
|
||||
|
||||
if (inRange) {
|
||||
if (globalData->flags & IGNORECASE) {
|
||||
REchar minch = (REchar)65535;
|
||||
REchar maxch = 0;
|
||||
/*
|
||||
|
||||
yuk
|
||||
|
||||
*/
|
||||
if (rangeStart < minch) minch = rangeStart;
|
||||
if (thisCh < minch) minch = thisCh;
|
||||
if (canonicalize(rangeStart) < minch) minch = canonicalize(rangeStart);
|
||||
if (canonicalize(thisCh) < minch) minch = canonicalize(thisCh);
|
||||
|
||||
if (rangeStart > maxch) maxch = rangeStart;
|
||||
if (thisCh > maxch) maxch = thisCh;
|
||||
if (canonicalize(rangeStart) > maxch) maxch = canonicalize(rangeStart);
|
||||
if (canonicalize(thisCh) > maxch) maxch = canonicalize(thisCh);
|
||||
addCharacterRangeToCharSet(charSet, minch, maxch);
|
||||
}
|
||||
else
|
||||
addCharacterRangeToCharSet(charSet, rangeStart, thisCh);
|
||||
inRange = false;
|
||||
}
|
||||
else {
|
||||
if (globalData->flags & IGNORECASE)
|
||||
addCharacterToCharSet(charSet, canonicalize(thisCh));
|
||||
addCharacterToCharSet(charSet, thisCh);
|
||||
if (src < (end - 1)) {
|
||||
if (*src == '-') {
|
||||
++src;
|
||||
inRange = true;
|
||||
rangeStart = thisCh;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/* Compile the source of the class into a CharSet */
|
||||
static REbool processCharSet(REGlobalData *globalData, RENode *target)
|
||||
{
|
||||
REchar rangeStart, thisCh;
|
||||
const REchar *src = (const REchar *)(target->child);
|
||||
const REchar *end = target->data.chclass.end;
|
||||
|
||||
REchar c;
|
||||
REint32 nDigits;
|
||||
REint32 i;
|
||||
REuint32 length;
|
||||
CharSet *charSet;
|
||||
bool inRange = false;
|
||||
|
||||
charSet = target->data.chclass.charSet;
|
||||
length = (charSet->length / 8) + 1;
|
||||
charSet->bits = (uint8 *)malloc(length);
|
||||
if (!charSet->bits)
|
||||
return false;
|
||||
memset(charSet->bits, 0, length);
|
||||
|
||||
target->data.chclass.sense = true;
|
||||
|
||||
if (src == end)
|
||||
return true;
|
||||
|
||||
if (*src == '^') {
|
||||
target->data.chclass.sense = false;
|
||||
++src;
|
||||
}
|
||||
while (src != end) {
|
||||
switch (*src) {
|
||||
case '\\':
|
||||
++src;
|
||||
c = *src++;
|
||||
switch (c) {
|
||||
case 'b':
|
||||
thisCh = 0x8;
|
||||
break;
|
||||
case 'f':
|
||||
thisCh = 0xC;
|
||||
addCharacterToCharSet(charSet, 0xC);
|
||||
break;
|
||||
case 'n':
|
||||
thisCh = 0xA;
|
||||
break;
|
||||
case 'r':
|
||||
thisCh = 0xD;
|
||||
break;
|
||||
case 't':
|
||||
thisCh = 0x9;
|
||||
break;
|
||||
case 'v':
|
||||
thisCh = 0xB;
|
||||
break;
|
||||
case 'c':
|
||||
if (((src + 1) < end) && RE_ISLETTER(src[1]))
|
||||
thisCh = (REchar)(*src++ & 0x1F);
|
||||
else {
|
||||
--src;
|
||||
thisCh = '\\';
|
||||
}
|
||||
break;
|
||||
case 'x':
|
||||
nDigits = 2;
|
||||
goto lexHex;
|
||||
case 'u':
|
||||
nDigits = 4;
|
||||
lexHex:
|
||||
{
|
||||
REuint32 n = 0;
|
||||
for (i = 0; (i < nDigits) && (src < end); i++) {
|
||||
REuint32 digit;
|
||||
c = *src++;
|
||||
if (!isASCIIHexDigit(c, &digit)) {
|
||||
/* back off to accepting the original '\'
|
||||
* as a literal
|
||||
*/
|
||||
src -= (i + 1);
|
||||
n = '\\';
|
||||
break;
|
||||
}
|
||||
n = (n << 4) | digit;
|
||||
}
|
||||
thisCh = (REchar)(n);
|
||||
}
|
||||
break;
|
||||
case 'd':
|
||||
addCharacterRangeToCharSet(charSet, '0', '9');
|
||||
continue; /* don't need range processing */
|
||||
case 'D':
|
||||
addCharacterRangeToCharSet(charSet, 0, '0' - 1);
|
||||
addCharacterRangeToCharSet(charSet, (REchar)('9' + 1),
|
||||
(REchar)(charSet->length - 1));
|
||||
continue;
|
||||
case 's':
|
||||
for (i = (REint32)(charSet->length - 1); i >= 0; i--)
|
||||
if (RE_ISWS(i))
|
||||
addCharacterToCharSet(charSet, (REchar)(i));
|
||||
continue;
|
||||
case 'S':
|
||||
for (i = (REint32)(charSet->length - 1); i >= 0; i--)
|
||||
if (!RE_ISWS(i))
|
||||
addCharacterToCharSet(charSet, (REchar)(i));
|
||||
continue;
|
||||
case 'w':
|
||||
for (i = (REint32)(charSet->length - 1); i >= 0; i--)
|
||||
if (RE_ISLETDIG(i))
|
||||
addCharacterToCharSet(charSet, (REchar)(i));
|
||||
continue;
|
||||
case 'W':
|
||||
for (i = (REint32)(charSet->length - 1); i >= 0; i--)
|
||||
if (!RE_ISLETDIG(i))
|
||||
addCharacterToCharSet(charSet, (REchar)(i));
|
||||
continue;
|
||||
default:
|
||||
thisCh = c;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
thisCh = *src++;
|
||||
break;
|
||||
}
|
||||
|
||||
if (inRange) {
|
||||
if (globalData->flags & IGNORECASE) {
|
||||
REchar minch = (REchar)65535;
|
||||
REchar maxch = 0;
|
||||
/*
|
||||
|
||||
yuk
|
||||
|
||||
*/
|
||||
if (rangeStart < minch) minch = rangeStart;
|
||||
if (thisCh < minch) minch = thisCh;
|
||||
if (canonicalize(rangeStart) < minch) minch = canonicalize(rangeStart);
|
||||
if (canonicalize(thisCh) < minch) minch = canonicalize(thisCh);
|
||||
|
||||
if (rangeStart > maxch) maxch = rangeStart;
|
||||
if (thisCh > maxch) maxch = thisCh;
|
||||
if (canonicalize(rangeStart) > maxch) maxch = canonicalize(rangeStart);
|
||||
if (canonicalize(thisCh) > maxch) maxch = canonicalize(thisCh);
|
||||
addCharacterRangeToCharSet(charSet, minch, maxch);
|
||||
}
|
||||
else
|
||||
addCharacterRangeToCharSet(charSet, rangeStart, thisCh);
|
||||
inRange = false;
|
||||
}
|
||||
else {
|
||||
if (globalData->flags & IGNORECASE)
|
||||
addCharacterToCharSet(charSet, canonicalize(thisCh));
|
||||
addCharacterToCharSet(charSet, thisCh);
|
||||
if (src < (end - 1)) {
|
||||
if (*src == '-') {
|
||||
++src;
|
||||
inRange = true;
|
||||
rangeStart = thisCh;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
Initialize the character set if it this is the first call.
|
||||
@ -1329,32 +1329,28 @@ static REState *classMatcher(REGlobalData *globalData, REState *x, RENode *targe
|
||||
REuint32 e = x->endIndex;
|
||||
if (e == globalData->length)
|
||||
return NULL;
|
||||
if (target->data.chclass.charSet->bits == NULL) {
|
||||
if (!processCharSet(globalData, target))
|
||||
return NULL;
|
||||
}
|
||||
if (target->data.chclass.charSet->bits == NULL) {
|
||||
if (!processCharSet(globalData, target))
|
||||
return NULL;
|
||||
}
|
||||
charSet = target->data.chclass.charSet;
|
||||
ch = globalData->input[e];
|
||||
if (globalData->flags & IGNORECASE) {
|
||||
ch = canonicalize(ch);
|
||||
}
|
||||
byteIndex = (REuint32)((ch / 8) + 1);
|
||||
ch &= 0x7;
|
||||
if (target->data.chclass.sense) {
|
||||
if ((charSet->length == 0) ||
|
||||
( (ch > charSet->length)
|
||||
|| ((charSet->bits[byteIndex - 1] & (1 << ch)) == 0) ))
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
if (! ((charSet->length == 0) ||
|
||||
( (ch > charSet->length)
|
||||
|| ((charSet->bits[byteIndex - 1] & (1 << ch)) == 0) )))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (charSet->length) /* match empty character */
|
||||
x->endIndex++;
|
||||
byteIndex = (REuint32)(ch / 8);
|
||||
if (target->data.chclass.sense) {
|
||||
if ((charSet->length == 0) ||
|
||||
( (ch > charSet->length)
|
||||
|| ((charSet->bits[byteIndex] & (1 << (ch & 0x7))) == 0) ))
|
||||
return NULL;
|
||||
}
|
||||
else {
|
||||
if (! ((charSet->length == 0) ||
|
||||
( (ch > charSet->length)
|
||||
|| ((charSet->bits[byteIndex] & (1 << (ch & 0x7))) == 0) )))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (charSet->length) /* match empty character */
|
||||
x->endIndex++;
|
||||
return x;
|
||||
}
|
||||
|
||||
@ -1649,7 +1645,7 @@ static REState *executeRENode(RENode *t, REGlobalData *globalData, REState *x)
|
||||
break;
|
||||
}
|
||||
else {
|
||||
for (k = 1; k <= t->data.quantifier.parenCount; k++)
|
||||
for (k = 0; k <= t->data.quantifier.parenCount; k++)
|
||||
x->parens[t->parenIndex + k].index = -1;
|
||||
currentContinuation.index = x->endIndex;
|
||||
currentContinuation.node = t;
|
||||
@ -1661,9 +1657,9 @@ static REState *executeRENode(RENode *t, REGlobalData *globalData, REState *x)
|
||||
continue;
|
||||
case REOP_MINIMALREPEAT:
|
||||
if (result == NULL) {
|
||||
if ((backTrackData->continuation.max == -1)
|
||||
|| (backTrackData->continuation.max > 0)) {
|
||||
for (k = 1; k <= t->data.quantifier.parenCount; k++)
|
||||
if ((backTrackData->continuation.max == -1)
|
||||
|| (backTrackData->continuation.max > 0)) {
|
||||
for (k = 0; k <= t->data.quantifier.parenCount; k++)
|
||||
x->parens[t->parenIndex + k].index = -1;
|
||||
currentContinuation.node = t;
|
||||
currentContinuation.op = REOP_MINIMALREPEAT;
|
||||
@ -1688,7 +1684,7 @@ static REState *executeRENode(RENode *t, REGlobalData *globalData, REState *x)
|
||||
if (currentContinuation.min > 0) --currentContinuation.min;
|
||||
if (currentContinuation.max != -1) --currentContinuation.max;
|
||||
if (currentContinuation.min > 0) {
|
||||
for (k = 1; k <= t->data.quantifier.parenCount; k++)
|
||||
for (k = 0; k <= t->data.quantifier.parenCount; k++)
|
||||
x->parens[t->parenIndex + k].index = -1;
|
||||
currentContinuation.node = t;
|
||||
currentContinuation.op = REOP_MINIMALREPEAT;
|
||||
@ -1747,11 +1743,9 @@ static REState *executeRENode(RENode *t, REGlobalData *globalData, REState *x)
|
||||
if (result == NULL)
|
||||
result = x;
|
||||
else {
|
||||
recoverState(x, backTrackStack[backTrackStackTop].state);
|
||||
|
||||
result = NULL;
|
||||
|
||||
}
|
||||
recoverState(x, backTrackStack[backTrackStackTop].state);
|
||||
result = NULL;
|
||||
}
|
||||
}
|
||||
currentContinuation = t->continuation;
|
||||
break;
|
||||
@ -1835,8 +1829,8 @@ REParseState *REParse(const REchar *source, REuint32 sourceLength,
|
||||
pState->flags |= MULTILINE; break;
|
||||
default:
|
||||
reportRegExpError(&pState->error, BAD_FLAG);
|
||||
free(pState);
|
||||
return NULL;
|
||||
free(pState);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (parseDisjunction(pState)) {
|
||||
@ -1845,16 +1839,16 @@ REParseState *REParse(const REchar *source, REuint32 sourceLength,
|
||||
while (t->next) t = t->next;
|
||||
t->next = newRENode(pState, REOP_END);
|
||||
if (!t->next) {
|
||||
free(pState);
|
||||
return NULL;
|
||||
}
|
||||
free(pState);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
pState->result = newRENode(pState, REOP_END);
|
||||
return pState;
|
||||
}
|
||||
else {
|
||||
free(pState);
|
||||
free(pState);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@ -1911,32 +1905,32 @@ REState *REExecute(REParseState *parseState, const REchar *text,
|
||||
}
|
||||
|
||||
/*
|
||||
Simple anchoring optimization -
|
||||
Simple anchoring optimization -
|
||||
*/
|
||||
if ((parseState->result->kind == REOP_FLAT1)
|
||||
|| (parseState->result->kind == REOP_FLATN)) {
|
||||
REchar matchCh = parseState->result->data.ch;
|
||||
|| (parseState->result->kind == REOP_FLATN)) {
|
||||
REchar matchCh = parseState->result->data.ch;
|
||||
if (parseState->result->kind == REOP_FLATN)
|
||||
matchCh = *((REchar *)parseState->result->child);
|
||||
for (j = (REuint32)i; j < length; j++) {
|
||||
if (text[j] == matchCh) {
|
||||
i = (REint32)j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (j == length) {
|
||||
for (j = (REuint32)i; j < length; j++) {
|
||||
if (text[j] == matchCh) {
|
||||
i = (REint32)j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (j == length) {
|
||||
parseState->lastIndex = 0;
|
||||
free(x);
|
||||
return NULL;
|
||||
}
|
||||
free(x);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
while (true) {
|
||||
x->endIndex = (REuint32)i;
|
||||
backTrackStackTop = 0;
|
||||
result = executeRENode(parseState->result, &gData, x);
|
||||
for (j = 0; j < backTrackStackTop; j++)
|
||||
free(backTrackStack[j].state);
|
||||
for (j = 0; j < backTrackStackTop; j++)
|
||||
free(backTrackStack[j].state);
|
||||
if (gData.error != NO_ERROR) return NULL;
|
||||
if (result == NULL) {
|
||||
i++;
|
||||
|
Loading…
x
Reference in New Issue
Block a user