diff --git a/mozilla/js/src/jsregexp.c b/mozilla/js/src/jsregexp.c index 18ab92c3582..05b797fd76e 100644 --- a/mozilla/js/src/jsregexp.c +++ b/mozilla/js/src/jsregexp.c @@ -68,7 +68,7 @@ #if JS_HAS_REGEXPS -/* Note : contiguity of 'simple opcodes' is important for simpleMatch() */ +/* Note : contiguity of 'simple opcodes' is important for SimpleMatch() */ typedef enum REOp { REOP_EMPTY = 0, /* match rest of input against rest of r.e. */ REOP_ALT = 1, /* alternative subexpressions in kid and next */ @@ -127,7 +127,8 @@ typedef enum REOp { REOP_END } REOp; -#define REOP_IS_SIMPLE(op) (((op) >= REOP_SIMPLE_START) && ((op) <= REOP_SIMPLE_END)) +#define REOP_IS_SIMPLE(op) ((unsigned)((op) - REOP_SIMPLE_START) < \ + (unsigned)REOP_SIMPLE_END) struct RENode { REOp op; /* r.e. op bytecode */ @@ -151,7 +152,7 @@ struct RENode { } ucclass; struct { /* or a literal sequence */ jschar chr; /* of one character */ - uint16 length; /* or many (via the kid) */ + uint16 length; /* or many (via the kid) */ } flat; struct { RENode *kid2; /* second operand from ALT */ @@ -161,12 +162,13 @@ struct RENode { } u; }; -#define RE_IS_LETTER(c) ( ((c >= 'A') && (c <= 'Z')) || \ - ((c >= 'a') && (c <= 'z')) ) -#define RE_IS_LINE_TERM(c) ( (c == '\n') || (c == '\r') || \ - (c == LINE_SEPARATOR) || (c == PARA_SEPARATOR)) +#define RE_IS_LETTER(c) (((c >= 'A') && (c <= 'Z')) || \ + ((c >= 'a') && (c <= 'z')) ) +#define RE_IS_LINE_TERM(c) ((c == '\n') || (c == '\r') || \ + (c == LINE_SEPARATOR) || (c == PARA_SEPARATOR)) + +#define CLASS_CACHE_SIZE 4 -#define CLASS_CACHE_SIZE (4) typedef struct CompilerState { JSContext *context; JSTokenStream *tokenStream; /* For reporting errors */ @@ -178,7 +180,7 @@ typedef struct CompilerState { uint16 classCount; /* number of [] encountered */ size_t progLength; /* estimated bytecode length */ uintN treeDepth; /* maximum depth of parse tree */ - RENode *result; + RENode *result; struct { const jschar *start; /* small cache of class strings */ uint16 length; /* since they're often the same */ @@ -193,7 +195,7 @@ typedef struct RECapture { typedef struct REMatchState { const jschar *cp; - RECapture parens[1]; /* first of 're->parenCount' captures, + RECapture parens[1]; /* first of 're->parenCount' captures, * allocated at end of this struct. */ } REMatchState; @@ -202,7 +204,7 @@ struct REBackTrackData; typedef struct REProgState { jsbytecode *continue_pc; /* current continuation data */ - jsbytecode continue_op; + jsbytecode continue_op; uint16 index; /* progress in text */ uintN parenSoFar; /* highest indexed paren started */ union { @@ -234,7 +236,7 @@ typedef struct REBackTrackData { typedef struct REGlobalData { JSContext *cx; - JSRegExp *regexp; /* the RE in execution */ + JSRegExp *regexp; /* the RE in execution */ JSBool ok; /* runtime error (out_of_memory only?) */ size_t start; /* offset to start at */ ptrdiff_t skipped; /* chars skipped anchoring this r.e. */ @@ -259,7 +261,7 @@ typedef struct REGlobalData { /* * 1. If IgnoreCase is false, return ch. - * 2. Let u be ch converted to upper case as if by calling + * 2. Let u be ch converted to upper case as if by calling * String.prototype.toUpperCase on the one-character string ch. * 3. If u does not consist of a single character, return ch. * 4. Let cu be u's character. @@ -271,7 +273,8 @@ static jschar upcase(jschar ch) { jschar cu = JS_TOUPPER(ch); - if ((ch >= 128) && (cu < 128)) return ch; + if (ch >= 128 && cu < 128) + return ch; return cu; } @@ -279,7 +282,8 @@ static jschar downcase(jschar ch) { jschar cl = JS_TOLOWER(ch); - if ((cl >= 128) && (ch < 128)) return ch; + if (cl >= 128 && ch < 128) + return ch; return cl; } @@ -332,65 +336,60 @@ typedef struct { } REOpData; -/* +/* * Process the op against the two top operands, reducing them to a single * operand in the penultimate slot. Update progLength and treeDepth. */ -static JSBool -processOp(CompilerState *state, REOpData *opData, RENode **operandStack, intN operandSP) +static JSBool +ProcessOp(CompilerState *state, REOpData *opData, RENode **operandStack, intN operandSP) { RENode *result; switch (opData->op) { case REOP_ALT: result = NewRENode(state, REOP_ALT); - if (!result) + if (!result) return JS_FALSE; result->kid = operandStack[operandSP - 2]; result->u.kid2 = operandStack[operandSP - 1]; operandStack[operandSP - 2] = result; - /* + /* * look at both alternates to see if there's a FLAT or a CLASS at * the start of each. If so, use a prerequisite match */ ++state->treeDepth; - if ((((RENode *)(result->kid))->op == REOP_FLAT) - && (((RENode *)(result->u.kid2))->op == REOP_FLAT) - && ((state->flags & JSREG_FOLD) == 0) ) { + if (((RENode *) result->kid)->op == REOP_FLAT && + ((RENode *) result->u.kid2)->op == REOP_FLAT && + (state->flags & JSREG_FOLD) == 0) { result->op = REOP_ALTPREREQ; - result->u.altprereq.ch1 - = ((RENode *)(result->kid))->u.flat.chr; - result->u.altprereq.ch2 - = ((RENode *)(result->u.kid2))->u.flat.chr; - /* ALTPREREQ, , uch1, uch2, , ..., + result->u.altprereq.ch1 = ((RENode *) result->kid)->u.flat.chr; + result->u.altprereq.ch2 = ((RENode *) result->u.kid2)->u.flat.chr; + /* ALTPREREQ, , uch1, uch2, , ..., JUMP, ... ENDALT */ state->progLength += 13; } else - if ((((RENode *)(result->kid))->op == REOP_CLASS) - && (((RENode *)(result->kid))->u.ucclass.index < 256) - && (((RENode *)(result->u.kid2))->op == REOP_FLAT) - && ((state->flags & JSREG_FOLD) == 0) ) { + if (((RENode *) result->kid)->op == REOP_CLASS && + ((RENode *) result->kid)->u.ucclass.index < 256 && + ((RENode *) result->u.kid2)->op == REOP_FLAT && + (state->flags & JSREG_FOLD) == 0) { result->op = REOP_ALTPREREQ2; - result->u.altprereq.ch1 - = ((RENode *)(result->u.kid2))->u.flat.chr; - result->u.altprereq.ch2 - = ((RENode *)(result->kid))->u.ucclass.index; - /* ALTPREREQ2, , uch1, uch2, , ..., + result->u.altprereq.ch1 = ((RENode *) result->u.kid2)->u.flat.chr; + result->u.altprereq.ch2 = ((RENode *) result->kid)->u.ucclass.index; + /* ALTPREREQ2, , uch1, uch2, , ..., JUMP, ... ENDALT */ state->progLength += 13; } else - if ((((RENode *)(result->kid))->op == REOP_FLAT) - && (((RENode *)(result->u.kid2))->op == REOP_CLASS) - && (((RENode *)(result->u.kid2))->u.ucclass.index < 256) - && ((state->flags & JSREG_FOLD) == 0) ) { + if (((RENode *) result->kid)->op == REOP_FLAT && + ((RENode *) result->u.kid2)->op == REOP_CLASS && + ((RENode *) result->u.kid2)->u.ucclass.index < 256 && + (state->flags & JSREG_FOLD) == 0) { result->op = REOP_ALTPREREQ2; - result->u.altprereq.ch1 - = ((RENode *)(result->kid))->u.flat.chr; - result->u.altprereq.ch2 - = ((RENode *)(result->u.kid2))->u.ucclass.index; - /* ALTPREREQ2, , uch1, uch2, , ..., + result->u.altprereq.ch1 = ((RENode *) result->kid)->u.flat.chr; + result->u.altprereq.ch2 = + ((RENode *) result->u.kid2)->u.ucclass.index; + /* ALTPREREQ2, , uch1, uch2, , ..., JUMP, ... ENDALT */ state->progLength += 13; } @@ -421,8 +420,8 @@ processOp(CompilerState *state, REOpData *opData, RENode **operandStack, intN op /* * Parser forward declarations. */ -static JSBool parseTerm(CompilerState *state); -static JSBool parseQuantifier(CompilerState *state); +static JSBool ParseTerm(CompilerState *state); +static JSBool ParseQuantifier(CompilerState *state); /* * Top-down regular expression grammar, based closely on Perl4. @@ -432,8 +431,8 @@ static JSBool parseQuantifier(CompilerState *state); */ #define INITIAL_STACK_SIZE (128) -static JSBool -parseRegExp(CompilerState *state) +static JSBool +ParseRegExp(CompilerState *state) { uint16 parenIndex; RENode *operand; @@ -452,18 +451,18 @@ parseRegExp(CompilerState *state) return (state->result != NULL); } - operatorStack = (REOpData *)JS_malloc(state->context, - sizeof(REOpData) * operatorStackSize); + operatorStack = (REOpData *) + JS_malloc(state->context, sizeof(REOpData) * operatorStackSize); if (!operatorStack) return JS_FALSE; - operandStack = (RENode **)JS_malloc(state->context, - sizeof(RENode *) * operandStackSize); + operandStack = (RENode **) + JS_malloc(state->context, sizeof(RENode *) * operandStackSize); if (!operandStack) goto out; - while (JS_TRUE) { + parenIndex = state->parenCount; if (state->cp == state->cpend) { /* * If we are at the end of the regexp and we're short an operand, @@ -480,42 +479,34 @@ parseRegExp(CompilerState *state) /* balance '(' */ case '(': /* balance ')' */ ++state->cp; - if ((state->cp < state->cpend) && (*state->cp == '?') - && ( (state->cp[1] == '=') - || (state->cp[1] == '!') - || (state->cp[1] == ':') )) { - ++state->cp; - if (state->cp == state->cpend) { - js_ReportCompileErrorNumber(state->context, - state->tokenStream, - NULL, JSREPORT_ERROR, - JSMSG_MISSING_PAREN); - goto out; - } - switch (*state->cp++) { + if (state->cp + 1 < state->cpend && + *state->cp == '?' && + (state->cp[1] == '=' || + state->cp[1] == '!' || + state->cp[1] == ':')) { + switch (state->cp[1]) { case '=': op = REOP_ASSERT; /* ASSERT, , ... ASSERTTEST */ - state->progLength += 4; + state->progLength += 4; break; case '!': op = REOP_ASSERT_NOT; /* ASSERTNOT, , ... ASSERTNOTTEST */ state->progLength += 4; break; - case ':': + default: op = REOP_LPARENNON; break; } - parenIndex = state->parenCount; - } - else { + state->cp += 2; + } else { op = REOP_LPAREN; /* LPAREN, , ... RPAREN, */ state->progLength += 6; - parenIndex = state->parenCount++; + state->parenCount++; if (state->parenCount == 65535) { - js_ReportCompileErrorNumber(state->context, + js_ReportCompileErrorNumber(state->context, state->tokenStream, NULL, JSREPORT_ERROR, JSMSG_TOO_MANY_PARENS); @@ -527,18 +518,20 @@ parseRegExp(CompilerState *state) /* If there's not a stacked open parenthesis, throw * a syntax error. */ - for (i = operatorSP - 1; i >= 0; i--) - if ((operatorStack[i].op == REOP_ASSERT) - || (operatorStack[i].op == REOP_ASSERT_NOT) - || (operatorStack[i].op == REOP_LPARENNON) - || (operatorStack[i].op == REOP_LPAREN)) + for (i = operatorSP - 1; ; i--) { + if (i < 0) { + js_ReportCompileErrorNumber(state->context, + state->tokenStream, + NULL, JSREPORT_ERROR, + JSMSG_UNMATCHED_RIGHT_PAREN); + goto out; + } + if (operatorStack[i].op == REOP_ASSERT || + operatorStack[i].op == REOP_ASSERT_NOT || + operatorStack[i].op == REOP_LPARENNON || + operatorStack[i].op == REOP_LPAREN) { break; - if (i == -1) { - js_ReportCompileErrorNumber(state->context, - state->tokenStream, - NULL, JSREPORT_ERROR, - JSMSG_UNMATCHED_RIGHT_PAREN); - goto out; + } } /* fall thru... */ case '|': @@ -548,13 +541,13 @@ parseRegExp(CompilerState *state) goto out; goto pushOperand; default: - if (!parseTerm(state)) + if (!ParseTerm(state)) goto out; operand = state->result; pushOperand: if (operandSP == operandStackSize) { operandStackSize += operandStackSize; - operandStack = + operandStack = (RENode **)JS_realloc(state->context, operandStack, sizeof(RENode *) * operandStackSize); if (!operandStack) @@ -569,7 +562,7 @@ restartOperator: if (state->cp == state->cpend) { while (operatorSP) { --operatorSP; - if (!processOp(state, &operatorStack[operatorSP], + if (!ProcessOp(state, &operatorStack[operatorSP], operandStack, operandSP)) goto out; --operandSP; @@ -580,13 +573,13 @@ restartOperator: goto out; } switch (*state->cp) { - case '|': + case '|': /* Process any stacked 'concat' operators */ ++state->cp; - while (operatorSP - && (operatorStack[operatorSP - 1].op == REOP_CONCAT)) { + while (operatorSP && + operatorStack[operatorSP - 1].op == REOP_CONCAT) { --operatorSP; - if (!processOp(state, &operatorStack[operatorSP], + if (!ProcessOp(state, &operatorStack[operatorSP], operandStack, operandSP)) goto out; --operandSP; @@ -598,23 +591,25 @@ restartOperator: /* If there's not a stacked open parenthesis,we * accept the close as a flat. */ - for (i = operatorSP - 1; i >= 0; i--) - if ((operatorStack[i].op == REOP_ASSERT) - || (operatorStack[i].op == REOP_ASSERT_NOT) - || (operatorStack[i].op == REOP_LPARENNON) - || (operatorStack[i].op == REOP_LPAREN)) + for (i = operatorSP - 1; ; i--) { + if (i < 0) { + js_ReportCompileErrorNumber(state->context, + state->tokenStream, + NULL, JSREPORT_ERROR, + JSMSG_UNMATCHED_RIGHT_PAREN); + goto out; + } + if (operatorStack[i].op == REOP_ASSERT || + operatorStack[i].op == REOP_ASSERT_NOT || + operatorStack[i].op == REOP_LPARENNON || + operatorStack[i].op == REOP_LPAREN) { break; - if (i == -1) { - js_ReportCompileErrorNumber(state->context, - state->tokenStream, - NULL, JSREPORT_ERROR, - JSMSG_UNMATCHED_RIGHT_PAREN); - goto out; + } } ++state->cp; /* process everything on the stack until the open */ while (JS_TRUE) { - JS_ASSERT(operatorSP); + JS_ASSERT(operatorSP); --operatorSP; switch (operatorStack[operatorSP].op) { case REOP_ASSERT: @@ -623,8 +618,8 @@ restartOperator: operand = NewRENode(state, operatorStack[operatorSP].op); if (!operand) goto out; - operand->u.parenIndex - = operatorStack[operatorSP].parenIndex; + operand->u.parenIndex = + operatorStack[operatorSP].parenIndex; JS_ASSERT(operandSP); operand->kid = operandStack[operandSP - 1]; operandStack[operandSP - 1] = operand; @@ -632,12 +627,12 @@ restartOperator: /* fall thru... */ case REOP_LPARENNON: state->result = operandStack[operandSP - 1]; - if (!parseQuantifier(state)) + if (!ParseQuantifier(state)) goto out; operandStack[operandSP - 1] = state->result; goto restartOperator; default: - if (!processOp(state, &operatorStack[operatorSP], + if (!ProcessOp(state, &operatorStack[operatorSP], operandStack, operandSP)) goto out; --operandSP; @@ -651,7 +646,7 @@ restartOperator: pushOperator: if (operatorSP == operatorStackSize) { operatorStackSize += operatorStackSize; - operatorStack = + operatorStack = (REOpData *)JS_realloc(state->context, operatorStack, sizeof(REOpData) * operatorStackSize); if (!operatorStack) @@ -675,12 +670,12 @@ out: * Extract and return a decimal value at state->cp, the * initial character 'c' has already been read. */ -static intN -getDecimalValue(jschar c, CompilerState *state) +static intN +GetDecimalValue(jschar c, CompilerState *state) { intN value = JS7_UNDEC(c); while (state->cp < state->cpend) { - c = *state->cp; + c = *state->cp; if (!JS7_ISDEC(c)) break; value = (10 * value) + JS7_UNDEC(c); @@ -692,14 +687,14 @@ getDecimalValue(jschar c, CompilerState *state) /* * Calculate the total size of the bitmap required for a class expression. */ -static JSBool -calculateBitmapSize(CompilerState *state, RENode *target, const jschar *src, +static JSBool +CalculateBitmapSize(CompilerState *state, RENode *target, const jschar *src, const jschar *end) { - jschar rangeStart, c; - uintN n, digit, nDigits, i; uintN max = 0; JSBool inRange = JS_FALSE; + jschar c, rangeStart = 0; + uintN n, digit, nDigits, i; target->u.ucclass.bmsize = 0; target->u.ucclass.sense = JS_TRUE; @@ -711,7 +706,7 @@ calculateBitmapSize(CompilerState *state, RENode *target, const jschar *src, ++src; target->u.ucclass.sense = JS_FALSE; } - + while (src != end) { uintN localMax = 0; switch (*src) { @@ -738,8 +733,8 @@ calculateBitmapSize(CompilerState *state, RENode *target, const jschar *src, localMax = 0xB; break; case 'c': - if (((src + 1) < end) && RE_IS_LETTER(src[1])) - localMax = (jschar)(*src++ & 0x1F); + if (src + 1 < end && RE_IS_LETTER(src[1])) + localMax = (jschar) (*src++ & 0x1F); else localMax = '\\'; break; @@ -753,11 +748,11 @@ lexHex: for (i = 0; (i < nDigits) && (src < end); i++) { c = *src++; if (!isASCIIHexDigit(c, &digit)) { - /* - * Back off to accepting the original - *'\' as a literal. + /* + * Back off to accepting the original + *'\' as a literal. */ - src -= (i + 1); + src -= i + 1; n = '\\'; break; } @@ -836,9 +831,8 @@ lexHex: return JS_FALSE; } inRange = JS_FALSE; - } - else { - if (src < (end - 1)) { + } else { + if (src < end - 1) { if (*src == '-') { ++src; inRange = JS_TRUE; @@ -913,26 +907,25 @@ lexHex: * otheratomchar Any character not first among the other * atom right-hand sides. */ -static JSBool -parseTerm(CompilerState *state) +static JSBool +ParseTerm(CompilerState *state) { jschar c = *state->cp++; uintN nDigits; uintN num, tmp, n, i; const jschar *termStart; - JSBool foundCachedCopy; switch (c) { /* assertions and atoms */ case '^': state->result = NewRENode(state, REOP_BOL); - if (!state->result) + if (!state->result) return JS_FALSE; state->progLength++; return JS_TRUE; case '$': state->result = NewRENode(state, REOP_EOL); - if (!state->result) + if (!state->result) return JS_FALSE; state->progLength++; return JS_TRUE; @@ -949,42 +942,41 @@ parseTerm(CompilerState *state) /* assertion escapes */ case 'b' : state->result = NewRENode(state, REOP_WBDRY); - if (!state->result) + if (!state->result) return JS_FALSE; state->progLength++; return JS_TRUE; case 'B': state->result = NewRENode(state, REOP_WNONBDRY); - if (!state->result) + if (!state->result) return JS_FALSE; state->progLength++; return JS_TRUE; /* Decimal escape */ case '0': - if (JS_HAS_STRICT_OPTION(state->context)) + if (JS_HAS_STRICT_OPTION(state->context)){ c = 0; - else { + } else { doOctal: num = 0; while (state->cp < state->cpend) { - if ('0' <= (c = *state->cp) && c <= '7') { - state->cp++; - tmp = 8 * num + (uintN)JS7_UNDEC(c); - if (tmp > 0377) - break; - num = tmp; - } - else + c = *state->cp; + if (c < '0' || '7' < c) break; + state->cp++; + tmp = 8 * num + (uintN)JS7_UNDEC(c); + if (tmp > 0377) + break; + num = tmp; } - c = (jschar)(num); + c = (jschar)num; } doFlat: state->result = NewRENode(state, REOP_FLAT); - if (!state->result) + if (!state->result) return JS_FALSE; state->result->u.flat.chr = c; - state->result->u.flat.length = 1; + state->result->u.flat.length = 1; state->progLength += 3; break; case '1': @@ -997,7 +989,7 @@ parseTerm(CompilerState *state) case '8': case '9': termStart = state->cp - 1; - num = (uintN)getDecimalValue(c, state); + num = (uintN)GetDecimalValue(c, state); if (num > 9 && num > state->parenCount && !JS_HAS_STRICT_OPTION(state->context)) { @@ -1005,7 +997,7 @@ parseTerm(CompilerState *state) goto doOctal; } state->result = NewRENode(state, REOP_BACKREF); - if (!state->result) + if (!state->result) return JS_FALSE; state->result->u.parenIndex = num - 1; state->progLength += 3; @@ -1028,10 +1020,9 @@ parseTerm(CompilerState *state) goto doFlat; /* Control letter */ case 'c': - if (((state->cp + 1) < state->cpend) && - RE_IS_LETTER(state->cp[1])) - c = (jschar)(*state->cp++ & 0x1F); - else { + if (state->cp + 1 < state->cpend && RE_IS_LETTER(state->cp[1])) { + c = (jschar) (*state->cp++ & 0x1F); + } else { /* back off to accepting the original '\' as a literal */ --state->cp; c = '\\'; @@ -1046,28 +1037,27 @@ parseTerm(CompilerState *state) nDigits = 4; lexHex: n = 0; - for (i = 0; (i < nDigits) - && (state->cp < state->cpend); i++) { + for (i = 0; i < nDigits && state->cp < state->cpend; i++) { uintN digit; c = *state->cp++; if (!isASCIIHexDigit(c, &digit)) { - /* - * back off to accepting the original - * 'u' or 'x' as a literal + /* + * back off to accepting the original + * 'u' or 'x' as a literal */ - state->cp -= (i + 2); + state->cp -= i + 2; n = *state->cp++; break; } n = (n << 4) | digit; } - c = (jschar)(n); + c = (jschar) n; goto doFlat; /* Character class escapes */ case 'd': state->result = NewRENode(state, REOP_DIGIT); doSimple: - if (!state->result) + if (!state->result) return JS_FALSE; state->progLength++; break; @@ -1089,18 +1079,18 @@ doSimple: /* IdentityEscape */ default: state->result = NewRENode(state, REOP_FLAT); - if (!state->result) + if (!state->result) return JS_FALSE; state->result->u.flat.chr = c; - state->result->u.flat.length = 1; - state->result->kid = (void *)(state->cp - 1); + state->result->u.flat.length = 1; + state->result->kid = (void *) (state->cp - 1); state->progLength += 3; break; } break; case '[': state->result = NewRENode(state, REOP_CLASS); - if (!state->result) + if (!state->result) return JS_FALSE; termStart = state->cp; state->result->u.ucclass.startIndex = termStart - state->cpbegin; @@ -1111,9 +1101,9 @@ doSimple: JSMSG_UNTERM_CLASS, termStart); return JS_FALSE; } - if (*state->cp == '\\') + if (*state->cp == '\\') { state->cp++; - else { + } else { if (*state->cp == ']') { state->result->u.ucclass.kidlen = state->cp - termStart; break; @@ -1121,37 +1111,33 @@ doSimple: } state->cp++; } - foundCachedCopy = JS_FALSE; for (i = 0; i < CLASS_CACHE_SIZE; i++) { - if (state->classCache[i].start) { - if (state->classCache[i].length == state->result->u.ucclass.kidlen) { - foundCachedCopy = JS_TRUE; - for (n = 0; n < state->classCache[i].length; n++) { - if (state->classCache[i].start[n] != termStart[n]) { - foundCachedCopy = JS_FALSE; - break; - } - } - if (foundCachedCopy) { - state->result->u.ucclass.index = state->classCache[i].index; - break; - } - } - } - else { + if (!state->classCache[i].start) { state->classCache[i].start = termStart; state->classCache[i].length = state->result->u.ucclass.kidlen; state->classCache[i].index = state->classCount; break; } + if (state->classCache[i].length == + state->result->u.ucclass.kidlen) { + for (n = 0; ; n++) { + if (n == state->classCache[i].length) { + state->result->u.ucclass.index = + state->classCache[i].index; + goto claim; + } + if (state->classCache[i].start[n] != termStart[n]) + break; + } + } } - if (!foundCachedCopy) - state->result->u.ucclass.index = state->classCount++; - /* - * Call calculateBitmapSize now as we want any errors it finds + state->result->u.ucclass.index = state->classCount++; + claim: + /* + * Call CalculateBitmapSize now as we want any errors it finds * to be reported during the parse phase, not at execution. */ - if (!calculateBitmapSize(state, state->result, termStart, state->cp++)) + if (!CalculateBitmapSize(state, state->result, termStart, state->cp++)) return JS_FALSE; state->progLength += 3; /* CLASS, */ break; @@ -1161,40 +1147,26 @@ doSimple: goto doSimple; case '*': case '+': - case '?': + case '?': js_ReportCompileErrorNumber(state->context, state->tokenStream, NULL, JSREPORT_ERROR, JSMSG_BAD_QUANTIFIER, state->cp - 1); return JS_FALSE; -#if 0 - case '{': /* balance '}' */ - /* Treat left-curly in a non-quantifier context as an error only - * if it's followed immediately by a decimal digit. - * This is an Perl extension. - */ - if ((state->cp != state->cpend) && JS7_ISDEC(*state->cp)) { - js_ReportCompileErrorNumber(state->context, state->tokenStream, - NULL, JSREPORT_ERROR, - JSMSG_BAD_QUANTIFIER, state->cp - 1); - return JS_FALSE; - } - /* fall thru... */ -#endif default: state->result = NewRENode(state, REOP_FLAT); - if (!state->result) + if (!state->result) return JS_FALSE; state->result->u.flat.chr = c; - state->result->u.flat.length = 1; - state->result->kid = (void *)(state->cp - 1); + state->result->u.flat.length = 1; + state->result->kid = (void *) (state->cp - 1); state->progLength += 3; break; } - return parseQuantifier(state); + return ParseQuantifier(state); } -static JSBool -parseQuantifier(CompilerState *state) +static JSBool +ParseQuantifier(CompilerState *state) { RENode *term; term = state->result; @@ -1202,7 +1174,7 @@ parseQuantifier(CompilerState *state) switch (*state->cp) { case '+': state->result = NewRENode(state, REOP_QUANT); - if (!state->result) + if (!state->result) return JS_FALSE; state->result->u.range.min = 1; state->result->u.range.max = -1; @@ -1211,7 +1183,7 @@ parseQuantifier(CompilerState *state) goto quantifier; case '*': state->result = NewRENode(state, REOP_QUANT); - if (!state->result) + if (!state->result) return JS_FALSE; state->result->u.range.min = 0; state->result->u.range.max = -1; @@ -1220,7 +1192,7 @@ parseQuantifier(CompilerState *state) goto quantifier; case '?': state->result = NewRENode(state, REOP_QUANT); - if (!state->result) + if (!state->result) return JS_FALSE; state->result->u.range.min = 0; state->result->u.range.max = 1; @@ -1234,11 +1206,11 @@ parseQuantifier(CompilerState *state) intN max = -1; jschar c; const jschar *errp = state->cp++; - + c = *state->cp; if (JS7_ISDEC(c)) { ++state->cp; - min = getDecimalValue(c, state); + min = GetDecimalValue(c, state); c = *state->cp; if ((min + 1) >> 16) { @@ -1249,7 +1221,7 @@ parseQuantifier(CompilerState *state) c = *++state->cp; if (JS7_ISDEC(c)) { ++state->cp; - max = getDecimalValue(c, state); + max = GetDecimalValue(c, state); c = *state->cp; if ((max + 1) >> 16) { err = JSMSG_MAX_TOO_BIG; @@ -1260,25 +1232,24 @@ parseQuantifier(CompilerState *state) goto quantError; } } - } - else { + } else { max = min; } if (c == '}') { state->result = NewRENode(state, REOP_QUANT); - if (!state->result) + if (!state->result) return JS_FALSE; state->result->u.range.min = min; state->result->u.range.max = max; /* QUANT, , , ... */ - state->progLength += 8; + state->progLength += 8; goto quantifier; } } state->cp = errp; return JS_TRUE; quantError: - js_ReportCompileErrorNumber(state->context, + js_ReportCompileErrorNumber(state->context, state->tokenStream, NULL, JSREPORT_ERROR, err, errp); @@ -1292,16 +1263,16 @@ quantifier: ++state->treeDepth; ++state->cp; state->result->kid = term; - if ((state->cp < state->cpend) && (*state->cp == '?')) { + if (state->cp < state->cpend && *state->cp == '?') { ++state->cp; state->result->u.range.greedy = JS_FALSE; } else - state->result->u.range.greedy = JS_TRUE; + state->result->u.range.greedy = JS_TRUE; return JS_TRUE; } -#define CHECK_OFFSET(diff) (JS_ASSERT(((diff) >= -32768) && ((diff) <= 32767))) +#define CHECK_OFFSET(diff) (JS_ASSERT(((diff) >= -32768) && ((diff) <= 32767))) #define SET_OFFSET(pc,off) ((pc)[0] = JUMP_OFFSET_HI(off), \ (pc)[1] = JUMP_OFFSET_LO(off)) #define GET_OFFSET(pc) ((int16)(((pc)[0] << 8) | (pc)[1])) @@ -1322,7 +1293,7 @@ typedef struct { } EmitStateStackEntry; static jsbytecode * -emitREBytecode(CompilerState *state, JSRegExp *re, intN treeDepth, +EmitREBytecode(CompilerState *state, JSRegExp *re, intN treeDepth, jsbytecode *pc, RENode *t) { ptrdiff_t diff; @@ -1331,10 +1302,10 @@ emitREBytecode(CompilerState *state, JSRegExp *re, intN treeDepth, REOp op; if (treeDepth) { - emitStateStack = + emitStateStack = (EmitStateStackEntry *)JS_malloc(state->context, - sizeof(EmitStateStackEntry) - * treeDepth); + sizeof(EmitStateStackEntry) * + treeDepth); if (!emitStateStack) return NULL; } @@ -1365,10 +1336,10 @@ emitREBytecode(CompilerState *state, JSRegExp *re, intN treeDepth, emitStateSP->continueOp = REOP_JUMP; ++emitStateSP; JS_ASSERT((emitStateSP - emitStateStack) <= treeDepth); - t = (RENode *)(t->kid); + t = (RENode *) t->kid; op = t->op; continue; - + case REOP_JUMP: emitStateSP->nextTermFixup = pc; /* address of following term */ pc += OFFSET_LEN; @@ -1378,7 +1349,7 @@ emitREBytecode(CompilerState *state, JSRegExp *re, intN treeDepth, emitStateSP->continueOp = REOP_ENDALT; ++emitStateSP; JS_ASSERT((emitStateSP - emitStateStack) <= treeDepth); - t = (RENode *)(t->u.kid2); + t = (RENode *) t->u.kid2; op = t->op; continue; @@ -1401,7 +1372,7 @@ emitREBytecode(CompilerState *state, JSRegExp *re, intN treeDepth, emitStateSP->continueOp = REOP_JUMP; ++emitStateSP; JS_ASSERT((emitStateSP - emitStateStack) <= treeDepth); - t = (RENode *)(t->kid); + t = (RENode *) t->kid; op = t->op; continue; @@ -1410,9 +1381,10 @@ emitREBytecode(CompilerState *state, JSRegExp *re, intN treeDepth, * Consecutize FLAT's if possible. */ if (t->kid) { - while (t->next && (t->next->op == REOP_FLAT) - && (((jschar*)(t->kid) + t->u.flat.length) - == (jschar*)(t->next->kid))) { + while (t->next && + t->next->op == REOP_FLAT && + (jschar*)t->kid + t->u.flat.length == + (jschar*)t->next->kid) { t->u.flat.length += t->next->u.flat.length; t->next = t->next->next; } @@ -1422,27 +1394,23 @@ emitREBytecode(CompilerState *state, JSRegExp *re, intN treeDepth, pc[-1] = REOP_FLATi; else pc[-1] = REOP_FLAT; - SET_ARG(pc, (jschar *)(t->kid) - state->cpbegin); + SET_ARG(pc, (jschar *)t->kid - state->cpbegin); pc += ARG_LEN; SET_ARG(pc, t->u.flat.length); pc += ARG_LEN; - } - else { - if (t->u.flat.chr < 256) { - if (state->flags & JSREG_FOLD) - pc[-1] = REOP_FLAT1i; - else - pc[-1] = REOP_FLAT1; - *pc++ = (jsbytecode)(t->u.flat.chr); - } - else { - if (state->flags & JSREG_FOLD) - pc[-1] = REOP_UCFLAT1i; - else - pc[-1] = REOP_UCFLAT1; - SET_ARG(pc, t->u.flat.chr); - pc += ARG_LEN; - } + } else if (t->u.flat.chr < 256) { + if (state->flags & JSREG_FOLD) + pc[-1] = REOP_FLAT1i; + else + pc[-1] = REOP_FLAT1; + *pc++ = (jsbytecode) t->u.flat.chr; + } else { + if (state->flags & JSREG_FOLD) + pc[-1] = REOP_UCFLAT1i; + else + pc[-1] = REOP_UCFLAT1; + SET_ARG(pc, t->u.flat.chr); + pc += ARG_LEN; } break; @@ -1454,7 +1422,7 @@ emitREBytecode(CompilerState *state, JSRegExp *re, intN treeDepth, emitStateSP->continueOp = REOP_RPAREN; ++emitStateSP; JS_ASSERT((emitStateSP - emitStateStack) <= treeDepth); - t = (RENode *)(t->kid); + t = (RENode *) t->kid; op = t->op; continue; case REOP_RPAREN: @@ -1474,7 +1442,7 @@ emitREBytecode(CompilerState *state, JSRegExp *re, intN treeDepth, emitStateSP->continueOp = REOP_ASSERTTEST; ++emitStateSP; JS_ASSERT((emitStateSP - emitStateStack) <= treeDepth); - t = (RENode *)(t->kid); + t = (RENode *) t->kid; op = t->op; continue; case REOP_ASSERTTEST: @@ -1491,21 +1459,20 @@ emitREBytecode(CompilerState *state, JSRegExp *re, intN treeDepth, emitStateSP->continueOp = REOP_ASSERTNOTTEST; ++emitStateSP; JS_ASSERT((emitStateSP - emitStateStack) <= treeDepth); - t = (RENode *)(t->kid); + t = (RENode *) t->kid; op = t->op; continue; case REOP_QUANT: JS_ASSERT(emitStateSP); - if ((t->u.range.min == 0) && (t->u.range.max == (uint16)(-1))) + if (t->u.range.min == 0 && t->u.range.max == (uint16)-1) { pc[-1] = (t->u.range.greedy) ? REOP_STAR : REOP_MINIMALSTAR; - else - if ((t->u.range.min == 0) && (t->u.range.max == 1)) + } else if (t->u.range.min == 0 && t->u.range.max == 1) { pc[-1] = (t->u.range.greedy) ? REOP_OPT : REOP_MINIMALOPT; - else - if ((t->u.range.min == 1) && (t->u.range.max == (uint16)(-1))) + } else if (t->u.range.min == 1 && t->u.range.max == (uint16) -1) { pc[-1] = (t->u.range.greedy) ? REOP_PLUS : REOP_MINIMALPLUS; - else { - if (!t->u.range.greedy) pc[-1] = REOP_MINIMALQUANT; + } else { + if (!t->u.range.greedy) + pc[-1] = REOP_MINIMALQUANT; SET_ARG(pc, t->u.range.min); pc += ARG_LEN; SET_ARG(pc, t->u.range.max); @@ -1517,7 +1484,7 @@ emitREBytecode(CompilerState *state, JSRegExp *re, intN treeDepth, emitStateSP->continueOp = REOP_ENDCHILD; ++emitStateSP; JS_ASSERT((emitStateSP - emitStateStack) <= treeDepth); - t = (RENode *)(t->kid); + t = (RENode *) t->kid; op = t->op; continue; case REOP_ENDCHILD: @@ -1541,7 +1508,7 @@ emitREBytecode(CompilerState *state, JSRegExp *re, intN treeDepth, break; } t = t->next; - if (t == NULL) { + if (!t) { if (emitStateSP == emitStateStack) break; --emitStateSP; @@ -1585,16 +1552,15 @@ js_NewRegExp(JSContext *cx, JSTokenStream *ts, state.classCache[i].start = NULL; len = JSSTRING_LENGTH(str); - + if (len != 0 && flat) { state.result = NewRENode(&state, REOP_FLAT); state.result->u.flat.chr = *state.cpbegin; - state.result->u.flat.length = JSSTRING_LENGTH(str); - state.result->kid = (void *)(state.cpbegin); + state.result->u.flat.length = JSSTRING_LENGTH(str); + state.result->kid = (void *) state.cpbegin; state.progLength += 5; - } - else { - if (!parseRegExp(&state)) + } else { + if (!ParseRegExp(&state)) goto out; } resize = sizeof *re + state.progLength + 1; @@ -1604,14 +1570,15 @@ js_NewRegExp(JSContext *cx, JSTokenStream *ts, re->classCount = state.classCount; if (state.classCount) { - re->classList = (RECharSet *)JS_malloc(cx, sizeof(RECharSet) - * state.classCount); - if (!re->classList) + re->classList = (RECharSet *)JS_malloc(cx, + sizeof(RECharSet) * + state.classCount); + if (!re->classList) goto out; } else re->classList = NULL; - endPC = emitREBytecode(&state, re, state.treeDepth, re->program, state.result); + endPC = EmitREBytecode(&state, re, state.treeDepth, re->program, state.result); if (!endPC) { re = NULL; goto out; @@ -1630,7 +1597,7 @@ out: } JSRegExp * -js_NewRegExpOpt(JSContext *cx, JSTokenStream *ts, +js_NewRegExpOpt(JSContext *cx, JSTokenStream *ts, JSString *str, JSString *opt, JSBool flat) { uintN flags; @@ -1652,7 +1619,7 @@ js_NewRegExpOpt(JSContext *cx, JSTokenStream *ts, case 'm': flags |= JSREG_MULTILINE; break; - default: + default: charBuf[0] = (char)s[i]; charBuf[1] = '\0'; js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR, @@ -1670,36 +1637,36 @@ js_NewRegExpOpt(JSContext *cx, JSTokenStream *ts, /* * Save the current state of the match - the position in the input - * text as well as the position in the bytecode. The state of any + * text as well as the position in the bytecode. The state of any * parent expressions is also saved (preceding state). * Contents of parenCount parentheses from parenIndex are also saved. */ static REBackTrackData * -pushBackTrackState(REGlobalData *gData, REOp op, +PushBackTrackState(REGlobalData *gData, REOp op, jsbytecode *target, REMatchState *x, const jschar *cp, intN parenIndex, intN parenCount) { intN i; - REBackTrackData *result - = (REBackTrackData *)((char *)(gData->backTrackSP) + gData->cursz); + REBackTrackData *result = + (REBackTrackData *) ((char *)gData->backTrackSP + gData->cursz); size_t sz = sizeof(REBackTrackData) + gData->stateStackTop * sizeof(REProgState) + parenCount * sizeof(RECapture); - if (((char *)result + sz) - > (char *)gData->backTrackStack + gData->maxBackTrack) { + if ((char *)result + sz > + (char *)gData->backTrackStack + gData->maxBackTrack) { ptrdiff_t offset = (char *)result - (char *)gData->backTrackStack; - gData->backTrackStack - = (REBackTrackData *)JS_ArenaGrow(&gData->pool, - gData->backTrackStack, - gData->maxBackTrack, + gData->backTrackStack + = (REBackTrackData *)JS_ArenaGrow(&gData->pool, + gData->backTrackStack, + gData->maxBackTrack, gData->maxBackTrack); gData->maxBackTrack <<= 1; if (!gData->backTrackStack) return NULL; - result = (REBackTrackData *)((char *)gData->backTrackStack + offset); + result = (REBackTrackData *) ((char *)gData->backTrackStack + offset); } gData->backTrackSP = result; result->sz = gData->cursz; @@ -1712,14 +1679,14 @@ pushBackTrackState(REGlobalData *gData, REOp op, result->precedingStateTop = gData->stateStackTop; JS_ASSERT(gData->stateStackTop); - memcpy(result + 1, gData->stateStack, + memcpy(result + 1, gData->stateStack, sizeof(REProgState) * result->precedingStateTop); - + if (parenCount != -1) { result->parenIndex = parenIndex; - memcpy((char *)(result + 1) - + sizeof(REProgState) * result->precedingStateTop, - &x->parens[parenIndex], + memcpy((char *)(result + 1) + + sizeof(REProgState) * result->precedingStateTop, + &x->parens[parenIndex], sizeof(RECapture) * parenCount); for (i = 0; i < parenCount; i++) x->parens[parenIndex + i].index = -1; @@ -1734,11 +1701,11 @@ pushBackTrackState(REGlobalData *gData, REOp op, */ #if 0 static REMatchState * -flatNMatcher(REGlobalData *gData, REMatchState *x, jschar *matchChars, +FlatNMatcher(REGlobalData *gData, REMatchState *x, jschar *matchChars, intN length) { intN i; - if ((x->cp + length) > gData->cpend) + if (x->cp + length > gData->cpend) return NULL; for (i = 0; i < length; i++) { if (matchChars[i] != x->cp[i]) @@ -1750,11 +1717,11 @@ flatNMatcher(REGlobalData *gData, REMatchState *x, jschar *matchChars, #endif static REMatchState * -flatNIMatcher(REGlobalData *gData, REMatchState *x, jschar *matchChars, +FlatNIMatcher(REGlobalData *gData, REMatchState *x, jschar *matchChars, intN length) { intN i; - if ((x->cp + length) > gData->cpend) + if (x->cp + length > gData->cpend) return NULL; for (i = 0; i < length; i++) { if (upcase(matchChars[i]) != upcase(x->cp[i])) @@ -1772,7 +1739,7 @@ flatNIMatcher(REGlobalData *gData, REMatchState *x, jschar *matchChars, * 5. Call CharacterSetMatcher(A, false) and return its Matcher result. * 6. E must be an integer. Let n be that integer. * 7. If n=0 or n>NCapturingParens then throw a SyntaxError exception. - * 8. Return an internal Matcher closure that takes two arguments, a State x + * 8. Return an internal Matcher closure that takes two arguments, a State x * and a Continuation c, and performs the following: * 1. Let cap be x's captures internal array. * 2. Let s be cap[n]. @@ -1782,13 +1749,13 @@ flatNIMatcher(REGlobalData *gData, REMatchState *x, jschar *matchChars, * 6. Let f be e+len. * 7. If f>InputLength, return failure. * 8. If there exists an integer i between 0 (inclusive) and len (exclusive) - * such that Canonicalize(s[i]) is not the same character as + * such that Canonicalize(s[i]) is not the same character as * Canonicalize(Input [e+i]), then return failure. * 9. Let y be the State (f, cap). * 10. Call c(y) and return its result. */ static REMatchState * -backrefMatcher(REGlobalData *gData, REMatchState *x, uintN parenIndex) +BackrefMatcher(REGlobalData *gData, REMatchState *x, uintN parenIndex) { uintN len; uintN i; @@ -1798,17 +1765,16 @@ backrefMatcher(REGlobalData *gData, REMatchState *x, uintN parenIndex) return x; len = s->length; - if ((x->cp + len) > gData->cpend) + if (x->cp + len > gData->cpend) return NULL; - + parenContent = &gData->cpbegin[s->index]; if (gData->regexp->flags & JSREG_FOLD) { for (i = 0; i < len; i++) { if (upcase(parenContent[i]) != upcase(x->cp[i])) return NULL; } - } - else { + } else { for (i = 0; i < len; i++) { if (parenContent[i] != x->cp[i]) return NULL; @@ -1820,64 +1786,62 @@ backrefMatcher(REGlobalData *gData, REMatchState *x, uintN parenIndex) /* Add a single character to the RECharSet */ -static void -addCharacterToCharSet(RECharSet *cs, jschar c) +static void +AddCharacterToCharSet(RECharSet *cs, jschar c) { - uintN byteIndex = (uintN)(c / 8); + uintN byteIndex = (uintN)(c >> 3); JS_ASSERT(c <= cs->length); cs->u.bits[byteIndex] |= 1 << (c & 0x7); } /* Add a character range, c1 to c2 (inclusive) to the RECharSet */ -static void -addCharacterRangeToCharSet(RECharSet *cs, jschar c1, jschar c2) +static void +AddCharacterRangeToCharSet(RECharSet *cs, jschar c1, jschar c2) { uintN i; - uintN byteIndex1 = (uintN)(c1 / 8); - uintN byteIndex2 = (uintN)(c2 / 8); + uintN byteIndex1 = (uintN)(c1 >> 3); + uintN byteIndex2 = (uintN)(c2 >> 3); JS_ASSERT((c2 <= cs->length) && (c1 <= c2)); c1 &= 0x7; c2 &= 0x7; - if (byteIndex1 == byteIndex2) - cs->u.bits[byteIndex1] |= ((uint8)(0xFF) >> (7 - (c2 - c1))) << c1; - else { + if (byteIndex1 == byteIndex2) { + cs->u.bits[byteIndex1] |= ((uint8)0xFF >> (7 - (c2 - c1))) << c1; + } else { cs->u.bits[byteIndex1] |= 0xFF << c1; for (i = byteIndex1 + 1; i < byteIndex2; i++) cs->u.bits[i] = 0xFF; - cs->u.bits[byteIndex2] |= (uint8)(0xFF) >> (7 - c2); + cs->u.bits[byteIndex2] |= (uint8)0xFF >> (7 - c2); } } /* Compile the source of the class into a RECharSet */ -static JSBool -processCharSet(REGlobalData *gData, RECharSet *charSet) +static JSBool +ProcessCharSet(REGlobalData *gData, RECharSet *charSet) { - const jschar *src = JSSTRING_CHARS(gData->regexp->source) - + charSet->u.src.startIndex; + const jschar *src = JSSTRING_CHARS(gData->regexp->source) + + charSet->u.src.startIndex; const jschar *end = src + charSet->u.src.length; - jschar rangeStart, thisCh; - uintN byteLength; - jschar c; - uintN n; - intN nDigits; - intN i; JSBool inRange = JS_FALSE; + jschar rangeStart = 0; + uintN byteLength, n; + jschar c, thisCh; + intN nDigits, i; JS_ASSERT(!charSet->converted); charSet->converted = JS_TRUE; - byteLength = (charSet->length / 8) + 1; + byteLength = (charSet->length >> 3) + 1; charSet->u.bits = (uint8 *)JS_malloc(gData->cx, byteLength); if (!charSet->u.bits) return JS_FALSE; memset(charSet->u.bits, 0, byteLength); - + if (src == end) return JS_TRUE; @@ -1914,9 +1878,9 @@ processCharSet(REGlobalData *gData, RECharSet *charSet) thisCh = 0xB; break; case 'c': - if (((src + 1) < end) && JS_ISWORD(src[1])) + if (src + 1 < end && JS_ISWORD(src[1])) { thisCh = (jschar)(*src++ & 0x1F); - else { + } else { --src; thisCh = '\\'; } @@ -1926,23 +1890,23 @@ processCharSet(REGlobalData *gData, RECharSet *charSet) goto lexHex; case 'u': nDigits = 4; -lexHex: + lexHex: n = 0; for (i = 0; (i < nDigits) && (src < end); i++) { uintN digit; c = *src++; if (!isASCIIHexDigit(c, &digit)) { - /* - * Back off to accepting the original '\' + /* + * Back off to accepting the original '\' * as a literal */ - src -= (i + 1); + src -= i + 1; n = '\\'; break; } n = (n << 4) | digit; } - thisCh = (jschar)(n); + thisCh = (jschar)n; break; case '0': case '1': @@ -1973,36 +1937,37 @@ lexHex: src--; } } - thisCh = (jschar)(n); + thisCh = (jschar)n; break; case 'd': - addCharacterRangeToCharSet(charSet, '0', '9'); + AddCharacterRangeToCharSet(charSet, '0', '9'); continue; /* don't need range processing */ case 'D': - addCharacterRangeToCharSet(charSet, 0, '0' - 1); - addCharacterRangeToCharSet(charSet, (jschar)('9' + 1), - (jschar)(charSet->length)); + AddCharacterRangeToCharSet(charSet, 0, '0' - 1); + AddCharacterRangeToCharSet(charSet, + (jschar)('9' + 1), + (jschar)charSet->length); continue; case 's': - for (i = (intN)(charSet->length); i >= 0; i--) + for (i = (intN)charSet->length; i >= 0; i--) if (JS_ISSPACE(i)) - addCharacterToCharSet(charSet, (jschar)(i)); + AddCharacterToCharSet(charSet, (jschar)i); continue; case 'S': - for (i = (intN)(charSet->length); i >= 0; i--) + for (i = (intN)charSet->length; i >= 0; i--) if (!JS_ISSPACE(i)) - addCharacterToCharSet(charSet, (jschar)(i)); + AddCharacterToCharSet(charSet, (jschar)i); continue; case 'w': - for (i = (intN)(charSet->length); i >= 0; i--) + for (i = (intN)charSet->length; i >= 0; i--) if (JS_ISWORD(i)) - addCharacterToCharSet(charSet, (jschar)(i)); + AddCharacterToCharSet(charSet, (jschar)i); continue; case 'W': - for (i = (intN)(charSet->length); i >= 0; i--) + for (i = (intN)charSet->length; i >= 0; i--) if (!JS_ISWORD(i)) - addCharacterToCharSet(charSet, (jschar)(i)); + AddCharacterToCharSet(charSet, (jschar)i); continue; default: thisCh = c; @@ -2018,23 +1983,22 @@ lexHex: } if (inRange) { if (gData->regexp->flags & JSREG_FOLD) { - addCharacterRangeToCharSet(charSet, upcase(rangeStart), + AddCharacterRangeToCharSet(charSet, upcase(rangeStart), upcase(thisCh)); - addCharacterRangeToCharSet(charSet, downcase(rangeStart), + AddCharacterRangeToCharSet(charSet, downcase(rangeStart), downcase(thisCh)); } else { - addCharacterRangeToCharSet(charSet, rangeStart, thisCh); + AddCharacterRangeToCharSet(charSet, rangeStart, thisCh); } inRange = JS_FALSE; - } - else { + } else { if (gData->regexp->flags & JSREG_FOLD) { - addCharacterToCharSet(charSet, upcase(thisCh)); - addCharacterToCharSet(charSet, downcase(thisCh)); + AddCharacterToCharSet(charSet, upcase(thisCh)); + AddCharacterToCharSet(charSet, downcase(thisCh)); } else { - addCharacterToCharSet(charSet, thisCh); + AddCharacterToCharSet(charSet, thisCh); } - if (src < (end - 1)) { + if (src < end - 1) { if (*src == '-') { ++src; inRange = JS_TRUE; @@ -2064,11 +2028,11 @@ js_DestroyRegExp(JSContext *cx, JSRegExp *re) } static JSBool -reallocStateStack(REGlobalData *gData) +ReallocStateStack(REGlobalData *gData) { size_t sz = sizeof(REProgState) * gData->maxStateStack; gData->maxStateStack <<= 1; - gData->stateStack + gData->stateStack = (REProgState *)JS_ArenaGrow(&gData->pool, gData->stateStack, sz, sz); if (!gData->stateStack) { gData->ok = JS_FALSE; @@ -2077,14 +2041,23 @@ reallocStateStack(REGlobalData *gData) return JS_TRUE; } +#define PUSH_STATE_STACK(data) \ + JS_BEGIN_MACRO \ + ++(data)->stateStackTop; \ + if ((data)->stateStackTop == (data)->maxStateStack && \ + !ReallocStateStack((data))) { \ + return NULL; \ + } \ + JS_END_MACRO + /* -* Apply the current op against the given input to see if -* it's going to match or fail. Return false if we don't -* get a match, true if we do and update the state of the -* input and pc if the update flag is true. -*/ -static REMatchState *simpleMatch(REGlobalData *gData, REMatchState *x, - REOp op, jsbytecode **startpc, JSBool update) + * Apply the current op against the given input to see if it's going to match + * or fail. Return false if we don't get a match, true if we do and update the + * state of the input and pc if the update flag is true. + */ +static REMatchState * +SimpleMatch(REGlobalData *gData, REMatchState *x, REOp op, + jsbytecode **startpc, JSBool update) { REMatchState *result = NULL; jschar matchCh; @@ -2096,43 +2069,40 @@ static REMatchState *simpleMatch(REGlobalData *gData, REMatchState *x, jschar ch; RECharSet *charSet; - switch (op) { - default: - JS_ASSERT(JS_FALSE); case REOP_BOL: if (x->cp != gData->cpbegin) { - if (gData->cx->regExpStatics.multiline || - (gData->regexp->flags & JSREG_MULTILINE)) { - if (!RE_IS_LINE_TERM(x->cp[-1])) - break; + if (!gData->cx->regExpStatics.multiline && + !(gData->regexp->flags & JSREG_MULTILINE)) { + break; } - else + if (!RE_IS_LINE_TERM(x->cp[-1])) break; } result = x; break; case REOP_EOL: if (x->cp != gData->cpend) { - if (gData->cx->regExpStatics.multiline || - (gData->regexp->flags & JSREG_MULTILINE)) { - if (!RE_IS_LINE_TERM(*x->cp)) - break; + if (!gData->cx->regExpStatics.multiline && + !(gData->regexp->flags & JSREG_MULTILINE)) { + break; } - else + if (!RE_IS_LINE_TERM(*x->cp)) break; } result = x; break; case REOP_WBDRY: - if ((x->cp == gData->cpbegin || !JS_ISWORD(x->cp[-1])) - ^ !((x->cp != gData->cpend) && JS_ISWORD(*x->cp))) + if ((x->cp == gData->cpbegin || !JS_ISWORD(x->cp[-1])) ^ + !(x->cp != gData->cpend && JS_ISWORD(*x->cp))) { result = x; + } break; case REOP_WNONBDRY: - if ((x->cp == gData->cpbegin || !JS_ISWORD(x->cp[-1])) - ^ ((x->cp != gData->cpend) && JS_ISWORD(*x->cp))) + if ((x->cp == gData->cpbegin || !JS_ISWORD(x->cp[-1])) ^ + (x->cp != gData->cpend && JS_ISWORD(*x->cp))) { result = x; + } break; case REOP_DOT: if (x->cp != gData->cpend && !RE_IS_LINE_TERM(*x->cp)) { @@ -2179,7 +2149,7 @@ static REMatchState *simpleMatch(REGlobalData *gData, REMatchState *x, case REOP_BACKREF: parenIndex = GET_ARG(pc); pc += ARG_LEN; - result = backrefMatcher(gData, x, parenIndex); + result = BackrefMatcher(gData, x, parenIndex); break; case REOP_FLAT: offset = GET_ARG(pc); @@ -2187,7 +2157,7 @@ static REMatchState *simpleMatch(REGlobalData *gData, REMatchState *x, length = GET_ARG(pc); pc += ARG_LEN; source = JSSTRING_CHARS(gData->regexp->source) + offset; - if ((x->cp + length) <= gData->cpend) { + if (x->cp + length <= gData->cpend) { for (index = 0; index < length; index++) { if (source[index] != x->cp[index]) return NULL; @@ -2198,7 +2168,7 @@ static REMatchState *simpleMatch(REGlobalData *gData, REMatchState *x, break; case REOP_FLAT1: matchCh = *pc++; - if ((x->cp != gData->cpend) && (*x->cp == matchCh)) { + if (x->cp != gData->cpend && *x->cp == matchCh) { result = x; result->cp++; } @@ -2209,11 +2179,11 @@ static REMatchState *simpleMatch(REGlobalData *gData, REMatchState *x, length = GET_ARG(pc); pc += ARG_LEN; source = JSSTRING_CHARS(gData->regexp->source); - result = flatNIMatcher(gData, x, source + offset, length); + result = FlatNIMatcher(gData, x, source + offset, length); break; case REOP_FLAT1i: matchCh = *pc++; - if ((x->cp != gData->cpend) && (upcase(*x->cp) == upcase(matchCh))) { + if (x->cp != gData->cpend && upcase(*x->cp) == upcase(matchCh)) { result = x; result->cp++; } @@ -2221,7 +2191,7 @@ static REMatchState *simpleMatch(REGlobalData *gData, REMatchState *x, case REOP_UCFLAT1: matchCh = GET_ARG(pc); pc += ARG_LEN; - if ((x->cp != gData->cpend) && (*x->cp == matchCh)) { + if (x->cp != gData->cpend && *x->cp == matchCh) { result = x; result->cp++; } @@ -2229,7 +2199,7 @@ static REMatchState *simpleMatch(REGlobalData *gData, REMatchState *x, case REOP_UCFLAT1i: matchCh = GET_ARG(pc); pc += ARG_LEN; - if ((x->cp != gData->cpend) && (upcase(*x->cp) == upcase(matchCh))) { + if (x->cp != gData->cpend && upcase(*x->cp) == upcase(matchCh)) { result = x; result->cp++; } @@ -2241,10 +2211,10 @@ static REMatchState *simpleMatch(REGlobalData *gData, REMatchState *x, charSet = &gData->regexp->classList[index]; JS_ASSERT(charSet->converted); ch = *x->cp; - index = ch / 8; - if ((charSet->length != 0) && - ( (ch <= charSet->length) - && ((charSet->u.bits[index] & (1 << (ch & 0x7))) != 0) )) { + index = ch >> 3; + if (charSet->length != 0 && + ch <= charSet->length && + (charSet->u.bits[index] & (1 << (ch & 0x7)))) { result = x; result->cp++; } @@ -2257,17 +2227,19 @@ static REMatchState *simpleMatch(REGlobalData *gData, REMatchState *x, charSet = &gData->regexp->classList[index]; JS_ASSERT(charSet->converted); ch = *x->cp; - index = ch / 8; - if ((charSet->length == 0) || - ( (ch > charSet->length) - || ((charSet->u.bits[index] & (1 << (ch & 0x7))) == 0) )) { + index = ch >> 3; + if (charSet->length == 0 || + ch > charSet->length || + !(charSet->u.bits[index] & (1 << (ch & 0x7)))) { result = x; result->cp++; } } break; + default: + JS_ASSERT(JS_FALSE); } - if (result != NULL) { + if (result) { if (update) *startpc = pc; else @@ -2279,9 +2251,9 @@ static REMatchState *simpleMatch(REGlobalData *gData, REMatchState *x, } static REMatchState * -executeREBytecode(REGlobalData *gData, REMatchState *x) +ExecuteREBytecode(REGlobalData *gData, REMatchState *x) { - REMatchState *result; + REMatchState *result = NULL; REBackTrackData *backTrackData; intN offset; jsbytecode *nextpc; @@ -2297,38 +2269,35 @@ executeREBytecode(REGlobalData *gData, REMatchState *x) JSBool anchor; jsbytecode *pc = gData->regexp->program; - REOp op = (REOp)(*pc++); + REOp op = (REOp) *pc++; /* - * If the first node is a simple match, step the index into - * the string until that match is made, or fail if it can't be - * found at all. + * If the first node is a simple match, step the index into the string + * until that match is made, or fail if it can't be found at all. */ if (REOP_IS_SIMPLE(op)) { anchor = JS_FALSE; while (x->cp <= gData->cpend) { nextpc = pc; /* reset back to start each time */ - result = simpleMatch(gData, x, op, &nextpc, JS_TRUE); + result = SimpleMatch(gData, x, op, &nextpc, JS_TRUE); if (result) { anchor = JS_TRUE; x = result; pc = nextpc; /* accept skip to next opcode */ - op = (REOp)(*pc++); + op = (REOp) *pc++; break; } - else { - gData->skipped++; - x->cp++; - } + gData->skipped++; + x->cp++; } if (!anchor) return NULL; } while (JS_TRUE) { - if (REOP_IS_SIMPLE(op)) - result = simpleMatch(gData, x, op, &pc, JS_TRUE); - else { + if (REOP_IS_SIMPLE(op)) { + result = SimpleMatch(gData, x, op, &pc, JS_TRUE); + } else { curState = &gData->stateStack[gData->stateStackTop]; switch (op) { case REOP_EMPTY: @@ -2349,14 +2318,14 @@ executeREBytecode(REGlobalData *gData, REMatchState *x) charSet = &gData->regexp->classList[k]; if (!charSet->converted) - if (!processCharSet(gData, charSet)) + if (!ProcessCharSet(gData, charSet)) return NULL; matchCh1 = *x->cp; - k = matchCh1 / 8; + k = matchCh1 >> 3; if ((charSet->length == 0 || matchCh1 > charSet->length || - (charSet->u.bits[k] & (1 << (matchCh1 & 0x7))) == 0) - ^ charSet->sense) { + !(charSet->u.bits[k] & (1 << (matchCh1 & 0x7)))) ^ + charSet->sense) { goto doAlt; } } @@ -2370,153 +2339,134 @@ executeREBytecode(REGlobalData *gData, REMatchState *x) pc += ARG_LEN; matchCh2 = GET_ARG(pc); pc += ARG_LEN; - if ((x->cp == gData->cpend) - || ((*x->cp != matchCh1) && (*x->cp != matchCh2))) { + if (x->cp == gData->cpend || + (*x->cp != matchCh1 && *x->cp != matchCh2)) { result = NULL; break; } /* else false thru... */ case REOP_ALT: -doAlt: + doAlt: nextpc = pc + GET_OFFSET(pc); /* start of next alternate */ pc += ARG_LEN; /* start of this alternate */ curState->parenSoFar = parenSoFar; - ++gData->stateStackTop; - if (gData->stateStackTop == gData->maxStateStack) - if (!reallocStateStack(gData)) - return NULL; - op = (REOp)(*pc++); + PUSH_STATE_STACK(gData); + op = (REOp) *pc++; startcp = x->cp; if (REOP_IS_SIMPLE(op)) { - if (!simpleMatch(gData, x, op, &pc, JS_TRUE)) { - op = (REOp)(*nextpc++); + if (!SimpleMatch(gData, x, op, &pc, JS_TRUE)) { + op = (REOp) *nextpc++; pc = nextpc; continue; } - else { /* accept the match and move on */ - result = x; - op = (REOp)(*pc++); - } + result = x; + op = (REOp) *pc++; } - nextop = (REOp)(*nextpc++); - if (!pushBackTrackState(gData, nextop, nextpc, x, startcp, 0, 0)) + nextop = (REOp) *nextpc++; + if (!PushBackTrackState(gData, nextop, nextpc, x, startcp, 0, 0)) return NULL; continue; /* - * Occurs at (succesful) end of REOP_ALT, + * Occurs at (succesful) end of REOP_ALT, */ case REOP_JUMP: --gData->stateStackTop; offset = GET_OFFSET(pc); pc += offset; - op = (REOp)(*pc++); + op = (REOp) *pc++; continue; - + /* - * Occurs at last (succesful) end of REOP_ALT, + * Occurs at last (succesful) end of REOP_ALT, */ case REOP_ENDALT: --gData->stateStackTop; - op = (REOp)(*pc++); + op = (REOp) *pc++; continue; - + case REOP_LPAREN: parenIndex = GET_ARG(pc); - if ((parenIndex + 1) > parenSoFar) + if (parenIndex + 1 > parenSoFar) parenSoFar = parenIndex + 1; pc += ARG_LEN; x->parens[parenIndex].index = x->cp - gData->cpbegin; x->parens[parenIndex].length = 0; - op = (REOp)(*pc++); + op = (REOp) *pc++; continue; case REOP_RPAREN: parenIndex = GET_ARG(pc); pc += ARG_LEN; cap = &x->parens[parenIndex]; cap->length = x->cp - (gData->cpbegin + cap->index); - op = (REOp)(*pc++); + op = (REOp) *pc++; continue; case REOP_ASSERT: nextpc = pc + GET_OFFSET(pc); /* start of term after ASSERT */ pc += ARG_LEN; /* start of ASSERT child */ - op = (REOp)(*pc++); - if (REOP_IS_SIMPLE(op) - && !simpleMatch(gData, x, op, &pc, JS_FALSE)) { + op = (REOp) *pc++; + if (REOP_IS_SIMPLE(op) && + !SimpleMatch(gData, x, op, &pc, JS_FALSE)) { result = NULL; break; } - else { - curState->u.assertion.top - = (char *)gData->backTrackSP - - (char *)gData->backTrackStack; - curState->u.assertion.sz = gData->cursz; - curState->index = x->cp - gData->cpbegin; - curState->parenSoFar = parenSoFar; - ++gData->stateStackTop; - if (gData->stateStackTop == gData->maxStateStack) - if (!reallocStateStack(gData)) - return NULL; - if (!pushBackTrackState(gData, REOP_ASSERTTEST, - nextpc, x, x->cp, 0, 0)) - return NULL; + curState->u.assertion.top = + (char *)gData->backTrackSP - (char *)gData->backTrackStack; + curState->u.assertion.sz = gData->cursz; + curState->index = x->cp - gData->cpbegin; + curState->parenSoFar = parenSoFar; + PUSH_STATE_STACK(gData); + if (!PushBackTrackState(gData, REOP_ASSERTTEST, + nextpc, x, x->cp, 0, 0)) { + return NULL; } continue; case REOP_ASSERT_NOT: nextpc = pc + GET_OFFSET(pc); pc += ARG_LEN; - op = (REOp)(*pc++); - if (REOP_IS_SIMPLE(op) - /* Note - fail to fail! */ - && simpleMatch(gData, x, op, &pc, JS_FALSE)) { + op = (REOp) *pc++; + if (REOP_IS_SIMPLE(op) /* Note - fail to fail! */ && + SimpleMatch(gData, x, op, &pc, JS_FALSE)) { result = NULL; break; } - else { - curState->u.assertion.top - = (char *)gData->backTrackSP - - (char *)gData->backTrackStack; - curState->u.assertion.sz = gData->cursz; - curState->index = x->cp - gData->cpbegin; - curState->parenSoFar = parenSoFar; - ++gData->stateStackTop; - if (gData->stateStackTop == gData->maxStateStack) - if (!reallocStateStack(gData)) - return NULL; - if (!pushBackTrackState(gData, REOP_ASSERTNOTTEST, - nextpc, x, x->cp, 0, 0)) - return NULL; - } + curState->u.assertion.top + = (char *)gData->backTrackSP + - (char *)gData->backTrackStack; + curState->u.assertion.sz = gData->cursz; + curState->index = x->cp - gData->cpbegin; + curState->parenSoFar = parenSoFar; + PUSH_STATE_STACK(gData); + if (!PushBackTrackState(gData, REOP_ASSERTNOTTEST, + nextpc, x, x->cp, 0, 0)) + return NULL; continue; case REOP_ASSERTTEST: --gData->stateStackTop; --curState; x->cp = gData->cpbegin + curState->index; - gData->backTrackSP - = (REBackTrackData *)((char *)gData->backTrackStack - + curState->u.assertion.top); + gData->backTrackSP = + (REBackTrackData *) ((char *)gData->backTrackStack + + curState->u.assertion.top); gData->cursz = curState->u.assertion.sz; - if (result != NULL) + if (result) result = x; break; case REOP_ASSERTNOTTEST: --gData->stateStackTop; --curState; x->cp = gData->cpbegin + curState->index; - gData->backTrackSP - = (REBackTrackData *)((char *)gData->backTrackStack - + curState->u.assertion.top); + gData->backTrackSP = + (REBackTrackData *) ((char *)gData->backTrackStack + + curState->u.assertion.top); gData->cursz = curState->u.assertion.sz; - if (result == NULL) - result = x; - else - result = NULL; + result = (!result) ? x : NULL; break; case REOP_END: - if (x != NULL) + if (x) return x; break; @@ -2537,19 +2487,19 @@ doAlt: pc += ARG_LEN; curState->u.quantifier.max = GET_ARG(pc); pc += ARG_LEN; -quantcommon: + quantcommon: if (curState->u.quantifier.max == 0) { pc = pc + GET_OFFSET(pc); - op = (REOp)(*pc++); + op = (REOp) *pc++; result = x; continue; } /* Step over */ nextpc = pc + ARG_LEN; - op = (REOp)(*nextpc++); + op = (REOp) *nextpc++; startcp = x->cp; if (REOP_IS_SIMPLE(op)) { - if (!simpleMatch(gData, x, op, &nextpc, JS_TRUE)) { + if (!SimpleMatch(gData, x, op, &nextpc, JS_TRUE)) { if (curState->u.quantifier.min == 0) result = x; else @@ -2557,23 +2507,19 @@ quantcommon: pc = pc + GET_OFFSET(pc); break; } - else { - op = (REOp)(*nextpc++); - result = x; - } + op = (REOp) *nextpc++; + result = x; } curState->index = startcp - gData->cpbegin; curState->continue_op = REOP_REPEAT; curState->continue_pc = pc; curState->parenSoFar = parenSoFar; - ++gData->stateStackTop; - if (gData->stateStackTop == gData->maxStateStack) - if (!reallocStateStack(gData)) - return NULL; - if (curState->u.quantifier.min == 0) - if (!pushBackTrackState(gData, REOP_REPEAT, - pc, x, startcp, 0, 0)) - return NULL; + PUSH_STATE_STACK(gData); + if (curState->u.quantifier.min == 0 && + !PushBackTrackState(gData, REOP_REPEAT, pc, x, startcp, + 0, 0)) { + return NULL; + } pc = nextpc; continue; @@ -2584,72 +2530,59 @@ quantcommon: case REOP_REPEAT: --curState; -repeatAgain: - --gData->stateStackTop; - if (result == NULL) { - /* - * There's been a failure, see if we have enough children. - */ - if (curState->u.quantifier.min == 0) { - result = x; - goto repeatDone; + do { + --gData->stateStackTop; + if (!result) { + /* Failed, see if we have enough children. */ + if (curState->u.quantifier.min == 0) + goto repeatDone; + goto break_switch; } - break; - } - else { - if ((curState->u.quantifier.min == 0) - && (x->cp == gData->cpbegin + curState->index)) { + if (curState->u.quantifier.min == 0 && + x->cp == gData->cpbegin + curState->index) { /* matched an empty string, that'll get us nowhere */ result = NULL; - break; + goto break_switch; } - if (curState->u.quantifier.min != 0) + if (curState->u.quantifier.min != 0) curState->u.quantifier.min--; - if (curState->u.quantifier.max != (uint16)(-1)) + if (curState->u.quantifier.max != (uint16) -1) curState->u.quantifier.max--; - if (curState->u.quantifier.max == 0) { - result = x; + if (curState->u.quantifier.max == 0) goto repeatDone; - } nextpc = pc + ARG_LEN; - nextop = (REOp)(*nextpc); + nextop = (REOp) *nextpc; startcp = x->cp; if (REOP_IS_SIMPLE(nextop)) { nextpc++; - if (!simpleMatch(gData, x, nextop, &nextpc, JS_TRUE)) { - if (curState->u.quantifier.min == 0) { - result = x; + if (!SimpleMatch(gData, x, nextop, &nextpc, JS_TRUE)) { + if (curState->u.quantifier.min == 0) goto repeatDone; - } - else - result = NULL; - break; + result = NULL; + goto break_switch; } result = x; } curState->index = startcp - gData->cpbegin; - ++gData->stateStackTop; - if (gData->stateStackTop == gData->maxStateStack) - if (!reallocStateStack(gData)) - return NULL; - if (curState->u.quantifier.min == 0) - if (!pushBackTrackState(gData, REOP_REPEAT, - pc, x, startcp, - curState->parenSoFar, - parenSoFar - - curState->parenSoFar)) - return NULL; - if (*nextpc == REOP_ENDCHILD) - goto repeatAgain; - pc = nextpc; - op = (REOp)(*pc++); - parenSoFar = curState->parenSoFar; - } - continue; -repeatDone: - pc = pc + GET_OFFSET(pc); - break; - + PUSH_STATE_STACK(gData); + if (curState->u.quantifier.min == 0 && + !PushBackTrackState(gData, REOP_REPEAT, + pc, x, startcp, + curState->parenSoFar, + parenSoFar - + curState->parenSoFar)) { + return NULL; + } + } while (*nextpc == REOP_ENDCHILD); + pc = nextpc; + op = (REOp) *pc++; + parenSoFar = curState->parenSoFar; + continue; + + repeatDone: + result = x; + pc += GET_OFFSET(pc); + goto break_switch; case REOP_MINIMALSTAR: curState->u.quantifier.min = 0; @@ -2668,27 +2601,23 @@ repeatDone: pc += ARG_LEN; curState->u.quantifier.max = GET_ARG(pc); pc += ARG_LEN; -minimalquantcommon: + minimalquantcommon: curState->index = x->cp - gData->cpbegin; curState->parenSoFar = parenSoFar; - ++gData->stateStackTop; - if (gData->stateStackTop == gData->maxStateStack) - if (!reallocStateStack(gData)) - return NULL; + PUSH_STATE_STACK(gData); if (curState->u.quantifier.min != 0) { curState->continue_op = REOP_MINIMALREPEAT; curState->continue_pc = pc; /* step over */ pc += ARG_LEN; - op = (REOp)(*pc++); - } - else { - if (!pushBackTrackState(gData, REOP_MINIMALREPEAT, + op = (REOp) *pc++; + } else { + if (!PushBackTrackState(gData, REOP_MINIMALREPEAT, pc, x, x->cp, 0, 0)) return NULL; --gData->stateStackTop; pc = pc + GET_OFFSET(pc); - op = (REOp)(*pc++); + op = (REOp) *pc++; } continue; @@ -2696,120 +2625,102 @@ minimalquantcommon: --gData->stateStackTop; --curState; - if (result == NULL) { - /* + if (!result) { + /* * Non-greedy failure - try to consume another child. */ - if ((curState->u.quantifier.max == (uint16)(-1)) - || (curState->u.quantifier.max > 0)) { + if (curState->u.quantifier.max == (uint16) -1 || + curState->u.quantifier.max > 0) { curState->index = x->cp - gData->cpbegin; curState->continue_op = REOP_MINIMALREPEAT; curState->continue_pc = pc; pc += ARG_LEN; for (k = curState->parenSoFar; k < parenSoFar; k++) x->parens[k].index = -1; - ++gData->stateStackTop; - if (gData->stateStackTop == gData->maxStateStack) - if (!reallocStateStack(gData)) - return NULL; - op = (REOp)(*pc++); + PUSH_STATE_STACK(gData); + op = (REOp) *pc++; continue; } - else { - /* Don't need to adjust pc since we're going to pop. */ - break; - } + /* Don't need to adjust pc since we're going to pop. */ + break; } - else { - if ((curState->u.quantifier.min == 0) - && (x->cp == gData->cpbegin + curState->index)) { - /* Matched an empty string, that'll get us nowhere. */ - result = NULL; - break; - } - if (curState->u.quantifier.min != 0) - curState->u.quantifier.min--; - if (curState->u.quantifier.max != (uint16)(-1)) - curState->u.quantifier.max--; - if (curState->u.quantifier.min != 0) { - curState->continue_op = REOP_MINIMALREPEAT; - curState->continue_pc = pc; - pc += ARG_LEN; - for (k = curState->parenSoFar; k < parenSoFar; k++) - x->parens[k].index = -1; - curState->index = x->cp - gData->cpbegin; - ++gData->stateStackTop; - if (gData->stateStackTop == gData->maxStateStack) - if (!reallocStateStack(gData)) - return NULL; - op = (REOp)(*pc++); - continue; - } - else { - curState->index = x->cp - gData->cpbegin; - curState->parenSoFar = parenSoFar; - ++gData->stateStackTop; - if (gData->stateStackTop == gData->maxStateStack) - if (!reallocStateStack(gData)) - return NULL; - if (!pushBackTrackState(gData, REOP_MINIMALREPEAT, - pc, x, x->cp, - curState->parenSoFar, - parenSoFar - - curState->parenSoFar)) - return NULL; - --gData->stateStackTop; - pc = pc + GET_OFFSET(pc); - op = (REOp)(*pc++); - continue; - } + if (curState->u.quantifier.min == 0 && + x->cp == gData->cpbegin + curState->index) { + /* Matched an empty string, that'll get us nowhere. */ + result = NULL; + break; } + if (curState->u.quantifier.min != 0) + curState->u.quantifier.min--; + if (curState->u.quantifier.max != (uint16) -1) + curState->u.quantifier.max--; + if (curState->u.quantifier.min != 0) { + curState->continue_op = REOP_MINIMALREPEAT; + curState->continue_pc = pc; + pc += ARG_LEN; + for (k = curState->parenSoFar; k < parenSoFar; k++) + x->parens[k].index = -1; + curState->index = x->cp - gData->cpbegin; + PUSH_STATE_STACK(gData); + op = (REOp) *pc++; + continue; + } + curState->index = x->cp - gData->cpbegin; + curState->parenSoFar = parenSoFar; + PUSH_STATE_STACK(gData); + if (!PushBackTrackState(gData, REOP_MINIMALREPEAT, + pc, x, x->cp, + curState->parenSoFar, + parenSoFar + - curState->parenSoFar)) + return NULL; + --gData->stateStackTop; + pc = pc + GET_OFFSET(pc); + op = (REOp) *pc++; + continue; default: JS_ASSERT(JS_FALSE); result = NULL; } + break_switch:; } /* * If the match failed and there's a backtrack option, take it. * Otherwise this is a complete and utter failure. */ - if (result == NULL) { - if (gData->cursz > 0) { - backTrackData = gData->backTrackSP; - gData->cursz = backTrackData->sz; - gData->backTrackSP - = (REBackTrackData *)((char *)backTrackData - - backTrackData->sz); - x->cp = backTrackData->cp; - pc = backTrackData->backtrack_pc; - op = backTrackData->backtrack_op; - gData->stateStackTop = backTrackData->precedingStateTop; - JS_ASSERT(gData->stateStackTop); - - memcpy(gData->stateStack, backTrackData + 1, - sizeof(REProgState) * backTrackData->precedingStateTop); - curState = &gData->stateStack[gData->stateStackTop - 1]; - - if (backTrackData->parenCount) { - memcpy(&x->parens[backTrackData->parenIndex], - (char *)(backTrackData + 1) + sizeof(REProgState) * backTrackData->precedingStateTop, - sizeof(RECapture) * backTrackData->parenCount); - parenSoFar = backTrackData->parenIndex + backTrackData->parenCount; - } - else { - for (k = curState->parenSoFar; k < parenSoFar; k++) - x->parens[k].index = -1; - parenSoFar = curState->parenSoFar; - } - continue; - } - else + if (!result) { + if (gData->cursz == 0) return NULL; + backTrackData = gData->backTrackSP; + gData->cursz = backTrackData->sz; + gData->backTrackSP = + (REBackTrackData *) ((char *)backTrackData - backTrackData->sz); + x->cp = backTrackData->cp; + pc = backTrackData->backtrack_pc; + op = backTrackData->backtrack_op; + gData->stateStackTop = backTrackData->precedingStateTop; + JS_ASSERT(gData->stateStackTop); + + memcpy(gData->stateStack, backTrackData + 1, + sizeof(REProgState) * backTrackData->precedingStateTop); + curState = &gData->stateStack[gData->stateStackTop - 1]; + + if (backTrackData->parenCount) { + memcpy(&x->parens[backTrackData->parenIndex], + (char *)(backTrackData + 1) + + sizeof(REProgState) * backTrackData->precedingStateTop, + sizeof(RECapture) * backTrackData->parenCount); + parenSoFar = backTrackData->parenIndex + backTrackData->parenCount; + } else { + for (k = curState->parenSoFar; k < parenSoFar; k++) + x->parens[k].index = -1; + parenSoFar = curState->parenSoFar; + } + continue; } - else - x = result; - + x = result; + /* * Continue with the expression. */ @@ -2826,7 +2737,7 @@ MatchRegExp(REGlobalData *gData, REMatchState *x) const jschar *cp2; uintN j; - /* + /* * Have to include the position beyond the last character * in order to detect end-of-input/line condition. */ @@ -2835,7 +2746,7 @@ MatchRegExp(REGlobalData *gData, REMatchState *x) x->cp = cp2; for (j = 0; j < gData->regexp->parenCount; j++) x->parens[j].index = -1; - result = executeREBytecode(gData, x); + result = ExecuteREBytecode(gData, x); if (!gData->ok || result) return result; gData->backTrackSP = gData->backTrackStack; @@ -2848,15 +2759,15 @@ MatchRegExp(REGlobalData *gData, REMatchState *x) static REMatchState * -initMatch(JSContext *cx, REGlobalData *gData, JSRegExp *re) +InitMatch(JSContext *cx, REGlobalData *gData, JSRegExp *re) { REMatchState *result; uintN i; - + gData->maxBackTrack = INITIAL_BACKTRACK; - JS_ARENA_ALLOCATE_CAST(gData->backTrackStack, REBackTrackData *, - &gData->pool, - INITIAL_BACKTRACK); + JS_ARENA_ALLOCATE_CAST(gData->backTrackStack, REBackTrackData *, + &gData->pool, + INITIAL_BACKTRACK); if (!gData->backTrackStack) return NULL; gData->backTrackSP = gData->backTrackStack; @@ -2864,8 +2775,8 @@ initMatch(JSContext *cx, REGlobalData *gData, JSRegExp *re) gData->maxStateStack = INITIAL_STATESTACK; - JS_ARENA_ALLOCATE_CAST(gData->stateStack, REProgState *, - &gData->pool, + JS_ARENA_ALLOCATE_CAST(gData->stateStack, REProgState *, + &gData->pool, sizeof(REProgState) * INITIAL_STATESTACK); if (!gData->stateStack) return NULL; @@ -2875,16 +2786,16 @@ initMatch(JSContext *cx, REGlobalData *gData, JSRegExp *re) gData->regexp = re; gData->ok = JS_TRUE; - JS_ARENA_ALLOCATE_CAST(result, REMatchState *, - &gData->pool, - sizeof(REMatchState) + JS_ARENA_ALLOCATE_CAST(result, REMatchState *, + &gData->pool, + sizeof(REMatchState) + (re->parenCount - 1) * sizeof(RECapture)); if (!result) return NULL; for (i = 0; i < re->classCount; i++) if (!re->classList[i].converted) - if (!processCharSet(gData, &re->classList[i])) + if (!ProcessCharSet(gData, &re->classList[i])) return NULL; return result; @@ -2907,7 +2818,7 @@ js_ExecuteRegExp(JSContext *cx, JSRegExp *re, JSString *str, size_t *indexp, JSString *parstr, *matchstr; JSObject *obj; - RECapture *parsub; + RECapture *parsub = NULL; /* * It's safe to load from cp because JSStrings have a zero at the end, @@ -2925,7 +2836,7 @@ js_ExecuteRegExp(JSContext *cx, JSRegExp *re, JSString *str, size_t *indexp, gData.skipped = 0; JS_InitArenaPool(&gData.pool, "RegExpPool", 8096, 4); - x = initMatch(cx, &gData, re); + x = InitMatch(cx, &gData, re); if (!x) return JS_FALSE; x->cp = cp; @@ -2935,7 +2846,9 @@ js_ExecuteRegExp(JSContext *cx, JSRegExp *re, JSString *str, size_t *indexp, * whether testing or not. On match, return an extended Array object. */ result = MatchRegExp(&gData, x); - if (!(ok = gData.ok)) goto out; + ok = gData.ok; + if (!ok) + goto out; if (!result) { *rval = JSVAL_NULL; goto out; @@ -2993,17 +2906,16 @@ js_ExecuteRegExp(JSContext *cx, JSRegExp *re, JSString *str, size_t *indexp, res = &cx->regExpStatics; res->input = str; res->parenCount = re->parenCount; - if (re->parenCount == 0) + if (re->parenCount == 0) { res->lastParen = js_EmptySubString; - else { + } else { for (num = 0; num < re->parenCount; num++) { parsub = &result->parens[num]; if (num < 9) { if (parsub->index == -1) { res->parens[num].chars = NULL; res->parens[num].length = 0; - } - else { + } else { res->parens[num].chars = gData.cpbegin + parsub->index; res->parens[num].length = parsub->length; } @@ -3012,12 +2924,13 @@ js_ExecuteRegExp(JSContext *cx, JSRegExp *re, JSString *str, size_t *indexp, morepar = res->moreParens; if (!morepar) { res->moreLength = 10; - morepar = (JSSubString*) JS_malloc(cx, - 10 * sizeof(JSSubString)); + morepar = (JSSubString*) + JS_malloc(cx, 10 * sizeof(JSSubString)); } else if (morenum >= res->moreLength) { res->moreLength += 10; - morepar = (JSSubString*) JS_realloc(cx, morepar, - res->moreLength * sizeof(JSSubString)); + morepar = (JSSubString*) + JS_realloc(cx, morepar, res->moreLength * + sizeof(JSSubString)); } if (!morepar) { cx->newborn[GCX_OBJECT] = NULL; @@ -3029,20 +2942,19 @@ js_ExecuteRegExp(JSContext *cx, JSRegExp *re, JSString *str, size_t *indexp, if (parsub->index == -1) { morepar[morenum].chars = NULL; morepar[morenum].length = 0; - } - else { + } else { morepar[morenum].chars = gData.cpbegin + parsub->index; morepar[morenum].length = parsub->length; } } if (test) continue; - if (parsub->index == -1) + if (parsub->index == -1) { ok = js_DefineProperty(cx, obj, INT_TO_JSVAL(num + 1), JSVAL_VOID, NULL, NULL, JSPROP_ENUMERATE, NULL); - else { - parstr = js_NewStringCopyN(cx, gData.cpbegin + parsub->index, + } else { + parstr = js_NewStringCopyN(cx, gData.cpbegin + parsub->index, parsub->length, 0); if (!parstr) { cx->newborn[GCX_OBJECT] = NULL; @@ -3061,10 +2973,8 @@ js_ExecuteRegExp(JSContext *cx, JSRegExp *re, JSString *str, size_t *indexp, } } if (parsub->index == -1) { - res->lastParen.chars = NULL; - res->lastParen.length = 0; - } - else { + res->lastParen = js_EmptySubString; + } else { res->lastParen.chars = gData.cpbegin + parsub->index; res->lastParen.length = parsub->length; } @@ -3516,7 +3426,7 @@ regexp_compile(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, obj2 = JSVAL_TO_OBJECT(argv[0]); if (obj2 && OBJ_GET_CLASS(cx, obj2) == &js_RegExpClass) { if (argc >= 2 && !JSVAL_IS_VOID(argv[1])) { /* 'flags' passed */ - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, + JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_NEWREGEXP_FLAGGED); return JS_FALSE; } @@ -3528,7 +3438,7 @@ regexp_compile(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, } re = js_NewRegExp(cx, NULL, re->source, re->flags, JS_FALSE); JS_UNLOCK_OBJ(cx, obj2); - goto madeit; + goto created; } } str = js_ValueToString(cx, argv[0]); @@ -3547,7 +3457,7 @@ regexp_compile(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, } } re = js_NewRegExpOpt(cx, NULL, str, opt, JS_FALSE); -madeit: +created: if (!re) return JS_FALSE; JS_LOCK_OBJ(cx, obj); @@ -3666,7 +3576,8 @@ RegExp(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) * (regexp_compile detects the regexp + flags case and throws a * TypeError.) See 10.15.3.1. */ - if ((argc < 2 || JSVAL_IS_VOID(argv[1])) && JSVAL_IS_OBJECT(argv[0]) && + if ((argc < 2 || JSVAL_IS_VOID(argv[1])) && + JSVAL_IS_OBJECT(argv[0]) && OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(argv[0])) == &js_RegExpClass) { *rval = argv[0]; return JS_TRUE;