- Segueix el treball en el debugger
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
libs = -lSDL3 -lGL
|
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
|
executable = mini_debug
|
||||||
sourcepath = . lua
|
sourcepath = . lua
|
||||||
buildpath = build
|
buildpath = build
|
||||||
|
|||||||
242
lua.cpp
242
lua.cpp
@@ -7,7 +7,191 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <vector>
|
#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;
|
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" {
|
extern "C" {
|
||||||
|
|
||||||
@@ -785,7 +969,7 @@ extern "C" {
|
|||||||
lua_newtable(L);
|
lua_newtable(L);
|
||||||
|
|
||||||
// name field (canonical absolute path)
|
// 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");
|
lua_setfield(L, -2, "name");
|
||||||
|
|
||||||
// dir field
|
// dir field
|
||||||
@@ -1112,6 +1296,23 @@ bool lua_is_playing() {
|
|||||||
return 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() {
|
void push_lua_funcs() {
|
||||||
lua_newtable(L);
|
lua_newtable(L);
|
||||||
lua_setglobal(L, "mini");
|
lua_setglobal(L, "mini");
|
||||||
@@ -1512,6 +1713,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");
|
||||||
@@ -1544,11 +1746,14 @@ void lua_init(const char *main_lua_file) {
|
|||||||
lua_pop(L,1);
|
lua_pop(L,1);
|
||||||
lua_pop(L,1);
|
lua_pop(L,1);
|
||||||
|
|
||||||
|
//std::thread(debugCommandThread).detach();
|
||||||
|
printf("stdin isatty: %d\n", isatty(0));
|
||||||
is_playing = true;
|
is_playing = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lua_call_init() {
|
void lua_call_init() {
|
||||||
if (!init_exists) return;
|
if (!init_exists) return;
|
||||||
|
lua_process_debugger_commands();
|
||||||
lua_getglobal(L, "mini");
|
lua_getglobal(L, "mini");
|
||||||
lua_getfield(L, -1, "init");
|
lua_getfield(L, -1, "init");
|
||||||
if (lua_pcall(L, 0, 0, 0)) {
|
if (lua_pcall(L, 0, 0, 0)) {
|
||||||
@@ -1560,6 +1765,7 @@ void lua_call_init() {
|
|||||||
|
|
||||||
void lua_call_update() {
|
void lua_call_update() {
|
||||||
if (!update_exists) return;
|
if (!update_exists) return;
|
||||||
|
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();
|
||||||
lua_getglobal(L, "mini");
|
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() {
|
void lua_quit() {
|
||||||
if (!is_playing) return;
|
if (!is_playing) return;
|
||||||
is_playing = false;
|
is_playing = false;
|
||||||
lua_close(L);
|
lua_close(L);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void lua_kill_thread() {
|
||||||
|
g_running = false;
|
||||||
|
stdinThread.request_stop();
|
||||||
|
}
|
||||||
|
|||||||
2
lua.h
2
lua.h
@@ -1,7 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
bool lua_is_playing();
|
bool lua_is_playing();
|
||||||
|
void lua_process_debugger_commands();
|
||||||
void lua_init(const char* main_lua_file = "main.lua");
|
void lua_init(const char* main_lua_file = "main.lua");
|
||||||
void lua_call_init();
|
void lua_call_init();
|
||||||
void lua_call_update();
|
void lua_call_update();
|
||||||
void lua_quit();
|
void lua_quit();
|
||||||
|
void lua_kill_thread();
|
||||||
|
|||||||
Reference in New Issue
Block a user