/*
 * LANGDISASM - Quick & dirty stack machine code disassembler
 *
 * Author:
 * Emile van Bergen, emile@evbergen.xs4all.nl
 *
 * Permission to redistribute an original or modified version of this program
 * in source, intermediate or object code form is hereby granted exclusively
 * under the terms of the GNU General Public License, version 2. Please see the
 * file COPYING for details, or refer to http://www.gnu.org/copyleft/gpl.html.
 *
 * History:
 * 2001/05/06 - EvB - Created
 * 2001/10/29 - EvB - Cleanup
 */

char langdisasm_id[] = "LANGDISASM - Copyright (C) 2001 Emile van Bergen.";


/*
 * INCLUDES & DEFINES
 */


#include <unistd.h>	/* For write() */
#include <string.h>	/* For strcpy(), strlen() */

#include <language.h>


/* 
 * GLOBALS
 */


#define OPCCNT 81

struct {
	int op;
	char *name;
} opcmap[OPCCNT + 1] = {

	{ OP_HALT, "HALT" },
	{ OP_ABORT, "ABORT" },
	{ OP_ACCEPT, "ACCEPT" },
	{ OP_REJECT, "REJECT" },
	{ OP_ACCTRESP, "ACCTRESP" },
	{ OP_NOP, "NOP" },
	{ OP_PUSHINT, "PUSHINT" },
	{ OP_PUSHSTR, "PUSHSTR" },
	{ OP_PUSHAV, "PUSHAVREF" },
	{ OP_POP, "POP" },

	{ OP_NEG, "NEG" },
	{ OP_NOT, "NOT" },
	{ OP_MUL, "MUL" },
	{ OP_DIV, "DIV" },
	{ OP_CIDRMASK, "CIDRMASK" },
	{ OP_MOD, "MOD" },
	{ OP_ADD, "ADD" },
	{ OP_SUB, "SUB" },
	{ OP_SHL, "SHL" },
	{ OP_SHR, "SHR" },
	{ OP_XOR, "XOR" },
	{ OP_AND, "AND" },
	{ OP_OR, "OR" },
	{ OP_GE, "GE" },
	{ OP_LE, "LE" },
	{ OP_GT, "GT" },
	{ OP_LT, "LT" },
	{ OP_EQ, "EQ" },
	{ OP_NE, "NE" },

	{ OP_BF, "BF" },
	{ OP_AF, "AF" },
	{ OP_BL, "BL" },
	{ OP_AL, "AL" },
	{ OP_FO, "FO" },
	{ OP_LO, "LO" },
	{ OP_MD5, "MD5" },
	{ OP_HEX, "HEX" },
	{ OP_UPPER, "UPPER" },
	{ OP_LOWER, "LOWER" },
	{ OP_RANDOM, "RANDOM" },
	{ OP_XORSTR, "XORSTR" },
	{ OP_CONCAT, "CONCAT" },
	{ OP_DICTENC, "DICTENC" },

	{ OP_GESTR, "GESTR" },
	{ OP_LESTR, "LESTR" },
	{ OP_GTSTR, "GTSTR" },
	{ OP_LTSTR, "LTSTR" },
	{ OP_EQSTR, "EQSTR" },
	{ OP_NESTR, "NESTR" },

	{ OP_ORD2OCTSTR, "ORD2OCTSTR" },
	{ OP_ORD2DECSTR, "ORD2DECSTR" },
	{ OP_ORD2HEXSTR, "ORD2HEXSTR" },
	{ OP_ORD2RAWSTR, "ORD2RAWSTR" },
	{ OP_ORD2IPASTR, "ORD2IPASTR" },
	{ OP_ORD2DATSTR, "ORD2DATSTR" },
	{ OP_ORD2DFMSTR, "ORD2DFMSTR" },
	{ OP_STR2MAC, "STR2MAC" },
	{ OP_PAPDECR, "PAPDECR" },
	{ OP_PAPENCR, "PAPENCR" },
	{ OP_UNIXCRYPT, "UNIXCRYPT" },
	{ OP_HMACMD5, "HMACMD5" },
	{ OP_DICTDEC, "DICTDEC" },

	{ OP_OCTSTR2ORD, "OCTSTR2ORD" },
	{ OP_DECSTR2ORD, "DECSTR2ORD" },
	{ OP_HEXSTR2ORD, "HEXSTR2ORD" },
	{ OP_RAWSTR2ORD, "RAWSTR2ORD" },
	{ OP_IPASTR2ORD, "IPASTR2ORD" },
	{ OP_DATSTR2ORD, "DATSTR2ORD" },
	{ OP_INTSTR2ORD, "INTSTR2ORD" },

	{ OP_EXISTS, "EXISTS" },
	{ OP_BOOLNOT, "BOOLNOT" },
	{ OP_JMPZ, "JMPZ" },
	{ OP_JMPNZ, "JMPNZ" },

	{ OP_ADDAV, "ADDAV" },
	{ OP_REPLACEAV, "REPLACEAV" },
	{ OP_POKEAV, "POKEAV" },
	{ OP_DELAV, "DELAV" },
	{ OP_DELALLAV, "DELALLAV" },
	{ OP_MOVEALLAV, "MOVEALLAV" },
	{ OP_JOINSTR, "JOINSTR" },

	{ OP_CALLIFACE, "CALLIFACE" },

	{ -1, "???" }};			/* Must not be included in OPCCNT */


/*
 * FUNCTIONS
 */


void lang_disassemble(META *m, INSN *code, ssize_t codelen)
{
	static char buf[1024];
	INSN *i, *e;
	char *o;
	int n;

	e = (INSN *)((char *)code + codelen);
	for(i = code; i < e; i++) {

		o = buf;

		/* Show relative instruction pointer */
		o += meta_ordtoa(o, 128, 0, 10, i - code);
		*o++ = ':'; *o++ = ' ';

		/* Show instruction name */
		for(n = 0; n < OPCCNT && i->op != opcmap[n].op; n++);
		strcpy(o, opcmap[n].name); o += strlen(o); *o++ = ' ';

		/* For some instructions, show and/or do something extra */
		switch(i->op) {

		  case OP_PUSHINT:
			o += meta_ordtoa(o, 128, 0, 10, i->imm.ord);
			strcpy(o, " (0x"); o += 4;
			o += meta_ordtoa(o, 128, 0, 16, i->imm.ord);
			*o++ = ')';
			break;

		  case OP_PUSHSTR: 
			*o++ = '\"';
			o += meta_atoprt((char *)(i + 1), i->imm.d.str_len,
					 0, 0, 0, 0, 
					 o, sizeof(buf) - 4 - (o - buf));
			*o++ = '\"';
			i += i->imm.d.disp;
			break;

		  case OP_PUSHAV:
			strcpy(o, i->imm.i.item->spc->name); 
			o += strlen(o); *o++ = '/';
			strcpy(o, meta_getvndbynr(m, i->imm.i.item->vnd)->name);
			o += strlen(o); *o++ = '/';
			strcpy(o, i->imm.i.item->name); 
			o += strlen(o);

			strcpy(o, i->imm.i.flags&AV_FIRST ? " (first":" (last");
			o += strlen(o); 

			if (i->imm.i.flags & AV_USEREPVALID)
				strcpy(o, i->imm.i.flags & AV_USEREP ? 
						" from REP)" : " from REQ)");
			else
				strcpy(o, i->imm.i.flags & AV_USEREP ? 
						" from NONSTD list for OP)" :
						" from STD list for OP)");
			o += strlen(o);
			break;

		  case OP_JMPZ:
		  case OP_JMPNZ:
			if (i->imm.d.disp >= 0) *o++ = '+';
			o += meta_ordtoa(o, 128, 0, 10, i->imm.d.disp);
			break;
		}

		*o++ = '\n';
		write(2, buf, o - buf);
	}
}



syntax highlighted by Code2HTML, v. 0.9.1