void breakpoint_destroy(struct breakpoint *b) { if (b != NULL) { breakpoint_clear(b); if (b->where != NULL) free(b->where); free(b); } }
/* * This just lets you punch in one-liners and Lua will run them as individual * chunks, but you can completely access all Lua state, including calling C * functions and altering tables. At this time, it's more of a "console" * than a debugger. You can do "p MojoLua_debugger()" from gdb to launch this * from a breakpoint in native code, or call MojoSetup.debugger() to launch * it from Lua code (with stacktrace intact, too: type 'bt' to see it). */ static int luahook_debugger(lua_State *L) { virgo_t* v = virgo__lua_context(L); #if DISABLE_LUA_PARSER logError(v, "Lua debugger is disabled in this build (no parser)."); #else int origtop; const virgo_log_level_e origloglevel = virgo_log_level_get(v); lua_pushcfunction(L, luahook_stackwalk); origtop = lua_gettop(L); printf("Quick and dirty Lua debugger. Type 'exit' to quit.\n"); while (1) { char *buf = (char *) scratchbuf; int len = 0; printf("> "); fflush(stdout); if (fgets(buf, sizeof (scratchbuf), stdin) == NULL) { printf("\n\n fgets() on stdin failed: "); break; } len = (int) (strlen(buf) - 1); while ( (len >= 0) && ((buf[len] == '\n') || (buf[len] == '\r')) ) buf[len--] = '\0'; if (strcmp(buf, "q") == 0) break; else if (strcmp(buf, "quit") == 0) break; else if (strcmp(buf, "exit") == 0) break; else if (strncmp(buf, "break ", 6) == 0) { int lineno = 0; char *p = strrchr(buf, ':'); if (p != NULL) { lineno = atoi(p+1); *p = '\0'; } breakpoint_add(buf+6, lineno); printf("Adding breakpoing to %s at line %d\n", buf+6, lineno); lua_sethook(L, debugger_breakpoint, LUA_MASKLINE, 0); continue; } else if (strncmp(buf, "clear ", 6) == 0) { int lineno = 0; char *p = strrchr(buf, ':'); if (p != NULL) { lineno = atoi(p+1); *p = '\0'; } breakpoint_clear(buf+6, lineno); printf("Clearing breakpoing to %s at line %d\n", buf+6, lineno); lua_sethook(L, debugger_breakpoint, 0, 0); continue; } else if (strcmp(buf, "clearall") == 0) { breakpoint_clearall(); lua_sethook(L, debugger_breakpoint, 0, 0); printf("All breakpoints cleared\n"); continue; } else if (strcmp(buf, "trace") == 0) { if (debugger_trace_enabled == 0) { lua_sethook(L, debugger_trace, LUA_MASKLINE, 0); debugger_trace_enabled = 1; printf("Tracing enabled!\n"); } else { lua_sethook(L, debugger_trace, 0, 0); debugger_trace_enabled = 0; printf("Tracing disabled!\n"); } continue; } else if (strcmp(buf, "bt") == 0) { /*MojoLog_logLevel = MOJOSETUP_LOG_EVERYTHING;*/ virgo_log_level_set(v, VIRGO_LOG_EVERYTHING); strcpy(buf, "virgo_stackwalk()"); } if ( (luaL_loadstring(L, buf) != 0) || (lua_pcall(L, 0, LUA_MULTRET, -2) != 0) ) { printf("%s\n", lua_tostring(L, -1)); lua_pop(L, 1); } else { printf("Returned %d values.\n", lua_gettop(L) - origtop); while (lua_gettop(L) != origtop) { /*!!! FIXME: dump details of values to stdout here.*/ lua_pop(L, 1); } printf("\n"); } /*MojoLog_logLevel = origloglevel;*/ virgo_log_level_set(v, origloglevel); } lua_pop(L, 1); printf("exiting debugger...\n"); /*#endif*/ return 0; }