⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jsregexp.c

📁 Swfdec still is development software, but has also followed a rigid no-crashes-allowed policy. I b
💻 C
📖 第 1 页 / 共 5 页
字号:
                                            JUMP, <end> ... 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) {            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, <end>, uch1, uch2, <next>, ...,                                            JUMP, <end> ... 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) {            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, <end>, uch1, uch2, <next>, ...,                                          JUMP, <end> ... ENDALT */            state->progLength += 13;        }        else            /* ALT, <next>, ..., JUMP, <end> ... ENDALT */            state->progLength += 7;        break;    case REOP_CONCAT:        result = operandStack[operandSP - 2];        while (result->next)            result = result->next;        result->next = operandStack[operandSP - 1];        break;    case REOP_ASSERT:    case REOP_ASSERT_NOT:    case REOP_LPARENNON:    case REOP_LPAREN:        /* These should have been processed by a close paren. */        js_ReportCompileErrorNumber(state->context, state->tokenStream,                                    NULL, JSREPORT_ERROR,                                    JSMSG_MISSING_PAREN, opData->errPos);        return JS_FALSE;    default:;    }    return JS_TRUE;}/* * Parser forward declarations. */static JSBool ParseTerm(CompilerState *state);static JSBool ParseQuantifier(CompilerState *state);/* * Top-down regular expression grammar, based closely on Perl4. * *  regexp:     altern                  A regular expression is one or more *              altern '|' regexp       alternatives separated by vertical bar. */#define INITIAL_STACK_SIZE  128static JSBoolParseRegExp(CompilerState *state){    uint16 parenIndex;    RENode *operand;    REOpData *operatorStack;    RENode **operandStack;    REOp op;    intN i;    JSBool result = JS_FALSE;    intN operatorSP = 0, operatorStackSize = INITIAL_STACK_SIZE;    intN operandSP = 0, operandStackSize = INITIAL_STACK_SIZE;    /* Watch out for empty regexp */    if (state->cp == state->cpend) {        state->result = NewRENode(state, REOP_EMPTY);        return (state->result != NULL);    }    operatorStack = (REOpData *)        JS_malloc(state->context, sizeof(REOpData) * operatorStackSize);    if (!operatorStack)        return JS_FALSE;    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 one or more             * operands, the regexp must have the form /x|/ or some such, with             * left parentheses making us short more than one operand.             */            if (operatorSP >= operandSP) {                operand = NewRENode(state, REOP_EMPTY);                if (!operand)                    goto out;                goto pushOperand;            }        } else {            switch (*state->cp) {                /* balance '(' */            case '(':           /* balance ')' */                ++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, <next>, ... ASSERTTEST */                        state->progLength += 4;                        break;                    case '!':                        op = REOP_ASSERT_NOT;                        /* ASSERTNOT, <next>, ... ASSERTNOTTEST */                        state->progLength += 4;                        break;                    default:                        op = REOP_LPARENNON;                        break;                    }                    state->cp += 2;                } else {                    op = REOP_LPAREN;                    /* LPAREN, <index>, ... RPAREN, <index> */                    state->progLength += 6;                    state->parenCount++;                    if (state->parenCount == 65535) {                        js_ReportCompileErrorNumber(state->context,                                                    state->tokenStream,                                                    NULL, JSREPORT_ERROR,                                                    JSMSG_TOO_MANY_PARENS);                        goto out;                    }                }                goto pushOperator;            case ')':                /* If there's not a stacked open parenthesis, throw                 * a syntax error.                 */                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;                    }                }                /* fall thru... */            case '|':                /* Expected an operand before these, so make an empty one */                operand = NewRENode(state, REOP_EMPTY);                if (!operand)                    goto out;                goto pushOperand;            default:                if (!ParseTerm(state))                    goto out;                operand = state->result;pushOperand:                if (operandSP == operandStackSize) {                    operandStackSize += operandStackSize;                    operandStack =                      (RENode **)JS_realloc(state->context, operandStack,                                            sizeof(RENode *) * operandStackSize);                    if (!operandStack)                        goto out;                }                operandStack[operandSP++] = operand;                break;            }        }            /* At the end; process remaining operators */restartOperator:        if (state->cp == state->cpend) {            while (operatorSP) {                --operatorSP;                if (!ProcessOp(state, &operatorStack[operatorSP],                               operandStack, operandSP))                    goto out;                --operandSP;            }            JS_ASSERT(operandSP == 1);            state->result = operandStack[0];            result = JS_TRUE;            goto out;        }        switch (*state->cp) {        case '|':            /* Process any stacked 'concat' operators */            ++state->cp;            while (operatorSP &&                   operatorStack[operatorSP - 1].op == REOP_CONCAT) {                --operatorSP;                if (!ProcessOp(state, &operatorStack[operatorSP],                               operandStack, operandSP))                    goto out;                --operandSP;            }            op = REOP_ALT;            goto pushOperator;        case ')':            /* If there's not a stacked open parenthesis,we             * accept the close as a flat.             */            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;                }            }            ++state->cp;            /* process everything on the stack until the open */            while (JS_TRUE) {                JS_ASSERT(operatorSP);                --operatorSP;                switch (operatorStack[operatorSP].op) {                case REOP_ASSERT:                case REOP_ASSERT_NOT:                case REOP_LPAREN:                    operand = NewRENode(state, operatorStack[operatorSP].op);                    if (!operand)                        goto out;                    operand->u.parenIndex =                        operatorStack[operatorSP].parenIndex;                    JS_ASSERT(operandSP);                    operand->kid = operandStack[operandSP - 1];                    operandStack[operandSP - 1] = operand;                    ++state->treeDepth;                    /* fall thru... */                case REOP_LPARENNON:                    state->result = operandStack[operandSP - 1];                    if (!ParseQuantifier(state))                        goto out;                    operandStack[operandSP - 1] = state->result;                    goto restartOperator;                default:                    if (!ProcessOp(state, &operatorStack[operatorSP],                                   operandStack, operandSP))                        goto out;                    --operandSP;                    break;                }            }            break;        case '+':        case '*':        case '?':        case '{':            js_ReportCompileErrorNumber(state->context, state->tokenStream,                                        NULL, JSREPORT_ERROR,                                        JSMSG_BAD_QUANTIFIER, state->cp);            result = JS_FALSE;            goto out;        default:            /* Anything else is the start of the next term */            op = REOP_CONCAT;pushOperator:            if (operatorSP == operatorStackSize) {                operatorStackSize += operatorStackSize;                operatorStack =                    (REOpData *)JS_realloc(state->context, operatorStack,                                           sizeof(REOpData) * operatorStackSize);                if (!operatorStack)                    goto out;            }            operatorStack[operatorSP].op = op;            operatorStack[operatorSP].errPos = state->cp;            operatorStack[operatorSP++].parenIndex = parenIndex;            break;        }    }out:    if (operatorStack)        JS_free(state->context, operatorStack);    if (operandStack)        JS_free(state->context, operandStack);    return result;}/* * Hack two bits in CompilerState.flags, for use within FindParenCount to flag * its being on the stack, and to propagate errors to its callers. */#define JSREG_FIND_PAREN_COUNT  0x8000#define JSREG_FIND_PAREN_ERROR  0x4000/* * Magic return value from FindParenCount and GetDecimalValue, to indicate * overflow beyond GetDecimalValue's max parameter, or a computed maximum if * its findMax parameter is non-null. */#define OVERFLOW_VALUE          ((uintN)-1)static uintNFindParenCount(CompilerState *state){    CompilerState temp;    int i;    if (state->flags & JSREG_FIND_PAREN_COUNT)        return OVERFLOW_VALUE;    /*     * Copy state into temp, flag it so we never report an invalid backref,     * and reset its members to parse the entire regexp.  This is obviously     * suboptimal, but GetDecimalValue calls us only if a backref appears to     * refer to a forward parenthetical, which is rare.     */    temp = *state;    temp.flags |= JSREG_FIND_PAREN_COUNT;    temp.cp = temp.cpbegin;    temp.parenCount = 0;    temp.classCount = 0;    temp.progLength = 0;    temp.treeDepth = 0;    for (i = 0; i < CLASS_CACHE_SIZE; i++)        temp.classCache[i].start = NULL;    if (!ParseRegExp(&temp)) {        state->flags |= JSREG_FIND_PAREN_ERROR;        return OVERFLOW_VALUE;    }    return temp.parenCount;}/* * Extract and return a decimal value at state->cp.  The initial character c * has already been read.  Return OVERFLOW_VALUE if the result exceeds max. * Callers who pass a non-null findMax should test JSREG_FIND_PAREN_ERROR in * state->flags to discover whether an error occurred under findMax. */static uintNGetDecimalValue(jschar c, uintN max, uintN (*findMax)(CompilerState *state),                CompilerState *state){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -