- [NEW] (del debugger) Ja funciona: start, pause, stop, breakpoints, step into, step over, step out. Intentant que funcione el enviament del stackTrace
This commit is contained in:
197
lua.cpp
197
lua.cpp
@@ -6,6 +6,7 @@
|
|||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <stack>
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -16,6 +17,11 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
lua_State *L;
|
||||||
|
bool is_playing = false;
|
||||||
|
bool init_exists = false;
|
||||||
|
bool update_exists = false;
|
||||||
|
|
||||||
std::unordered_map<std::string, std::vector<int>> g_breakpoints;
|
std::unordered_map<std::string, std::vector<int>> g_breakpoints;
|
||||||
std::mutex g_breakMutex;
|
std::mutex g_breakMutex;
|
||||||
|
|
||||||
@@ -27,6 +33,19 @@ std::atomic<bool> g_paused = false;
|
|||||||
|
|
||||||
std::string g_pauseFile;
|
std::string g_pauseFile;
|
||||||
int g_pauseLine = 0;
|
int g_pauseLine = 0;
|
||||||
|
bool function_has_breakpoints = false;
|
||||||
|
std::stack<bool> funBreakStack;
|
||||||
|
bool debug_enabled = false;
|
||||||
|
|
||||||
|
enum StepMode {
|
||||||
|
STEP_NONE,
|
||||||
|
STEP_INTO,
|
||||||
|
STEP_OVER,
|
||||||
|
STEP_OUT
|
||||||
|
};
|
||||||
|
|
||||||
|
StepMode g_stepMode = STEP_NONE;
|
||||||
|
int g_stepDepth = 0;
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
using json = nlohmann::json;
|
using json = nlohmann::json;
|
||||||
@@ -77,6 +96,53 @@ std::string chunkToPath(const std::string& chunk) {
|
|||||||
return abs.lexically_normal().string();
|
return abs.lexically_normal().string();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int getStackDepth(lua_State* L) {
|
||||||
|
lua_Debug ar;
|
||||||
|
int depth = 0;
|
||||||
|
|
||||||
|
while (lua_getstack(L, depth, &ar)) {
|
||||||
|
depth++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
json getStackTrace(lua_State* L) {
|
||||||
|
json frames = json::array();
|
||||||
|
lua_Debug ar;
|
||||||
|
|
||||||
|
int depth = 0;
|
||||||
|
while (lua_getstack(L, depth, &ar)) {
|
||||||
|
lua_getinfo(L, "nSl", &ar);
|
||||||
|
|
||||||
|
const char* src = ar.source;
|
||||||
|
if (src[0] == '@')
|
||||||
|
src++;
|
||||||
|
|
||||||
|
json frame = {
|
||||||
|
{ "file", src },
|
||||||
|
{ "line", ar.currentline },
|
||||||
|
{ "name", ar.name ? ar.name : "?" }
|
||||||
|
};
|
||||||
|
|
||||||
|
frames.push_back(frame);
|
||||||
|
depth++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return json{
|
||||||
|
{ "frames", frames }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void sendDebugResponse(const std::string& type, const json& payload) {
|
||||||
|
json msg = {
|
||||||
|
{ "type", type },
|
||||||
|
{ "payload", payload }
|
||||||
|
};
|
||||||
|
printf("STACKTRACE: %s", msg.dump().c_str());
|
||||||
|
std::cout << "@@DEBUG@@" << msg.dump() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
void processDebugCommand(const std::string& line) {
|
void processDebugCommand(const std::string& line) {
|
||||||
//printf("COMANDO PROCESADO: %s\n", line.c_str());
|
//printf("COMANDO PROCESADO: %s\n", line.c_str());
|
||||||
if (!line.starts_with("@@DEBUGCMD@@"))
|
if (!line.starts_with("@@DEBUGCMD@@"))
|
||||||
@@ -96,8 +162,31 @@ void processDebugCommand(const std::string& line) {
|
|||||||
}
|
}
|
||||||
else if (cmd == "continue") {
|
else if (cmd == "continue") {
|
||||||
printf("CONTINUA\n\n");
|
printf("CONTINUA\n\n");
|
||||||
|
g_stepMode = STEP_NONE;
|
||||||
g_paused = false;
|
g_paused = false;
|
||||||
}
|
}
|
||||||
|
else if (cmd == "pause") {
|
||||||
|
g_stepMode = STEP_INTO;
|
||||||
|
g_paused = false;
|
||||||
|
}
|
||||||
|
else if (cmd == "stepOver") {
|
||||||
|
g_stepMode = STEP_OVER;
|
||||||
|
g_stepDepth = getStackDepth(L);
|
||||||
|
g_paused = false;
|
||||||
|
}
|
||||||
|
else if (cmd == "stepInto") {
|
||||||
|
g_stepMode = STEP_INTO;
|
||||||
|
g_paused = false;
|
||||||
|
}
|
||||||
|
else if (cmd == "stepOut") {
|
||||||
|
g_stepMode = STEP_OUT;
|
||||||
|
g_stepDepth = getStackDepth(L);
|
||||||
|
g_paused = false;
|
||||||
|
}
|
||||||
|
else if (cmd == "stackTrace") {
|
||||||
|
json result = getStackTrace(L);
|
||||||
|
sendDebugResponse("stackTrace", result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isBreakpoint(const std::string& file, int line) {
|
bool isBreakpoint(const std::string& file, int line) {
|
||||||
@@ -161,36 +250,92 @@ std::string waitForDebugCommand() {
|
|||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
extern "C" void luaHook(lua_State* L, lua_Debug* ar) {
|
bool shouldPauseForStepping(lua_State* L, lua_Debug* ar) {
|
||||||
lua_getinfo(L, "Sl", ar);
|
int depth = getStackDepth(L);
|
||||||
|
|
||||||
if (ar->currentline <= 0)
|
switch (g_stepMode) {
|
||||||
return;
|
case STEP_INTO:
|
||||||
|
return true; // siempre parar en la siguiente línea
|
||||||
|
|
||||||
const char* src = ar->source;
|
case STEP_OVER:
|
||||||
|
return depth <= g_stepDepth;
|
||||||
|
|
||||||
// Lua usa "@filename" para archivos reales
|
case STEP_OUT:
|
||||||
//if (src[0] == '@')
|
return depth < g_stepDepth;
|
||||||
// src++;
|
|
||||||
|
|
||||||
int line = ar->currentline;
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (isBreakpoint(src, line)) {
|
void pauseHere(const std::string& src, int line) {
|
||||||
g_paused = true;
|
g_paused = true;
|
||||||
g_pauseFile = src;
|
g_pauseFile = src;
|
||||||
g_pauseLine = line;
|
g_pauseLine = line;
|
||||||
|
g_stepMode = STEP_NONE;
|
||||||
|
|
||||||
std::string realPath = chunkToPath(src);
|
sendBreakEvent(chunkToPath(src), line);
|
||||||
sendBreakEvent(realPath, line);
|
|
||||||
//sendBreakEvent(src, line);
|
|
||||||
|
|
||||||
// Esperar comandos del Debug Adapter
|
|
||||||
while (g_paused) {
|
while (g_paused) {
|
||||||
std::string cmd = waitForDebugCommand();
|
std::string cmd = waitForDebugCommand();
|
||||||
printf("PROCESANDO COMANDO: %s\n", cmd.c_str());
|
|
||||||
processDebugCommand(cmd);
|
processDebugCommand(cmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" void luaHook(lua_State* L, lua_Debug* ar) {
|
||||||
|
lua_getinfo(L, "Sl", ar);
|
||||||
|
|
||||||
|
const char* src = ar->source;
|
||||||
|
if (src[0]=='=') return;
|
||||||
|
|
||||||
|
if (ar->event == LUA_HOOKCALL) {
|
||||||
|
funBreakStack.push(function_has_breakpoints);
|
||||||
|
bool new_function_has_breakpoints = false;
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(g_breakMutex);
|
||||||
|
auto it = g_breakpoints.find(src);
|
||||||
|
new_function_has_breakpoints = (it != g_breakpoints.end() && !it->second.empty());
|
||||||
|
}
|
||||||
|
if (new_function_has_breakpoints || g_stepMode != STEP_NONE) {
|
||||||
|
if (!function_has_breakpoints)
|
||||||
|
lua_sethook(L, luaHook, LUA_MASKCALL | LUA_MASKLINE | LUA_MASKRET, 0);
|
||||||
|
} else {
|
||||||
|
//if (function_has_breakpoints)
|
||||||
|
lua_sethook(L, luaHook, LUA_MASKCALL | LUA_MASKRET, 0);
|
||||||
|
}
|
||||||
|
function_has_breakpoints = new_function_has_breakpoints;
|
||||||
|
}
|
||||||
|
else if (ar->event == LUA_HOOKRET) {
|
||||||
|
// Siempre volver al hook base
|
||||||
|
bool new_function_has_breakpoints = funBreakStack.empty() ? false : funBreakStack.top();
|
||||||
|
funBreakStack.pop();
|
||||||
|
if (new_function_has_breakpoints || g_stepMode != STEP_NONE) {
|
||||||
|
if (!function_has_breakpoints)
|
||||||
|
lua_sethook(L, luaHook, LUA_MASKCALL | LUA_MASKLINE | LUA_MASKRET, 0);
|
||||||
|
} else {
|
||||||
|
//if (function_has_breakpoints)
|
||||||
|
lua_sethook(L, luaHook, LUA_MASKCALL | LUA_MASKRET, 0);
|
||||||
|
}
|
||||||
|
function_has_breakpoints = new_function_has_breakpoints;
|
||||||
|
}
|
||||||
|
else if (ar->event == LUA_HOOKLINE) {
|
||||||
|
if (ar->currentline <= 0) return;
|
||||||
|
const char* src = ar->source;
|
||||||
|
int line = ar->currentline;
|
||||||
|
|
||||||
|
if (isBreakpoint(src, line)) {
|
||||||
|
pauseHere(src, line);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Stepping
|
||||||
|
if (g_stepMode != STEP_NONE) {
|
||||||
|
if (shouldPauseForStepping(L, ar)) {
|
||||||
|
pauseHere(src, line);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -1287,10 +1432,6 @@ extern "C" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
lua_State *L;
|
|
||||||
bool is_playing = false;
|
|
||||||
bool init_exists = false;
|
|
||||||
bool update_exists = false;
|
|
||||||
|
|
||||||
bool lua_is_playing() {
|
bool lua_is_playing() {
|
||||||
return is_playing;
|
return is_playing;
|
||||||
@@ -1643,6 +1784,7 @@ int MiniLoader(lua_State *L) {
|
|||||||
|
|
||||||
// 1. Convertir puntos en barras
|
// 1. Convertir puntos en barras
|
||||||
std::string path(name);
|
std::string path(name);
|
||||||
|
std::string regpath(name);
|
||||||
std::replace(path.begin(), path.end(), '.', '/');
|
std::replace(path.begin(), path.end(), '.', '/');
|
||||||
|
|
||||||
// 2. Detectar comodín "/*"
|
// 2. Detectar comodín "/*"
|
||||||
@@ -1650,6 +1792,7 @@ int MiniLoader(lua_State *L) {
|
|||||||
if (path.size() >= 2 && path.substr(path.size()-2) == "/*") {
|
if (path.size() >= 2 && path.substr(path.size()-2) == "/*") {
|
||||||
load_all = true;
|
load_all = true;
|
||||||
path = path.substr(0, path.size()-2); // quitar "/*"
|
path = path.substr(0, path.size()-2); // quitar "/*"
|
||||||
|
regpath = regpath.substr(0, regpath.size()-2); // quitar "/*"
|
||||||
}
|
}
|
||||||
|
|
||||||
if (load_all) {
|
if (load_all) {
|
||||||
@@ -1658,7 +1801,7 @@ int MiniLoader(lua_State *L) {
|
|||||||
// Ejecutar todos los módulos
|
// Ejecutar todos los módulos
|
||||||
for (auto &f : files) {
|
for (auto &f : files) {
|
||||||
std::string fullpath = path + "/" + f;
|
std::string fullpath = path + "/" + f;
|
||||||
std::string registerpath = std::string(path + "." + f.substr(0,f.size()-4));
|
std::string registerpath = std::string(regpath + "." + f.substr(0,f.size()-4));
|
||||||
|
|
||||||
int size;
|
int size;
|
||||||
char* buffer = file_getfilebuffer(fullpath.c_str(), size);
|
char* buffer = file_getfilebuffer(fullpath.c_str(), size);
|
||||||
@@ -1713,7 +1856,7 @@ int MiniLoader(lua_State *L) {
|
|||||||
void lua_init(const char *main_lua_file) {
|
void lua_init(const char *main_lua_file) {
|
||||||
L = luaL_newstate();
|
L = luaL_newstate();
|
||||||
luaL_openlibs(L);
|
luaL_openlibs(L);
|
||||||
lua_sethook(L, luaHook, LUA_MASKLINE, 0);
|
|
||||||
push_lua_funcs();
|
push_lua_funcs();
|
||||||
lua_register(L, "mini_loader", MiniLoader);
|
lua_register(L, "mini_loader", MiniLoader);
|
||||||
luaL_dostring(L, "table.insert(package.searchers,2,mini_loader)\n");
|
luaL_dostring(L, "table.insert(package.searchers,2,mini_loader)\n");
|
||||||
@@ -1765,6 +1908,8 @@ void lua_call_init() {
|
|||||||
|
|
||||||
void lua_call_update() {
|
void lua_call_update() {
|
||||||
if (!update_exists) return;
|
if (!update_exists) return;
|
||||||
|
function_has_breakpoints = false;
|
||||||
|
while (!funBreakStack.empty()) funBreakStack.pop();
|
||||||
lua_process_debugger_commands();
|
lua_process_debugger_commands();
|
||||||
delta_time = float(SDL_GetTicks() - last_update)/1000.0f;
|
delta_time = float(SDL_GetTicks() - last_update)/1000.0f;
|
||||||
last_update = SDL_GetTicks();
|
last_update = SDL_GetTicks();
|
||||||
@@ -1816,3 +1961,13 @@ void lua_kill_thread() {
|
|||||||
g_running = false;
|
g_running = false;
|
||||||
stdinThread.request_stop();
|
stdinThread.request_stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void lua_toggle_debug() {
|
||||||
|
if (debug_enabled) {
|
||||||
|
debug_enabled = false;
|
||||||
|
lua_sethook(L, NULL,0, 0);
|
||||||
|
} else {
|
||||||
|
debug_enabled = true;
|
||||||
|
lua_sethook(L, luaHook, LUA_MASKCALL | LUA_MASKRET, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
2
lua.h
2
lua.h
@@ -7,3 +7,5 @@ void lua_call_init();
|
|||||||
void lua_call_update();
|
void lua_call_update();
|
||||||
void lua_quit();
|
void lua_quit();
|
||||||
void lua_kill_thread();
|
void lua_kill_thread();
|
||||||
|
void lua_toggle_debug();
|
||||||
|
//void lua_disable_debug();
|
||||||
|
|||||||
2
mini.cpp
2
mini.cpp
@@ -740,6 +740,8 @@ int main(int argc,char*argv[]){
|
|||||||
//} else {
|
//} else {
|
||||||
// should_exit=true;
|
// should_exit=true;
|
||||||
//}
|
//}
|
||||||
|
} else if (mini_eve.key.scancode == SDL_SCANCODE_F11) {
|
||||||
|
lua_toggle_debug();
|
||||||
} else if (mini_eve.key.scancode == SDL_SCANCODE_F5) {
|
} else if (mini_eve.key.scancode == SDL_SCANCODE_F5) {
|
||||||
should_exit=true;
|
should_exit=true;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user