sdebuggerui.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  1. #include <precomp.h>
  2. #include "sdebuggerui.h"
  3. #include <api/script/debugger/jitd.h>
  4. #include <tataki/canvas/canvas.h>
  5. #include <api/wnd/wndclass/editwnd.h>
  6. #include <api/script/objcontroller.h>
  7. #include <bfc/string/stringdict.h>
  8. #include <bfc/parse/paramparser.h>
  9. #include <api/wnd/notifmsg.h>
  10. #include <api/script/objecttable.h>
  11. #include <api/script/debugger/sourcecodeline.h>
  12. #include "../nu/AutoWide.h"
  13. #define LEFTCOLUMN 100
  14. #define RIGHTCOLUMN 200
  15. #define INPUTHEIGHT 21
  16. #define NCONSOLELINES 4
  17. #define LINEHEIGHT 14
  18. #define REGWIDTH 100
  19. SimpleDebuggerUI::SimpleDebuggerUI()
  20. {
  21. leave = 0;
  22. jitd = NULL;
  23. edit = NULL;
  24. memset(cmdbuf, 0, sizeof(cmdbuf));
  25. retcode = JITD_RETURN_CONTINUE;
  26. }
  27. SimpleDebuggerUI::~SimpleDebuggerUI()
  28. {}
  29. void SimpleDebuggerUI::setJITD(MakiJITD *_jitd)
  30. {
  31. jitd = _jitd;
  32. }
  33. int SimpleDebuggerUI::messageLoop()
  34. {
  35. leave = 0;
  36. retcode = JITD_RETURN_STEPINTO;
  37. if (!isInited())
  38. {
  39. setVirtual(0);
  40. setStartHidden(1);
  41. setParent(WASABI_API_WND->main_getRootWnd());
  42. init(WASABI_API_WND->main_getRootWnd(), 1);
  43. edit = new EditWnd;
  44. edit->setParent(this);
  45. edit->setBackgroundColor(RGB(0, 0, 0));
  46. edit->setTextColor(RGB(0, 255, 0));
  47. edit->setWantFocus(0);
  48. *cmdbuf = 0;
  49. edit->setBuffer(cmdbuf, 256);
  50. edit->init(this);
  51. RECT r;
  52. POINT pt = {0, 0};
  53. Wasabi::Std::getViewport(&r, &pt);
  54. resize(r.right - 656, r.top + 16, 640, 480);
  55. bringToFront();
  56. }
  57. for (int s = 0;s < jitd->getVSP();s++)
  58. {
  59. scriptVar v = WASABI_API_MAKIDEBUG->debugger_readStack(s);
  60. StringW str;
  61. switch (v.type)
  62. {
  63. case SCRIPT_VOID:
  64. str = L"NULL";
  65. break;
  66. case SCRIPT_INT:
  67. str = StringPrintfW(L"%d", GET_SCRIPT_INT(v));
  68. break;
  69. case SCRIPT_BOOLEAN:
  70. str = StringPrintfW(L"%s", GET_SCRIPT_BOOLEAN(v) ? L"true" : L"false");
  71. break;
  72. case SCRIPT_FLOAT:
  73. str = StringPrintfW(L"%f", GET_SCRIPT_FLOAT(v));
  74. break;
  75. case SCRIPT_DOUBLE:
  76. str = StringPrintfW(L"%f", (float)GET_SCRIPT_DOUBLE(v));
  77. break;
  78. case SCRIPT_STRING:
  79. str = GET_SCRIPT_STRING(v);
  80. break;
  81. default:
  82. {
  83. if (v.type == SCRIPT_OBJECT)
  84. str = L"Object";
  85. else
  86. str = ObjectTable::getClassName(v.type);
  87. #ifdef WASABI_COMPILE_SKIN
  88. ScriptObject *o = GET_SCRIPT_OBJECT(v);
  89. if (o != NULL)
  90. {
  91. GuiObject *go = static_cast<GuiObject *>(o->vcpu_getInterface(guiObjectGuid));
  92. if (go != NULL)
  93. {
  94. str += L";";
  95. str.cat(go->guiobject_getId());
  96. }
  97. }
  98. #endif
  99. break;
  100. }
  101. }
  102. strstack.addItem(new StringW(str));
  103. }
  104. setVisible(1);
  105. //WASABI_API_WND->pushModalWnd(this);
  106. #ifdef WIN32
  107. MSG msg;
  108. //DWORD leavetime = GetTickCount()+5;
  109. while (!leave/* && !(GetTickCount() >leavetime)*/)
  110. {
  111. if (PeekMessage(&msg, /*(HWND)NULL*/ getOsWindowHandle(), 0, 0, PM_NOREMOVE))
  112. {
  113. GetMessage(&msg, /*(HWND) NULL*/getOsWindowHandle(), 0, 0) &&
  114. TranslateMessage(&msg);
  115. DispatchMessage(&msg);
  116. }
  117. }
  118. #endif
  119. //WASABI_API_WND->popModalWnd(this);
  120. setVisible(0);
  121. strstack.deleteAll();
  122. return retcode;
  123. }
  124. int SimpleDebuggerUI::onPaint(Canvas *c)
  125. {
  126. SimpleDebuggerUI_PARENT::onPaint(c);
  127. Wasabi::FontInfo fontInfo;
  128. RECT r;
  129. getClientRect(&r);
  130. c->fillRect(&r, RGB(0, 0, 0));
  131. c->drawRect(&r, 1, RGB(0, 255, 0));
  132. fontInfo.color = RGB(0, 255, 0);
  133. fontInfo.pointSize = 14;
  134. fontInfo.face = L"Courier New";
  135. c->pushPen(PENSTYLE_SOLID, 1, RGB(0, 255, 0));
  136. c->textOut(r.right - REGWIDTH + 7, r.bottom - (INPUTHEIGHT + (NCONSOLELINES*LINEHEIGHT) + 2) + 8, StringPrintfW(L"VSD:%08X", jitd->getVSD()), &fontInfo);
  137. c->textOut(r.right - REGWIDTH + 7, r.bottom - (INPUTHEIGHT + (NCONSOLELINES*LINEHEIGHT) + 2) + 8 + (LINEHEIGHT + 1), StringPrintfW(L"VIP:%08X", jitd->getVIP()), &fontInfo);
  138. c->textOut(r.right - REGWIDTH + 7, r.bottom - (INPUTHEIGHT + (NCONSOLELINES*LINEHEIGHT) + 2) + 8 + (LINEHEIGHT + 1)*2, StringPrintfW(L"VSP:%08X", jitd->getVSP()), &fontInfo);
  139. c->textOut(r.right - REGWIDTH + 7, r.bottom - (INPUTHEIGHT + (NCONSOLELINES*LINEHEIGHT) + 2) + 8 + (LINEHEIGHT + 1)*3, StringPrintfW(L"VCC:%08X", jitd->getVCC()), &fontInfo);
  140. c->lineDraw(r.left, r.bottom - (INPUTHEIGHT + (NCONSOLELINES*LINEHEIGHT) + 2), r.right, r.bottom - (INPUTHEIGHT + (NCONSOLELINES*LINEHEIGHT) + 2));
  141. c->lineDraw(r.left, r.bottom - (INPUTHEIGHT + 2), r.right - REGWIDTH, r.bottom - (INPUTHEIGHT + 2));
  142. c->lineDraw(r.right - REGWIDTH, r.bottom - (INPUTHEIGHT + (NCONSOLELINES*LINEHEIGHT) + 2), r.right - REGWIDTH, r.bottom);
  143. c->lineDraw(r.right - RIGHTCOLUMN, 0, r.right - RIGHTCOLUMN, r.bottom - (INPUTHEIGHT + (NCONSOLELINES*LINEHEIGHT) + 2));
  144. disassemble(c);
  145. for (int s = 0;s < strstack.getNumItems();s++)
  146. {
  147. c->textOutEllipsed(r.right - RIGHTCOLUMN + 4, s*LINEHEIGHT + 4, RIGHTCOLUMN - 8, 16, strstack.enumItem(s)->getValue(), &fontInfo);
  148. }
  149. return 1;
  150. }
  151. int SimpleDebuggerUI::onLeftButtonDown(int x, int y)
  152. {
  153. SimpleDebuggerUI_PARENT::onLeftButtonDown(x, y);
  154. if (edit) edit->onGetFocus();
  155. // leave = 1;
  156. return 1;
  157. }
  158. void SimpleDebuggerUI::disassemble(Canvas *c)
  159. {
  160. RECT r;
  161. getClientRect(&r);
  162. int x = 4;
  163. int y = (r.bottom - r.top - 4) / 2 + 4;
  164. int ln = jitd->findLine(jitd->getVIP());
  165. if (ln != -1)
  166. {
  167. Wasabi::FontInfo fontInfo;
  168. SourceCodeLine *l = jitd->enumLine(ln);
  169. int sourcecode = l->getSourceFile() != NULL;
  170. int g;
  171. int j = 0;
  172. for (g = y;g < r.bottom - (INPUTHEIGHT + 4 + (NCONSOLELINES*LINEHEIGHT)) - LINEHEIGHT;g += LINEHEIGHT)
  173. {
  174. if (!sourcecode || j == 0)
  175. l = jitd->enumLine(ln + j);
  176. if (!l) break;
  177. if (j == 0)
  178. {
  179. RECT br;
  180. br.left = 4;
  181. br.top = g;
  182. br.right = r.right - (RIGHTCOLUMN + 4);
  183. br.bottom = br.top + LINEHEIGHT;
  184. c->fillRect(&br, RGB(0, 255, 0));
  185. fontInfo.color = RGB(0, 0, 0);
  186. }
  187. if (!sourcecode)
  188. {
  189. String str;
  190. unsigned const char *d = (unsigned const char *)(l->getPointer() + jitd->getCodeBlock());
  191. for (int k = 0;k < l->getLength();k++)
  192. {
  193. if (!str.isempty()) str += " ";
  194. str += StringPrintf("%02X", *d);
  195. d++;
  196. }
  197. c->textOut(x, g, StringPrintfW(L"%08X", l->getPointer()), &fontInfo);
  198. c->textOut(x + 70, g, AutoWide(str), &fontInfo);
  199. c->textOut(x + 70 + 150, g, l->getLine(), &fontInfo);
  200. }
  201. else
  202. {
  203. c->textOutEllipsed(x, g, r.right - r.left - (RIGHTCOLUMN + 4 + x), 16, (getLine(l->getSourceFile(), l->getSourceFileLine() + j)), &fontInfo);
  204. }
  205. j++;
  206. }
  207. j = 1;
  208. for (g = y - LINEHEIGHT;g > 1;g -= LINEHEIGHT)
  209. {
  210. if (!sourcecode || j == 0)
  211. l = jitd->enumLine(ln - j);
  212. if (!l) break;
  213. if (!sourcecode)
  214. {
  215. String str;
  216. unsigned const char *d = (unsigned const char *)(l->getPointer() + jitd->getCodeBlock());
  217. for (int k = 0;k < l->getLength();k++)
  218. {
  219. if (!str.isempty()) str += " ";
  220. str += StringPrintf("%02X", *d);
  221. d++;
  222. }
  223. c->textOut(x, g, StringPrintfW(L"%08X", l->getPointer()), &fontInfo);
  224. c->textOut(x + 70, g, AutoWide(str), &fontInfo);
  225. c->textOut(x + 70 + 150, g, (l->getLine()), &fontInfo);
  226. }
  227. else
  228. {
  229. c->textOutEllipsed(x, g, r.right - r.left - (RIGHTCOLUMN + 4 + x), 16, (getLine(l->getSourceFile(), l->getSourceFileLine() - j)), &fontInfo);
  230. }
  231. j++;
  232. }
  233. }
  234. }
  235. int SimpleDebuggerUI::onResize()
  236. {
  237. SimpleDebuggerUI_PARENT::onResize();
  238. if (edit != NULL)
  239. {
  240. RECT r;
  241. getClientRect(&r);
  242. edit->resize(1, r.bottom - (INPUTHEIGHT + 1), r.right - r.left - (REGWIDTH + 1), INPUTHEIGHT);
  243. }
  244. return 1;
  245. }
  246. int SimpleDebuggerUI::childNotify(ifc_window *child, int msg, intptr_t p1, intptr_t p2)
  247. {
  248. if (child == edit)
  249. {
  250. if (msg == ChildNotify::EDITWND_ENTER_PRESSED)
  251. {
  252. onCommand(cmdbuf);
  253. }
  254. }
  255. return SimpleDebuggerUI_PARENT::childNotify(child, msg, p1, p2);
  256. }
  257. BEGIN_STRINGDICTIONARY(_debuggercommands)
  258. SDI(L"b", DEBUG_CMD_BREAKPOINT);
  259. SDI(L"break", DEBUG_CMD_BREAKPOINT);
  260. SDI(L"x", DEBUG_CMD_CONTINUE);
  261. SDI(L"continue", DEBUG_CMD_CONTINUE);
  262. SDI(L"i", DEBUG_CMD_STEPINTO);
  263. SDI(L"stepinto", DEBUG_CMD_STEPINTO);
  264. SDI(L"o", DEBUG_CMD_STEPOVER);
  265. SDI(L"stepover", DEBUG_CMD_STEPOVER);
  266. SDI(L"p", DEBUG_CMD_STEPOUT);
  267. SDI(L"stepout", DEBUG_CMD_STEPOUT);
  268. SDI(L"k", DEBUG_CMD_KILL);
  269. SDI(L"kill", DEBUG_CMD_KILL);
  270. SDI(L"?", DEBUG_CMD_HELP);
  271. SDI(L"help", DEBUG_CMD_HELP);
  272. END_STRINGDICTIONARY(_debuggercommands, debuggercommands)
  273. void SimpleDebuggerUI::onCommand(const wchar_t *cmd)
  274. {
  275. if (*cmd == 0)
  276. {
  277. stepOver();
  278. return;
  279. }
  280. ParamParser pp(cmd, L" ");
  281. int i = debuggercommands.getId(pp.enumItem(0));
  282. switch (i)
  283. {
  284. case DEBUG_CMD_BREAKPOINT:
  285. addBreakPoint(pp.enumItem(1));
  286. break;
  287. case DEBUG_CMD_CONTINUE:
  288. continueExecution();
  289. break;
  290. case DEBUG_CMD_STEPINTO:
  291. stepInto();
  292. break;
  293. case DEBUG_CMD_STEPOVER:
  294. stepOver();
  295. break;
  296. case DEBUG_CMD_KILL:
  297. killScript();
  298. break;
  299. case DEBUG_CMD_HELP:
  300. showHelp();
  301. break;
  302. }
  303. }
  304. int SimpleDebuggerUI::evaluate(const wchar_t *ascii)
  305. {
  306. if (!_wcsicmp(ascii, L"VSD")) return jitd->getVSD();
  307. if (!_wcsicmp(ascii, L"VIP")) return jitd->getVIP();
  308. if (!_wcsicmp(ascii, L"VSP")) return jitd->getVSP();
  309. if (!_wcsicmp(ascii, L"VCC")) return jitd->getVCC();
  310. wchar_t *end;
  311. return wcstol(ascii, &end, 16);
  312. }
  313. void SimpleDebuggerUI::addBreakPoint(const wchar_t *pointer_ascii)
  314. {
  315. /*int i = */evaluate(pointer_ascii);
  316. }
  317. void SimpleDebuggerUI::continueExecution()
  318. {
  319. retcode = JITD_RETURN_CONTINUE;
  320. leave = 1;
  321. }
  322. void SimpleDebuggerUI::stepInto()
  323. {
  324. retcode = JITD_RETURN_STEPINTO;
  325. leave = 1;
  326. }
  327. void SimpleDebuggerUI::stepOver()
  328. {
  329. int ln = jitd->findLine(jitd->getVIP());
  330. ln++;
  331. SourceCodeLine *l = jitd->enumLine(ln);
  332. if (l != NULL) // else ret as last opcode
  333. jitd->setSysBreakpoint(l->getPointer());
  334. retcode = JITD_RETURN_CONTINUE;
  335. leave = 1;
  336. }
  337. void SimpleDebuggerUI::killScript()
  338. {
  339. retcode = JITD_RETURN_TERMINATE;
  340. leave = 1;
  341. }
  342. void SimpleDebuggerUI::showHelp()
  343. {}
  344. int SimpleDebuggerUI::onGetFocus()
  345. {
  346. SimpleDebuggerUI_PARENT::onGetFocus();
  347. if (edit) edit->onGetFocus();
  348. return 1;
  349. }
  350. void SimpleDebuggerUI::onSetVisible(int show)
  351. {
  352. SimpleDebuggerUI_PARENT::onSetVisible(show);
  353. if (edit) edit->onGetFocus();
  354. }
  355. #undef fgets
  356. const wchar_t *SimpleDebuggerUI::getLine(const wchar_t *filename, int fileline)
  357. {
  358. if (fileline <= 0)
  359. return L"";
  360. static StringW str;
  361. FILE *f = _wfopen(filename, L"rt");
  362. if (!f)
  363. {
  364. str = L"couldn't load ";
  365. str += filename;
  366. return str;
  367. }
  368. char t[256] = {0};
  369. char u[256] = {0};
  370. int n = fileline;
  371. while (n--)
  372. {
  373. *u = 0;
  374. char *p;
  375. do
  376. {
  377. p = *u ? t : u;
  378. fgets(p, 255, f);
  379. t[255] = 0;
  380. }
  381. while (!feof(f) && p[STRLEN(p)-1] != '\n' && p[STRLEN(p)-1] != '\r');
  382. }
  383. char *p = u;
  384. while (p && *p && p < u + 256)
  385. {
  386. if (*p < 0x21) *p = ' ';
  387. p++;
  388. }
  389. str = AutoWide(u, CP_UTF8);
  390. fclose(f);
  391. return str;
  392. }