438 lines
10 KiB
C++
438 lines
10 KiB
C++
|
#include <precomp.h>
|
||
|
#include "sdebuggerui.h"
|
||
|
#include <api/script/debugger/jitd.h>
|
||
|
#include <tataki/canvas/canvas.h>
|
||
|
#include <api/wnd/wndclass/editwnd.h>
|
||
|
#include <api/script/objcontroller.h>
|
||
|
#include <bfc/string/stringdict.h>
|
||
|
#include <bfc/parse/paramparser.h>
|
||
|
#include <api/wnd/notifmsg.h>
|
||
|
#include <api/script/objecttable.h>
|
||
|
#include <api/script/debugger/sourcecodeline.h>
|
||
|
#include "../nu/AutoWide.h"
|
||
|
|
||
|
#define LEFTCOLUMN 100
|
||
|
#define RIGHTCOLUMN 200
|
||
|
#define INPUTHEIGHT 21
|
||
|
#define NCONSOLELINES 4
|
||
|
#define LINEHEIGHT 14
|
||
|
#define REGWIDTH 100
|
||
|
|
||
|
SimpleDebuggerUI::SimpleDebuggerUI()
|
||
|
{
|
||
|
leave = 0;
|
||
|
jitd = NULL;
|
||
|
edit = NULL;
|
||
|
memset(cmdbuf, 0, sizeof(cmdbuf));
|
||
|
retcode = JITD_RETURN_CONTINUE;
|
||
|
}
|
||
|
|
||
|
SimpleDebuggerUI::~SimpleDebuggerUI()
|
||
|
{}
|
||
|
|
||
|
void SimpleDebuggerUI::setJITD(MakiJITD *_jitd)
|
||
|
{
|
||
|
jitd = _jitd;
|
||
|
}
|
||
|
|
||
|
int SimpleDebuggerUI::messageLoop()
|
||
|
{
|
||
|
leave = 0;
|
||
|
retcode = JITD_RETURN_STEPINTO;
|
||
|
|
||
|
if (!isInited())
|
||
|
{
|
||
|
setVirtual(0);
|
||
|
setStartHidden(1);
|
||
|
setParent(WASABI_API_WND->main_getRootWnd());
|
||
|
init(WASABI_API_WND->main_getRootWnd(), 1);
|
||
|
|
||
|
edit = new EditWnd;
|
||
|
edit->setParent(this);
|
||
|
edit->setBackgroundColor(RGB(0, 0, 0));
|
||
|
edit->setTextColor(RGB(0, 255, 0));
|
||
|
edit->setWantFocus(0);
|
||
|
|
||
|
*cmdbuf = 0;
|
||
|
edit->setBuffer(cmdbuf, 256);
|
||
|
edit->init(this);
|
||
|
|
||
|
RECT r;
|
||
|
POINT pt = {0, 0};
|
||
|
Wasabi::Std::getViewport(&r, &pt);
|
||
|
resize(r.right - 656, r.top + 16, 640, 480);
|
||
|
bringToFront();
|
||
|
}
|
||
|
|
||
|
for (int s = 0;s < jitd->getVSP();s++)
|
||
|
{
|
||
|
scriptVar v = WASABI_API_MAKIDEBUG->debugger_readStack(s);
|
||
|
StringW str;
|
||
|
switch (v.type)
|
||
|
{
|
||
|
case SCRIPT_VOID:
|
||
|
str = L"NULL";
|
||
|
break;
|
||
|
case SCRIPT_INT:
|
||
|
str = StringPrintfW(L"%d", GET_SCRIPT_INT(v));
|
||
|
break;
|
||
|
case SCRIPT_BOOLEAN:
|
||
|
str = StringPrintfW(L"%s", GET_SCRIPT_BOOLEAN(v) ? L"true" : L"false");
|
||
|
break;
|
||
|
case SCRIPT_FLOAT:
|
||
|
str = StringPrintfW(L"%f", GET_SCRIPT_FLOAT(v));
|
||
|
break;
|
||
|
case SCRIPT_DOUBLE:
|
||
|
str = StringPrintfW(L"%f", (float)GET_SCRIPT_DOUBLE(v));
|
||
|
break;
|
||
|
case SCRIPT_STRING:
|
||
|
str = GET_SCRIPT_STRING(v);
|
||
|
break;
|
||
|
default:
|
||
|
{
|
||
|
if (v.type == SCRIPT_OBJECT)
|
||
|
str = L"Object";
|
||
|
else
|
||
|
str = ObjectTable::getClassName(v.type);
|
||
|
#ifdef WASABI_COMPILE_SKIN
|
||
|
ScriptObject *o = GET_SCRIPT_OBJECT(v);
|
||
|
if (o != NULL)
|
||
|
{
|
||
|
GuiObject *go = static_cast<GuiObject *>(o->vcpu_getInterface(guiObjectGuid));
|
||
|
if (go != NULL)
|
||
|
{
|
||
|
str += L";";
|
||
|
str.cat(go->guiobject_getId());
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
strstack.addItem(new StringW(str));
|
||
|
}
|
||
|
|
||
|
setVisible(1);
|
||
|
|
||
|
//WASABI_API_WND->pushModalWnd(this);
|
||
|
|
||
|
#ifdef WIN32
|
||
|
MSG msg;
|
||
|
//DWORD leavetime = GetTickCount()+5;
|
||
|
while (!leave/* && !(GetTickCount() >leavetime)*/)
|
||
|
{
|
||
|
if (PeekMessage(&msg, /*(HWND)NULL*/ getOsWindowHandle(), 0, 0, PM_NOREMOVE))
|
||
|
{
|
||
|
GetMessage(&msg, /*(HWND) NULL*/getOsWindowHandle(), 0, 0) &&
|
||
|
TranslateMessage(&msg);
|
||
|
DispatchMessage(&msg);
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
//WASABI_API_WND->popModalWnd(this);
|
||
|
|
||
|
setVisible(0);
|
||
|
strstack.deleteAll();
|
||
|
|
||
|
return retcode;
|
||
|
}
|
||
|
|
||
|
int SimpleDebuggerUI::onPaint(Canvas *c)
|
||
|
{
|
||
|
SimpleDebuggerUI_PARENT::onPaint(c);
|
||
|
Wasabi::FontInfo fontInfo;
|
||
|
RECT r;
|
||
|
getClientRect(&r);
|
||
|
c->fillRect(&r, RGB(0, 0, 0));
|
||
|
c->drawRect(&r, 1, RGB(0, 255, 0));
|
||
|
|
||
|
fontInfo.color = RGB(0, 255, 0);
|
||
|
fontInfo.pointSize = 14;
|
||
|
fontInfo.face = L"Courier New";
|
||
|
c->pushPen(PENSTYLE_SOLID, 1, RGB(0, 255, 0));
|
||
|
c->textOut(r.right - REGWIDTH + 7, r.bottom - (INPUTHEIGHT + (NCONSOLELINES*LINEHEIGHT) + 2) + 8, StringPrintfW(L"VSD:%08X", jitd->getVSD()), &fontInfo);
|
||
|
c->textOut(r.right - REGWIDTH + 7, r.bottom - (INPUTHEIGHT + (NCONSOLELINES*LINEHEIGHT) + 2) + 8 + (LINEHEIGHT + 1), StringPrintfW(L"VIP:%08X", jitd->getVIP()), &fontInfo);
|
||
|
c->textOut(r.right - REGWIDTH + 7, r.bottom - (INPUTHEIGHT + (NCONSOLELINES*LINEHEIGHT) + 2) + 8 + (LINEHEIGHT + 1)*2, StringPrintfW(L"VSP:%08X", jitd->getVSP()), &fontInfo);
|
||
|
c->textOut(r.right - REGWIDTH + 7, r.bottom - (INPUTHEIGHT + (NCONSOLELINES*LINEHEIGHT) + 2) + 8 + (LINEHEIGHT + 1)*3, StringPrintfW(L"VCC:%08X", jitd->getVCC()), &fontInfo);
|
||
|
c->lineDraw(r.left, r.bottom - (INPUTHEIGHT + (NCONSOLELINES*LINEHEIGHT) + 2), r.right, r.bottom - (INPUTHEIGHT + (NCONSOLELINES*LINEHEIGHT) + 2));
|
||
|
c->lineDraw(r.left, r.bottom - (INPUTHEIGHT + 2), r.right - REGWIDTH, r.bottom - (INPUTHEIGHT + 2));
|
||
|
c->lineDraw(r.right - REGWIDTH, r.bottom - (INPUTHEIGHT + (NCONSOLELINES*LINEHEIGHT) + 2), r.right - REGWIDTH, r.bottom);
|
||
|
c->lineDraw(r.right - RIGHTCOLUMN, 0, r.right - RIGHTCOLUMN, r.bottom - (INPUTHEIGHT + (NCONSOLELINES*LINEHEIGHT) + 2));
|
||
|
disassemble(c);
|
||
|
for (int s = 0;s < strstack.getNumItems();s++)
|
||
|
{
|
||
|
c->textOutEllipsed(r.right - RIGHTCOLUMN + 4, s*LINEHEIGHT + 4, RIGHTCOLUMN - 8, 16, strstack.enumItem(s)->getValue(), &fontInfo);
|
||
|
}
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
int SimpleDebuggerUI::onLeftButtonDown(int x, int y)
|
||
|
{
|
||
|
SimpleDebuggerUI_PARENT::onLeftButtonDown(x, y);
|
||
|
if (edit) edit->onGetFocus();
|
||
|
// leave = 1;
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
void SimpleDebuggerUI::disassemble(Canvas *c)
|
||
|
{
|
||
|
RECT r;
|
||
|
getClientRect(&r);
|
||
|
int x = 4;
|
||
|
|
||
|
int y = (r.bottom - r.top - 4) / 2 + 4;
|
||
|
|
||
|
int ln = jitd->findLine(jitd->getVIP());
|
||
|
if (ln != -1)
|
||
|
{
|
||
|
Wasabi::FontInfo fontInfo;
|
||
|
SourceCodeLine *l = jitd->enumLine(ln);
|
||
|
int sourcecode = l->getSourceFile() != NULL;
|
||
|
int g;
|
||
|
int j = 0;
|
||
|
for (g = y;g < r.bottom - (INPUTHEIGHT + 4 + (NCONSOLELINES*LINEHEIGHT)) - LINEHEIGHT;g += LINEHEIGHT)
|
||
|
{
|
||
|
if (!sourcecode || j == 0)
|
||
|
l = jitd->enumLine(ln + j);
|
||
|
if (!l) break;
|
||
|
|
||
|
if (j == 0)
|
||
|
{
|
||
|
RECT br;
|
||
|
br.left = 4;
|
||
|
br.top = g;
|
||
|
br.right = r.right - (RIGHTCOLUMN + 4);
|
||
|
br.bottom = br.top + LINEHEIGHT;
|
||
|
c->fillRect(&br, RGB(0, 255, 0));
|
||
|
fontInfo.color = RGB(0, 0, 0);
|
||
|
}
|
||
|
if (!sourcecode)
|
||
|
{
|
||
|
String str;
|
||
|
unsigned const char *d = (unsigned const char *)(l->getPointer() + jitd->getCodeBlock());
|
||
|
for (int k = 0;k < l->getLength();k++)
|
||
|
{
|
||
|
if (!str.isempty()) str += " ";
|
||
|
str += StringPrintf("%02X", *d);
|
||
|
d++;
|
||
|
}
|
||
|
c->textOut(x, g, StringPrintfW(L"%08X", l->getPointer()), &fontInfo);
|
||
|
c->textOut(x + 70, g, AutoWide(str), &fontInfo);
|
||
|
c->textOut(x + 70 + 150, g, l->getLine(), &fontInfo);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
c->textOutEllipsed(x, g, r.right - r.left - (RIGHTCOLUMN + 4 + x), 16, (getLine(l->getSourceFile(), l->getSourceFileLine() + j)), &fontInfo);
|
||
|
}
|
||
|
|
||
|
j++;
|
||
|
}
|
||
|
j = 1;
|
||
|
for (g = y - LINEHEIGHT;g > 1;g -= LINEHEIGHT)
|
||
|
{
|
||
|
if (!sourcecode || j == 0)
|
||
|
l = jitd->enumLine(ln - j);
|
||
|
if (!l) break;
|
||
|
if (!sourcecode)
|
||
|
{
|
||
|
String str;
|
||
|
unsigned const char *d = (unsigned const char *)(l->getPointer() + jitd->getCodeBlock());
|
||
|
for (int k = 0;k < l->getLength();k++)
|
||
|
{
|
||
|
if (!str.isempty()) str += " ";
|
||
|
str += StringPrintf("%02X", *d);
|
||
|
d++;
|
||
|
}
|
||
|
c->textOut(x, g, StringPrintfW(L"%08X", l->getPointer()), &fontInfo);
|
||
|
c->textOut(x + 70, g, AutoWide(str), &fontInfo);
|
||
|
c->textOut(x + 70 + 150, g, (l->getLine()), &fontInfo);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
c->textOutEllipsed(x, g, r.right - r.left - (RIGHTCOLUMN + 4 + x), 16, (getLine(l->getSourceFile(), l->getSourceFileLine() - j)), &fontInfo);
|
||
|
}
|
||
|
j++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int SimpleDebuggerUI::onResize()
|
||
|
{
|
||
|
SimpleDebuggerUI_PARENT::onResize();
|
||
|
if (edit != NULL)
|
||
|
{
|
||
|
RECT r;
|
||
|
getClientRect(&r);
|
||
|
edit->resize(1, r.bottom - (INPUTHEIGHT + 1), r.right - r.left - (REGWIDTH + 1), INPUTHEIGHT);
|
||
|
}
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
int SimpleDebuggerUI::childNotify(ifc_window *child, int msg, intptr_t p1, intptr_t p2)
|
||
|
{
|
||
|
if (child == edit)
|
||
|
{
|
||
|
if (msg == ChildNotify::EDITWND_ENTER_PRESSED)
|
||
|
{
|
||
|
onCommand(cmdbuf);
|
||
|
}
|
||
|
}
|
||
|
return SimpleDebuggerUI_PARENT::childNotify(child, msg, p1, p2);
|
||
|
}
|
||
|
|
||
|
BEGIN_STRINGDICTIONARY(_debuggercommands)
|
||
|
SDI(L"b", DEBUG_CMD_BREAKPOINT);
|
||
|
SDI(L"break", DEBUG_CMD_BREAKPOINT);
|
||
|
SDI(L"x", DEBUG_CMD_CONTINUE);
|
||
|
SDI(L"continue", DEBUG_CMD_CONTINUE);
|
||
|
SDI(L"i", DEBUG_CMD_STEPINTO);
|
||
|
SDI(L"stepinto", DEBUG_CMD_STEPINTO);
|
||
|
SDI(L"o", DEBUG_CMD_STEPOVER);
|
||
|
SDI(L"stepover", DEBUG_CMD_STEPOVER);
|
||
|
SDI(L"p", DEBUG_CMD_STEPOUT);
|
||
|
SDI(L"stepout", DEBUG_CMD_STEPOUT);
|
||
|
SDI(L"k", DEBUG_CMD_KILL);
|
||
|
SDI(L"kill", DEBUG_CMD_KILL);
|
||
|
SDI(L"?", DEBUG_CMD_HELP);
|
||
|
SDI(L"help", DEBUG_CMD_HELP);
|
||
|
END_STRINGDICTIONARY(_debuggercommands, debuggercommands)
|
||
|
|
||
|
|
||
|
void SimpleDebuggerUI::onCommand(const wchar_t *cmd)
|
||
|
{
|
||
|
if (*cmd == 0)
|
||
|
{
|
||
|
stepOver();
|
||
|
return;
|
||
|
}
|
||
|
ParamParser pp(cmd, L" ");
|
||
|
int i = debuggercommands.getId(pp.enumItem(0));
|
||
|
switch (i)
|
||
|
{
|
||
|
case DEBUG_CMD_BREAKPOINT:
|
||
|
addBreakPoint(pp.enumItem(1));
|
||
|
break;
|
||
|
case DEBUG_CMD_CONTINUE:
|
||
|
continueExecution();
|
||
|
break;
|
||
|
case DEBUG_CMD_STEPINTO:
|
||
|
stepInto();
|
||
|
break;
|
||
|
case DEBUG_CMD_STEPOVER:
|
||
|
stepOver();
|
||
|
break;
|
||
|
case DEBUG_CMD_KILL:
|
||
|
killScript();
|
||
|
break;
|
||
|
case DEBUG_CMD_HELP:
|
||
|
showHelp();
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int SimpleDebuggerUI::evaluate(const wchar_t *ascii)
|
||
|
{
|
||
|
if (!_wcsicmp(ascii, L"VSD")) return jitd->getVSD();
|
||
|
if (!_wcsicmp(ascii, L"VIP")) return jitd->getVIP();
|
||
|
if (!_wcsicmp(ascii, L"VSP")) return jitd->getVSP();
|
||
|
if (!_wcsicmp(ascii, L"VCC")) return jitd->getVCC();
|
||
|
wchar_t *end;
|
||
|
return wcstol(ascii, &end, 16);
|
||
|
}
|
||
|
|
||
|
void SimpleDebuggerUI::addBreakPoint(const wchar_t *pointer_ascii)
|
||
|
{
|
||
|
/*int i = */evaluate(pointer_ascii);
|
||
|
}
|
||
|
|
||
|
void SimpleDebuggerUI::continueExecution()
|
||
|
{
|
||
|
retcode = JITD_RETURN_CONTINUE;
|
||
|
leave = 1;
|
||
|
}
|
||
|
|
||
|
void SimpleDebuggerUI::stepInto()
|
||
|
{
|
||
|
retcode = JITD_RETURN_STEPINTO;
|
||
|
leave = 1;
|
||
|
}
|
||
|
|
||
|
void SimpleDebuggerUI::stepOver()
|
||
|
{
|
||
|
int ln = jitd->findLine(jitd->getVIP());
|
||
|
ln++;
|
||
|
SourceCodeLine *l = jitd->enumLine(ln);
|
||
|
|
||
|
if (l != NULL) // else ret as last opcode
|
||
|
jitd->setSysBreakpoint(l->getPointer());
|
||
|
|
||
|
retcode = JITD_RETURN_CONTINUE;
|
||
|
leave = 1;
|
||
|
}
|
||
|
|
||
|
void SimpleDebuggerUI::killScript()
|
||
|
{
|
||
|
retcode = JITD_RETURN_TERMINATE;
|
||
|
leave = 1;
|
||
|
}
|
||
|
|
||
|
void SimpleDebuggerUI::showHelp()
|
||
|
{}
|
||
|
|
||
|
int SimpleDebuggerUI::onGetFocus()
|
||
|
{
|
||
|
SimpleDebuggerUI_PARENT::onGetFocus();
|
||
|
if (edit) edit->onGetFocus();
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
void SimpleDebuggerUI::onSetVisible(int show)
|
||
|
{
|
||
|
SimpleDebuggerUI_PARENT::onSetVisible(show);
|
||
|
if (edit) edit->onGetFocus();
|
||
|
}
|
||
|
#undef fgets
|
||
|
const wchar_t *SimpleDebuggerUI::getLine(const wchar_t *filename, int fileline)
|
||
|
{
|
||
|
if (fileline <= 0)
|
||
|
return L"";
|
||
|
static StringW str;
|
||
|
FILE *f = _wfopen(filename, L"rt");
|
||
|
if (!f)
|
||
|
{
|
||
|
str = L"couldn't load ";
|
||
|
str += filename;
|
||
|
return str;
|
||
|
}
|
||
|
|
||
|
char t[256] = {0};
|
||
|
char u[256] = {0};
|
||
|
int n = fileline;
|
||
|
while (n--)
|
||
|
{
|
||
|
*u = 0;
|
||
|
char *p;
|
||
|
do
|
||
|
{
|
||
|
p = *u ? t : u;
|
||
|
fgets(p, 255, f);
|
||
|
t[255] = 0;
|
||
|
}
|
||
|
while (!feof(f) && p[STRLEN(p)-1] != '\n' && p[STRLEN(p)-1] != '\r');
|
||
|
}
|
||
|
|
||
|
char *p = u;
|
||
|
while (p && *p && p < u + 256)
|
||
|
{
|
||
|
if (*p < 0x21) *p = ' ';
|
||
|
p++;
|
||
|
}
|
||
|
|
||
|
str = AutoWide(u, CP_UTF8);
|
||
|
fclose(f);
|
||
|
|
||
|
return str;
|
||
|
}
|
||
|
|