- Segueix el treball en el debugger
This commit is contained in:
242
lua.cpp
242
lua.cpp
@@ -7,7 +7,191 @@
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
#include <thread>
|
||||
#include <atomic>
|
||||
#include <iostream>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
std::unordered_map<std::string, std::vector<int>> g_breakpoints;
|
||||
std::mutex g_breakMutex;
|
||||
|
||||
std::queue<std::string> g_debugCommands;
|
||||
std::mutex g_cmdMutex;
|
||||
|
||||
std::atomic<bool> g_running = true;
|
||||
std::atomic<bool> 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<int> lines = j["lines"];
|
||||
std::lock_guard<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> 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 <poll.h>
|
||||
|
||||
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<std::mutex> 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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user