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

📄 jsopcode.c

📁 一个基于alice开发的机器人
💻 C
📖 第 1 页 / 共 5 页
字号:
                }
                jp->indent -= 2;
                js_printf(jp, "\tdefault:\n");
                jp->indent += 2;
            }
            if (!Decompile(ss, pc + off, off2 - off))
                return JS_FALSE;
            jp->indent -= 4;
        }
    }

    if (defaultOffset == switchLength) {
        jp->indent += 2;
        js_printf(jp, "\tdefault:\n");
        jp->indent -= 2;
    }
    js_printf(jp, "\t}\n");
    return JS_TRUE;
}
#endif

static JSAtom *
GetSlotAtom(JSPrinter *jp, JSPropertyOp getter, uintN slot)
{
    JSScope *scope;
    JSScopeProperty *sprop;
    JSObject *obj, *proto;

    scope = jp->scope;
    while (scope) {
        for (sprop = SCOPE_LAST_PROP(scope); sprop; sprop = sprop->parent) {
            if (sprop->getter != getter)
                continue;
            JS_ASSERT(sprop->flags & SPROP_HAS_SHORTID);
            JS_ASSERT(!JSVAL_IS_INT(sprop->id));
            if ((uintN) sprop->shortid == slot)
                return (JSAtom *) sprop->id;
        }
        obj = scope->object;
        if (!obj)
            break;
        proto = OBJ_GET_PROTO(jp->sprinter.context, obj);
        if (!proto)
            break;
        scope = OBJ_SCOPE(proto);
    }
    return NULL;
}

static const char *
VarPrefix(jssrcnote *sn)
{
    const char *kw;
    static char buf[8];

    kw = NULL;
    if (sn) {
        if (SN_TYPE(sn) == SRC_VAR)
            kw = js_var_str;
        else if (SN_TYPE(sn) == SRC_CONST)
            kw = js_const_str;
    }
    if (!kw)
        return "";
    JS_snprintf(buf, sizeof buf, "%s ", kw);
    return buf;
}

static JSBool
Decompile(SprintStack *ss, jsbytecode *pc, intN nb)
{
    JSContext *cx;
    JSPrinter *jp, *jp2;
    jsbytecode *endpc, *done, *forelem_tail, *forelem_done;
    ptrdiff_t len, todo, oplen, cond, next, tail;
    JSOp op, lastop, saveop;
    const JSCodeSpec *cs, *topcs;
    jssrcnote *sn, *sn2;
    const char *lval, *rval, *xval, *fmt;
    jsint i, argc;
    char **argv;
    JSAtom *atom;
    JSObject *obj;
    JSFunction *fun;
    JSString *str;
    JSBool ok;
    jsval val;

/*
 * Local macros
 */
#define DECOMPILE_CODE(pc,nb)	if (!Decompile(ss, pc, nb)) return JS_FALSE
#define POP_STR()		OFF2STR(&ss->sprinter, PopOff(ss, op))
#define LOCAL_ASSERT(expr)	JS_ASSERT(expr); if (!(expr)) return JS_FALSE

/*
 * Get atom from script's atom map, quote/escape its string appropriately into
 * rval, and select fmt from the quoted and unquoted alternatives.
 */
#define GET_ATOM_QUOTE_AND_FMT(qfmt, ufmt, rval)                              \
    JS_BEGIN_MACRO                                                            \
        jschar quote_;                                                        \
        atom = GET_ATOM(cx, jp->script, pc);                                  \
        if (ATOM_KEYWORD(atom)) {                                             \
            quote_ = '\'';                                                    \
            fmt = qfmt;                                                       \
        } else {                                                              \
            quote_ = 0;                                                       \
            fmt = ufmt;                                                       \
        }                                                                     \
        rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), quote_);      \
        if (!rval)                                                            \
            return JS_FALSE;                                                  \
    JS_END_MACRO

    cx = ss->sprinter.context;
    jp = ss->printer;
    endpc = pc + nb;
    forelem_tail = forelem_done = NULL;
    todo = -2;			/* NB: different from Sprint() error return. */
    tail = -1;
    op = JSOP_NOP;
    sn = NULL;
    rval = NULL;

    while (pc < endpc) {
        lastop = op;
        op = saveop = (JSOp) *pc;
        if (op >= JSOP_LIMIT) {
            switch (op) {
              case JSOP_GETPROP2:
                saveop = JSOP_GETPROP;
                break;
              case JSOP_GETELEM2:
                saveop = JSOP_GETELEM;
                break;
              default:;
            }
        }
        cs = &js_CodeSpec[saveop];
        len = oplen = cs->length;

        if (cs->token) {
            switch (cs->nuses) {
              case 2:
                rval = POP_STR();
                lval = POP_STR();
                sn = js_GetSrcNote(jp->script, pc);
                if (sn && SN_TYPE(sn) == SRC_ASSIGNOP) {
                    /* Print only the right operand of the assignment-op. */
                    todo = SprintPut(&ss->sprinter, rval, strlen(rval));
                } else {
                    todo = Sprint(&ss->sprinter, "%s %s %s",
                                  lval, cs->token, rval);
                }
                break;

              case 1:
                rval = POP_STR();
                todo = Sprint(&ss->sprinter, "%s%s", cs->token, rval);
                break;

              case 0:
#if JS_HAS_GETTER_SETTER
                if (op == JSOP_GETTER || op == JSOP_SETTER) {
                    todo = -2;
                    break;
                }
#endif
                todo = SprintPut(&ss->sprinter, cs->token, strlen(cs->token));
                break;

              default:
                todo = -2;
                break;
            }
        } else {
            switch (op) {
              case JSOP_NOP:
                /*
                 * Check for a do-while loop, a for-loop with an empty
                 * initializer part, a labeled statement, a function
                 * definition, or try/finally.
                 */
                sn = js_GetSrcNote(jp->script, pc);
                todo = -2;
                switch (sn ? SN_TYPE(sn) : SRC_NULL) {
#if JS_HAS_DO_WHILE_LOOP
                  case SRC_WHILE:
                    js_printf(jp, "\tdo {\n");
                    jp->indent += 4;
                    break;
#endif /* JS_HAS_DO_WHILE_LOOP */

                  case SRC_FOR:
                    rval = "";

                  do_forloop:
                    /* Skip the JSOP_NOP or JSOP_POP bytecode. */
                    pc++;

                    /* Get the cond, next, and loop-closing tail offsets. */
                    cond = js_GetSrcNoteOffset(sn, 0);
                    next = js_GetSrcNoteOffset(sn, 1);
                    tail = js_GetSrcNoteOffset(sn, 2);
                    LOCAL_ASSERT(tail + GetJumpOffset(pc+tail, pc+tail) == 0);

                    /* Print the keyword and the possibly empty init-part. */
                    js_printf(jp, "\tfor (%s;", rval);

                    if (pc[cond] == JSOP_IFEQ || pc[cond] == JSOP_IFEQX) {
                        /* Decompile the loop condition. */
                        DECOMPILE_CODE(pc, cond);
                        js_printf(jp, " %s", POP_STR());
                    }

                    /* Need a semicolon whether or not there was a cond. */
                    js_puts(jp, ";");

                    if (pc[next] != JSOP_GOTO && pc[next] != JSOP_GOTOX) {
                        /* Decompile the loop updater. */
                        DECOMPILE_CODE(pc + next, tail - next - 1);
                        js_printf(jp, " %s", POP_STR());
                    }

                    /* Do the loop body. */
                    js_puts(jp, ") {\n");
                    jp->indent += 4;
                    oplen = (cond) ? js_CodeSpec[pc[cond]].length : 0;
                    DECOMPILE_CODE(pc + cond + oplen, next - cond - oplen);
                    jp->indent -= 4;
                    js_printf(jp, "\t}\n");

                    /* Set len so pc skips over the entire loop. */
                    len = tail + js_CodeSpec[pc[tail]].length;
                    break;

                  case SRC_LABEL:
                    atom = js_GetAtom(cx, &jp->script->atomMap,
                                      (jsatomid) js_GetSrcNoteOffset(sn, 0));
                    jp->indent -= 4;
                    rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
                    if (!rval)
                        return JS_FALSE;
                    RETRACT(&ss->sprinter, rval);
                    js_printf(jp, "\t%s:\n", rval);
                    jp->indent += 4;
                    break;

                  case SRC_LABELBRACE:
                    atom = js_GetAtom(cx, &jp->script->atomMap,
                                      (jsatomid) js_GetSrcNoteOffset(sn, 0));
                    rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
                    if (!rval)
                        return JS_FALSE;
                    RETRACT(&ss->sprinter, rval);
                    js_printf(jp, "\t%s: {\n", rval);
                    jp->indent += 4;
                    break;

                  case SRC_ENDBRACE:
                    jp->indent -= 4;
                    js_printf(jp, "\t}\n");
                    break;

                  case SRC_CATCH:
                    jp->indent -= 4;
                    sn = js_GetSrcNote(jp->script, pc);
                    pc += oplen;
                    js_printf(jp, "\t} catch (");

                    LOCAL_ASSERT(*pc == JSOP_NAME);
                    pc += js_CodeSpec[JSOP_NAME].length;
                    LOCAL_ASSERT(*pc == JSOP_PUSHOBJ);
                    pc += js_CodeSpec[JSOP_PUSHOBJ].length;
                    LOCAL_ASSERT(*pc == JSOP_NEWINIT);
                    pc += js_CodeSpec[JSOP_NEWINIT].length;
                    LOCAL_ASSERT(*pc == JSOP_EXCEPTION);
                    pc += js_CodeSpec[JSOP_EXCEPTION].length;
                    LOCAL_ASSERT(*pc == JSOP_INITCATCHVAR);
                    atom = GET_ATOM(cx, jp->script, pc);
                    rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), 0);
                    if (!rval)
                        return JS_FALSE;
                    RETRACT(&ss->sprinter, rval);
                    js_printf(jp, "%s", rval);
                    pc += js_CodeSpec[JSOP_INITCATCHVAR].length;
                    LOCAL_ASSERT(*pc == JSOP_ENTERWITH);
                    pc += js_CodeSpec[JSOP_ENTERWITH].length;

                    len = js_GetSrcNoteOffset(sn, 0);
                    if (len) {
                        js_printf(jp, " if ");
                        DECOMPILE_CODE(pc, len);
                        js_printf(jp, "%s", POP_STR());
                        pc += len;
                        LOCAL_ASSERT(*pc == JSOP_IFEQ || *pc == JSOP_IFEQX);
                        pc += js_CodeSpec[*pc].length;
                    }

                    js_printf(jp, ") {\n");
                    jp->indent += 4;
                    len = 0;
                    break;

                  case SRC_FUNCDEF:
                    atom = js_GetAtom(cx, &jp->script->atomMap,
                                      (jsatomid) js_GetSrcNoteOffset(sn, 0));
                    JS_ASSERT(ATOM_IS_OBJECT(atom));
                  do_function:
                    obj = ATOM_TO_OBJECT(atom);
                    fun = (JSFunction *) JS_GetPrivate(cx, obj);
                    jp2 = js_NewPrinter(cx, JS_GetFunctionName(fun),
                                        jp->indent, jp->pretty);
                    if (!jp2)
                        return JS_FALSE;
                    jp2->scope = jp->scope;
                    if (js_DecompileFunction(jp2, fun)) {
                        str = js_GetPrinterOutput(jp2);
                        if (str)
                            js_printf(jp, "%s\n", JS_GetStringBytes(str));
                    }
                    js_DestroyPrinter(jp2);
                    break;

                  default:;
                }
              case JSOP_RETRVAL:
                break;

              case JSOP_GROUP:
                /* Use last real op so PopOff adds parens if needed. */
                todo = PopOff(ss, lastop);

                /* Now add user-supplied parens only if PopOff did not. */
                cs    = &js_CodeSpec[lastop];
                topcs = &js_CodeSpec[ss->opcodes[ss->top]];
                if (topcs->prec >= cs->prec) {
                    todo = Sprint(&ss->sprinter, "(%s)",
                                  OFF2STR(&ss->sprinter, todo));
                }
                break;

              case JSOP_PUSH:
              case JSOP_PUSHOBJ:
              case JSOP_BINDNAME:
                todo = Sprint(&ss->sprinter, "");
                break;

#if JS_HAS_EXCEPTIONS
              case JSOP_TRY:
                js_printf(jp, "\ttry {\n");
                jp->indent += 4;
                todo = -2;
                break;

            {
              static const char finally_cookie[] = "finally-cookie";

              case JSOP_FINALLY:
                jp->indent -= 4;
                js_printf(jp, "\t} finally {\n");
                jp->indent += 4;

                /*
                 * We must push an empty string placeholder for gosub's return
                 * address, popped by JSOP_RETSUB and counted by script->depth
                 * but not by ss->top (see JSOP_SETSP, below).
                 */
                todo = Sprint(&ss->sprinter, finally_cookie);
                break;

              case JSOP_RETSUB:
                rval = POP_STR();
                LOCAL_ASSERT(strcmp(rval, finally_cookie) == 0);

⌨️ 快捷键说明

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