//--------------------------------------------------------------------------- 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_sprintf(buf, TJS_W("\\x%02x"), (int)*p); hexflag = true; ret += buf; continue; } } if(*p < 0x20) { tjs_char buf[20]; TJS_sprintf(buf, TJS_W("\\x%02x"), (int)*p); hexflag = true; ret += buf; } else { ret += *p; hexflag = false; } } } return ret; }
//--------------------------------------------------------------------------- ttstr TVPGetVersionInformation(void) { TVPGetVersion(); tjs_char verstr[100]; TJS_sprintf(verstr, TJS_W("%d.%d.%d.%d"), TVPVersionMajor, TVPVersionMinor, TVPVersionRelease, TVPVersionBuild); tjs_char tjsverstr[100]; TJS_sprintf(tjsverstr, TJS_W("%d.%d.%d"), TJSVersionMajor, TJSVersionMinor, TJSVersionRelease); return TVPFormatMessage(TVPVersionInformation, verstr, tjsverstr); }
//--------------------------------------------------------------------------- // version information related functions //--------------------------------------------------------------------------- ttstr TVPGetAboutString(void) { TVPGetVersion(); tjs_char verstr[100]; TJS_sprintf(verstr, TJS_W("%d.%d.%d.%d"), TVPVersionMajor, TVPVersionMinor, TVPVersionRelease, TVPVersionBuild); tjs_char tjsverstr[100]; TJS_sprintf(tjsverstr, TJS_W("%d.%d.%d"), TJSVersionMajor, TJSVersionMinor, TJSVersionRelease); return TVPFormatMessage(TVPAboutString, verstr, tjsverstr) + TVPGetImportantLog(); }
//--------------------------------------------------------------------------- ttstr TVPGetVersionString() { TVPGetVersion(); tjs_char verstr[100]; TJS_sprintf(verstr, TJS_W("%d.%d.%d.%d"), TVPVersionMajor, TVPVersionMinor, TVPVersionRelease, TVPVersionBuild); return ttstr(verstr); }
//--------------------------------------------------------------------------- void tTJSScriptBlock::Dump() const { std::list<tTJSInterCodeContext *>::const_iterator i = InterCodeContextList.begin(); while(i != InterCodeContextList.end()) { ConsoleOutput(TJS_W(""), (void*)this); tjs_char ptr[256]; TJS_sprintf(ptr, TJS_W(" 0x%p"), (*i)); ConsoleOutput((ttstr(TJS_W("(")) + ttstr((*i)->GetContextTypeName()) + TJS_W(") ") + ttstr((*i)->GetName()) + ptr).c_str(), (void*)this); (*i)->Disassemble(ConsoleOutput, (void*)this); i++; } }
//--------------------------------------------------------------------------- void tTJSScriptBlock::ExecuteTopLevelScript(tTJSVariant *result, iTJSDispatch2 * context) { if(TopLevelContext) { #ifdef TJS_DEBUG_PROFILE_TIME clock_t start = clock(); #endif TopLevelContext->FuncCall(0, NULL, NULL, result, 0, NULL, context); #ifdef TJS_DEBUG_PROFILE_TIME tjs_char str[100]; TJS_sprintf(str, TJS_W("%d"), clock() - start); ConsoleOutput(str, (void*)this); #endif } }
//--------------------------------------------------------------------------- ttstr tTJSScriptBlock::GetLineDescriptionString(tjs_int pos) const { // get short description, like "mainwindow.tjs(321)" // pos is in character count from the first of the script tjs_int line =SrcPosToLine(pos)+1; ttstr name; if(Name) { name = Name; } else { tjs_char ptr[128]; TJS_sprintf(ptr, TJS_W("0x%p"), this); name = ttstr(TJS_W("anonymous@")) + ptr; } return name + TJS_W("(") + ttstr(line) + TJS_W(")"); }
//--------------------------------------------------------------------------- void __fastcall TTVPMainForm::SystemWatchTimerTimer(TObject *Sender) { if(TVPTerminated) { // this will ensure terminating the application. // the WM_QUIT message disappears in some unknown situations... ::PostMessage(TVPMainForm->Handle, WM_USER+0x31/*dummy msg*/, 0, 0); Application->Terminate(); ::PostMessage(TVPMainForm->Handle, WM_USER+0x31/*dummy msg*/, 0, 0); } // call events DWORD tick = GetTickCount(); // push environ noise TVPPushEnvironNoise(&tick, sizeof(tick)); TVPPushEnvironNoise(&LastCompactedTick, sizeof(LastCompactedTick)); TVPPushEnvironNoise(&LastShowModalWindowSentTick, sizeof(LastShowModalWindowSentTick)); TVPPushEnvironNoise(&MixedIdleTick, sizeof(MixedIdleTick)); POINT pt; GetCursorPos(&pt); TVPPushEnvironNoise(&pt, sizeof(pt)); // CPU clock monitoring { static bool clock_rough_printed = false; if(!clock_rough_printed && TVPCPUClockAccuracy == ccaRough) { tjs_char msg[80]; TJS_sprintf(msg, TJS_W("(info) CPU clock (roughly) : %dMHz"), (int)TVPCPUClock); TVPAddImportantLog(msg); clock_rough_printed = true; } static bool clock_printed = false; if(!clock_printed && TVPCPUClockAccuracy == ccaAccurate) { tjs_char msg[80]; TJS_sprintf(msg, TJS_W("(info) CPU clock : %.1fMHz"), (float)TVPCPUClock); TVPAddImportantLog(msg); clock_printed = true; } } // check status and deliver events DeliverEvents(); // call TickBeat tjs_int count = TVPGetWindowCount(); for(tjs_int i = 0; i<count; i++) { tTJSNI_Window *win = TVPGetWindowListAt(i); win->TickBeat(); } if(!ContinuousEventCalling && tick - LastCompactedTick > 4000) { // idle state over 4 sec. LastCompactedTick = tick; // fire compact event TVPDeliverCompactEvent(TVP_COMPACT_LEVEL_IDLE); } if(!ContinuousEventCalling && tick > LastRehashedTick + 1500) { // TJS2 object rehash LastRehashedTick = tick; TJSDoRehash(); } if(LastCloseClickedTick && tick - LastCloseClickedTick > 3100) { // display force suicide confirmation form if(TVPHaltWarnForm) { TVPHaltWarnForm->Visible = true; } else { TVPHaltWarnForm = new TTVPHaltWarnForm(Application); TVPHaltWarnForm->Visible = true; } } // ensure modal window visible if(tick > LastShowModalWindowSentTick + 4100) { // ::PostMessage(Handle, WM_USER+0x32, 0, 0); // This is currently disabled because IME composition window // hides behind the window which is bringed top by the // window-rearrangement. LastShowModalWindowSentTick = tick; } }
//--------------------------------------------------------------------------- void tTJS::Dump(tjs_uint width) const { // dumps all existing script block tjs_char version[100]; TJS_sprintf(version, 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_sprintf(buf, 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_sprintf(ptr, TJS_W(" 0x%p"), (*i)); title += ptr; OutputToConsole(title.c_str()); n = (*i)->GetContextCount(); totalcontexts += n; TJS_sprintf(buf, TJS_W("\tCount of contexts : %d"), n); OutputToConsole(buf); n = (*i)->GetTotalVMCodeSize(); totalcodesize += n; TJS_sprintf(buf, TJS_W("\tVM code area size : %d words"), n); OutputToConsole(buf); n = (*i)->GetTotalVMDataSize(); totaldatasize += n; TJS_sprintf(buf, TJS_W("\tVM constant data count : %d"), n); OutputToConsole(buf); OutputToConsole(TJS_W("")); } TJS_sprintf(buf, TJS_W("Total count of contexts : %d"), totalcontexts); OutputToConsole(buf); TJS_sprintf(buf, TJS_W("Total VM code area size : %d words"), totalcodesize); OutputToConsole(buf); TJS_sprintf(buf, 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_sprintf(ptr, 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.")); } }
//--------------------------------------------------------------------------- void TVPDumpHWException() { // dump latest hardware exception if it exists if(!TVPHWExcRaised) return; TVPHWExcRaised = false; TVPOnError(); tjs_char buf[256]; tTVPHWExceptionData * d = &TVPLastHWExceptionData; TVPAddLog(ttstr(TVPHardwareExceptionRaised)); ttstr line; line = TJS_W("Exception : "); tjs_char *p = NULL; switch(d->Code) { case 3: p = TJS_W("Divide By Zero"); break; case 4: p = TJS_W("Range Error"); break; case 5: p = TJS_W("Integer Overflow"); break; case 6: p = TJS_W("Invalid Operation"); break; case 7: p = TJS_W("Zero Divide"); break; case 8: p = TJS_W("Overflow"); break; case 9: p = TJS_W("Underflow"); break; case 10: p = TJS_W("Invalid Cast"); break; case 11: p = TJS_W("Access Violation"); break; case 12: p = TJS_W("Privilege Violation"); break; case 13: p = TJS_W("Control C"); break; case 14: p = TJS_W("Stack Overflow"); break; } if(p) line += p; if(d->Code == 11) { // EAccessViolation const tjs_char *mode = TJS_W("unknown"); if(d->AccessFlag == 0) mode = TJS_W("read"); else if(d->AccessFlag == 1) mode = TJS_W("write"); else if(d->AccessFlag == 8) mode = TJS_W("execute"); TJS_sprintf(buf, TJS_W("(%ls access to 0x%p)"), mode, d->AccessTarget); line += buf; } TJS_sprintf(buf, TJS_W(" at EIP = 0x%p ESP = 0x%p"), d->EIP, d->ESP); line += buf; if(d->Module[0]) { line += TJS_W(" in ") + ttstr(d->Module); } TVPAddLog(line); // dump OS context TVPDumpOSContext(d->Context); // dump codes at EIP line = TJS_W("Codes at EIP : "); for(tjs_int i = 0; i<d->CodesAtEIPLen; i++) { TJS_sprintf(buf, TJS_W("0x%02X "), d->CodesAtEIP[i]); line += buf; } TVPAddLog(line); TVPAddLog(TJS_W("Stack data and data pointed by each stack data :")); // dump stack and data for(tjs_int s = 0; s<d->StackAtESPLen; s++) { TJS_sprintf(buf, TJS_W("0x%p (ESP+%3d) : 0x%p : "), (DWORD)d->ESP + s*sizeof(tjs_uint32), s*sizeof(tjs_uint32), d->StackAtESP[s]); line = buf; for(tjs_int i = 0; i<d->StackDumpsLen[s]; i++) { TJS_sprintf(buf, TJS_W("0x%02X "), d->StackDumps[s][i]); line += buf; } TVPAddLog(line); } // dump call trace TVPAddLog(TJS_W("Call Trace :")); for(tjs_int s = 0; s<d->CallTraceLen; s++) { TJS_sprintf(buf, TJS_W("0x%p : "), d->CallTrace[s]); line = buf; for(tjs_int i = 0; i<d->CallTraceDumpsLen[s]; i++) { TJS_sprintf(buf, TJS_W("0x%02X "), d->CallTraceDumps[s][i]); line += buf; } MEMORY_BASIC_INFORMATION mbi; VirtualQuery((void*)d->CallTrace[s], &mbi, sizeof(mbi)); if(mbi.State == MEM_COMMIT) { char module[MAX_PATH]; if(GetModuleFileName((HMODULE)mbi.AllocationBase, module, MAX_PATH)) { line += ttstr(ExtractFileName(module).c_str()); TJS_sprintf(buf, TJS_W(" base 0x%p"), mbi.AllocationBase); line += buf; } } TVPAddLog(line); } }
//--------------------------------------------------------------------------- void TVPDumpOSContext(const CONTEXT &ctx) { // dump OS context block tjs_char buf[256]; // mask FP exception TJSSetFPUE(); // - context flags ttstr line; TJS_sprintf(buf, TJS_W("Context Flags : 0x%08X [ "), ctx.ContextFlags); line += buf; if(ctx.ContextFlags & CONTEXT_DEBUG_REGISTERS) line += TJS_W("CONTEXT_DEBUG_REGISTERS "); if(ctx.ContextFlags & CONTEXT_FLOATING_POINT) line += TJS_W("CONTEXT_FLOATING_POINT "); if(ctx.ContextFlags & CONTEXT_SEGMENTS) line += TJS_W("CONTEXT_SEGMENTS "); if(ctx.ContextFlags & CONTEXT_INTEGER) line += TJS_W("CONTEXT_INTEGER "); if(ctx.ContextFlags & CONTEXT_CONTROL) line += TJS_W("CONTEXT_CONTROL "); if(ctx.ContextFlags & CONTEXT_EXTENDED_REGISTERS) line += TJS_W("CONTEXT_EXTENDED_REGISTERS "); line += TJS_W("]"); TVPAddLog(line); // - debug registers TJS_sprintf(buf, TJS_W( "Debug Registers : " "0:0x%08X " "1:0x%08X " "2:0x%08X " "3:0x%08X " "6:0x%08X " "7:0x%08X "), ctx.Dr0, ctx.Dr1, ctx.Dr2, ctx.Dr3, ctx.Dr6, ctx.Dr7); TVPAddLog(buf); // - Segment registers TJS_sprintf(buf, TJS_W("Segment Registers : GS:0x%04X FS:0x%04X ES:0x%04X DS:0x%04X CS:0x%04X SS:0x%04X"), ctx.SegGs, ctx.SegFs, ctx.SegEs, ctx.SegDs, ctx.SegCs, ctx.SegSs); TVPAddLog(buf); // - Generic Integer Registers TJS_sprintf(buf, TJS_W("Integer Registers : EAX:0x%08X EBX:0x%08X ECX:0x%08X EDX:0x%08X"), ctx.Eax, ctx.Ebx, ctx.Ecx, ctx.Edx); TVPAddLog(buf); // - Index Registers TJS_sprintf(buf, TJS_W("Index Registers : ESI:0x%08X EDI:0x%08X"), ctx.Esi, ctx.Edi); TVPAddLog(buf); // - Pointer Registers TJS_sprintf(buf, TJS_W("Pointer Registers : EBP:0x%08X ESP:0x%08X EIP:0x%08X"), ctx.Ebp, ctx.Esp, ctx.Eip); TVPAddLog(buf); // - Flag Register TJS_sprintf(buf, TJS_W("Flag Register : 0x%08X [ "), ctx.EFlags); line = buf; TVPDumpCPUFlags(line, ctx.EFlags, (1<< 0), TJS_W("CF")); TVPDumpCPUFlags(line, ctx.EFlags, (1<< 2), TJS_W("PF")); TVPDumpCPUFlags(line, ctx.EFlags, (1<< 4), TJS_W("AF")); TVPDumpCPUFlags(line, ctx.EFlags, (1<< 6), TJS_W("ZF")); TVPDumpCPUFlags(line, ctx.EFlags, (1<< 7), TJS_W("SF")); TVPDumpCPUFlags(line, ctx.EFlags, (1<< 8), TJS_W("TF")); TVPDumpCPUFlags(line, ctx.EFlags, (1<< 9), TJS_W("IF")); TVPDumpCPUFlags(line, ctx.EFlags, (1<<10), TJS_W("DF")); TVPDumpCPUFlags(line, ctx.EFlags, (1<<11), TJS_W("OF")); TJS_sprintf(buf, TJS_W("IO%d "), (ctx.EFlags >> 12) & 0x03); line += buf; TVPDumpCPUFlags(line, ctx.EFlags, (1<<14), TJS_W("NF")); TVPDumpCPUFlags(line, ctx.EFlags, (1<<16), TJS_W("RF")); TVPDumpCPUFlags(line, ctx.EFlags, (1<<17), TJS_W("VM")); TVPDumpCPUFlags(line, ctx.EFlags, (1<<18), TJS_W("AC")); TVPDumpCPUFlags(line, ctx.EFlags, (1<<19), TJS_W("VF")); TVPDumpCPUFlags(line, ctx.EFlags, (1<<20), TJS_W("VP")); TVPDumpCPUFlags(line, ctx.EFlags, (1<<21), TJS_W("ID")); line += TJS_W("]"); TVPAddLog(line); // - FP registers // -- control words TJS_sprintf(buf, TJS_W("FP Control Word : 0x%08X FP Status Word : 0x%08X FP Tag Word : 0x%08X"), ctx.FloatSave.ControlWord, ctx.FloatSave.StatusWord, ctx.FloatSave.TagWord); TVPAddLog(buf); // -- offsets/selectors TJS_sprintf(buf, TJS_W("FP Error Offset : 0x%08X FP Error Selector : 0x%08X"), ctx.FloatSave.ErrorOffset, ctx.FloatSave.ErrorSelector); TJS_sprintf(buf, TJS_W("FP Data Offset : 0x%08X FP Data Selector : 0x%08X"), ctx.FloatSave.DataOffset, ctx.FloatSave.DataSelector); // -- registers long double *ptr = (long double *)&(ctx.FloatSave.RegisterArea[0]); for(tjs_int i = 0; i < 8; i++) { TJS_sprintf(buf, TJS_W("FP ST(%d) : %28.20Lg 0x%04X%016I64X"), i, ptr[i], (unsigned int)*(tjs_uint16*)(((tjs_uint8*)(ptr + i)) + 8), *(tjs_uint64*)(ptr + i)); TVPAddLog(buf); } // -- Cr0NpxState TJS_sprintf(buf, TJS_W("FP CR0 NPX State : 0x%08X"), ctx.FloatSave.Cr0NpxState); TVPAddLog(buf); // -- SSE/SSE2 registers if(ctx.ContextFlags & CONTEXT_EXTENDED_REGISTERS) { // ExtendedRegisters is a area which meets fxsave and fxrstor instruction? #pragma pack(push,1) union xmm_t { struct { float sA; float sB; float sC; float sD; }; struct { double dA; double dB; }; struct { tjs_uint64 i64A; tjs_uint64 i64B; }; }; #pragma pack(pop) for(tjs_int i = 0; i < 8; i++) { xmm_t * xmm = (xmm_t *)(ctx.ExtendedRegisters + i * 16+ 0xa0); TJS_sprintf(buf, TJS_W("XMM %d : [ %15.8g %15.8g %15.8g %15.8g ] [ %24.16lg %24.16lg ] [ 0x%016I64X-0x%016I64X ]"), i, xmm->sD, xmm->sC, xmm->sB, xmm->sA, xmm->dB, xmm->dA, xmm->i64B, xmm->i64A); TVPAddLog(buf); } TJS_sprintf(buf, TJS_W("MXCSR : 0x%08X"), *(DWORD*)(ctx.ExtendedRegisters + 0x18)); TVPAddLog(buf); } }