//--------------------------------------------------------------------------- tjs_char * TJS_tTVInt_to_str(tjs_int64 value, tjs_char *string) { if(value == TJS_UI64_VAL(0x8000000000000000)) { // this is a special number which we must avoid normal conversion TJS_strcpy(string, TJS_W("-9223372036854775808")); return string; } tjs_char *ostring = string; if(value<0) *(string++) = TJS_W('-'), value = -value; tjs_char buf[40]; tjs_char *p = buf; do { *(p++) = (value % 10) + TJS_W('0'); value /= 10; } while(value); p--; while(buf <= p) *(string++) = *(p--); *string = 0; return ostring; }
//--------------------------------------------------------------------------- tjs_int TJS_cdecl tTJSString::printf(const tjs_char *format, ...) { tjs_int r; tjs_char *buf = new tjs_char [TJS_TTSTR_SPRINTF_BUF_SIZE]; try { tjs_int size = TJS_TTSTR_SPRINTF_BUF_SIZE-1; /*TJS_vsnprintf(NULL, 0, format, param);*/ va_list param; va_start(param, format); r = TJS_vsnprintf(buf, size, format, param); AllocBuffer(r); if(r) { TJS_strcpy(const_cast<tjs_char*>(c_str()), buf); } va_end(param); FixLen(); } catch(...) { delete [] buf; throw; } delete [] buf; return r; }
/* these functions do : replace each %%, %1, %2 into %, p1, p2. %1 must appear only once in the message string, otherwise internal buffer will overflow. ( %2 must also so ) */ ttstr TVPFormatMessage(const tjs_char *msg, const ttstr & p1) { tjs_char *p; tjs_char * buf = new tjs_char[TJS_strlen(msg) + p1.GetLen() + 1]; p = buf; for(;*msg;msg++,p++) { if(*msg == TJS_W('%')) { if(msg[1] == TJS_W('%')) { // %% *p = TJS_W('%'); msg++; continue; } else if(msg[1] == TJS_W('1')) { // %1 TJS_strcpy(p, p1.c_str()); p += p1.GetLen(); p--; msg++; continue; } } *p = *msg; } *p = 0; ttstr ret(buf); delete [] buf; return ret; }
//--------------------------------------------------------------------------- void tTJS::OutputToConsoleWithCentering(const tjs_char *msg, tjs_uint width) const { // this function does not matter whether msg includes ZENKAKU characters ... if(!msg) return; tjs_int len = TJS_strlen(msg); tjs_int ns = ((tjs_int)width - len)/2; if(ns<=0) { OutputToConsole(msg); } else { tjs_char *outbuf = new tjs_char[ns + len +1]; tjs_char *p = outbuf; while(ns--) *(p++)= TJS_W(' '); TJS_strcpy(p, msg); try { OutputToConsole(outbuf); } catch(...) { delete [] outbuf; throw; } delete [] outbuf; } }
int TVPWriteHWEDumpFile( EXCEPTION_POINTERS* pExceptionPointers ) { BOOL bMiniDumpSuccessful; WCHAR szPath[MAX_PATH]; WCHAR szFileName[MAX_PATH]; const wchar_t* szAppName = TVPKirikiri; const wchar_t* szVersion = TVPGetVersionString().c_str(); TVPEnsureDataPathDirectory(); TJS_strcpy(szPath, TVPNativeDataPath.c_str()); SYSTEMTIME stLocalTime; ::GetLocalTime( &stLocalTime ); StringCchPrintf( szFileName, MAX_PATH, L"%s%s%s-%04d%02d%02d-%02d%02d%02d-%ld-%ld.dmp", szPath, szAppName, szVersion, stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay, stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond, GetCurrentProcessId(), GetCurrentThreadId()); HANDLE hDumpFile = ::CreateFile(szFileName, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_WRITE|FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0); MINIDUMP_EXCEPTION_INFORMATION ExpParam; ExpParam.ThreadId = ::GetCurrentThreadId(); ExpParam.ExceptionPointers = pExceptionPointers; ExpParam.ClientPointers = TRUE; bMiniDumpSuccessful = MiniDumpWriteDump( ::GetCurrentProcess(), ::GetCurrentProcessId(), hDumpFile, MiniDumpWithDataSegs, &ExpParam, NULL, NULL); return EXCEPTION_EXECUTE_HANDLER; }
//--------------------------------------------------------------------------- void tTJSScriptBlock::SetName(const tjs_char *name, tjs_int lineofs) { if(Name) delete [] Name, Name = NULL; if(name) { LineOffset = lineofs; Name = new tjs_char[ TJS_strlen(name) + 1]; TJS_strcpy(Name, name); } }
//--------------------------------------------------------------------------- void TVPClipboardSetText(const ttstr & text) { if( ::OpenClipboard(0) ) { HGLOBAL ansihandle = NULL; HGLOBAL unicodehandle = NULL; try { // store ANSI string std::string ansistr = text.AsNarrowStdString(); int ansistrlen = (ansistr.length() + 1)*sizeof(char); ansihandle = ::GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, ansistrlen); if( !ansihandle ) TVPThrowExceptionMessage( TVPFaildClipboardCopy ); char *mem = (char*)::GlobalLock(ansihandle); if(mem) strncpy_s(mem, ansistrlen, ansistr.c_str(),ansistrlen); ::GlobalUnlock(ansihandle); ::SetClipboardData( CF_TEXT, ansihandle ); ansihandle = NULL; // store UNICODE string unicodehandle = ::GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, (text.GetLen() + 1) * sizeof(tjs_char)); if(!unicodehandle) TVPThrowExceptionMessage( TVPFaildClipboardCopy );; tjs_char *unimem = (tjs_char*)::GlobalLock(unicodehandle); if(unimem) TJS_strcpy(unimem, text.c_str()); ::GlobalUnlock(unicodehandle); ::SetClipboardData( CF_UNICODETEXT, unicodehandle ); unicodehandle = NULL; } catch(...) { if(ansihandle) ::GlobalFree(ansihandle); if(unicodehandle) ::GlobalFree(unicodehandle); ::CloseClipboard(); throw; } ::CloseClipboard(); } }
//--------------------------------------------------------------------------- void tTJS::OutputToConsoleSeparator(const tjs_char *text, tjs_uint count) const { tjs_int len = TJS_strlen(text); tjs_char *outbuf = new tjs_char [ len * count + 1]; tjs_char *p = outbuf; while(count--) { TJS_strcpy(p, text); p += len; } try { OutputToConsole(outbuf); } catch(...) { delete [] outbuf; throw; } delete [] outbuf; }
void tTJSScriptBlock::SetText(tTJSVariant *result, const tjs_char *text, iTJSDispatch2 * context, bool isexpression) { TJS_F_TRACE("tTJSScriptBlock::SetText"); // compiles text and executes its global level scripts. // the script will be compiled as an expression if isexpressn is true. if(!text) return; if(!text[0]) return; TJS_D((TJS_W("Counting lines ...\n"))) Script = new tjs_char[TJS_strlen(text)+1]; TJS_strcpy(Script, text); // calculation of line-count tjs_char *ls = Script; tjs_char *p = Script; while(*p) { if(*p == TJS_W('\r') || *p == TJS_W('\n')) { LineVector.push_back(int(ls - Script)); LineLengthVector.push_back(int(p - ls)); if(*p == TJS_W('\r') && p[1] == TJS_W('\n')) p++; p++; ls = p; } else { p++; } } if(p!=ls) { LineVector.push_back(int(ls - Script)); LineLengthVector.push_back(int(p - ls)); } try { // parse and execute #ifdef TJS_DEBUG_PROFILE_TIME { tTJSTimeProfiler p(parsetime); #endif Parse(text, isexpression, result != NULL); #ifdef TJS_DEBUG_PROFILE_TIME } { char buf[256]; sprintf(buf, "parsing : %d", parsetime); OutputDebugString(buf); if(parsetime) { sprintf(buf, "Commit : %d (%d%%)", time_Commit, time_Commit*100/parsetime); OutputDebugString(buf); sprintf(buf, "yylex : %d (%d%%)", time_yylex, time_yylex*100/parsetime); OutputDebugString(buf); sprintf(buf, "MakeNP : %d (%d%%)", time_make_np, time_make_np*100/parsetime); OutputDebugString(buf); sprintf(buf, "GenNodeCode : %d (%d%%)", time_GenNodeCode, time_GenNodeCode*100/parsetime); OutputDebugString(buf); sprintf(buf, " PutCode : %d (%d%%)", time_PutCode, time_PutCode*100/parsetime); OutputDebugString(buf); sprintf(buf, " PutData : %d (%d%%)", time_PutData, time_PutData*100/parsetime); OutputDebugString(buf); sprintf(buf, " this_proxy : %d (%d%%)", time_this_proxy, time_this_proxy*100/parsetime); OutputDebugString(buf); sprintf(buf, "ns::Push : %d (%d%%)", time_ns_Push, time_ns_Push*100/parsetime); OutputDebugString(buf); sprintf(buf, "ns::Pop : %d (%d%%)", time_ns_Pop, time_ns_Pop*100/parsetime); OutputDebugString(buf); sprintf(buf, "ns::Find : %d (%d%%)", time_ns_Find, time_ns_Find*100/parsetime); OutputDebugString(buf); sprintf(buf, "ns::Remove : %d (%d%%)", time_ns_Remove, time_ns_Remove*100/parsetime); OutputDebugString(buf); sprintf(buf, "ns::Commit : %d (%d%%)", time_ns_Commit, time_ns_Commit*100/parsetime); OutputDebugString(buf); } } #endif #ifdef TJS_DEBUG_DISASM std::list<tTJSInterCodeContext *>::iterator i = InterCodeContextList.begin(); while(i != InterCodeContextList.end()) { ConsoleOutput(TJS_W(""), (void*)this); ConsoleOutput((*i)->GetName(), (void*)this); (*i)->Disassemble(ConsoleOutput, (void*)this); i++; } #endif // execute global level script ExecuteTopLevelScript(result, context); } catch(...) { if(InterCodeContextList.size() != 1) { if(TopLevelContext) TopLevelContext->Release(), TopLevelContext = NULL; while(ContextStack.size()) { ContextStack.top()->Release(); ContextStack.pop(); } } throw; } if(InterCodeContextList.size() != 1) { // this is not a single-context script block // (may hook itself) // release all contexts and global at this time if(TopLevelContext) TopLevelContext->Release(), TopLevelContext = NULL; while(ContextStack.size()) { ContextStack.top()->Release(); ContextStack.pop(); } } }
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; } }