From 8a4110e82182f0046be5a4e0178e8a924a0a07fb Mon Sep 17 00:00:00 2001 From: Raimon Zamora Date: Mon, 30 Mar 2026 06:41:13 +0200 Subject: [PATCH] - Segueix el treball en el debugger --- lagueirtofile | 2 +- lua.cpp | 242 +++++++++++++++++++++++++++++++++++++++++++++++++- lua.h | 2 + mini.cpp | 2 +- 4 files changed, 245 insertions(+), 3 deletions(-) diff --git a/lagueirtofile b/lagueirtofile index 91969c3..842cb31 100644 --- a/lagueirtofile +++ b/lagueirtofile @@ -1,5 +1,5 @@ libs = -lSDL3 -lGL -cppflags = -D LUA_USE_LINUX -D DEBUG -g -Wall +cppflags = -D LUA_USE_LINUX -D DEBUG -g -Wall -std=c++20 executable = mini_debug sourcepath = . lua buildpath = build diff --git a/lua.cpp b/lua.cpp index 766f6f2..9830f87 100644 --- a/lua.cpp +++ b/lua.cpp @@ -7,7 +7,191 @@ #include #include +#include +#include +#include +#include +#include +#include +#include +#include + +std::unordered_map> g_breakpoints; +std::mutex g_breakMutex; + +std::queue g_debugCommands; +std::mutex g_cmdMutex; + +std::atomic g_running = true; +std::atomic g_paused = false; + +std::string g_pauseFile; +int g_pauseLine = 0; + namespace fs = std::filesystem; +using json = nlohmann::json; + +std::string pathToChunk(const std::string& path) { + std::filesystem::path p(path); + + // 1. Normalizar la ruta + p = p.lexically_normal(); + + // 2. Buscar el directorio "data" + auto it = std::find(p.begin(), p.end(), "data"); + if (it == p.end()) + return ""; // no es un script Lua válido + + // 3. Construir la parte relativa después de "data" + std::filesystem::path rel; + for (++it; it != p.end(); ++it) + rel /= *it; + + // 4. Quitar ".lua" + std::string s = rel.string(); + if (s.ends_with(".lua")) + s = s.substr(0, s.size() - 4); + + // 5. Convertir "/" → "." + for (char& c : s) + if (c == '/') + c = '.'; + + return s; +} + +std::string chunkToPath(const std::string& chunk) { + // 1. Convertir "ia.test" → "ia/test" + std::string rel; + rel.reserve(chunk.size() + 10); + + for (char c : chunk) + rel += (c == '.' ? '/' : c); + + // 2. Añadir prefijo y sufijo + rel = "data/" + rel + ".lua"; + + // 3. Convertir a ruta absoluta + std::filesystem::path abs = std::filesystem::current_path() / rel; + + return abs.lexically_normal().string(); +} + +void processDebugCommand(const std::string& line) { + //printf("COMANDO PROCESADO: %s\n", line.c_str()); + if (!line.starts_with("@@DEBUGCMD@@")) + return; + + json j = json::parse(line.substr(12)); + + std::string cmd = j["cmd"]; + + if (cmd == "setBreakpoints") { + std::string file = j["file"]; + std::vector lines = j["lines"]; + std::lock_guard lock(g_breakMutex); + std::string chunk = pathToChunk(file); + //printf("Es un BREAKPOINT: %s, %i\n", chunk.c_str(), lines[0]); + g_breakpoints[chunk] = lines; + } + else if (cmd == "continue") { + printf("CONTINUA\n\n"); + g_paused = false; + } +} + +bool isBreakpoint(const std::string& file, int line) { + std::lock_guard lock(g_breakMutex); + + //if (!g_breakpoints.empty()) { + // printf("file: %s\n", file.c_str()); + //} + auto it = g_breakpoints.find(file); + if (it == g_breakpoints.end()) + return false; + + for (int bp : it->second) { + if (bp == line) + return true; + } + + return false; +} + +void sendBreakEvent(const std::string& file, int line) { + json j = { + {"type", "break"}, + {"file", file}, + {"line", line} + }; + + std::cout << "@@DEBUG@@" << j.dump() << std::endl; + std::cout.flush(); +} + +std::string waitForDebugCommand() { + //printf("HOLA"); + while (true) { + { + std::lock_guard lock(g_cmdMutex); + if (!g_debugCommands.empty()) { + std::string cmd = g_debugCommands.front(); + g_debugCommands.pop(); + return cmd; + } + } + + SDL_Delay(1); + } +} + +/*void debugCommandThread() { + std::string line; + + while (true) { + if (!std::getline(std::cin, line)) { + break; // stdin cerrado + } + + if (!g_running) + break; + + std::lock_guard lock(g_cmdMutex); + g_debugCommands.push(line); + } +}*/ + +extern "C" void luaHook(lua_State* L, lua_Debug* ar) { + lua_getinfo(L, "Sl", ar); + + if (ar->currentline <= 0) + return; + + const char* src = ar->source; + + // Lua usa "@filename" para archivos reales + //if (src[0] == '@') + // src++; + + int line = ar->currentline; + + if (isBreakpoint(src, line)) { + g_paused = true; + g_pauseFile = src; + g_pauseLine = line; + + std::string realPath = chunkToPath(src); + sendBreakEvent(realPath, line); + //sendBreakEvent(src, line); + + // Esperar comandos del Debug Adapter + while (g_paused) { + std::string cmd = waitForDebugCommand(); + printf("PROCESANDO COMANDO: %s\n", cmd.c_str()); + processDebugCommand(cmd); + } + } +} extern "C" { @@ -785,7 +969,7 @@ extern "C" { lua_newtable(L); // name field (canonical absolute path) - lua_pushstring(L, fs::canonical(entry.path()).u8string().c_str()); + lua_pushstring(L, (const char*)fs::canonical(entry.path()).u8string().c_str()); lua_setfield(L, -2, "name"); // dir field @@ -1112,6 +1296,23 @@ bool lua_is_playing() { return is_playing; } +void lua_process_debugger_commands() { + while (true) { + std::string cmd; + + { + std::lock_guard lock(g_cmdMutex); + if (g_debugCommands.empty()) + break; + + cmd = g_debugCommands.front(); + g_debugCommands.pop(); + } + + processDebugCommand(cmd); + } +} + void push_lua_funcs() { lua_newtable(L); lua_setglobal(L, "mini"); @@ -1512,6 +1713,7 @@ int MiniLoader(lua_State *L) { void lua_init(const char *main_lua_file) { L = luaL_newstate(); luaL_openlibs(L); + lua_sethook(L, luaHook, LUA_MASKLINE, 0); push_lua_funcs(); lua_register(L, "mini_loader", MiniLoader); luaL_dostring(L, "table.insert(package.searchers,2,mini_loader)\n"); @@ -1544,11 +1746,14 @@ void lua_init(const char *main_lua_file) { lua_pop(L,1); lua_pop(L,1); + //std::thread(debugCommandThread).detach(); + printf("stdin isatty: %d\n", isatty(0)); is_playing = true; } void lua_call_init() { if (!init_exists) return; + lua_process_debugger_commands(); lua_getglobal(L, "mini"); lua_getfield(L, -1, "init"); if (lua_pcall(L, 0, 0, 0)) { @@ -1560,6 +1765,7 @@ void lua_call_init() { void lua_call_update() { if (!update_exists) return; + lua_process_debugger_commands(); delta_time = float(SDL_GetTicks() - last_update)/1000.0f; last_update = SDL_GetTicks(); lua_getglobal(L, "mini"); @@ -1571,8 +1777,42 @@ void lua_call_update() { } } +#include + +std::jthread stdinThread([](std::stop_token st) { + std::string line; + + struct pollfd pfd; + pfd.fd = 0; // stdin + pfd.events = POLLIN; // queremos saber si hay datos + + while (!st.stop_requested()) { + int ret = poll(&pfd, 1, 10); // timeout 10 ms + + if (ret > 0 && (pfd.revents & POLLIN)) { + if (!std::getline(std::cin, line)) { + break; // EOF + } + + { + std::lock_guard lock(g_cmdMutex); + g_debugCommands.push(line); + printf("COMANDO RECIBIDO: %s\n", line.c_str()); + } + } else { + SDL_Delay(1); + } + } +}); + + void lua_quit() { if (!is_playing) return; is_playing = false; lua_close(L); } + +void lua_kill_thread() { + g_running = false; + stdinThread.request_stop(); +} diff --git a/lua.h b/lua.h index 5ffa159..a50e8d6 100644 --- a/lua.h +++ b/lua.h @@ -1,7 +1,9 @@ #pragma once bool lua_is_playing(); +void lua_process_debugger_commands(); void lua_init(const char* main_lua_file = "main.lua"); void lua_call_init(); void lua_call_update(); void lua_quit(); +void lua_kill_thread(); diff --git a/mini.cpp b/mini.cpp index 87889d0..82d7a20 100644 --- a/mini.cpp +++ b/mini.cpp @@ -828,7 +828,7 @@ int main(int argc,char*argv[]){ destroyDisplay(); SDL_Quit(); } - + lua_kill_thread(); return 0; }