Exemple #1
0
//---------------------------------------------------------------------------
tTJSString tTJSString::EscapeC() const
{
	ttstr ret;
	const tjs_char * p = c_str();
	bool hexflag = false;
	for(;*p;p++)
	{
		switch(*p)
		{
		case 0x07: ret += TJS_W("\\a"); hexflag = false; continue;
		case 0x08: ret += TJS_W("\\b"); hexflag = false; continue;
		case 0x0c: ret += TJS_W("\\f"); hexflag = false; continue;
		case 0x0a: ret += TJS_W("\\n"); hexflag = false; continue;
		case 0x0d: ret += TJS_W("\\r"); hexflag = false; continue;
		case 0x09: ret += TJS_W("\\t"); hexflag = false; continue;
		case 0x0b: ret += TJS_W("\\v"); hexflag = false; continue;
		case TJS_W('\\'): ret += TJS_W("\\\\"); hexflag = false; continue;
		case TJS_W('\''): ret += TJS_W("\\\'"); hexflag = false; continue;
		case TJS_W('\"'): ret += TJS_W("\\\""); hexflag = false; continue;
		default:
			if(hexflag)
			{
				if(*p >= TJS_W('a') && *p <= TJS_W('f') ||
					*p >= TJS_W('A') && *p <= TJS_W('F') ||
						*p >= TJS_W('0') && *p <= TJS_W('9') )
				{
					tjs_char buf[20];
					TJS_snprintf(buf, sizeof(buf)/sizeof(tjs_char), TJS_W("\\x%02x"), (int)*p);
					hexflag = true;
					ret += buf;
					continue;
				}
			}

			if(*p < 0x20)
			{
				tjs_char buf[20];
				TJS_snprintf(buf, sizeof(buf)/sizeof(tjs_char), TJS_W("\\x%02x"), (int)*p);
				hexflag = true;
				ret += buf;
			}
			else
			{
				ret += *p;
				hexflag = false;
			}
		}
	}
	return ret;
}
Exemple #2
0
//---------------------------------------------------------------------------
ttstr TVPGetVersionInformation(void)
{
	TVPGetVersion();
	tjs_char verstr[100];
	TJS_snprintf(verstr, sizeof(verstr)/sizeof(tjs_char), TJS_W("%d.%d.%d.%d"),
		TVPVersionMajor, TVPVersionMinor,
		TVPVersionRelease, TVPVersionBuild);

	tjs_char tjsverstr[100];
	TJS_snprintf(tjsverstr, sizeof(tjsverstr)/sizeof(tjs_char), TJS_W("%d.%d.%d"),
		TJSVersionMajor, TJSVersionMinor, TJSVersionRelease);

	return TVPFormatMessage(TVPVersionInformation, verstr, tjsverstr);
}
Exemple #3
0
//---------------------------------------------------------------------------
// version information related functions
//---------------------------------------------------------------------------
ttstr TVPGetAboutString(void)
{
	TVPGetVersion();
	tjs_char verstr[100];
	TJS_snprintf(verstr, sizeof(verstr)/sizeof(tjs_char), TJS_W("%d.%d.%d.%d"),
		TVPVersionMajor, TVPVersionMinor,
		TVPVersionRelease, TVPVersionBuild);

	tjs_char tjsverstr[100];
	TJS_snprintf(tjsverstr, sizeof(tjsverstr)/sizeof(tjs_char), TJS_W("%d.%d.%d"),
		TJSVersionMajor, TJSVersionMinor, TJSVersionRelease);

	return TVPFormatMessage(TVPAboutString, verstr, tjsverstr) +
        TVPGetImportantLog();
}
void tTJSInterCodeContext::_output_func(const tjs_char *msg,
	const tjs_char *comment, tjs_int addr, const tjs_int32 *codestart,
		tjs_int size, void *data)

{
	tjs_int buflen = TJS_strlen(msg) + TJS_strlen(comment) + 20;
	tjs_char *buf = new tjs_char[buflen];

	TJS_snprintf(buf, buflen, TJS_W("%08d %ls"), addr, msg);
	if(comment[0])
	{
		TJS_strcat(buf, TJS_W("\t// "));
		TJS_strcat(buf, comment);
	}

	try
	{
		of_data *dat = (of_data *)(data);
		dat->func(buf, dat->funcdata);
	}
	catch(...)
	{
		delete [] buf;
		throw;
	}

	delete [] buf;
}
Exemple #5
0
//---------------------------------------------------------------------------
ttstr TVPGetVersionString()
{
	TVPGetVersion();
	tjs_char verstr[100];
	TJS_snprintf(verstr, sizeof(verstr)/sizeof(tjs_char), TJS_W("%d.%d.%d.%d"),
		TVPVersionMajor, TVPVersionMinor,
		TVPVersionRelease, TVPVersionBuild);
	return ttstr(verstr);
}
Exemple #6
0
void tTVPApplication::CloseConsole() {
	wchar_t buf[100];
	DWORD len = TJS_snprintf(buf, 100, TVPExitCode, TVPTerminateCode);
	PrintConsole(buf, len);
	if( is_attach_console_ ) {
		::SetConsoleTitle( console_title_.c_str() );
		::FreeConsole();
		is_attach_console_ = false;
	}
}
void tTJSInterCodeContext::_output_func_src(const tjs_char *msg,
	const tjs_char *name, tjs_int line, void *data)
{
	tjs_int buflen = TJS_strlen(msg) + TJS_strlen(name) + 20;
	tjs_char *buf = new tjs_char[buflen];
	if(line >= 0)
		TJS_snprintf(buf, buflen, TJS_W("#%ls(%d) %ls"), name, line+1, msg);
	else
		TJS_snprintf(buf, buflen, TJS_W("#%ls %ls"), name, msg);
	try
	{
		of_data *dat = (of_data *)(data);
		dat->func(buf, dat->funcdata);
	}
	catch(...)
	{
		delete [] buf;
		throw;
	}

	delete [] buf;
}
//---------------------------------------------------------------------------
void TJSThrowFrom_tjs_error(tjs_error hr, const tjs_char *name)
{
	// raise an exception descripted as tjs_error
	// name = variable name ( otherwide it can be NULL )

	switch(hr)
	{
	case TJS_E_MEMBERNOTFOUND:
	  {
		if(name)
		{
			ttstr str(TJSMemberNotFound);
			str.Replace(TJS_W("%1"), name);
			TJS_eTJSError(str);
		}
		else
		{
			TJS_eTJSError(TJSMemberNotFoundNoNameGiven);
		}
	  }
	case TJS_E_NOTIMPL:
		TJS_eTJSError(TJSNotImplemented);
	case TJS_E_INVALIDPARAM:
		TJS_eTJSError(TJSInvalidParam);
	case TJS_E_BADPARAMCOUNT:
		TJS_eTJSError(TJSBadParamCount);
	case TJS_E_INVALIDTYPE:
		TJS_eTJSError(TJSInvalidType);
	case TJS_E_ACCESSDENYED:
		TJS_eTJSError(TJSAccessDenyed);
	case TJS_E_INVALIDOBJECT:
		TJS_eTJSError(TJSInvalidObject);
	case TJS_E_NATIVECLASSCRASH:
		TJS_eTJSError(TJSNativeClassCrash);
	default:
		if(TJS_FAILED(hr))
		{
			tjs_char buf[256];
            TJS_snprintf(buf, 256, TJS_W("Unknown failure : %08X"), hr);
			TJS_eTJSError(buf);
		}
	}
}
Exemple #9
0
//---------------------------------------------------------------------------
void tTJS::Dump(tjs_uint width) const
{
	// dumps all existing script block
	tjs_char version[100];
	TJS_snprintf(version, sizeof(version)/sizeof(tjs_char), TJS_W("TJS version %d.%d.%d (%s)"), TJSVersionMajor,
		TJSVersionMinor, TJSVersionRelease, TJSCompiledDate);

	OutputToConsoleSeparator(TJS_W("#"), width);
	OutputToConsoleWithCentering(TJS_W("TJS Context Dump"), width);
	OutputToConsoleSeparator(TJS_W("#"), width);
	OutputToConsole(version);
	OutputToConsole(TJS_W(""));

	if(ScriptBlocks.size())
	{
		std::vector<tTJSScriptBlock*>::const_iterator i;

		tjs_char buf[1024];
		TJS_snprintf(buf, sizeof(buf)/sizeof(tjs_char), TJS_W("Total %d script block(s)"), ScriptBlocks.size());
		OutputToConsole(buf);
		OutputToConsole(TJS_W(""));

		tjs_uint totalcontexts = 0;
		tjs_uint totalcodesize = 0;
		tjs_uint totaldatasize = 0;

		for(i = ScriptBlocks.begin(); i != ScriptBlocks.end(); i++)
		{
			tjs_uint n;
			const tjs_char * name = (*i)-> GetName();

			ttstr title;
			if(name)
				title = (*i)-> GetNameInfo();
			else
				title = TJS_W("(no-named script block)");

			tjs_char ptr[256];
			TJS_snprintf(ptr, sizeof(ptr)/sizeof(tjs_char), TJS_W(" 0x%p"), (*i));

			title += ptr;

			OutputToConsole(title.c_str());

			n = (*i)->GetContextCount();
			totalcontexts += n;
			TJS_snprintf(buf, sizeof(buf)/sizeof(tjs_char), TJS_W("\tCount of contexts      : %d"), n);
			OutputToConsole(buf);

			n = (*i)->GetTotalVMCodeSize();
			totalcodesize += n;
			TJS_snprintf(buf, sizeof(buf)/sizeof(tjs_char), TJS_W("\tVM code area size      : %d words"), n);
			OutputToConsole(buf);

			n = (*i)->GetTotalVMDataSize();
			totaldatasize += n;
			TJS_snprintf(buf, sizeof(buf)/sizeof(tjs_char), TJS_W("\tVM constant data count : %d"), n);
			OutputToConsole(buf);

			OutputToConsole(TJS_W(""));
		}

		TJS_snprintf(buf, sizeof(buf)/sizeof(tjs_char), TJS_W("Total count of contexts      : %d"), totalcontexts);
		OutputToConsole(buf);
		TJS_snprintf(buf, sizeof(buf)/sizeof(tjs_char), TJS_W("Total VM code area size      : %d words"), totalcodesize);
		OutputToConsole(buf);
		TJS_snprintf(buf, sizeof(buf)/sizeof(tjs_char), TJS_W("Total VM constant data count : %d"), totaldatasize);
		OutputToConsole(buf);

		OutputToConsole(TJS_W(""));


		for(i = ScriptBlocks.begin(); i != ScriptBlocks.end(); i++)
		{

			OutputToConsoleSeparator(TJS_W("-"), width);
			const tjs_char * name = (*i)-> GetName();

			ttstr title;
			if(name)
				title = (*i)-> GetNameInfo();
			else
				title = TJS_W("(no-named script block)");

			tjs_char ptr[256];
			TJS_snprintf(ptr, sizeof(ptr)/sizeof(tjs_char), TJS_W(" 0x%p"), (*i));

			title += ptr;

			OutputToConsoleWithCentering(title.c_str(), width);

			OutputToConsoleSeparator(TJS_W("-"), width);

			(*i)->Dump();

			OutputToConsole(TJS_W(""));
			OutputToConsole(TJS_W(""));
		}
	}
	else
	{
		OutputToConsole(TJS_W(""));
		OutputToConsole(TJS_W("There are no script blocks in the system."));
	}
}
Exemple #10
0
void tTJSInterCodeContext::Disassemble(
	void (*output_func)(const tjs_char *msg, const tjs_char *comment, tjs_int addr,
	const tjs_int32 *codestart, tjs_int size, void *data),
	void (*output_func_src)(const tjs_char *msg, const tjs_char *name, tjs_int line,
	void *data), void *data, tjs_int start, tjs_int end)
{
	// dis-assemble the intermediate code.
	// "output_func" points a line output function.

//	tTJSVariantString * s;

	tTJSString msg;
	tTJSString com;

	tjs_int prevline = -1;
	tjs_int curline = -1;

	if(end <= 0) end = CodeAreaSize;
	if(end > CodeAreaSize) end = CodeAreaSize;

	for(tjs_int i = start; i < end; )
	{
		msg.Clear();
		com.Clear();
		tjs_int size;
		tjs_int srcpos = CodePosToSrcPos(i);
		tjs_int line = Block->SrcPosToLine(srcpos);

		// output source lines as comment
		if(curline == -1 || curline <= line)
		{
			if(curline == -1) curline = line;
			tjs_int nl = line - curline;
			while(curline <= line)
			{
				if(nl<3 || nl >= 3 && line-curline <= 2)
				{
					tjs_int len;
					tjs_char *src = Block->GetLine(curline, &len);
					tjs_char * buf = new tjs_char[len + 1];
					TJS_strcpy_maxlen(buf, src, len);
					try
					{
						output_func_src(buf, TJS_W(""), curline, data);
					}
					catch(...)
					{
						delete [] buf;
						throw;
					}
					delete [] buf;
					curline++;
				}
				else
				{
					curline = line - 2;
				}
			}
		}
		else if(prevline != line)
		{
			tjs_int len;
			tjs_char *src = Block->GetLine(line, &len);
			tjs_char * buf = new tjs_char[len + 1];
			TJS_strcpy_maxlen(buf, src, len);
			try
			{
				output_func_src((const tjs_char*)buf, TJS_W(""), line, data);
			}
			catch(...)
			{
				delete [] buf;
				throw;
			}
			delete [] buf;
		}

		prevline = line;

		// decode each instructions
		switch(CodeArea[i])
		{
		case VM_NOP:
			msg.printf(TJS_W("nop"));
			size = 1;
			break;

		case VM_NF:
			msg.printf(TJS_W("nf"));
			size = 1;
			break;

		case VM_CONST:
			msg.printf(TJS_W("const %%%d, *%d"),
				TJS_FROM_VM_REG_ADDR(CodeArea[i+1]),
				TJS_FROM_VM_REG_ADDR(CodeArea[i+2]));
			if(DataArea)
			{
				com.printf(TJS_W("*%d = %ls"), TJS_FROM_VM_REG_ADDR(CodeArea[i+2]),
					GetValueComment(TJS_GET_VM_REG(DataArea, CodeArea[i+2])).c_str());
			}
			size = 3;
			break;


#define OP2_DISASM(c, x) \
	case c: \
		msg.printf(TJS_W(x) TJS_W(" %%%d, %%%d"), TJS_FROM_VM_REG_ADDR(CodeArea[i+1]), \
										TJS_FROM_VM_REG_ADDR(CodeArea[i+2])); \
		size = 3; \
		break
		// instructions that
		// 1. have two operands that represent registers.
		// 2. do not have property access variants.
		OP2_DISASM(VM_CP,		"cp");
		OP2_DISASM(VM_CEQ,		"ceq");
		OP2_DISASM(VM_CDEQ,		"cdeq");
		OP2_DISASM(VM_CLT,		"clt");
		OP2_DISASM(VM_CGT,		"cgt");
		OP2_DISASM(VM_CHKINS,	"chkins");
#undef OP2_DISASM


#define OP2_DISASM(c, x) \
	case c: \
		msg.printf(TJS_W(x) TJS_W(" %%%d, %%%d"), TJS_FROM_VM_REG_ADDR(CodeArea[i+1]), \
									TJS_FROM_VM_REG_ADDR(CodeArea[i+2])); \
		size = 3; \
		break; \
	case c+1: \
		msg.printf(TJS_W(x) TJS_W("pd") TJS_W(" %%%d, %%%d.*%d, %%%d"), \
			TJS_FROM_VM_REG_ADDR(CodeArea[i+1]), \
			TJS_FROM_VM_REG_ADDR(CodeArea[i+2]), \
			TJS_FROM_VM_REG_ADDR(CodeArea[i+3]), \
			TJS_FROM_VM_REG_ADDR(CodeArea[i+4])); \
		if(DataArea) \
		{ \
			com.printf(TJS_W("*%d = %ls"), TJS_FROM_VM_REG_ADDR(CodeArea[i+3]), \
				GetValueComment(TJS_GET_VM_REG(DataArea, CodeArea[i+3])).c_str()); \
		} \
		size = 5; \
		break; \
	case c+2: \
		msg.printf(TJS_W(x) TJS_W("pi") TJS_W(" %%%d, %%%d.%%%d, %%%d"), \
			TJS_FROM_VM_REG_ADDR(CodeArea[i+1]), \
			TJS_FROM_VM_REG_ADDR(CodeArea[i+2]), \
			TJS_FROM_VM_REG_ADDR(CodeArea[i+3]), \
			TJS_FROM_VM_REG_ADDR(CodeArea[i+4])); \
		size = 5; \
		break; \
	case c+3: \
		msg.printf(TJS_W(x) TJS_W("p") TJS_W(" %%%d, %%%d, %%%d"), \
			TJS_FROM_VM_REG_ADDR(CodeArea[i+1]), \
			TJS_FROM_VM_REG_ADDR(CodeArea[i+2]), \
			TJS_FROM_VM_REG_ADDR(CodeArea[i+3])); \
		size = 4; \
		break
		// instructions that
		// 1. have two operands that represent registers.
		// 2. have property access variants
		OP2_DISASM(VM_LOR,		"lor");
		OP2_DISASM(VM_LAND,		"land");
		OP2_DISASM(VM_BOR,		"bor");
		OP2_DISASM(VM_BXOR,		"bxor");
		OP2_DISASM(VM_BAND,		"band");
		OP2_DISASM(VM_SAR,		"sar");
		OP2_DISASM(VM_SAL,		"sal");
		OP2_DISASM(VM_SR,		"sr");
		OP2_DISASM(VM_ADD,		"add");
		OP2_DISASM(VM_SUB,		"sub");
		OP2_DISASM(VM_MOD,		"mod");
		OP2_DISASM(VM_DIV,		"div");
		OP2_DISASM(VM_IDIV,		"idiv");
		OP2_DISASM(VM_MUL,		"mul");
#undef OP2_DISASM

#define OP1_DISASM(x) \
	msg.printf(TJS_W(x) TJS_W(" %%%d"), TJS_FROM_VM_REG_ADDR(CodeArea[i+1])); \
	size = 2
		// instructions that have one operand which represent a register,
		// except for inc, dec
		case VM_TT:			OP1_DISASM("tt");		break;
		case VM_TF:			OP1_DISASM("tf");		break;
		case VM_SETF:		OP1_DISASM("setf");		break;
		case VM_SETNF:		OP1_DISASM("setnf");	break;
		case VM_LNOT:		OP1_DISASM("lnot");		break;
		case VM_BNOT:		OP1_DISASM("bnot");		break;
		case VM_ASC:		OP1_DISASM("asc");		break;
		case VM_CHR:		OP1_DISASM("chr");		break;
		case VM_NUM:		OP1_DISASM("num");		break;
		case VM_CHS:		OP1_DISASM("chs");		break;
		case VM_CL:			OP1_DISASM("cl");		break;
		case VM_INV:		OP1_DISASM("inv");		break;
		case VM_CHKINV:		OP1_DISASM("chkinv");	break;
		case VM_TYPEOF:		OP1_DISASM("typeof");	break;
		case VM_EVAL:		OP1_DISASM("eval");		break;
		case VM_EEXP:		OP1_DISASM("eexp");		break;
		case VM_INT:		OP1_DISASM("int");		break;
		case VM_REAL:		OP1_DISASM("real");		break;
		case VM_STR:		OP1_DISASM("str");		break;
		case VM_OCTET:		OP1_DISASM("octet");	break;
#undef OP1_DISASM

		case VM_CCL:
			msg.printf(TJS_W("ccl %%%d-%%%d"), TJS_FROM_VM_REG_ADDR(CodeArea[i+1]),
				TJS_FROM_VM_REG_ADDR(CodeArea[i+1]) + CodeArea[i+2] -1);
			size = 3;
			break;

#define OP1_DISASM(c, x) \
	case c: \
		msg.printf(TJS_W(x) TJS_W(" %%%d"), TJS_FROM_VM_REG_ADDR(CodeArea[i+1])); \
		size = 2; \
		break; \
	case c+1: \
		msg.printf(TJS_W(x) TJS_W("pd") TJS_W(" %%%d, %%%d.*%d"), \
			TJS_FROM_VM_REG_ADDR(CodeArea[i+1]), \
			TJS_FROM_VM_REG_ADDR(CodeArea[i+2]), \
			TJS_FROM_VM_REG_ADDR(CodeArea[i+3])); \
		if(DataArea) \
		{ \
			com.printf(TJS_W("*%d = %ls"), \
				TJS_FROM_VM_REG_ADDR(CodeArea[i+3]), \
				GetValueComment(TJS_GET_VM_REG(DataArea, CodeArea[i+3])).c_str()); \
		} \
		size = 4; \
		break; \
	case c+2: \
		msg.printf(TJS_W(x) TJS_W("pi") TJS_W(" %%%d, %%%d.%%%d"), \
			TJS_FROM_VM_REG_ADDR(CodeArea[i+1]), \
			TJS_FROM_VM_REG_ADDR(CodeArea[i+2]), \
			TJS_FROM_VM_REG_ADDR(CodeArea[i+3])); \
		size = 4; \
		break; \
	case c+3: \
		msg.printf(TJS_W(x) TJS_W("p") TJS_W(" %%%d, %%%d"), \
			TJS_FROM_VM_REG_ADDR(CodeArea[i+1]), \
			TJS_FROM_VM_REG_ADDR(CodeArea[i+2])); \
		size = 3; \
		break

		// inc and dec
		OP1_DISASM(VM_INC,	"inc");
		OP1_DISASM(VM_DEC,	"dec");
#undef OP1_DISASM



#define OP1A_DISASM(x) \
	msg.printf(TJS_W(x) TJS_W(" %09d"), TJS_FROM_VM_CODE_ADDR(CodeArea[i+1]) + i); \
	size = 2
		// instructions that have one operand which represents code area
		case VM_JF:		OP1A_DISASM("jf");		break;
		case VM_JNF:	OP1A_DISASM("jnf");		break;
		case VM_JMP:	OP1A_DISASM("jmp");		break;
#undef OP1A_DISASM

		case VM_CALL:
		case VM_CALLD:
		case VM_CALLI:
		case VM_NEW:
		  {
			// function call variants

			msg.printf(
				CodeArea[i] == VM_CALL  ?TJS_W("call %%%d, %%%d("):
				CodeArea[i] == VM_CALLD ?TJS_W("calld %%%d, %%%d.*%d("):
				CodeArea[i] == VM_CALLI ?TJS_W("calli %%%d, %%%d.%%%d("):
										 TJS_W("new %%%d, %%%d("),
				TJS_FROM_VM_REG_ADDR(CodeArea[i+1]),
				TJS_FROM_VM_REG_ADDR(CodeArea[i+2]),
				TJS_FROM_VM_REG_ADDR(CodeArea[i+3]));
			tjs_int st; // start of arguments
			if(CodeArea[i] == VM_CALLD || CodeArea[i] == VM_CALLI)
				st = 5;
			else
				st = 4;
			tjs_int num = CodeArea[i+st-1];     // st-1 = argument count
			bool first = true;
			tjs_char buf[256];
			tjs_int c = 0;
			if(num == -1)
			{
				// omit arg
				size = st;
				msg += TJS_W("...");
			}
			else if(num == -2)
			{
				// expand arg
				st ++;
				num = CodeArea[i+st-1];
				size = st + num * 2;
				for(tjs_int j = 0; j < num; j++)
				{
					if(!first) msg += TJS_W(", ");
					first = false;
					switch(CodeArea[i+st+j*2])
					{
					case fatNormal:
						TJS_snprintf(buf, sizeof(buf)/sizeof(tjs_char), TJS_W("%%%d"),
							TJS_FROM_VM_REG_ADDR(CodeArea[i+st+j*2+1]));
						break;
					case fatExpand:
						TJS_snprintf(buf, sizeof(buf)/sizeof(tjs_char), TJS_W("%%%d*"),
							TJS_FROM_VM_REG_ADDR(CodeArea[i+st+j*2+1]));
						break;
					case fatUnnamedExpand:
						TJS_strcpy(buf, TJS_W("*"));
						break;
					}
					msg += buf;
				}
			}
			else
			{
				// normal operation
				size = st + num;
				while(num--)
				{
					if(!first) msg += TJS_W(", ");
					first = false;
					TJS_snprintf(buf, sizeof(buf)/sizeof(tjs_char), TJS_W("%%%d"),
						TJS_FROM_VM_REG_ADDR(CodeArea[i+c+st]));
					c++;
					msg += buf;
				}
			}

			msg += TJS_W(")");
			if(DataArea && CodeArea[i] == VM_CALLD)
			{
				com.printf(TJS_W("*%d = %ls"), TJS_FROM_VM_REG_ADDR(CodeArea[i+3]),
					GetValueComment(TJS_GET_VM_REG(DataArea, CodeArea[i+3])).c_str());
			}

			break;
		  }

		case VM_GPD:
		case VM_GPDS:
			// property get direct
			msg.printf(
				CodeArea[i] == VM_GPD?TJS_W("gpd %%%d, %%%d.*%d"):
									  TJS_W("gpds %%%d, %%%d.*%d"),
				TJS_FROM_VM_REG_ADDR(CodeArea[i+1]),
				TJS_FROM_VM_REG_ADDR(CodeArea[i+2]),
				TJS_FROM_VM_REG_ADDR(CodeArea[i+3]));
			if(DataArea)
			{
				com.printf(TJS_W("*%d = %ls"), TJS_FROM_VM_REG_ADDR(CodeArea[i+3]),
					GetValueComment(TJS_GET_VM_REG(DataArea, CodeArea[i+3])).c_str());
			}
			size = 4;
			break;


		case VM_SPD:
		case VM_SPDE:
		case VM_SPDEH:
		case VM_SPDS:
			// property set direct
			msg.printf(
				CodeArea[i] == VM_SPD ? TJS_W("spd %%%d.*%d, %%%d"):
				CodeArea[i] == VM_SPDE? TJS_W("spde %%%d.*%d, %%%d"):
				CodeArea[i] == VM_SPDEH?TJS_W("spdeh %%%d.*%d, %%%d"):
										TJS_W("spds %%%d.*%d, %%%d"),
				TJS_FROM_VM_REG_ADDR(CodeArea[i+1]),
				TJS_FROM_VM_REG_ADDR(CodeArea[i+2]),
				TJS_FROM_VM_REG_ADDR(CodeArea[i+3]));
			if(DataArea)
			{
				com.printf(TJS_W("*%d = %ls"), TJS_FROM_VM_REG_ADDR(CodeArea[i+2]),
					GetValueComment(TJS_GET_VM_REG(DataArea, CodeArea[i+2])).c_str());
			}

			size = 4;
			break;


		case VM_GPI:
		case VM_GPIS:
			// property get indirect
			msg.printf(
				CodeArea[i] == VM_GPI ?  TJS_W("gpi %%%d, %%%d.%%%d"):
										 TJS_W("gpis %%%d, %%%d.%%%d"),
				TJS_FROM_VM_REG_ADDR(CodeArea[i+1]),
				TJS_FROM_VM_REG_ADDR(CodeArea[i+2]),
				TJS_FROM_VM_REG_ADDR(CodeArea[i+3]));
			size = 4;
			break;


		case VM_SPI:
		case VM_SPIE:
		case VM_SPIS:
			// property set indirect
			msg.printf(
				CodeArea[i] == VM_SPI  ?TJS_W("spi %%%d.%%%d, %%%d"):
				CodeArea[i] == VM_SPIE ?TJS_W("spie %%%d.%%%d, %%%d"):
										TJS_W("spis %%%d.%%%d, %%%d"),
				TJS_FROM_VM_REG_ADDR(CodeArea[i+1]),
				TJS_FROM_VM_REG_ADDR(CodeArea[i+2]),
				TJS_FROM_VM_REG_ADDR(CodeArea[i+3]));
			size = 4;
			break;


		case VM_SETP:
			// property set
			msg.printf(
				TJS_W("setp %%%d, %%%d"),
					TJS_FROM_VM_REG_ADDR(CodeArea[i+1]),
					TJS_FROM_VM_REG_ADDR(CodeArea[i+2]));
			size = 3;
			break;

		case VM_GETP:
			// property get
			msg.printf(
				TJS_W("getp %%%d, %%%d"),
					TJS_FROM_VM_REG_ADDR(CodeArea[i+1]),
					TJS_FROM_VM_REG_ADDR(CodeArea[i+2]));
			size = 3;
			break;


		case VM_DELD:
		case VM_TYPEOFD:
			// member delete direct / typeof direct
			msg.printf(
				CodeArea[i] == VM_DELD   ?TJS_W("deld %%%d, %%%d.*%d"):
										  TJS_W("typeofd %%%d, %%%d.*%d"),
				TJS_FROM_VM_REG_ADDR(CodeArea[i+1]),
				TJS_FROM_VM_REG_ADDR(CodeArea[i+2]),
				TJS_FROM_VM_REG_ADDR(CodeArea[i+3]));
			if(DataArea)
			{
				com.printf(TJS_W("*%d = %ls"), TJS_FROM_VM_REG_ADDR(CodeArea[i+3]),
					GetValueComment(TJS_GET_VM_REG(DataArea, CodeArea[i+3])).c_str());
			}
			size = 4;
			break;

		case VM_DELI:
		case VM_TYPEOFI:
			// member delete indirect / typeof indirect
			msg.printf(
				CodeArea[i] == VM_DELI   ?TJS_W("deli %%%d, %%%d.%%%d"):
										  TJS_W("typeofi %%%d, %%%d.%%%d"),
				TJS_FROM_VM_REG_ADDR(CodeArea[i+1]),
				TJS_FROM_VM_REG_ADDR(CodeArea[i+2]),
				TJS_FROM_VM_REG_ADDR(CodeArea[i+3]));
			size = 4;
			break;

		case VM_SRV:
			// set return value
			msg.printf(TJS_W("srv %%%d"), TJS_FROM_VM_REG_ADDR(CodeArea[i+1]));
			size = 2;
			break;

		case VM_RET:
			// return
			msg.printf(TJS_W("ret"));
			size = 1;
			break;

		case VM_ENTRY:
			// enter try-protected block
			msg.printf(TJS_W("entry %09d, %%%d"),
				TJS_FROM_VM_CODE_ADDR(CodeArea[i+1]) + i,
				TJS_FROM_VM_REG_ADDR(CodeArea[i+2]));
			size = 3;
			break;


		case VM_EXTRY:
			// exit from try-protected block
			msg.printf(TJS_W("extry"));
			size = 1;
			break;

		case VM_THROW:
			msg.printf(TJS_W("throw %%%d"), TJS_FROM_VM_REG_ADDR(CodeArea[i+1]));
			size = 2;
			break;

		case VM_CHGTHIS:
			msg.printf(TJS_W("chgthis %%%d, %%%d"),
				TJS_FROM_VM_REG_ADDR(CodeArea[i+1]),
				TJS_FROM_VM_REG_ADDR(CodeArea[i+2]));
			size = 3;
			break;

		case VM_GLOBAL:
			msg.printf(TJS_W("global %%%d"),
				TJS_FROM_VM_REG_ADDR(CodeArea[i+1]));
			size = 2;
			break;

		case VM_ADDCI:
			msg.printf(TJS_W("addci %%%d, %%%d"),
				TJS_FROM_VM_REG_ADDR(CodeArea[i+1]),
				TJS_FROM_VM_REG_ADDR(CodeArea[i+2]));
			size = 3;
			break;

		case VM_REGMEMBER:
			msg.printf(TJS_W("regmember"));
			size = 1;
			break;

		case VM_DEBUGGER:
			msg.printf(TJS_W("debugger"));
			size = 1;
			break;

		default:
			msg.printf(TJS_W("unknown instruction %d"), CodeArea[i]);
			size = 1;
			break;
		} /* switch */

		output_func(msg.c_str(), com.c_str(), i,
			CodeArea + i, size, data);  // call the callback

		i+=size;
	}

}