#include #include "systems/compiler_system.hpp" #include "text/text.hpp" namespace Nimbin { CompilerSystem::~CompilerSystem() { if (_worker.joinable()) _worker.join(); } void CompilerSystem::compile(Text::Handler& out, const std::string& src) { if (_running.load()) return; if (_worker.joinable()) _worker.join(); last_compile_ok = false; out.clear(); _count = 0; { std::lock_guard lock(_mtx); _pending.clear(); } _running.store(true); _worker = std::thread(&CompilerSystem::run_Compile, this, src); } void CompilerSystem::run_Compile(CompilerSystem* self, std::string src) { FILE* f = fopen("/tmp/game_prog.cpp", "w"); if (!f) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "CompilerSystem: could not write temp file"); self->_running.store(false); return; } fputs(src.c_str(), f); fclose(f); FILE* pipe = popen("LC_ALL=C c++ /tmp/game_prog.cpp -o /tmp/game_prog 2>&1", "r"); if (!pipe) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "CompilerSystem: popen failed"); self->_running.store(false); return; } int n = 0; char buf[512]; while (fgets(buf, sizeof(buf), pipe)) { std::string line(buf); if (!line.empty() && line.back() == '\n') line.pop_back(); if (line.empty()) continue; std::lock_guard lock(self->_mtx); self->_pending.push_back(line); ++n; } pclose(pipe); if (n == 0) { // no diagnostics → success std::lock_guard lock(self->_mtx); self->_pending.push_back("OK"); } self->_running.store(false); } void CompilerSystem::update(Text::Handler& out) { constexpr size_t LINES_PER_FRAME = 2; DynArray batch; { std::lock_guard lock(_mtx); if (_pending.empty()) return; const size_t n = SDL_min(LINES_PER_FRAME, _pending.size()); for (size_t i = 0; i < n; i++) batch.push_back(std::move(_pending[i])); _pending.erase(_pending.begin(), _pending.begin() + static_cast(n)); } for (const std::string& line : batch) push_Line(out, line); } void CompilerSystem::push_Line(Text::Handler& out, const std::string& line) { if (line == "OK") last_compile_ok = true; out.append_Line(Text::ascii_Sanitize(line)); _count++; } } // namespace Nimbin