164 lines
5.1 KiB
C++
164 lines
5.1 KiB
C++
#include <iostream>
|
|
#include <fstream>
|
|
#include <string>
|
|
#include <vector>
|
|
#include <cstdlib>
|
|
#include <filesystem>
|
|
#include <windows.h>
|
|
#include "compiler_types.h"
|
|
#include "parser.h"
|
|
#include "codegen.h"
|
|
#include "preprocessor.h"
|
|
|
|
std::string getExecutablePath() {
|
|
char buffer[MAX_PATH];
|
|
GetModuleFileNameA(NULL, buffer, MAX_PATH);
|
|
std::string::size_type pos = std::string(buffer).find_last_of("\\/");
|
|
return std::string(buffer).substr(0, pos);
|
|
}
|
|
|
|
int main(int argc, char* argv[]) {
|
|
std::string inputFile, outputName;
|
|
std::string Version = "v0.0.5-beta";
|
|
bool showHelp = false, showVersion = false, showCredits = false;
|
|
|
|
// --- PARSOWANIE ARGUMENTÓW ---
|
|
for (int i = 1; i < argc; i++) {
|
|
std::string arg = argv[i];
|
|
|
|
if (arg == "--help" || arg == "-h") {
|
|
showHelp = true;
|
|
}
|
|
else if (arg == "--version" || arg == "-v") {
|
|
showVersion = true;
|
|
}
|
|
else if (arg == "--credits" || arg == "-c") {
|
|
showCredits = true;
|
|
}
|
|
else if (arg.substr(0, 2) == "-o") {
|
|
if (arg.size() > 2) {
|
|
outputName = arg.substr(2);
|
|
}
|
|
else if (i + 1 < argc) {
|
|
outputName = argv[++i];
|
|
}
|
|
}
|
|
else {
|
|
inputFile = arg;
|
|
}
|
|
}
|
|
|
|
// --- OBSŁUGA INFORMACYJNA ---
|
|
if (showVersion) {
|
|
std::cout << "PCC Compiler " << Version << " (x64, Modular structure)\n";
|
|
return 0;
|
|
}
|
|
|
|
if (showCredits) {
|
|
std::cout << "Created by: Michal Lewandowski\n";
|
|
std::cout << "Contact : slawek.1q2w3e4r@gmail.com\n"; // Twój email z oryginału
|
|
std::cout << "Docs: https://nodrop.xyz/PCC_docs.html\n";
|
|
return 0;
|
|
}
|
|
|
|
if (showHelp || inputFile.empty()) {
|
|
std::cout << "PCC Compiler " << Version << "\n";
|
|
std::cout << "Usage: PCC [Options] File.pcc\n\n";
|
|
std::cout << "Options:\n";
|
|
std::cout << " -h, --help Show Help\n";
|
|
std::cout << " -v, --version Show Version\n";
|
|
std::cout << " -o Name Exe Name (output\\Name.exe)\n";
|
|
return 0;
|
|
}
|
|
|
|
// --- WCZYTYWANIE PLIKU ---
|
|
std::ifstream in(inputFile);
|
|
if (!in) {
|
|
std::cerr << "Error: Cannot open file " << inputFile << "\n";
|
|
return 1;
|
|
}
|
|
|
|
// ... wczytywanie pliku (to co miałeś) ...
|
|
std::string src((std::istreambuf_iterator<char>(in)), std::istreambuf_iterator<char>());
|
|
in.close();
|
|
|
|
// --- PREPROCESSOR START ---
|
|
std::cout << "[INFO] Preprocessing...\n";
|
|
|
|
// 1. Ścieżka projektu (tam gdzie plik wejściowy)
|
|
std::filesystem::path p(inputFile);
|
|
std::string projectDir = p.parent_path().string();
|
|
|
|
// 2. Ścieżka kompilatora (tam gdzie PCC.exe i folder std)
|
|
std::string compilerDir = getExecutablePath();
|
|
|
|
// Uruchamiamy z obiema ścieżkami
|
|
src = preprocessSource(src, projectDir, compilerDir);
|
|
CompilerState state;
|
|
|
|
std::cout << "[INFO] Parsing code...\n";
|
|
// 1. Parsowanie tekstu do struktur
|
|
processSource(src, state);
|
|
|
|
std::cout << "[INFO] Calculating expressions...\n";
|
|
// 2. Obliczanie matematyki
|
|
calculateExpressions(state);
|
|
|
|
std::cout << "[INFO] Generating Assembly...\n";
|
|
// 3. Generowanie kodu ASM
|
|
std::string asmCode = generateAssembly(state);
|
|
|
|
|
|
// --- ZAPIS I KOMPILACJA ZEWNĘTRZNA ---
|
|
std::system("if not exist output mkdir output");
|
|
|
|
// 1. Ustal bazową nazwę (bez rozszerzenia)
|
|
std::string baseName;
|
|
if (outputName.empty()) {
|
|
// Jeśli nie podano -o, weź nazwę pliku wejściowego i utnij .pcc
|
|
size_t lastDot = inputFile.find_last_of(".");
|
|
if (lastDot != std::string::npos)
|
|
baseName = inputFile.substr(0, lastDot);
|
|
else
|
|
baseName = inputFile;
|
|
}
|
|
else {
|
|
// Jeśli podano -o, sprawdź czy ma .exe i ewentualnie utnij
|
|
// (żebyśmy mogli dodać .asm i .obj bez bałaganu)
|
|
size_t exePos = outputName.find(".exe");
|
|
if (exePos != std::string::npos)
|
|
baseName = outputName.substr(0, exePos);
|
|
else
|
|
baseName = outputName;
|
|
}
|
|
|
|
// Teraz budujemy ścieżki - czysto i ładnie
|
|
std::string asmPath = "output\\" + baseName + ".asm";
|
|
std::string objPath = "output\\" + baseName + ".obj";
|
|
std::string exePath = "output\\" + baseName + ".exe";
|
|
|
|
|
|
// Zapisz ASM
|
|
std::ofstream asmOut(asmPath);
|
|
asmOut << asmCode;
|
|
asmOut.close();
|
|
std::cout << "ASM saved to: " << asmPath << "\n";
|
|
|
|
// Uruchom NASM
|
|
std::string nasmCmd = "nasm -f win64 \"" + asmPath + "\" -o \"" + objPath + "\"";
|
|
if (std::system(nasmCmd.c_str()) != 0) {
|
|
std::cerr << "NASM Error! Check if NASM is in PATH.\n";
|
|
return 1;
|
|
}
|
|
|
|
// Uruchom GoLink
|
|
std::string linkCmd = "go-link.exe /console /entry:main \"" + objPath + "\" msvcrt.dll kernel32.dll user32.dll \"" + exePath + "\"";
|
|
if (std::system(linkCmd.c_str()) != 0) {
|
|
std::cerr << "GoLink Error! Check if go-link.exe is in PATH.\n";
|
|
return 1;
|
|
}
|
|
|
|
std::cout << "SUCCESS! Executable created: " << exePath << "\n";
|
|
return 0;
|
|
}
|