mud++0.35/etc/
mud++0.35/etc/guilds/
mud++0.35/help/propert/
mud++0.35/mudC/
mud++0.35/player/
mud++0.35/src/interface/
mud++0.35/src/os/cygwin32/
mud++0.35/src/os/win32/
mud++0.35/src/os/win32/bcppbuilder/
mud++0.35/src/osaddon/
mud++0.35/src/util/
/*
....[@@@..[@@@..............[@.................. MUD++ is a written from
....[@..[@..[@..[@..[@..[@@@@@....[@......[@.... scratch multi-user swords and
....[@..[@..[@..[@..[@..[@..[@..[@@@@@..[@@@@@.. sorcery game written in C++.
....[@......[@..[@..[@..[@..[@....[@......[@.... This server is an ongoing
....[@......[@..[@@@@@..[@@@@@.................. development project.  All 
................................................ contributions are welcome. 
....Copyright(C).1995.Melvin.Smith.............. Enjoy. 
------------------------------------------------------------------------------
Melvin Smith (aka Fusion)         msmith@hom.net
MUD++ development mailing list    mudpp@van.ml.org
------------------------------------------------------------------------------
asmparser.cc
*/

#include "config.h"
#include "string.h"
#include "io.h"
#include "vmopcodes.h"
#include "asmobjfile.h"
#include "asmparser.h"
#include "erratum.h"

struct _parser_table AsmParser::parser_table[] =
{
	{"aadd", 	VMOPC_AADD   , &AsmParser::paramless, NULL },
	{"abort", 	VMOPC_ABORT,  &AsmParser::paramless, NULL },
	{"add", 	VMOPC_ADD   , &AsmParser::paramless, NULL },
	{"alen", 	VMOPC_ALEN   , &AsmParser::paramless, NULL },
	{"apop", 	VMOPC_APOP   , &AsmParser::paramless, NULL },
	{"apush", 	VMOPC_APUSH   , &AsmParser::paramless, NULL },
	{"call",	VMOPC_CALL, &AsmParser::read_unknown_call, NULL },
	{"cast2f", 	VMOPC_CAST2F, &AsmParser::paramless, NULL },
	{"cast2i", 	VMOPC_CAST2I, &AsmParser::paramless, NULL },
	{"checkcast", VMOPC_CHECKCAST, &AsmParser::paramless, NULL},
	{"clone", 	VMOPC_CLONE , &AsmParser::paramless, NULL },
	{"dec", 	VMOPC_DEC   , &AsmParser::paramless, NULL },
	{"decl", 	VMOPC_DECL  , &AsmParser::read_local_var, NULL },
	{"div", 	VMOPC_DIV   , &AsmParser::paramless, NULL },
	{"exit", 	VMOPC_EXIT  , &AsmParser::read_u8, NULL },
	{"fcall", 	VMOPC_FCALL , &AsmParser::read_fun_call, NULL },
	{"fcmp",	VMOPC_FCMP,	&AsmParser::read_cond_jump, NULL },
	{"feval",	VMOPC_FEVAL,&AsmParser::read_cond_jump, NULL },
	{"getfield",	VMOPC_GETFIELD,&AsmParser::read_field, NULL },
	{"icall", 	VMOPC_ICALL , &AsmParser::read_interface_call, NULL },
	{"icmp",	VMOPC_ICMP,	&AsmParser::read_cond_jump, NULL },
	{"ieval",	VMOPC_IEVAL,&AsmParser::read_cond_jump, NULL },
	{"ilookupswitch", VMOPC_ILOOKUPSWITCH,&AsmParser::read_ilookupswitch, NULL },
	{"inc", 	VMOPC_INC   , &AsmParser::paramless, NULL },
	{"incl", 	VMOPC_INCL  , &AsmParser::read_local_var, NULL },
	{"initl", 	VMOPC_INITL , &AsmParser::read_local_var, NULL },
	{"initp", 	VMOPC_INITP , &AsmParser::read_local_var, NULL },
	{"isnull",	VMOPC_ISNULL,	&AsmParser::read_cond_jump, NULL },
	{"itableswitch", VMOPC_ITABLESWITCH,&AsmParser::read_itableswitch, NULL },
	{"jmp", 	VMOPC_JMP  , &AsmParser::read_jump, NULL },
	{"licmp",	VMOPC_LICMP,	&AsmParser::read_cond_local_var_jump, NULL },
	{"lieval",	VMOPC_LIEVAL,&AsmParser::read_cond_local_var_jump, NULL },
	{"mod", 	VMOPC_MOD   , &AsmParser::paramless, NULL },
	{"movc",	VMOPC_MOVI	, &AsmParser::read_local_var_constant, NULL },
	{"movf",	VMOPC_MOVI	, &AsmParser::read_local_var_float, NULL },
	{"movi",	VMOPC_MOVI	, &AsmParser::read_local_var_int, NULL },
	{"mpop", 	VMOPC_MPOP  , &AsmParser::read_u8, NULL },
	{"mul", 	VMOPC_MUL   , &AsmParser::paramless, NULL },
	{"nop", 	VMOPC_NOP   , &AsmParser::paramless, NULL },
	{"ocmp", 	VMOPC_OCMP, &AsmParser::read_cond_jump, NULL },
	{"pop", 	VMOPC_POP   , &AsmParser::paramless, NULL },
	{"popl", 	VMOPC_POPL   , &AsmParser::read_local_var, NULL },
	{"popstat",	VMOPC_POPSTAT, &AsmParser::read_static, NULL },
	{"pushc", 	VMOPC_PUSHC , &AsmParser::read_const, NULL },
	{"pushf", 	VMOPC_PUSHF , &AsmParser::read_float, NULL },
	{"pushfz", 	VMOPC_PUSHFZ, &AsmParser::paramless, NULL },
	{"pushi", 	VMOPC_PUSHI,  &AsmParser::read_s32, NULL },
	{"pushiz", 	VMOPC_PUSHIZ, &AsmParser::paramless, NULL },
	{"pushl", 	VMOPC_PUSHL,  &AsmParser::read_local_var, NULL },
	{"pushstat",VMOPC_PUSHSTAT, &AsmParser::read_static, NULL },
	{"pushthis",VMOPC_PUSHTHIS, &AsmParser::paramless, NULL },
	{"reducel",	VMOPC_REDUCEL, &AsmParser::read_u16, NULL },
	{"ret", 	VMOPC_RET   , &AsmParser::paramless, NULL },
	{"scharat", VMOPC_SCHARAT, &AsmParser::paramless, NULL },
	{"scharatl", VMOPC_SCHARAT, &AsmParser::read_local_var, NULL },
	{"scmp", 	VMOPC_SCMP, &AsmParser::read_cond_jump, NULL },
	{"sconcat", VMOPC_SCONCAT , &AsmParser::paramless, NULL },
	{"setfield", VMOPC_SETFIELD , &AsmParser::read_field, NULL },
	{"sfloatcat", VMOPC_SFLOATCAT , &AsmParser::paramless, NULL },
	{"sgetarg", VMOPC_SGETARG, &AsmParser::paramless, NULL },
	{"sgetargrest", VMOPC_SGETARGREST, &AsmParser::paramless, NULL },
	{"sintcat", VMOPC_SINTCAT , &AsmParser::paramless, NULL },
	{"sisempty",	VMOPC_SISEMPTY,	&AsmParser::read_cond_jump, NULL },
	{"sisnumber",	VMOPC_SISNUMBER,	&AsmParser::read_cond_jump, NULL },
	{"sleep", VMOPC_SLEEP, &AsmParser::paramless, NULL },
	{"slookupswitch", VMOPC_SLOOKUPSWITCH, &AsmParser::read_slookupswitch, NULL },
	{"spushempty", VMOPC_SPUSHEMPTY, &AsmParser::paramless, NULL },
	{"sstartargs", VMOPC_SSTARTARGS, &AsmParser::paramless, NULL },
	{"stoint", VMOPC_STOINT, &AsmParser::paramless, NULL },
	{"sub", 	VMOPC_SUB   , &AsmParser::paramless, NULL },
	{"swap", 	VMOPC_SWAP  , &AsmParser::paramless, NULL },
	{"upcast", VMOPC_UPCAST, &AsmParser::read_classname, NULL },
	{ NULL, 		VMOPC_ABORT, &AsmParser::paramless, NULL }
};

const int parse_table_size = (sizeof( AsmParser::parser_table ) / sizeof( _parser_table ))-1;

struct _parser_table * lookupOpcodeTable(char * mnem)
{
/*
	int i;
	for ( i =0; AsmParser::parser_table[i].name; i++)
	{
		if ( !strcmp(mnem, AsmParser::parser_table[i].name) )
			return &AsmParser::parser_table[i];
	}
*/

	// Binary search

	int cmp, k, l,p;
	l = 0;
	p = parse_table_size;
	
	while ( l <= p )
	{
		k = (l+p) >> 1;
		cmp = strcmp( mnem, AsmParser::parser_table[k].name );
		if ( cmp < 0 )
			p = k-1;
		else if ( cmp > 0 )
			l = k+1;
		else
			return &AsmParser::parser_table[k];
	}

 	return NULL;
}

const u16 ADRESS_UNKNOWN = 0xffff;


int AsmParser::parse( StaticInput & infr, Output & outfr )
{
	obj = new AsmObjFile();
	char buf[BUF];
	int asmerr = 0;
	int cnumber;
	infun = false;
	label * lab;
	String str;
	struct _parser_table  * tbl;
	inf = &infr;
	outf = &outfr;
	memorycell cell;
	

	while ( true )
	{
		inf->getword(buf);
		// Support for comments
		if( buf[0] == '#' )
		{
			inf->skipline();
			continue;
		}
		else if ( buf[0] == '!' )
		{
			// CONTROL COMMANDS
			if ( !strcmp(buf, "!A") )	// Argument definition
			{
				if ( !infun )
				{
					inf->error("AsmParser: '!A' outside of fun");
					asmerr = -1;
					break;
				}
				readVariable();
				args_count++;
			}
			else if ( !strcmp(buf, "!L") )	// Local variable definition
			{
				if ( !infun )
				{
					inf->error("AsmParser: '!L' outside of fun");
					asmerr = -1;
					break;
				}
				readVariable();
				vars_count++;
			}
			else if ( !strcmp(buf, "!funstart") )
			{
				if (infun)
				{
					inf->error( "AsmParser: '!funstart' inside another fun." );
					asmerr = -1;
					break;
				}
				inf->getword(buf);
				infun = true;
				funstart = obj->getOffset();
				strcpy(funname, buf);
				cell.vmint = 0;
				obj->putCell(cell); // for INITP
				obj->putCell(cell);	// for INITL
				args_count = 0;
				vars_count = 0;
			}
			else if ( !strcmp( buf, "!funend") )
			{
				int i;
				int reduced_length;

				if (!infun)
				{
					Cout << "AsmParser: '!funend' without matching funstart" <<endl;
					asmerr = -1;
					break;
				}
				infun = false;
				// check if all labels are resolved
				for_each( labels, lab)
				{
					if ( lab->adress == ADRESS_UNKNOWN )
					{
						str <<"AsmParser:: fun ended but there is at least" <<
							" one unresolved label: " << lab->name;
						inf->error(str);
						asmerr = -1;
						break;
					}
				}
				
				if ( vars_count && args_count )
				{
					cell.vmint =0;
					cell.s.opcode = VMOPC_INITP;
					cell.s.u.number = args_count;
					obj->setCell(funstart, cell);
					cell.s.opcode = VMOPC_INITL;
					cell.s.u.number = vars_count;
					obj->setCell(funstart+1, cell);
					reduced_length = 0;
				}
				else if ( !vars_count )
				{
					cell.vmint =0;
					cell.s.opcode = VMOPC_INITP;
					cell.s.u.number = args_count;
					obj->setCell(funstart+1, cell);
					reduced_length = -1;
				}
				else if ( !args_count )
				{
					cell.vmint =0;
					cell.s.opcode = VMOPC_INITL;
					cell.s.u.number = vars_count;
					obj->setCell(funstart+1, cell);
					reduced_length = -1;
				}
				else	// both arguments an locals missing
				{
					reduced_length = -2;
				}

				if ( reduced_length )
				{
					for( i = shortjumps.length() - 1; i >=0; i-- )
					{
/*						Cout << "Relocated cell " << shortjumps[i] <<
								" by " << reduced_length << " in fun " <<
								funname << endl;*/
						obj->relocCell(shortjumps[i]+ funstart, reduced_length );
				}
				}

				// reduced_length <= 0 so need -= instead of +=
				funstart -= reduced_length;

				// it has to be before fun entry - AsmLoader 'feature'
				cnumber = obj->addConstant( VMT_CONST_STRING, funname, 
						strlen(funname) + 1 );
				vmfilefun vmff;
				vmff.start = funstart;
				vmff.end = obj->getOffset();
				vmff.name = cnumber;
				obj->addConstant( VMT_EXPORT_FUN, &vmff, sizeof(vmfilefun) );
				clearLabels();
				locals.clr();
			}
			else if ( !strcmp(buf, "!constant" ) )
			{
				if (readConstant() < 0)
				{
					asmerr = -1;
					break;
				}
			}
			else if ( !strcmp(buf, "!end" ) )
			{
				if ( infun )
				{
					inf->error("AsmParser: '!end' occured inside of fun.");
					asmerr = -1;
					break;
				}
				asmerr = 0;
				break;
			}
			else
			{
				str << "AsmParser: unrecognized command " << buf;
				inf->error(str);
				asmerr = -1;
				break;
			}
		}
		else if ( buf[0] == ':' )
		{
			// LABEL
			if ( !infun )
			{
				inf->error("AsmParser: Label outside function.");
				asmerr = -1;
				break;
			}
			setLabel(&buf[1], obj->getOffset() - funstart);
		}
		else
		{
			// MNEMONIC
			tbl = lookupOpcodeTable(buf);
			if (!tbl)
			{
				str<< "Asmparser: - unknown mnemonic " << buf;
				inf->error(str);
				asmerr = -1;
				break;
			}
			// zero cell
			cell.vmint = 0;

			cell.s.opcode = tbl->opcode;
			if (! (this->*(tbl->mnem2code)) (cell))
			{
				inf->error("Asmparser: error occured during mnemonic parsing");
				asmerr = -1;
				break;
			}
		}
	}

	if ( !asmerr  ) 
		obj->writeTo(*outf);
	delete obj;
	clearLabels();
	locals.clr();
	return (asmerr);
}

// Params: name - name of label we want jump to
//         adress - point at which u16 absolute jump will be placed
// Return: absolute offset of label ( or ADRESS_UNKNOWN(0xffff) 
//         if unknown at time)
// absolute offsets are counted from start of function

u16 AsmParser::getLabel(char * name, int adress)
{
	label * lab;
	for_each(labels, lab)
	{
		if ( lab->name == name )
		{
			// Label already known ?
			if ( lab->adress != ADRESS_UNKNOWN )
			{
//				Cout << "Set absolute jump " << name << " at " << (int) adress << " to " << (int) lab->adress <<endl;
				shortjumps.add(adress);
				return (lab->adress);
			}
			lab->to_resolve.add(adress);
			shortjumps.add(adress);
			return ADRESS_UNKNOWN;

		}
	}

	lab = new label;
	lab->name = name;
	lab->adress = ADRESS_UNKNOWN;
	lab->to_resolve.add(adress);
	labels.add(lab);
	shortjumps.add(adress);
	return ADRESS_UNKNOWN;
}

// Params: name - name of label we want to define
//         adress - place in code that label describes
void AsmParser::setLabel(char * name, int adress)
{
	label * lab;
	int i,size;

	if ( adress == ADRESS_UNKNOWN )
		Error::dump("ADRESS_UNKNOWN passed to AsmParser::setLabel");

	for_each(labels, lab)
	{
		if (lab->name == name)
		{
			// later redefine to local error not global
			if ( lab->adress != ADRESS_UNKNOWN )
				Error::dump("Tried to redefine label at AsmParser::setLabel");
			lab->adress = (u16)adress;
			size = lab->to_resolve.length();
			for( i=0; i < size; i++ )
			{
//				Cout << "Resolved one " << lab->name << " of " << size << endl;
				setAbsoluteJump( lab->to_resolve[i], adress );
			}
			lab->to_resolve.clr();
			return;
		}
	}

	lab = new label;
	lab->name = name;
	lab->adress = (u16)adress;
	labels.add(lab);
}

void AsmParser::clearLabels()
{
	label * lab;
	labels.reset();
	while ( (lab = labels.remove()) != NULL )
	{
		delete lab;
	}
	shortjumps.clr();
}


/*
void AsmParser::setRelativeJump( int point, int to )
{
//	Cout << "Set relative jump at " << (int) point << " to " << (int) to <<endl;
	(*obj)[point].s.u.reloc = (s16) (to - point - 1);
}
*/

void AsmParser::setAbsoluteJump( int point, int to )
{
//	Cout << "Set absolute jump at " << (int) point << " to " << (int) to <<endl;
	(*obj)[point+funstart].s.u.number = (u16) (to);
}


int AsmParser::readConstant()
{
	char buf[BUF];
	int i;
	inf->getword(buf);

	if ( !strcmp(buf, "string") )
	{
		inf->getstring(buf);
		return obj->addConstant(VMT_CONST_STRING, buf, strlen(buf)+1);
	}
	else if ( !strcmp(buf, "funcall") )
	{
		inf->getword(buf);
		return obj->addConstant(VMT_IMPORT_FUN, buf, strlen(buf)+1);
	}
	else if ( !strcmp(buf, "interfacecall") )
	{
		inf->getword(buf);
		return obj->addConstant(VMT_IMPORT_INTERFACE, buf, strlen(buf)+1);
	}
	else if ( !strcmp(buf, "constant" ) )
	{
		i = inf->getnum();
		if ( i >= obj->numberOfConstants() )
		{
			inf->error("AsmParser::readConstant - constant keyword with undefined const.");
			return -1;
		}
		return i;
	}
	else
	{
		inf->error("AsmParser::readConstant - only strings and imports supported for now.");
		return -1;
	}
}

void AsmParser::readVariable()
{
	char buf[BUF];
	inf->getword(buf);	// type - ignored for now
	inf->getword(buf);	// name
		locals.add(String(buf));
}

bool AsmParser::read_float(memorycell cell)
{
	obj->putCell(cell);
	obj->putFloat(inf->getfloat());
	return true;
}


bool AsmParser::read_const(memorycell cell)
{
	int i = readConstant();
	if ( i < 0 )
		return false;
	cell.s.u.number = i;
	obj->addRelocation();
	obj->putCell(cell);
	return true;
}

u8 AsmParser::parseConditions(const char * txt)
{
	int i;
	int len = strlen(txt);
	u8 answer = 0;
	for ( i=0; i < len; i++)
	{
		switch (txt[i])
		{
			case 'a':
				answer = VMFLAG_EQUAL | VMFLAG_GREATER | VMFLAG_LESSER;
				break;
			case 'e':
				answer |= VMFLAG_EQUAL;
				break;
			case 'g':
				answer |= VMFLAG_GREATER;
				break;
			case 'l':
				answer |= VMFLAG_LESSER;
				break;
			default:
				answer = 255;
				inf->error("AsmParser::parseConditions - unknown letter");
				break;
		}
	}

	return answer;
}

bool AsmParser::read_cond_jump(memorycell cell)
{
	char buf[256];
	inf->getword(buf);
	cell.s.conds = parseConditions(buf);
	inf->getword(buf);
	cell.s.u.number = getLabel(buf, obj->getOffset() -funstart);
	obj->putCell(cell);
	return true;
}

bool AsmParser::read_jump(memorycell cell)
{
	char buf[256];
	inf->getword(buf);
	cell.s.u.number = getLabel(buf, obj->getOffset() -funstart);
	obj->putCell(cell);
	return true;
}




bool AsmParser::read_fun_call(memorycell cell)
{
	char buf[256];

	inf->getword(buf);
	obj->addRelocation();
	cell.s.u.number = obj->addConstant( VMT_IMPORT_FUN, buf, strlen(buf) + 1);
	obj->putCell(cell);
	return true;
}

bool AsmParser::read_interface_call(memorycell cell)
{
	char buf[256];

	inf->getword(buf);
	obj->addRelocation();
	cell.s.u.number = obj->addConstant( VMT_IMPORT_INTERFACE, buf, strlen(buf) + 1);
	obj->putCell(cell);
	return true;
}

bool AsmParser::read_unknown_call(memorycell cell)
{
	char buf[256];

	inf->getword(buf);
	obj->addRelocation();
	cell.s.u.number = obj->addConstant( VMT_IMPORT_FUN_OR_INTERFACE, buf, strlen(buf) + 1);
	obj->putCell(cell);
	return true;
}

bool AsmParser::read_static( memorycell cell )
{
	char buf[256];

	inf->getword(buf);
	obj->addRelocation();
	cell.s.u.number = obj->addConstant( VMT_IMPORT_STATIC, buf, strlen(buf) +1);
	obj->putCell(cell);
	return true;
}

// Later add checks for boundaries

bool AsmParser::read_u8(memorycell cell)
{
	cell.s.conds = inf->getnum();
	obj->putCell(cell);
	return true;
}

bool AsmParser::read_u16(memorycell cell)
{
	cell.s.u.number = inf->getnum();
	obj->putCell(cell);
	return true;
}

bool AsmParser::read_s16(memorycell cell)
{
	cell.s.u.reloc = inf->getnum();
	obj->putCell(cell);
	return true;
}

bool AsmParser::read_s32(memorycell cell)
{
	obj->putCell(cell);
	obj->putInt(inf->getnum());
	return true;
}

bool AsmParser::paramless( memorycell cell )
{
	obj->putCell(cell);
	return true;
}


int AsmParser::lookupLocal( const char * txt )
{
	if ( *txt == '@' )
	{
		int size = locals.length();
		int i;
		const char * buf = txt +1;
		for ( i=0; i < size; i++ )
		{
			if ( locals[i] == buf )
				return i;
		}
		return -1;
	}
	if ( !isdigit(*txt) )
		return -1;

	return atoi( txt );
}

bool AsmParser::read_local_var( memorycell cell )
{
	char buf[256];
	int number;
	number = lookupLocal(inf->getword(buf));
	if ( number == -1 )
		return false;
	cell.s.u.number = number;
	obj->putCell(cell);
	return true;
}

bool AsmParser::read_cond_local_var_jump( memorycell cell )
{
	char buf[256];
	int number;
 
 	inf->getword(buf);
	cell.s.conds = parseConditions(buf);

	number = lookupLocal(inf->getword(buf));
	if ( number == -1 )
		return false;
	cell.s.u.number = number;
	obj->putCell(cell);

	cell.vmint = 0;
	inf->getword(buf);
	cell.s.u.number = getLabel(buf, obj->getOffset() -funstart);
	obj->putCell(cell);
	return true;
}



bool AsmParser::read_local_var_int( memorycell cell )
{
	char buf[256];
	int number;
	number = lookupLocal(inf->getword(buf));
	if ( number == -1 )
		return false;
	cell.s.u.number = number;
	obj->putCell(cell);
	obj->putInt(inf->getnum());
	return true;
}

bool AsmParser::read_local_var_float( memorycell cell )
{
	char buf[256];
	int number;
	number = lookupLocal(inf->getword(buf));
	if ( number == -1 )
		return false;
	cell.s.u.number = number;
	obj->putCell(cell);
	obj->putFloat(inf->getfloat());
	return true;
}

bool AsmParser::read_local_var_constant( memorycell cell )
{
	char buf[256];
	int number;
	number = lookupLocal(inf->getword(buf));
	if ( number == -1 )
		return false;
	cell.s.u.number = number;
	obj->putCell(cell);
 	number = readConstant();
	if ( number < 0 )
		return false;
	obj->addRelocation();
	cell.vmint =0;
	cell.s.u.number = number;
	obj->putCell(cell);
	return true;
}


bool AsmParser::read_ilookupswitch( memorycell cell )
{
	char buf[256];
	int length = inf->getnum();
	if ( length > 255 )
		return false;
	cell.s.conds = length;
	inf->getword(buf);
	cell.s.u.number = getLabel( buf, obj->getOffset() - funstart );
	obj->putCell(cell);
	
	for ( ; length > 0; length-- )
	{
		cell.vmint = inf->getnum();
		obj->putCell(cell);
		inf->getword(buf);
		cell.vmint  = 0;
		cell.s.u.number = getLabel(buf, obj->getOffset() - funstart );
		obj->putCell(cell);
	}
	return true;
}

bool AsmParser::read_slookupswitch( memorycell cell )
{
	char buf[256];
	int length = inf->getnum();
	if ( length > 255 )
		return false;
	cell.s.conds = length;
	inf->getword(buf);
	cell.s.u.number = getLabel( buf, obj->getOffset() - funstart );
	obj->putCell(cell);
	
	for ( ; length > 0; length-- )
	{
		cell.vmint =0;
		inf->getstring(buf);
		cell.s.u.number = obj->addConstant(VMT_CONST_STRING, buf, strlen(buf)+1);
		obj->addRelocation();
    	obj->putCell(cell);
		inf->getword(buf);
		cell.vmint  = 0;
		cell.s.u.number = getLabel(buf, obj->getOffset() - funstart );
		obj->putCell(cell);
	}
	return true;
}

bool AsmParser::read_itableswitch( memorycell cell )
{
	int min,max,i;
	char buf[256];
	char defaul[256];

	inf->getword(defaul);
	cell.s.u.number = getLabel( defaul, obj->getOffset() - funstart );
	obj->putCell(cell);
	
	min = inf->getnum();
	max = inf->getnum();
	if ( min > max )
		return false;

	cell.vmint = min;
	obj->putCell(cell);
	cell.vmint = max;
	obj->putCell(cell);

	cell.vmint = 0;
	while ( min <= max )
	{
		i = inf->getnum();
		while (min < i)
		{
			cell.s.u.number = getLabel( defaul, obj->getOffset() - funstart );
			obj->putCell(cell);
			min++;
		}
		inf->getword(buf);
		cell.s.u.number = getLabel( buf, obj->getOffset() - funstart );
		obj->putCell(cell);
		min++;
	}
	return true;
}

bool AsmParser::read_field( memorycell cell )
{
	char buf1[256];
	char buf2[256];
	int s1, s2;
	inf->getword( buf1 );
	inf->getword( buf2 );
	s1 = strlen(buf1);
	s2 = strlen(buf2);
	memcpy( &buf1[s1+1], buf2, s2 +1 );
	cell.s.u.number = obj->addConstant( VMT_FIELD_DATA, buf1, s1 + s2 + 2);
	obj->addRelocation();
	obj->putCell(cell);
	return true;
}

bool AsmParser::read_classname( memorycell cell )
{
	char buf[128];
	inf->getword(buf);
	cell.s.u.number =  obj->addConstant(VMT_CLASS_TYPE, buf, strlen(buf)+1);
	obj->addRelocation();
	obj->putCell(cell);
	return true;
}
 


// If I ever write run-time disassember of VM code this code will change
// Table containg opcode -> parser_table mapping will be constructed at boot
const char * lookupOpcodeName( u8 opcode )
{
	int i;
	for ( i =0; AsmParser::parser_table[i].name; i++)
	{
		if ( opcode == AsmParser::parser_table[i].opcode )
			return AsmParser::parser_table[i].name;
	}
	return "UNKNOWN";	
}