ELSE update
This commit is contained in:
@@ -3,13 +3,18 @@
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <filesystem>
|
||||
#include <regex>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
// Funkcja pomocnicza do wczytania pliku
|
||||
std::string loadFileContent(const std::string& path) {
|
||||
std::ifstream in(path);
|
||||
static std::string ltrim(std::string s) {
|
||||
const size_t first = s.find_first_not_of(" \t");
|
||||
if (first == std::string::npos) return "";
|
||||
return s.substr(first);
|
||||
}
|
||||
|
||||
static std::string loadFileContent(const std::string& path) {
|
||||
std::ifstream in(path, std::ios::binary);
|
||||
if (!in) {
|
||||
std::cerr << "[PREPROCESSOR] Error: Could not open included file: " << path << "\n";
|
||||
return "";
|
||||
@@ -17,63 +22,109 @@ std::string loadFileContent(const std::string& path) {
|
||||
return std::string((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>());
|
||||
}
|
||||
|
||||
std::string preprocessSource(const std::string& src, const std::string& projectDir, const std::string& compilerDir) {
|
||||
// Próbuje sparsowaæ #include "x" albo #include <x>
|
||||
// Zwraca: true jeœli linia to include i uda³o siê wyci¹gn¹æ œcie¿kê.
|
||||
static bool parseIncludeLine(const std::string& line, std::string& includePath, bool& isStdLib) {
|
||||
includePath.clear();
|
||||
isStdLib = false;
|
||||
|
||||
std::string t = ltrim(line);
|
||||
if (t.rfind("#include", 0) != 0) return false;
|
||||
|
||||
const size_t openQuote = t.find('"');
|
||||
const size_t closeQuote = t.rfind('"');
|
||||
const size_t openAngle = t.find('<');
|
||||
const size_t closeAngle = t.rfind('>');
|
||||
|
||||
if (openQuote != std::string::npos && closeQuote != std::string::npos && closeQuote > openQuote) {
|
||||
includePath = t.substr(openQuote + 1, closeQuote - openQuote - 1);
|
||||
isStdLib = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (openAngle != std::string::npos && closeAngle != std::string::npos && closeAngle > openAngle) {
|
||||
includePath = t.substr(openAngle + 1, closeAngle - openAngle - 1);
|
||||
isStdLib = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// To jest #include ale w z³ym formacie (np. brak cudzys³owu / nawiasów)
|
||||
return true;
|
||||
}
|
||||
|
||||
// Wewnêtrzna funkcja z guardem na rekurencjê.
|
||||
static std::string preprocessSourceImpl(
|
||||
const std::string& src,
|
||||
const std::string& projectDir,
|
||||
const std::string& compilerDir,
|
||||
std::unordered_set<std::string>& includeGuard
|
||||
) {
|
||||
std::istringstream iss(src);
|
||||
std::string line;
|
||||
std::stringstream output;
|
||||
|
||||
while (std::getline(iss, line)) {
|
||||
// Szukamy: #include "..." lub #include <...>
|
||||
// U¿ywamy prostego find, ¿eby by³o szybko
|
||||
std::string trimLine = line;
|
||||
// Usuwamy bia³e znaki z pocz¹tku
|
||||
size_t first = trimLine.find_first_not_of(" \t");
|
||||
if (first != std::string::npos) trimLine = trimLine.substr(first);
|
||||
std::string includePath;
|
||||
bool isStdLib = false;
|
||||
|
||||
if (trimLine.rfind("#include", 0) == 0) {
|
||||
// Mamy include!
|
||||
size_t openQuote = trimLine.find('"');
|
||||
size_t closeQuote = trimLine.rfind('"');
|
||||
size_t openAngle = trimLine.find('<');
|
||||
size_t closeAngle = trimLine.rfind('>');
|
||||
const bool isIncludeLine = parseIncludeLine(line, includePath, isStdLib);
|
||||
|
||||
std::string includePath;
|
||||
bool isStdLib = false;
|
||||
if (!isIncludeLine) {
|
||||
output << line << "\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
// Wersja: #include "plik.pcc"
|
||||
if (openQuote != std::string::npos && closeQuote > openQuote) {
|
||||
includePath = trimLine.substr(openQuote + 1, closeQuote - openQuote - 1);
|
||||
}
|
||||
// Wersja: #include <plik.pcc>
|
||||
else if (openAngle != std::string::npos && closeAngle > openAngle) {
|
||||
includePath = trimLine.substr(openAngle + 1, closeAngle - openAngle - 1);
|
||||
isStdLib = true;
|
||||
}
|
||||
if (includePath.empty()) {
|
||||
output << "\n// [PREPROCESSOR] Invalid include (no path): " << line << "\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!includePath.empty()) {
|
||||
std::string fullPath;
|
||||
if (isStdLib) {
|
||||
fullPath = compilerDir + "/std/" + includePath;
|
||||
std::cout << "[PREPROCESSOR] Including STD lib: " << fullPath << "\n";
|
||||
}
|
||||
else {
|
||||
// Plik lokalny: Szukamy w folderze projektu
|
||||
if (projectDir.empty()) fullPath = includePath;
|
||||
else fullPath = projectDir + "/" + includePath;
|
||||
std::cout << "[PREPROCESSOR] Including local file: " << fullPath << "\n";
|
||||
}
|
||||
std::string content = loadFileContent(fullPath);
|
||||
std::string processedContent = preprocessSource(content, projectDir, compilerDir);
|
||||
|
||||
output << "\n// --- BEGIN INCLUDE: " << includePath << " ---\n";
|
||||
output << processedContent;
|
||||
output << "\n// --- END INCLUDE ---\n";
|
||||
}
|
||||
// Z³ó¿ fullPath
|
||||
fs::path fullPath;
|
||||
if (isStdLib) {
|
||||
fullPath = fs::path(compilerDir) / "std" / includePath;
|
||||
std::cout << "[PREPROCESSOR] Including STD lib: " << fullPath.string() << "\n";
|
||||
}
|
||||
else {
|
||||
output << line << "\n";
|
||||
if (projectDir.empty()) fullPath = fs::path(includePath);
|
||||
else fullPath = fs::path(projectDir) / includePath;
|
||||
std::cout << "[PREPROCESSOR] Including local file: " << fullPath.string() << "\n";
|
||||
}
|
||||
|
||||
// Normalizacja œcie¿ki (jeœli siê da)
|
||||
std::string guardKey;
|
||||
try {
|
||||
guardKey = fs::weakly_canonical(fullPath).string();
|
||||
}
|
||||
catch (...) {
|
||||
guardKey = fullPath.lexically_normal().string();
|
||||
}
|
||||
|
||||
// Guard przeciw include-loop oraz wielokrotnemu includowaniu
|
||||
if (includeGuard.find(guardKey) != includeGuard.end()) {
|
||||
output << "\n// [PREPROCESSOR] Skipped include (already included): " << includePath << "\n";
|
||||
continue;
|
||||
}
|
||||
includeGuard.insert(guardKey);
|
||||
|
||||
// Wczytaj + przetwórz rekurencyjnie
|
||||
std::string content = loadFileContent(fullPath.string());
|
||||
if (content.empty()) {
|
||||
output << "\n// [PREPROCESSOR] FAILED INCLUDE: " << includePath << "\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string processedContent = preprocessSourceImpl(content, projectDir, compilerDir, includeGuard);
|
||||
|
||||
output << "\n// --- BEGIN INCLUDE: " << includePath << " ---\n";
|
||||
output << processedContent;
|
||||
output << "\n// --- END INCLUDE ---\n";
|
||||
}
|
||||
|
||||
return output.str();
|
||||
}
|
||||
|
||||
std::string preprocessSource(const std::string& src, const std::string& projectDir, const std::string& compilerDir) {
|
||||
std::unordered_set<std::string> includeGuard;
|
||||
return preprocessSourceImpl(src, projectDir, compilerDir, includeGuard);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user