if (!numStr) { JS_ReportOutOfMemory(cx); return JS_FALSE; } todo = Sprint(&ss->sprinter, numStr); } else if (JSVAL_IS_STRING(key)) { rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), (jschar)'"'); if (!rval) return JS_FALSE; todo = Sprint(&ss->sprinter, "%s", rval); } else if (JSVAL_IS_OBJECT(key)) { #if JS_HAS_LEXICAL_CLOSURE if (JSVAL_IS_FUNCTION(cx, key)) goto do_closure; #endif str = js_ValueToString(cx, key); if (!str) return JS_FALSE; todo = SprintPut(&ss->sprinter, JS_GetStringBytes(str), str->length); } else { todo = -2; } break;
if (!numStr) { JS_ReportOutOfMemory(cx); return JS_FALSE; } todo = Sprint(&ss->sprinter, numStr); } break;  case JSOP_STRING: atom = GET_ATOM(cx, jp->script, pc); rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom), (jschar)'"'); if (!rval) return JS_FALSE; todo = Sprint(&ss->sprinter, "%s", rval); break;  case JSOP_OBJECT: case JSOP_ANONFUNOBJ: case JSOP_NAMEDFUNOBJ: atom = GET_ATOM(cx, jp->script, pc); str = js_ValueToSource(cx, ATOM_KEY(atom)); if (!str) return JS_FALSE; todo = SprintPut(&ss->sprinter, JS_GetStringBytes(str), str->length); break;
Decompile(SprintStack *ss, jsbytecode *pc, intN nb){    JSContext *cx;    JSPrinter *jp;    jsbytecode *endpc, *done, *forelem2_done;    ptrdiff_t len, todo, oplen, cond, next, tail;    JSOp op, lastop, saveop;    JSCodeSpec *cs, *topcs;    jssrcnote *sn;    const char *lval, *rval = NULL, *xval;    jsint i, argc;    char **argv;    JSAtom *atom;    JSString *str;    JSBool ok;    jsval key;/* * 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    cx = ss->sprinter.context;    jp = ss->printer;    endpc = pc + nb;    todo = -2;			/* NB: different from Sprint() error return. */    op = JSOP_NOP;    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();		if ((sn = js_GetSrcNote(jp->script, pc)) != NULL &&		    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 extra user parenthesization, 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) {		  case SRC_PAREN:		    /* 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;#if JS_HAS_DO_WHILE_LOOP		  case SRC_WHILE:		    js_printf(jp, "\tdo {\n");	/* balance} */		    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 + GET_JUMP_OFFSET(pc + tail) == 0);		    /* Print the keyword and the possibly empty init-part. */		    js_printf(jp, "\tfor (%s;", rval);		    if (pc[cond] == JSOP_IFEQ) {			/* 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) {			/* 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;		    js_printf(jp, "\t%s:\n", ATOM_BYTES(atom));		    jp->indent += 4;		    break;		  case SRC_LABELBRACE:		    atom = js_GetAtom(cx, &jp->script->atomMap,				      (jsatomid) js_GetSrcNoteOffset(sn, 0));		    js_printf(jp, "\t%s: {\n", ATOM_BYTES(atom));		    jp->indent += 4;		    break;		  case SRC_ENDBRACE:		    jp->indent -= 4;		    js_printf(jp, "\t}\n");		    break;		  case SRC_TRYFIN:		    if (js_GetSrcNoteOffset(sn, 0) == 0) {			js_printf(jp, "\ttry {\n");		    } else {			jp->indent -= 4;			js_printf(jp, "\t} finally {\n");		    }		    jp->indent += 4;		    break;		  case SRC_CATCH:		    jp->indent -= 4;		    sn = js_GetSrcNote(jp->script, pc);		    pc += oplen;		    js_printf(jp, "\t} catch ("); /* balance) */		    pc += 6;	/* name Object, pushobj, exception */		    js_printf(jp, "%s",			      ATOM_BYTES(GET_ATOM(cx, jp->script, pc)));		    len = js_GetSrcNoteOffset(sn, 0);		    pc += 4;	/* initprop, enterwith */		    if (len) {			js_printf(jp, " : ");			DECOMPILE_CODE(pc, len - 3); /* don't decompile ifeq */			js_printf(jp, "%s", POP_STR());			pc += len;		    }		    js_printf(jp, ") {\n"); /* balance} */		    jp->indent += 4;		    len = 0;		    break;		  case SRC_FUNCDEF: {		    JSPrinter *jp2;		    JSObject *obj;		    JSFunction *fun;		    atom = js_GetAtom(cx, &jp->script->atomMap,				      (jsatomid) js_GetSrcNoteOffset(sn, 0));		    JS_ASSERT(ATOM_IS_OBJECT(atom));		    obj = ATOM_TO_OBJECT(atom);		    fun = 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:;		}		break;	      case JSOP_PUSH:	      case JSOP_PUSHOBJ:	      case JSOP_BINDNAME:		todo = Sprint(&ss->sprinter, "");		break;#if JS_HAS_EXCEPTIONS	      case JSOP_GOSUB:	      case JSOP_RETSUB:	      case JSOP_SETSP:		todo = -2;		break;	      case JSOP_EXCEPTION:		sn = js_GetSrcNote(jp->script, pc);		if (sn && SN_TYPE(sn) == SRC_HIDDEN)		    todo = -2;		break;#endif /* JS_HAS_EXCEPTIONS */	      case JSOP_POP:	      case JSOP_POPV:		sn = js_GetSrcNote(jp->script, pc);		switch (sn ? SN_TYPE(sn) : SRC_NULL) {		  case SRC_FOR:		    rval = POP_STR();		    todo = -2;		    goto do_forloop;		  case SRC_PCDELTA:		    /* Pop and save to avoid blowing stack depth budget. */		    lval = JS_strdup(cx, POP_STR());		    if (!lval)			return JS_FALSE;		    /*                     * The offset tells distance to the end of the right-hand                     * operand of the comma operator.                     */		    done = pc + len;		    pc += js_GetSrcNoteOffset(sn, 0);		    len = 0;		    if (!Decompile(ss, done, pc - done)) {			JS_free(cx, (char *)lval);			return JS_FALSE;		    }		    /* Pop Decompile result and print comma expression. */		    rval = POP_STR();		    todo = Sprint(&ss->sprinter, "%s, %s", lval, rval);		    JS_free(cx, (char *)lval);		    break;		  case SRC_HIDDEN:		    /* Hide this pop, it's from a goto in a with or for/in. */		    todo = -2;		    break;		  default:		    rval = POP_STR();		    if (*rval != '\0')			js_printf(jp, "\t%s;\n", rval);		    todo = -2;		    break;		}		break;	      case JSOP_POP2:		(void) PopOff(ss, op);		(void) PopOff(ss, op);		todo = -2;		break;	      case JSOP_ENTERWITH:		sn = js_GetSrcNote(jp->script, pc);		todo = -2;		if (sn && SN_TYPE(sn) == SRC_HIDDEN)		    break;		rval = POP_STR();		js_printf(jp, "\twith (%s) {\n", rval);		jp->indent += 4;		break;	      case JSOP_LEAVEWITH:		sn = js_GetSrcNote(jp->script, pc);		todo = -2;		if (sn && SN_TYPE(sn) == SRC_HIDDEN)		    break;		jp->indent -= 4;		js_printf(jp, "\t}\n");		break;	      case JSOP_RETURN:		rval = POP_STR();		if (*rval != '\0')		    js_printf(jp, "\t%s %s;\n", cs->name, rval);		else		    js_printf(jp, "\t%s;\n", cs->name);		todo = -2;		break;#if JS_HAS_EXCEPTIONS	      case JSOP_THROW:		sn = js_GetSrcNote(jp->script, pc);		todo = -2;		if (sn && SN_TYPE(sn) == SRC_HIDDEN)		    break;		rval = POP_STR();		js_printf(jp, "\t%s %s;\n", cs->name, rval);		break;#endif /* JS_HAS_EXCEPTIONS */	      case JSOP_GOTO:		sn = js_GetSrcNote(jp->script, pc);		switch (sn ? SN_TYPE(sn) : SRC_NULL) {		  case SRC_CONT2LABEL:		    atom = js_GetAtom(cx, &jp->script->atomMap,				      (jsatomid) js_GetSrcNoteOffset(sn, 0));		    js_printf(jp, "\tcontinue %s;\n", ATOM_BYTES(atom));		    break;		  case SRC_CONTINUE:		    js_printf(jp, "\tcontinue;\n");		    break;		  case SRC_BREAK2LABEL:		    atom = js_GetAtom(cx, &jp->script->atomMap,				      (jsatomid) js_GetSrcNoteOffset(sn, 0));		    js_printf(jp, "\tbreak %s;\n", ATOM_BYTES(atom));		    break;		  case SRC_HIDDEN:		    break;		  default:		    js_printf(jp, "\tbreak;\n");		    break;		}		todo = -2;		break;	      case JSOP_IFEQ:		len = GET_JUMP_OFFSET(pc);		sn = js_GetSrcNote(jp->script, pc);		switch (sn ? SN_TYPE(sn) : SRC_NULL) {		  case SRC_IF:		  case SRC_IF_ELSE:		    rval = POP_STR();		    js_printf(jp, "\tif (%s) {\n", rval);		    jp->indent += 4;		    if (SN_TYPE(sn) == SRC_IF) {			DECOMPILE_CODE(pc + oplen, len - oplen);		    } else {			DECOMPILE_CODE(pc + oplen,			    len - (oplen + js_CodeSpec[JSOP_GOTO].length));			jp->indent -= 4;			pc += len - oplen;			LOCAL_ASSERT(*pc == JSOP_GOTO);			oplen = js_CodeSpec[JSOP_GOTO].length;			len = GET_JUMP_OFFSET(pc);			js_printf(jp, "\t} else {\n");			jp->indent += 4;			DECOMPILE_CODE(pc + oplen, len - oplen);		    }		    jp->indent -= 4;		    js_printf(jp, "\t}\n");		    todo = -2;		    break;		  case SRC_WHILE:		    rval = POP_STR();		    js_printf(jp, "\twhile (%s) {\n", rval);		    jp->indent += 4;		    DECOMPILE_CODE(pc + oplen,			len - (oplen + js_CodeSpec[JSOP_GOTO].length));		    jp->indent -= 4;		    js_printf(jp, "\t}\n");		    todo = -2;		    break;		  case SRC_COND:		    xval = JS_strdup(cx, POP_STR());		    if (!xval)			return JS_FALSE;		    DECOMPILE_CODE(pc + oplen,			len - (oplen + js_CodeSpec[JSOP_GOTO].length));		    lval = JS_strdup(cx, POP_STR());		    if (!lval) {			JS_free(cx, (void *)xval);			return JS_FALSE;		    }		    pc += len - oplen;		    LOCAL_ASSERT(*pc == JSOP_GOTO);		    oplen = js_CodeSpec[JSOP_GOTO].length;		    len = GET_JUMP_OFFSET(pc);		    DECOMPILE_CODE(pc + oplen, len - oplen);		    rval = POP_STR();		    todo = Sprint(&ss->sprinter, "%s ? %s : %s",				  xval, lval, rval);		    JS_free(cx, (void *)xval);		    JS_free(cx, (void *)lval);		    break;		  default:#if JS_BUG_SHORT_CIRCUIT		    {			/* top is the first clause in a disjunction (||). */			jsbytecode *ifeq;			lval = JS_strdup(cx, POP_STR());			if (!lval)			    return JS_FALSE;			ifeq = pc + len;			LOCAL_ASSERT(pc[oplen] == JSOP_TRUE);			pc += oplen + js_CodeSpec[JSOP_TRUE].length;			LOCAL_ASSERT(*pc == JSOP_GOTO);			oplen = js_CodeSpec[JSOP_GOTO].length;			done = pc + GET_JUMP_OFFSET(pc);			pc += oplen;			DECOMPILE_CODE(pc, done - ifeq);			rval = POP_STR();			todo = Sprint(&ss->sprinter, "%s || %s", lval, rval);			JS_free(cx, (void *)lval);			len = PTRDIFF(done, pc, jsbytecode);		    }#endif /* JS_BUG_SHORT_CIRCUIT */		    break;		}		break;	      case JSOP_IFNE:#if JS_HAS_DO_WHILE_LOOP		/* Check for a do-while loop's upward branch. */		sn = js_GetSrcNote(jp->script, pc);		if (sn && SN_TYPE(sn) == SRC_WHILE) {		    jp->indent -= 4;		    /* {balance: */		    js_printf(jp, "\t} while (%s);\n", POP_STR());		    todo = -2;		    break;		}#endif /* JS_HAS_DO_WHILE_LOOP */#if JS_BUG_SHORT_CIRCUIT		{		    jsbytecode *ifne;		    /* This bytecode is used only for conjunction (&&). */		    lval = JS_strdup(cx, POP_STR());		    if (!lval)			return JS_FALSE;		    ifne = pc + GET_JUMP_OFFSET(pc);		    LOCAL_ASSERT(pc[oplen] == JSOP_FALSE);		    pc += len + js_CodeSpec[JSOP_FALSE].length;		    LOCAL_ASSERT(*pc == JSOP_GOTO);		    oplen = js_CodeSpec[JSOP_GOTO].length;		    done = pc + GET_JUMP_OFFSET(pc);		    pc += oplen;		    DECOMPILE_CODE(pc, done - ifne);		    rval = POP_STR();		    todo = Sprint(&ss->sprinter, "%s && %s", lval, rval);		    JS_free(cx, (void *)lval);		    len = PTRDIFF(done, pc, jsbytecode);		}#endif /* JS_BUG_SHORT_CIRCUIT */		break;#if !JS_BUG_SHORT_CIRCUIT	      case JSOP_OR:		/* Top of stack is the first clause in a disjunction (||). */		lval = JS_strdup(cx, POP_STR());		if (!lval)		    return JS_FALSE;		done = pc + GET_JUMP_OFFSET(pc);		pc += len;		len = PTRDIFF(done, pc, jsbytecode);		DECOMPILE_CODE(pc, len);		rval = POP_STR();		todo = Sprint(&ss->sprinter, "%s || %s", lval, rval);		JS_free(cx, (char *)lval);		break;	      case JSOP_AND:		/* Top of stack is the first clause in a conjunction (&&). */		lval = JS_strdup(cx, POP_STR());		if (!lval)		    return JS_FALSE;		done = pc + GET_JUMP_OFFSET(pc);		pc += len;		len = PTRDIFF(done, pc, jsbytecode);		DECOMPILE_CODE(pc, len);		rval = POP_STR();		todo = Sprint(&ss->sprinter, "%s && %s", lval, rval);		JS_free(cx, (char *)lval);		break;#endif	      case JSOP_FORNAME:		rval = POP_STR();		/* FALL THROUGH */	      case JSOP_FORNAME2:		xval = NULL;		atom = NULL;		lval = ATOM_BYTES(GET_ATOM(cx, jp->script, pc));		sn = js_GetSrcNote(jp->script, pc);		pc += oplen;		goto do_forinloop;	      case JSOP_FORPROP:		rval = POP_STR();		/* FALL THROUGH */	      case JSOP_FORPROP2:		xval = NULL;		atom = GET_ATOM(cx, jp->script, pc);		lval = POP_STR();		sn = NULL;		pc += oplen;		goto do_forinloop;	      case JSOP_FORELEM:		rval = POP_STR();		xval = POP_STR();		atom = NULL;		lval = POP_STR();		sn = NULL;		pc++;	      do_forinloop:		LOCAL_ASSERT(*pc == JSOP_IFEQ);		oplen = js_CodeSpec[JSOP_IFEQ].length;		len = GET_JUMP_OFFSET(pc);              do_forinbody:		js_printf(jp, "\tfor (%s%s", VarPrefix(sn), lval);		if (atom)		    js_printf(jp, ".%s", ATOM_BYTES(atom));		else if (xval)		    js_printf(jp, "[%s]", xval);		if (cs->format & JOF_FOR2)		    rval = OFF2STR(&ss->sprinter, ss->offsets[ss->top-1]);		js_printf(jp, " in %s) {\n", rval);		jp->indent += 4;		DECOMPILE_CODE(pc + oplen,			       len - (oplen + js_CodeSpec[JSOP_GOTO].length));		jp->indent -= 4;		js_printf(jp, "\t}\n");		todo = -2;		break;              case JSOP_FORELEM2:		pc++;		LOCAL_ASSERT(*pc == JSOP_IFEQ);		len = js_CodeSpec[JSOP_IFEQ].length;                /*                 * This gets a little wacky.  Only the length of the for loop                 * body PLUS the element-indexing expression is known here, so                 * we pass it to the immediately following code to decompile                 * JSOP_ENUMELEM via the 'forelem2_done' local.                 */		forelem2_done = pc + GET_JUMP_OFFSET(pc);                break;	      case JSOP_ENUMELEM:		/*		 * The stack has the object under the (top) index expression.		 * The "rval" property id is underneath those two on the stack.		 * The for loop body length can now be adjusted to account for		 * the length of the indexing expression.		 */		atom = NULL;		xval = POP_STR();		lval = POP_STR();		rval = OFF2STR(&ss->sprinter, ss->offsets[ss->top-1]);		len = forelem2_done - pc;		goto do_forinbody;	      case JSOP_DUP2:		rval = OFF2STR(&ss->sprinter, ss->offsets[ss->top-2]);		todo = SprintPut(&ss->sprinter, rval, strlen(rval));		if (todo < 0 || !PushOff(ss, todo, op))		    return JS_FALSE;		/* FALL THROUGH */	      case JSOP_DUP:		rval = OFF2STR(&ss->sprinter, ss->offsets[ss->top-1]);		todo = SprintPut(&ss->sprinter, rval, strlen(rval));		break;	      case JSOP_SETARG:		atom = GetSlotAtom(jp, js_GetArgument, GET_ARGNO(pc));		LOCAL_ASSERT(atom);		goto do_setname;	      case JSOP_SETVAR:		atom = GetSlotAtom(jp, js_GetLocalVariable, GET_VARNO(pc));		LOCAL_ASSERT(atom);		goto do_setname;	      case JSOP_SETCONST:	      case JSOP_SETNAME:		atom = GET_ATOM(cx, jp->script, pc);	      do_setname:		lval = ATOM_BYTES(atom);		rval = POP_STR();		if (op == JSOP_SETNAME)		    (void) PopOff(ss, op);		if ((sn = js_GetSrcNote(jp->script, pc - 1)) != NULL &&		    SN_TYPE(sn) == SRC_ASSIGNOP) {		    todo = Sprint(&ss->sprinter, "%s %s= %s",				  lval, js_CodeSpec[lastop].token, rval);		} else {		    sn = js_GetSrcNote(jp->script, pc);		    todo = Sprint(&ss->sprinter, "%s%s = %s",				  VarPrefix(sn), lval, rval);		}		break;	      case JSOP_NEW:	      case JSOP_CALL:	      case JSOP_EVAL:		saveop = op;		op = JSOP_NOP;           /* turn off parens */		argc = GET_ARGC(pc);		argv = JS_malloc(cx, (size_t)(argc + 1) * sizeof *argv);		if (!argv)		    return JS_FALSE;		ok = JS_TRUE;		for (i = argc; i > 0; i--) {		    argv[i] = JS_strdup(cx, POP_STR());		    if (!argv[i]) {			ok = JS_FALSE;			break;		    }		}		/* Skip the JSOP_PUSHOBJ-created empty string. */		LOCAL_ASSERT(ss->top >= 2);		(void) PopOff(ss, op);		/* Get the callee's decompiled image in argv[0]. */		argv[0] = JS_strdup(cx, POP_STR());		if (!argv[i])		    ok = JS_FALSE;		lval = "(", rval = ")";		if (saveop == JSOP_NEW) {		    todo = Sprint(&ss->sprinter, "%s %s%s",				  js_new_str, argv[0], lval);		} else {		    todo = Sprint(&ss->sprinter, "%s%s",				  argv[0], lval);		}		if (todo < 0)		    ok = JS_FALSE;		for (i = 1; i <= argc; i++) {		    if (!argv[i] ||			Sprint(&ss->sprinter, "%s%s",			       argv[i], (i < argc) ? ", " : "") < 0) {			ok = JS_FALSE;			break;		    }		}		if (Sprint(&ss->sprinter, rval) < 0)		    ok = JS_FALSE;		for (i = 0; i <= argc; i++) {		    if (argv[i])			JS_free(cx, argv[i]);		}		JS_free(cx, argv);		if (!ok)		    return JS_FALSE;		op = saveop;		break;	      case JSOP_DELNAME:		atom = GET_ATOM(cx, jp->script, pc);		lval = ATOM_BYTES(atom);		todo = Sprint(&ss->sprinter, "%s %s", js_delete_str, lval);		break;	      case JSOP_DELPROP:		atom = GET_ATOM(cx, jp->script, pc);		lval = POP_STR();		todo = Sprint(&ss->sprinter, "%s %s.%s",			      js_delete_str, lval, ATOM_BYTES(atom));		break;	      case JSOP_DELELEM:		xval = POP_STR();		lval = POP_STR();		todo = Sprint(&ss->sprinter, "%s %s[%s]",			      js_delete_str, lval, xval);		break;	      case JSOP_TYPEOF:	      case JSOP_VOID:		rval = POP_STR();		todo = Sprint(&ss->sprinter, "%s %s", cs->name, rval);		break;	      case JSOP_INCARG:	      case JSOP_DECARG:		atom = GetSlotAtom(jp, js_GetArgument, GET_ARGNO(pc));		LOCAL_ASSERT(atom);		goto do_incatom;	      case JSOP_INCVAR:	      case JSOP_DECVAR:		atom = GetSlotAtom(jp, js_GetLocalVariable, GET_VARNO(pc));		LOCAL_ASSERT(atom);		goto do_incatom;	      case JSOP_INCNAME:	      case JSOP_DECNAME:		atom = GET_ATOM(cx, jp->script, pc);	      do_incatom:		lval = ATOM_BYTES(atom);		todo = Sprint(&ss->sprinter, "%s%s",			      js_incop_str[!(cs->format & JOF_INC)], lval);		break;	      case JSOP_INCPROP:	      case JSOP_DECPROP:		atom = GET_ATOM(cx, jp->script, pc);		lval = POP_STR();		todo = Sprint(&ss->sprinter, "%s%s.%s",			      js_incop_str[!(cs->format & JOF_INC)],			      lval, ATOM_BYTES(atom));		break;	      case JSOP_INCELEM:	      case JSOP_DECELEM:		xval = POP_STR();		lval = POP_STR();		todo = Sprint(&ss->sprinter, "%s%s[%s]",			      js_incop_str[!(cs->format & JOF_INC)],			      lval, xval);		break;	      case JSOP_ARGINC:	      case JSOP_ARGDEC:		atom = GetSlotAtom(jp, js_GetArgument, GET_ARGNO(pc));		LOCAL_ASSERT(atom);		goto do_atominc;	      case JSOP_VARINC:	      case JSOP_VARDEC:		atom = GetSlotAtom(jp, js_GetLocalVariable, GET_VARNO(pc));		LOCAL_ASSERT(atom);		goto do_atominc;	      case JSOP_NAMEINC:	      case JSOP_NAMEDEC:		atom = GET_ATOM(cx, jp->script, pc);	      do_atominc:		lval = ATOM_BYTES(atom);		todo = Sprint(&ss->sprinter, "%s%s",			      lval, js_incop_str[!(cs->format & JOF_INC)]);		break;	      case JSOP_PROPINC:	      case JSOP_PROPDEC:		atom = GET_ATOM(cx, jp->script, pc);		lval = POP_STR();		todo = Sprint(&ss->sprinter, "%s.%s%s",			      lval, ATOM_BYTES(atom),			      js_incop_str[!(cs->format & JOF_INC)]);		break;	      case JSOP_ELEMINC:	      case JSOP_ELEMDEC:		xval = POP_STR();		lval = POP_STR();		todo = Sprint(&ss->sprinter, "%s[%s]%s",			      lval, xval,			      js_incop_str[!(cs->format & JOF_INC)]);		break;	      case JSOP_GETPROP2:		op = JSOP_GETPROP;		(void) PopOff(ss, lastop);		/* FALL THROUGH */	      case JSOP_GETPROP:		atom = GET_ATOM(cx, jp->script, pc);		lval = POP_STR();		todo = Sprint(&ss->sprinter, "%s.%s", lval, ATOM_BYTES(atom));		break;	      case JSOP_SETPROP:		rval = POP_STR();		atom = GET_ATOM(cx, jp->script, pc);		lval = POP_STR();		if ((sn = js_GetSrcNote(jp->script, pc - 1)) != NULL &&		    SN_TYPE(sn) == SRC_ASSIGNOP) {		    todo = Sprint(&ss->sprinter, "%s.%s %s= %s",				  lval, ATOM_BYTES(atom),				  js_CodeSpec[lastop].token, rval);		} else {		    todo = Sprint(&ss->sprinter, "%s.%s = %s",				  lval, ATOM_BYTES(atom), rval);		}		break;	      case JSOP_GETELEM2:		op = JSOP_GETELEM;		(void) PopOff(ss, lastop);		/* FALL THROUGH */	      case JSOP_GETELEM:		op = JSOP_NOP;           /* turn off parens */		xval = POP_STR();		op = JSOP_GETELEM;		lval = POP_STR();		todo = Sprint(&ss->sprinter, "%s[%s]", lval, xval);		break;	      case JSOP_SETELEM:		op = JSOP_NOP;           /* turn off parens */		rval = POP_STR();		xval = POP_STR();		op = JSOP_SETELEM;		lval = POP_STR();		if ((sn = js_GetSrcNote(jp->script, pc - 1)) != NULL &&		    SN_TYPE(sn) == SRC_ASSIGNOP) {		    todo = Sprint(&ss->sprinter, "%s[%s] %s= %s",				  lval, xval,				  js_CodeSpec[lastop].token, rval);		} else {		    todo = Sprint(&ss->sprinter, "%s[%s] = %s",				  lval, xval, rval);		}		break;	      case JSOP_GETARG:		atom = GetSlotAtom(jp, js_GetArgument, GET_ARGNO(pc));		LOCAL_ASSERT(atom);		goto do_name;	      case JSOP_GETVAR:		atom = GetSlotAtom(jp, js_GetLocalVariable, GET_VARNO(pc));		LOCAL_ASSERT(atom);		goto do_name;	      case JSOP_NAME:		atom = GET_ATOM(cx, jp->script, pc);	      do_name:		sn = js_GetSrcNote(jp->script, pc);		todo = Sprint(&ss->sprinter, "%s%s",			      VarPrefix(sn), ATOM_BYTES(atom));		break;	      case JSOP_UINT16:		i = (jsint) GET_ATOM_INDEX(pc);		todo = Sprint(&ss->sprinter, "%u", (unsigned) i);		break;	      case JSOP_NUMBER:	      case JSOP_STRING:	      case JSOP_OBJECT:	      case JSOP_ANONFUNOBJ:	      case JSOP_NAMEDFUNOBJ:		atom = GET_ATOM(cx, jp->script, pc);		key = ATOM_KEY(atom);		if (JSVAL_IS_INT(key)) {		    long ival = (long)JSVAL_TO_INT(key);		    todo = Sprint(&ss->sprinter, "%ld", ival);		} else if (JSVAL_IS_DOUBLE(key)) {		    char buf[DTOSTR_STANDARD_BUFFER_SIZE];		    char *numStr = JS_dtostr(buf, sizeof buf, DTOSTR_STANDARD,                                             0, *JSVAL_TO_DOUBLE(key));		    if (!numStr) {			JS_ReportOutOfMemory(cx);			return JS_FALSE;		    }		    todo = Sprint(&ss->sprinter, numStr);		} else if (JSVAL_IS_STRING(key)) {		    rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom),				       (jschar)'"');		    if (!rval)			return JS_FALSE;		    todo = Sprint(&ss->sprinter, "%s", rval);		} else if (JSVAL_IS_OBJECT(key)) {#if JS_HAS_LEXICAL_CLOSURE		    if (JSVAL_IS_FUNCTION(cx, key))			goto do_closure;#endif		    str = js_ValueToString(cx, key);		    if (!str)			return JS_FALSE;		    todo = SprintPut(&ss->sprinter,				     JS_GetStringBytes(str),				     str->length);		} else {		    todo = -2;		}		break;#if JS_HAS_SWITCH_STATEMENT	      case JSOP_TABLESWITCH:	      {		jsbytecode *pc2, *end;		ptrdiff_t off, off2;		jsint j, n, low, high;		TableEntry *table;		sn = js_GetSrcNote(jp->script, pc);		JS_ASSERT(sn && SN_TYPE(sn) == SRC_SWITCH);		len = js_GetSrcNoteOffset(sn, 0);		pc2 = pc;		off = GET_JUMP_OFFSET(pc2);		end = pc + off;		pc2 += JUMP_OFFSET_LEN;		low = GET_JUMP_OFFSET(pc2);		pc2 += JUMP_OFFSET_LEN;		high = GET_JUMP_OFFSET(pc2);		n = high - low + 1;		table = JS_malloc(cx, (size_t)n * sizeof *table);		if (!table)		    return JS_FALSE;		if (pc2 + JUMP_OFFSET_LEN + 1 >= end) {		    j = 0;		} else {		    for (i = j = 0; i < n; i++) {			pc2 += JUMP_OFFSET_LEN;			off2 = GET_JUMP_OFFSET(pc2);			if (off2) {			    table[j].key = INT_TO_JSVAL(low + i);			    table[j++].offset = off2;			}		    }		}		js_qsort(table, (size_t)j, sizeof *table, CompareOffsets, NULL);		ok = DecompileSwitch(ss, table, (uintN)j, pc, len, off,				     JS_FALSE);		JS_free(cx, table);		if (!ok)		    return ok;		todo = -2;		break;	      }	      case JSOP_LOOKUPSWITCH:	      {		jsbytecode *pc2;		ptrdiff_t off, off2;		jsint npairs;		TableEntry *table;		sn = js_GetSrcNote(jp->script, pc);		JS_ASSERT(sn && SN_TYPE(sn) == SRC_SWITCH);		len = js_GetSrcNoteOffset(sn, 0);		pc2 = pc;		off = GET_JUMP_OFFSET(pc2);		pc2 += JUMP_OFFSET_LEN;		npairs = (jsint) GET_ATOM_INDEX(pc2);		pc2 += ATOM_INDEX_LEN;		table = JS_malloc(cx, (size_t)npairs * sizeof *table);		if (!table)		    return JS_FALSE;		for (i = 0; i < npairs; i++) {		    atom = GET_ATOM(cx, jp->script, pc2);		    pc2 += ATOM_INDEX_LEN;		    off2 = GET_JUMP_OFFSET(pc2);		    pc2 += JUMP_OFFSET_LEN;		    table[i].key = ATOM_KEY(atom);		    table[i].offset = off2;		}		ok = DecompileSwitch(ss, table, (uintN)npairs, pc, len, off,				     JS_FALSE);		JS_free(cx, table);		if (!ok)		    return ok;		todo = -2;		break;	      }	      case JSOP_CONDSWITCH:	      {		jsbytecode *pc2;		ptrdiff_t off, off2, caseOff;		jsint ncases;		TableEntry *table;		sn = js_GetSrcNote(jp->script, pc);		JS_ASSERT(sn && SN_TYPE(sn) == SRC_SWITCH);		len = js_GetSrcNoteOffset(sn, 0);		off = js_GetSrcNoteOffset(sn, 1);		/*		 * Count the cases using offsets from switch to first case,		 * and case to case, stored in srcnote immediates.		 */		pc2 = pc;		off2 = off;		for (ncases = 0; off2 != 0; ncases++) {		    pc2 += off2;		    JS_ASSERT(*pc2 == JSOP_CASE || *pc2 == JSOP_DEFAULT);		    if (*pc2 == JSOP_DEFAULT) {			/* End of cases, but count default as a case. */			off2 = 0;		    } else {			sn = js_GetSrcNote(jp->script, pc2);			JS_ASSERT(sn && SN_TYPE(sn) == SRC_PCDELTA);			off2 = js_GetSrcNoteOffset(sn, 0);		    }		}		/*		 * Allocate table and rescan the cases using their srcnotes,		 * stashing each case's delta from switch top in table[i].key,		 * and the distance to its statements in table[i].offset.		 */		table = JS_malloc(cx, (size_t)ncases * sizeof *table);		if (!table)		    return JS_FALSE;		pc2 = pc;		off2 = off;		for (i = 0; i < ncases; i++) {		    pc2 += off2;		    JS_ASSERT(*pc2 == JSOP_CASE || *pc2 == JSOP_DEFAULT);		    caseOff = pc2 - pc;		    table[i].key = INT_TO_JSVAL((jsint) caseOff);		    table[i].offset = caseOff + GET_JUMP_OFFSET(pc2);		    if (*pc2 == JSOP_CASE) {			sn = js_GetSrcNote(jp->script, pc2);			JS_ASSERT(sn && SN_TYPE(sn) == SRC_PCDELTA);			off2 = js_GetSrcNoteOffset(sn, 0);		    }		}		/*		 * Find offset of default code by fetching the default offset		 * from the end of table.  JSOP_CONDSWITCH always has a default		 * case at the end.		 */		off = JSVAL_TO_INT(table[ncases-1].key);		pc2 = pc + off;		off += GET_JUMP_OFFSET(pc2);		ok = DecompileSwitch(ss, table, (uintN)ncases, pc, len, off,				     JS_TRUE);		JS_free(cx, table);		if (!ok)		    return ok;		todo = -2;		break;	      }	      case JSOP_CASE:	      {		lval = POP_STR();		if (!lval)		    return JS_FALSE;		js_printf(jp, "\tcase %s:\n", lval);		todo = -2;		break;	      }#endif /* JS_HAS_SWITCH_STATEMENT */#if !JS_BUG_FALLIBLE_EQOPS	      case JSOP_NEW_EQ:	      case JSOP_NEW_NE:		rval = POP_STR();		lval = POP_STR();		todo = Sprint(&ss->sprinter, "%s %c%s %s",			      lval,			      (op == JSOP_NEW_EQ) ? '=' : '!',#if JS_HAS_TRIPLE_EQOPS			      JSVERSION_IS_ECMA(cx->version) ? "==" :#endif			      "=",			      rval);		break;#endif /* !JS_BUG_FALLIBLE_EQOPS */#if JS_HAS_LEXICAL_CLOSURE	      case JSOP_CLOSURE:	      {		JSObject *obj;		JSFunction *fun;		JSPrinter *jp2;		atom = GET_ATOM(cx, jp->script, pc);		JS_ASSERT(ATOM_IS_OBJECT(atom));	      do_closure:		obj = ATOM_TO_OBJECT(atom);		fun = JS_GetPrivate(cx, obj);		jp2 = js_NewPrinter(cx, JS_GetFunctionName(fun), jp->indent,                                    JS_FALSE);		if (!jp2)		    return JS_FALSE;		jp2->scope = jp->scope;		todo = -1;		if (js_DecompileFunction(jp2, fun)) {		    str = js_GetPrinterOutput(jp2);		    if (str) {			todo = SprintPut(&ss->sprinter,					 JS_GetStringBytes(str),					 str->length);		    }		}		js_DestroyPrinter(jp2);		break;	      }#endif /* JS_HAS_LEXICAL_CLOSURE */#if JS_HAS_EXPORT_IMPORT	      case JSOP_EXPORTALL:		js_printf(jp, "\texport *\n");		todo = -2;		break;	      case JSOP_EXPORTNAME:		atom = GET_ATOM(cx, jp->script, pc);		js_printf(jp, "\texport %s\n", ATOM_BYTES(atom));		todo = -2;		break;	      case JSOP_IMPORTALL:		lval = POP_STR();		js_printf(jp, "\timport %s.*\n", lval);		todo = -2;		break;	      case JSOP_IMPORTPROP:		atom = GET_ATOM(cx, jp->script, pc);		lval = POP_STR();		js_printf(jp, "\timport %s.%s\n", lval, ATOM_BYTES(atom));		todo = -2;		break;	      case JSOP_IMPORTELEM:		xval = POP_STR();		op = JSOP_GETELEM;		lval = POP_STR();		js_printf(jp, "\timport %s[%s]\n", lval, xval);		todo = -2;		break;#endif /* JS_HAS_EXPORT_IMPORT */	      case JSOP_TRAP:		op = JS_GetTrapOpcode(cx, jp->script, pc);		if (op == JSOP_LIMIT)		    return JS_FALSE;		*pc = op;		cs = &js_CodeSpec[op];		len = cs->length;		DECOMPILE_CODE(pc, len);		*pc = JSOP_TRAP;		todo = -2;		break;#if JS_HAS_INITIALIZERS	      case JSOP_NEWINIT:		LOCAL_ASSERT(ss->top >= 2);		(void) PopOff(ss, op);		lval = POP_STR();#if JS_HAS_SHARP_VARS		op = (JSOp)pc[len];		if (op == JSOP_DEFSHARP) {		    pc += len;		    cs = &js_CodeSpec[op];		    len = cs->length;		    i = (jsint) GET_ATOM_INDEX(pc);		    todo = Sprint(&ss->sprinter, "#%u=%c",				  (unsigned) i,				  (*lval == 'O') ? '{' : '[');		    /* balance}] */		} else#endif /* JS_HAS_SHARP_VARS */		{		    todo = Sprint(&ss->sprinter, (*lval == 'O') ? "{" : "[");		    /* balance}] */		}		break;	      case JSOP_ENDINIT:		rval = POP_STR();		sn = js_GetSrcNote(jp->script, pc);		todo = Sprint(&ss->sprinter, "%s%s%c",			      rval,			      (sn && SN_TYPE(sn) == SRC_CONTINUE) ? ", " : "",			      /* [balance */			      (*rval == '{') ? '}' : ']');		break;	      case JSOP_INITPROP:		rval = POP_STR();		atom = GET_ATOM(cx, jp->script, pc);		xval = ATOM_BYTES(atom);		lval = POP_STR();	      do_initprop:		todo = Sprint(&ss->sprinter, "%s%s%s%s%s:%s",			      lval,                              (lval[1] != '\0') ? ", " : "",			      xval,                              (lastop == JSOP_GETTER || lastop == JSOP_SETTER)                              ? " " : "",                              (lastop == JSOP_GETTER) ? js_getter_str :                              (lastop == JSOP_SETTER) ? js_setter_str :                              "",                              rval);		break;	      case JSOP_INITELEM:		rval = POP_STR();		xval = POP_STR();		lval = POP_STR();		sn = js_GetSrcNote(jp->script, pc);		if (sn && SN_TYPE(sn) == SRC_LABEL)		    goto do_initprop;		todo = Sprint(&ss->sprinter, "%s%s%s",			      lval,			      (lval[1] != '\0' || *xval != '0') ? ", " : "",			      rval);		break;#if JS_HAS_SHARP_VARS	      case JSOP_DEFSHARP:		i = (jsint) GET_ATOM_INDEX(pc);		rval = POP_STR();		todo = Sprint(&ss->sprinter, "#%u=%s", (unsigned) i, rval);		break;	      case JSOP_USESHARP:		i = (jsint) GET_ATOM_INDEX(pc);		todo = Sprint(&ss->sprinter, "#%u#", (unsigned) i);		break;#endif /* JS_HAS_SHARP_VARS */#endif /* JS_HAS_INITIALIZERS */#if JS_HAS_DEBUGGER_KEYWORD	      case JSOP_DEBUGGER:		js_printf(jp, "\tdebugger;\n");		todo = -2;		break;#endif /* JS_HAS_DEBUGGER_KEYWORD */	      default:		todo = -2;		break;	    }	}	if (todo < 0) {	    /* -2 means "don't push", -1 means reported error. */	    if (todo == -1)		return JS_FALSE;	} else {	    if (!PushOff(ss, todo, op))		return JS_FALSE;	}	pc += len;    }/* * Undefine local macros. */#undef DECOMPILE_CODE#undef POP_STR#undef LOCAL_ASSERT    return JS_TRUE;}