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

📄 jsopcode.c

📁 Swfdec still is development software, but has also followed a rigid no-crashes-allowed policy. I b
💻 C
📖 第 1 页 / 共 5 页
字号:
    '\r', 'r',    '\t', 't',    '\v', 'v',    '"',  '"',    '\'', '\'',    '\\', '\\',    0};static char *QuoteString(Sprinter *sp, JSString *str, jschar quote){    ptrdiff_t off, len, nb;    const jschar *s, *t, *u, *z;    char *bp;    jschar c;    JSBool ok;    /* Sample off first for later return value pointer computation. */    off = sp->offset;    if (quote && Sprint(sp, "%c", (char)quote) < 0)        return NULL;    /* Loop control variables: z points at end of string sentinel. */    s = JSSTRING_CHARS(str);    z = s + JSSTRING_LENGTH(str);    for (t = s; t < z; s = ++t) {        /* Move t forward from s past un-quote-worthy characters. */        c = *t;        while (JS_ISPRINT(c) && c != quote && c != '\\' && !(c >> 8)) {            c = *++t;            if (t == z)                break;        }        len = PTRDIFF(t, s, jschar);        /* Allocate space for s, including the '\0' at the end. */        nb = (sp->offset + len + 1) - sp->size;        if (nb > 0 && !SprintAlloc(sp, nb))            return NULL;        /* Advance sp->offset and copy s into sp's buffer. */        bp = sp->base + sp->offset;        sp->offset += len;        while (--len >= 0)            *bp++ = (char) *s++;        *bp = '\0';        if (t == z)            break;        /* Use js_EscapeMap, \u, or \x only if necessary. */        if ((u = js_strchr(js_EscapeMap, c)) != NULL)            ok = Sprint(sp, "\\%c", (char)u[1]) >= 0;        else            ok = Sprint(sp, (c >> 8) ? "\\u%04X" : "\\x%02X", c) >= 0;        if (!ok)            return NULL;    }    /* Sprint the closing quote and return the quoted string. */    if (quote && Sprint(sp, "%c", (char)quote) < 0)        return NULL;    return OFF2STR(sp, off);}JSString *js_QuoteString(JSContext *cx, JSString *str, jschar quote){    void *mark;    Sprinter sprinter;    char *bytes;    JSString *escstr;    mark = JS_ARENA_MARK(&cx->tempPool);    INIT_SPRINTER(cx, &sprinter, &cx->tempPool, 0);    bytes = QuoteString(&sprinter, str, quote);    escstr = bytes ? JS_NewStringCopyZ(cx, bytes) : NULL;    JS_ARENA_RELEASE(&cx->tempPool, mark);    return escstr;}/************************************************************************/struct JSPrinter {    Sprinter        sprinter;       /* base class state */    JSArenaPool     pool;           /* string allocation pool */    uintN           indent;         /* indentation in spaces */    JSPackedBool    pretty;         /* pretty-print: indent, use newlines */    JSPackedBool    grouped;        /* in parenthesized expression context */    JSScript        *script;        /* script being printed */    JSScope         *scope;         /* script function scope */};/* * Hack another flag, a la JS_DONT_PRETTY_PRINT, into uintN indent parameters * to functions such as js_DecompileFunction and js_NewPrinter.  This time, as * opposed to JS_DONT_PRETTY_PRINT back in the dark ages, we can assume that a * uintN is at least 32 bits. */#define JS_IN_GROUP_CONTEXT 0x10000JSPrinter *js_NewPrinter(JSContext *cx, const char *name, uintN indent, JSBool pretty){    JSPrinter *jp;    JSStackFrame *fp;    JSObjectMap *map;    jp = (JSPrinter *) JS_malloc(cx, sizeof(JSPrinter));    if (!jp)        return NULL;    INIT_SPRINTER(cx, &jp->sprinter, &jp->pool, 0);    JS_InitArenaPool(&jp->pool, name, 256, 1);    jp->indent = indent & ~JS_IN_GROUP_CONTEXT;    jp->pretty = pretty;    jp->grouped = (indent & JS_IN_GROUP_CONTEXT) != 0;    jp->script = NULL;    jp->scope = NULL;    fp = cx->fp;    if (fp && fp->fun && fp->fun->object) {        map = fp->fun->object->map;        if (MAP_IS_NATIVE(map))            jp->scope = (JSScope *)map;    }    return jp;}voidjs_DestroyPrinter(JSPrinter *jp){    JS_FinishArenaPool(&jp->pool);    JS_free(jp->sprinter.context, jp);}JSString *js_GetPrinterOutput(JSPrinter *jp){    JSContext *cx;    JSString *str;    cx = jp->sprinter.context;    if (!jp->sprinter.base)        return cx->runtime->emptyString;    str = JS_NewStringCopyZ(cx, jp->sprinter.base);    if (!str)        return NULL;    JS_FreeArenaPool(&jp->pool);    INIT_SPRINTER(cx, &jp->sprinter, &jp->pool, 0);    return str;}intjs_printf(JSPrinter *jp, const char *format, ...){    va_list ap;    char *bp, *fp;    int cc;    if (*format == '\0')        return 0;    va_start(ap, format);    /* If pretty-printing, expand magic tab into a run of jp->indent spaces. */    if (*format == '\t') {        if (jp->pretty && Sprint(&jp->sprinter, "%*s", jp->indent, "") < 0)            return -1;        format++;    }    /* Suppress newlines (must be once per format, at the end) if not pretty. */    fp = NULL;    if (!jp->pretty && format[cc = strlen(format)-1] == '\n') {        fp = JS_strdup(jp->sprinter.context, format);        if (!fp)            return -1;        fp[cc] = '\0';        format = fp;    }    /* Allocate temp space, convert format, and put. */    bp = JS_vsmprintf(format, ap);	/* XXX vsaprintf */    if (fp) {        JS_free(jp->sprinter.context, fp);        format = NULL;    }    if (!bp) {        JS_ReportOutOfMemory(jp->sprinter.context);        return -1;    }    cc = strlen(bp);    if (SprintPut(&jp->sprinter, bp, (size_t)cc) < 0)        cc = -1;    free(bp);    va_end(ap);    return cc;}JSBooljs_puts(JSPrinter *jp, const char *s){    return SprintPut(&jp->sprinter, s, strlen(s)) >= 0;}/************************************************************************/typedef struct SprintStack {    Sprinter    sprinter;       /* sprinter for postfix to infix buffering */    ptrdiff_t   *offsets;       /* stack of postfix string offsets */    jsbytecode  *opcodes;       /* parallel stack of JS opcodes */    uintN       top;            /* top of stack index */    JSPrinter   *printer;       /* permanent output goes here */} SprintStack;/* Gap between stacked strings to allow for insertion of parens and commas. */#define PAREN_SLOP	(2 + 1)/* * These pseudo-ops help js_DecompileValueGenerator decompile JSOP_SETNAME, * JSOP_SETPROP, and JSOP_SETELEM, respectively.  See the first assertion in * PushOff. */#define JSOP_GETPROP2   254#define JSOP_GETELEM2   255static JSBoolPushOff(SprintStack *ss, ptrdiff_t off, JSOp op){    uintN top;#if JSOP_LIMIT > JSOP_GETPROP2#error JSOP_LIMIT must be <= JSOP_GETPROP2#endif    if (!SprintAlloc(&ss->sprinter, PAREN_SLOP))        return JS_FALSE;    /* ss->top points to the next free slot; be paranoid about overflow. */    top = ss->top;    JS_ASSERT(top < ss->printer->script->depth);    if (top >= ss->printer->script->depth) {        JS_ReportOutOfMemory(ss->sprinter.context);        return JS_FALSE;    }    /* The opcodes stack must contain real bytecodes that index js_CodeSpec. */    ss->offsets[top] = off;    ss->opcodes[top] = (op == JSOP_GETPROP2) ? JSOP_GETPROP                     : (op == JSOP_GETELEM2) ? JSOP_GETELEM                     : (jsbytecode) op;    ss->top = ++top;    ss->sprinter.offset += PAREN_SLOP;    return JS_TRUE;}static ptrdiff_tPopOff(SprintStack *ss, JSOp op){    uintN top;    const JSCodeSpec *cs, *topcs;    ptrdiff_t off;    /* ss->top points to the next free slot; be paranoid about underflow. */    top = ss->top;    JS_ASSERT(top != 0);    if (top == 0)        return 0;    ss->top = --top;    topcs = &js_CodeSpec[ss->opcodes[top]];    cs = &js_CodeSpec[op];    if (topcs->prec != 0 && topcs->prec < cs->prec) {        ss->offsets[top] -= 2;        ss->sprinter.offset = ss->offsets[top];        off = Sprint(&ss->sprinter, "(%s)",                     OFF2STR(&ss->sprinter, ss->sprinter.offset + 2));    } else {        off = ss->sprinter.offset = ss->offsets[top];    }    return off;}#if JS_HAS_SWITCH_STATEMENTtypedef struct TableEntry {    jsval       key;    ptrdiff_t   offset;    JSAtom      *label;    jsint       order;          /* source order for stable tableswitch sort */} TableEntry;static intCompareOffsets(const void *v1, const void *v2, void *arg){    const TableEntry *te1 = (const TableEntry *) v1,                     *te2 = (const TableEntry *) v2;    if (te1->offset == te2->offset)        return (int) (te1->order - te2->order);    return (int) (te1->offset - te2->offset);}static JSBoolDecompile(SprintStack *ss, jsbytecode *pc, intN nb);static JSBoolDecompileSwitch(SprintStack *ss, TableEntry *table, uintN tableLength,                jsbytecode *pc, ptrdiff_t switchLength,                ptrdiff_t defaultOffset, JSBool isCondSwitch){    JSContext *cx;    JSPrinter *jp;    char *lval, *rval;    uintN i;    ptrdiff_t diff, off, off2, caseExprOff;    jsval key;    JSString *str;    cx = ss->sprinter.context;    jp = ss->printer;    lval = OFF2STR(&ss->sprinter, PopOff(ss, JSOP_NOP));    js_printf(jp, "\tswitch (%s) {\n", lval);    if (tableLength) {        diff = table[0].offset - defaultOffset;        if (diff > 0) {            jp->indent += 2;            js_printf(jp, "\tdefault:\n");            jp->indent += 2;            if (!Decompile(ss, pc + defaultOffset, diff))                return JS_FALSE;            jp->indent -= 4;        }        caseExprOff = isCondSwitch                      ? (ptrdiff_t) js_CodeSpec[JSOP_CONDSWITCH].length                      : 0;        for (i = 0; i < tableLength; i++) {            off = table[i].offset;            off2 = (i + 1 < tableLength) ? table[i + 1].offset : switchLength;            key = table[i].key;            if (isCondSwitch) {                ptrdiff_t nextCaseExprOff;                /*                 * key encodes the JSOP_CASE bytecode's offset from switchtop.                 * The next case expression follows immediately, unless we are                 * at the last case.                 */                nextCaseExprOff = (ptrdiff_t)JSVAL_TO_INT(key);                nextCaseExprOff += js_CodeSpec[pc[nextCaseExprOff]].length;                jp->indent += 2;                if (!Decompile(ss, pc + caseExprOff,                               nextCaseExprOff - caseExprOff)) {                    return JS_FALSE;                }                caseExprOff = nextCaseExprOff;            } else {                /*                 * key comes from an atom, not the decompiler, so we need to                 * quote it if it's a string literal.  But if table[i].label                 * is non-null, key was constant-propagated and label is the                 * name of the const we should show as the case label.  We set                 * key to undefined so this identifier is escaped, if required                 * by non-ASCII characters, but not quoted, by QuoteString.                 */                if (table[i].label) {                    str = ATOM_TO_STRING(table[i].label);                    key = JSVAL_VOID;                } else {                    str = js_ValueToString(cx, key);                    if (!str)                        return JS_FALSE;                }                rval = QuoteString(&ss->sprinter, str,                                   JSVAL_IS_STRING(key) ? (jschar)'"' : 0);                if (!rval)

⌨️ 快捷键说明

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