diff options
32 files changed, 4975 insertions, 6109 deletions
diff --git a/Private/CompilerKit/AsmKit/Arch/32x0.hpp b/Private/CompilerKit/AsmKit/Arch/32x0.hpp index f9be82b..bf4b4c1 100644 --- a/Private/CompilerKit/AsmKit/Arch/32x0.hpp +++ b/Private/CompilerKit/AsmKit/Arch/32x0.hpp @@ -15,43 +15,44 @@ // @file Arch/32x0.hpp #define kAsmOpcodeDecl(__NAME, __OPCODE, __FUNCT3, __FUNCT7) \ - { .fName = __NAME, .fOpcode = __OPCODE, .fFunct3 = __FUNCT3, .fFunct7 = __FUNCT7 }, - - - + {.fName = __NAME, \ + .fOpcode = __OPCODE, \ + .fFunct3 = __FUNCT3, \ + .fFunct7 = __FUNCT7}, #define kAsmImmediate 0x01 #define kAsmSyscall 0x02 #define kAsmJump 0x03 #define kAsmNoArgs 0x04 -#define kAsmByte 0 +#define kAsmByte 0 #define kAsmHWord 1 -#define kAsmWord 2 - -struct CpuCode32x0 -{ - const char fName[32]; - char fOpcode; - char fSize; - char fFunct3; - char fFunct7; +#define kAsmWord 2 + +struct CpuCode32x0 { + const char fName[32]; + char fOpcode; + char fSize; + char fFunct3; + char fFunct7; }; -#define kAsmDWordStr ".dword" /* 64 bit */ -#define kAsmWordStr ".word" /* 32-bit */ -#define kAsmHWordStr ".half" /* 16-bit */ -#define kAsmByteStr ".byte" /* 8-bit */ +#define kAsmDWordStr ".dword" /* 64 bit */ +#define kAsmWordStr ".word" /* 32-bit */ +#define kAsmHWordStr ".half" /* 16-bit */ +#define kAsmByteStr ".byte" /* 8-bit */ inline std::vector<CpuCode32x0> kOpcodes32x0 = { - kAsmOpcodeDecl("nop", 0b0100011, 0b000, kAsmNoArgs) // nothing to do. - kAsmOpcodeDecl("jmp", 0b1110011, 0b001, kAsmJump) // jump to branch - kAsmOpcodeDecl("move", 0b0100011, 0b101, kAsmImmediate) // move registers - kAsmOpcodeDecl("push", 0b0111011, 0b000, kAsmImmediate) // push to sp - kAsmOpcodeDecl("pop", 0b0111011, 0b001, kAsmImmediate) // pop from sp. - kAsmOpcodeDecl("cls", 0b0111011, 0b010, kAsmImmediate) // setup stack and call, store address to CR. - kAsmOpcodeDecl("rts", 0b0111011, 0b110, kAsmImmediate) // pull stack and return form CR. - kAsmOpcodeDecl("int", 0b0111111, 0b000, kAsmSyscall) // raise interrupt + kAsmOpcodeDecl("nop", 0b0100011, 0b000, kAsmNoArgs) // nothing to do. + kAsmOpcodeDecl("jmp", 0b1110011, 0b001, kAsmJump) // jump to branch + kAsmOpcodeDecl("move", 0b0100011, 0b101, kAsmImmediate) // move registers + kAsmOpcodeDecl("push", 0b0111011, 0b000, kAsmImmediate) // push to sp + kAsmOpcodeDecl("pop", 0b0111011, 0b001, kAsmImmediate) // pop from sp. + kAsmOpcodeDecl("cls", 0b0111011, 0b010, + kAsmImmediate) // setup stack and call, store address to CR. + kAsmOpcodeDecl("rts", 0b0111011, 0b110, + kAsmImmediate) // pull stack and return form CR. + kAsmOpcodeDecl("int", 0b0111111, 0b000, kAsmSyscall) // raise interrupt }; // \brief 64x0 register prefix @@ -60,13 +61,13 @@ inline std::vector<CpuCode32x0> kOpcodes32x0 = { // r0 -> hw zero #define kAsmRegisterPrefix "r" -#define kAsmRegisterLimit 16 -#define kAsmPcRegister 17 -#define kAsmCrRegister 18 -#define kAsmSpRegister 5 +#define kAsmRegisterLimit 16 +#define kAsmPcRegister 17 +#define kAsmCrRegister 18 +#define kAsmSpRegister 5 /* return address register */ -#define kAsmRetRegister 19 +#define kAsmRetRegister 19 ///////////////////////////////////////////////////////////////////////////// @@ -93,4 +94,4 @@ inline std::vector<CpuCode32x0> kOpcodes32x0 = { // PROCESS INTERRUPT // ENABLE INTERRUPTS -////////////////////////////////
\ No newline at end of file +//////////////////////////////// diff --git a/Private/CompilerKit/AsmKit/Arch/64x0.hpp b/Private/CompilerKit/AsmKit/Arch/64x0.hpp index 3052021..c00b0c9 100644 --- a/Private/CompilerKit/AsmKit/Arch/64x0.hpp +++ b/Private/CompilerKit/AsmKit/Arch/64x0.hpp @@ -15,9 +15,10 @@ // @file Arch/64x0.hpp #define kAsmOpcodeDecl(__NAME, __OPCODE, __FUNCT3, __FUNCT7) \ - { .fName = __NAME, .fOpcode = __OPCODE, .fFunct3 = __FUNCT3, .fFunct7 = __FUNCT7 }, - - + {.fName = __NAME, \ + .fOpcode = __OPCODE, \ + .fFunct3 = __FUNCT3, \ + .fFunct7 = __FUNCT7}, #define kAsmImmediate 0x01 #define kAsmRegToReg 0x02 @@ -28,40 +29,41 @@ typedef char e64k_character_t; typedef uint8_t e64k_num_t; -struct CpuCode64x0 -{ - const e64k_character_t fName[32]; - e64k_num_t fOpcode; - e64k_num_t fFunct3; - e64k_num_t fFunct7; +struct CpuCode64x0 { + const e64k_character_t fName[32]; + e64k_num_t fOpcode; + e64k_num_t fFunct3; + e64k_num_t fFunct7; }; inline std::vector<CpuCode64x0> kOpcodes64x0 = { - kAsmOpcodeDecl("nop", 0b0000000, 0b0000000, kAsmNoArgs) // no-operation. - kAsmOpcodeDecl("np", 0b0000000, 0b0000000, kAsmNoArgs) // no-operation. - kAsmOpcodeDecl("jlr", 0b1110011, 0b0000111, kAsmJump) // jump to linked return register - kAsmOpcodeDecl("jrl", 0b1110011, 0b0001111, kAsmJump) // jump from return register. - kAsmOpcodeDecl("mv", 0b0100011, 0b101, kAsmRegToReg) - kAsmOpcodeDecl("bg", 0b1100111, 0b111, kAsmRegToReg) - kAsmOpcodeDecl("bl", 0b1100111, 0b011, kAsmRegToReg) - kAsmOpcodeDecl("beq", 0b1100111, 0b000, kAsmRegToReg) - kAsmOpcodeDecl("bne", 0b1100111, 0b001, kAsmRegToReg) - kAsmOpcodeDecl("bge", 0b1100111, 0b101, kAsmRegToReg) - kAsmOpcodeDecl("ble", 0b1100111, 0b100, kAsmRegToReg) - kAsmOpcodeDecl("stw", 0b0001111, 0b100, kAsmImmediate) - kAsmOpcodeDecl("ldw", 0b0001111, 0b100, kAsmImmediate) - kAsmOpcodeDecl("lda", 0b0001111, 0b101, kAsmImmediate) - kAsmOpcodeDecl("sta", 0b0001111, 0b001, kAsmImmediate) + kAsmOpcodeDecl("nop", 0b0000000, 0b0000000, kAsmNoArgs) // no-operation. + kAsmOpcodeDecl("np", 0b0000000, 0b0000000, kAsmNoArgs) // no-operation. + kAsmOpcodeDecl("jlr", 0b1110011, 0b0000111, + kAsmJump) // jump to linked return register + kAsmOpcodeDecl("jrl", 0b1110011, 0b0001111, + kAsmJump) // jump from return register. + kAsmOpcodeDecl("mv", 0b0100011, 0b101, kAsmRegToReg) kAsmOpcodeDecl( + "bg", 0b1100111, 0b111, + kAsmRegToReg) kAsmOpcodeDecl("bl", 0b1100111, 0b011, kAsmRegToReg) + kAsmOpcodeDecl("beq", 0b1100111, 0b000, kAsmRegToReg) kAsmOpcodeDecl( + "bne", 0b1100111, 0b001, + kAsmRegToReg) kAsmOpcodeDecl("bge", 0b1100111, 0b101, kAsmRegToReg) + kAsmOpcodeDecl("ble", 0b1100111, 0b100, kAsmRegToReg) + kAsmOpcodeDecl("stw", 0b0001111, 0b100, kAsmImmediate) + kAsmOpcodeDecl("ldw", 0b0001111, 0b100, kAsmImmediate) + kAsmOpcodeDecl("lda", 0b0001111, 0b101, kAsmImmediate) + kAsmOpcodeDecl("sta", 0b0001111, 0b001, + kAsmImmediate) // add/sub without carry flag kAsmOpcodeDecl("add", 0b0101011, 0b100, kAsmImmediate) - kAsmOpcodeDecl("dec", 0b0101011, 0b101, kAsmImmediate) + kAsmOpcodeDecl("dec", 0b0101011, 0b101, kAsmImmediate) // add/sub with carry flag kAsmOpcodeDecl("addc", 0b0101011, 0b110, kAsmImmediate) - kAsmOpcodeDecl("decc", 0b0101011, 0b111, kAsmImmediate) - kAsmOpcodeDecl("int", 0b1110011, 0b00, kAsmSyscall) - kAsmOpcodeDecl("pha", 0b1110011, 0b00, kAsmNoArgs) - kAsmOpcodeDecl("pla", 0b1110011, 0b01, kAsmNoArgs) -}; + kAsmOpcodeDecl("decc", 0b0101011, 0b111, kAsmImmediate) + kAsmOpcodeDecl("int", 0b1110011, 0b00, kAsmSyscall) + kAsmOpcodeDecl("pha", 0b1110011, 0b00, kAsmNoArgs) + kAsmOpcodeDecl("pla", 0b1110011, 0b01, kAsmNoArgs)}; // \brief 64x0 register prefix // example: r32, r0 @@ -72,13 +74,13 @@ inline std::vector<CpuCode64x0> kOpcodes64x0 = { #define kAsmZeroRegister 0 #define kAsmRegisterPrefix "r" -#define kAsmRegisterLimit 30 -#define kAsmPcRegister 17 -#define kAsmCrRegister 18 -#define kAsmSpRegister 5 +#define kAsmRegisterLimit 30 +#define kAsmPcRegister 17 +#define kAsmCrRegister 18 +#define kAsmSpRegister 5 /* return address register */ -#define kAsmRetRegister 19 +#define kAsmRetRegister 19 ///////////////////////////////////////////////////////////////////////////// @@ -105,4 +107,4 @@ inline std::vector<CpuCode64x0> kOpcodes64x0 = { // PROCESS INTERRUPT // ENABLE INTERRUPTS -////////////////////////////////
\ No newline at end of file +//////////////////////////////// diff --git a/Private/CompilerKit/AsmKit/Arch/amd64.hpp b/Private/CompilerKit/AsmKit/Arch/amd64.hpp index ac92c9b..f7845e2 100644 --- a/Private/CompilerKit/AsmKit/Arch/amd64.hpp +++ b/Private/CompilerKit/AsmKit/Arch/amd64.hpp @@ -14,63 +14,51 @@ // @brief 64x0 support. // @file Arch/64x0.hpp -#define kAsmOpcodeDecl(__NAME, __OPCODE) \ - { .fName = __NAME, .fOpcode = __OPCODE }, - - - +#define kAsmOpcodeDecl(__NAME, __OPCODE) {.fName = __NAME, .fOpcode = __OPCODE}, typedef char e64k_character_t; typedef uint8_t e64_byte_t; typedef uint16_t e64_hword_t; typedef uint32_t e64k_word_t; -struct CpuCodeAMD64 -{ - std::string fName; - e64_byte_t fPrefixBytes[4]; - e64_hword_t fOpcode; - e64_hword_t fModReg; - e64k_word_t fDisplacment; - e64k_word_t fImmediate; +struct CpuCodeAMD64 { + std::string fName; + e64_byte_t fPrefixBytes[4]; + e64_hword_t fOpcode; + e64_hword_t fModReg; + e64k_word_t fDisplacment; + e64k_word_t fImmediate; }; /// these two are edge cases #define kAsmIntOpcode 0xCC #define kasmIntOpcodeAlt 0xCD -#define kAsmJumpOpcode 0x0F80 -#define kJumpLimit 30 -#define kJumpLimitStandard 0xE3 +#define kAsmJumpOpcode 0x0F80 +#define kJumpLimit 30 +#define kJumpLimitStandard 0xE3 #define kJumpLimitStandardLimit 0xEB inline std::vector<CpuCodeAMD64> kOpcodesAMD64 = { - kAsmOpcodeDecl("int", 0xCD) - kAsmOpcodeDecl("into", 0xCE) - kAsmOpcodeDecl("intd", 0xF1) - kAsmOpcodeDecl("int3", 0xC3) - - kAsmOpcodeDecl("iret", 0xCF) - kAsmOpcodeDecl("retf", 0xCB) - kAsmOpcodeDecl("retn", 0xC3) - kAsmOpcodeDecl("sti", 0xfb) - kAsmOpcodeDecl("cli", 0xfa) - - kAsmOpcodeDecl("nop", 0x90) - - kAsmOpcodeDecl("mov eax", 0xb8) - kAsmOpcodeDecl("mov ecx", 0xb9) - kAsmOpcodeDecl("mov edx", 0xba) - kAsmOpcodeDecl("mov ebx", 0xbb) - kAsmOpcodeDecl("mov esp", 0xbc) - kAsmOpcodeDecl("mov ebp", 0xbd) - kAsmOpcodeDecl("mov esi", 0xbe) - - kAsmOpcodeDecl("jmp", 0xE9) - kAsmOpcodeDecl("call", 0xE9) - - kAsmOpcodeDecl("mov", 0x00) -}; + kAsmOpcodeDecl("int", 0xCD) kAsmOpcodeDecl("into", 0xCE) kAsmOpcodeDecl( + "intd", 0xF1) kAsmOpcodeDecl("int3", 0xC3) + + kAsmOpcodeDecl("iret", 0xCF) kAsmOpcodeDecl("retf", 0xCB) + kAsmOpcodeDecl("retn", 0xC3) kAsmOpcodeDecl("sti", 0xfb) + kAsmOpcodeDecl("cli", 0xfa) + + kAsmOpcodeDecl("nop", 0x90) + + kAsmOpcodeDecl("mov eax", 0xb8) kAsmOpcodeDecl( + "mov ecx", 0xb9) kAsmOpcodeDecl("mov edx", 0xba) + kAsmOpcodeDecl("mov ebx", 0xbb) kAsmOpcodeDecl( + "mov esp", 0xbc) kAsmOpcodeDecl("mov ebp", 0xbd) + kAsmOpcodeDecl("mov esi", 0xbe) + + kAsmOpcodeDecl("jmp", 0xE9) + kAsmOpcodeDecl("call", 0xE9) + + kAsmOpcodeDecl("mov", 0x00)}; // \brief 64x0 register prefix // example: r32, r0 @@ -78,13 +66,13 @@ inline std::vector<CpuCodeAMD64> kOpcodesAMD64 = { // r0 -> hw zero #define kAsmFloatZeroRegister -1 -#define kAsmZeroRegister -1 +#define kAsmZeroRegister -1 #define kAsmRegisterPrefix "r" -#define kAsmRegisterLimit 16 -#define kAsmPcRegister 8 -#define kAsmCrRegister -1 -#define kAsmSpRegister 9 +#define kAsmRegisterLimit 16 +#define kAsmPcRegister 8 +#define kAsmCrRegister -1 +#define kAsmSpRegister 9 /* return address register */ -#define kAsmRetRegister 0 +#define kAsmRetRegister 0 diff --git a/Private/CompilerKit/AsmKit/AsmKit.cc b/Private/CompilerKit/AsmKit/AsmKit.cc index 1eea5cc..7cd1360 100644 --- a/Private/CompilerKit/AsmKit/AsmKit.cc +++ b/Private/CompilerKit/AsmKit/AsmKit.cc @@ -16,9 +16,9 @@ * @brief Assembler Kit * @version 0.1 * @date 2024-01-27 - * + * * @copyright Copyright (c) 2024, Mahrouss Logic - * + * */ #include <iostream> @@ -26,37 +26,29 @@ //! @file AsmKit.cpp //! @brief AssemblyKit source implementation. -namespace CompilerKit -{ - //! @brief Compile for specific format (ELF, PEF, ZBIN) - Int32 AssemblyFactory::Compile(StringView& sourceFile, - const Int32& arch) noexcept - { - if (sourceFile.Length() < 1 || - !fMounted) - return CXXKIT_UNIMPLEMENTED; - - return fMounted->CompileToFormat(sourceFile, arch); - } - - //! @brief mount assembly backend. - void AssemblyFactory::Mount(AssemblyMountpoint* mountPtr) noexcept - { - if (mountPtr) - { - fMounted = mountPtr; - } - } - - AssemblyMountpoint* AssemblyFactory::Unmount() noexcept - { - auto mount_prev = fMounted; - - if (mount_prev) - { - fMounted = nullptr; - } - - return mount_prev; - } +namespace CompilerKit { +//! @brief Compile for specific format (ELF, PEF, ZBIN) +Int32 AssemblyFactory::Compile(StringView& sourceFile, + const Int32& arch) noexcept { + if (sourceFile.Length() < 1 || !fMounted) return CXXKIT_UNIMPLEMENTED; + + return fMounted->CompileToFormat(sourceFile, arch); +} + +//! @brief mount assembly backend. +void AssemblyFactory::Mount(AssemblyMountpoint* mountPtr) noexcept { + if (mountPtr) { + fMounted = mountPtr; + } +} + +AssemblyMountpoint* AssemblyFactory::Unmount() noexcept { + auto mount_prev = fMounted; + + if (mount_prev) { + fMounted = nullptr; + } + + return mount_prev; } +} // namespace CompilerKit diff --git a/Private/CompilerKit/AsmKit/AsmKit.hpp b/Private/CompilerKit/AsmKit/AsmKit.hpp index a561aad..c838221 100644 --- a/Private/CompilerKit/AsmKit/AsmKit.hpp +++ b/Private/CompilerKit/AsmKit/AsmKit.hpp @@ -13,171 +13,156 @@ #include <CompilerKit/Defines.hpp> #include <CompilerKit/StdKit/String.hpp> -namespace CompilerKit -{ - // - // @brief Frontend to Assembly mountpoint. - // - class AssemblyMountpoint - { - public: - explicit AssemblyMountpoint() = default; - virtual ~AssemblyMountpoint() = default; - - CXXKIT_COPY_DEFAULT(AssemblyMountpoint); - - //@ brief compile to object file. - // Example C++ -> MASM -> AE object. - virtual Int32 CompileToFormat(StringView& src, Int32 arch) = 0; - - }; - - /// @brief Simple assembly factory - class AssemblyFactory final - { - public: - explicit AssemblyFactory() = default; - ~AssemblyFactory() = default; - - CXXKIT_COPY_DEFAULT(AssemblyFactory); - - public: - enum - { - kArchAMD64, - kArch32x0, - kArch64x0, - kArchRISCV, - kArchUnknown, - }; - - Int32 Compile(StringView& sourceFile, const Int32& arch) noexcept; - - void Mount(AssemblyMountpoint* mountPtr) noexcept; - AssemblyMountpoint* Unmount() noexcept; - - private: - AssemblyMountpoint* fMounted{ nullptr }; - - }; - - union NumberCastBase - { - NumberCastBase() = default; - ~NumberCastBase() = default; - - }; - - union NumberCast64 final - { - NumberCast64() = default; - explicit NumberCast64(UInt64 raw) : raw(raw) {} - ~NumberCast64() { raw = 0; } - - CharType number[8]; - UInt64 raw; - }; - - union NumberCast32 final - { - NumberCast32() = default; - explicit NumberCast32(UInt32 raw) : raw(raw) {} - ~NumberCast32() { raw = 0; } - - CharType number[4]; - UInt32 raw; - }; - - union NumberCast16 final - { - NumberCast16() = default; - explicit NumberCast16(UInt16 raw) : raw(raw) {} - ~NumberCast16() { raw = 0; } - - CharType number[2]; - UInt16 raw; - }; - - union NumberCast8 final - { - NumberCast8() = default; - explicit NumberCast8(UInt8 raw) : raw(raw) {} - ~NumberCast8() { raw = 0; } - - CharType number; - UInt8 raw; - }; - - class PlatformAssembler - { - public: - explicit PlatformAssembler() = default; - ~PlatformAssembler() = default; - - CXXKIT_COPY_DEFAULT(PlatformAssembler); - - virtual std::string CheckLine(std::string &line, const std::string &file) = 0; - virtual bool WriteLine(std::string &line, const std::string &file) = 0; - virtual bool WriteNumber(const std::size_t &pos, std::string &from_what) = 0; - - }; +namespace CompilerKit { +// +// @brief Frontend to Assembly mountpoint. +// +class AssemblyMountpoint { + public: + explicit AssemblyMountpoint() = default; + virtual ~AssemblyMountpoint() = default; + + CXXKIT_COPY_DEFAULT(AssemblyMountpoint); + + //@ brief compile to object file. + // Example C++ -> MASM -> AE object. + virtual Int32 CompileToFormat(StringView& src, Int32 arch) = 0; +}; + +/// @brief Simple assembly factory +class AssemblyFactory final { + public: + explicit AssemblyFactory() = default; + ~AssemblyFactory() = default; + + CXXKIT_COPY_DEFAULT(AssemblyFactory); + + public: + enum { + kArchAMD64, + kArch32x0, + kArch64x0, + kArchRISCV, + kArchUnknown, + }; + + Int32 Compile(StringView& sourceFile, const Int32& arch) noexcept; + + void Mount(AssemblyMountpoint* mountPtr) noexcept; + AssemblyMountpoint* Unmount() noexcept; + + private: + AssemblyMountpoint* fMounted{nullptr}; +}; + +union NumberCastBase { + NumberCastBase() = default; + ~NumberCastBase() = default; +}; + +union NumberCast64 final { + NumberCast64() = default; + explicit NumberCast64(UInt64 raw) : raw(raw) {} + ~NumberCast64() { raw = 0; } + + CharType number[8]; + UInt64 raw; +}; + +union NumberCast32 final { + NumberCast32() = default; + explicit NumberCast32(UInt32 raw) : raw(raw) {} + ~NumberCast32() { raw = 0; } + + CharType number[4]; + UInt32 raw; +}; + +union NumberCast16 final { + NumberCast16() = default; + explicit NumberCast16(UInt16 raw) : raw(raw) {} + ~NumberCast16() { raw = 0; } + + CharType number[2]; + UInt16 raw; +}; + +union NumberCast8 final { + NumberCast8() = default; + explicit NumberCast8(UInt8 raw) : raw(raw) {} + ~NumberCast8() { raw = 0; } + + CharType number; + UInt8 raw; +}; + +class PlatformAssembler { + public: + explicit PlatformAssembler() = default; + ~PlatformAssembler() = default; + + CXXKIT_COPY_DEFAULT(PlatformAssembler); + + virtual std::string CheckLine(std::string& line, const std::string& file) = 0; + virtual bool WriteLine(std::string& line, const std::string& file) = 0; + virtual bool WriteNumber(const std::size_t& pos, std::string& from_what) = 0; +}; #ifdef __ASM_NEED_AMD64__ - class PlatformAssemblerAMD64 final : public PlatformAssembler - { - public: - explicit PlatformAssemblerAMD64() = default; - ~PlatformAssemblerAMD64() = default; +class PlatformAssemblerAMD64 final : public PlatformAssembler { + public: + explicit PlatformAssemblerAMD64() = default; + ~PlatformAssemblerAMD64() = default; - CXXKIT_COPY_DEFAULT(PlatformAssemblerAMD64); + CXXKIT_COPY_DEFAULT(PlatformAssemblerAMD64); - virtual std::string CheckLine(std::string &line, const std::string &file) override; - virtual bool WriteLine(std::string &line, const std::string &file) override; - virtual bool WriteNumber(const std::size_t& pos, std::string& from_what) override; + virtual std::string CheckLine(std::string& line, + const std::string& file) override; + virtual bool WriteLine(std::string& line, const std::string& file) override; + virtual bool WriteNumber(const std::size_t& pos, + std::string& from_what) override; - virtual bool WriteNumber16(const std::size_t& pos, std::string& from_what); - virtual bool WriteNumber32(const std::size_t& pos, std::string& from_what); - virtual bool WriteNumber8(const std::size_t& pos, std::string& from_what); + virtual bool WriteNumber16(const std::size_t& pos, std::string& from_what); + virtual bool WriteNumber32(const std::size_t& pos, std::string& from_what); + virtual bool WriteNumber8(const std::size_t& pos, std::string& from_what); +}; - }; - -#endif // __ASM_NEED_AMD64__ +#endif // __ASM_NEED_AMD64__ #ifdef __ASM_NEED_64x0__ - class PlatformAssembler64x0 final : public PlatformAssembler - { - public: - explicit PlatformAssembler64x0() = default; - ~PlatformAssembler64x0() = default; - - CXXKIT_COPY_DEFAULT(PlatformAssembler64x0); +class PlatformAssembler64x0 final : public PlatformAssembler { + public: + explicit PlatformAssembler64x0() = default; + ~PlatformAssembler64x0() = default; - virtual std::string CheckLine(std::string &line, const std::string &file) override; - virtual bool WriteLine(std::string &line, const std::string &file) override; - virtual bool WriteNumber(const std::size_t& pos, std::string& from_what) override; + CXXKIT_COPY_DEFAULT(PlatformAssembler64x0); - }; + virtual std::string CheckLine(std::string& line, + const std::string& file) override; + virtual bool WriteLine(std::string& line, const std::string& file) override; + virtual bool WriteNumber(const std::size_t& pos, + std::string& from_what) override; +}; -#endif // __ASM_NEED_64x0__ +#endif // __ASM_NEED_64x0__ #ifdef __ASM_NEED_32x0__ - class PlatformAssembler32x0 final : public PlatformAssembler - { - public: - explicit PlatformAssembler32x0() = default; - ~PlatformAssembler32x0() = default; - - CXXKIT_COPY_DEFAULT(PlatformAssembler32x0); - - virtual std::string CheckLine(std::string &line, const std::string &file) override; - virtual bool WriteLine(std::string &line, const std::string &file) override; - virtual bool WriteNumber(const std::size_t& pos, std::string& from_what) override; +class PlatformAssembler32x0 final : public PlatformAssembler { + public: + explicit PlatformAssembler32x0() = default; + ~PlatformAssembler32x0() = default; - }; + CXXKIT_COPY_DEFAULT(PlatformAssembler32x0); -#endif // __ASM_NEED_32x0__ -} + virtual std::string CheckLine(std::string& line, + const std::string& file) override; + virtual bool WriteLine(std::string& line, const std::string& file) override; + virtual bool WriteNumber(const std::size_t& pos, + std::string& from_what) override; +}; +#endif // __ASM_NEED_32x0__ +} // namespace CompilerKit diff --git a/Private/CompilerKit/Compiler.hpp b/Private/CompilerKit/Compiler.hpp index 810652f..d3d32bb 100644 --- a/Private/CompilerKit/Compiler.hpp +++ b/Private/CompilerKit/Compiler.hpp @@ -12,25 +12,20 @@ #ifndef _CK_CL_HPP #define _CK_CL_HPP -#define CXXKIT_COPY_DELETE(KLASS) \ - KLASS &operator=(const KLASS &) = delete; \ - KLASS(const KLASS &) = delete; +#define CXXKIT_COPY_DELETE(KLASS) \ + KLASS &operator=(const KLASS &) = delete; \ + KLASS(const KLASS &) = delete; +#define CXXKIT_COPY_DEFAULT(KLASS) \ + KLASS &operator=(const KLASS &) = default; \ + KLASS(const KLASS &) = default; -#define CXXKIT_COPY_DEFAULT(KLASS) \ - KLASS &operator=(const KLASS &) = default; \ - KLASS(const KLASS &) = default; +#define CXXKIT_MOVE_DELETE(KLASS) \ + KLASS &operator=(KLASS &&) = delete; \ + KLASS(KLASS &&) = delete; +#define CXXKIT_MOVE_DEFAULT(KLASS) \ + KLASS &operator=(KLASS &&) = default; \ + KLASS(KLASS &&) = default; -#define CXXKIT_MOVE_DELETE(KLASS) \ - KLASS &operator=(KLASS &&) = delete; \ - KLASS(KLASS &&) = delete; - - -#define CXXKIT_MOVE_DEFAULT(KLASS) \ - KLASS &operator=(KLASS &&) = default; \ - KLASS(KLASS &&) = default; - - - -#endif /* ifndef _CK_CL_HPP */
\ No newline at end of file +#endif /* ifndef _CK_CL_HPP */ diff --git a/Private/CompilerKit/Defines.hpp b/Private/CompilerKit/Defines.hpp index 568e024..42c7d2a 100644 --- a/Private/CompilerKit/Defines.hpp +++ b/Private/CompilerKit/Defines.hpp @@ -12,17 +12,17 @@ #ifndef Yes #define Yes true -#endif // ifndef Yes +#endif // ifndef Yes #ifndef No #define No false -#endif // ifndef No +#endif // ifndef No #include <stdint.h> #define SizeType size_t -#define VoidPtr void* +#define VoidPtr void * #define voidPtr VoidPtr #define UIntPtr uintptr_t @@ -44,103 +44,93 @@ #define CharType char #define Boolean bool -#include <new> -#include <cstring> #include <cassert> +#include <cstring> +#include <new> #define nullPtr std::nullptr_t #define MUST_PASS(E) assert(E) #ifndef __FORCE_STRLEN -# define __FORCE_STRLEN 1 +#define __FORCE_STRLEN 1 -# define string_length(len) strlen(len) +#define string_length(len) strlen(len) #endif #ifndef __FORCE_MEMCPY -# define __FORCE_MEMCPY 1 +#define __FORCE_MEMCPY 1 -# define rt_copy_memory(dst, src, len) memcpy(dst, src, len) +#define rt_copy_memory(dst, src, len) memcpy(dst, src, len) #endif -#define CXXKIT_COPY_DELETE(KLASS) \ - KLASS &operator=(const KLASS &) = delete; \ - KLASS(const KLASS &) = delete; +#define CXXKIT_COPY_DELETE(KLASS) \ + KLASS &operator=(const KLASS &) = delete; \ + KLASS(const KLASS &) = delete; +#define CXXKIT_COPY_DEFAULT(KLASS) \ + KLASS &operator=(const KLASS &) = default; \ + KLASS(const KLASS &) = default; -#define CXXKIT_COPY_DEFAULT(KLASS) \ - KLASS &operator=(const KLASS &) = default; \ - KLASS(const KLASS &) = default; +#define CXXKIT_MOVE_DELETE(KLASS) \ + KLASS &operator=(KLASS &&) = delete; \ + KLASS(KLASS &&) = delete; +#define CXXKIT_MOVE_DEFAULT(KLASS) \ + KLASS &operator=(KLASS &&) = default; \ + KLASS(KLASS &&) = default; -#define CXXKIT_MOVE_DELETE(KLASS) \ - KLASS &operator=(KLASS &&) = delete; \ - KLASS(KLASS &&) = delete; +#include <ctime> +#include <fstream> +#include <string> +namespace CompilerKit { +inline constexpr int BASE_YEAR = 1900; -#define CXXKIT_MOVE_DEFAULT(KLASS) \ - KLASS &operator=(KLASS &&) = default; \ - KLASS(KLASS &&) = default; +inline std::string current_date() { + auto time_data = time(nullptr); + auto time_struct = gmtime(&time_data); + std::string fmt = std::to_string(BASE_YEAR + time_struct->tm_year); + fmt += "-"; + fmt += std::to_string(time_struct->tm_mon + 1); + fmt += "-"; + fmt += std::to_string(time_struct->tm_mday); + return fmt; +} -#include <ctime> -#include <string> -#include <fstream> +inline bool to_str(CharType *str, Int32 limit, Int32 base) { + if (limit == 0) return false; + + Int32 copy_limit = limit; + Int32 cnt = 0; + Int32 ret = base; -namespace CompilerKit -{ - inline constexpr int BASE_YEAR = 1900; - - inline std::string current_date() - { - auto time_data = time(nullptr); - auto time_struct = gmtime(&time_data); - - std::string fmt = std::to_string(BASE_YEAR + time_struct->tm_year); - fmt += "-"; - fmt += std::to_string(time_struct->tm_mon + 1); - fmt += "-"; - fmt += std::to_string(time_struct->tm_mday); - - return fmt; - } - - inline bool to_str(CharType *str, Int32 limit, Int32 base) - { - if (limit == 0) - return false; - - Int32 copy_limit = limit; - Int32 cnt = 0; - Int32 ret = base; - - while (limit != 1) - { - ret = ret % 10; - str[cnt] = ret; - - ++cnt; - --limit; - --ret; - } - - str[copy_limit] = '\0'; - return true; - } + while (limit != 1) { + ret = ret % 10; + str[cnt] = ret; + + ++cnt; + --limit; + --ret; + } + + str[copy_limit] = '\0'; + return true; } +} // namespace CompilerKit typedef char char_type; -#define kObjectFileExt ".o" -#define kAsmFileExts { ".64x", ".32x", ".masm", ".s", ".S" } +#define kObjectFileExt ".o" +#define kAsmFileExts \ + { ".64x", ".32x", ".masm", ".s", ".S" } #ifdef __MODULE_NEED__ -# define MPCC_MODULE(name) int name(int argc, char** argv) +#define MPCC_MODULE(name) int name(int argc, char **argv) #else -# define MPCC_MODULE(name) int main(int argc, char** argv) +#define MPCC_MODULE(name) int main(int argc, char **argv) #endif /* ifdef __MODULE_NEED__ */ #endif /* ifndef __CXXKIT_DEFINES_HPP__ */ - diff --git a/Private/CompilerKit/ParserKit.hpp b/Private/CompilerKit/ParserKit.hpp index 49907e5..614e56c 100644 --- a/Private/CompilerKit/ParserKit.hpp +++ b/Private/CompilerKit/ParserKit.hpp @@ -11,101 +11,89 @@ #include <CompilerKit/AsmKit/AsmKit.hpp> -namespace ParserKit -{ - using namespace CompilerKit; - - class CompilerBackend - { - public: - explicit CompilerBackend() = default; - virtual ~CompilerBackend() = default; - - CXXKIT_COPY_DEFAULT(CompilerBackend); - - // NOTE: cast this to your user defined ast. - typedef void* AstType; - - //! @brief Compile a syntax tree ouf of the text. - //! Also takes the source file name for metadata. - - virtual bool Compile(const std::string& text, const char* file) = 0; - - //! @brief What language are we dealing with? - virtual const char* Language() { return "Generic Language"; } - - }; - - struct SyntaxLeafList; - struct SyntaxLeafList; - - struct SyntaxLeafList final - { - struct SyntaxLeaf final - { - Int32 fUserType; - std::string fUserData; - std::string fUserValue; - struct SyntaxLeaf* fNext; - }; - - std::vector<SyntaxLeaf> fLeafList; - SizeType fNumLeafs; - - size_t SizeOf() { return fNumLeafs; } - std::vector<SyntaxLeaf>& Get() { return fLeafList; } - SyntaxLeaf& At(size_t index) { return fLeafList[index]; } - - }; - - /// find the perfect matching word in a haystack. - /// \param haystack base string - /// \param needle the string we search for. - /// \return if we found it or not. - inline bool find_word(const std::string& haystack,const std::string& needle) noexcept - { - auto index = haystack.find(needle); - - // check for needle validity. - if (index == std::string::npos) - return false; - - // declare lambda - auto not_part_of_word = [&](int index){ - if (std::isspace(haystack[index]) || std::ispunct(haystack[index])) - return true; - - if (index < 0 || index >= haystack.size()) - return true; - - return false; - }; - - return not_part_of_word(index - 1) && - not_part_of_word(index + needle.size()); - } - - /// find a word within strict conditions and returns a range of it. - /// \param haystack - /// \param needle - /// \return position of needle. - inline std::size_t find_word_range(const std::string& haystack, const std::string& needle) noexcept - { - auto index = haystack.find(needle); - - // check for needle validity. - if (index == std::string::npos) - return false; - - if (!isalnum((haystack[index + needle.size() + 1])) && - !isdigit(haystack[index + needle.size() + 1]) && - !isalnum((haystack[index - needle.size() - 1])) && - !isdigit(haystack[index - needle.size() - 1])) - { - return index; - } - - return false; - } +namespace ParserKit { +using namespace CompilerKit; + +class CompilerBackend { + public: + explicit CompilerBackend() = default; + virtual ~CompilerBackend() = default; + + CXXKIT_COPY_DEFAULT(CompilerBackend); + + // NOTE: cast this to your user defined ast. + typedef void* AstType; + + //! @brief Compile a syntax tree ouf of the text. + //! Also takes the source file name for metadata. + + virtual bool Compile(const std::string& text, const char* file) = 0; + + //! @brief What language are we dealing with? + virtual const char* Language() { return "Generic Language"; } +}; + +struct SyntaxLeafList; +struct SyntaxLeafList; + +struct SyntaxLeafList final { + struct SyntaxLeaf final { + Int32 fUserType; + std::string fUserData; + std::string fUserValue; + struct SyntaxLeaf* fNext; + }; + + std::vector<SyntaxLeaf> fLeafList; + SizeType fNumLeafs; + + size_t SizeOf() { return fNumLeafs; } + std::vector<SyntaxLeaf>& Get() { return fLeafList; } + SyntaxLeaf& At(size_t index) { return fLeafList[index]; } +}; + +/// find the perfect matching word in a haystack. +/// \param haystack base string +/// \param needle the string we search for. +/// \return if we found it or not. +inline bool find_word(const std::string& haystack, + const std::string& needle) noexcept { + auto index = haystack.find(needle); + + // check for needle validity. + if (index == std::string::npos) return false; + + // declare lambda + auto not_part_of_word = [&](int index) { + if (std::isspace(haystack[index]) || std::ispunct(haystack[index])) + return true; + + if (index < 0 || index >= haystack.size()) return true; + + return false; + }; + + return not_part_of_word(index - 1) && not_part_of_word(index + needle.size()); } +/// find a word within strict conditions and returns a range of it. +/// \param haystack +/// \param needle +/// \return position of needle. +inline std::size_t find_word_range(const std::string& haystack, + const std::string& needle) noexcept { + auto index = haystack.find(needle); + + // check for needle validity. + if (index == std::string::npos) return false; + + if (!isalnum((haystack[index + needle.size() + 1])) && + !isdigit(haystack[index + needle.size() + 1]) && + !isalnum((haystack[index - needle.size() - 1])) && + !isdigit(haystack[index - needle.size() - 1])) { + return index; + } + + return false; +} +} // namespace ParserKit diff --git a/Private/CompilerKit/StdKit/AE.hpp b/Private/CompilerKit/StdKit/AE.hpp index 77358fb..4144252 100644 --- a/Private/CompilerKit/StdKit/AE.hpp +++ b/Private/CompilerKit/StdKit/AE.hpp @@ -15,127 +15,115 @@ #define kAEMag1 'E' #define kAESymbolLen 64 -#define kAEPad 8 +#define kAEPad 8 #define kAEMagLen 2 #define kAEInvalidOpcode 0x00 // Advanced Executable File Format for MetroLink. // Reloctable by offset is the default strategy. -// You can also relocate at runtime but that's up to the operating system loader. - -namespace CompilerKit -{ - // @brief Advanced Executable Header - // One thing to keep in mind. - // This object format, is reloctable. - typedef struct AEHeader final - { - CharType fMagic[kAEMagLen]; - CharType fArch; - SizeType fCount; - CharType fSize; - SizeType fStartCode; - SizeType fCodeSize; - CharType fPad[kAEPad]; - } __attribute__((packed)) AEHeader, *AEHeaderPtr; - - // @brief Advanced Executable Record. - // Could be data, code or bss. - // fKind must be filled with PEF fields. - - typedef struct AERecordHeader final - { - CharType fName[kAESymbolLen]; - SizeType fKind; - SizeType fSize; - SizeType fFlags; - UIntPtr fOffset; - CharType fPad[kAEPad]; - } __attribute__((packed)) AERecordHeader, *AERecordHeaderPtr; - - enum - { - kKindRelocationByOffset = 0x23f, - kKindRelocationAtRuntime = 0x34f, - }; -} - +// You can also relocate at runtime but that's up to the operating system +// loader. + +namespace CompilerKit { +// @brief Advanced Executable Header +// One thing to keep in mind. +// This object format, is reloctable. +typedef struct AEHeader final { + CharType fMagic[kAEMagLen]; + CharType fArch; + SizeType fCount; + CharType fSize; + SizeType fStartCode; + SizeType fCodeSize; + CharType fPad[kAEPad]; +} __attribute__((packed)) AEHeader, *AEHeaderPtr; + +// @brief Advanced Executable Record. +// Could be data, code or bss. +// fKind must be filled with PEF fields. + +typedef struct AERecordHeader final { + CharType fName[kAESymbolLen]; + SizeType fKind; + SizeType fSize; + SizeType fFlags; + UIntPtr fOffset; + CharType fPad[kAEPad]; +} __attribute__((packed)) AERecordHeader, *AERecordHeaderPtr; + +enum { + kKindRelocationByOffset = 0x23f, + kKindRelocationAtRuntime = 0x34f, +}; +} // namespace CompilerKit // provide operator<< for AE -std::ofstream &operator<<(std::ofstream &fp, CompilerKit::AEHeader &container) -{ - fp.write((char *)&container, sizeof(CompilerKit::AEHeader)); +std::ofstream &operator<<(std::ofstream &fp, CompilerKit::AEHeader &container) { + fp.write((char *)&container, sizeof(CompilerKit::AEHeader)); - return fp; + return fp; } -std::ofstream &operator<<(std::ofstream &fp, CompilerKit::AERecordHeader &container) -{ - fp.write((char *)&container, sizeof(CompilerKit::AERecordHeader)); +std::ofstream &operator<<(std::ofstream &fp, + CompilerKit::AERecordHeader &container) { + fp.write((char *)&container, sizeof(CompilerKit::AERecordHeader)); - return fp; + return fp; } -std::ifstream &operator>>(std::ifstream& fp, CompilerKit::AEHeader& container) -{ - fp.read((char*)&container, sizeof(CompilerKit::AEHeader)); - return fp; +std::ifstream &operator>>(std::ifstream &fp, CompilerKit::AEHeader &container) { + fp.read((char *)&container, sizeof(CompilerKit::AEHeader)); + return fp; } -std::ifstream &operator>>(std::ifstream& fp, CompilerKit::AERecordHeader& container) -{ - fp.read((char*)&container, sizeof(CompilerKit::AERecordHeader)); - return fp; +std::ifstream &operator>>(std::ifstream &fp, + CompilerKit::AERecordHeader &container) { + fp.read((char *)&container, sizeof(CompilerKit::AERecordHeader)); + return fp; } -namespace CompilerKit::Utils -{ - /** - * @brief AE Reader protocol - * - */ - class AEReadableProtocol final - { - public: - std::ifstream FP; - - public: - explicit AEReadableProtocol() = default; - ~AEReadableProtocol() = default; - - CXXKIT_COPY_DELETE(AEReadableProtocol); - - /** - * @brief Read AE record - * - * @param raw the containing buffer - * @param sz it's size (without sizeof(AERecordHeader) added to it.) - * @return AERecordHeaderPtr - */ - AERecordHeaderPtr Read(char* raw, std::size_t sz) - { - if (!raw) - return nullptr; - - return this->_Read<AERecordHeader>(raw, sz * sizeof(AERecordHeader)); - } - - private: - /** - * @brief Implementation of Read for raw classes. - * - * @tparam TypeClass The class to read. - * @param raw the buffer - * @param sz the size - * @return TypeClass* the returning class. - */ - template <typename TypeClass> - TypeClass* _Read(char* raw, std::size_t sz) - { - FP.read(raw, std::streamsize(sz)); - return reinterpret_cast<TypeClass*>(raw); - } - - }; -} // namespace CompilerKit::Utils
\ No newline at end of file +namespace CompilerKit::Utils { +/** + * @brief AE Reader protocol + * + */ +class AEReadableProtocol final { + public: + std::ifstream FP; + + public: + explicit AEReadableProtocol() = default; + ~AEReadableProtocol() = default; + + CXXKIT_COPY_DELETE(AEReadableProtocol); + + /** + * @brief Read AE record + * + * @param raw the containing buffer + * @param sz it's size (without sizeof(AERecordHeader) added to it.) + * @return AERecordHeaderPtr + */ + AERecordHeaderPtr Read(char *raw, std::size_t sz) { + if (!raw) return nullptr; + + return this->_Read<AERecordHeader>(raw, sz * sizeof(AERecordHeader)); + } + + private: + /** + * @brief Implementation of Read for raw classes. + * + * @tparam TypeClass The class to read. + * @param raw the buffer + * @param sz the size + * @return TypeClass* the returning class. + */ + template <typename TypeClass> + TypeClass *_Read(char *raw, std::size_t sz) { + FP.read(raw, std::streamsize(sz)); + return reinterpret_cast<TypeClass *>(raw); + } +}; +} // namespace CompilerKit::Utils diff --git a/Private/CompilerKit/StdKit/ErrorID.hpp b/Private/CompilerKit/StdKit/ErrorID.hpp index e7bc7de..5577197 100644 --- a/Private/CompilerKit/StdKit/ErrorID.hpp +++ b/Private/CompilerKit/StdKit/ErrorID.hpp @@ -9,8 +9,8 @@ #pragma once -#include <StdKit/ErrorOr.hpp> #include <Defines.hpp> +#include <StdKit/ErrorOr.hpp> #define CXXKIT_EXEC_ERROR -30 #define CXXKIT_FILE_NOT_FOUND -31 diff --git a/Private/CompilerKit/StdKit/ErrorOr.hpp b/Private/CompilerKit/StdKit/ErrorOr.hpp index 97aeaa2..7da6135 100644 --- a/Private/CompilerKit/StdKit/ErrorOr.hpp +++ b/Private/CompilerKit/StdKit/ErrorOr.hpp @@ -12,47 +12,34 @@ #include <CompilerKit/Defines.hpp> #include <CompilerKit/StdKit/Ref.hpp> -namespace CompilerKit -{ +namespace CompilerKit { using ErrorT = UInt32; -template <typename T> -class ErrorOr final -{ - public: - ErrorOr() = default; - ~ErrorOr() = default; - - public: - explicit ErrorOr(Int32 err) - : mId(err) - {} - - explicit ErrorOr(nullPtr Null) - {} - - explicit ErrorOr(T Class) - : mRef(Class) - {} - - ErrorOr &operator=(const ErrorOr &) = default; - ErrorOr(const ErrorOr &) = default; - - Ref<T> Leak() - { - return mRef; - } - - operator bool() - { - return mRef; - } - - private: - Ref<T> mRef; - Int32 mId{0}; +template <typename T> +class ErrorOr final { + public: + ErrorOr() = default; + ~ErrorOr() = default; + + public: + explicit ErrorOr(Int32 err) : mId(err) {} + + explicit ErrorOr(nullPtr Null) {} + + explicit ErrorOr(T Class) : mRef(Class) {} + + ErrorOr &operator=(const ErrorOr &) = default; + ErrorOr(const ErrorOr &) = default; + + Ref<T> Leak() { return mRef; } + + operator bool() { return mRef; } + + private: + Ref<T> mRef; + Int32 mId{0}; }; using ErrorOrAny = ErrorOr<voidPtr>; -} // namespace CompilerKit +} // namespace CompilerKit diff --git a/Private/CompilerKit/StdKit/PEF.hpp b/Private/CompilerKit/StdKit/PEF.hpp index a26af9e..dbc98ca 100644 --- a/Private/CompilerKit/StdKit/PEF.hpp +++ b/Private/CompilerKit/StdKit/PEF.hpp @@ -14,7 +14,7 @@ // @file PEF.hpp // @brief Preferred Executable Format -#define kPefMagic "PEF" +#define kPefMagic "PEF" #define kPefMagicFat "FEP" #define kPefExt ".out" @@ -29,84 +29,78 @@ #define kPefBaseOrigin 0x1000 -namespace CompilerKit -{ - enum - { - kPefArchIntel86S = 100, - kPefArchAMD64, - kPefArchRISCV, - kPefArch64000, /* 64x0 RISC architecture. */ - kPefArch32000, - kPefArchInvalid = 0xFF, - }; - - enum - { - kPefKindExec = 1, /* .o/.pef/<none> */ - kPefKindSharedObject = 2, /* .lib */ - kPefKindObject = 4, /* .obj */ - kPefKindDwarf = 5, /* .dsym */ - }; - - /* PEF container */ - typedef struct PEFContainer final - { - CharType Magic[kPefMagicLen]; - UInt32 Linker; - UInt32 Version; - UInt32 Kind; - UInt32 Abi; - UInt32 Cpu; - UInt32 SubCpu; /* Cpu specific information */ - UIntPtr Start; /* Origin of code */ - SizeType HdrSz; /* Size of header */ - SizeType Count; /* container header count */ - } __attribute__((packed)) PEFContainer; - - /* First PEFCommandHeader starts after PEFContainer */ - /* Last container is __exec_end */ - - /* PEF executable section and commands. */ - - typedef struct PEFCommandHeader final - { - CharType Name[kPefNameLen]; /* container name */ - UInt32 Flags; /* container flags */ - UInt16 Kind; /* container kind */ - UIntPtr Offset; /* file offset */ - SizeType Size; /* file size */ - } __attribute__((packed)) PEFCommandHeader; - - enum - { - kPefCode = 0xC, - kPefData = 0xD, - kPefZero = 0xE, - kPefLinkerID = 0x1, - }; -} // namespace CompilerKit - -inline std::ofstream& operator<<(std::ofstream& fp, CompilerKit::PEFContainer& container) -{ - fp.write((char*)&container, sizeof(CompilerKit::PEFContainer)); - return fp; +namespace CompilerKit { +enum { + kPefArchIntel86S = 100, + kPefArchAMD64, + kPefArchRISCV, + kPefArch64000, /* 64x0 RISC architecture. */ + kPefArch32000, + kPefArchInvalid = 0xFF, +}; + +enum { + kPefKindExec = 1, /* .o/.pef/<none> */ + kPefKindSharedObject = 2, /* .lib */ + kPefKindObject = 4, /* .obj */ + kPefKindDwarf = 5, /* .dsym */ +}; + +/* PEF container */ +typedef struct PEFContainer final { + CharType Magic[kPefMagicLen]; + UInt32 Linker; + UInt32 Version; + UInt32 Kind; + UInt32 Abi; + UInt32 Cpu; + UInt32 SubCpu; /* Cpu specific information */ + UIntPtr Start; /* Origin of code */ + SizeType HdrSz; /* Size of header */ + SizeType Count; /* container header count */ +} __attribute__((packed)) PEFContainer; + +/* First PEFCommandHeader starts after PEFContainer */ +/* Last container is __exec_end */ + +/* PEF executable section and commands. */ + +typedef struct PEFCommandHeader final { + CharType Name[kPefNameLen]; /* container name */ + UInt32 Flags; /* container flags */ + UInt16 Kind; /* container kind */ + UIntPtr Offset; /* file offset */ + SizeType Size; /* file size */ +} __attribute__((packed)) PEFCommandHeader; + +enum { + kPefCode = 0xC, + kPefData = 0xD, + kPefZero = 0xE, + kPefLinkerID = 0x1, +}; +} // namespace CompilerKit + +inline std::ofstream& operator<<(std::ofstream& fp, + CompilerKit::PEFContainer& container) { + fp.write((char*)&container, sizeof(CompilerKit::PEFContainer)); + return fp; } -inline std::ofstream& operator<<(std::ofstream& fp, CompilerKit::PEFCommandHeader& container) -{ - fp.write((char*)&container, sizeof(CompilerKit::PEFCommandHeader)); - return fp; +inline std::ofstream& operator<<(std::ofstream& fp, + CompilerKit::PEFCommandHeader& container) { + fp.write((char*)&container, sizeof(CompilerKit::PEFCommandHeader)); + return fp; } -std::ifstream &operator>>(std::ifstream& fp, CompilerKit::PEFContainer& container) -{ - fp.read((char*)&container, sizeof(CompilerKit::PEFContainer)); - return fp; +std::ifstream& operator>>(std::ifstream& fp, + CompilerKit::PEFContainer& container) { + fp.read((char*)&container, sizeof(CompilerKit::PEFContainer)); + return fp; } -std::ifstream &operator>>(std::ifstream& fp, CompilerKit::PEFCommandHeader& container) -{ - fp.read((char*)&container, sizeof(CompilerKit::PEFCommandHeader)); - return fp; +std::ifstream& operator>>(std::ifstream& fp, + CompilerKit::PEFCommandHeader& container) { + fp.read((char*)&container, sizeof(CompilerKit::PEFCommandHeader)); + return fp; } diff --git a/Private/CompilerKit/StdKit/Ref.hpp b/Private/CompilerKit/StdKit/Ref.hpp index 9b79ca9..d7ef957 100644 --- a/Private/CompilerKit/StdKit/Ref.hpp +++ b/Private/CompilerKit/StdKit/Ref.hpp @@ -10,78 +10,57 @@ #pragma once -namespace CompilerKit -{ - // @author Amlal EL Mahrouss - // @brief Reference class, refers to a pointer of data in static memory. - template <typename T> - class Ref final - { - public: - explicit Ref() = default; - ~Ref() = default; - - public: - explicit Ref(T cls, const bool &strong = false) : m_Class(cls), m_Strong(strong) {} - - Ref& operator=(T ref) - { - m_Class = ref; - return *this; - } - - public: - T operator->() const - { - return m_Class; - } - - T &Leak() - { - return m_Class; - } - - T operator*() - { - return m_Class; - } - - bool IsStrong() const - { - return m_Strong; - } - - operator bool() - { - return m_Class; - } - - private: - T m_Class; - bool m_Strong{ false }; - - }; - - template <typename T> - class NonNullRef final - { - public: - NonNullRef() = delete; - NonNullRef(nullPtr) = delete; - - explicit NonNullRef(T *ref) : m_Ref(ref, true) {} - - Ref<T> &operator->() - { - MUST_PASS(m_Ref); - return m_Ref; - } - - NonNullRef &operator=(const NonNullRef<T> &ref) = delete; - NonNullRef(const NonNullRef<T> &ref) = default; - - private: - Ref<T> m_Ref{ nullptr }; - - }; -} // namespace CompilerKit +namespace CompilerKit { +// @author Amlal EL Mahrouss +// @brief Reference class, refers to a pointer of data in static memory. +template <typename T> +class Ref final { + public: + explicit Ref() = default; + ~Ref() = default; + + public: + explicit Ref(T cls, const bool &strong = false) + : m_Class(cls), m_Strong(strong) {} + + Ref &operator=(T ref) { + m_Class = ref; + return *this; + } + + public: + T operator->() const { return m_Class; } + + T &Leak() { return m_Class; } + + T operator*() { return m_Class; } + + bool IsStrong() const { return m_Strong; } + + operator bool() { return m_Class; } + + private: + T m_Class; + bool m_Strong{false}; +}; + +template <typename T> +class NonNullRef final { + public: + NonNullRef() = delete; + NonNullRef(nullPtr) = delete; + + explicit NonNullRef(T *ref) : m_Ref(ref, true) {} + + Ref<T> &operator->() { + MUST_PASS(m_Ref); + return m_Ref; + } + + NonNullRef &operator=(const NonNullRef<T> &ref) = delete; + NonNullRef(const NonNullRef<T> &ref) = default; + + private: + Ref<T> m_Ref{nullptr}; +}; +} // namespace CompilerKit diff --git a/Private/CompilerKit/StdKit/String.cc b/Private/CompilerKit/StdKit/String.cc index 519ccff..958638d 100644 --- a/Private/CompilerKit/StdKit/String.cc +++ b/Private/CompilerKit/StdKit/String.cc @@ -13,241 +13,187 @@ * @brief C++ String Manip API. * @version 0.2 * @date 2024-01-23 - * + * * @copyright Copyright (c) 2024 Mahrouss Logic - * + * */ #include "String.hpp" + #include <utility> -namespace CompilerKit -{ - CharType* StringView::Data() - { - return m_Data; - } +namespace CompilerKit { +CharType *StringView::Data() { return m_Data; } - const CharType* StringView::CData() const - { - return m_Data; - } +const CharType *StringView::CData() const { return m_Data; } - SizeType StringView::Length() const - { - return strlen(m_Data); - } +SizeType StringView::Length() const { return strlen(m_Data); } - bool StringView::operator==(const StringView &rhs) const - { - if (rhs.Length() != Length()) - return false; +bool StringView::operator==(const StringView &rhs) const { + if (rhs.Length() != Length()) return false; - for (SizeType index = 0; index < Length(); ++index) - { - if (rhs.m_Data[index] != m_Data[index]) - return false; - } + for (SizeType index = 0; index < Length(); ++index) { + if (rhs.m_Data[index] != m_Data[index]) return false; + } - return true; - } + return true; +} - bool StringView::operator==(const CharType *rhs) const - { - if (string_length(rhs) != Length()) - return false; +bool StringView::operator==(const CharType *rhs) const { + if (string_length(rhs) != Length()) return false; - for (SizeType index = 0; index < string_length(rhs); ++index) - { - if (rhs[index] != m_Data[index]) - return false; - } + for (SizeType index = 0; index < string_length(rhs); ++index) { + if (rhs[index] != m_Data[index]) return false; + } - return true; - } + return true; +} - bool StringView::operator!=(const StringView &rhs) const - { - if (rhs.Length() != Length()) - return false; +bool StringView::operator!=(const StringView &rhs) const { + if (rhs.Length() != Length()) return false; - for (SizeType index = 0; index < rhs.Length(); ++index) - { - if (rhs.m_Data[index] == m_Data[index]) - return false; - } + for (SizeType index = 0; index < rhs.Length(); ++index) { + if (rhs.m_Data[index] == m_Data[index]) return false; + } - return true; - } + return true; +} - bool StringView::operator!=(const CharType *rhs) const - { - if (string_length(rhs) != Length()) - return false; +bool StringView::operator!=(const CharType *rhs) const { + if (string_length(rhs) != Length()) return false; - for (SizeType index = 0; index < string_length(rhs); ++index) - { - if (rhs[index] == m_Data[index]) - return false; - } + for (SizeType index = 0; index < string_length(rhs); ++index) { + if (rhs[index] == m_Data[index]) return false; + } - return true; - } - - StringView StringBuilder::Construct(const CharType *data) - { - if (!data || - *data == 0) - return StringView(0); + return true; +} - StringView view(strlen(data)); - view += data; - - return view; - } +StringView StringBuilder::Construct(const CharType *data) { + if (!data || *data == 0) return StringView(0); - const char* StringBuilder::FromInt(const char *fmt, int i) - { - if (!fmt) - return ("-1"); + StringView view(strlen(data)); + view += data; - char *ret = new char[8 + string_length(fmt)]; + return view; +} - if (!ret) - return ("-1"); +const char *StringBuilder::FromInt(const char *fmt, int i) { + if (!fmt) return ("-1"); - CharType result[8]; - if (!to_str(result, sizeof(int), i)) - { - delete[] ret; - return ("-1"); - } + char *ret = new char[8 + string_length(fmt)]; - const auto fmt_len = string_length(fmt); - const auto res_len = string_length(result); + if (!ret) return ("-1"); - for (SizeType idx = 0; idx < fmt_len; ++idx) - { - if (fmt[idx] == '%') { - SizeType result_cnt = idx; + CharType result[8]; + if (!to_str(result, sizeof(int), i)) { + delete[] ret; + return ("-1"); + } - for (auto y_idx = idx; y_idx < res_len; ++y_idx) { - ret[result_cnt] = result[y_idx]; - ++result_cnt; - } + const auto fmt_len = string_length(fmt); + const auto res_len = string_length(result); - break; - } + for (SizeType idx = 0; idx < fmt_len; ++idx) { + if (fmt[idx] == '%') { + SizeType result_cnt = idx; - ret[idx] = fmt[idx]; - } + for (auto y_idx = idx; y_idx < res_len; ++y_idx) { + ret[result_cnt] = result[y_idx]; + ++result_cnt; + } - return ret; /* Copy that ret into a buffer, Alloca allocates to the stack */ + break; } - const char* StringBuilder::FromBool(const char *fmt, bool i) - { - if (!fmt) - return ("?"); + ret[idx] = fmt[idx]; + } - const char *boolean_expr = i ? "true" : "false"; - char *ret = new char[i ? 4 : 5 + string_length(fmt)]; + return ret; /* Copy that ret into a buffer, Alloca allocates to the stack */ +} - if (!ret) - return ("?"); +const char *StringBuilder::FromBool(const char *fmt, bool i) { + if (!fmt) return ("?"); - const auto fmt_len = string_length(fmt); - const auto res_len = string_length(boolean_expr); + const char *boolean_expr = i ? "true" : "false"; + char *ret = new char[i ? 4 : 5 + string_length(fmt)]; - for (SizeType idx = 0; idx < fmt_len; ++idx) - { - if (fmt[idx] == '%') - { - SizeType result_cnt = idx; + if (!ret) return ("?"); - for (auto y_idx = idx; y_idx < res_len; ++y_idx) - { - ret[result_cnt] = boolean_expr[y_idx]; - ++result_cnt; - } + const auto fmt_len = string_length(fmt); + const auto res_len = string_length(boolean_expr); - break; - } + for (SizeType idx = 0; idx < fmt_len; ++idx) { + if (fmt[idx] == '%') { + SizeType result_cnt = idx; - ret[idx] = fmt[idx]; - } + for (auto y_idx = idx; y_idx < res_len; ++y_idx) { + ret[result_cnt] = boolean_expr[y_idx]; + ++result_cnt; + } - return ret; + break; } - bool StringBuilder::Equals(const char *lhs, const char *rhs) - { - if (string_length(rhs) != string_length(lhs)) - return false; + ret[idx] = fmt[idx]; + } - for (SizeType index = 0; index < string_length(rhs); ++index) - { - if (rhs[index] != lhs[index]) - return false; - } + return ret; +} - return true; - } +bool StringBuilder::Equals(const char *lhs, const char *rhs) { + if (string_length(rhs) != string_length(lhs)) return false; - const char *StringBuilder::Format(const char *fmt, const char *fmt2) - { - if (!fmt || !fmt2) - return ("?"); + for (SizeType index = 0; index < string_length(rhs); ++index) { + if (rhs[index] != lhs[index]) return false; + } - char *ret = new char[string_length(fmt2) + string_length(fmt2)]; - if (!ret) - return ("?"); + return true; +} - for (SizeType idx = 0; idx < string_length(fmt); ++idx) - { - if (fmt[idx] == '%') - { - SizeType result_cnt = idx; +const char *StringBuilder::Format(const char *fmt, const char *fmt2) { + if (!fmt || !fmt2) return ("?"); - for (SizeType y_idx = 0; y_idx < string_length(fmt2); ++y_idx) - { - ret[result_cnt] = fmt2[y_idx]; - ++result_cnt; - } + char *ret = new char[string_length(fmt2) + string_length(fmt2)]; + if (!ret) return ("?"); - break; - } + for (SizeType idx = 0; idx < string_length(fmt); ++idx) { + if (fmt[idx] == '%') { + SizeType result_cnt = idx; - ret[idx] = fmt[idx]; - } + for (SizeType y_idx = 0; y_idx < string_length(fmt2); ++y_idx) { + ret[result_cnt] = fmt2[y_idx]; + ++result_cnt; + } - return ret; + break; } - StringView &StringView::operator+=(const CharType *rhs) - { - if (strlen(rhs) > this->m_Sz) - { - throw std::runtime_error("out_of_bounds: StringView"); - } + ret[idx] = fmt[idx]; + } + return ret; +} - memcpy(this->m_Data + this->m_Cur, rhs, strlen(rhs)); - this->m_Cur += strlen(rhs); +StringView &StringView::operator+=(const CharType *rhs) { + if (strlen(rhs) > this->m_Sz) { + throw std::runtime_error("out_of_bounds: StringView"); + } - return *this; - } + memcpy(this->m_Data + this->m_Cur, rhs, strlen(rhs)); + this->m_Cur += strlen(rhs); - StringView &StringView::operator+=(const StringView &rhs) - { - if (rhs.m_Cur > this->m_Sz) - { - throw std::runtime_error("out_of_bounds: StringView"); - } + return *this; +} - memcpy(this->m_Data + this->m_Cur, rhs.CData(), strlen(rhs.CData())); - this->m_Cur += strlen(rhs.CData()); +StringView &StringView::operator+=(const StringView &rhs) { + if (rhs.m_Cur > this->m_Sz) { + throw std::runtime_error("out_of_bounds: StringView"); + } - return *this; - } -} // namespace CompilerKit + memcpy(this->m_Data + this->m_Cur, rhs.CData(), strlen(rhs.CData())); + this->m_Cur += strlen(rhs.CData()); + + return *this; +} +} // namespace CompilerKit diff --git a/Private/CompilerKit/StdKit/String.hpp b/Private/CompilerKit/StdKit/String.hpp index eada24d..1e4b34c 100644 --- a/Private/CompilerKit/StdKit/String.hpp +++ b/Private/CompilerKit/StdKit/String.hpp @@ -12,81 +12,66 @@ #include <CompilerKit/Defines.hpp> #include <CompilerKit/StdKit/ErrorOr.hpp> -namespace CompilerKit -{ - /** - * @brief StringView class, contains a C string and manages it. - * @note No need to manage it it's getting deleted by default. - */ - - class StringView final - { - public: - explicit StringView() = delete; - - explicit StringView(SizeType Sz) noexcept - : m_Sz(Sz) - { - m_Data = new char[Sz]; - assert(m_Data); - } - - ~StringView() noexcept - { - if (m_Data) - { - memset(m_Data, 0, m_Sz); - delete[] m_Data; - - m_Data = nullptr; - } - } - - CXXKIT_COPY_DEFAULT(StringView); - - CharType *Data(); - const CharType *CData() const; - SizeType Length() const; - - bool operator==(const CharType *rhs) const; - bool operator!=(const CharType *rhs) const; - - bool operator==(const StringView &rhs) const; - bool operator!=(const StringView &rhs) const; - - StringView &operator+=(const CharType *rhs); - StringView &operator+=(const StringView &rhs); - - operator bool() - { - return m_Data && m_Data[0] != 0; - } - - bool operator!() - { - return !m_Data || m_Data[0] == 0; - } - - private: - char* m_Data{ nullptr }; - SizeType m_Sz{ 0 }; - SizeType m_Cur{ 0 }; - - friend class StringBuilder; - - }; - - /** - * @brief StringBuilder class - * @note These results shall call delete[] after they're used. - */ - struct StringBuilder final - { - static StringView Construct(const CharType *data); - static const char* FromInt(const char *fmt, int n); - static const char* FromBool(const char *fmt, bool n); - static const char* Format(const char *fmt, const char* from); - static bool Equals(const char *lhs, const char *rhs); - - }; -} // namespace CompilerKit +namespace CompilerKit { +/** + * @brief StringView class, contains a C string and manages it. + * @note No need to manage it it's getting deleted by default. + */ + +class StringView final { + public: + explicit StringView() = delete; + + explicit StringView(SizeType Sz) noexcept : m_Sz(Sz) { + m_Data = new char[Sz]; + assert(m_Data); + } + + ~StringView() noexcept { + if (m_Data) { + memset(m_Data, 0, m_Sz); + delete[] m_Data; + + m_Data = nullptr; + } + } + + CXXKIT_COPY_DEFAULT(StringView); + + CharType *Data(); + const CharType *CData() const; + SizeType Length() const; + + bool operator==(const CharType *rhs) const; + bool operator!=(const CharType *rhs) const; + + bool operator==(const StringView &rhs) const; + bool operator!=(const StringView &rhs) const; + + StringView &operator+=(const CharType *rhs); + StringView &operator+=(const StringView &rhs); + + operator bool() { return m_Data && m_Data[0] != 0; } + + bool operator!() { return !m_Data || m_Data[0] == 0; } + + private: + char *m_Data{nullptr}; + SizeType m_Sz{0}; + SizeType m_Cur{0}; + + friend class StringBuilder; +}; + +/** + * @brief StringBuilder class + * @note These results shall call delete[] after they're used. + */ +struct StringBuilder final { + static StringView Construct(const CharType *data); + static const char *FromInt(const char *fmt, int n); + static const char *FromBool(const char *fmt, bool n); + static const char *Format(const char *fmt, const char *from); + static bool Equals(const char *lhs, const char *rhs); +}; +} // namespace CompilerKit diff --git a/Private/Frontend/Compiler/compiler_command.d b/Private/Frontend/Compiler/compiler_command.d index 80d8673..7da7ff3 100644 --- a/Private/Frontend/Compiler/compiler_command.d +++ b/Private/Frontend/Compiler/compiler_command.d @@ -20,7 +20,7 @@ public void mpcc_summon_executable(string path) { import core.stdc.stdlib; import std.string; - + system(toStringz(path)); } @@ -32,7 +32,7 @@ public class Platform import std.string; import std.conv; import std.path; - + string pathHome = expandTilde("~"); pathHome ~= "/mp-ux/libc/"; @@ -45,7 +45,7 @@ public class Platform import std.string; import std.conv; import std.path; - + string pathHome = expandTilde("~"); pathHome ~= "/mp-ux/mp-ux/"; @@ -59,7 +59,7 @@ public class CompileCommand { import std.string; import std.algorithm; - + foreach (file; files) { if (file.length == 0) @@ -68,7 +68,7 @@ public class CompileCommand import std.datetime; string input = "/usr/local/bin/bin/cpp"; - + string[] arr_macros = CompilerMacroHelpers.getStandardMacros(); foreach (string macro_name; arr_macros) @@ -149,4 +149,4 @@ public class CompileCommand mpcc_summon_executable("/usr/local/bin/bin/ld " ~ obj ~ output_object); } -}
\ No newline at end of file +} diff --git a/Private/Frontend/Compiler/compiler_macro_helpers.d b/Private/Frontend/Compiler/compiler_macro_helpers.d index 4dfe65e..f567cb1 100644 --- a/Private/Frontend/Compiler/compiler_macro_helpers.d +++ b/Private/Frontend/Compiler/compiler_macro_helpers.d @@ -7,4 +7,4 @@ class CompilerMacroHelpers string[] macros = [ "__64x0__", "__mpux__" ]; return macros; } -}
\ No newline at end of file +} diff --git a/Private/Frontend/Compiler/compiler_start.d b/Private/Frontend/Compiler/compiler_start.d index 44e17da..4b5c1cd 100644 --- a/Private/Frontend/Compiler/compiler_start.d +++ b/Private/Frontend/Compiler/compiler_start.d @@ -31,7 +31,7 @@ void mpcc_summon_manual(string path) core.stdc.stdlib.system(toStringz(base ~ path ~ extension)); } -void main(string[] args) +void main(string[] args) { import std.range, std.stdio; @@ -109,4 +109,4 @@ void main(string[] args) compiler.compile(Platform.getKernelPath(), args_list, shared_library, output_file, compile_only); else compiler.compile(Platform.getIncludePath(), args_list, shared_library, output_file, compile_only); -}
\ No newline at end of file +} diff --git a/Private/Toolchain/32asm.cc b/Private/Toolchain/32asm.cc index 6c28868..6114f4a 100644 --- a/Private/Toolchain/32asm.cc +++ b/Private/Toolchain/32asm.cc @@ -15,8 +15,8 @@ // @author Amlal El Mahrouss // @brief 32x0 Assembler. -// REMINDER: when dealing with an undefined symbol use (string size):LinkerFindSymbol:(string) -// so that ld will look for it. +// REMINDER: when dealing with an undefined symbol use (string +// size):LinkerFindSymbol:(string) so that ld will look for it. ///////////////////////////////////////////////////////////////////////////////////////// @@ -24,11 +24,11 @@ #include <CompilerKit/AsmKit/Arch/32x0.hpp> #include <CompilerKit/ParserKit.hpp> -#include <CompilerKit/StdKit/PEF.hpp> #include <CompilerKit/StdKit/AE.hpp> +#include <CompilerKit/StdKit/PEF.hpp> #include <filesystem> -#include <iostream> #include <fstream> +#include <iostream> ///////////////////// @@ -47,9 +47,4 @@ ///////////////////////////////////////////////////////////////////////////////////////// -MPCC_MODULE(MPUXAssembler32000) -{ - - - return 0; -}
\ No newline at end of file +MPCC_MODULE(MPUXAssembler32000) { return 0; } diff --git a/Private/Toolchain/64asm.cc b/Private/Toolchain/64asm.cc index 2764bf0..c91eb74 100644 --- a/Private/Toolchain/64asm.cc +++ b/Private/Toolchain/64asm.cc @@ -15,8 +15,8 @@ // @author Amlal El Mahrouss // @brief 64x0 Assembler. -// REMINDER: when dealing with an undefined symbol use (string size):LinkerFindSymbol:(string) -// so that ld will look for it. +// REMINDER: when dealing with an undefined symbol use (string +// size):LinkerFindSymbol:(string) so that ld will look for it. ///////////////////////////////////////////////////////////////////////////////////////// @@ -24,11 +24,11 @@ #include <CompilerKit/AsmKit/Arch/64x0.hpp> #include <CompilerKit/ParserKit.hpp> -#include <CompilerKit/StdKit/PEF.hpp> #include <CompilerKit/StdKit/AE.hpp> +#include <CompilerKit/StdKit/PEF.hpp> #include <filesystem> -#include <iostream> #include <fstream> +#include <iostream> ///////////////////// @@ -59,12 +59,8 @@ static bool kVerbose = false; static std::vector<e64k_num_t> kBytes; -static CompilerKit::AERecordHeader kCurrentRecord { - .fName = "", - .fKind = CompilerKit::kPefCode, - .fSize = 0, - .fOffset = 0 - }; +static CompilerKit::AERecordHeader kCurrentRecord{ + .fName = "", .fKind = CompilerKit::kPefCode, .fSize = 0, .fOffset = 0}; static std::vector<CompilerKit::AERecordHeader> kRecords; static std::vector<std::string> kUndefinedSymbols; @@ -75,35 +71,31 @@ static const std::string kRelocSymbol = ":mld:"; // \brief forward decl. static bool asm_read_attributes(std::string &line); -namespace detail -{ - void print_error(std::string reason, const std::string &file) noexcept - { - if (reason[0] == '\n') - reason.erase(0, 1); +namespace detail { +void print_error(std::string reason, const std::string &file) noexcept { + if (reason[0] == '\n') reason.erase(0, 1); - kStdErr << kRed << "[ 64asm ] " << kWhite << ((file == "64asm") ? "internal assembler error " : ("in file, " + file)) << kBlank << std::endl; - kStdErr << kRed << "[ 64asm ] " << kWhite << reason << kBlank << std::endl; + kStdErr << kRed << "[ 64asm ] " << kWhite + << ((file == "64asm") ? "internal assembler error " + : ("in file, " + file)) + << kBlank << std::endl; + kStdErr << kRed << "[ 64asm ] " << kWhite << reason << kBlank << std::endl; - if (kAcceptableErrors > kErrorLimit) - std::exit(3); + if (kAcceptableErrors > kErrorLimit) std::exit(3); - ++kAcceptableErrors; - } + ++kAcceptableErrors; +} - void print_warning(std::string reason, const std::string &file) noexcept - { - if (reason[0] == '\n') - reason.erase(0, 1); +void print_warning(std::string reason, const std::string &file) noexcept { + if (reason[0] == '\n') reason.erase(0, 1); - if (!file.empty()) - { - kStdOut << kYellow << "[ file ] " << kWhite << file << kBlank << std::endl; - } + if (!file.empty()) { + kStdOut << kYellow << "[ file ] " << kWhite << file << kBlank << std::endl; + } - kStdOut << kYellow << "[ 64asm ] " << kWhite << reason << kBlank << std::endl; - } + kStdOut << kYellow << "[ 64asm ] " << kWhite << reason << kBlank << std::endl; } +} // namespace detail ///////////////////////////////////////////////////////////////////////////////////////// @@ -111,225 +103,192 @@ namespace detail ///////////////////////////////////////////////////////////////////////////////////////// -MPCC_MODULE(MPUXAssembler64000) -{ - for (size_t i = 1; i < argc; ++i) - { - if (argv[i][0] == '-') - { - if (strcmp(argv[i], "-version") == 0 || - strcmp(argv[i], "-v") == 0) - { - kStdOut << "64asm: 64x0 Assembler.\n64asm: v1.10\n64asm: Copyright (c) 2024 Mahrouss Logic.\n"; - return 0; - } - else if (strcmp(argv[i], "-h") == 0) - { - kStdOut << "64asm: 64x0 Assembler.\n64asm: Copyright (c) 2024 Mahrouss Logic.\n"; - kStdOut << "-version: Print program version.\n"; - kStdOut << "-verbose: Print verbose output.\n"; - kStdOut << "-binary: Output as flat binary.\n"; - kStdOut << "-64xxx: Compile for a subset of the X64000.\n"; - - return 0; - } - else if (strcmp(argv[i], "-binary") == 0) - { - kOutputAsBinary = true; - continue; - } - else if (strcmp(argv[i], "-verbose") == 0) - { - kVerbose = true; - continue; - } - - kStdOut << "64asm: ignore " << argv[i] << "\n"; - continue; - } +MPCC_MODULE(MPUXAssembler64000) { + for (size_t i = 1; i < argc; ++i) { + if (argv[i][0] == '-') { + if (strcmp(argv[i], "-version") == 0 || strcmp(argv[i], "-v") == 0) { + kStdOut << "64asm: 64x0 Assembler.\n64asm: v1.10\n64asm: Copyright (c) " + "2024 Mahrouss Logic.\n"; + return 0; + } else if (strcmp(argv[i], "-h") == 0) { + kStdOut << "64asm: 64x0 Assembler.\n64asm: Copyright (c) 2024 Mahrouss " + "Logic.\n"; + kStdOut << "-version: Print program version.\n"; + kStdOut << "-verbose: Print verbose output.\n"; + kStdOut << "-binary: Output as flat binary.\n"; + kStdOut << "-64xxx: Compile for a subset of the X64000.\n"; - if (!std::filesystem::exists(argv[i])) - { - kStdOut << "64asm: can't open: " << argv[i] << std::endl; - goto asm_fail_exit; - } + return 0; + } else if (strcmp(argv[i], "-binary") == 0) { + kOutputAsBinary = true; + continue; + } else if (strcmp(argv[i], "-verbose") == 0) { + kVerbose = true; + continue; + } + + kStdOut << "64asm: ignore " << argv[i] << "\n"; + continue; + } - std::string object_output(argv[i]); + if (!std::filesystem::exists(argv[i])) { + kStdOut << "64asm: can't open: " << argv[i] << std::endl; + goto asm_fail_exit; + } - for (auto &ext : kAsmFileExts) - { - if (object_output.find(ext) != std::string::npos) - { - object_output.erase(object_output.find(ext), std::strlen(ext)); - } - } + std::string object_output(argv[i]); - object_output += kObjectFileExt; + for (auto &ext : kAsmFileExts) { + if (object_output.find(ext) != std::string::npos) { + object_output.erase(object_output.find(ext), std::strlen(ext)); + } + } - std::ifstream file_ptr(argv[i]); - std::ofstream file_ptr_out(object_output, - std::ofstream::binary); + object_output += kObjectFileExt; - if (file_ptr_out.bad()) - { - if (kVerbose) - { - kStdOut << "64asm: error: " << strerror(errno) << "\n"; - } - } + std::ifstream file_ptr(argv[i]); + std::ofstream file_ptr_out(object_output, std::ofstream::binary); - std::string line; + if (file_ptr_out.bad()) { + if (kVerbose) { + kStdOut << "64asm: error: " << strerror(errno) << "\n"; + } + } - CompilerKit::AEHeader hdr{0}; + std::string line; - memset(hdr.fPad, kAEInvalidOpcode, kAEPad); + CompilerKit::AEHeader hdr{0}; - hdr.fMagic[0] = kAEMag0; - hdr.fMagic[1] = kAEMag1; - hdr.fSize = sizeof(CompilerKit::AEHeader); - hdr.fArch = kOutputArch; + memset(hdr.fPad, kAEInvalidOpcode, kAEPad); - ///////////////////////////////////////////////////////////////////////////////////////// + hdr.fMagic[0] = kAEMag0; + hdr.fMagic[1] = kAEMag1; + hdr.fSize = sizeof(CompilerKit::AEHeader); + hdr.fArch = kOutputArch; - // COMPILATION LOOP + ///////////////////////////////////////////////////////////////////////////////////////// - ///////////////////////////////////////////////////////////////////////////////////////// + // COMPILATION LOOP - CompilerKit::PlatformAssembler64x0 asm64; + ///////////////////////////////////////////////////////////////////////////////////////// - while (std::getline(file_ptr, line)) - { - if (auto ln = asm64.CheckLine(line, argv[i]); - !ln.empty()) - { - detail::print_error(ln, argv[i]); - continue; - } + CompilerKit::PlatformAssembler64x0 asm64; - try - { - asm_read_attributes(line); - asm64.WriteLine(line, argv[i]); - } - catch (const std::exception &e) - { - if (kVerbose) - { - std::string what = e.what(); - detail::print_warning("exit because of: " + what, "64asm"); - } + while (std::getline(file_ptr, line)) { + if (auto ln = asm64.CheckLine(line, argv[i]); !ln.empty()) { + detail::print_error(ln, argv[i]); + continue; + } - std::filesystem::remove(object_output); - goto asm_fail_exit; - } + try { + asm_read_attributes(line); + asm64.WriteLine(line, argv[i]); + } catch (const std::exception &e) { + if (kVerbose) { + std::string what = e.what(); + detail::print_warning("exit because of: " + what, "64asm"); } - if (!kOutputAsBinary) - { - if (kVerbose) - { - kStdOut << "64asm: Writing object file...\n"; - } + std::filesystem::remove(object_output); + goto asm_fail_exit; + } + } - // this is the final step, write everything to the file. + if (!kOutputAsBinary) { + if (kVerbose) { + kStdOut << "64asm: Writing object file...\n"; + } - auto pos = file_ptr_out.tellp(); + // this is the final step, write everything to the file. - hdr.fCount = kRecords.size() + kUndefinedSymbols.size(); + auto pos = file_ptr_out.tellp(); - file_ptr_out << hdr; + hdr.fCount = kRecords.size() + kUndefinedSymbols.size(); - if (kRecords.empty()) - { - kStdErr << "64asm: At least one record is needed to write an object file.\n64asm: Make one using `export .text foo_bar`.\n"; + file_ptr_out << hdr; - std::filesystem::remove(object_output); - return -1; - } + if (kRecords.empty()) { + kStdErr << "64asm: At least one record is needed to write an object " + "file.\n64asm: Make one using `export .text foo_bar`.\n"; - kRecords[kRecords.size() - 1].fSize = kBytes.size(); + std::filesystem::remove(object_output); + return -1; + } - std::size_t record_count = 0UL; + kRecords[kRecords.size() - 1].fSize = kBytes.size(); - for (auto &rec : kRecords) - { - if (kVerbose) - kStdOut << "64asm: Wrote record " << rec.fName << " to file...\n"; + std::size_t record_count = 0UL; - rec.fFlags |= CompilerKit::kKindRelocationAtRuntime; - rec.fOffset = record_count; - ++record_count; + for (auto &rec : kRecords) { + if (kVerbose) + kStdOut << "64asm: Wrote record " << rec.fName << " to file...\n"; - file_ptr_out << rec; - } + rec.fFlags |= CompilerKit::kKindRelocationAtRuntime; + rec.fOffset = record_count; + ++record_count; - // increment once again, so that we won't lie about the kUndefinedSymbols. - ++record_count; + file_ptr_out << rec; + } - for (auto &sym : kUndefinedSymbols) - { - CompilerKit::AERecordHeader _record_hdr{0}; + // increment once again, so that we won't lie about the kUndefinedSymbols. + ++record_count; - if (kVerbose) - kStdOut << "64asm: Wrote symbol " << sym << " to file...\n"; + for (auto &sym : kUndefinedSymbols) { + CompilerKit::AERecordHeader _record_hdr{0}; - _record_hdr.fKind = kAEInvalidOpcode; - _record_hdr.fSize = sym.size(); - _record_hdr.fOffset = record_count; + if (kVerbose) + kStdOut << "64asm: Wrote symbol " << sym << " to file...\n"; - ++record_count; + _record_hdr.fKind = kAEInvalidOpcode; + _record_hdr.fSize = sym.size(); + _record_hdr.fOffset = record_count; - memset(_record_hdr.fPad, kAEInvalidOpcode, kAEPad); - memcpy(_record_hdr.fName, sym.c_str(), sym.size()); + ++record_count; - file_ptr_out << _record_hdr; + memset(_record_hdr.fPad, kAEInvalidOpcode, kAEPad); + memcpy(_record_hdr.fName, sym.c_str(), sym.size()); - ++kCounter; - } + file_ptr_out << _record_hdr; - auto pos_end = file_ptr_out.tellp(); + ++kCounter; + } - file_ptr_out.seekp(pos); + auto pos_end = file_ptr_out.tellp(); - hdr.fStartCode = pos_end; - hdr.fCodeSize = kBytes.size(); + file_ptr_out.seekp(pos); - file_ptr_out << hdr; + hdr.fStartCode = pos_end; + hdr.fCodeSize = kBytes.size(); - file_ptr_out.seekp(pos_end); - } - else - { - if (kVerbose) - { - kStdOut << "64asm: Write raw binary...\n"; - } - } + file_ptr_out << hdr; - // byte from byte, we write this. - for (auto& byte : kBytes) - { - file_ptr_out.write(reinterpret_cast<const char*>(&byte), sizeof(byte)); - } + file_ptr_out.seekp(pos_end); + } else { + if (kVerbose) { + kStdOut << "64asm: Write raw binary...\n"; + } + } - if (kVerbose) - kStdOut << "64asm: Wrote file with program in it.\n"; + // byte from byte, we write this. + for (auto &byte : kBytes) { + file_ptr_out.write(reinterpret_cast<const char *>(&byte), sizeof(byte)); + } - file_ptr_out.flush(); - file_ptr_out.close(); + if (kVerbose) kStdOut << "64asm: Wrote file with program in it.\n"; - if (kVerbose) - kStdOut << "64asm: Exit succeeded.\n"; + file_ptr_out.flush(); + file_ptr_out.close(); - return 0; - } + if (kVerbose) kStdOut << "64asm: Exit succeeded.\n"; + + return 0; + } asm_fail_exit: - if (kVerbose) - kStdOut << "64asm: Exit failed.\n"; + if (kVerbose) kStdOut << "64asm: Exit failed.\n"; - return -1; + return -1; } ///////////////////////////////////////////////////////////////////////////////////////// @@ -339,165 +298,143 @@ asm_fail_exit: ///////////////////////////////////////////////////////////////////////////////////////// -static bool asm_read_attributes(std::string &line) -{ - // import is the opposite of export, it signals to the ld - // that we need this symbol. - if (ParserKit::find_word(line, "import ")) - { - if (kOutputAsBinary) - { - detail::print_error("Invalid import directive in flat binary mode.", "64asm"); - throw std::runtime_error("invalid_import_bin"); - } - - auto name = line.substr(line.find("import ") + strlen("import ")); +static bool asm_read_attributes(std::string &line) { + // import is the opposite of export, it signals to the ld + // that we need this symbol. + if (ParserKit::find_word(line, "import ")) { + if (kOutputAsBinary) { + detail::print_error("Invalid import directive in flat binary mode.", + "64asm"); + throw std::runtime_error("invalid_import_bin"); + } - std::string result = std::to_string(name.size()); - result += kUndefinedSymbol; + auto name = line.substr(line.find("import ") + strlen("import ")); - // mangle this - for (char &j : name) - { - if (j == ' ' || - j == ',') - j = '$'; - } + std::string result = std::to_string(name.size()); + result += kUndefinedSymbol; - result += name; + // mangle this + for (char &j : name) { + if (j == ' ' || j == ',') j = '$'; + } - if (name.find(".text") != std::string::npos) - { - // data is treated as code. - kCurrentRecord.fKind = CompilerKit::kPefCode; - } - else if (name.find(".data") != std::string::npos) - { - // no code will be executed from here. - kCurrentRecord.fKind = CompilerKit::kPefData; - } - else if (name.find(".page_zero") != std::string::npos) - { - // this is a bss section. - kCurrentRecord.fKind = CompilerKit::kPefZero; - } + result += name; + + if (name.find(".text") != std::string::npos) { + // data is treated as code. + kCurrentRecord.fKind = CompilerKit::kPefCode; + } else if (name.find(".data") != std::string::npos) { + // no code will be executed from here. + kCurrentRecord.fKind = CompilerKit::kPefData; + } else if (name.find(".page_zero") != std::string::npos) { + // this is a bss section. + kCurrentRecord.fKind = CompilerKit::kPefZero; + } - // this is a special case for the start stub. - // we want this so that ld can find it. + // this is a special case for the start stub. + // we want this so that ld can find it. - if (name == "__start") - { - kCurrentRecord.fKind = CompilerKit::kPefCode; - } + if (name == "__start") { + kCurrentRecord.fKind = CompilerKit::kPefCode; + } - // now we can tell the code size of the previous kCurrentRecord. + // now we can tell the code size of the previous kCurrentRecord. - if (!kRecords.empty()) - kRecords[kRecords.size() - 1].fSize = kBytes.size(); + if (!kRecords.empty()) kRecords[kRecords.size() - 1].fSize = kBytes.size(); - memset(kCurrentRecord.fName, 0, kAESymbolLen); - memcpy(kCurrentRecord.fName, result.c_str(), result.size()); + memset(kCurrentRecord.fName, 0, kAESymbolLen); + memcpy(kCurrentRecord.fName, result.c_str(), result.size()); - ++kCounter; + ++kCounter; - memset(kCurrentRecord.fPad, kAEInvalidOpcode, kAEPad); + memset(kCurrentRecord.fPad, kAEInvalidOpcode, kAEPad); - kRecords.emplace_back(kCurrentRecord); + kRecords.emplace_back(kCurrentRecord); - return true; + return true; + } + // export is a special keyword used by 64asm to tell the AE output stage to + // mark this section as a header. it currently supports .text, .data., + // page_zero + else if (ParserKit::find_word(line, "export ")) { + if (kOutputAsBinary) { + detail::print_error("Invalid export directive in flat binary mode.", + "64asm"); + throw std::runtime_error("invalid_export_bin"); } - // export is a special keyword used by 64asm to tell the AE output stage to mark this section as a header. - // it currently supports .text, .data., page_zero - else if (ParserKit::find_word(line, "export ")) - { - if (kOutputAsBinary) - { - detail::print_error("Invalid export directive in flat binary mode.", "64asm"); - throw std::runtime_error("invalid_export_bin"); - } - auto name = line.substr(line.find("export ") + strlen("export ")); + auto name = line.substr(line.find("export ") + strlen("export ")); - std::string name_copy = name; + std::string name_copy = name; - for (char &j : name) - { - if (j == ' ') - j = '$'; - } + for (char &j : name) { + if (j == ' ') j = '$'; + } - if (name.find(".text") != std::string::npos) - { - // data is treated as code. + if (name.find(".text") != std::string::npos) { + // data is treated as code. - name_copy.erase(name_copy.find(".text"), strlen(".text")); - kCurrentRecord.fKind = CompilerKit::kPefCode; - } - else if (name.find(".data") != std::string::npos) - { - // no code will be executed from here. + name_copy.erase(name_copy.find(".text"), strlen(".text")); + kCurrentRecord.fKind = CompilerKit::kPefCode; + } else if (name.find(".data") != std::string::npos) { + // no code will be executed from here. - name_copy.erase(name_copy.find(".data"), strlen(".data")); - kCurrentRecord.fKind = CompilerKit::kPefData; - } - else if (name.find(".page_zero") != std::string::npos) - { - // this is a bss section. + name_copy.erase(name_copy.find(".data"), strlen(".data")); + kCurrentRecord.fKind = CompilerKit::kPefData; + } else if (name.find(".page_zero") != std::string::npos) { + // this is a bss section. - name_copy.erase(name_copy.find(".page_zero"), strlen(".page_zero")); - kCurrentRecord.fKind = CompilerKit::kPefZero; - } + name_copy.erase(name_copy.find(".page_zero"), strlen(".page_zero")); + kCurrentRecord.fKind = CompilerKit::kPefZero; + } - // this is a special case for the start stub. - // we want this so that ld can find it. + // this is a special case for the start stub. + // we want this so that ld can find it. - if (name == "__start") - { - kCurrentRecord.fKind = CompilerKit::kPefCode; - } + if (name == "__start") { + kCurrentRecord.fKind = CompilerKit::kPefCode; + } - while (name_copy.find(" ") != std::string::npos) - name_copy.erase(name_copy.find(" "), 1); + while (name_copy.find(" ") != std::string::npos) + name_copy.erase(name_copy.find(" "), 1); - kOriginLabel.push_back(std::make_pair(name_copy, kOrigin)); - ++kOrigin; + kOriginLabel.push_back(std::make_pair(name_copy, kOrigin)); + ++kOrigin; - // now we can tell the code size of the previous kCurrentRecord. + // now we can tell the code size of the previous kCurrentRecord. - if (!kRecords.empty()) - kRecords[kRecords.size() - 1].fSize = kBytes.size(); + if (!kRecords.empty()) kRecords[kRecords.size() - 1].fSize = kBytes.size(); - memset(kCurrentRecord.fName, 0, kAESymbolLen); - memcpy(kCurrentRecord.fName, name.c_str(), name.size()); + memset(kCurrentRecord.fName, 0, kAESymbolLen); + memcpy(kCurrentRecord.fName, name.c_str(), name.size()); - ++kCounter; + ++kCounter; - memset(kCurrentRecord.fPad, kAEInvalidOpcode, kAEPad); + memset(kCurrentRecord.fPad, kAEInvalidOpcode, kAEPad); - kRecords.emplace_back(kCurrentRecord); + kRecords.emplace_back(kCurrentRecord); - return true; - } + return true; + } - return false; + return false; } // \brief algorithms and helpers. -namespace detail::algorithm -{ - // \brief authorize a brief set of characters. - static inline bool is_not_alnum_space(char c) - { - return !(isalpha(c) || isdigit(c) || (c == ' ') || (c == '\t') || (c == ',') || - (c == '(') || (c == ')') || (c == '"') || (c == '\'') || (c == '[') || (c == ']') || (c == '+') || (c == '_') || (c == ':') || (c == '@') || (c == '.')); - } +namespace detail::algorithm { +// \brief authorize a brief set of characters. +static inline bool is_not_alnum_space(char c) { + return !(isalpha(c) || isdigit(c) || (c == ' ') || (c == '\t') || + (c == ',') || (c == '(') || (c == ')') || (c == '"') || + (c == '\'') || (c == '[') || (c == ']') || (c == '+') || + (c == '_') || (c == ':') || (c == '@') || (c == '.')); +} - bool is_valid(const std::string &str) - { - return find_if(str.begin(), str.end(), is_not_alnum_space) == str.end(); - } +bool is_valid(const std::string &str) { + return find_if(str.begin(), str.end(), is_not_alnum_space) == str.end(); } +} // namespace detail::algorithm ///////////////////////////////////////////////////////////////////////////////////////// @@ -505,262 +442,214 @@ namespace detail::algorithm ///////////////////////////////////////////////////////////////////////////////////////// -std::string CompilerKit::PlatformAssembler64x0::CheckLine(std::string &line, const std::string &file) -{ - std::string err_str; - - if (line.empty() || - ParserKit::find_word(line, "import") || - ParserKit::find_word(line, "export") || - ParserKit::find_word(line, "#") || - ParserKit::find_word(line, ";")) - { - if (line.find('#') != std::string::npos) - { - line.erase(line.find('#')); - } - else if (line.find(';') != std::string::npos) - { - line.erase(line.find(';')); - } - else - { - // now check the line for validity - if (!detail::algorithm::is_valid(line)) - { - err_str = "Line contains non alphanumeric characters.\nhere -> "; - err_str += line; - } - } - - return err_str; - } - - if (!detail::algorithm::is_valid(line)) - { +std::string CompilerKit::PlatformAssembler64x0::CheckLine( + std::string &line, const std::string &file) { + std::string err_str; + + if (line.empty() || ParserKit::find_word(line, "import") || + ParserKit::find_word(line, "export") || ParserKit::find_word(line, "#") || + ParserKit::find_word(line, ";")) { + if (line.find('#') != std::string::npos) { + line.erase(line.find('#')); + } else if (line.find(';') != std::string::npos) { + line.erase(line.find(';')); + } else { + // now check the line for validity + if (!detail::algorithm::is_valid(line)) { err_str = "Line contains non alphanumeric characters.\nhere -> "; err_str += line; - - return err_str; + } } - // check for a valid instruction format. + return err_str; + } - if (line.find(',') != std::string::npos) - { - if (line.find(',') + 1 == line.size()) - { - err_str += "\nInstruction lacks right register, here -> "; - err_str += line.substr(line.find(',')); + if (!detail::algorithm::is_valid(line)) { + err_str = "Line contains non alphanumeric characters.\nhere -> "; + err_str += line; - return err_str; - } - else - { - bool nothing_on_right = true; + return err_str; + } - if (line.find(',') + 1 > line.size()) - { - err_str += "\nInstruction not complete, here -> "; - err_str += line; + // check for a valid instruction format. - return err_str; - } + if (line.find(',') != std::string::npos) { + if (line.find(',') + 1 == line.size()) { + err_str += "\nInstruction lacks right register, here -> "; + err_str += line.substr(line.find(',')); - auto substr = line.substr(line.find(',') + 1); + return err_str; + } else { + bool nothing_on_right = true; - for (auto &ch : substr) - { - if (ch != ' ' && - ch != '\t') - { - nothing_on_right = false; - } - } + if (line.find(',') + 1 > line.size()) { + err_str += "\nInstruction not complete, here -> "; + err_str += line; - // this means we found nothing after that ',' . - if (nothing_on_right) - { - err_str += "\nInstruction not complete, here -> "; - err_str += line; + return err_str; + } - return err_str; - } - } - } + auto substr = line.substr(line.find(',') + 1); - // these do take an argument. - std::vector<std::string> operands_inst = {"stw", "ldw", "lda", "sta"}; - - // these don't. - std::vector<std::string> filter_inst = {"jlr", "jrl", "int"}; - - for (auto &opcode64x0 : kOpcodes64x0) - { - if (line.find(opcode64x0.fName) != std::string::npos) - { - if (opcode64x0.fFunct7 == kAsmNoArgs) - return err_str; - - for (auto &op : operands_inst) - { - // if only the instruction was found. - if (line == op) - { - err_str += "\nMalformed "; - err_str += op; - err_str += " instruction, here -> "; - err_str += line; - } - } + for (auto &ch : substr) { + if (ch != ' ' && ch != '\t') { + nothing_on_right = false; + } + } - // if it is like that -> addr1, 0x0 - if (auto it = std::find(filter_inst.begin(), filter_inst.end(), opcode64x0.fName); - it == filter_inst.cend()) - { - if (ParserKit::find_word(line, opcode64x0.fName)) - { - if (!isspace(line[line.find(opcode64x0.fName) + strlen(opcode64x0.fName)])) - { - err_str += "\nMissing space between "; - err_str += opcode64x0.fName; - err_str += " and operands.\nhere -> "; - err_str += line; - } - } - } + // this means we found nothing after that ',' . + if (nothing_on_right) { + err_str += "\nInstruction not complete, here -> "; + err_str += line; - return err_str; - } + return err_str; + } + } + } + + // these do take an argument. + std::vector<std::string> operands_inst = {"stw", "ldw", "lda", "sta"}; + + // these don't. + std::vector<std::string> filter_inst = {"jlr", "jrl", "int"}; + + for (auto &opcode64x0 : kOpcodes64x0) { + if (line.find(opcode64x0.fName) != std::string::npos) { + if (opcode64x0.fFunct7 == kAsmNoArgs) return err_str; + + for (auto &op : operands_inst) { + // if only the instruction was found. + if (line == op) { + err_str += "\nMalformed "; + err_str += op; + err_str += " instruction, here -> "; + err_str += line; + } + } + + // if it is like that -> addr1, 0x0 + if (auto it = std::find(filter_inst.begin(), filter_inst.end(), + opcode64x0.fName); + it == filter_inst.cend()) { + if (ParserKit::find_word(line, opcode64x0.fName)) { + if (!isspace(line[line.find(opcode64x0.fName) + + strlen(opcode64x0.fName)])) { + err_str += "\nMissing space between "; + err_str += opcode64x0.fName; + err_str += " and operands.\nhere -> "; + err_str += line; + } + } + } + + return err_str; } + } - err_str += "Unrecognized instruction and operands: " + line; + err_str += "Unrecognized instruction and operands: " + line; - return err_str; + return err_str; } -bool CompilerKit::PlatformAssembler64x0::WriteNumber(const std::size_t &pos, std::string &jump_label) -{ - if (!isdigit(jump_label[pos])) - return false; - - switch (jump_label[pos + 1]) - { - case 'x': - { - if (auto res = strtoq(jump_label.substr(pos + 2).c_str(), - nullptr, 16); - !res) - { - if (errno != 0) - { - detail::print_error("invalid hex number: " + jump_label, "64asm"); - throw std::runtime_error("invalid_hex"); - } +bool CompilerKit::PlatformAssembler64x0::WriteNumber(const std::size_t &pos, + std::string &jump_label) { + if (!isdigit(jump_label[pos])) return false; + + switch (jump_label[pos + 1]) { + case 'x': { + if (auto res = strtoq(jump_label.substr(pos + 2).c_str(), nullptr, 16); + !res) { + if (errno != 0) { + detail::print_error("invalid hex number: " + jump_label, "64asm"); + throw std::runtime_error("invalid_hex"); } + } - CompilerKit::NumberCast64 num(strtoq(jump_label.substr(pos + 2).c_str(), - nullptr, 16)); + CompilerKit::NumberCast64 num( + strtoq(jump_label.substr(pos + 2).c_str(), nullptr, 16)); - for (char &i : num.number) - { - kBytes.push_back(i); - } + for (char &i : num.number) { + kBytes.push_back(i); + } - if (kVerbose) - { - kStdOut << "64asm: found a base 16 number here: " << jump_label.substr(pos) << "\n"; - } + if (kVerbose) { + kStdOut << "64asm: found a base 16 number here: " + << jump_label.substr(pos) << "\n"; + } - return true; + return true; } - case 'b': - { - if (auto res = strtoq(jump_label.substr(pos + 2).c_str(), - nullptr, 2); - !res) - { - if (errno != 0) - { - detail::print_error("invalid binary number: " + jump_label, "64asm"); - throw std::runtime_error("invalid_bin"); - } + case 'b': { + if (auto res = strtoq(jump_label.substr(pos + 2).c_str(), nullptr, 2); + !res) { + if (errno != 0) { + detail::print_error("invalid binary number: " + jump_label, "64asm"); + throw std::runtime_error("invalid_bin"); } + } - CompilerKit::NumberCast64 num(strtoq(jump_label.substr(pos + 2).c_str(), - nullptr, 2)); + CompilerKit::NumberCast64 num( + strtoq(jump_label.substr(pos + 2).c_str(), nullptr, 2)); - if (kVerbose) - { - kStdOut << "64asm: found a base 2 number here: " << jump_label.substr(pos) << "\n"; - } + if (kVerbose) { + kStdOut << "64asm: found a base 2 number here: " + << jump_label.substr(pos) << "\n"; + } - for (char &i : num.number) - { - kBytes.push_back(i); - } + for (char &i : num.number) { + kBytes.push_back(i); + } - return true; + return true; } - case 'o': - { - if (auto res = strtoq(jump_label.substr(pos + 2).c_str(), - nullptr, 7); - !res) - { - if (errno != 0) - { - detail::print_error("invalid octal number: " + jump_label, "64asm"); - throw std::runtime_error("invalid_octal"); - } + case 'o': { + if (auto res = strtoq(jump_label.substr(pos + 2).c_str(), nullptr, 7); + !res) { + if (errno != 0) { + detail::print_error("invalid octal number: " + jump_label, "64asm"); + throw std::runtime_error("invalid_octal"); } + } - CompilerKit::NumberCast64 num(strtoq(jump_label.substr(pos + 2).c_str(), - nullptr, 7)); + CompilerKit::NumberCast64 num( + strtoq(jump_label.substr(pos + 2).c_str(), nullptr, 7)); - if (kVerbose) - { - kStdOut << "64asm: found a base 8 number here: " << jump_label.substr(pos) << "\n"; - } + if (kVerbose) { + kStdOut << "64asm: found a base 8 number here: " + << jump_label.substr(pos) << "\n"; + } - for (char &i : num.number) - { - kBytes.push_back(i); - } + for (char &i : num.number) { + kBytes.push_back(i); + } - return true; - } - default: - { - break; + return true; } + default: { + break; } + } - /* check for errno and stuff like that */ - if (auto res = strtoq(jump_label.substr(pos).c_str(), - nullptr, 10); - !res) - { - if (errno != 0) - { - return false; - } + /* check for errno and stuff like that */ + if (auto res = strtoq(jump_label.substr(pos).c_str(), nullptr, 10); !res) { + if (errno != 0) { + return false; } + } - CompilerKit::NumberCast64 num(strtoq(jump_label.substr(pos).c_str(), - nullptr, 10)); + CompilerKit::NumberCast64 num( + strtoq(jump_label.substr(pos).c_str(), nullptr, 10)); - for (char &i : num.number) - { - kBytes.push_back(i); - } + for (char &i : num.number) { + kBytes.push_back(i); + } - if (kVerbose) - { - kStdOut << "64asm: found a base 10 number here: " << jump_label.substr(pos) << "\n"; - } + if (kVerbose) { + kStdOut << "64asm: found a base 10 number here: " << jump_label.substr(pos) + << "\n"; + } - return true; + return true; } ///////////////////////////////////////////////////////////////////////////////////////// @@ -769,328 +658,284 @@ bool CompilerKit::PlatformAssembler64x0::WriteNumber(const std::size_t &pos, std ///////////////////////////////////////////////////////////////////////////////////////// -bool CompilerKit::PlatformAssembler64x0::WriteLine(std::string &line, const std::string &file) -{ - if (ParserKit::find_word(line, "export ")) - return true; - - for (auto &opcode64x0 : kOpcodes64x0) - { - // strict check here - if (ParserKit::find_word(line, opcode64x0.fName) && - detail::algorithm::is_valid(line)) - { - std::string name(opcode64x0.fName); - std::string jump_label, cpy_jump_label; - - kBytes.emplace_back(opcode64x0.fOpcode); - kBytes.emplace_back(opcode64x0.fFunct3); - kBytes.emplace_back(opcode64x0.fFunct7); - - // check funct7 type. - switch (opcode64x0.fFunct7) - { - // reg to reg means register to register transfer operation. - case kAsmRegToReg: - case kAsmImmediate: - { - // \brief how many registers we found. - std::size_t found_some = 0UL; - - for (size_t line_index = 0UL; line_index < line.size(); line_index++) - { - if (line[line_index] == kAsmRegisterPrefix[0] && - isdigit(line[line_index + 1])) - { - std::string register_syntax = kAsmRegisterPrefix; - register_syntax += line[line_index + 1]; - - if (isdigit(line[line_index + 2])) - register_syntax += line[line_index + 2]; - - std::string reg_str; - reg_str += line[line_index + 1]; - - if (isdigit(line[line_index + 2])) - reg_str += line[line_index + 2]; - - // it ranges from r0 to r19 - // something like r190 doesn't exist in the instruction set. - if (kOutputArch == CompilerKit::kPefArch64000) - { - if (isdigit(line[line_index + 3]) && - isdigit(line[line_index + 2])) - { - reg_str += line[line_index + 3]; - detail::print_error("invalid register index, r" + reg_str + "\nnote: The 64x0 accepts registers from r0 to r20.", file); - throw std::runtime_error("invalid_register_index"); - } - } - - // finally cast to a size_t - std::size_t reg_index = strtoq( - reg_str.c_str(), - nullptr, - 10); - - if (reg_index > kAsmRegisterLimit) - { - detail::print_error("invalid register index, r" + reg_str, file); - throw std::runtime_error("invalid_register_index"); - } - - kBytes.emplace_back(reg_index); - ++found_some; - - if (kVerbose) - { - kStdOut << "64asm: Register found: " << register_syntax << "\n"; - kStdOut << "64asm: Register amount in instruction: " << found_some << "\n"; - } - } +bool CompilerKit::PlatformAssembler64x0::WriteLine(std::string &line, + const std::string &file) { + if (ParserKit::find_word(line, "export ")) return true; + + for (auto &opcode64x0 : kOpcodes64x0) { + // strict check here + if (ParserKit::find_word(line, opcode64x0.fName) && + detail::algorithm::is_valid(line)) { + std::string name(opcode64x0.fName); + std::string jump_label, cpy_jump_label; + + kBytes.emplace_back(opcode64x0.fOpcode); + kBytes.emplace_back(opcode64x0.fFunct3); + kBytes.emplace_back(opcode64x0.fFunct7); + + // check funct7 type. + switch (opcode64x0.fFunct7) { + // reg to reg means register to register transfer operation. + case kAsmRegToReg: + case kAsmImmediate: { + // \brief how many registers we found. + std::size_t found_some = 0UL; + + for (size_t line_index = 0UL; line_index < line.size(); + line_index++) { + if (line[line_index] == kAsmRegisterPrefix[0] && + isdigit(line[line_index + 1])) { + std::string register_syntax = kAsmRegisterPrefix; + register_syntax += line[line_index + 1]; + + if (isdigit(line[line_index + 2])) + register_syntax += line[line_index + 2]; + + std::string reg_str; + reg_str += line[line_index + 1]; + + if (isdigit(line[line_index + 2])) + reg_str += line[line_index + 2]; + + // it ranges from r0 to r19 + // something like r190 doesn't exist in the instruction set. + if (kOutputArch == CompilerKit::kPefArch64000) { + if (isdigit(line[line_index + 3]) && + isdigit(line[line_index + 2])) { + reg_str += line[line_index + 3]; + detail::print_error( + "invalid register index, r" + reg_str + + "\nnote: The 64x0 accepts registers from r0 to r20.", + file); + throw std::runtime_error("invalid_register_index"); } + } - // we're not in immediate addressing, reg to reg. - if (opcode64x0.fFunct7 != kAsmImmediate) - { - // remember! register to register! - if (found_some == 1) - { - detail::print_error("Unrecognized register found.\ntip: each 64asm register starts with 'r'.\nline: " + line, file); - throw std::runtime_error("not_a_register"); - } - } + // finally cast to a size_t + std::size_t reg_index = strtoq(reg_str.c_str(), nullptr, 10); - if (found_some < 1 && - name != "ldw" && - name != "lda" && - name != "stw") - { - detail::print_error("invalid combination of opcode and registers.\nline: " + line, file); - throw std::runtime_error("invalid_comb_op_reg"); - } - else if (found_some == 1 && - name == "add") - { - detail::print_error("invalid combination of opcode and registers.\nline: " + line, file); - throw std::runtime_error("invalid_comb_op_reg"); - } - else if (found_some == 1 && - name == "dec") - { - detail::print_error("invalid combination of opcode and registers.\nline: " + line, file); - throw std::runtime_error("invalid_comb_op_reg"); - } + if (reg_index > kAsmRegisterLimit) { + detail::print_error("invalid register index, r" + reg_str, + file); + throw std::runtime_error("invalid_register_index"); + } - if (found_some > 0 && - name == "pop") - { - detail::print_error("invalid combination for opcode 'pop'.\ntip: it expects nothing.\nline: " + line, file); - throw std::runtime_error("invalid_comb_op_pop"); - } + kBytes.emplace_back(reg_index); + ++found_some; + + if (kVerbose) { + kStdOut << "64asm: Register found: " << register_syntax << "\n"; + kStdOut << "64asm: Register amount in instruction: " + << found_some << "\n"; + } } - default: - break; + } + + // we're not in immediate addressing, reg to reg. + if (opcode64x0.fFunct7 != kAsmImmediate) { + // remember! register to register! + if (found_some == 1) { + detail::print_error( + "Unrecognized register found.\ntip: each 64asm register " + "starts with 'r'.\nline: " + + line, + file); + throw std::runtime_error("not_a_register"); } + } + + if (found_some < 1 && name != "ldw" && name != "lda" && + name != "stw") { + detail::print_error( + "invalid combination of opcode and registers.\nline: " + line, + file); + throw std::runtime_error("invalid_comb_op_reg"); + } else if (found_some == 1 && name == "add") { + detail::print_error( + "invalid combination of opcode and registers.\nline: " + line, + file); + throw std::runtime_error("invalid_comb_op_reg"); + } else if (found_some == 1 && name == "dec") { + detail::print_error( + "invalid combination of opcode and registers.\nline: " + line, + file); + throw std::runtime_error("invalid_comb_op_reg"); + } + + if (found_some > 0 && name == "pop") { + detail::print_error( + "invalid combination for opcode 'pop'.\ntip: it expects " + "nothing.\nline: " + + line, + file); + throw std::runtime_error("invalid_comb_op_pop"); + } + } + default: + break; + } + + // try to fetch a number from the name + if (name == "stw" || name == "ldw" || name == "lda" || name == "sta") { + auto where_string = name; + + // if we load something, we'd need it's symbol/literal + if (name == "stw" || name == "sta" || name == "ldw" || name == "lda" || + name == "sta") + where_string = ","; + + jump_label = line; + + auto found_sym = false; + + while (jump_label.find(where_string) != std::string::npos) { + jump_label = jump_label.substr(jump_label.find(where_string) + + where_string.size()); + + while (jump_label.find(" ") != std::string::npos) { + jump_label.erase(jump_label.find(" "), 1); + } + + if (jump_label[0] != kAsmRegisterPrefix[0] && + !isdigit(jump_label[1])) { + if (found_sym) { + detail::print_error( + "invalid combination of opcode and operands.\nhere -> " + + jump_label, + file); + throw std::runtime_error("invalid_comb_op_ops"); + } else { + // death trap installed. + found_sym = true; + } + } + } - // try to fetch a number from the name - if (name == "stw" || - name == "ldw" || - name == "lda" || - name == "sta") - { - auto where_string = name; - - // if we load something, we'd need it's symbol/literal - if (name == "stw" || - name == "sta" || - name == "ldw" || - name == "lda" || - name == "sta") - where_string = ","; - - jump_label = line; - - auto found_sym = false; - - while (jump_label.find(where_string) != std::string::npos) - { - jump_label = jump_label.substr(jump_label.find(where_string) + where_string.size()); - - while (jump_label.find(" ") != std::string::npos) - { - jump_label.erase(jump_label.find(" "), 1); - } - - if (jump_label[0] != kAsmRegisterPrefix[0] && - !isdigit(jump_label[1])) - { - if (found_sym) - { - detail::print_error("invalid combination of opcode and operands.\nhere -> " + jump_label, file); - throw std::runtime_error("invalid_comb_op_ops"); - } - else - { - // death trap installed. - found_sym = true; - } - } - } + cpy_jump_label = jump_label; - cpy_jump_label = jump_label; + // replace any spaces with $ + if (jump_label[0] == ' ') { + while (jump_label.find(' ') != std::string::npos) { + if (isalnum(jump_label[0]) || isdigit(jump_label[0])) break; - // replace any spaces with $ - if (jump_label[0] == ' ') - { - while (jump_label.find(' ') != std::string::npos) - { - if (isalnum(jump_label[0]) || - isdigit(jump_label[0])) - break; + jump_label.erase(jump_label.find(' '), 1); + } + } - jump_label.erase(jump_label.find(' '), 1); - } - } + if (!this->WriteNumber(0, jump_label)) { + // sta expects this: sta 0x000000, r0 + if (name == "sta") { + detail::print_error( + "invalid combination of opcode and operands.\nhere ->" + line, + file); + throw std::runtime_error("invalid_comb_op_ops"); + } + } else { + if (name == "sta" && + cpy_jump_label.find("import ") != std::string::npos) { + detail::print_error("invalid usage import on 'sta', here: " + line, + file); + throw std::runtime_error("invalid_sta_usage"); + } + } - if (!this->WriteNumber(0, jump_label)) - { - // sta expects this: sta 0x000000, r0 - if (name == "sta") - { - detail::print_error("invalid combination of opcode and operands.\nhere ->" + line, file); - throw std::runtime_error("invalid_comb_op_ops"); - } - } - else - { - if (name == "sta" && - cpy_jump_label.find("import ") != std::string::npos) - { - detail::print_error("invalid usage import on 'sta', here: " + line, file); - throw std::runtime_error("invalid_sta_usage"); - } - } + goto asm_write_label; + } - goto asm_write_label; - } + // This is the case where we jump to a label, it is also used as a goto. + if (name == "lda" || name == "sta") { + asm_write_label: + if (cpy_jump_label.find('\n') != std::string::npos) + cpy_jump_label.erase(cpy_jump_label.find('\n'), 1); - // This is the case where we jump to a label, it is also used as a goto. - if (name == "lda" || - name == "sta") - { - asm_write_label: - if (cpy_jump_label.find('\n') != std::string::npos) - cpy_jump_label.erase(cpy_jump_label.find('\n'), 1); - - if (cpy_jump_label.find("import") != std::string::npos) - { - cpy_jump_label.erase(cpy_jump_label.find("import"), strlen("import")); - - if (name == "sta") - { - detail::print_error("import is not allowed on a sta operation.", file); - throw std::runtime_error("import_sta_op"); - } - else - { - goto asm_end_label_cpy; - } - } + if (cpy_jump_label.find("import") != std::string::npos) { + cpy_jump_label.erase(cpy_jump_label.find("import"), strlen("import")); - if (name == "lda" || - name == "sta") - { - for (auto &label : kOriginLabel) - { - if (cpy_jump_label == label.first) - { - if (kVerbose) - { - kStdOut << "64asm: Replace label " - << cpy_jump_label - << " to address: " - << label.second - << std::endl; - } - - CompilerKit::NumberCast64 num(label.second); - - for (auto &num : num.number) - { - kBytes.push_back(num); - } - - goto asm_end_label_cpy; - } - } - - if (cpy_jump_label[0] == '0') - { - switch (cpy_jump_label[1]) - { - case 'x': - case 'o': - case 'b': - if (this->WriteNumber(0, cpy_jump_label)) - goto asm_end_label_cpy; - - break; - default: - break; - } - - if (isdigit(cpy_jump_label[0])) - { - if (this->WriteNumber(0, cpy_jump_label)) - goto asm_end_label_cpy; - - break; - } - } - } + if (name == "sta") { + detail::print_error("import is not allowed on a sta operation.", + file); + throw std::runtime_error("import_sta_op"); + } else { + goto asm_end_label_cpy; + } + } - if (cpy_jump_label.size() < 1) - { - detail::print_error("label is empty, can't jump on it.", file); - throw std::runtime_error("label_empty"); - } + if (name == "lda" || name == "sta") { + for (auto &label : kOriginLabel) { + if (cpy_jump_label == label.first) { + if (kVerbose) { + kStdOut << "64asm: Replace label " << cpy_jump_label + << " to address: " << label.second << std::endl; + } - auto mld_reloc_str = std::to_string(cpy_jump_label.size()); - mld_reloc_str += kRelocSymbol; - mld_reloc_str += cpy_jump_label; + CompilerKit::NumberCast64 num(label.second); - bool ignore_back_slash = false; + for (auto &num : num.number) { + kBytes.push_back(num); + } - for (auto &reloc_chr : mld_reloc_str) - { - if (reloc_chr == '\\') - { - ignore_back_slash = true; - continue; - } + goto asm_end_label_cpy; + } + } - if (ignore_back_slash) - { - ignore_back_slash = false; - continue; - } + if (cpy_jump_label[0] == '0') { + switch (cpy_jump_label[1]) { + case 'x': + case 'o': + case 'b': + if (this->WriteNumber(0, cpy_jump_label)) + goto asm_end_label_cpy; - kBytes.push_back(reloc_chr); - } + break; + default: + break; + } + + if (isdigit(cpy_jump_label[0])) { + if (this->WriteNumber(0, cpy_jump_label)) goto asm_end_label_cpy; - kBytes.push_back('\0'); - goto asm_end_label_cpy; + break; } + } + } - asm_end_label_cpy: - ++kOrigin; + if (cpy_jump_label.size() < 1) { + detail::print_error("label is empty, can't jump on it.", file); + throw std::runtime_error("label_empty"); + } - break; + auto mld_reloc_str = std::to_string(cpy_jump_label.size()); + mld_reloc_str += kRelocSymbol; + mld_reloc_str += cpy_jump_label; + + bool ignore_back_slash = false; + + for (auto &reloc_chr : mld_reloc_str) { + if (reloc_chr == '\\') { + ignore_back_slash = true; + continue; + } + + if (ignore_back_slash) { + ignore_back_slash = false; + continue; + } + + kBytes.push_back(reloc_chr); } + + kBytes.push_back('\0'); + goto asm_end_label_cpy; + } + + asm_end_label_cpy: + ++kOrigin; + + break; } + } - return true; + return true; } -// Last rev 13-1-24
\ No newline at end of file +// Last rev 13-1-24 diff --git a/Private/Toolchain/bccl.cc b/Private/Toolchain/bccl.cc index 048424b..2a03061 100644 --- a/Private/Toolchain/bccl.cc +++ b/Private/Toolchain/bccl.cc @@ -9,14 +9,15 @@ /// bugs: ? -#include <cstdio> -#include <vector> -#include <string> -#include <fstream> -#include <iostream> #include <uuid/uuid.h> + #include <CompilerKit/AsmKit/Arch/64x0.hpp> #include <CompilerKit/ParserKit.hpp> +#include <cstdio> +#include <fstream> +#include <iostream> +#include <string> +#include <vector> #define kOk 0 @@ -46,87 +47,78 @@ ///////////////////////////////////// -namespace detail -{ - // \brief name to register struct. - struct CompilerRegisterMap final - { - std::string fName; - std::string fReg; - }; - - // \brief Map for BCCL structs - // \author amlel - struct CompilerStructMap final - { - // 'my_foo' - std::string fName; - - // if instance: stores a valid register. - std::string fReg; - - // offset count - std::size_t fOffsetsCnt; - - // offset array. - std::vector<std::pair<Int32, std::string>> fOffsets; - }; - - struct CompilerState final - { - std::vector<ParserKit::SyntaxLeafList> fSyntaxTreeList; - std::vector<CompilerRegisterMap> kStackFrame; - std::vector<CompilerStructMap> kStructMap; - ParserKit::SyntaxLeafList *fSyntaxTree{nullptr}; - std::unique_ptr<std::ofstream> fOutputAssembly; - std::string fLastFile; - std::string fLastError; - bool kVerbose; - }; -} +namespace detail { +// \brief name to register struct. +struct CompilerRegisterMap final { + std::string fName; + std::string fReg; +}; + +// \brief Map for BCCL structs +// \author amlel +struct CompilerStructMap final { + // 'my_foo' + std::string fName; + + // if instance: stores a valid register. + std::string fReg; + + // offset count + std::size_t fOffsetsCnt; + + // offset array. + std::vector<std::pair<Int32, std::string>> fOffsets; +}; + +struct CompilerState final { + std::vector<ParserKit::SyntaxLeafList> fSyntaxTreeList; + std::vector<CompilerRegisterMap> kStackFrame; + std::vector<CompilerStructMap> kStructMap; + ParserKit::SyntaxLeafList *fSyntaxTree{nullptr}; + std::unique_ptr<std::ofstream> fOutputAssembly; + std::string fLastFile; + std::string fLastError; + bool kVerbose; +}; +} // namespace detail static detail::CompilerState kState; static SizeType kErrorLimit = 100; static Int32 kAcceptableErrors = 0; -namespace detail -{ - void print_error(std::string reason, std::string file) noexcept - { - if (reason[0] == '\n') - reason.erase(0, 1); +namespace detail { +void print_error(std::string reason, std::string file) noexcept { + if (reason[0] == '\n') reason.erase(0, 1); - if (file.find(".pp") != std::string::npos) - { - file.erase(file.find(".pp"), 3); - } + if (file.find(".pp") != std::string::npos) { + file.erase(file.find(".pp"), 3); + } - if (kState.fLastFile != file) - { - std::cout << kRed << "[ bccl ] " << kWhite << ((file == "bccl") ? "internal compiler error " : ("in file, " + file)) << kBlank << std::endl; - std::cout << kRed << "[ bccl ] " << kWhite << reason << kBlank << std::endl; + if (kState.fLastFile != file) { + std::cout << kRed << "[ bccl ] " << kWhite + << ((file == "bccl") ? "internal compiler error " + : ("in file, " + file)) + << kBlank << std::endl; + std::cout << kRed << "[ bccl ] " << kWhite << reason << kBlank << std::endl; - kState.fLastFile = file; - } - else - { - std::cout << kRed << "[ bccl ] [ " << kState.fLastFile << " ] " << kWhite << reason << kBlank << std::endl; - } + kState.fLastFile = file; + } else { + std::cout << kRed << "[ bccl ] [ " << kState.fLastFile << " ] " << kWhite + << reason << kBlank << std::endl; + } - if (kAcceptableErrors > kErrorLimit) - std::exit(3); - - ++kAcceptableErrors; - } + if (kAcceptableErrors > kErrorLimit) std::exit(3); - struct CompilerType final - { - std::string fName; - std::string fValue; - }; + ++kAcceptableErrors; } +struct CompilerType final { + std::string fName; + std::string fValue; +}; +} // namespace detail + ///////////////////////////////////////////////////////////////////////////////////////// // Target architecture. @@ -159,18 +151,17 @@ static bool kInBraces = false; static size_t kBracesCount = 0UL; /* @brief BCCL compiler backend for BCCL */ -class CompilerBackendBccl final : public ParserKit::CompilerBackend -{ -public: - explicit CompilerBackendBccl() = default; - ~CompilerBackendBccl() override = default; +class CompilerBackendBccl final : public ParserKit::CompilerBackend { + public: + explicit CompilerBackendBccl() = default; + ~CompilerBackendBccl() override = default; - CXXKIT_COPY_DEFAULT(CompilerBackendBccl); + CXXKIT_COPY_DEFAULT(CompilerBackendBccl); - std::string Check(const char *text, const char *file); - bool Compile(const std::string &text, const char *file) override; + std::string Check(const char *text, const char *file); + bool Compile(const std::string &text, const char *file) override; - const char *Language() override { return "BCCL 64x0, Generic MP/UX target."; } + const char *Language() override { return "BCCL 64x0, Generic MP/UX target."; } }; static CompilerBackendBccl *kCompilerBackend = nullptr; @@ -178,33 +169,28 @@ static std::vector<detail::CompilerType> kCompilerVariables; static std::vector<std::string> kCompilerFunctions; static std::vector<detail::CompilerType> kCompilerTypes; -namespace detail -{ - union number_cast final - { - public: - number_cast(UInt64 _Raw) : _Raw(_Raw) {} - - public: - char _Num[8]; - UInt64 _Raw; - - }; - - union double_cast final - { - public: - double_cast(float _Raw) : _Raw(_Raw) {} - - public: - char _Sign; - char _Lh[8]; - char _Rh[23]; - - float _Raw; - - }; -} +namespace detail { +union number_cast final { + public: + number_cast(UInt64 _Raw) : _Raw(_Raw) {} + + public: + char _Num[8]; + UInt64 _Raw; +}; + +union double_cast final { + public: + double_cast(float _Raw) : _Raw(_Raw) {} + + public: + char _Sign; + char _Lh[8]; + char _Rh[23]; + + float _Raw; +}; +} // namespace detail ///////////////////////////////////////////////////////////////////////////////////////// @@ -213,1067 +199,852 @@ namespace detail ///////////////////////////////////////////////////////////////////////////////////////// -bool CompilerBackendBccl::Compile(const std::string &text, const char *file) -{ - std::string _text = text; - - auto syntax_tree = ParserKit::SyntaxLeafList::SyntaxLeaf(); - bool type_found = false; - bool function_found = false; - - // start parsing - for (size_t text_index = 0; text_index < _text.size(); ++text_index) - { - uuid_t out{0}; +bool CompilerBackendBccl::Compile(const std::string &text, const char *file) { + std::string _text = text; - uuid_generate_random(out); - detail::number_cast time_off = (UInt64)out; + auto syntax_tree = ParserKit::SyntaxLeafList::SyntaxLeaf(); + bool type_found = false; + bool function_found = false; - if (!type_found) - { - auto substr = _text.substr(text_index); - std::string match_type; + // start parsing + for (size_t text_index = 0; text_index < _text.size(); ++text_index) { + uuid_t out{0}; - for (size_t y = 0; y < substr.size(); ++y) - { - if (substr[y] == ' ') - { - while (match_type.find(' ') != std::string::npos) - { - match_type.erase(match_type.find(' ')); - } + uuid_generate_random(out); + detail::number_cast time_off = (UInt64)out; - for (auto &clType : kCompilerTypes) - { - if (clType.fName == match_type) - { - match_type.clear(); + if (!type_found) { + auto substr = _text.substr(text_index); + std::string match_type; - std::string buf; + for (size_t y = 0; y < substr.size(); ++y) { + if (substr[y] == ' ') { + while (match_type.find(' ') != std::string::npos) { + match_type.erase(match_type.find(' ')); + } - buf += clType.fValue; - buf += ' '; + for (auto &clType : kCompilerTypes) { + if (clType.fName == match_type) { + match_type.clear(); - if (substr.find('=') != std::string::npos) - { - break; - } + std::string buf; - if (_text.find('(') != std::string::npos) - { - syntax_tree.fUserValue = buf; + buf += clType.fValue; + buf += ' '; - kState.fSyntaxTree->fLeafList.push_back(syntax_tree); - } + if (substr.find('=') != std::string::npos) { + break; + } - type_found = true; - break; - } - } + if (_text.find('(') != std::string::npos) { + syntax_tree.fUserValue = buf; - break; - } + kState.fSyntaxTree->fLeafList.push_back(syntax_tree); + } - match_type += substr[y]; + type_found = true; + break; } + } + + break; } - if (_text[text_index] == '{') - { - if (kInStruct) - { - continue; - } + match_type += substr[y]; + } + } - kInBraces = true; - ++kBracesCount; + if (_text[text_index] == '{') { + if (kInStruct) { + continue; + } - kState.fSyntaxTree->fLeafList.push_back(syntax_tree); - } + kInBraces = true; + ++kBracesCount; - // return keyword handler - if (_text[text_index] == 'r') - { - std::string return_keyword; - return_keyword += "return"; + kState.fSyntaxTree->fLeafList.push_back(syntax_tree); + } - std::size_t index = 0UL; + // return keyword handler + if (_text[text_index] == 'r') { + std::string return_keyword; + return_keyword += "return"; - std::string value; + std::size_t index = 0UL; - for (size_t return_index = text_index; return_index < _text.size(); ++return_index) - { - if (_text[return_index] != return_keyword[index]) - { - for (size_t value_index = return_index; value_index < _text.size(); ++value_index) - { - if (_text[value_index] == ';') - break; + std::string value; - value += _text[value_index]; - } + for (size_t return_index = text_index; return_index < _text.size(); + ++return_index) { + if (_text[return_index] != return_keyword[index]) { + for (size_t value_index = return_index; value_index < _text.size(); + ++value_index) { + if (_text[value_index] == ';') break; - break; - } + value += _text[value_index]; + } - ++index; - } + break; + } - if (index == return_keyword.size()) - { - if (!value.empty()) - { - if (value.find('(') != std::string::npos) - { - value.erase(value.find('(')); - } + ++index; + } - if (!isdigit(value[value.find('(') + 2])) - { - std::string tmp = value; - bool reg_to_reg = false; + if (index == return_keyword.size()) { + if (!value.empty()) { + if (value.find('(') != std::string::npos) { + value.erase(value.find('(')); + } - value.clear(); + if (!isdigit(value[value.find('(') + 2])) { + std::string tmp = value; + bool reg_to_reg = false; - value += " import"; - value += tmp; - } + value.clear(); - syntax_tree.fUserValue = "\tldw r1, "; + value += " import"; + value += tmp; + } - // make it pretty. - if (value.find('\t') != std::string::npos) - value.erase(value.find('\t'), 1); + syntax_tree.fUserValue = "\tldw r1, "; - syntax_tree.fUserValue += value + "\n"; - } + // make it pretty. + if (value.find('\t') != std::string::npos) + value.erase(value.find('\t'), 1); - syntax_tree.fUserValue += "\tjlr"; + syntax_tree.fUserValue += value + "\n"; + } - kState.fSyntaxTree->fLeafList.push_back(syntax_tree); + syntax_tree.fUserValue += "\tjlr"; - break; - } - } + kState.fSyntaxTree->fLeafList.push_back(syntax_tree); - // Parse expressions and instructions here. - // what does this mean? - // we encounter an assignment, or we reached the end of an expression. - if (_text[text_index] == '=' || - _text[text_index] == ';') - { - if (function_found) - continue; - - if (_text[text_index] == ';' && - kInStruct) - continue; - - if (_text.find("typedef ") != std::string::npos) - continue; - - if (_text[text_index] == '=' && - kInStruct) - { - detail::print_error("assignement of value in struct " + _text, file); - continue; - } + break; + } + } - if (_text[text_index] == ';' && - kInStruct) - { - bool space_found_ = false; - std::string sym; + // Parse expressions and instructions here. + // what does this mean? + // we encounter an assignment, or we reached the end of an expression. + if (_text[text_index] == '=' || _text[text_index] == ';') { + if (function_found) continue; - for (auto &ch : _text) - { - if (ch == ' ') - { - space_found_ = true; - } + if (_text[text_index] == ';' && kInStruct) continue; - if (ch == ';') - break; + if (_text.find("typedef ") != std::string::npos) continue; - if (space_found_) - sym.push_back(ch); - } + if (_text[text_index] == '=' && kInStruct) { + detail::print_error("assignement of value in struct " + _text, file); + continue; + } - kState.kStructMap[kState.kStructMap.size() - 1].fOffsets.push_back( - std::make_pair(kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt + 4, sym)); + if (_text[text_index] == ';' && kInStruct) { + bool space_found_ = false; + std::string sym; - kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt = kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt + 4; + for (auto &ch : _text) { + if (ch == ' ') { + space_found_ = true; + } - continue; - } + if (ch == ';') break; - if (_text[text_index] == '=' && - kInStruct) - { - continue; - } + if (space_found_) sym.push_back(ch); + } - if (_text[text_index + 1] == '=' || - _text[text_index - 1] == '!' || - _text[text_index - 1] == '<' || - _text[text_index - 1] == '>') - { - continue; - } + kState.kStructMap[kState.kStructMap.size() - 1].fOffsets.push_back( + std::make_pair( + kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt + 4, + sym)); - std::string substr; - - if (_text.find('=') != std::string::npos && - kInBraces) - { - if (_text.find("*") != std::string::npos) - { - if (_text.find("=") > _text.find("*")) - substr += "\tlda "; - else - substr += "\tldw "; - } - else - { - substr += "\tldw "; - } - } - else if (_text.find('=') != std::string::npos && - !kInBraces) - { - substr += "stw export .data "; - } + kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt = + kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt + 4; - int first_encountered = 0; + continue; + } - std::string str_name; + if (_text[text_index] == '=' && kInStruct) { + continue; + } - for (size_t text_index_2 = 0; text_index_2 < _text.size(); ++text_index_2) - { - if (_text[text_index_2] == '\"') - { - ++text_index_2; + if (_text[text_index + 1] == '=' || _text[text_index - 1] == '!' || + _text[text_index - 1] == '<' || _text[text_index - 1] == '>') { + continue; + } + + std::string substr; + + if (_text.find('=') != std::string::npos && kInBraces) { + if (_text.find("*") != std::string::npos) { + if (_text.find("=") > _text.find("*")) + substr += "\tlda "; + else + substr += "\tldw "; + } else { + substr += "\tldw "; + } + } else if (_text.find('=') != std::string::npos && !kInBraces) { + substr += "stw export .data "; + } - // want to add this, so that the parser recognizes that this is a string. - substr += '"'; + int first_encountered = 0; - for (; text_index_2 < _text.size(); ++text_index_2) - { - if (_text[text_index_2] == '\"') - break; + std::string str_name; - substr += _text[text_index_2]; - } - } + for (size_t text_index_2 = 0; text_index_2 < _text.size(); + ++text_index_2) { + if (_text[text_index_2] == '\"') { + ++text_index_2; - if (_text[text_index_2] == '{' || - _text[text_index_2] == '}') - continue; + // want to add this, so that the parser recognizes that this is a + // string. + substr += '"'; - if (_text[text_index_2] == ';') - { - break; - } + for (; text_index_2 < _text.size(); ++text_index_2) { + if (_text[text_index_2] == '\"') break; - if (_text[text_index_2] == ' ' || - _text[text_index_2] == '\t') - { - if (first_encountered != 2) - { - if (_text[text_index] != '=' && - substr.find("export .data") == std::string::npos && - !kInStruct) - substr += "export .data "; - } + substr += _text[text_index_2]; + } + } - ++first_encountered; + if (_text[text_index_2] == '{' || _text[text_index_2] == '}') continue; - continue; - } + if (_text[text_index_2] == ';') { + break; + } - if (_text[text_index_2] == '=') - { - if (!kInBraces) - { - substr.replace(substr.find("export .data"), strlen("export .data"), "export .page_zero "); - } + if (_text[text_index_2] == ' ' || _text[text_index_2] == '\t') { + if (first_encountered != 2) { + if (_text[text_index] != '=' && + substr.find("export .data") == std::string::npos && !kInStruct) + substr += "export .data "; + } - substr += ","; - continue; - } + ++first_encountered; - substr += _text[text_index_2]; - } + continue; + } - for (auto &clType : kCompilerTypes) - { - if (substr.find(clType.fName) != std::string::npos) - { - if (substr.find(clType.fName) > substr.find('"')) - continue; + if (_text[text_index_2] == '=') { + if (!kInBraces) { + substr.replace(substr.find("export .data"), strlen("export .data"), + "export .page_zero "); + } - substr.erase(substr.find(clType.fName), clType.fName.size()); - } - else if (substr.find(clType.fValue) != std::string::npos) - { - if (substr.find(clType.fValue) > substr.find('"')) - continue; + substr += ","; + continue; + } - if (clType.fName == "const") - continue; + substr += _text[text_index_2]; + } - substr.erase(substr.find(clType.fValue), clType.fValue.size()); - } - } + for (auto &clType : kCompilerTypes) { + if (substr.find(clType.fName) != std::string::npos) { + if (substr.find(clType.fName) > substr.find('"')) continue; - if (substr.find("extern") != std::string::npos) - { - substr.replace(substr.find("extern"), strlen("extern"), "import "); + substr.erase(substr.find(clType.fName), clType.fName.size()); + } else if (substr.find(clType.fValue) != std::string::npos) { + if (substr.find(clType.fValue) > substr.find('"')) continue; - if (substr.find("export .data") != std::string::npos) - substr.erase(substr.find("export .data"), strlen("export .data")); - } + if (clType.fName == "const") continue; - auto var_to_find = std::find_if(kCompilerVariables.cbegin(), kCompilerVariables.cend(), [&](detail::CompilerType type) - { return type.fName.find(substr) != std::string::npos; }); + substr.erase(substr.find(clType.fValue), clType.fValue.size()); + } + } - if (kRegisterCounter == 5 || - kRegisterCounter == 6) - ++kRegisterCounter; + if (substr.find("extern") != std::string::npos) { + substr.replace(substr.find("extern"), strlen("extern"), "import "); - std::string reg = kAsmRegisterPrefix; - reg += std::to_string(kRegisterCounter); + if (substr.find("export .data") != std::string::npos) + substr.erase(substr.find("export .data"), strlen("export .data")); + } - if (var_to_find == kCompilerVariables.cend()) - { - ++kRegisterCounter; + auto var_to_find = + std::find_if(kCompilerVariables.cbegin(), kCompilerVariables.cend(), + [&](detail::CompilerType type) { + return type.fName.find(substr) != std::string::npos; + }); - kState.kStackFrame.push_back({.fName = substr, .fReg = reg}); - kCompilerVariables.push_back({.fName = substr}); - } + if (kRegisterCounter == 5 || kRegisterCounter == 6) ++kRegisterCounter; - syntax_tree.fUserValue += substr; - kState.fSyntaxTree->fLeafList.push_back(syntax_tree); + std::string reg = kAsmRegisterPrefix; + reg += std::to_string(kRegisterCounter); - if (_text[text_index] == '=') - break; - } + if (var_to_find == kCompilerVariables.cend()) { + ++kRegisterCounter; - // function handler. + kState.kStackFrame.push_back({.fName = substr, .fReg = reg}); + kCompilerVariables.push_back({.fName = substr}); + } - if (_text[text_index] == '(' && - !function_found) - { - std::string substr; - std::string args_buffer; - std::string args; + syntax_tree.fUserValue += substr; + kState.fSyntaxTree->fLeafList.push_back(syntax_tree); - bool type_crossed = false; + if (_text[text_index] == '=') break; + } - for (size_t idx = _text.find('(') + 1; idx < _text.size(); ++idx) - { - if (_text[idx] == ',') - continue; + // function handler. - if (_text[idx] == ' ') - continue; + if (_text[text_index] == '(' && !function_found) { + std::string substr; + std::string args_buffer; + std::string args; - if (_text[idx] == ')') - break; - } + bool type_crossed = false; - for (char substr_first_index : _text) - { - if (substr_first_index != ',') - args_buffer += substr_first_index; - else - args_buffer += '$'; + for (size_t idx = _text.find('(') + 1; idx < _text.size(); ++idx) { + if (_text[idx] == ',') continue; - if (substr_first_index == ';') - { - args_buffer = args_buffer.erase(0, args_buffer.find('(')); - args_buffer = args_buffer.erase(args_buffer.find(';'), 1); - args_buffer = args_buffer.erase(args_buffer.find(')'), 1); - args_buffer = args_buffer.erase(args_buffer.find('('), 1); + if (_text[idx] == ' ') continue; - if (!args_buffer.empty()) - args += "\tldw r6, "; + if (_text[idx] == ')') break; + } - std::string register_type; - std::size_t index = 7UL; + for (char substr_first_index : _text) { + if (substr_first_index != ',') + args_buffer += substr_first_index; + else + args_buffer += '$'; - while (args_buffer.find("$") != std::string::npos) - { - register_type = kRegisterPrefix; - register_type += std::to_string(index); + if (substr_first_index == ';') { + args_buffer = args_buffer.erase(0, args_buffer.find('(')); + args_buffer = args_buffer.erase(args_buffer.find(';'), 1); + args_buffer = args_buffer.erase(args_buffer.find(')'), 1); + args_buffer = args_buffer.erase(args_buffer.find('('), 1); - ++index; + if (!args_buffer.empty()) args += "\tldw r6, "; - args_buffer.replace(args_buffer.find('$'), 1, "\n\tldw " + register_type + ","); - } + std::string register_type; + std::size_t index = 7UL; - args += args_buffer; - args += "\n\tlda r19, "; - } - } + while (args_buffer.find("$") != std::string::npos) { + register_type = kRegisterPrefix; + register_type += std::to_string(index); - for (char _text_i : _text) - { - if (_text_i == '\t' || - _text_i == ' ') - { - if (!type_crossed) - { - substr.clear(); - type_crossed = true; - } - - continue; - } + ++index; - if (_text_i == '(') - break; + args_buffer.replace(args_buffer.find('$'), 1, + "\n\tldw " + register_type + ","); + } - substr += _text_i; - } + args += args_buffer; + args += "\n\tlda r19, "; + } + } - if (kInBraces) - { - syntax_tree.fUserValue = args; - syntax_tree.fUserValue += substr; - syntax_tree.fUserValue += "\n\tjrl\n"; + for (char _text_i : _text) { + if (_text_i == '\t' || _text_i == ' ') { + if (!type_crossed) { + substr.clear(); + type_crossed = true; + } - kState.fSyntaxTree->fLeafList.push_back(syntax_tree); + continue; + } - function_found = true; - } - else - { - syntax_tree.fUserValue.clear(); + if (_text_i == '(') break; - syntax_tree.fUserValue += "export .text "; + substr += _text_i; + } - syntax_tree.fUserValue += substr; - syntax_tree.fUserValue += "\n"; + if (kInBraces) { + syntax_tree.fUserValue = args; + syntax_tree.fUserValue += substr; + syntax_tree.fUserValue += "\n\tjrl\n"; - kState.fSyntaxTree->fLeafList.push_back(syntax_tree); + kState.fSyntaxTree->fLeafList.push_back(syntax_tree); - function_found = true; - } + function_found = true; + } else { + syntax_tree.fUserValue.clear(); - kCompilerFunctions.push_back(_text); - } + syntax_tree.fUserValue += "export .text "; - if (_text[text_index] == '-' && - _text[text_index + 1] == '-') - { - _text = _text.replace(_text.find("--"), strlen("--"), ""); + syntax_tree.fUserValue += substr; + syntax_tree.fUserValue += "\n"; - for (int _text_i = 0; _text_i < _text.size(); ++_text_i) - { - if (_text[_text_i] == '\t' || - _text[_text_i] == ' ') - _text.erase(_text_i, 1); - } + kState.fSyntaxTree->fLeafList.push_back(syntax_tree); - syntax_tree.fUserValue += "dec "; - syntax_tree.fUserValue += _text; + function_found = true; + } - kState.fSyntaxTree->fLeafList.push_back(syntax_tree); - break; - } + kCompilerFunctions.push_back(_text); + } - if (_text[text_index] == '}') - { - kRegisterCounter = kStartUsable; + if (_text[text_index] == '-' && _text[text_index + 1] == '-') { + _text = _text.replace(_text.find("--"), strlen("--"), ""); - --kBracesCount; + for (int _text_i = 0; _text_i < _text.size(); ++_text_i) { + if (_text[_text_i] == '\t' || _text[_text_i] == ' ') + _text.erase(_text_i, 1); + } - if (kBracesCount < 1) - { - kInBraces = false; - kBracesCount = 0; - } + syntax_tree.fUserValue += "dec "; + syntax_tree.fUserValue += _text; - if (kInStruct) - kInStruct = false; + kState.fSyntaxTree->fLeafList.push_back(syntax_tree); + break; + } - kState.fSyntaxTree->fLeafList.push_back(syntax_tree); - } + if (_text[text_index] == '}') { + kRegisterCounter = kStartUsable; - syntax_tree.fUserValue.clear(); + --kBracesCount; + + if (kBracesCount < 1) { + kInBraces = false; + kBracesCount = 0; + } + + if (kInStruct) kInStruct = false; + + kState.fSyntaxTree->fLeafList.push_back(syntax_tree); } - syntax_tree.fUserValue = "\n"; - kState.fSyntaxTree->fLeafList.push_back(syntax_tree); + syntax_tree.fUserValue.clear(); + } + + syntax_tree.fUserValue = "\n"; + kState.fSyntaxTree->fLeafList.push_back(syntax_tree); - return true; + return true; } static bool kShouldHaveBraces = false; static std::string kFnName; -std::string CompilerBackendBccl::Check(const char *text, const char *file) -{ - std::string err_str; - std::string ln = text; +std::string CompilerBackendBccl::Check(const char *text, const char *file) { + std::string err_str; + std::string ln = text; - if (ln.empty()) - { - return err_str; - } - - bool non_ascii_found = false; + if (ln.empty()) { + return err_str; + } - for (int i = 0; i < ln.size(); ++i) - { - if (isalnum(ln[i])) - { - non_ascii_found = true; - break; - } - } + bool non_ascii_found = false; - if (kShouldHaveBraces && - ln.find('{') != std::string::npos) - { - kShouldHaveBraces = false; + for (int i = 0; i < ln.size(); ++i) { + if (isalnum(ln[i])) { + non_ascii_found = true; + break; } + } - if (!non_ascii_found) - return err_str; + if (kShouldHaveBraces && ln.find('{') != std::string::npos) { + kShouldHaveBraces = false; + } - size_t string_index = 1UL; + if (!non_ascii_found) return err_str; - if (ln.find('\'') != std::string::npos) - { - string_index = ln.find('\'') + 1; + size_t string_index = 1UL; - for (; string_index < ln.size(); ++string_index) - { - if (ln[string_index] == '\'') - { - if (ln[string_index + 1] != ';') - { - ln.erase(string_index, 1); - } + if (ln.find('\'') != std::string::npos) { + string_index = ln.find('\'') + 1; - return err_str; - } - } - } - else if (ln.find('"') != std::string::npos) - { - string_index = ln.find('"') + 1; - - for (; string_index < ln.size(); ++string_index) - { - if (ln[string_index] == '"') - { - if (ln[string_index + 1] != ';') - { - ln.erase(string_index, 1); - } - else - { - break; - } - } + for (; string_index < ln.size(); ++string_index) { + if (ln[string_index] == '\'') { + if (ln[string_index + 1] != ';') { + ln.erase(string_index, 1); } + + return err_str; + } } - else if (ln.find('"') == std::string::npos && - ln.find('\'') == std::string::npos) - { - std::vector<std::string> forbidden_words; - - forbidden_words.push_back("\\"); - forbidden_words.push_back("?"); - forbidden_words.push_back("@"); - forbidden_words.push_back("~"); - forbidden_words.push_back("::"); - forbidden_words.push_back("/*"); - forbidden_words.push_back("*/"); - - // add them to avoid stupid mistakes. - forbidden_words.push_back("namespace"); - forbidden_words.push_back("struct"); - forbidden_words.push_back("union"); - forbidden_words.push_back("enum"); - forbidden_words.push_back("."); - forbidden_words.push_back("->"); - forbidden_words.push_back("class"); - forbidden_words.push_back("*"); - forbidden_words.push_back("extern \"C\""); - - for (auto &forbidden : forbidden_words) - { - if (ln.find(forbidden) != std::string::npos) - { - err_str += "\nForbidden character detected: "; - err_str += forbidden; - - return err_str; - } + } else if (ln.find('"') != std::string::npos) { + string_index = ln.find('"') + 1; + + for (; string_index < ln.size(); ++string_index) { + if (ln[string_index] == '"') { + if (ln[string_index + 1] != ';') { + ln.erase(string_index, 1); + } else { + break; } + } } + } else if (ln.find('"') == std::string::npos && + ln.find('\'') == std::string::npos) { + std::vector<std::string> forbidden_words; + + forbidden_words.push_back("\\"); + forbidden_words.push_back("?"); + forbidden_words.push_back("@"); + forbidden_words.push_back("~"); + forbidden_words.push_back("::"); + forbidden_words.push_back("/*"); + forbidden_words.push_back("*/"); + + // add them to avoid stupid mistakes. + forbidden_words.push_back("namespace"); + forbidden_words.push_back("struct"); + forbidden_words.push_back("union"); + forbidden_words.push_back("enum"); + forbidden_words.push_back("."); + forbidden_words.push_back("->"); + forbidden_words.push_back("class"); + forbidden_words.push_back("*"); + forbidden_words.push_back("extern \"C\""); + + for (auto &forbidden : forbidden_words) { + if (ln.find(forbidden) != std::string::npos) { + err_str += "\nForbidden character detected: "; + err_str += forbidden; - struct CompilerVariableRange final - { - std::string fBegin; - std::string fEnd; - }; - - const std::vector<CompilerVariableRange> variables_list = { - {.fBegin = "static ", .fEnd = "="}, - {.fBegin = "=", .fEnd = ";"}, - {.fBegin = "if(", .fEnd = "="}, - {.fBegin = "if (", .fEnd = "="}, - {.fBegin = "if(", .fEnd = "<"}, - {.fBegin = "if (", .fEnd = "<"}, - {.fBegin = "if(", .fEnd = ">"}, - {.fBegin = "if (", .fEnd = ">"}, - {.fBegin = "if(", .fEnd = ")"}, - {.fBegin = "if (", .fEnd = ")"}, - - {.fBegin = "else(", .fEnd = "="}, - {.fBegin = "else (", .fEnd = "="}, - {.fBegin = "else(", .fEnd = "<"}, - {.fBegin = "else (", .fEnd = "<"}, - {.fBegin = "else(", .fEnd = ">"}, - {.fBegin = "else (", .fEnd = ">"}, - {.fBegin = "else(", .fEnd = ")"}, - {.fBegin = "else (", .fEnd = ")"}, - }; - - for (auto &variable : variables_list) - { - if (ln.find(variable.fBegin) != std::string::npos) - { - string_index = ln.find(variable.fBegin) + variable.fBegin.size(); - - while (ln[string_index] == ' ') - ++string_index; - - std::string keyword; - - for (; string_index < ln.size(); ++string_index) - { - if (ln[string_index] == variable.fEnd[0]) - { - std::string varname = ""; - - for (size_t index_keyword = ln.find(' '); ln[index_keyword] != variable.fBegin[0]; - ++index_keyword) - { - if (ln[index_keyword] == ' ') - { - continue; - } - - if (isdigit(ln[index_keyword])) - { - goto cc_next_loop; - } - - varname += ln[index_keyword]; - } - - if (varname.find(' ') != std::string::npos) - { - varname.erase(0, varname.find(' ')); - - if (variable.fBegin == "extern") - { - varname.erase(0, varname.find(' ')); - } - } - - if (kRegisterCounter == 5 || - kRegisterCounter == 6) - ++kRegisterCounter; - - std::string reg = kAsmRegisterPrefix; - reg += std::to_string(kRegisterCounter); - - kCompilerVariables.push_back({.fValue = varname}); - goto cc_check_done; - } + return err_str; + } + } + } + + struct CompilerVariableRange final { + std::string fBegin; + std::string fEnd; + }; + + const std::vector<CompilerVariableRange> variables_list = { + {.fBegin = "static ", .fEnd = "="}, {.fBegin = "=", .fEnd = ";"}, + {.fBegin = "if(", .fEnd = "="}, {.fBegin = "if (", .fEnd = "="}, + {.fBegin = "if(", .fEnd = "<"}, {.fBegin = "if (", .fEnd = "<"}, + {.fBegin = "if(", .fEnd = ">"}, {.fBegin = "if (", .fEnd = ">"}, + {.fBegin = "if(", .fEnd = ")"}, {.fBegin = "if (", .fEnd = ")"}, + + {.fBegin = "else(", .fEnd = "="}, {.fBegin = "else (", .fEnd = "="}, + {.fBegin = "else(", .fEnd = "<"}, {.fBegin = "else (", .fEnd = "<"}, + {.fBegin = "else(", .fEnd = ">"}, {.fBegin = "else (", .fEnd = ">"}, + {.fBegin = "else(", .fEnd = ")"}, {.fBegin = "else (", .fEnd = ")"}, + }; + + for (auto &variable : variables_list) { + if (ln.find(variable.fBegin) != std::string::npos) { + string_index = ln.find(variable.fBegin) + variable.fBegin.size(); + + while (ln[string_index] == ' ') ++string_index; + + std::string keyword; + + for (; string_index < ln.size(); ++string_index) { + if (ln[string_index] == variable.fEnd[0]) { + std::string varname = ""; + + for (size_t index_keyword = ln.find(' '); + ln[index_keyword] != variable.fBegin[0]; ++index_keyword) { + if (ln[index_keyword] == ' ') { + continue; + } - keyword.push_back(ln[string_index]); + if (isdigit(ln[index_keyword])) { + goto cc_next_loop; } - goto cc_next_loop; + varname += ln[index_keyword]; + } - cc_check_done: + if (varname.find(' ') != std::string::npos) { + varname.erase(0, varname.find(' ')); - // skip digit value. - if (isdigit(keyword[0]) || - keyword[0] == '"') - { - goto cc_next_loop; + if (variable.fBegin == "extern") { + varname.erase(0, varname.find(' ')); } + } - while (keyword.find(' ') != std::string::npos) - keyword.erase(keyword.find(' '), 1); + if (kRegisterCounter == 5 || kRegisterCounter == 6) + ++kRegisterCounter; - for (auto &var : kCompilerVariables) - { - if (var.fValue.find(keyword) != std::string::npos) - { - err_str.clear(); - goto cc_next; - } - } + std::string reg = kAsmRegisterPrefix; + reg += std::to_string(kRegisterCounter); - for (auto &fn : kCompilerFunctions) - { - if (fn.find(keyword[0]) != std::string::npos) - { - auto where_begin = fn.find(keyword[0]); - auto keyword_begin = 0UL; - auto failed = false; - - for (; where_begin < keyword.size(); ++where_begin) - { - if (fn[where_begin] == '(' && - keyword[keyword_begin] == '(') - break; - - if (fn[where_begin] != keyword[keyword_begin]) - { - failed = true; - break; - } - - ++keyword_begin; - } - - if (!failed) - { - err_str.clear(); - goto cc_next; - } - else - { - continue; - } - } - } + kCompilerVariables.push_back({.fValue = varname}); + goto cc_check_done; + } + + keyword.push_back(ln[string_index]); + } + + goto cc_next_loop; - cc_error_value: - if (keyword.find("->") != std::string::npos) - return err_str; + cc_check_done: - if (keyword.find(".") != std::string::npos) - return err_str; + // skip digit value. + if (isdigit(keyword[0]) || keyword[0] == '"') { + goto cc_next_loop; + } - if (isalnum(keyword[0])) - err_str += "\nUndefined value: " + keyword; + while (keyword.find(' ') != std::string::npos) + keyword.erase(keyword.find(' '), 1); - return err_str; + for (auto &var : kCompilerVariables) { + if (var.fValue.find(keyword) != std::string::npos) { + err_str.clear(); + goto cc_next; } + } - cc_next_loop: - continue; - } + for (auto &fn : kCompilerFunctions) { + if (fn.find(keyword[0]) != std::string::npos) { + auto where_begin = fn.find(keyword[0]); + auto keyword_begin = 0UL; + auto failed = false; -cc_next: + for (; where_begin < keyword.size(); ++where_begin) { + if (fn[where_begin] == '(' && keyword[keyword_begin] == '(') break; - // extern does not declare anything, it imports a variable. - // so that's why it's not declare upper. - if (ParserKit::find_word(ln, "extern")) - { - auto substr = ln.substr(ln.find("extern") + strlen("extern")); - kCompilerVariables.push_back({.fValue = substr}); - } + if (fn[where_begin] != keyword[keyword_begin]) { + failed = true; + break; + } - if (kShouldHaveBraces && - ln.find('{') == std::string::npos) - { - err_str += "Missing '{' for function "; - err_str += kFnName; - err_str += "\n"; + ++keyword_begin; + } - kShouldHaveBraces = false; - kFnName.clear(); - } - else if (kShouldHaveBraces && - ln.find('{') != std::string::npos) - { - kShouldHaveBraces = false; - kFnName.clear(); - } + if (!failed) { + err_str.clear(); + goto cc_next; + } else { + continue; + } + } + } - bool type_not_found = true; + cc_error_value: + if (keyword.find("->") != std::string::npos) return err_str; - if (ln.find('\'') != std::string::npos) - { - ln.replace(ln.find('\''), 3, "0"); + if (keyword.find(".") != std::string::npos) return err_str; + + if (isalnum(keyword[0])) err_str += "\nUndefined value: " + keyword; + + return err_str; } - auto first = ln.find('"'); - if (first != std::string::npos) - { - auto second = 0UL; - bool found_second_quote = false; + cc_next_loop: + continue; + } - for (size_t i = first + 1; i < ln.size(); ++i) - { - if (ln[i] == '\"') - { - found_second_quote = true; - second = i; +cc_next: - break; - } - } + // extern does not declare anything, it imports a variable. + // so that's why it's not declare upper. + if (ParserKit::find_word(ln, "extern")) { + auto substr = ln.substr(ln.find("extern") + strlen("extern")); + kCompilerVariables.push_back({.fValue = substr}); + } + + if (kShouldHaveBraces && ln.find('{') == std::string::npos) { + err_str += "Missing '{' for function "; + err_str += kFnName; + err_str += "\n"; + + kShouldHaveBraces = false; + kFnName.clear(); + } else if (kShouldHaveBraces && ln.find('{') != std::string::npos) { + kShouldHaveBraces = false; + kFnName.clear(); + } + + bool type_not_found = true; + + if (ln.find('\'') != std::string::npos) { + ln.replace(ln.find('\''), 3, "0"); + } + + auto first = ln.find('"'); + if (first != std::string::npos) { + auto second = 0UL; + bool found_second_quote = false; + + for (size_t i = first + 1; i < ln.size(); ++i) { + if (ln[i] == '\"') { + found_second_quote = true; + second = i; + + break; + } + } - if (!found_second_quote) - { - err_str += "Missing terminating \"."; - err_str += " here -> " + ln.substr(ln.find('"'), second); - } + if (!found_second_quote) { + err_str += "Missing terminating \"."; + err_str += " here -> " + ln.substr(ln.find('"'), second); } + } - if (ln.find(')') != std::string::npos && - ln.find(';') == std::string::npos) - { - if (ln.find('{') == std::string::npos) - { - kFnName = ln; - kShouldHaveBraces = true; + if (ln.find(')') != std::string::npos && ln.find(';') == std::string::npos) { + if (ln.find('{') == std::string::npos) { + kFnName = ln; + kShouldHaveBraces = true; - goto skip_braces_check; - } - else if (ln.find('{') != std::string::npos) - { - kShouldHaveBraces = false; - } + goto skip_braces_check; + } else if (ln.find('{') != std::string::npos) { + kShouldHaveBraces = false; } + } skip_braces_check: - for (auto &key : kCompilerTypes) - { - if (ParserKit::find_word(ln, key.fName)) - { - if (isdigit(ln[ln.find(key.fName) + key.fName.size() + 1])) - { - err_str += "\nNumber cannot be set for "; - err_str += key.fName; - err_str += "'s name. here -> "; - err_str += ln; - } + for (auto &key : kCompilerTypes) { + if (ParserKit::find_word(ln, key.fName)) { + if (isdigit(ln[ln.find(key.fName) + key.fName.size() + 1])) { + err_str += "\nNumber cannot be set for "; + err_str += key.fName; + err_str += "'s name. here -> "; + err_str += ln; + } - if (ln.find(key.fName) == 0 || - ln[ln.find(key.fName) - 1] == ' ' || - ln[ln.find(key.fName) - 1] == '\t') - { - type_not_found = false; + if (ln.find(key.fName) == 0 || ln[ln.find(key.fName) - 1] == ' ' || + ln[ln.find(key.fName) - 1] == '\t') { + type_not_found = false; - if (ln[ln.find(key.fName) + key.fName.size()] != ' ') - { - type_not_found = true; + if (ln[ln.find(key.fName) + key.fName.size()] != ' ') { + type_not_found = true; - if (ln[ln.find(key.fName) + key.fName.size()] == '\t') - type_not_found = false; + if (ln[ln.find(key.fName) + key.fName.size()] == '\t') + type_not_found = false; - goto next; - } - else if (ln[ln.find(key.fName) + key.fName.size()] != '\t') - { - type_not_found = true; + goto next; + } else if (ln[ln.find(key.fName) + key.fName.size()] != '\t') { + type_not_found = true; - if (ln[ln.find(key.fName) + key.fName.size()] == ' ') - type_not_found = false; - } - } + if (ln[ln.find(key.fName) + key.fName.size()] == ' ') + type_not_found = false; + } + } - next: + next: - if (ln.find(';') == std::string::npos) - { - if (ln.find('(') != std::string::npos) - { - if (ln.find('=') == std::string::npos) - continue; - } + if (ln.find(';') == std::string::npos) { + if (ln.find('(') != std::string::npos) { + if (ln.find('=') == std::string::npos) continue; + } - err_str += "\nMissing ';', here -> "; - err_str += ln; - } - else - { - continue; - } + err_str += "\nMissing ';', here -> "; + err_str += ln; + } else { + continue; + } - if (ln.find('=') != std::string::npos) - { - if (ln.find('(') != std::string::npos) - { - if (ln.find(')') == std::string::npos) - { - err_str += "\nMissing ')', after '(' here -> "; - err_str += ln.substr(ln.find('(')); - } - } - } + if (ln.find('=') != std::string::npos) { + if (ln.find('(') != std::string::npos) { + if (ln.find(')') == std::string::npos) { + err_str += "\nMissing ')', after '(' here -> "; + err_str += ln.substr(ln.find('(')); + } } + } } - - if (kInBraces && - ln.find("struct") != std::string::npos && - ln.find("union") != std::string::npos && - ln.find("enum") != std::string::npos && - ln.find('=') != std::string::npos) - { - if (ln.find(';') == std::string::npos) - { - err_str += "\nMissing ';' after struct/union/enum declaration, here -> "; - err_str += ln; - } + } + + if (kInBraces && ln.find("struct") != std::string::npos && + ln.find("union") != std::string::npos && + ln.find("enum") != std::string::npos && + ln.find('=') != std::string::npos) { + if (ln.find(';') == std::string::npos) { + err_str += "\nMissing ';' after struct/union/enum declaration, here -> "; + err_str += ln; } - - if (ln.find(';') != std::string::npos && - ln.find("for") == std::string::npos) - { - if (ln.find(';') + 1 != ln.size()) - { - for (int i = 0; i < ln.substr(ln.find(';') + 1).size(); ++i) - { - if ((ln.substr(ln.find(';') + 1)[i] != ' ') || - (ln.substr(ln.find(';') + 1)[i] != '\t')) - { - if (auto err = this->Check(ln.substr(ln.find(';') + 1).c_str(), file); - !err.empty()) - { - err_str += "\nUnexpected text after ';' -> "; - err_str += ln.substr(ln.find(';')); - err_str += err; - } - } - } + } + + if (ln.find(';') != std::string::npos && + ln.find("for") == std::string::npos) { + if (ln.find(';') + 1 != ln.size()) { + for (int i = 0; i < ln.substr(ln.find(';') + 1).size(); ++i) { + if ((ln.substr(ln.find(';') + 1)[i] != ' ') || + (ln.substr(ln.find(';') + 1)[i] != '\t')) { + if (auto err = this->Check(ln.substr(ln.find(';') + 1).c_str(), file); + !err.empty()) { + err_str += "\nUnexpected text after ';' -> "; + err_str += ln.substr(ln.find(';')); + err_str += err; + } } + } } + } + + if (ln.find('(') != std::string::npos) { + if (ln.find(';') == std::string::npos && !ParserKit::find_word(ln, "|") && + !ParserKit::find_word(ln, "||") && !ParserKit::find_word(ln, "&") && + !ParserKit::find_word(ln, "&&") && !ParserKit::find_word(ln, "~")) { + bool found_func = false; + size_t i = ln.find('('); + std::vector<char> opens; + std::vector<char> closes; + + for (; i < ln.size(); ++i) { + if (ln[i] == ')') { + closes.push_back(1); + } - if (ln.find('(') != std::string::npos) - { - if (ln.find(';') == std::string::npos && - !ParserKit::find_word(ln, "|") && - !ParserKit::find_word(ln, "||") && - !ParserKit::find_word(ln, "&") && - !ParserKit::find_word(ln, "&&") && - !ParserKit::find_word(ln, "~")) - { - bool found_func = false; - size_t i = ln.find('('); - std::vector<char> opens; - std::vector<char> closes; - - for (; i < ln.size(); ++i) - { - if (ln[i] == ')') - { - closes.push_back(1); - } - - if (ln[i] == '(') - { - opens.push_back(1); - } - } - - if (closes.size() != opens.size()) - err_str += "Unterminated (), here -> " + ln; + if (ln[i] == '(') { + opens.push_back(1); + } + } - bool space_found = false; + if (closes.size() != opens.size()) + err_str += "Unterminated (), here -> " + ln; - for (int i = 0; i < ln.size(); ++i) - { - if (ln[i] == ')' && - !space_found) - { - space_found = true; - continue; - } + bool space_found = false; - if (space_found) - { - if (ln[i] == ' ' && - isalnum(ln[i + 1])) - { - err_str += "\nBad function format here -> "; - err_str += ln; - } - } - } + for (int i = 0; i < ln.size(); ++i) { + if (ln[i] == ')' && !space_found) { + space_found = true; + continue; } - if (ln.find('(') < 1) - { - err_str += "\nMissing identifier before '(' here -> "; + if (space_found) { + if (ln[i] == ' ' && isalnum(ln[i + 1])) { + err_str += "\nBad function format here -> "; err_str += ln; + } } - else - { - if (type_not_found && - ln.find(';') == std::string::npos && - ln.find("if") == std::string::npos && - ln.find("|") == std::string::npos && - ln.find("&") == std::string::npos && - ln.find("(") == std::string::npos && - ln.find(")") == std::string::npos) - { - err_str += "\n Missing ';' or type, here -> "; - err_str += ln; - } - } - - if (ln.find(')') == std::string::npos) - { - err_str += "\nMissing ')', after '(' here -> "; - err_str += ln.substr(ln.find('(')); - } + } } - else - { - if (ln.find("for") != std::string::npos || - ln.find("while") != std::string::npos) - { - err_str += "\nMissing '(', after \"for\", here -> "; - err_str += ln; - } + + if (ln.find('(') < 1) { + err_str += "\nMissing identifier before '(' here -> "; + err_str += ln; + } else { + if (type_not_found && ln.find(';') == std::string::npos && + ln.find("if") == std::string::npos && + ln.find("|") == std::string::npos && + ln.find("&") == std::string::npos && + ln.find("(") == std::string::npos && + ln.find(")") == std::string::npos) { + err_str += "\n Missing ';' or type, here -> "; + err_str += ln; + } } - if (ln.find('}') != std::string::npos && - !kInBraces) - { - if (!kInStruct && - ln.find(';') == std::string::npos) - { - err_str += "\nMismatched '}', here -> "; - err_str += ln; - } + if (ln.find(')') == std::string::npos) { + err_str += "\nMissing ')', after '(' here -> "; + err_str += ln.substr(ln.find('(')); } + } else { + if (ln.find("for") != std::string::npos || + ln.find("while") != std::string::npos) { + err_str += "\nMissing '(', after \"for\", here -> "; + err_str += ln; + } + } - if (!ln.empty()) - { - if (ln.find(';') == std::string::npos && - ln.find('{') == std::string::npos && - ln.find('}') == std::string::npos && - ln.find(')') == std::string::npos && - ln.find('(') == std::string::npos && - ln.find(',') == std::string::npos) - { - if (ln.size() <= 2) - return err_str; - - err_str += "\nMissing ';', here -> "; - err_str += ln; - } + if (ln.find('}') != std::string::npos && !kInBraces) { + if (!kInStruct && ln.find(';') == std::string::npos) { + err_str += "\nMismatched '}', here -> "; + err_str += ln; + } + } + + if (!ln.empty()) { + if (ln.find(';') == std::string::npos && + ln.find('{') == std::string::npos && + ln.find('}') == std::string::npos && + ln.find(')') == std::string::npos && + ln.find('(') == std::string::npos && + ln.find(',') == std::string::npos) { + if (ln.size() <= 2) return err_str; + + err_str += "\nMissing ';', here -> "; + err_str += ln; } + } - return err_str; + return err_str; } ///////////////////////////////////////////////////////////////////////////////////////// @@ -1284,170 +1055,147 @@ skip_braces_check: ///////////////////////////////////////////////////////////////////////////////////////// -class AssemblyMountpointBccl final : public CompilerKit::AssemblyMountpoint -{ -public: - explicit AssemblyMountpointBccl() = default; - ~AssemblyMountpointBccl() override = default; +class AssemblyMountpointBccl final : public CompilerKit::AssemblyMountpoint { + public: + explicit AssemblyMountpointBccl() = default; + ~AssemblyMountpointBccl() override = default; - CXXKIT_COPY_DEFAULT(AssemblyMountpointBccl); + CXXKIT_COPY_DEFAULT(AssemblyMountpointBccl); - [[maybe_unused]] static Int32 Arch() noexcept { return CompilerKit::AssemblyFactory::kArchRISCV; } + [[maybe_unused]] static Int32 Arch() noexcept { + return CompilerKit::AssemblyFactory::kArchRISCV; + } - Int32 CompileToFormat(CompilerKit::StringView &src, Int32 arch) override - { - if (arch != AssemblyMountpointBccl::Arch()) - return -1; + Int32 CompileToFormat(CompilerKit::StringView &src, Int32 arch) override { + if (arch != AssemblyMountpointBccl::Arch()) return -1; - if (kCompilerBackend == nullptr) - return -1; + if (kCompilerBackend == nullptr) return -1; - /* @brief copy contents wihtout extension */ - std::string src_file = src.CData(); - std::ifstream src_fp = std::ifstream(src_file, std::ios::in); - std::string dest; + /* @brief copy contents wihtout extension */ + std::string src_file = src.CData(); + std::ifstream src_fp = std::ifstream(src_file, std::ios::in); + std::string dest; - for (auto &ch : src_file) - { - if (ch == '.') - { - break; - } + for (auto &ch : src_file) { + if (ch == '.') { + break; + } - dest += ch; - } + dest += ch; + } - /* According to pef abi. */ - std::vector<const char*> exts = kAsmFileExts; - dest += exts[0]; + /* According to pef abi. */ + std::vector<const char *> exts = kAsmFileExts; + dest += exts[0]; - kState.fOutputAssembly = std::make_unique<std::ofstream>(dest); + kState.fOutputAssembly = std::make_unique<std::ofstream>(dest); - auto fmt = CompilerKit::current_date(); + auto fmt = CompilerKit::current_date(); - (*kState.fOutputAssembly) << "# Path: " << src_file << "\n"; - (*kState.fOutputAssembly) << "# Language: MP-UX Assembly (Generated from BCCL)\n"; - (*kState.fOutputAssembly) << "# Build Date: " << fmt << "\n\n"; + (*kState.fOutputAssembly) << "# Path: " << src_file << "\n"; + (*kState.fOutputAssembly) + << "# Language: MP-UX Assembly (Generated from BCCL)\n"; + (*kState.fOutputAssembly) << "# Build Date: " << fmt << "\n\n"; - ParserKit::SyntaxLeafList syntax; + ParserKit::SyntaxLeafList syntax; - kState.fSyntaxTreeList.push_back(syntax); - kState.fSyntaxTree = &kState.fSyntaxTreeList[kState.fSyntaxTreeList.size() - 1]; + kState.fSyntaxTreeList.push_back(syntax); + kState.fSyntaxTree = + &kState.fSyntaxTreeList[kState.fSyntaxTreeList.size() - 1]; - std::string line_src; + std::string line_src; - while (std::getline(src_fp, line_src)) - { - if (auto err = kCompilerBackend->Check(line_src.c_str(), src.CData()); - err.empty()) - { - kCompilerBackend->Compile(line_src, src.CData()); - } - else - { - detail::print_error(err, src.CData()); - } + while (std::getline(src_fp, line_src)) { + if (auto err = kCompilerBackend->Check(line_src.c_str(), src.CData()); + err.empty()) { + kCompilerBackend->Compile(line_src, src.CData()); + } else { + detail::print_error(err, src.CData()); + } + } + + if (kAcceptableErrors > 0) return -1; + + std::vector<std::string> keywords = {"ldw", "stw", "lda", "sta", + "add", "dec", "mv"}; + + /// + /// Replace, optimize, fix assembly output. + /// + + for (auto &leaf : kState.fSyntaxTree->fLeafList) { + std::vector<std::string> access_keywords = {"->", "."}; + + for (auto &access_ident : access_keywords) { + if (ParserKit::find_word(leaf.fUserValue, access_ident)) { + for (auto &struc : kState.kStructMap) { + } } + } - if (kAcceptableErrors > 0) - return -1; + for (auto &keyword : keywords) { + if (ParserKit::find_word(leaf.fUserValue, keyword)) { + std::size_t cnt = 0UL; - std::vector<std::string> keywords = {"ldw", "stw", "lda", "sta", "add", "dec", "mv"}; + for (auto ® : kState.kStackFrame) { + std::string needle; - /// - /// Replace, optimize, fix assembly output. - /// + for (size_t i = 0; i < reg.fName.size(); i++) { + if (reg.fName[i] == ' ') { + ++i; + + for (; i < reg.fName.size(); i++) { + if (reg.fName[i] == ',') { + break; + } - for (auto &leaf : kState.fSyntaxTree->fLeafList) - { - std::vector<std::string> access_keywords = {"->", "."}; + if (reg.fName[i] == ' ') continue; - for (auto &access_ident : access_keywords) - { - if (ParserKit::find_word(leaf.fUserValue, access_ident)) - { - for (auto &struc : kState.kStructMap) - { - } + needle += reg.fName[i]; } + + break; + } } - for (auto &keyword : keywords) - { - if (ParserKit::find_word(leaf.fUserValue, keyword)) - { - std::size_t cnt = 0UL; - - for (auto ® : kState.kStackFrame) - { - std::string needle; - - for (size_t i = 0; i < reg.fName.size(); i++) - { - if (reg.fName[i] == ' ') - { - ++i; - - for (; i < reg.fName.size(); i++) - { - if (reg.fName[i] == ',') - { - break; - } - - if (reg.fName[i] == ' ') - continue; - - needle += reg.fName[i]; - } - - break; - } - } - - if (ParserKit::find_word(leaf.fUserValue, needle)) - { - if (leaf.fUserValue.find("ldw r6") != std::string::npos) - { - std::string::difference_type countComma = std::count(leaf.fUserValue.begin(), - leaf.fUserValue.end(), ','); - - if (countComma == 1) - { - leaf.fUserValue.replace(leaf.fUserValue.find("ldw"), strlen("ldw"), "mv"); - } - } - - leaf.fUserValue.replace(leaf.fUserValue.find(needle), - needle.size(), reg.fReg); - - ++cnt; - } - } - - if (cnt > 1 && - keyword != "mv" && - keyword != "add" && - keyword != "dec") - { - leaf.fUserValue.replace(leaf.fUserValue.find(keyword), keyword.size(), "mv"); - } + if (ParserKit::find_word(leaf.fUserValue, needle)) { + if (leaf.fUserValue.find("ldw r6") != std::string::npos) { + std::string::difference_type countComma = std::count( + leaf.fUserValue.begin(), leaf.fUserValue.end(), ','); + + if (countComma == 1) { + leaf.fUserValue.replace(leaf.fUserValue.find("ldw"), + strlen("ldw"), "mv"); } + } + + leaf.fUserValue.replace(leaf.fUserValue.find(needle), + needle.size(), reg.fReg); + + ++cnt; } - } + } - for (auto &leaf : kState.fSyntaxTree->fLeafList) - { - (*kState.fOutputAssembly) << leaf.fUserValue; + if (cnt > 1 && keyword != "mv" && keyword != "add" && + keyword != "dec") { + leaf.fUserValue.replace(leaf.fUserValue.find(keyword), + keyword.size(), "mv"); + } } + } + } - kState.fSyntaxTree = nullptr; + for (auto &leaf : kState.fSyntaxTree->fLeafList) { + (*kState.fOutputAssembly) << leaf.fUserValue; + } - kState.fOutputAssembly->flush(); - kState.fOutputAssembly.reset(); + kState.fSyntaxTree = nullptr; - return kOk; - } + kState.fOutputAssembly->flush(); + kState.fOutputAssembly.reset(); + + return kOk; + } }; ///////////////////////////////////////////////////////////////////////////////////////// @@ -1455,130 +1203,114 @@ public: #define kPrintF printf #define kSplashCxx() kPrintF(kWhite "%s\n", "bccl, v1.15, (c) Mahrouss Logic") -static void cc_print_help() -{ - kSplashCxx(); +static void cc_print_help() { + kSplashCxx(); - kPrintF(kWhite "--asm={ASSEMBLER}: %s\n", "Compile with a specific syntax. (64x0, 32x0)"); - kPrintF(kWhite "--compiler={COMPILER}: %s\n", "Select compiler engine (builtins are The dalvik engine)."); + kPrintF(kWhite "--asm={ASSEMBLER}: %s\n", + "Compile with a specific syntax. (64x0, 32x0)"); + kPrintF(kWhite "--compiler={COMPILER}: %s\n", + "Select compiler engine (builtins are The dalvik engine)."); } ///////////////////////////////////////////////////////////////////////////////////////// #define kExt ".bccl" -MPCC_MODULE(CompilerBccl64x0) -{ - kCompilerTypes.push_back({.fName = "void", .fValue = "void"}); - kCompilerTypes.push_back({.fName = "char", .fValue = "byte"}); - kCompilerTypes.push_back({.fName = "short", .fValue = "hword"}); - kCompilerTypes.push_back({.fName = "int", .fValue = "dword"}); - kCompilerTypes.push_back({.fName = "long", .fValue = "qword"}); - - bool skip = false; - - for (auto index = 1UL; index < argc; ++index) - { - if (skip) - { - skip = false; - continue; - } +MPCC_MODULE(CompilerBccl64x0) { + kCompilerTypes.push_back({.fName = "void", .fValue = "void"}); + kCompilerTypes.push_back({.fName = "char", .fValue = "byte"}); + kCompilerTypes.push_back({.fName = "short", .fValue = "hword"}); + kCompilerTypes.push_back({.fName = "int", .fValue = "dword"}); + kCompilerTypes.push_back({.fName = "long", .fValue = "qword"}); - if (argv[index][0] == '-') - { - if (strcmp(argv[index], "-v") == 0 || - strcmp(argv[index], "--version") == 0) - { - kSplashCxx(); - return kOk; - } + bool skip = false; - if (strcmp(argv[index], "-verbose") == 0) - { - kState.kVerbose = true; + for (auto index = 1UL; index < argc; ++index) { + if (skip) { + skip = false; + continue; + } - continue; - } + if (argv[index][0] == '-') { + if (strcmp(argv[index], "-v") == 0 || + strcmp(argv[index], "--version") == 0) { + kSplashCxx(); + return kOk; + } - if (strcmp(argv[index], "-h") == 0 || - strcmp(argv[index], "--help") == 0) - { - cc_print_help(); + if (strcmp(argv[index], "-verbose") == 0) { + kState.kVerbose = true; - return kOk; - } + continue; + } - if (strcmp(argv[index], "--dialect") == 0) - { - if (kCompilerBackend) - std::cout << kCompilerBackend->Language() << "\n"; + if (strcmp(argv[index], "-h") == 0 || + strcmp(argv[index], "--help") == 0) { + cc_print_help(); - return kOk; - } + return kOk; + } - if (strcmp(argv[index], "--asm=masm") == 0) - { - delete kFactory.Unmount(); + if (strcmp(argv[index], "--dialect") == 0) { + if (kCompilerBackend) std::cout << kCompilerBackend->Language() << "\n"; - kFactory.Mount(new AssemblyMountpointBccl()); - kMachine = CompilerKit::AssemblyFactory::kArchRISCV; + return kOk; + } - continue; - } + if (strcmp(argv[index], "--asm=masm") == 0) { + delete kFactory.Unmount(); - if (strcmp(argv[index], "--compiler=dalvik") == 0) - { - if (!kCompilerBackend) - kCompilerBackend = new CompilerBackendBccl(); + kFactory.Mount(new AssemblyMountpointBccl()); + kMachine = CompilerKit::AssemblyFactory::kArch64x0; - continue; - } + continue; + } - if (strcmp(argv[index], "-fmax-exceptions") == 0) - { - try - { - kErrorLimit = std::strtol(argv[index + 1], nullptr, 10); - } - // catch anything here - catch (...) - { - kErrorLimit = 0; - } + if (strcmp(argv[index], "--compiler=dalvik") == 0) { + if (!kCompilerBackend) kCompilerBackend = new CompilerBackendBccl(); + + continue; + } - skip = true; + if (strcmp(argv[index], "-fmax-exceptions") == 0) { + try { + kErrorLimit = std::strtol(argv[index + 1], nullptr, 10); + } + // catch anything here + catch (...) { + kErrorLimit = 0; + } - continue; - } + skip = true; - std::string err = "Unknown command: "; - err += argv[index]; + continue; + } - detail::print_error(err, "bccl"); + std::string err = "Unknown command: "; + err += argv[index]; - continue; - } + detail::print_error(err, "bccl"); - kFileList.emplace_back(argv[index]); + continue; + } - CompilerKit::StringView srcFile = CompilerKit::StringBuilder::Construct(argv[index]); + kFileList.emplace_back(argv[index]); - if (strstr(argv[index], kExt) == nullptr) - { - if (kState.kVerbose) - { - std::cerr << argv[index] << " is not a valid BCCL source.\n"; - } + CompilerKit::StringView srcFile = + CompilerKit::StringBuilder::Construct(argv[index]); - return -1; - } + if (strstr(argv[index], kExt) == nullptr) { + if (kState.kVerbose) { + std::cerr << argv[index] << " is not a valid BCCL source.\n"; + } - if (kFactory.Compile(srcFile, kMachine) != kOk) - return -1; + return -1; } - return kOk; + if (kFactory.Compile(srcFile, kMachine) != kOk) return -1; + } + + return kOk; } -// Last rev 8-1-24
\ No newline at end of file +// Last rev 8-1-24 diff --git a/Private/Toolchain/bpp.cc b/Private/Toolchain/bpp.cc index cd1bc47..291c25e 100644 --- a/Private/Toolchain/bpp.cc +++ b/Private/Toolchain/bpp.cc @@ -9,11 +9,10 @@ /// bugs: ? -#include <CompilerKit/StdKit/ErrorID.hpp> #include <CompilerKit/ParserKit.hpp> -#include <sstream> -#include <iostream> +#include <CompilerKit/StdKit/ErrorID.hpp> #include <fstream> +#include <iostream> #define kMacroPrefix '%' @@ -21,7 +20,8 @@ // @file bpp.cc // @brief BCCL preprocessor. -typedef Int32 (*bpp_parser_fn_t)(std::string &line, std::ifstream &hdr_file, std::ofstream &pp_out); +typedef Int32 (*bpp_parser_fn_t)(std::string &line, std::ifstream &hdr_file, + std::ofstream &pp_out); ///////////////////////////////////////////////////////////////////////////////////////// @@ -29,43 +29,38 @@ typedef Int32 (*bpp_parser_fn_t)(std::string &line, std::ifstream &hdr_file, std ///////////////////////////////////////////////////////////////////////////////////////// -namespace details -{ - enum - { - kEqual, - kGreaterEqThan, - kLesserEqThan, - kGreaterThan, - kLesserThan, - kNotEqual, - }; - - struct bpp_macro_condition final - { - int32_t fType; - std::string fTypeName; - }; - - struct bpp_macro final - { - std::vector<std::string> fArgs; - std::string fName; - std::string fValue; - }; - - class bpp_pragma final - { - public: - explicit bpp_pragma() = default; - ~bpp_pragma() = default; - - CXXKIT_COPY_DEFAULT(bpp_pragma); - - std::string fMacroName; - bpp_parser_fn_t fParse; - }; -} +namespace details { +enum { + kEqual, + kGreaterEqThan, + kLesserEqThan, + kGreaterThan, + kLesserThan, + kNotEqual, +}; + +struct bpp_macro_condition final { + int32_t fType; + std::string fTypeName; +}; + +struct bpp_macro final { + std::vector<std::string> fArgs; + std::string fName; + std::string fValue; +}; + +class bpp_pragma final { + public: + explicit bpp_pragma() = default; + ~bpp_pragma() = default; + + CXXKIT_COPY_DEFAULT(bpp_pragma); + + std::string fMacroName; + bpp_parser_fn_t fParse; +}; +} // namespace details static std::vector<std::string> kFiles; static std::vector<details::bpp_macro> kMacros; @@ -74,16 +69,8 @@ static std::vector<std::string> kIncludes; static std::string kWorkingDir; static std::vector<std::string> kKeywords = { - "inc", - "if", - "pragma", - "def", - "elif", - "ifdef", - "ifndef", - "else", - "warning", - "error"}; + "inc", "if", "pragma", "def", "elif", + "ifdef", "ifndef", "else", "warning", "error"}; #define kKeywordCxxCnt kKeywords.size() @@ -95,177 +82,148 @@ static std::vector<std::string> kKeywords = { ///////////////////////////////////////////////////////////////////////////////////////// int32_t bpp_parse_if_condition(details::bpp_macro_condition &cond, - details::bpp_macro ¯o, - bool &inactive_code, bool &defined, - std::string ¯o_str) -{ - if (cond.fType == details::kEqual) - { - auto substr_macro = macro_str.substr(macro_str.find(macro.fName) + macro.fName.size()); - - if (substr_macro.find(macro.fValue) != std::string::npos) - { - if (macro.fValue == "0") - { - defined = false; - inactive_code = true; - - return 1; - } - - defined = true; - inactive_code = false; - - return 1; - } - } - else if (cond.fType == details::kNotEqual) - { - auto substr_macro = macro_str.substr(macro_str.find(macro.fName) + macro.fName.size()); - - if (substr_macro.find(macro.fName) != std::string::npos) - { - if (substr_macro.find(macro.fValue) != std::string::npos) - { - defined = false; - inactive_code = true; - - return 1; - } - - defined = true; - inactive_code = false; - - return 1; - } - - return 0; - } - - auto substr_macro = macro_str.substr(macro_str.find(macro.fName) + macro.fName.size()); - - std::string number; - - for (auto ¯o_num : kMacros) - { - if (substr_macro.find(macro_num.fName) != std::string::npos) - { - for (size_t i = 0; i < macro_num.fName.size(); ++i) - { - if (isdigit(macro_num.fValue[i])) - { - number += macro_num.fValue[i]; - } - else - { - number.clear(); - break; - } - } - - break; - } - } - - size_t y = 2; - - /* last try */ - for (; y < macro_str.size(); y++) - { - if (isdigit(macro_str[y])) - { - for (size_t x = y; x < macro_str.size(); x++) - { - if (macro_str[x] == ' ') - break; - - number += macro_str[x]; - } - - break; - } - } - - size_t rhs = atol(macro.fValue.c_str()); - size_t lhs = atol(number.c_str()); - - if (lhs == 0) - { - number.clear(); - ++y; - - for (; y < macro_str.size(); y++) - { - if (isdigit(macro_str[y])) - { - for (size_t x = y; x < macro_str.size(); x++) - { - if (macro_str[x] == ' ') - break; - - number += macro_str[x]; - } - - break; - } - } - - lhs = atol(number.c_str()); - } - - if (cond.fType == details::kGreaterThan) - { - if (lhs < rhs) - { - defined = true; - inactive_code = false; - - return 1; - } - - return 0; - } - - if (cond.fType == details::kGreaterEqThan) - { - if (lhs <= rhs) - { - defined = true; - inactive_code = false; - - return 1; - } - - return 0; - } - - if (cond.fType == details::kLesserEqThan) - { - if (lhs >= rhs) - { - defined = true; - inactive_code = false; - - return 1; - } - - return 0; - } - - if (cond.fType == details::kLesserThan) - { - if (lhs > rhs) - { - defined = true; - inactive_code = false; - - return 1; - } - - return 0; - } - - return 0; + details::bpp_macro ¯o, bool &inactive_code, + bool &defined, std::string ¯o_str) { + if (cond.fType == details::kEqual) { + auto substr_macro = + macro_str.substr(macro_str.find(macro.fName) + macro.fName.size()); + + if (substr_macro.find(macro.fValue) != std::string::npos) { + if (macro.fValue == "0") { + defined = false; + inactive_code = true; + + return 1; + } + + defined = true; + inactive_code = false; + + return 1; + } + } else if (cond.fType == details::kNotEqual) { + auto substr_macro = + macro_str.substr(macro_str.find(macro.fName) + macro.fName.size()); + + if (substr_macro.find(macro.fName) != std::string::npos) { + if (substr_macro.find(macro.fValue) != std::string::npos) { + defined = false; + inactive_code = true; + + return 1; + } + + defined = true; + inactive_code = false; + + return 1; + } + + return 0; + } + + auto substr_macro = + macro_str.substr(macro_str.find(macro.fName) + macro.fName.size()); + + std::string number; + + for (auto ¯o_num : kMacros) { + if (substr_macro.find(macro_num.fName) != std::string::npos) { + for (size_t i = 0; i < macro_num.fName.size(); ++i) { + if (isdigit(macro_num.fValue[i])) { + number += macro_num.fValue[i]; + } else { + number.clear(); + break; + } + } + + break; + } + } + + size_t y = 2; + + /* last try */ + for (; y < macro_str.size(); y++) { + if (isdigit(macro_str[y])) { + for (size_t x = y; x < macro_str.size(); x++) { + if (macro_str[x] == ' ') break; + + number += macro_str[x]; + } + + break; + } + } + + size_t rhs = atol(macro.fValue.c_str()); + size_t lhs = atol(number.c_str()); + + if (lhs == 0) { + number.clear(); + ++y; + + for (; y < macro_str.size(); y++) { + if (isdigit(macro_str[y])) { + for (size_t x = y; x < macro_str.size(); x++) { + if (macro_str[x] == ' ') break; + + number += macro_str[x]; + } + + break; + } + } + + lhs = atol(number.c_str()); + } + + if (cond.fType == details::kGreaterThan) { + if (lhs < rhs) { + defined = true; + inactive_code = false; + + return 1; + } + + return 0; + } + + if (cond.fType == details::kGreaterEqThan) { + if (lhs <= rhs) { + defined = true; + inactive_code = false; + + return 1; + } + + return 0; + } + + if (cond.fType == details::kLesserEqThan) { + if (lhs >= rhs) { + defined = true; + inactive_code = false; + + return 1; + } + + return 0; + } + + if (cond.fType == details::kLesserThan) { + if (lhs > rhs) { + defined = true; + inactive_code = false; + + return 1; + } + + return 0; + } + + return 0; } ///////////////////////////////////////////////////////////////////////////////////////// @@ -283,703 +241,582 @@ std::vector<std::string> kAllIncludes; ///////////////////////////////////////////////////////////////////////////////////////// -void bpp_parse_file(std::ifstream &hdr_file, std::ofstream &pp_out) -{ - std::string hdr_line; - std::string line_after_include; - - bool inactive_code = false; - bool defined = false; - - try - { - while (std::getline(hdr_file, hdr_line)) - { - if (hdr_line.find("@bdoc") != std::string::npos) - { - hdr_line.erase(hdr_line.find("@bdoc")); - } - - if (hdr_line[0] == kMacroPrefix && - hdr_line.find("endif") != std::string::npos) - { - if (!defined && - inactive_code) - { - inactive_code = false; - defined = false; - - continue; - } - - continue; - } - - if (!defined && - inactive_code) - { - continue; - } - - if (defined && - inactive_code) - { - continue; - } - - for (auto macro : kMacros) - { - if (ParserKit::find_word(hdr_line, macro.fName) && - hdr_line.find("%def") == std::string::npos) - { - auto substr = hdr_line.substr(hdr_line.find(macro.fName)); - - std::vector<std::string> sym_vec; - std::string sym_str; - - for (auto &subc : substr) - { - if (subc == ',' || - subc == ')') - { - if (sym_str.empty()) - continue; - - sym_vec.push_back(sym_str); - sym_str.clear(); - - continue; - } - - if (isalnum(subc)) - sym_str.push_back(subc); - } - - if (macro.fArgs.size() > 0) - { - - for (auto &item : sym_vec) - { - std::size_t cnt = 0; - - for (auto &arg : macro.fArgs) - { - if (item == arg) - ++cnt; - } - - if (cnt > 1) - { - auto it = std::find(macro.fArgs.begin(), macro.fArgs.end(), item); - - while (it != macro.fArgs.end()) - { - macro.fArgs.erase(it); - it = std::find(macro.fArgs.begin(), macro.fArgs.end(), item); - } - } - } - - if (sym_vec.size() != macro.fArgs.size()) - { - throw std::runtime_error("bpp: arguments count mismatch, except " + std::to_string(sym_vec.size()) + ", got: " + std::to_string(macro.fArgs.size())); - return; - } - - substr = macro.fValue; - - std::size_t cnt = 0UL; - - for (auto &val : macro.fArgs) - { - substr.replace(substr.find(val), val.size(), sym_vec[cnt]); - ++cnt; - } - } - - hdr_line.replace(hdr_line.find(macro.fName), macro.fName.size(), substr); - hdr_line.erase(hdr_line.find(substr) + substr.size()); - } - } - - if (hdr_line[0] == kMacroPrefix && - hdr_line.find("def ") != std::string::npos) - { - auto line_after_define = hdr_line.substr(hdr_line.find("def ") + strlen("def ")); - - std::string macro_value; - std::string macro_key; - - std::size_t pos = 0UL; - - std::vector<std::string> args; - bool on_args = false; - - for (auto &ch : line_after_define) - { - ++pos; - - if (ch == '(') - { - on_args = true; - continue; - } - - if (ch == ')') - { - on_args = false; - continue; - } - - if (ch == '\\') - continue; - - if (on_args) - continue; - - if (ch == ' ') - { - for (size_t i = pos; i < line_after_define.size(); i++) - { - macro_value += line_after_define[i]; - } - - break; - } - - macro_key += ch; - } - - std::vector<std::string> dupls; - std::string str; - - line_after_define.erase(0, line_after_define.find("(") + 1); - - for (auto &subc : line_after_define) - { - if (subc == ',' || - subc == ')') - { - if (str.empty()) - continue; - - dupls.push_back(str); - args.push_back(str); - - str.clear(); - - continue; - } - - if (isalnum(subc)) - str.push_back(subc); - } - - for (auto &dupl : dupls) - { - std::size_t cnt = 0; - - for (auto &arg : args) - { - if (dupl == arg) - ++cnt; - } - - if (cnt > 1) - { - auto it = std::find(args.begin(), args.end(), dupl); - - while (it != args.end()) - { - args.erase(it); - it = std::find(args.begin(), args.end(), dupl); - } - } - } - - details::bpp_macro macro; - - macro.fArgs = args; - macro.fName = macro_key; - macro.fValue = macro_value; - - kMacros.emplace_back(macro); - - continue; - } - - if (hdr_line[0] != kMacroPrefix) - { - if (inactive_code) - { - continue; - } - - for (auto ¯o : kMacros) - { - if (hdr_line.find(macro.fName) != std::string::npos) - { - std::vector<std::string> arg_values; - - if (macro.fArgs.size() > 0) - { - for (size_t i = 0; i < hdr_line.size(); ++i) - { - if (hdr_line[i] == '(') - { - std::string tmp_arg; - - for (size_t x = i; x < hdr_line.size(); x++) - { - if (hdr_line[x] == ')') - break; - - if (hdr_line[x] == ' ') - continue; - - if (hdr_line[i] == '\\') - continue; - - if (hdr_line[x] == ',') - { - arg_values.push_back(tmp_arg); - tmp_arg.clear(); - continue; - } - - tmp_arg += hdr_line[x]; - } - - break; - } - } - - std::string symbol; - - for (char i : macro.fValue) - { - if (i == '(') - break; - - if (i == '\\') - continue; - - symbol += i; - } - - hdr_line.replace(hdr_line.find(macro.fName), macro.fName.size(), symbol); - - size_t x_arg_indx = 0; - - for (size_t i = hdr_line.find(macro.fValue); i < hdr_line.size(); ++i) - { - if (hdr_line.find(macro.fArgs[x_arg_indx]) == i) - { - hdr_line.replace(i, macro.fArgs[x_arg_indx].size(), arg_values[x_arg_indx]); - ++x_arg_indx; - } - } - } - else - { - std::string symbol; - - for (size_t i = 0; i < macro.fValue.size(); i++) - { - if (macro.fValue[i] == ' ') - continue; - - if (macro.fValue[i] == '\\') - continue; - - symbol += macro.fValue[i]; - } - - hdr_line.replace(hdr_line.find(macro.fName), macro.fName.size(), symbol); - } - - break; - } - } - - pp_out << hdr_line << std::endl; - - continue; - } - - if (hdr_line[0] == kMacroPrefix && - hdr_line.find("ifndef") != std::string::npos) - { - auto line_after_ifndef = hdr_line.substr(hdr_line.find("ifndef") + strlen("ifndef") + 1); - std::string macro; - - for (auto &ch : line_after_ifndef) - { - if (ch == ' ') - { - break; - } - - macro += ch; - } - - if (macro == "0") - { - defined = true; - inactive_code = false; - continue; - } - - if (macro == "1") - { - defined = false; - inactive_code = true; - - continue; - } - - bool found = false; - - defined = true; - inactive_code = false; - - for (auto ¯o_ref : kMacros) - { - if (hdr_line.find(macro_ref.fName) != std::string::npos) - { - found = true; - break; - } - } - - if (found) - { - defined = false; - inactive_code = true; - - continue; - } - } - else if (hdr_line[0] == kMacroPrefix && - hdr_line.find("else") != std::string::npos) - { - if (!defined && - inactive_code) - { - inactive_code = false; - defined = true; - - continue; - } - else - { - defined = false; - inactive_code = true; - - continue; - } - } - else if (hdr_line[0] == kMacroPrefix && - hdr_line.find("ifdef") != std::string::npos) - { - auto line_after_ifdef = hdr_line.substr(hdr_line.find("ifdef") + strlen("ifdef") + 1); - std::string macro; - - for (auto &ch : line_after_ifdef) - { - if (ch == ' ') - { - break; - } - - macro += ch; - } - - if (macro == "0") - { - defined = false; - inactive_code = true; - - continue; - } - - if (macro == "1") - { - defined = true; - inactive_code = false; - - continue; - } - - defined = false; - inactive_code = true; - - for (auto ¯o_ref : kMacros) - { - if (hdr_line.find(macro_ref.fName) != std::string::npos) - { - defined = true; - inactive_code = false; - - break; - } - } - } - else if (hdr_line[0] == kMacroPrefix && - hdr_line.find("pragma") != std::string::npos) - { - line_after_include = hdr_line.substr(hdr_line.find("pragma once")); - - // search for this file - auto it = std::find(kAllIncludes.cbegin(), - kAllIncludes.cend(), line_after_include); - - if (it == kAllIncludes.cend()) - { - goto kIncludeFile; - } - } - else if (hdr_line[0] == kMacroPrefix && - hdr_line.find("if") != std::string::npos) - { - inactive_code = true; - - std::vector<details::bpp_macro_condition> bpp_macro_condition_list = { - { - .fType = details::kEqual, - .fTypeName = "==", - }, - { - .fType = details::kNotEqual, - .fTypeName = "!=", - }, - { - .fType = details::kLesserThan, - .fTypeName = "<", - }, - { - .fType = details::kGreaterThan, - .fTypeName = ">", - }, - { - .fType = details::kLesserEqThan, - .fTypeName = "<=", - }, - { - .fType = details::kGreaterEqThan, - .fTypeName = ">=", - }, - }; - - int32_t good_to_go = 0; - - for (auto ¯o_condition : bpp_macro_condition_list) - { - if (hdr_line.find(macro_condition.fTypeName) != std::string::npos) - { - for (auto &found_macro : kMacros) - { - if (hdr_line.find(found_macro.fName) != std::string::npos) - { - good_to_go = bpp_parse_if_condition(macro_condition, found_macro, - inactive_code, defined, - hdr_line); - - break; - } - } - } - } - - if (good_to_go) - continue; - - auto line_after_if = hdr_line.substr(hdr_line.find("if") + strlen("if") + 1); - std::string macro; - - for (auto &ch : line_after_if) - { - if (ch == ' ') - { - break; - } - - macro += ch; - } - - if (macro == "0") - { - defined = false; - inactive_code = true; - continue; - } - - if (macro == "1") - { - defined = true; - inactive_code = false; - - continue; - } - - // last try, is it defined to be one? - for (auto ¯o_ref : kMacros) - { - if (macro_ref.fName.find(macro) != std::string::npos && - macro_ref.fValue == "1") - { - inactive_code = false; - defined = true; - - break; - } - } - } - else if (hdr_line[0] == kMacroPrefix && - hdr_line.find("warning") != std::string::npos) - { - auto line_after_warning = hdr_line.substr(hdr_line.find("warning") + strlen("warning") + 1); - std::string message; - - for (auto &ch : line_after_warning) - { - if (ch == '\r' || - ch == '\n') - { - break; - } - - message += ch; - } - - std::cout << "Warning: " << message << std::endl; - } - else if (hdr_line[0] == kMacroPrefix && - hdr_line.find("error") != std::string::npos) - { - auto line_after_warning = hdr_line.substr(hdr_line.find("error") + strlen("error") + 1); - std::string message; - - for (auto &ch : line_after_warning) - { - if (ch == '\r' || - ch == '\n') - { - break; - } - - message += ch; - } - - throw std::runtime_error("Error: " + message); - } - else if (hdr_line[0] == kMacroPrefix && - hdr_line.find("inc ") != std::string::npos) - { - line_after_include = hdr_line.substr(hdr_line.find("inc ") + strlen("inc ")); - - kIncludeFile: - auto it = std::find(kAllIncludes.cbegin(), - kAllIncludes.cend(), line_after_include); - - if (it != kAllIncludes.cend()) - { - continue; - } - - std::string path; - - kAllIncludes.push_back(line_after_include); - - bool enable = false; - bool not_local = false; - - for (auto &ch : line_after_include) - { - if (ch == ' ') - continue; - - if (ch == '<') - { - not_local = true; - enable = true; - - continue; - } - - if (ch == '\'') - { - enable = true; - continue; - } - - if (enable) - { - if (not_local) - { - if (ch == '>') - break; - } - else - { - if (ch == '\'') - { - break; - } - } - - path += ch; - } - } - - if (not_local) - { - bool open = false; - - for (auto &include : kIncludes) - { - std::string header_path = include; - header_path.push_back('/'); - header_path += path; - - std::ifstream header(header_path); - - if (!header.is_open()) - continue; - - open = true; - - bpp_parse_file(header, pp_out); - - break; - } - - if (!open) - { - throw std::runtime_error("bpp: no such include file: " + path); - } - } - else - { - std::ifstream header(kWorkingDir + path); - - if (!header.is_open()) - throw std::runtime_error("bpp: no such include file: " + path); - - bpp_parse_file(header, pp_out); - } - } - else - { - std::cerr << ("bpp: unknown pre-processor directive, " + hdr_line) << "\n"; - continue; - } - } - } - catch (std::out_of_range &oor) - { - return; - } +void bpp_parse_file(std::ifstream &hdr_file, std::ofstream &pp_out) { + std::string hdr_line; + std::string line_after_include; + + bool inactive_code = false; + bool defined = false; + + try { + while (std::getline(hdr_file, hdr_line)) { + if (hdr_line.find("@bdoc") != std::string::npos) { + hdr_line.erase(hdr_line.find("@bdoc")); + } + + if (hdr_line[0] == kMacroPrefix && + hdr_line.find("endif") != std::string::npos) { + if (!defined && inactive_code) { + inactive_code = false; + defined = false; + + continue; + } + + continue; + } + + if (!defined && inactive_code) { + continue; + } + + if (defined && inactive_code) { + continue; + } + + for (auto macro : kMacros) { + if (ParserKit::find_word(hdr_line, macro.fName) && + hdr_line.find("%def") == std::string::npos) { + auto substr = hdr_line.substr(hdr_line.find(macro.fName)); + + std::vector<std::string> sym_vec; + std::string sym_str; + + for (auto &subc : substr) { + if (subc == ',' || subc == ')') { + if (sym_str.empty()) continue; + + sym_vec.push_back(sym_str); + sym_str.clear(); + + continue; + } + + if (isalnum(subc)) sym_str.push_back(subc); + } + + if (macro.fArgs.size() > 0) { + for (auto &item : sym_vec) { + std::size_t cnt = 0; + + for (auto &arg : macro.fArgs) { + if (item == arg) ++cnt; + } + + if (cnt > 1) { + auto it = + std::find(macro.fArgs.begin(), macro.fArgs.end(), item); + + while (it != macro.fArgs.end()) { + macro.fArgs.erase(it); + it = std::find(macro.fArgs.begin(), macro.fArgs.end(), item); + } + } + } + + if (sym_vec.size() != macro.fArgs.size()) { + throw std::runtime_error( + "bpp: arguments count mismatch, except " + + std::to_string(sym_vec.size()) + + ", got: " + std::to_string(macro.fArgs.size())); + return; + } + + substr = macro.fValue; + + std::size_t cnt = 0UL; + + for (auto &val : macro.fArgs) { + substr.replace(substr.find(val), val.size(), sym_vec[cnt]); + ++cnt; + } + } + + hdr_line.replace(hdr_line.find(macro.fName), macro.fName.size(), + substr); + hdr_line.erase(hdr_line.find(substr) + substr.size()); + } + } + + if (hdr_line[0] == kMacroPrefix && + hdr_line.find("def ") != std::string::npos) { + auto line_after_define = + hdr_line.substr(hdr_line.find("def ") + strlen("def ")); + + std::string macro_value; + std::string macro_key; + + std::size_t pos = 0UL; + + std::vector<std::string> args; + bool on_args = false; + + for (auto &ch : line_after_define) { + ++pos; + + if (ch == '(') { + on_args = true; + continue; + } + + if (ch == ')') { + on_args = false; + continue; + } + + if (ch == '\\') continue; + + if (on_args) continue; + + if (ch == ' ') { + for (size_t i = pos; i < line_after_define.size(); i++) { + macro_value += line_after_define[i]; + } + + break; + } + + macro_key += ch; + } + + std::vector<std::string> dupls; + std::string str; + + line_after_define.erase(0, line_after_define.find("(") + 1); + + for (auto &subc : line_after_define) { + if (subc == ',' || subc == ')') { + if (str.empty()) continue; + + dupls.push_back(str); + args.push_back(str); + + str.clear(); + + continue; + } + + if (isalnum(subc)) str.push_back(subc); + } + + for (auto &dupl : dupls) { + std::size_t cnt = 0; + + for (auto &arg : args) { + if (dupl == arg) ++cnt; + } + + if (cnt > 1) { + auto it = std::find(args.begin(), args.end(), dupl); + + while (it != args.end()) { + args.erase(it); + it = std::find(args.begin(), args.end(), dupl); + } + } + } + + details::bpp_macro macro; + + macro.fArgs = args; + macro.fName = macro_key; + macro.fValue = macro_value; + + kMacros.emplace_back(macro); + + continue; + } + + if (hdr_line[0] != kMacroPrefix) { + if (inactive_code) { + continue; + } + + for (auto ¯o : kMacros) { + if (hdr_line.find(macro.fName) != std::string::npos) { + std::vector<std::string> arg_values; + + if (macro.fArgs.size() > 0) { + for (size_t i = 0; i < hdr_line.size(); ++i) { + if (hdr_line[i] == '(') { + std::string tmp_arg; + + for (size_t x = i; x < hdr_line.size(); x++) { + if (hdr_line[x] == ')') break; + + if (hdr_line[x] == ' ') continue; + + if (hdr_line[i] == '\\') continue; + + if (hdr_line[x] == ',') { + arg_values.push_back(tmp_arg); + tmp_arg.clear(); + continue; + } + + tmp_arg += hdr_line[x]; + } + + break; + } + } + + std::string symbol; + + for (char i : macro.fValue) { + if (i == '(') break; + + if (i == '\\') continue; + + symbol += i; + } + + hdr_line.replace(hdr_line.find(macro.fName), macro.fName.size(), + symbol); + + size_t x_arg_indx = 0; + + for (size_t i = hdr_line.find(macro.fValue); i < hdr_line.size(); + ++i) { + if (hdr_line.find(macro.fArgs[x_arg_indx]) == i) { + hdr_line.replace(i, macro.fArgs[x_arg_indx].size(), + arg_values[x_arg_indx]); + ++x_arg_indx; + } + } + } else { + std::string symbol; + + for (size_t i = 0; i < macro.fValue.size(); i++) { + if (macro.fValue[i] == ' ') continue; + + if (macro.fValue[i] == '\\') continue; + + symbol += macro.fValue[i]; + } + + hdr_line.replace(hdr_line.find(macro.fName), macro.fName.size(), + symbol); + } + + break; + } + } + + pp_out << hdr_line << std::endl; + + continue; + } + + if (hdr_line[0] == kMacroPrefix && + hdr_line.find("ifndef") != std::string::npos) { + auto line_after_ifndef = + hdr_line.substr(hdr_line.find("ifndef") + strlen("ifndef") + 1); + std::string macro; + + for (auto &ch : line_after_ifndef) { + if (ch == ' ') { + break; + } + + macro += ch; + } + + if (macro == "0") { + defined = true; + inactive_code = false; + continue; + } + + if (macro == "1") { + defined = false; + inactive_code = true; + + continue; + } + + bool found = false; + + defined = true; + inactive_code = false; + + for (auto ¯o_ref : kMacros) { + if (hdr_line.find(macro_ref.fName) != std::string::npos) { + found = true; + break; + } + } + + if (found) { + defined = false; + inactive_code = true; + + continue; + } + } else if (hdr_line[0] == kMacroPrefix && + hdr_line.find("else") != std::string::npos) { + if (!defined && inactive_code) { + inactive_code = false; + defined = true; + + continue; + } else { + defined = false; + inactive_code = true; + + continue; + } + } else if (hdr_line[0] == kMacroPrefix && + hdr_line.find("ifdef") != std::string::npos) { + auto line_after_ifdef = + hdr_line.substr(hdr_line.find("ifdef") + strlen("ifdef") + 1); + std::string macro; + + for (auto &ch : line_after_ifdef) { + if (ch == ' ') { + break; + } + + macro += ch; + } + + if (macro == "0") { + defined = false; + inactive_code = true; + + continue; + } + + if (macro == "1") { + defined = true; + inactive_code = false; + + continue; + } + + defined = false; + inactive_code = true; + + for (auto ¯o_ref : kMacros) { + if (hdr_line.find(macro_ref.fName) != std::string::npos) { + defined = true; + inactive_code = false; + + break; + } + } + } else if (hdr_line[0] == kMacroPrefix && + hdr_line.find("pragma") != std::string::npos) { + line_after_include = hdr_line.substr(hdr_line.find("pragma once")); + + // search for this file + auto it = std::find(kAllIncludes.cbegin(), kAllIncludes.cend(), + line_after_include); + + if (it == kAllIncludes.cend()) { + goto kIncludeFile; + } + } else if (hdr_line[0] == kMacroPrefix && + hdr_line.find("if") != std::string::npos) { + inactive_code = true; + + std::vector<details::bpp_macro_condition> bpp_macro_condition_list = { + { + .fType = details::kEqual, + .fTypeName = "==", + }, + { + .fType = details::kNotEqual, + .fTypeName = "!=", + }, + { + .fType = details::kLesserThan, + .fTypeName = "<", + }, + { + .fType = details::kGreaterThan, + .fTypeName = ">", + }, + { + .fType = details::kLesserEqThan, + .fTypeName = "<=", + }, + { + .fType = details::kGreaterEqThan, + .fTypeName = ">=", + }, + }; + + int32_t good_to_go = 0; + + for (auto ¯o_condition : bpp_macro_condition_list) { + if (hdr_line.find(macro_condition.fTypeName) != std::string::npos) { + for (auto &found_macro : kMacros) { + if (hdr_line.find(found_macro.fName) != std::string::npos) { + good_to_go = + bpp_parse_if_condition(macro_condition, found_macro, + inactive_code, defined, hdr_line); + + break; + } + } + } + } + + if (good_to_go) continue; + + auto line_after_if = + hdr_line.substr(hdr_line.find("if") + strlen("if") + 1); + std::string macro; + + for (auto &ch : line_after_if) { + if (ch == ' ') { + break; + } + + macro += ch; + } + + if (macro == "0") { + defined = false; + inactive_code = true; + continue; + } + + if (macro == "1") { + defined = true; + inactive_code = false; + + continue; + } + + // last try, is it defined to be one? + for (auto ¯o_ref : kMacros) { + if (macro_ref.fName.find(macro) != std::string::npos && + macro_ref.fValue == "1") { + inactive_code = false; + defined = true; + + break; + } + } + } else if (hdr_line[0] == kMacroPrefix && + hdr_line.find("warning") != std::string::npos) { + auto line_after_warning = + hdr_line.substr(hdr_line.find("warning") + strlen("warning") + 1); + std::string message; + + for (auto &ch : line_after_warning) { + if (ch == '\r' || ch == '\n') { + break; + } + + message += ch; + } + + std::cout << "Warning: " << message << std::endl; + } else if (hdr_line[0] == kMacroPrefix && + hdr_line.find("error") != std::string::npos) { + auto line_after_warning = + hdr_line.substr(hdr_line.find("error") + strlen("error") + 1); + std::string message; + + for (auto &ch : line_after_warning) { + if (ch == '\r' || ch == '\n') { + break; + } + + message += ch; + } + + throw std::runtime_error("Error: " + message); + } else if (hdr_line[0] == kMacroPrefix && + hdr_line.find("inc ") != std::string::npos) { + line_after_include = + hdr_line.substr(hdr_line.find("inc ") + strlen("inc ")); + + kIncludeFile: + auto it = std::find(kAllIncludes.cbegin(), kAllIncludes.cend(), + line_after_include); + + if (it != kAllIncludes.cend()) { + continue; + } + + std::string path; + + kAllIncludes.push_back(line_after_include); + + bool enable = false; + bool not_local = false; + + for (auto &ch : line_after_include) { + if (ch == ' ') continue; + + if (ch == '<') { + not_local = true; + enable = true; + + continue; + } + + if (ch == '\'') { + enable = true; + continue; + } + + if (enable) { + if (not_local) { + if (ch == '>') break; + } else { + if (ch == '\'') { + break; + } + } + + path += ch; + } + } + + if (not_local) { + bool open = false; + + for (auto &include : kIncludes) { + std::string header_path = include; + header_path.push_back('/'); + header_path += path; + + std::ifstream header(header_path); + + if (!header.is_open()) continue; + + open = true; + + bpp_parse_file(header, pp_out); + + break; + } + + if (!open) { + throw std::runtime_error("bpp: no such include file: " + path); + } + } else { + std::ifstream header(kWorkingDir + path); + + if (!header.is_open()) + throw std::runtime_error("bpp: no such include file: " + path); + + bpp_parse_file(header, pp_out); + } + } else { + std::cerr << ("bpp: unknown pre-processor directive, " + hdr_line) + << "\n"; + continue; + } + } + } catch (std::out_of_range &oor) { + return; + } } ///////////////////////////////////////////////////////////////////////////////////////// @@ -988,140 +825,119 @@ void bpp_parse_file(std::ifstream &hdr_file, std::ofstream &pp_out) ///////////////////////////////////////////////////////////////////////////////////////// -MPCC_MODULE(MPUXPreprocessor) -{ - try - { - bool skip = false; - bool double_skip = false; - - details::bpp_macro macro_1; - macro_1.fName = "__true"; - macro_1.fValue = "1"; - - kMacros.push_back(macro_1); - - details::bpp_macro macro_0; - macro_0.fName = "__false"; - macro_0.fValue = "0"; - - kMacros.push_back(macro_0); - - for (auto index = 1UL; index < argc; ++index) - { - if (skip) - { - skip = false; - continue; - } - - if (double_skip) - { - ++index; - double_skip = false; - continue; - } - - if (argv[index][0] == '-') - { - if (strcmp(argv[index], "--version") == 0) - { - printf("%s\n", "bpp v1.11, (c) Mahrouss Logic"); - return 0; - } - - if (strcmp(argv[index], "-h") == 0 || - strcmp(argv[index], "--help") == 0) - { - printf("%s\n", "bpp v1.11, (c) Mahrouss Logic"); - printf("%s\n", "--working-dir: set directory to working path."); - printf("%s\n", "--include-dir: add directory to include path."); - printf("%s\n", "--define: define macro."); - printf("%s\n", "--version: print the version."); - - return 0; - } - - if (strcmp(argv[index], "--include-dir") == 0) - { - std::string inc = argv[index + 1]; - - skip = true; - - kIncludes.push_back(inc); - } - - if (strcmp(argv[index], "--working-dir") == 0) - { - std::string inc = argv[index + 1]; - skip = true; - kWorkingDir = inc; - } - - if (strcmp(argv[index], "--define") == 0 && - argv[index + 1] != nullptr && - argv[index + 2] != nullptr) - { - std::string macro_key = argv[index + 1]; - - std::string macro_value; - bool is_string = false; - - for (int argv_find_len = 0; - argv_find_len < strlen(argv[index]); - ++argv_find_len) - { - if (!isdigit(argv[index][argv_find_len])) - { - is_string = true; - macro_value += "\""; - - break; - } - } - - macro_value += argv[index + 2]; - - if (is_string) - macro_value += "\""; - - details::bpp_macro macro; - macro.fName = macro_key; - macro.fValue = macro_value; - - kMacros.push_back(macro); - - double_skip = true; - } - - continue; - } - - kFiles.emplace_back(argv[index]); - } - - if (kFiles.empty()) - return CXXKIT_EXEC_ERROR; - - for (auto &file : kFiles) - { - if (!std::filesystem::exists(file)) - continue; - - std::ifstream file_descriptor(file); - std::ofstream file_descriptor_pp(file + ".pp"); - - bpp_parse_file(file_descriptor, file_descriptor_pp); - } - - return 0; - } - catch (const std::runtime_error &e) - { - std::cout << e.what() << '\n'; - } - - return 0; +MPCC_MODULE(MPUXPreprocessor) { + try { + bool skip = false; + bool double_skip = false; + + details::bpp_macro macro_1; + macro_1.fName = "__true"; + macro_1.fValue = "1"; + + kMacros.push_back(macro_1); + + details::bpp_macro macro_0; + macro_0.fName = "__false"; + macro_0.fValue = "0"; + + kMacros.push_back(macro_0); + + for (auto index = 1UL; index < argc; ++index) { + if (skip) { + skip = false; + continue; + } + + if (double_skip) { + ++index; + double_skip = false; + continue; + } + + if (argv[index][0] == '-') { + if (strcmp(argv[index], "--version") == 0) { + printf("%s\n", "bpp v1.11, (c) Mahrouss Logic"); + return 0; + } + + if (strcmp(argv[index], "-h") == 0 || + strcmp(argv[index], "--help") == 0) { + printf("%s\n", "bpp v1.11, (c) Mahrouss Logic"); + printf("%s\n", "--working-dir: set directory to working path."); + printf("%s\n", "--include-dir: add directory to include path."); + printf("%s\n", "--define: define macro."); + printf("%s\n", "--version: print the version."); + + return 0; + } + + if (strcmp(argv[index], "--include-dir") == 0) { + std::string inc = argv[index + 1]; + + skip = true; + + kIncludes.push_back(inc); + } + + if (strcmp(argv[index], "--working-dir") == 0) { + std::string inc = argv[index + 1]; + skip = true; + kWorkingDir = inc; + } + + if (strcmp(argv[index], "--define") == 0 && + argv[index + 1] != nullptr && argv[index + 2] != nullptr) { + std::string macro_key = argv[index + 1]; + + std::string macro_value; + bool is_string = false; + + for (int argv_find_len = 0; argv_find_len < strlen(argv[index]); + ++argv_find_len) { + if (!isdigit(argv[index][argv_find_len])) { + is_string = true; + macro_value += "\""; + + break; + } + } + + macro_value += argv[index + 2]; + + if (is_string) macro_value += "\""; + + details::bpp_macro macro; + macro.fName = macro_key; + macro.fValue = macro_value; + + kMacros.push_back(macro); + + double_skip = true; + } + + continue; + } + + kFiles.emplace_back(argv[index]); + } + + if (kFiles.empty()) return CXXKIT_EXEC_ERROR; + + for (auto &file : kFiles) { + if (!std::filesystem::exists(file)) continue; + + std::ifstream file_descriptor(file); + std::ofstream file_descriptor_pp(file + ".pp"); + + bpp_parse_file(file_descriptor, file_descriptor_pp); + } + + return 0; + } catch (const std::runtime_error &e) { + std::cout << e.what() << '\n'; + } + + return 0; } -// Last rev 8-1-24
\ No newline at end of file +// Last rev 8-1-24 diff --git a/Private/Toolchain/ccplus.cc b/Private/Toolchain/ccplus.cc index 91e8a28..092e30a 100644 --- a/Private/Toolchain/ccplus.cc +++ b/Private/Toolchain/ccplus.cc @@ -9,16 +9,16 @@ /// bugs: ? +#include <uuid/uuid.h> + +#include <CompilerKit/AsmKit/Arch/64x0.hpp> +#include <CompilerKit/ParserKit.hpp> #include <cstdio> -#include <vector> -#include <string> #include <fstream> #include <iostream> -#include <stack> +#include <string> #include <utility> -#include <uuid/uuid.h> -#include <CompilerKit/AsmKit/Arch/64x0.hpp> -#include <CompilerKit/ParserKit.hpp> +#include <vector> #define kOk 0 @@ -46,82 +46,74 @@ ///////////////////////////////////// -namespace detail -{ - struct CompilerRegisterMap final - { - std::string fName; - std::string fReg; - }; +namespace detail { +struct CompilerRegisterMap final { + std::string fName; + std::string fReg; +}; - // \brief Offset based struct/class - struct CompilerStructMap final - { - std::string fName; - std::string fReg; - - // offset counter - std::size_t fOffsetsCnt; - - // offset array - std::vector<std::pair<Int32, std::string>> fOffsets; - }; +// \brief Offset based struct/class +struct CompilerStructMap final { + std::string fName; + std::string fReg; - struct CompilerState final - { - std::vector<ParserKit::SyntaxLeafList> fSyntaxTreeList; - std::vector<CompilerRegisterMap> kStackFrame; - std::vector<CompilerStructMap> kStructMap; - ParserKit::SyntaxLeafList* fSyntaxTree{ nullptr }; - std::unique_ptr<std::ofstream> fOutputAssembly; - std::string fLastFile; - std::string fLastError; - bool kVerbose; - }; -} + // offset counter + std::size_t fOffsetsCnt; + + // offset array + std::vector<std::pair<Int32, std::string>> fOffsets; +}; + +struct CompilerState final { + std::vector<ParserKit::SyntaxLeafList> fSyntaxTreeList; + std::vector<CompilerRegisterMap> kStackFrame; + std::vector<CompilerStructMap> kStructMap; + ParserKit::SyntaxLeafList* fSyntaxTree{nullptr}; + std::unique_ptr<std::ofstream> fOutputAssembly; + std::string fLastFile; + std::string fLastError; + bool kVerbose; +}; +} // namespace detail static detail::CompilerState kState; static SizeType kErrorLimit = 100; static Int32 kAcceptableErrors = 0; -namespace detail -{ - void print_error(std::string reason, std::string file) noexcept - { - if (reason[0] == '\n') - reason.erase(0, 1); - - if (file.find(".pp") != std::string::npos) - { - file.erase(file.find(".pp"), 3); - } +namespace detail { +void print_error(std::string reason, std::string file) noexcept { + if (reason[0] == '\n') reason.erase(0, 1); - if (kState.fLastFile != file) - { - std::cout << kRed << "[ ccplus ] " << kWhite << ((file == "ccplus") ? "internal compiler error " : ("in file, " + file)) << kBlank << std::endl; - std::cout << kRed << "[ ccplus ] " << kWhite << reason << kBlank << std::endl; + if (file.find(".pp") != std::string::npos) { + file.erase(file.find(".pp"), 3); + } - kState.fLastFile = file; - } - else - { - std::cout << kRed << "[ ccplus ] [ " << kState.fLastFile << " ] " << kWhite << reason << kBlank << std::endl; - } + if (kState.fLastFile != file) { + std::cout << kRed << "[ ccplus ] " << kWhite + << ((file == "ccplus") ? "internal compiler error " + : ("in file, " + file)) + << kBlank << std::endl; + std::cout << kRed << "[ ccplus ] " << kWhite << reason << kBlank + << std::endl; - if (kAcceptableErrors > kErrorLimit) - std::exit(3); + kState.fLastFile = file; + } else { + std::cout << kRed << "[ ccplus ] [ " << kState.fLastFile << " ] " << kWhite + << reason << kBlank << std::endl; + } - ++kAcceptableErrors; - } + if (kAcceptableErrors > kErrorLimit) std::exit(3); - struct CompilerType - { - std::string fName; - std::string fValue; - }; + ++kAcceptableErrors; } +struct CompilerType { + std::string fName; + std::string fValue; +}; +} // namespace detail + ///////////////////////////////////////////////////////////////////////////////////////// // Target architecture. @@ -155,41 +147,36 @@ static bool kInBraces = false; static size_t kBracesCount = 0UL; /* @brief C compiler backend for Mahrouss Logic C */ -class CompilerBackendClang final : public ParserKit::CompilerBackend -{ -public: - explicit CompilerBackendClang() = default; - ~CompilerBackendClang() override = default; +class CompilerBackendClang final : public ParserKit::CompilerBackend { + public: + explicit CompilerBackendClang() = default; + ~CompilerBackendClang() override = default; - CXXKIT_COPY_DEFAULT(CompilerBackendClang); + CXXKIT_COPY_DEFAULT(CompilerBackendClang); - bool Compile(const std::string& text, const char* file) override; - - const char* Language() override { return "64x0 C++, Generic MP/UX/h-core target."; } + bool Compile(const std::string& text, const char* file) override; + const char* Language() override { + return "64x0 C++, Generic MP/UX/h-core target."; + } }; /// compiler variables -static CompilerBackendClang* kCompilerBackend = nullptr; -static std::vector<detail::CompilerType> kCompilerVariables; -static std::vector<std::string> kCompilerFunctions; +static CompilerBackendClang* kCompilerBackend = nullptr; +static std::vector<detail::CompilerType> kCompilerVariables; +static std::vector<std::string> kCompilerFunctions; /// detail namespaces -namespace detail -{ - union number_cast final - { - number_cast(UInt64 raw) - : raw(raw) - {} - - char number[8]; - UInt64 raw; - - }; -} +namespace detail { +union number_cast final { + number_cast(UInt64 raw) : raw(raw) {} + + char number[8]; + UInt64 raw; +}; +} // namespace detail ///////////////////////////////////////////////////////////////////////////////////////// @@ -198,46 +185,41 @@ namespace detail ///////////////////////////////////////////////////////////////////////////////////////// -bool CompilerBackendClang::Compile(const std::string& text, const char* file) -{ - if (text.empty()) - return false; +bool CompilerBackendClang::Compile(const std::string& text, const char* file) { + if (text.empty()) return false; - // if (expr) - // int name = expr; - // expr; + // if (expr) + // int name = expr; + // expr; - std::size_t index = 0UL; + std::size_t index = 0UL; - auto syntax_tree = ParserKit::SyntaxLeafList::SyntaxLeaf(); + auto syntax_tree = ParserKit::SyntaxLeafList::SyntaxLeaf(); - syntax_tree.fUserData = text; - kState.fSyntaxTree->fLeafList.emplace_back(syntax_tree); + syntax_tree.fUserData = text; + kState.fSyntaxTree->fLeafList.emplace_back(syntax_tree); - std::string text_cpy = text; + std::string text_cpy = text; - std::vector<std::pair<std::string, std::size_t>> keywords_list; + std::vector<std::pair<std::string, std::size_t>> keywords_list; - for (auto& keyword : kKeywords) - { - while (text_cpy.find(keyword) != std::string::npos) - { - keywords_list.emplace_back(std::make_pair(keyword, index)); - ++index; + for (auto& keyword : kKeywords) { + while (text_cpy.find(keyword) != std::string::npos) { + keywords_list.emplace_back(std::make_pair(keyword, index)); + ++index; - text_cpy.erase(text_cpy.find(keyword), keyword.size()); - } + text_cpy.erase(text_cpy.find(keyword), keyword.size()); } + } - // TODO: sort keywords + // TODO: sort keywords - for (auto& keyword : keywords_list) - { - syntax_tree.fUserData = keyword.first; - kState.fSyntaxTree->fLeafList.emplace_back(syntax_tree); - } + for (auto& keyword : keywords_list) { + syntax_tree.fUserData = keyword.first; + kState.fSyntaxTree->fLeafList.emplace_back(syntax_tree); + } - return true; + return true; } ///////////////////////////////////////////////////////////////////////////////////////// @@ -248,551 +230,483 @@ bool CompilerBackendClang::Compile(const std::string& text, const char* file) ///////////////////////////////////////////////////////////////////////////////////////// -class AssemblyMountpointClang final : public CompilerKit::AssemblyMountpoint -{ -public: - explicit AssemblyMountpointClang() = default; - ~AssemblyMountpointClang() override = default; +class AssemblyMountpointClang final : public CompilerKit::AssemblyMountpoint { + public: + explicit AssemblyMountpointClang() = default; + ~AssemblyMountpointClang() override = default; - CXXKIT_COPY_DEFAULT(AssemblyMountpointClang); + CXXKIT_COPY_DEFAULT(AssemblyMountpointClang); - [[maybe_unused]] static Int32 Arch() noexcept { return CompilerKit::AssemblyFactory::kArchRISCV; } + [[maybe_unused]] static Int32 Arch() noexcept { + return CompilerKit::AssemblyFactory::kArchRISCV; + } - Int32 CompileToFormat(CompilerKit::StringView& src, Int32 arch) override - { - if (arch != AssemblyMountpointClang::Arch()) - return -1; + Int32 CompileToFormat(CompilerKit::StringView& src, Int32 arch) override { + if (arch != AssemblyMountpointClang::Arch()) return -1; - if (kCompilerBackend == nullptr) - return -1; + if (kCompilerBackend == nullptr) return -1; - /* @brief copy contents wihtout extension */ - std::string src_file = src.CData(); - std::ifstream src_fp = std::ifstream(src_file, std::ios::in); - std::string dest; + /* @brief copy contents wihtout extension */ + std::string src_file = src.CData(); + std::ifstream src_fp = std::ifstream(src_file, std::ios::in); + std::string dest; - for (auto& ch : src_file) - { - if (ch == '.') - { - break; - } + for (auto& ch : src_file) { + if (ch == '.') { + break; + } - dest += ch; - } + dest += ch; + } - /* According to pef abi. */ + /* According to pef abi. */ - std::vector<const char*> exts = kAsmFileExts; - dest += exts[0]; + std::vector<const char*> exts = kAsmFileExts; + dest += exts[0]; - kState.fOutputAssembly = std::make_unique<std::ofstream>(dest); + kState.fOutputAssembly = std::make_unique<std::ofstream>(dest); - auto fmt = CompilerKit::current_date(); + auto fmt = CompilerKit::current_date(); - (*kState.fOutputAssembly) << "# Path: " << src_file << "\n"; - (*kState.fOutputAssembly) << "# Language: RISC 64x0 MP-UX Assembly (Generated from C++)\n"; - (*kState.fOutputAssembly) << "# Build Date: " << fmt << "\n\n"; + (*kState.fOutputAssembly) << "# Path: " << src_file << "\n"; + (*kState.fOutputAssembly) + << "# Language: RISC 64x0 MP-UX Assembly (Generated from C++)\n"; + (*kState.fOutputAssembly) << "# Build Date: " << fmt << "\n\n"; - ParserKit::SyntaxLeafList syntax; + ParserKit::SyntaxLeafList syntax; - kState.fSyntaxTreeList.emplace_back(syntax); - kState.fSyntaxTree = &kState.fSyntaxTreeList[kState.fSyntaxTreeList.size() - 1]; + kState.fSyntaxTreeList.emplace_back(syntax); + kState.fSyntaxTree = + &kState.fSyntaxTreeList[kState.fSyntaxTreeList.size() - 1]; - std::string source; + std::string source; - while (std::getline(src_fp, source)) - { - // compile into AST. - kCompilerBackend->Compile(source.c_str(), src.CData()); - } + while (std::getline(src_fp, source)) { + // compile into AST. + kCompilerBackend->Compile(source.c_str(), src.CData()); + } + + if (kAcceptableErrors > 0) return -1; - if (kAcceptableErrors > 0) - return -1; + std::vector<std::string> lines; - std::vector<std::string> lines; - - // \brief compiler scope type. - struct scope_type - { - std::vector<std::string> vals; - std::size_t reg_cnt{ kRegisterCounter }; - std::size_t id{ 0 }; + // \brief compiler scope type. + struct scope_type { + std::vector<std::string> vals; + std::size_t reg_cnt{kRegisterCounter}; + std::size_t id{0}; + + bool operator==(const scope_type& typ) const { return typ.id == id; } + }; - bool operator==(const scope_type& typ) const { return typ.id == id; } - }; + std::vector<scope_type> scope; + scope.emplace_back(); - std::vector<scope_type> scope; + bool found_type = false; + bool is_pointer = false; + bool found_expr = false; + bool found_func = false; + bool is_access_field = false; + std::string type; + + for (auto& leaf : kState.fSyntaxTree->fLeafList) { + if (leaf.fUserData == "{") { scope.emplace_back(); + } + + if (leaf.fUserData == "{") { + kRegisterCounter = kStartUsable; + scope.pop_back(); + } + + if (leaf.fUserData == "int" || leaf.fUserData == "long" || + leaf.fUserData == "unsigned" || leaf.fUserData == "short" || + leaf.fUserData == "char" || leaf.fUserData == "struct" || + leaf.fUserData == "class") { + type += leaf.fUserData; + found_type = true; + } + + if (leaf.fUserData == "(") { + if (found_type) { + found_expr = true; + found_type = false; + is_pointer = false; + } + } - bool found_type = false; - bool is_pointer = false; - bool found_expr = false; - bool found_func = false; - bool is_access_field = false; - std::string type; - - for (auto& leaf : kState.fSyntaxTree->fLeafList) - { - if (leaf.fUserData == "{") - { - scope.emplace_back(); - } + if (leaf.fUserData == ";") { + is_access_field = false; + } - if (leaf.fUserData == "{") - { - kRegisterCounter = kStartUsable; - scope.pop_back(); - } + if (leaf.fUserData.find(" this") != std::string::npos) { + leaf.fUserData.replace(leaf.fUserData.find(" this"), strlen(" this"), + "r6"); + is_access_field = true; + } - if (leaf.fUserData == "int" || - leaf.fUserData == "long" || - leaf.fUserData == "unsigned" || - leaf.fUserData == "short" || - leaf.fUserData == "char" || - leaf.fUserData == "struct" || - leaf.fUserData == "class") - { - type += leaf.fUserData; - found_type = true; - } + if (leaf.fUserData.find("->") != std::string::npos) { + leaf.fUserData.replace(leaf.fUserData.find("->"), strlen("->"), ", "); - if (leaf.fUserData == "(") - { - if (found_type) - { - found_expr = true; - found_type = false; - is_pointer = false; - } - } + is_access_field = true; + } - if (leaf.fUserData == ";") - { - is_access_field = false; - } + if (leaf.fUserData == ")") { + if (found_expr) { + found_expr = false; + is_pointer = false; + } else { + leaf.fUserValue = "export .text _CppZ_MPUX_"; - if (leaf.fUserData.find(" this") != std::string::npos) - { - leaf.fUserData.replace(leaf.fUserData.find(" this"), strlen(" this"), "r6"); - is_access_field = true; - } + for (auto& line : lines) { + if (line.find(type) != std::string::npos && + line.find("(") != std::string::npos) { + auto fn_name = line.substr(line.find(type), line.find("(")); - if (leaf.fUserData.find("->") != std::string::npos) - { - leaf.fUserData.replace(leaf.fUserData.find("->"), strlen("->"), ", "); - - is_access_field = true; - } + while (fn_name.find(' ') != std::string::npos) + fn_name.replace(fn_name.find(' '), 1, "@"); - if (leaf.fUserData == ")") - { - if (found_expr) - { - found_expr = false; - is_pointer = false; - } - else - { - leaf.fUserValue = "export .text _CppZ_MPUX_"; - - for (auto& line : lines) - { - if (line.find(type) != std::string::npos && - line.find("(") != std::string::npos) - { - auto fn_name = line.substr(line.find(type), line.find("(")); - - while (fn_name.find(' ') != std::string::npos) - fn_name.replace(fn_name.find(' '), 1, "@"); - - leaf.fUserValue += fn_name; - - break; - } - } - - leaf.fUserValue += "\n"; - - found_func = true; - } + leaf.fUserValue += fn_name; + + break; } + } - if (leaf.fUserData == ",") - { - if (is_pointer) - { - is_pointer = false; - } + leaf.fUserValue += "\n"; - auto& front = scope.front(); + found_func = true; + } + } - std::string reg = "r"; - reg += std::to_string(front.reg_cnt); - ++front.reg_cnt; + if (leaf.fUserData == ",") { + if (is_pointer) { + is_pointer = false; + } - front.vals.push_back(reg); - } + auto& front = scope.front(); - if (leaf.fUserData == "*" || - leaf.fUserData == "&") - { - if (found_type && !found_expr) - is_pointer = true; - } + std::string reg = "r"; + reg += std::to_string(front.reg_cnt); + ++front.reg_cnt; - if (leaf.fUserData == "=") - { - if (found_type) - { - auto& front = scope.front(); + front.vals.push_back(reg); + } - std::string reg = "r"; - reg += std::to_string(front.reg_cnt); - ++front.reg_cnt; + if (leaf.fUserData == "*" || leaf.fUserData == "&") { + if (found_type && !found_expr) is_pointer = true; + } - front.vals.push_back(reg); + if (leaf.fUserData == "=") { + if (found_type) { + auto& front = scope.front(); - leaf.fUserValue = !is_pointer ? "ldw %s, %s1\n" : "lda %s, %s1\n"; + std::string reg = "r"; + reg += std::to_string(front.reg_cnt); + ++front.reg_cnt; - for (auto& ln : lines) - { - if (ln.find(leaf.fUserData) != std::string::npos && - ln.find(";") != std::string::npos) - { - auto val = ln.substr(ln.find(leaf.fUserData) + leaf.fUserData.size()); + front.vals.push_back(reg); - if (val.find(";") != std::string::npos) - val.erase(val.find(";"), 1); + leaf.fUserValue = !is_pointer ? "ldw %s, %s1\n" : "lda %s, %s1\n"; - while (val.find(" ") != std::string::npos) - val.erase(val.find(" "), 1); + for (auto& ln : lines) { + if (ln.find(leaf.fUserData) != std::string::npos && + ln.find(";") != std::string::npos) { + auto val = + ln.substr(ln.find(leaf.fUserData) + leaf.fUserData.size()); - if (isalnum(val[0]) && - !isdigit(val[0]) && - ln.find("r6") == std::string::npos) - val.insert(0, "import "); + if (val.find(";") != std::string::npos) + val.erase(val.find(";"), 1); - leaf.fUserValue.replace(leaf.fUserValue.find("%s1"), strlen("%s1"), val); - } - } + while (val.find(" ") != std::string::npos) + val.erase(val.find(" "), 1); - leaf.fUserValue.replace(leaf.fUserValue.find("%s"), strlen("%s"), reg); + if (isalnum(val[0]) && !isdigit(val[0]) && + ln.find("r6") == std::string::npos) + val.insert(0, "import "); - found_type = false; - } - else - { - leaf.fUserValue = !is_pointer ? "ldw %s, %s1\n" : "lda 0(%s), %s1\n"; - - for (auto& ln : lines) - { - if (ln.find(leaf.fUserData) != std::string::npos && - ln.find(";") != std::string::npos) - { - std::string nm; - for (auto i = ln.find('=') + 1; i < ln.size(); ++i) - { - if (ln[i] == ';') - break; - - nm.push_back(ln[i]); - } - - if (!nm.empty()) - { - leaf.fUserValue.replace(leaf.fUserValue.find("%s1"), strlen("%s1"), nm); - break; - } - } - } - - auto& front = scope.front(); - - std::string reg = "r"; - reg += std::to_string(front.reg_cnt); - ++front.reg_cnt; - - leaf.fUserValue.replace(leaf.fUserValue.find("%s"), strlen("%s"), reg); - - front.vals.push_back(reg); - - if (is_pointer) - { - is_pointer = false; - } - } + leaf.fUserValue.replace(leaf.fUserValue.find("%s1"), + strlen("%s1"), val); } + } - if (leaf.fUserData == "return") - { - leaf.fUserValue = "mv r1, %s\njlr"; - - if (!lines.empty()) - { - for (auto& ln : lines) - { - if (ln.find(leaf.fUserData) != std::string::npos && - ln.find(";") != std::string::npos) - { - auto val = ln.substr(ln.find(leaf.fUserData) + leaf.fUserData.size()); - val.erase(val.find(";"), 1); - - std::string val_reg; - std::size_t reg_cnt = kRegisterCounter; - - for (int i = ln.find(leaf.fUserData) + leaf.fUserData.size(); i < ln.size(); ++i) - { - try - { - if (ln[i] == ',' || - ln[i] == '+' || - ln[i] == '/' || - ln[i] == '-' || - ln[i] == '*' || - ln[i] == '|' || - ln[i] == '&' || - ln[i] == '&' || - ln[i] == '|' || - ln[i] == ';') - { - val.replace(val.find(val_reg), val_reg.size(), "r" + std::to_string(reg_cnt)); - val_reg.clear(); - ++reg_cnt; - - continue; - } - } - catch (...) - { - - } - - if (isalnum(ln[i])) - val_reg += ln[i]; - } - - while (val.find(" ") != std::string::npos) - val.erase(val.find(" "), 1); - - leaf.fUserValue.replace(leaf.fUserValue.find("%s"), strlen("%s"), val); - } - } - } - else - { - leaf.fUserValue.replace(leaf.fUserValue.find("%s"), strlen("%s"), "0"); - } + leaf.fUserValue.replace(leaf.fUserValue.find("%s"), strlen("%s"), + reg); + + found_type = false; + } else { + leaf.fUserValue = !is_pointer ? "ldw %s, %s1\n" : "lda 0(%s), %s1\n"; + + for (auto& ln : lines) { + if (ln.find(leaf.fUserData) != std::string::npos && + ln.find(";") != std::string::npos) { + std::string nm; + for (auto i = ln.find('=') + 1; i < ln.size(); ++i) { + if (ln[i] == ';') break; - continue; + nm.push_back(ln[i]); + } + + if (!nm.empty()) { + leaf.fUserValue.replace(leaf.fUserValue.find("%s1"), + strlen("%s1"), nm); + break; + } } + } + + auto& front = scope.front(); + + std::string reg = "r"; + reg += std::to_string(front.reg_cnt); + ++front.reg_cnt; - lines.emplace_back(leaf.fUserData); + leaf.fUserValue.replace(leaf.fUserValue.find("%s"), strlen("%s"), + reg); + + front.vals.push_back(reg); + + if (is_pointer) { + is_pointer = false; + } } + } + + if (leaf.fUserData == "return") { + leaf.fUserValue = "mv r1, %s\njlr"; + + if (!lines.empty()) { + for (auto& ln : lines) { + if (ln.find(leaf.fUserData) != std::string::npos && + ln.find(";") != std::string::npos) { + auto val = + ln.substr(ln.find(leaf.fUserData) + leaf.fUserData.size()); + val.erase(val.find(";"), 1); + + std::string val_reg; + std::size_t reg_cnt = kRegisterCounter; + + for (int i = ln.find(leaf.fUserData) + leaf.fUserData.size(); + i < ln.size(); ++i) { + try { + if (ln[i] == ',' || ln[i] == '+' || ln[i] == '/' || + ln[i] == '-' || ln[i] == '*' || ln[i] == '|' || + ln[i] == '&' || ln[i] == '&' || ln[i] == '|' || + ln[i] == ';') { + val.replace(val.find(val_reg), val_reg.size(), + "r" + std::to_string(reg_cnt)); + val_reg.clear(); + ++reg_cnt; + + continue; + } + } catch (...) { + } - for (auto& leaf : kState.fSyntaxTree->fLeafList) - { - (*kState.fOutputAssembly) << leaf.fUserValue; + if (isalnum(ln[i])) val_reg += ln[i]; + } + + while (val.find(" ") != std::string::npos) + val.erase(val.find(" "), 1); + + leaf.fUserValue.replace(leaf.fUserValue.find("%s"), strlen("%s"), + val); + } + } + } else { + leaf.fUserValue.replace(leaf.fUserValue.find("%s"), strlen("%s"), + "0"); } - kState.fSyntaxTree = nullptr; + continue; + } - kState.fOutputAssembly->flush(); - kState.fOutputAssembly.reset(); + lines.emplace_back(leaf.fUserData); + } - return kOk; + for (auto& leaf : kState.fSyntaxTree->fLeafList) { + (*kState.fOutputAssembly) << leaf.fUserValue; } + kState.fSyntaxTree = nullptr; + + kState.fOutputAssembly->flush(); + kState.fOutputAssembly.reset(); + + return kOk; + } }; ///////////////////////////////////////////////////////////////////////////////////////// #define kPrintF printf -#define kSplashCxx() kPrintF(kWhite "%s\n", "ccplus, v1.15, (c) Mahrouss Logic.") - -static void cxx_print_help() -{ - kSplashCxx(); - kPrintF(kWhite "--asm={ASSEMBLER}: %s\n", "Compile with a specific syntax. (64x0, 32x0)"); - kPrintF(kWhite "--compiler={COMPILER}: %s\n", "Select compiler engine (builtin -> vanhalen)."); +#define kSplashCxx() \ + kPrintF(kWhite "%s\n", "ccplus, v1.15, (c) Mahrouss Logic.") + +static void cxx_print_help() { + kSplashCxx(); + kPrintF(kWhite "--asm={ASSEMBLER}: %s\n", + "Compile with a specific syntax. (64x0, 32x0)"); + kPrintF(kWhite "--compiler={COMPILER}: %s\n", + "Select compiler engine (builtin -> vanhalen)."); } ///////////////////////////////////////////////////////////////////////////////////////// -#define kExt { ".cpp", ".cxx", ".cc", ".c++" } - -MPCC_MODULE(CompilerCPlusPlus64x0) -{ - kKeywords.emplace_back("auto"); - kKeywords.emplace_back("else"); - kKeywords.emplace_back("break"); - kKeywords.emplace_back("switch"); - kKeywords.emplace_back("enum"); - kKeywords.emplace_back("register"); - kKeywords.emplace_back("do"); - kKeywords.emplace_back("return"); - kKeywords.emplace_back("if"); - kKeywords.emplace_back("default"); - kKeywords.emplace_back("struct"); - kKeywords.emplace_back("_Packed"); - kKeywords.emplace_back("extern"); - kKeywords.emplace_back("volatile"); - kKeywords.emplace_back("static"); - kKeywords.emplace_back("for"); - kKeywords.emplace_back("class"); - kKeywords.emplace_back("{"); - kKeywords.emplace_back("}"); - kKeywords.emplace_back("("); - kKeywords.emplace_back(")"); - kKeywords.emplace_back("char"); - kKeywords.emplace_back("int"); - kKeywords.emplace_back("short"); - kKeywords.emplace_back("long"); - kKeywords.emplace_back("float"); - kKeywords.emplace_back("double"); - kKeywords.emplace_back("unsigned"); - kKeywords.emplace_back("__export__"); - kKeywords.emplace_back("__import__"); - kKeywords.emplace_back("__packed__"); - kKeywords.emplace_back("namespace"); - kKeywords.emplace_back("while"); - kKeywords.emplace_back("sizeof"); - kKeywords.emplace_back("private"); - kKeywords.emplace_back("->"); - kKeywords.emplace_back("."); - kKeywords.emplace_back("::"); - kKeywords.emplace_back("*"); - kKeywords.emplace_back("+"); - kKeywords.emplace_back("-"); - kKeywords.emplace_back("/"); - kKeywords.emplace_back("="); - kKeywords.emplace_back("=="); - kKeywords.emplace_back("!="); - kKeywords.emplace_back(">="); - kKeywords.emplace_back("<="); - kKeywords.emplace_back(">"); - kKeywords.emplace_back("<"); - kKeywords.emplace_back(":"); - kKeywords.emplace_back(","); - kKeywords.emplace_back(";"); - kKeywords.emplace_back("&"); - kKeywords.emplace_back("public"); - kKeywords.emplace_back("protected"); - - bool skip = false; - - for (auto index = 1UL; index < argc; ++index) - { - if (skip) - { - skip = false; - continue; - } +#define kExt \ + { ".cpp", ".cxx", ".cc", ".c++" } + +MPCC_MODULE(CompilerCPlusPlus64x0) { + kKeywords.emplace_back("auto"); + kKeywords.emplace_back("else"); + kKeywords.emplace_back("break"); + kKeywords.emplace_back("switch"); + kKeywords.emplace_back("enum"); + kKeywords.emplace_back("register"); + kKeywords.emplace_back("do"); + kKeywords.emplace_back("return"); + kKeywords.emplace_back("if"); + kKeywords.emplace_back("default"); + kKeywords.emplace_back("struct"); + kKeywords.emplace_back("_Packed"); + kKeywords.emplace_back("extern"); + kKeywords.emplace_back("volatile"); + kKeywords.emplace_back("static"); + kKeywords.emplace_back("for"); + kKeywords.emplace_back("class"); + kKeywords.emplace_back("{"); + kKeywords.emplace_back("}"); + kKeywords.emplace_back("("); + kKeywords.emplace_back(")"); + kKeywords.emplace_back("char"); + kKeywords.emplace_back("int"); + kKeywords.emplace_back("short"); + kKeywords.emplace_back("long"); + kKeywords.emplace_back("float"); + kKeywords.emplace_back("double"); + kKeywords.emplace_back("unsigned"); + kKeywords.emplace_back("__export__"); + kKeywords.emplace_back("__import__"); + kKeywords.emplace_back("__packed__"); + kKeywords.emplace_back("namespace"); + kKeywords.emplace_back("while"); + kKeywords.emplace_back("sizeof"); + kKeywords.emplace_back("private"); + kKeywords.emplace_back("->"); + kKeywords.emplace_back("."); + kKeywords.emplace_back("::"); + kKeywords.emplace_back("*"); + kKeywords.emplace_back("+"); + kKeywords.emplace_back("-"); + kKeywords.emplace_back("/"); + kKeywords.emplace_back("="); + kKeywords.emplace_back("=="); + kKeywords.emplace_back("!="); + kKeywords.emplace_back(">="); + kKeywords.emplace_back("<="); + kKeywords.emplace_back(">"); + kKeywords.emplace_back("<"); + kKeywords.emplace_back(":"); + kKeywords.emplace_back(","); + kKeywords.emplace_back(";"); + kKeywords.emplace_back("&"); + kKeywords.emplace_back("public"); + kKeywords.emplace_back("protected"); + + bool skip = false; + + for (auto index = 1UL; index < argc; ++index) { + if (skip) { + skip = false; + continue; + } - if (argv[index][0] == '-') - { - if (strcmp(argv[index], "-v") == 0 || - strcmp(argv[index], "--version") == 0) - { - kSplashCxx(); - return kOk; - } + if (argv[index][0] == '-') { + if (strcmp(argv[index], "-v") == 0 || + strcmp(argv[index], "--version") == 0) { + kSplashCxx(); + return kOk; + } - if (strcmp(argv[index], "-verbose") == 0) - { - kState.kVerbose = true; + if (strcmp(argv[index], "-verbose") == 0) { + kState.kVerbose = true; - continue; - } + continue; + } - if (strcmp(argv[index], "-h") == 0 || - strcmp(argv[index], "--help") == 0) - { - cxx_print_help(); + if (strcmp(argv[index], "-h") == 0 || + strcmp(argv[index], "--help") == 0) { + cxx_print_help(); - return kOk; - } + return kOk; + } - if (strcmp(argv[index], "--dialect") == 0) - { - if (kCompilerBackend) - std::cout << kCompilerBackend->Language() << "\n"; + if (strcmp(argv[index], "--dialect") == 0) { + if (kCompilerBackend) std::cout << kCompilerBackend->Language() << "\n"; - return kOk; - } + return kOk; + } - if (strcmp(argv[index], "--asm=masm") == 0) - { - delete kFactory.Unmount(); + if (strcmp(argv[index], "--asm=masm") == 0) { + delete kFactory.Unmount(); - kFactory.Mount(new AssemblyMountpointClang()); - kMachine = CompilerKit::AssemblyFactory::kArchRISCV; + kFactory.Mount(new AssemblyMountpointClang()); + kMachine = CompilerKit::AssemblyFactory::kArch64x0; - continue; - } + continue; + } - if (strcmp(argv[index], "--compiler=vanhalen") == 0) - { - if (!kCompilerBackend) - kCompilerBackend = new CompilerBackendClang(); + if (strcmp(argv[index], "--compiler=vanhalen") == 0) { + if (!kCompilerBackend) kCompilerBackend = new CompilerBackendClang(); - continue; - } + continue; + } - if (strcmp(argv[index], "-fmax-exceptions") == 0) - { - try - { - kErrorLimit = std::strtol(argv[index + 1], nullptr, 10); - } - // catch anything here - catch (...) - { - kErrorLimit = 0; - } + if (strcmp(argv[index], "-fmax-exceptions") == 0) { + try { + kErrorLimit = std::strtol(argv[index + 1], nullptr, 10); + } + // catch anything here + catch (...) { + kErrorLimit = 0; + } - skip = true; + skip = true; - continue; - } + continue; + } - std::string err = "Unknown option: "; - err += argv[index]; + std::string err = "Unknown option: "; + err += argv[index]; - detail::print_error(err, "ccplus"); + detail::print_error(err, "ccplus"); - continue; - } + continue; + } - kFileList.emplace_back(argv[index]); + kFileList.emplace_back(argv[index]); - CompilerKit::StringView srcFile = CompilerKit::StringBuilder::Construct(argv[index]); + CompilerKit::StringView srcFile = + CompilerKit::StringBuilder::Construct(argv[index]); - std::vector exts = kExt; - std::string argv_i = argv[index]; + std::vector exts = kExt; + std::string argv_i = argv[index]; - for (std::string ext : exts) - { - if (argv_i.find(ext) != std::string::npos) - { - if (kState.kVerbose) - { - std::cerr << argv[index] << " is not a valid C++ source.\n"; - } - - return -1; - } - else - { - break; - } + for (std::string ext : exts) { + if (argv_i.find(ext) != std::string::npos) { + if (kState.kVerbose) { + std::cerr << argv[index] << " is not a valid C++ source.\n"; } - if (kFactory.Compile(srcFile, kMachine) != kOk) - return -1; + return -1; + } else { + break; + } } - return kOk; + if (kFactory.Compile(srcFile, kMachine) != kOk) return -1; + } + + return kOk; } -// Last rev 8-1-24
\ No newline at end of file +// Last rev 8-1-24 diff --git a/Private/Toolchain/compile_flags.txt b/Private/Toolchain/compile_flags.txt new file mode 100644 index 0000000..9afc1ed --- /dev/null +++ b/Private/Toolchain/compile_flags.txt @@ -0,0 +1,3 @@ +-std=c++20 +-I../ +-I../CompilerKit diff --git a/Private/Toolchain/i64asm.cc b/Private/Toolchain/i64asm.cc index f23c3e9..1e3cde6 100644 --- a/Private/Toolchain/i64asm.cc +++ b/Private/Toolchain/i64asm.cc @@ -15,8 +15,8 @@ // @author Amlal El Mahrouss // @brief AMD64 Assembler. -// REMINDER: when dealing with an undefined symbol use (string size):LinkerFindSymbol:(string) -// so that ld will look for it. +// REMINDER: when dealing with an undefined symbol use (string +// size):LinkerFindSymbol:(string) so that ld will look for it. ///////////////////////////////////////////////////////////////////////////////////////// @@ -24,11 +24,11 @@ #include <CompilerKit/AsmKit/Arch/amd64.hpp> #include <CompilerKit/ParserKit.hpp> -#include <CompilerKit/StdKit/PEF.hpp> #include <CompilerKit/StdKit/AE.hpp> +#include <CompilerKit/StdKit/PEF.hpp> #include <filesystem> -#include <iostream> #include <fstream> +#include <iostream> ///////////////////// @@ -60,10 +60,7 @@ static bool kVerbose = false; static std::vector<e64_byte_t> kBytes; static CompilerKit::AERecordHeader kCurrentRecord{ - .fName = "", - .fKind = CompilerKit::kPefCode, - .fSize = 0, - .fOffset = 0}; + .fName = "", .fKind = CompilerKit::kPefCode, .fSize = 0, .fOffset = 0}; static std::vector<CompilerKit::AERecordHeader> kRecords; static std::vector<std::string> kUndefinedSymbols; @@ -74,35 +71,32 @@ static const std::string kRelocSymbol = ":mld:"; // \brief forward decl. static bool asm_read_attributes(std::string &line); -namespace detail -{ - void print_error(std::string reason, const std::string &file) noexcept - { - if (reason[0] == '\n') - reason.erase(0, 1); +namespace detail { +void print_error(std::string reason, const std::string &file) noexcept { + if (reason[0] == '\n') reason.erase(0, 1); - kStdErr << kRed << "[ i64asm ] " << kWhite << ((file == "i64asm") ? "internal assembler error " : ("in file, " + file)) << kBlank << std::endl; - kStdErr << kRed << "[ i64asm ] " << kWhite << reason << kBlank << std::endl; + kStdErr << kRed << "[ i64asm ] " << kWhite + << ((file == "i64asm") ? "internal assembler error " + : ("in file, " + file)) + << kBlank << std::endl; + kStdErr << kRed << "[ i64asm ] " << kWhite << reason << kBlank << std::endl; - if (kAcceptableErrors > kErrorLimit) - std::exit(3); + if (kAcceptableErrors > kErrorLimit) std::exit(3); - ++kAcceptableErrors; - } + ++kAcceptableErrors; +} - void print_warning(std::string reason, const std::string &file) noexcept - { - if (reason[0] == '\n') - reason.erase(0, 1); +void print_warning(std::string reason, const std::string &file) noexcept { + if (reason[0] == '\n') reason.erase(0, 1); - if (!file.empty()) - { - kStdOut << kYellow << "[ file ] " << kWhite << file << kBlank << std::endl; - } + if (!file.empty()) { + kStdOut << kYellow << "[ file ] " << kWhite << file << kBlank << std::endl; + } - kStdOut << kYellow << "[ i64asm ] " << kWhite << reason << kBlank << std::endl; - } + kStdOut << kYellow << "[ i64asm ] " << kWhite << reason << kBlank + << std::endl; } +} // namespace detail ///////////////////////////////////////////////////////////////////////////////////////// @@ -110,269 +104,233 @@ namespace detail ///////////////////////////////////////////////////////////////////////////////////////// -MPCC_MODULE(MPUXAssemblerAMD64) -{ - //////////////// CPU OPCODES BEGIN //////////////// - - std::string opcodes_jump[kJumpLimit] = { - "ja", "jae", "jb", "jbe", "jc", "je", "jg", "jge", - "jl", "jle", "jna", "jnae", "jnb", "jnbe", "jnc", "jne", "jng", "jnge", - "jnl", "jnle", "jno", "jnp", "jns", "jnz", "jo", "jp", "jpe", "jpo", "js", "jz"}; +MPCC_MODULE(MPUXAssemblerAMD64) { + //////////////// CPU OPCODES BEGIN //////////////// - for (e64_hword_t i = 0; i < kJumpLimit; i++) - { - CpuCodeAMD64 code{.fName = opcodes_jump[i], .fOpcode = static_cast<e64_hword_t>(kAsmJumpOpcode + i)}; - kOpcodesAMD64.push_back(code); - } + std::string opcodes_jump[kJumpLimit] = { + "ja", "jae", "jb", "jbe", "jc", "je", "jg", "jge", "jl", "jle", + "jna", "jnae", "jnb", "jnbe", "jnc", "jne", "jng", "jnge", "jnl", "jnle", + "jno", "jnp", "jns", "jnz", "jo", "jp", "jpe", "jpo", "js", "jz"}; - CpuCodeAMD64 code{.fName = "jcxz", .fOpcode = 0xE3}; + for (e64_hword_t i = 0; i < kJumpLimit; i++) { + CpuCodeAMD64 code{.fName = opcodes_jump[i], + .fOpcode = static_cast<e64_hword_t>(kAsmJumpOpcode + i)}; kOpcodesAMD64.push_back(code); + } - for (e64_hword_t i = kJumpLimitStandard; i < kJumpLimitStandardLimit; i++) - { - CpuCodeAMD64 code{.fName = "jmp", .fOpcode = i}; - kOpcodesAMD64.push_back(code); - } + CpuCodeAMD64 code{.fName = "jcxz", .fOpcode = 0xE3}; + kOpcodesAMD64.push_back(code); - CpuCodeAMD64 lahf{.fName = "lahf", .fOpcode = 0x9F}; - kOpcodesAMD64.push_back(lahf); + for (e64_hword_t i = kJumpLimitStandard; i < kJumpLimitStandardLimit; i++) { + CpuCodeAMD64 code{.fName = "jmp", .fOpcode = i}; + kOpcodesAMD64.push_back(code); + } - CpuCodeAMD64 lds{.fName = "lds", .fOpcode = 0xC5}; - kOpcodesAMD64.push_back(lds); + CpuCodeAMD64 lahf{.fName = "lahf", .fOpcode = 0x9F}; + kOpcodesAMD64.push_back(lahf); - CpuCodeAMD64 lea{.fName = "lea", .fOpcode = 0x8D}; - kOpcodesAMD64.push_back(lea); + CpuCodeAMD64 lds{.fName = "lds", .fOpcode = 0xC5}; + kOpcodesAMD64.push_back(lds); - CpuCodeAMD64 mov{.fName = "nop", .fOpcode = 0x90}; - kOpcodesAMD64.push_back(mov); + CpuCodeAMD64 lea{.fName = "lea", .fOpcode = 0x8D}; + kOpcodesAMD64.push_back(lea); - //////////////// CPU OPCODES END //////////////// + CpuCodeAMD64 mov{.fName = "nop", .fOpcode = 0x90}; + kOpcodesAMD64.push_back(mov); - for (size_t i = 1; i < argc; ++i) - { - if (argv[i][0] == '-') - { - if (strcmp(argv[i], "-version") == 0 || - strcmp(argv[i], "-v") == 0) - { - kStdOut << "i64asm: AMD64 Assembler.\ni64asm: v1.10\ni64asm: Copyright (c) 2024 Mahrouss Logic.\n"; - return 0; - } - else if (strcmp(argv[i], "-h") == 0) - { - kStdOut << "i64asm: AMD64 Assembler.\ni64asm: Copyright (c) 2024 Mahrouss Logic.\n"; - kStdOut << "-version: Print program version.\n"; - kStdOut << "-verbose: Print verbose output.\n"; - kStdOut << "-binary: Output as flat binary.\n"; - kStdOut << "-64xxx: Compile for a subset of the X64000.\n"; - - return 0; - } - else if (strcmp(argv[i], "-binary") == 0) - { - kOutputAsBinary = true; - continue; - } - else if (strcmp(argv[i], "-verbose") == 0) - { - kVerbose = true; - continue; - } + //////////////// CPU OPCODES END //////////////// - kStdOut << "i64asm: ignore " << argv[i] << "\n"; - continue; - } + for (size_t i = 1; i < argc; ++i) { + if (argv[i][0] == '-') { + if (strcmp(argv[i], "-version") == 0 || strcmp(argv[i], "-v") == 0) { + kStdOut << "i64asm: AMD64 Assembler.\ni64asm: v1.10\ni64asm: Copyright " + "(c) 2024 Mahrouss Logic.\n"; + return 0; + } else if (strcmp(argv[i], "-h") == 0) { + kStdOut << "i64asm: AMD64 Assembler.\ni64asm: Copyright (c) 2024 " + "Mahrouss Logic.\n"; + kStdOut << "-version: Print program version.\n"; + kStdOut << "-verbose: Print verbose output.\n"; + kStdOut << "-binary: Output as flat binary.\n"; + kStdOut << "-64xxx: Compile for a subset of the X64000.\n"; - if (!std::filesystem::exists(argv[i])) - { - kStdOut << "i64asm: can't open: " << argv[i] << std::endl; - goto asm_fail_exit; - } + return 0; + } else if (strcmp(argv[i], "-binary") == 0) { + kOutputAsBinary = true; + continue; + } else if (strcmp(argv[i], "-verbose") == 0) { + kVerbose = true; + continue; + } + + kStdOut << "i64asm: ignore " << argv[i] << "\n"; + continue; + } - std::string object_output(argv[i]); + if (!std::filesystem::exists(argv[i])) { + kStdOut << "i64asm: can't open: " << argv[i] << std::endl; + goto asm_fail_exit; + } - for (auto &ext : kAsmFileExts) - { - if (object_output.find(ext) != std::string::npos) - { - object_output.erase(object_output.find(ext), std::strlen(ext)); - } - } + std::string object_output(argv[i]); - object_output += kObjectFileExt; + for (auto &ext : kAsmFileExts) { + if (object_output.find(ext) != std::string::npos) { + object_output.erase(object_output.find(ext), std::strlen(ext)); + } + } - std::ifstream file_ptr(argv[i]); - std::ofstream file_ptr_out(object_output, - std::ofstream::binary); + object_output += kObjectFileExt; - if (file_ptr_out.bad()) - { - if (kVerbose) - { - kStdOut << "i64asm: error: " << strerror(errno) << "\n"; - } - } + std::ifstream file_ptr(argv[i]); + std::ofstream file_ptr_out(object_output, std::ofstream::binary); - std::string line; + if (file_ptr_out.bad()) { + if (kVerbose) { + kStdOut << "i64asm: error: " << strerror(errno) << "\n"; + } + } - CompilerKit::AEHeader hdr{0}; + std::string line; - memset(hdr.fPad, kAEInvalidOpcode, kAEPad); + CompilerKit::AEHeader hdr{0}; - hdr.fMagic[0] = kAEMag0; - hdr.fMagic[1] = kAEMag1; - hdr.fSize = sizeof(CompilerKit::AEHeader); - hdr.fArch = kOutputArch; + memset(hdr.fPad, kAEInvalidOpcode, kAEPad); - ///////////////////////////////////////////////////////////////////////////////////////// + hdr.fMagic[0] = kAEMag0; + hdr.fMagic[1] = kAEMag1; + hdr.fSize = sizeof(CompilerKit::AEHeader); + hdr.fArch = kOutputArch; - // COMPILATION LOOP + ///////////////////////////////////////////////////////////////////////////////////////// - ///////////////////////////////////////////////////////////////////////////////////////// + // COMPILATION LOOP - CompilerKit::PlatformAssemblerAMD64 asm64; + ///////////////////////////////////////////////////////////////////////////////////////// - while (std::getline(file_ptr, line)) - { - if (auto ln = asm64.CheckLine(line, argv[i]); - !ln.empty()) - { - detail::print_error(ln, argv[i]); - continue; - } + CompilerKit::PlatformAssemblerAMD64 asm64; - try - { - asm_read_attributes(line); - asm64.WriteLine(line, argv[i]); - } - catch (const std::exception &e) - { - if (kVerbose) - { - std::string what = e.what(); - detail::print_warning("exit because of: " + what, "i64asm"); - } - - std::filesystem::remove(object_output); - goto asm_fail_exit; - } + while (std::getline(file_ptr, line)) { + if (auto ln = asm64.CheckLine(line, argv[i]); !ln.empty()) { + detail::print_error(ln, argv[i]); + continue; + } + + try { + asm_read_attributes(line); + asm64.WriteLine(line, argv[i]); + } catch (const std::exception &e) { + if (kVerbose) { + std::string what = e.what(); + detail::print_warning("exit because of: " + what, "i64asm"); } - if (!kOutputAsBinary) - { - if (kVerbose) - { - kStdOut << "i64asm: Writing object file...\n"; - } + std::filesystem::remove(object_output); + goto asm_fail_exit; + } + } - // this is the final step, write everything to the file. + if (!kOutputAsBinary) { + if (kVerbose) { + kStdOut << "i64asm: Writing object file...\n"; + } - auto pos = file_ptr_out.tellp(); + // this is the final step, write everything to the file. - hdr.fCount = kRecords.size() + kUndefinedSymbols.size(); + auto pos = file_ptr_out.tellp(); - file_ptr_out << hdr; + hdr.fCount = kRecords.size() + kUndefinedSymbols.size(); - if (kRecords.empty()) - { - kStdErr << "i64asm: At least one record is needed to write an object file.\ni64asm: Make one using `export .text foo_bar`.\n"; + file_ptr_out << hdr; - std::filesystem::remove(object_output); - return -1; - } + if (kRecords.empty()) { + kStdErr << "i64asm: At least one record is needed to write an object " + "file.\ni64asm: Make one using `export .text foo_bar`.\n"; - kRecords[kRecords.size() - 1].fSize = kBytes.size(); + std::filesystem::remove(object_output); + return -1; + } - std::size_t record_count = 0UL; + kRecords[kRecords.size() - 1].fSize = kBytes.size(); - for (auto &rec : kRecords) - { - if (kVerbose) - kStdOut << "i64asm: Wrote record " << rec.fName << " to file...\n"; + std::size_t record_count = 0UL; - rec.fFlags |= CompilerKit::kKindRelocationAtRuntime; - rec.fOffset = record_count; - ++record_count; + for (auto &rec : kRecords) { + if (kVerbose) + kStdOut << "i64asm: Wrote record " << rec.fName << " to file...\n"; - file_ptr_out << rec; - } + rec.fFlags |= CompilerKit::kKindRelocationAtRuntime; + rec.fOffset = record_count; + ++record_count; - // increment once again, so that we won't lie about the kUndefinedSymbols. - ++record_count; + file_ptr_out << rec; + } - for (auto &sym : kUndefinedSymbols) - { - CompilerKit::AERecordHeader _record_hdr{0}; + // increment once again, so that we won't lie about the kUndefinedSymbols. + ++record_count; - if (kVerbose) - kStdOut << "i64asm: Wrote symbol " << sym << " to file...\n"; + for (auto &sym : kUndefinedSymbols) { + CompilerKit::AERecordHeader _record_hdr{0}; - _record_hdr.fKind = kAEInvalidOpcode; - _record_hdr.fSize = sym.size(); - _record_hdr.fOffset = record_count; + if (kVerbose) + kStdOut << "i64asm: Wrote symbol " << sym << " to file...\n"; - ++record_count; + _record_hdr.fKind = kAEInvalidOpcode; + _record_hdr.fSize = sym.size(); + _record_hdr.fOffset = record_count; - memset(_record_hdr.fPad, kAEInvalidOpcode, kAEPad); - memcpy(_record_hdr.fName, sym.c_str(), sym.size()); + ++record_count; - file_ptr_out << _record_hdr; + memset(_record_hdr.fPad, kAEInvalidOpcode, kAEPad); + memcpy(_record_hdr.fName, sym.c_str(), sym.size()); - ++kCounter; - } + file_ptr_out << _record_hdr; - auto pos_end = file_ptr_out.tellp(); + ++kCounter; + } - file_ptr_out.seekp(pos); + auto pos_end = file_ptr_out.tellp(); - hdr.fStartCode = pos_end; - hdr.fCodeSize = kBytes.size(); + file_ptr_out.seekp(pos); - file_ptr_out << hdr; + hdr.fStartCode = pos_end; + hdr.fCodeSize = kBytes.size(); - file_ptr_out.seekp(pos_end); - } - else - { - if (kVerbose) - { - kStdOut << "i64asm: Write raw binary...\n"; - } - } + file_ptr_out << hdr; - // byte from byte, we write this. - for (auto &byte : kBytes) - { - if (byte == 0) - continue; + file_ptr_out.seekp(pos_end); + } else { + if (kVerbose) { + kStdOut << "i64asm: Write raw binary...\n"; + } + } - if (byte == 0xFF) - { - byte = 0; - } + // byte from byte, we write this. + for (auto &byte : kBytes) { + if (byte == 0) continue; - file_ptr_out << reinterpret_cast<const char *>(&byte)[0]; - } + if (byte == 0xFF) { + byte = 0; + } - if (kVerbose) - kStdOut << "i64asm: Wrote file with program in it.\n"; + file_ptr_out << reinterpret_cast<const char *>(&byte)[0]; + } - file_ptr_out.flush(); - file_ptr_out.close(); + if (kVerbose) kStdOut << "i64asm: Wrote file with program in it.\n"; - if (kVerbose) - kStdOut << "i64asm: Exit succeeded.\n"; + file_ptr_out.flush(); + file_ptr_out.close(); - return 0; - } + if (kVerbose) kStdOut << "i64asm: Exit succeeded.\n"; + + return 0; + } asm_fail_exit: - if (kVerbose) - kStdOut << "i64asm: Exit failed.\n"; + if (kVerbose) kStdOut << "i64asm: Exit failed.\n"; - return -1; + return -1; } ///////////////////////////////////////////////////////////////////////////////////////// @@ -382,165 +340,143 @@ asm_fail_exit: ///////////////////////////////////////////////////////////////////////////////////////// -static bool asm_read_attributes(std::string &line) -{ - // import is the opposite of export, it signals to the ld - // that we need this symbol. - if (ParserKit::find_word(line, "import ")) - { - if (kOutputAsBinary) - { - detail::print_error("invalid import directive in flat binary mode.", "i64asm"); - throw std::runtime_error("invalid_import_bin"); - } +static bool asm_read_attributes(std::string &line) { + // import is the opposite of export, it signals to the ld + // that we need this symbol. + if (ParserKit::find_word(line, "import ")) { + if (kOutputAsBinary) { + detail::print_error("invalid import directive in flat binary mode.", + "i64asm"); + throw std::runtime_error("invalid_import_bin"); + } - auto name = line.substr(line.find("import ") + strlen("import ")); + auto name = line.substr(line.find("import ") + strlen("import ")); - std::string result = std::to_string(name.size()); - result += kUndefinedSymbol; + std::string result = std::to_string(name.size()); + result += kUndefinedSymbol; - // mangle this - for (char &j : name) - { - if (j == ' ' || - j == ',') - j = '$'; - } - - result += name; + // mangle this + for (char &j : name) { + if (j == ' ' || j == ',') j = '$'; + } - if (name.find(".text") != std::string::npos) - { - // data is treated as code. - kCurrentRecord.fKind = CompilerKit::kPefCode; - } - else if (name.find(".data") != std::string::npos) - { - // no code will be executed from here. - kCurrentRecord.fKind = CompilerKit::kPefData; - } - else if (name.find(".page_zero") != std::string::npos) - { - // this is a bss section. - kCurrentRecord.fKind = CompilerKit::kPefZero; - } + result += name; + + if (name.find(".text") != std::string::npos) { + // data is treated as code. + kCurrentRecord.fKind = CompilerKit::kPefCode; + } else if (name.find(".data") != std::string::npos) { + // no code will be executed from here. + kCurrentRecord.fKind = CompilerKit::kPefData; + } else if (name.find(".page_zero") != std::string::npos) { + // this is a bss section. + kCurrentRecord.fKind = CompilerKit::kPefZero; + } - // this is a special case for the start stub. - // we want this so that ld can find it. + // this is a special case for the start stub. + // we want this so that ld can find it. - if (name == "__start") - { - kCurrentRecord.fKind = CompilerKit::kPefCode; - } + if (name == "__start") { + kCurrentRecord.fKind = CompilerKit::kPefCode; + } - // now we can tell the code size of the previous kCurrentRecord. + // now we can tell the code size of the previous kCurrentRecord. - if (!kRecords.empty()) - kRecords[kRecords.size() - 1].fSize = kBytes.size(); + if (!kRecords.empty()) kRecords[kRecords.size() - 1].fSize = kBytes.size(); - memset(kCurrentRecord.fName, 0, kAESymbolLen); - memcpy(kCurrentRecord.fName, result.c_str(), result.size()); + memset(kCurrentRecord.fName, 0, kAESymbolLen); + memcpy(kCurrentRecord.fName, result.c_str(), result.size()); - ++kCounter; + ++kCounter; - memset(kCurrentRecord.fPad, kAEInvalidOpcode, kAEPad); + memset(kCurrentRecord.fPad, kAEInvalidOpcode, kAEPad); - kRecords.emplace_back(kCurrentRecord); + kRecords.emplace_back(kCurrentRecord); - return true; + return true; + } + // export is a special keyword used by i64asm to tell the AE output stage to + // mark this section as a header. it currently supports .text, .data., + // page_zero + else if (ParserKit::find_word(line, "export ")) { + if (kOutputAsBinary) { + detail::print_error("invalid export directive in flat binary mode.", + "i64asm"); + throw std::runtime_error("invalid_export_bin"); } - // export is a special keyword used by i64asm to tell the AE output stage to mark this section as a header. - // it currently supports .text, .data., page_zero - else if (ParserKit::find_word(line, "export ")) - { - if (kOutputAsBinary) - { - detail::print_error("invalid export directive in flat binary mode.", "i64asm"); - throw std::runtime_error("invalid_export_bin"); - } - auto name = line.substr(line.find("export ") + strlen("export ")); + auto name = line.substr(line.find("export ") + strlen("export ")); - std::string name_copy = name; + std::string name_copy = name; - for (char &j : name) - { - if (j == ' ') - j = '$'; - } + for (char &j : name) { + if (j == ' ') j = '$'; + } - if (name.find(".text") != std::string::npos) - { - // data is treated as code. + if (name.find(".text") != std::string::npos) { + // data is treated as code. - name_copy.erase(name_copy.find(".text"), strlen(".text")); - kCurrentRecord.fKind = CompilerKit::kPefCode; - } - else if (name.find(".data") != std::string::npos) - { - // no code will be executed from here. + name_copy.erase(name_copy.find(".text"), strlen(".text")); + kCurrentRecord.fKind = CompilerKit::kPefCode; + } else if (name.find(".data") != std::string::npos) { + // no code will be executed from here. - name_copy.erase(name_copy.find(".data"), strlen(".data")); - kCurrentRecord.fKind = CompilerKit::kPefData; - } - else if (name.find(".page_zero") != std::string::npos) - { - // this is a bss section. + name_copy.erase(name_copy.find(".data"), strlen(".data")); + kCurrentRecord.fKind = CompilerKit::kPefData; + } else if (name.find(".page_zero") != std::string::npos) { + // this is a bss section. - name_copy.erase(name_copy.find(".page_zero"), strlen(".page_zero")); - kCurrentRecord.fKind = CompilerKit::kPefZero; - } + name_copy.erase(name_copy.find(".page_zero"), strlen(".page_zero")); + kCurrentRecord.fKind = CompilerKit::kPefZero; + } - // this is a special case for the start stub. - // we want this so that ld can find it. + // this is a special case for the start stub. + // we want this so that ld can find it. - if (name == "__start") - { - kCurrentRecord.fKind = CompilerKit::kPefCode; - } + if (name == "__start") { + kCurrentRecord.fKind = CompilerKit::kPefCode; + } - while (name_copy.find(" ") != std::string::npos) - name_copy.erase(name_copy.find(" "), 1); + while (name_copy.find(" ") != std::string::npos) + name_copy.erase(name_copy.find(" "), 1); - kOriginLabel.push_back(std::make_pair(name_copy, kOrigin)); - ++kOrigin; + kOriginLabel.push_back(std::make_pair(name_copy, kOrigin)); + ++kOrigin; - // now we can tell the code size of the previous kCurrentRecord. + // now we can tell the code size of the previous kCurrentRecord. - if (!kRecords.empty()) - kRecords[kRecords.size() - 1].fSize = kBytes.size(); + if (!kRecords.empty()) kRecords[kRecords.size() - 1].fSize = kBytes.size(); - memset(kCurrentRecord.fName, 0, kAESymbolLen); - memcpy(kCurrentRecord.fName, name.c_str(), name.size()); + memset(kCurrentRecord.fName, 0, kAESymbolLen); + memcpy(kCurrentRecord.fName, name.c_str(), name.size()); - ++kCounter; + ++kCounter; - memset(kCurrentRecord.fPad, kAEInvalidOpcode, kAEPad); + memset(kCurrentRecord.fPad, kAEInvalidOpcode, kAEPad); - kRecords.emplace_back(kCurrentRecord); + kRecords.emplace_back(kCurrentRecord); - return true; - } + return true; + } - return false; + return false; } // \brief algorithms and helpers. -namespace detail::algorithm -{ - // \brief authorize a brief set of characters. - static inline bool is_not_alnum_space(char c) - { - return !(isalpha(c) || isdigit(c) || (c == ' ') || (c == '\t') || (c == ',') || - (c == '(') || (c == ')') || (c == '"') || (c == '\'') || (c == '[') || (c == ']') || (c == '+') || (c == '_') || (c == ':') || (c == '@') || (c == '.')); - } +namespace detail::algorithm { +// \brief authorize a brief set of characters. +static inline bool is_not_alnum_space(char c) { + return !(isalpha(c) || isdigit(c) || (c == ' ') || (c == '\t') || + (c == ',') || (c == '(') || (c == ')') || (c == '"') || + (c == '\'') || (c == '[') || (c == ']') || (c == '+') || + (c == '_') || (c == ':') || (c == '@') || (c == '.')); +} - bool is_valid(const std::string &str) - { - return find_if(str.begin(), str.end(), is_not_alnum_space) == str.end(); - } +bool is_valid(const std::string &str) { + return find_if(str.begin(), str.end(), is_not_alnum_space) == str.end(); } +} // namespace detail::algorithm ///////////////////////////////////////////////////////////////////////////////////////// @@ -548,611 +484,492 @@ namespace detail::algorithm ///////////////////////////////////////////////////////////////////////////////////////// -std::string CompilerKit::PlatformAssemblerAMD64::CheckLine(std::string &line, const std::string &file) -{ - std::string err_str; - - if (line.empty() || - ParserKit::find_word(line, "import") || - ParserKit::find_word(line, "export") || - ParserKit::find_word(line, "#") || - ParserKit::find_word(line, ";")) - { - if (line.find('#') != std::string::npos) - { - line.erase(line.find('#')); - } - else if (line.find(';') != std::string::npos) - { - line.erase(line.find(';')); - } - else - { - // now check the line for validity - if (!detail::algorithm::is_valid(line)) - { - err_str = "Line contains non alphanumeric characters.\nhere -> "; - err_str += line; - } - } - - return err_str; - } - - if (!detail::algorithm::is_valid(line)) - { +std::string CompilerKit::PlatformAssemblerAMD64::CheckLine( + std::string &line, const std::string &file) { + std::string err_str; + + if (line.empty() || ParserKit::find_word(line, "import") || + ParserKit::find_word(line, "export") || ParserKit::find_word(line, "#") || + ParserKit::find_word(line, ";")) { + if (line.find('#') != std::string::npos) { + line.erase(line.find('#')); + } else if (line.find(';') != std::string::npos) { + line.erase(line.find(';')); + } else { + // now check the line for validity + if (!detail::algorithm::is_valid(line)) { err_str = "Line contains non alphanumeric characters.\nhere -> "; err_str += line; - - return err_str; + } } - // check for a valid instruction format. + return err_str; + } - if (line.find(',') != std::string::npos) - { - if (line.find(',') + 1 == line.size()) - { - err_str += "\nInstruction lacks right register, here -> "; - err_str += line.substr(line.find(',')); + if (!detail::algorithm::is_valid(line)) { + err_str = "Line contains non alphanumeric characters.\nhere -> "; + err_str += line; - return err_str; - } - else - { - bool nothing_on_right = true; + return err_str; + } - if (line.find(',') + 1 > line.size()) - { - err_str += "\nInstruction not complete, here -> "; - err_str += line; + // check for a valid instruction format. - return err_str; - } + if (line.find(',') != std::string::npos) { + if (line.find(',') + 1 == line.size()) { + err_str += "\nInstruction lacks right register, here -> "; + err_str += line.substr(line.find(',')); - auto substr = line.substr(line.find(',') + 1); + return err_str; + } else { + bool nothing_on_right = true; - for (auto &ch : substr) - { - if (ch != ' ' && - ch != '\t') - { - nothing_on_right = false; - } - } + if (line.find(',') + 1 > line.size()) { + err_str += "\nInstruction not complete, here -> "; + err_str += line; - // this means we found nothing after that ',' . - if (nothing_on_right) - { - err_str += "\nInstruction not complete, here -> "; - err_str += line; + return err_str; + } - return err_str; - } + auto substr = line.substr(line.find(',') + 1); + + for (auto &ch : substr) { + if (ch != ' ' && ch != '\t') { + nothing_on_right = false; } + } + + // this means we found nothing after that ',' . + if (nothing_on_right) { + err_str += "\nInstruction not complete, here -> "; + err_str += line; + + return err_str; + } } + } - return err_str; + return err_str; } -bool CompilerKit::PlatformAssemblerAMD64::WriteNumber(const std::size_t &pos, std::string &jump_label) -{ - if (!isdigit(jump_label[pos])) - return false; - - switch (jump_label[pos + 1]) - { - case 'x': - { - if (auto res = strtoq(jump_label.substr(pos + 2).c_str(), - nullptr, 16); - !res) - { - if (errno != 0) - { - detail::print_error("invalid hex number: " + jump_label, "i64asm"); - throw std::runtime_error("invalid_hex"); - } - } +bool CompilerKit::PlatformAssemblerAMD64::WriteNumber(const std::size_t &pos, + std::string &jump_label) { + if (!isdigit(jump_label[pos])) return false; + + switch (jump_label[pos + 1]) { + case 'x': { + if (auto res = strtoq(jump_label.substr(pos + 2).c_str(), nullptr, 16); + !res) { + if (errno != 0) { + detail::print_error("invalid hex number: " + jump_label, "i64asm"); + throw std::runtime_error("invalid_hex"); + } + } - CompilerKit::NumberCast64 num = CompilerKit::NumberCast64(strtoq(jump_label.substr(pos + 2).c_str(), - nullptr, 16)); + CompilerKit::NumberCast64 num = CompilerKit::NumberCast64( + strtoq(jump_label.substr(pos + 2).c_str(), nullptr, 16)); - for (char &i : num.number) - { - if (i == 0) - i = 0xFF; + for (char &i : num.number) { + if (i == 0) i = 0xFF; - kBytes.push_back(i); - } + kBytes.push_back(i); + } - if (kVerbose) - { - kStdOut << "i64asm: found a base 16 number here: " << jump_label.substr(pos) << "\n"; - } + if (kVerbose) { + kStdOut << "i64asm: found a base 16 number here: " + << jump_label.substr(pos) << "\n"; + } - return true; + return true; + } + case 'b': { + if (auto res = strtoq(jump_label.substr(pos + 2).c_str(), nullptr, 2); + !res) { + if (errno != 0) { + detail::print_error("invalid binary number: " + jump_label, "i64asm"); + throw std::runtime_error("invalid_bin"); } - case 'b': - { - if (auto res = strtoq(jump_label.substr(pos + 2).c_str(), - nullptr, 2); - !res) - { - if (errno != 0) - { - detail::print_error("invalid binary number: " + jump_label, "i64asm"); - throw std::runtime_error("invalid_bin"); - } - } + } - CompilerKit::NumberCast64 num = CompilerKit::NumberCast64(strtoq(jump_label.substr(pos + 2).c_str(), - nullptr, 2)); + CompilerKit::NumberCast64 num = CompilerKit::NumberCast64( + strtoq(jump_label.substr(pos + 2).c_str(), nullptr, 2)); - if (kVerbose) - { - kStdOut << "i64asm: found a base 2 number here: " << jump_label.substr(pos) << "\n"; - } + if (kVerbose) { + kStdOut << "i64asm: found a base 2 number here: " + << jump_label.substr(pos) << "\n"; + } - for (char &i : num.number) - { - if (i == 0) - i = 0xFF; + for (char &i : num.number) { + if (i == 0) i = 0xFF; - kBytes.push_back(i); - } + kBytes.push_back(i); + } - return true; + return true; + } + case 'o': { + if (auto res = strtoq(jump_label.substr(pos + 2).c_str(), nullptr, 7); + !res) { + if (errno != 0) { + detail::print_error("invalid octal number: " + jump_label, "i64asm"); + throw std::runtime_error("invalid_octal"); } - case 'o': - { - if (auto res = strtoq(jump_label.substr(pos + 2).c_str(), - nullptr, 7); - !res) - { - if (errno != 0) - { - detail::print_error("invalid octal number: " + jump_label, "i64asm"); - throw std::runtime_error("invalid_octal"); - } - } + } - CompilerKit::NumberCast64 num = CompilerKit::NumberCast64(strtoq(jump_label.substr(pos + 2).c_str(), - nullptr, 7)); + CompilerKit::NumberCast64 num = CompilerKit::NumberCast64( + strtoq(jump_label.substr(pos + 2).c_str(), nullptr, 7)); - if (kVerbose) - { - kStdOut << "i64asm: found a base 8 number here: " << jump_label.substr(pos) << "\n"; - } + if (kVerbose) { + kStdOut << "i64asm: found a base 8 number here: " + << jump_label.substr(pos) << "\n"; + } - for (char &i : num.number) - { - if (i == 0) - i = 0xFF; + for (char &i : num.number) { + if (i == 0) i = 0xFF; - kBytes.push_back(i); - } + kBytes.push_back(i); + } - return true; - } - default: - { - break; - } + return true; + } + default: { + break; } + } - /* check for errno and stuff like that */ - if (auto res = strtoq(jump_label.substr(pos).c_str(), - nullptr, 10); - !res) - { - if (errno != 0) - { - return false; - } + /* check for errno and stuff like that */ + if (auto res = strtoq(jump_label.substr(pos).c_str(), nullptr, 10); !res) { + if (errno != 0) { + return false; } + } - CompilerKit::NumberCast64 num = CompilerKit::NumberCast64(strtoq(jump_label.substr(pos).c_str(), - nullptr, 10)); + CompilerKit::NumberCast64 num = CompilerKit::NumberCast64( + strtoq(jump_label.substr(pos).c_str(), nullptr, 10)); - for (char &i : num.number) - { - if (i == 0) - i = 0xFF; + for (char &i : num.number) { + if (i == 0) i = 0xFF; - kBytes.push_back(i); - } + kBytes.push_back(i); + } - if (kVerbose) - { - kStdOut << "i64asm: found a base 10 number here: " << jump_label.substr(pos) << "\n"; - } + if (kVerbose) { + kStdOut << "i64asm: found a base 10 number here: " << jump_label.substr(pos) + << "\n"; + } - return true; + return true; } -bool CompilerKit::PlatformAssemblerAMD64::WriteNumber32(const std::size_t &pos, std::string &jump_label) -{ - if (!isdigit(jump_label[pos])) - return false; - - switch (jump_label[pos + 1]) - { - case 'x': - { - if (auto res = strtoq(jump_label.substr(pos + 2).c_str(), - nullptr, 16); - !res) - { - if (errno != 0) - { - detail::print_error("invalid hex number: " + jump_label, "i64asm"); - throw std::runtime_error("invalid_hex"); - } - } +bool CompilerKit::PlatformAssemblerAMD64::WriteNumber32( + const std::size_t &pos, std::string &jump_label) { + if (!isdigit(jump_label[pos])) return false; + + switch (jump_label[pos + 1]) { + case 'x': { + if (auto res = strtoq(jump_label.substr(pos + 2).c_str(), nullptr, 16); + !res) { + if (errno != 0) { + detail::print_error("invalid hex number: " + jump_label, "i64asm"); + throw std::runtime_error("invalid_hex"); + } + } - CompilerKit::NumberCast32 num = CompilerKit::NumberCast32(strtoq(jump_label.substr(pos + 2).c_str(), - nullptr, 16)); + CompilerKit::NumberCast32 num = CompilerKit::NumberCast32( + strtoq(jump_label.substr(pos + 2).c_str(), nullptr, 16)); - for (char &i : num.number) - { - if (i == 0) - i = 0xFF; + for (char &i : num.number) { + if (i == 0) i = 0xFF; - kBytes.push_back(i); - } + kBytes.push_back(i); + } - if (kVerbose) - { - kStdOut << "i64asm: found a base 16 number here: " << jump_label.substr(pos) << "\n"; - } + if (kVerbose) { + kStdOut << "i64asm: found a base 16 number here: " + << jump_label.substr(pos) << "\n"; + } - return true; + return true; + } + case 'b': { + if (auto res = strtoq(jump_label.substr(pos + 2).c_str(), nullptr, 2); + !res) { + if (errno != 0) { + detail::print_error("invalid binary number: " + jump_label, "i64asm"); + throw std::runtime_error("invalid_bin"); } - case 'b': - { - if (auto res = strtoq(jump_label.substr(pos + 2).c_str(), - nullptr, 2); - !res) - { - if (errno != 0) - { - detail::print_error("invalid binary number: " + jump_label, "i64asm"); - throw std::runtime_error("invalid_bin"); - } - } + } - CompilerKit::NumberCast32 num = CompilerKit::NumberCast32(strtoq(jump_label.substr(pos + 2).c_str(), - nullptr, 2)); + CompilerKit::NumberCast32 num = CompilerKit::NumberCast32( + strtoq(jump_label.substr(pos + 2).c_str(), nullptr, 2)); - if (kVerbose) - { - kStdOut << "i64asm: found a base 2 number here: " << jump_label.substr(pos) << "\n"; - } + if (kVerbose) { + kStdOut << "i64asm: found a base 2 number here: " + << jump_label.substr(pos) << "\n"; + } - for (char &i : num.number) - { - if (i == 0) - i = 0xFF; + for (char &i : num.number) { + if (i == 0) i = 0xFF; - kBytes.push_back(i); - } + kBytes.push_back(i); + } - return true; + return true; + } + case 'o': { + if (auto res = strtoq(jump_label.substr(pos + 2).c_str(), nullptr, 7); + !res) { + if (errno != 0) { + detail::print_error("invalid octal number: " + jump_label, "i64asm"); + throw std::runtime_error("invalid_octal"); } - case 'o': - { - if (auto res = strtoq(jump_label.substr(pos + 2).c_str(), - nullptr, 7); - !res) - { - if (errno != 0) - { - detail::print_error("invalid octal number: " + jump_label, "i64asm"); - throw std::runtime_error("invalid_octal"); - } - } + } - CompilerKit::NumberCast32 num = CompilerKit::NumberCast32(strtoq(jump_label.substr(pos + 2).c_str(), - nullptr, 7)); + CompilerKit::NumberCast32 num = CompilerKit::NumberCast32( + strtoq(jump_label.substr(pos + 2).c_str(), nullptr, 7)); - if (kVerbose) - { - kStdOut << "i64asm: found a base 8 number here: " << jump_label.substr(pos) << "\n"; - } + if (kVerbose) { + kStdOut << "i64asm: found a base 8 number here: " + << jump_label.substr(pos) << "\n"; + } - for (char &i : num.number) - { - if (i == 0) - i = 0xFF; + for (char &i : num.number) { + if (i == 0) i = 0xFF; - kBytes.push_back(i); - } + kBytes.push_back(i); + } - return true; - } - default: - { - break; - } + return true; } + default: { + break; + } + } - /* check for errno and stuff like that */ - if (auto res = strtoq(jump_label.substr(pos).c_str(), - nullptr, 10); - !res) - { - if (errno != 0) - { - return false; - } + /* check for errno and stuff like that */ + if (auto res = strtoq(jump_label.substr(pos).c_str(), nullptr, 10); !res) { + if (errno != 0) { + return false; } + } - CompilerKit::NumberCast32 num = CompilerKit::NumberCast32(strtoq(jump_label.substr(pos).c_str(), - nullptr, 10)); + CompilerKit::NumberCast32 num = CompilerKit::NumberCast32( + strtoq(jump_label.substr(pos).c_str(), nullptr, 10)); - for (char &i : num.number) - { - if (i == 0) - i = 0xFF; + for (char &i : num.number) { + if (i == 0) i = 0xFF; - kBytes.push_back(i); - } + kBytes.push_back(i); + } - if (kVerbose) - { - kStdOut << "i64asm: found a base 10 number here: " << jump_label.substr(pos) << "\n"; - } + if (kVerbose) { + kStdOut << "i64asm: found a base 10 number here: " << jump_label.substr(pos) + << "\n"; + } - return true; + return true; } -bool CompilerKit::PlatformAssemblerAMD64::WriteNumber16(const std::size_t &pos, std::string &jump_label) -{ - if (!isdigit(jump_label[pos])) - return false; - - switch (jump_label[pos + 1]) - { - case 'x': - { - if (auto res = strtoq(jump_label.substr(pos + 2).c_str(), - nullptr, 16); - !res) - { - if (errno != 0) - { - detail::print_error("invalid hex number: " + jump_label, "i64asm"); - throw std::runtime_error("invalid_hex"); - } - } +bool CompilerKit::PlatformAssemblerAMD64::WriteNumber16( + const std::size_t &pos, std::string &jump_label) { + if (!isdigit(jump_label[pos])) return false; + + switch (jump_label[pos + 1]) { + case 'x': { + if (auto res = strtoq(jump_label.substr(pos + 2).c_str(), nullptr, 16); + !res) { + if (errno != 0) { + detail::print_error("invalid hex number: " + jump_label, "i64asm"); + throw std::runtime_error("invalid_hex"); + } + } - CompilerKit::NumberCast16 num = CompilerKit::NumberCast16(strtoq(jump_label.substr(pos + 2).c_str(), - nullptr, 16)); + CompilerKit::NumberCast16 num = CompilerKit::NumberCast16( + strtoq(jump_label.substr(pos + 2).c_str(), nullptr, 16)); - for (char &i : num.number) - { - if (i == 0) - i = 0xFF; + for (char &i : num.number) { + if (i == 0) i = 0xFF; - kBytes.push_back(i); - } + kBytes.push_back(i); + } - if (kVerbose) - { - kStdOut << "i64asm: found a base 16 number here: " << jump_label.substr(pos) << "\n"; - } + if (kVerbose) { + kStdOut << "i64asm: found a base 16 number here: " + << jump_label.substr(pos) << "\n"; + } - return true; + return true; + } + case 'b': { + if (auto res = strtoq(jump_label.substr(pos + 2).c_str(), nullptr, 2); + !res) { + if (errno != 0) { + detail::print_error("invalid binary number: " + jump_label, "i64asm"); + throw std::runtime_error("invalid_bin"); } - case 'b': - { - if (auto res = strtoq(jump_label.substr(pos + 2).c_str(), - nullptr, 2); - !res) - { - if (errno != 0) - { - detail::print_error("invalid binary number: " + jump_label, "i64asm"); - throw std::runtime_error("invalid_bin"); - } - } + } - CompilerKit::NumberCast16 num = CompilerKit::NumberCast16(strtoq(jump_label.substr(pos + 2).c_str(), - nullptr, 2)); + CompilerKit::NumberCast16 num = CompilerKit::NumberCast16( + strtoq(jump_label.substr(pos + 2).c_str(), nullptr, 2)); - if (kVerbose) - { - kStdOut << "i64asm: found a base 2 number here: " << jump_label.substr(pos) << "\n"; - } + if (kVerbose) { + kStdOut << "i64asm: found a base 2 number here: " + << jump_label.substr(pos) << "\n"; + } - for (char &i : num.number) - { - if (i == 0) - i = 0xFF; + for (char &i : num.number) { + if (i == 0) i = 0xFF; - kBytes.push_back(i); - } + kBytes.push_back(i); + } - return true; + return true; + } + case 'o': { + if (auto res = strtoq(jump_label.substr(pos + 2).c_str(), nullptr, 7); + !res) { + if (errno != 0) { + detail::print_error("invalid octal number: " + jump_label, "i64asm"); + throw std::runtime_error("invalid_octal"); } - case 'o': - { - if (auto res = strtoq(jump_label.substr(pos + 2).c_str(), - nullptr, 7); - !res) - { - if (errno != 0) - { - detail::print_error("invalid octal number: " + jump_label, "i64asm"); - throw std::runtime_error("invalid_octal"); - } - } + } - CompilerKit::NumberCast16 num = CompilerKit::NumberCast16(strtoq(jump_label.substr(pos + 2).c_str(), - nullptr, 7)); + CompilerKit::NumberCast16 num = CompilerKit::NumberCast16( + strtoq(jump_label.substr(pos + 2).c_str(), nullptr, 7)); - if (kVerbose) - { - kStdOut << "i64asm: found a base 8 number here: " << jump_label.substr(pos) << "\n"; - } + if (kVerbose) { + kStdOut << "i64asm: found a base 8 number here: " + << jump_label.substr(pos) << "\n"; + } - for (char &i : num.number) - { - if (i == 0) - i = 0xFF; + for (char &i : num.number) { + if (i == 0) i = 0xFF; - kBytes.push_back(i); - } + kBytes.push_back(i); + } - return true; - } - default: - { - break; - } + return true; + } + default: { + break; } + } - /* check for errno and stuff like that */ - if (auto res = strtoq(jump_label.substr(pos).c_str(), - nullptr, 10); - !res) - { - if (errno != 0) - { - return false; - } + /* check for errno and stuff like that */ + if (auto res = strtoq(jump_label.substr(pos).c_str(), nullptr, 10); !res) { + if (errno != 0) { + return false; } + } - CompilerKit::NumberCast16 num = CompilerKit::NumberCast16(strtoq(jump_label.substr(pos).c_str(), - nullptr, 10)); + CompilerKit::NumberCast16 num = CompilerKit::NumberCast16( + strtoq(jump_label.substr(pos).c_str(), nullptr, 10)); - for (char &i : num.number) - { - if (i == 0) - i = 0xFF; + for (char &i : num.number) { + if (i == 0) i = 0xFF; - kBytes.push_back(i); - } + kBytes.push_back(i); + } - if (kVerbose) - { - kStdOut << "i64asm: found a base 10 number here: " << jump_label.substr(pos) << "\n"; - } + if (kVerbose) { + kStdOut << "i64asm: found a base 10 number here: " << jump_label.substr(pos) + << "\n"; + } - return true; + return true; } -bool CompilerKit::PlatformAssemblerAMD64::WriteNumber8(const std::size_t &pos, std::string &jump_label) -{ - if (!isdigit(jump_label[pos])) - return false; - - switch (jump_label[pos + 1]) - { - case 'x': - { - if (auto res = strtoq(jump_label.substr(pos + 2).c_str(), - nullptr, 16); - !res) - { - if (errno != 0) - { - detail::print_error("invalid hex number: " + jump_label, "i64asm"); - throw std::runtime_error("invalid_hex"); - } - } +bool CompilerKit::PlatformAssemblerAMD64::WriteNumber8( + const std::size_t &pos, std::string &jump_label) { + if (!isdigit(jump_label[pos])) return false; + + switch (jump_label[pos + 1]) { + case 'x': { + if (auto res = strtoq(jump_label.substr(pos + 2).c_str(), nullptr, 16); + !res) { + if (errno != 0) { + detail::print_error("invalid hex number: " + jump_label, "i64asm"); + throw std::runtime_error("invalid_hex"); + } + } - CompilerKit::NumberCast8 num = CompilerKit::NumberCast8(strtoq(jump_label.substr(pos + 2).c_str(), - nullptr, 16)); + CompilerKit::NumberCast8 num = CompilerKit::NumberCast8( + strtoq(jump_label.substr(pos + 2).c_str(), nullptr, 16)); - kBytes.push_back(num.number); + kBytes.push_back(num.number); - if (kVerbose) - { - kStdOut << "i64asm: found a base 16 number here: " << jump_label.substr(pos) << "\n"; - } + if (kVerbose) { + kStdOut << "i64asm: found a base 16 number here: " + << jump_label.substr(pos) << "\n"; + } - return true; + return true; + } + case 'b': { + if (auto res = strtoq(jump_label.substr(pos + 2).c_str(), nullptr, 2); + !res) { + if (errno != 0) { + detail::print_error("invalid binary number: " + jump_label, "i64asm"); + throw std::runtime_error("invalid_bin"); } - case 'b': - { - if (auto res = strtoq(jump_label.substr(pos + 2).c_str(), - nullptr, 2); - !res) - { - if (errno != 0) - { - detail::print_error("invalid binary number: " + jump_label, "i64asm"); - throw std::runtime_error("invalid_bin"); - } - } + } - CompilerKit::NumberCast8 num = CompilerKit::NumberCast8(strtoq(jump_label.substr(pos + 2).c_str(), - nullptr, 2)); + CompilerKit::NumberCast8 num = CompilerKit::NumberCast8( + strtoq(jump_label.substr(pos + 2).c_str(), nullptr, 2)); - if (kVerbose) - { - kStdOut << "i64asm: found a base 2 number here: " << jump_label.substr(pos) << "\n"; - } + if (kVerbose) { + kStdOut << "i64asm: found a base 2 number here: " + << jump_label.substr(pos) << "\n"; + } - kBytes.push_back(num.number); + kBytes.push_back(num.number); - return true; + return true; + } + case 'o': { + if (auto res = strtoq(jump_label.substr(pos + 2).c_str(), nullptr, 7); + !res) { + if (errno != 0) { + detail::print_error("invalid octal number: " + jump_label, "i64asm"); + throw std::runtime_error("invalid_octal"); } - case 'o': - { - if (auto res = strtoq(jump_label.substr(pos + 2).c_str(), - nullptr, 7); - !res) - { - if (errno != 0) - { - detail::print_error("invalid octal number: " + jump_label, "i64asm"); - throw std::runtime_error("invalid_octal"); - } - } + } - CompilerKit::NumberCast8 num = CompilerKit::NumberCast8(strtoq(jump_label.substr(pos + 2).c_str(), - nullptr, 7)); + CompilerKit::NumberCast8 num = CompilerKit::NumberCast8( + strtoq(jump_label.substr(pos + 2).c_str(), nullptr, 7)); - if (kVerbose) - { - kStdOut << "i64asm: found a base 8 number here: " << jump_label.substr(pos) << "\n"; - } + if (kVerbose) { + kStdOut << "i64asm: found a base 8 number here: " + << jump_label.substr(pos) << "\n"; + } - kBytes.push_back(num.number); + kBytes.push_back(num.number); - return true; - } - default: - { - break; - } + return true; + } + default: { + break; } + } - /* check for errno and stuff like that */ - if (auto res = strtoq(jump_label.substr(pos).c_str(), - nullptr, 10); - !res) - { - if (errno != 0) - { - return false; - } + /* check for errno and stuff like that */ + if (auto res = strtoq(jump_label.substr(pos).c_str(), nullptr, 10); !res) { + if (errno != 0) { + return false; } + } - CompilerKit::NumberCast8 num = CompilerKit::NumberCast8(strtoq(jump_label.substr(pos).c_str(), - nullptr, 10)); + CompilerKit::NumberCast8 num = CompilerKit::NumberCast8( + strtoq(jump_label.substr(pos).c_str(), nullptr, 10)); - kBytes.push_back(num.number); + kBytes.push_back(num.number); - if (kVerbose) - { - kStdOut << "i64asm: found a base 10 number here: " << jump_label.substr(pos) << "\n"; - } + if (kVerbose) { + kStdOut << "i64asm: found a base 10 number here: " << jump_label.substr(pos) + << "\n"; + } - return true; + return true; } ///////////////////////////////////////////////////////////////////////////////////////// @@ -1161,146 +978,120 @@ bool CompilerKit::PlatformAssemblerAMD64::WriteNumber8(const std::size_t &pos, s ///////////////////////////////////////////////////////////////////////////////////////// -bool CompilerKit::PlatformAssemblerAMD64::WriteLine(std::string &line, const std::string &file) -{ - if (ParserKit::find_word(line, "export ")) - return true; - - for (auto &opcodeAMD64 : kOpcodesAMD64) - { - // strict check here - if (ParserKit::find_word(line, opcodeAMD64.fName) && - detail::algorithm::is_valid(line)) - { - std::string name(opcodeAMD64.fName); - - if (name.find("mov") != std::string::npos) - { - struct RegMapAMD64 { - std::string fName; - e64_byte_t fModRM; - }; - - std::vector<RegMapAMD64> regs { - { .fName = "ax", .fModRM = 0 }, - { .fName = "cx", .fModRM = 1 }, - { .fName = "dx", .fModRM = 2 }, - { .fName = "bx", .fModRM = 3 }, - { .fName = "sp", .fModRM = 4 }, - { .fName = "bp", .fModRM = 5 }, - { .fName = "si", .fModRM = 6 }, - { .fName = "di", .fModRM = 7 }, - }; - - std::string substr = line.substr(line.find(name) + name.size()); - - uint64_t bits = 16; - - if (substr.find(",") == std::string::npos) - { - detail::print_error("Invalid combination of operands and registers.", "i64asm"); - throw std::runtime_error("comb_op_reg"); - } - - bool found = false; - - for (auto& reg : regs) - { - if (line.find(reg.fName) != std::string::npos) - { - if (!found) - { - if (line.substr(line.find(reg.fName) - 1)[0] == 'r') - { - bits = 64; - - kBytes.emplace_back(0x48); - kBytes.emplace_back(0x89); - kBytes.emplace_back(0x00); - } - else - { - detail::print_error("Invalid combination of registers, each 64-bit register must start with 'r'.", "i64asm"); - throw std::runtime_error("comb_op_reg"); - } - - found = true; - - kBytes.push_back(0xc0 + reg.fModRM); - - continue; - } - } - } - - if (bits == 64) - this->WriteNumber32(line.find(name) + name.size() + 2, line); - else if (bits == 16) - this->WriteNumber16(line.find(name) + name.size() + 2, line); - else - { - detail::print_error("Invalid combination of operands and registers.", "i64asm"); - throw std::runtime_error("comb_op_reg"); - } - - break; - } - else if (name == "int" || - name == "into" || - name == "intd") - { - kBytes.emplace_back(opcodeAMD64.fOpcode); - this->WriteNumber8(line.find(name) + name.size() + 1, line); - - break; - } - else if (name == "jmp" || - name == "call") - { - kBytes.emplace_back(opcodeAMD64.fOpcode); - this->WriteNumber32(line.find(name) + name.size() + 1, line); +bool CompilerKit::PlatformAssemblerAMD64::WriteLine(std::string &line, + const std::string &file) { + if (ParserKit::find_word(line, "export ")) return true; + + for (auto &opcodeAMD64 : kOpcodesAMD64) { + // strict check here + if (ParserKit::find_word(line, opcodeAMD64.fName) && + detail::algorithm::is_valid(line)) { + std::string name(opcodeAMD64.fName); + + if (name.find("mov") != std::string::npos) { + struct RegMapAMD64 { + std::string fName; + e64_byte_t fModRM; + }; + + std::vector<RegMapAMD64> regs{ + {.fName = "ax", .fModRM = 0}, {.fName = "cx", .fModRM = 1}, + {.fName = "dx", .fModRM = 2}, {.fName = "bx", .fModRM = 3}, + {.fName = "sp", .fModRM = 4}, {.fName = "bp", .fModRM = 5}, + {.fName = "si", .fModRM = 6}, {.fName = "di", .fModRM = 7}, + }; + + std::string substr = line.substr(line.find(name) + name.size()); + + uint64_t bits = 16; + + if (substr.find(",") == std::string::npos) { + detail::print_error("Invalid combination of operands and registers.", + "i64asm"); + throw std::runtime_error("comb_op_reg"); + } - break; - } - else - { - kBytes.emplace_back(0); - kBytes.emplace_back(opcodeAMD64.fOpcode); + bool found = false; - break; + for (auto ® : regs) { + if (line.find(reg.fName) != std::string::npos) { + if (!found) { + if (line.substr(line.find(reg.fName) - 1)[0] == 'r') { + bits = 64; + + kBytes.emplace_back(0x48); + kBytes.emplace_back(0x89); + kBytes.emplace_back(0x00); + } else { + detail::print_error( + "Invalid combination of registers, each 64-bit register " + "must start with 'r'.", + "i64asm"); + throw std::runtime_error("comb_op_reg"); + } + + found = true; + + kBytes.push_back(0xc0 + reg.fModRM); + + continue; } + } } - } - if (line.find("db") != std::string::npos) - { - this->WriteNumber(line.find("db") + strlen("db") + 1, line); + if (bits == 64) + this->WriteNumber32(line.find(name) + name.size() + 2, line); + else if (bits == 16) + this->WriteNumber16(line.find(name) + name.size() + 2, line); + else { + detail::print_error("Invalid combination of operands and registers.", + "i64asm"); + throw std::runtime_error("comb_op_reg"); + } + + break; + } else if (name == "int" || name == "into" || name == "intd") { + kBytes.emplace_back(opcodeAMD64.fOpcode); + this->WriteNumber8(line.find(name) + name.size() + 1, line); + + break; + } else if (name == "jmp" || name == "call") { + kBytes.emplace_back(opcodeAMD64.fOpcode); + this->WriteNumber32(line.find(name) + name.size() + 1, line); + + break; + } else { + kBytes.emplace_back(0); + kBytes.emplace_back(opcodeAMD64.fOpcode); + + break; + } } - if (line.find("org ") != std::string::npos) - { - size_t base[] = {10, 16, 2, 7}; - - for (size_t i = 0; i < 4; i++) - { - if (kOrigin = strtol((line.substr(line.find("org") + strlen("org") + 1)).c_str(), nullptr, base[i]); - kOrigin) - { - if (errno != 0) - { - continue; - } - else - { - if (kVerbose) - { - kStdOut << "Origin: " << kOrigin << std::endl; - } - } - } + } + + if (line.find("db") != std::string::npos) { + this->WriteNumber(line.find("db") + strlen("db") + 1, line); + } + if (line.find("org ") != std::string::npos) { + size_t base[] = {10, 16, 2, 7}; + + for (size_t i = 0; i < 4; i++) { + if (kOrigin = strtol( + (line.substr(line.find("org") + strlen("org") + 1)).c_str(), + nullptr, base[i]); + kOrigin) { + if (errno != 0) { + continue; + } else { + if (kVerbose) { + kStdOut << "Origin: " << kOrigin << std::endl; + } } + } } + } - return true; + return true; } -// Last rev 13-1-24
\ No newline at end of file +// Last rev 13-1-24 diff --git a/Private/Toolchain/ld.cc b/Private/Toolchain/ld.cc index 239c622..814cb14 100644 --- a/Private/Toolchain/ld.cc +++ b/Private/Toolchain/ld.cc @@ -25,11 +25,11 @@ #include <CompilerKit/StdKit/PEF.hpp> //! Advanced Executable Object Format -#include <CompilerKit/StdKit/AE.hpp> +#include <uuid/uuid.h> +#include <CompilerKit/StdKit/AE.hpp> #include <fstream> #include <iostream> -#include <uuid/uuid.h> //! @brief standard PEF entry. #define kPefStart "__start" @@ -67,534 +67,484 @@ static const char *kLdDynamicSym = ":mld:"; static std::vector<std::string> kObjectList; static std::vector<char> kObjectBytes; -MPCC_MODULE(MPUXLinker) -{ - bool is_executable = true; - - /** - * @brief parse flags and such. - * - */ - for (size_t i = 1; i < argc; ++i) - { - if (StringCompare(argv[i], "-h") == 0) - { - kStdOut << kToolVersion << "\n"; - kStdOut << "-version: Show program version.\n"; - kStdOut << "-verbose: Enable program trace.\n"; - kStdOut << "-shared: Output as a shared PEF.\n"; - kStdOut << "-fat-bin: Output as FAT PEF.\n"; - kStdOut << "-32x0: Output as 32x0 PEF.\n"; - kStdOut << "-64x0: Output as 64x0 PEF.\n"; - kStdOut << "-output-file: Select output file name.\n"; - - return 0; - } - else if (StringCompare(argv[i], "-version") == 0) - { - kStdOut << kToolVersion << std::endl; +MPCC_MODULE(MPUXLinker) { + bool is_executable = true; + + /** + * @brief parse flags and such. + * + */ + for (size_t i = 1; i < argc; ++i) { + if (StringCompare(argv[i], "-h") == 0) { + kStdOut << kToolVersion << "\n"; + kStdOut << "-version: Show program version.\n"; + kStdOut << "-verbose: Enable program trace.\n"; + kStdOut << "-shared: Output as a shared PEF.\n"; + kStdOut << "-fat-bin: Output as FAT PEF.\n"; + kStdOut << "-32x0: Output as 32x0 PEF.\n"; + kStdOut << "-64x0: Output as 64x0 PEF.\n"; + kStdOut << "-output-file: Select output file name.\n"; + + return 0; + } else if (StringCompare(argv[i], "-version") == 0) { + kStdOut << kToolVersion << std::endl; + + return 0; + } else if (StringCompare(argv[i], "-fat-bin") == 0) { + kFatBinaryEnable = true; + + continue; + } else if (StringCompare(argv[i], "-64x0") == 0) { + kArch = CompilerKit::kPefArch64000; + + continue; + } else if (StringCompare(argv[i], "-32x0") == 0) { + kArch = CompilerKit::kPefArch32000; + + continue; + } else if (StringCompare(argv[i], "-verbose") == 0) { + kVerbose = true; + + continue; + } else if (StringCompare(argv[i], "-shared") == 0) { + if (kOutput.find(kPefExt) != std::string::npos) + kOutput.erase(kOutput.find(kPefExt), strlen(kPefExt)); + + kOutput += kPefDylibExt; + + is_executable = false; + + continue; + } else if (StringCompare(argv[i], "-output-file") == 0) { + kOutput = argv[i + 1]; + ++i; + + continue; + } else { + if (argv[i][0] == '-') { + kStdOut << "ld: unknown flag: " << argv[i] << "\n"; + return -CXXKIT_EXEC_ERROR; + } - return 0; - } - else if (StringCompare(argv[i], "-fat-bin") == 0) - { - kFatBinaryEnable = true; + kObjectList.emplace_back(argv[i]); - continue; - } - else if (StringCompare(argv[i], "-64x0") == 0) - { - kArch = CompilerKit::kPefArch64000; + continue; + } + } + + // sanity check. + if (kObjectList.empty()) { + kStdOut << "ld: no input files." << std::endl; + return CXXKIT_EXEC_ERROR; + } else { + // check for existing files, if they don't throw an error. + for (auto &obj : kObjectList) { + if (!std::filesystem::exists(obj)) { + // if filesystem doesn't find file + // -> throw error. + kStdOut << "ld: no such file: " << obj << std::endl; + return CXXKIT_EXEC_ERROR; + } + } + } - continue; - } - else if (StringCompare(argv[i], "-32x0") == 0) - { - kArch = CompilerKit::kPefArch32000; + // PEF expects a valid architecture when outputing a binary. + if (kArch == 0) { + kStdOut << "ld: no target architecture set, can't continue." << std::endl; + return CXXKIT_EXEC_ERROR; + } - continue; - } - else if (StringCompare(argv[i], "-verbose") == 0) - { - kVerbose = true; + CompilerKit::PEFContainer pef_container{}; - continue; - } - else if (StringCompare(argv[i], "-shared") == 0) - { - if (kOutput.find(kPefExt) != std::string::npos) - kOutput.erase(kOutput.find(kPefExt), strlen(kPefExt)); + int32_t archs = kArch; - kOutput += kPefDylibExt; + pef_container.Count = 0UL; + pef_container.Kind = CompilerKit::kPefKindExec; + pef_container.SubCpu = kSubArch; + pef_container.Linker = kPefLinkerNumId; // Mahrouss Logic Linker + pef_container.Abi = kAbi; // Multi-Processor UX ABI + pef_container.Magic[0] = kPefMagic[kFatBinaryEnable ? 2 : 0]; + pef_container.Magic[1] = kPefMagic[1]; + pef_container.Magic[2] = kPefMagic[kFatBinaryEnable ? 0 : 2]; + pef_container.Version = kPefVersion; - is_executable = false; + // specify the start address, can be 0x10000 + pef_container.Start = kPefDeaultOrg; + pef_container.HdrSz = sizeof(CompilerKit::PEFContainer); - continue; - } - else if (StringCompare(argv[i], "-output-file") == 0) - { - kOutput = argv[i + 1]; - ++i; + std::ofstream output_fc(kOutput, std::ofstream::binary); - continue; - } - else - { - if (argv[i][0] == '-') - { - kStdOut << "ld: unknown flag: " << argv[i] << "\n"; - return -CXXKIT_EXEC_ERROR; - } + if (output_fc.bad()) { + if (kVerbose) { + kStdOut << "ld: error: " << strerror(errno) << "\n"; + } - kObjectList.emplace_back(argv[i]); + return -CXXKIT_FILE_NOT_FOUND; + } - continue; - } - } + //! Read AE to convert as PEF. - // sanity check. - if (kObjectList.empty()) - { - kStdOut << "ld: no input files." << std::endl; - return CXXKIT_EXEC_ERROR; - } - else - { - // check for existing files, if they don't throw an error. - for (auto &obj : kObjectList) - { - if (!std::filesystem::exists(obj)) - { - // if filesystem doesn't find file - // -> throw error. - kStdOut << "ld: no such file: " << obj << std::endl; - return CXXKIT_EXEC_ERROR; - } - } - } + std::vector<CompilerKit::PEFCommandHeader> pef_command_hdrs; + CompilerKit::Utils::AEReadableProtocol readProto{}; - // PEF expects a valid architecture when outputing a binary. - if (kArch == 0) - { - kStdOut << "ld: no target architecture set, can't continue." << std::endl; - return CXXKIT_EXEC_ERROR; - } + for (const auto &i : kObjectList) { + if (!std::filesystem::exists(i)) continue; - CompilerKit::PEFContainer pef_container{}; + CompilerKit::AEHeader hdr{}; - int32_t archs = kArch; + readProto.FP = std::ifstream(i, std::ifstream::binary); + readProto.FP >> hdr; - pef_container.Count = 0UL; - pef_container.Kind = CompilerKit::kPefKindExec; - pef_container.SubCpu = kSubArch; - pef_container.Linker = kPefLinkerNumId; // Mahrouss Logic Linker - pef_container.Abi = kAbi; // Multi-Processor UX ABI - pef_container.Magic[0] = kPefMagic[kFatBinaryEnable ? 2 : 0]; - pef_container.Magic[1] = kPefMagic[1]; - pef_container.Magic[2] = kPefMagic[kFatBinaryEnable ? 0 : 2]; - pef_container.Version = kPefVersion; + auto ae_header = hdr; - // specify the start address, can be 0x10000 - pef_container.Start = kPefDeaultOrg; - pef_container.HdrSz = sizeof(CompilerKit::PEFContainer); + if (ae_header.fMagic[0] == kAEMag0 && ae_header.fMagic[1] == kAEMag1 && + ae_header.fSize == sizeof(CompilerKit::AEHeader)) { + if (ae_header.fArch != kArch) { + if (kVerbose) kStdOut << "ld: info: is a fat binary? : "; - std::ofstream output_fc(kOutput, std::ofstream::binary); + if (!kFatBinaryEnable) { + if (kVerbose) kStdOut << "no.\n"; - if (output_fc.bad()) - { - if (kVerbose) - { - kStdOut << "ld: error: " << strerror(errno) << "\n"; + kStdOut << "ld: error: object " << i + << " is a different kind of architecture and output isn't " + "treated as FAT binary." + << std::endl; + + std::remove(kOutput.c_str()); + return -CXXKIT_FAT_ERROR; + } else { + if (kVerbose) { + kStdOut << "yes.\n"; + } } + } - return -CXXKIT_FILE_NOT_FOUND; - } + // append arch type to archs varaible. + archs |= ae_header.fArch; + std::size_t cnt = ae_header.fCount; - //! Read AE to convert as PEF. - - std::vector<CompilerKit::PEFCommandHeader> pef_command_hdrs; - CompilerKit::Utils::AEReadableProtocol readProto{}; - - for (const auto &i : kObjectList) - { - if (!std::filesystem::exists(i)) - continue; - - CompilerKit::AEHeader hdr{}; - - readProto.FP = std::ifstream(i, std::ifstream::binary); - readProto.FP >> hdr; - - auto ae_header = hdr; - - if (ae_header.fMagic[0] == kAEMag0 && - ae_header.fMagic[1] == kAEMag1 && - ae_header.fSize == sizeof(CompilerKit::AEHeader)) - { - if (ae_header.fArch != kArch) - { - if (kVerbose) - kStdOut << "ld: info: is a fat binary? : "; - - if (!kFatBinaryEnable) - { - if (kVerbose) - kStdOut << "no.\n"; - - kStdOut << "ld: error: object " << i << " is a different kind of architecture and output isn't treated as FAT binary." << std::endl; - - std::remove(kOutput.c_str()); - return -CXXKIT_FAT_ERROR; - } - else - { - if (kVerbose) - { - kStdOut << "yes.\n"; - } - } - } + if (kVerbose) + kStdOut << "ld: object header found, record count: " << cnt << "\n"; - // append arch type to archs varaible. - archs |= ae_header.fArch; - std::size_t cnt = ae_header.fCount; - - if (kVerbose) - kStdOut << "ld: object header found, record count: " << cnt << "\n"; - - pef_container.Count = cnt; - - char_type *raw_ae_records = new char[cnt * sizeof(CompilerKit::AERecordHeader)]; - memset(raw_ae_records, 0, cnt * sizeof(CompilerKit::AERecordHeader)); - - auto *ae_records = readProto.Read(raw_ae_records, cnt); - - for (size_t ae_record_index = 0; ae_record_index < cnt; ++ae_record_index) - { - CompilerKit::PEFCommandHeader command_header{0}; - - memcpy(command_header.Name, ae_records[ae_record_index].fName, kPefNameLen); - - // check this header if it's any valid. - if (std::string(command_header.Name).find(".text") == std::string::npos && - std::string(command_header.Name).find(".data") == std::string::npos && - std::string(command_header.Name).find(".page_zero") == std::string::npos) - { - if (std::string(command_header.Name).find(kPefStart) == std::string::npos && - *command_header.Name == 0) - { - if (std::string(command_header.Name).find(kLdDefineSymbol) != std::string::npos) - { - goto ld_mark_header; - } - else - { - continue; - } - } - } - - if (std::string(command_header.Name).find(kPefStart) != std::string::npos && - std::string(command_header.Name).find(".text") != std::string::npos) - { - kStartFound = true; - pef_container.Start = ae_records[ae_record_index].fOffset; - } - - ld_mark_header: - command_header.Offset = ae_records[ae_record_index].fOffset; - command_header.Kind = ae_records[ae_record_index].fKind; - command_header.Size = ae_records[ae_record_index].fSize; - - if (kVerbose) - kStdOut << "ld: object record: " << ae_records[ae_record_index].fName << " was marked.\n"; - - pef_command_hdrs.emplace_back(command_header); - } + pef_container.Count = cnt; - delete[] raw_ae_records; + char_type *raw_ae_records = + new char[cnt * sizeof(CompilerKit::AERecordHeader)]; + memset(raw_ae_records, 0, cnt * sizeof(CompilerKit::AERecordHeader)); - std::vector<char> bytes; - bytes.resize(ae_header.fCodeSize); + auto *ae_records = readProto.Read(raw_ae_records, cnt); - readProto.FP.seekg(std::streamsize(ae_header.fStartCode)); - readProto.FP.read(bytes.data(), std::streamsize(ae_header.fCodeSize)); + for (size_t ae_record_index = 0; ae_record_index < cnt; + ++ae_record_index) { + CompilerKit::PEFCommandHeader command_header{0}; - for (auto &byte : bytes) - { - kObjectBytes.push_back(byte); - } + memcpy(command_header.Name, ae_records[ae_record_index].fName, + kPefNameLen); - readProto.FP.close(); + // check this header if it's any valid. + if (std::string(command_header.Name).find(".text") == + std::string::npos && + std::string(command_header.Name).find(".data") == + std::string::npos && + std::string(command_header.Name).find(".page_zero") == + std::string::npos) { + if (std::string(command_header.Name).find(kPefStart) == + std::string::npos && + *command_header.Name == 0) { + if (std::string(command_header.Name).find(kLdDefineSymbol) != + std::string::npos) { + goto ld_mark_header; + } else { + continue; + } + } + } - continue; + if (std::string(command_header.Name).find(kPefStart) != + std::string::npos && + std::string(command_header.Name).find(".text") != + std::string::npos) { + kStartFound = true; + pef_container.Start = ae_records[ae_record_index].fOffset; } - kStdOut << "ld: not an object: " << i << std::endl; - std::remove(kOutput.c_str()); + ld_mark_header: + command_header.Offset = ae_records[ae_record_index].fOffset; + command_header.Kind = ae_records[ae_record_index].fKind; + command_header.Size = ae_records[ae_record_index].fSize; - // don't continue, it is a fatal error. - return -CXXKIT_EXEC_ERROR; - } + if (kVerbose) + kStdOut << "ld: object record: " << ae_records[ae_record_index].fName + << " was marked.\n"; - pef_container.Cpu = archs; + pef_command_hdrs.emplace_back(command_header); + } - output_fc << pef_container; + delete[] raw_ae_records; - if (kVerbose) - { - kStdOut << "ld: pef: wrote container header.\n"; + std::vector<char> bytes; + bytes.resize(ae_header.fCodeSize); + + readProto.FP.seekg(std::streamsize(ae_header.fStartCode)); + readProto.FP.read(bytes.data(), std::streamsize(ae_header.fCodeSize)); + + for (auto &byte : bytes) { + kObjectBytes.push_back(byte); + } + + readProto.FP.close(); + + continue; } - output_fc.seekp(std::streamsize(pef_container.HdrSz)); + kStdOut << "ld: not an object: " << i << std::endl; + std::remove(kOutput.c_str()); - std::vector<std::string> not_found; - std::vector<std::string> symbols; + // don't continue, it is a fatal error. + return -CXXKIT_EXEC_ERROR; + } - // step 2: check for errors (multiple symbols, undefined ones) + pef_container.Cpu = archs; - for (auto &pef_command_hdr : pef_command_hdrs) - { - // check if this symbol needs to be resolved. - if (std::string(pef_command_hdr.Name).find(kLdDefineSymbol) != - std::string::npos && - std::string(pef_command_hdr.Name).find(kLdDynamicSym) == - std::string::npos) - { - if (kVerbose) - kStdOut << "ld: found undefined symbol: " << pef_command_hdr.Name << "\n"; - - if (auto it = std::find(not_found.begin(), not_found.end(), std::string(pef_command_hdr.Name)); - it == not_found.end()) - { - not_found.emplace_back(pef_command_hdr.Name); - } - } + output_fc << pef_container; + + if (kVerbose) { + kStdOut << "ld: pef: wrote container header.\n"; + } + + output_fc.seekp(std::streamsize(pef_container.HdrSz)); + + std::vector<std::string> not_found; + std::vector<std::string> symbols; + + // step 2: check for errors (multiple symbols, undefined ones) - symbols.emplace_back(pef_command_hdr.Name); + for (auto &pef_command_hdr : pef_command_hdrs) { + // check if this symbol needs to be resolved. + if (std::string(pef_command_hdr.Name).find(kLdDefineSymbol) != + std::string::npos && + std::string(pef_command_hdr.Name).find(kLdDynamicSym) == + std::string::npos) { + if (kVerbose) + kStdOut << "ld: found undefined symbol: " << pef_command_hdr.Name + << "\n"; + + if (auto it = std::find(not_found.begin(), not_found.end(), + std::string(pef_command_hdr.Name)); + it == not_found.end()) { + not_found.emplace_back(pef_command_hdr.Name); + } } - // Now try to solve these symbols. + symbols.emplace_back(pef_command_hdr.Name); + } - for (size_t not_found_idx = 0; not_found_idx < pef_command_hdrs.size(); ++not_found_idx) - { - if (auto it = std::find(not_found.begin(), not_found.end(), std::string(pef_command_hdrs[not_found_idx].Name)); - it != not_found.end()) - { - std::string symbol_imp = *it; + // Now try to solve these symbols. - if (symbol_imp.find(kLdDefineSymbol) == std::string::npos) - continue; + for (size_t not_found_idx = 0; not_found_idx < pef_command_hdrs.size(); + ++not_found_idx) { + if (auto it = std::find(not_found.begin(), not_found.end(), + std::string(pef_command_hdrs[not_found_idx].Name)); + it != not_found.end()) { + std::string symbol_imp = *it; - // erase the lookup prefix. - symbol_imp.erase(0, symbol_imp.find(kLdDefineSymbol) + strlen(kLdDefineSymbol)); + if (symbol_imp.find(kLdDefineSymbol) == std::string::npos) continue; - // demangle everything. - while (symbol_imp.find('$') != std::string::npos) - symbol_imp.erase(symbol_imp.find('$'), 1); + // erase the lookup prefix. + symbol_imp.erase( + 0, symbol_imp.find(kLdDefineSymbol) + strlen(kLdDefineSymbol)); - // the reason we do is because, this may not match the symbol, and we need - // to look for other matching symbols. - for (auto &pef_command_hdr : pef_command_hdrs) - { - if (std::string(pef_command_hdr.Name).find(symbol_imp) != std::string::npos && - std::string(pef_command_hdr.Name).find(kLdDefineSymbol) == std::string::npos) - { - std::string undefined_symbol = pef_command_hdr.Name; - auto result_of_sym = undefined_symbol.substr(undefined_symbol.find(symbol_imp)); + // demangle everything. + while (symbol_imp.find('$') != std::string::npos) + symbol_imp.erase(symbol_imp.find('$'), 1); - for (int i = 0; result_of_sym[i] != 0; ++i) - { - if (result_of_sym[i] != symbol_imp[i]) - goto ld_continue_search; - } + // the reason we do is because, this may not match the symbol, and we need + // to look for other matching symbols. + for (auto &pef_command_hdr : pef_command_hdrs) { + if (std::string(pef_command_hdr.Name).find(symbol_imp) != + std::string::npos && + std::string(pef_command_hdr.Name).find(kLdDefineSymbol) == + std::string::npos) { + std::string undefined_symbol = pef_command_hdr.Name; + auto result_of_sym = + undefined_symbol.substr(undefined_symbol.find(symbol_imp)); - not_found.erase(it); + for (int i = 0; result_of_sym[i] != 0; ++i) { + if (result_of_sym[i] != symbol_imp[i]) goto ld_continue_search; + } - if (kVerbose) - kStdOut << "ld: found symbol: " << pef_command_hdr.Name << "\n"; + not_found.erase(it); - break; - } - } + if (kVerbose) + kStdOut << "ld: found symbol: " << pef_command_hdr.Name << "\n"; - ld_continue_search: - continue; + break; } + } + + ld_continue_search: + continue; } + } - // step 3: check for errors (recheck if we have those symbols.) + // step 3: check for errors (recheck if we have those symbols.) - if (!kStartFound && is_executable) - { - if (kVerbose) - kStdOut << "ld: undefined symbol: __start, you may have forget to link against your runtime library.\n"; + if (!kStartFound && is_executable) { + if (kVerbose) + kStdOut << "ld: undefined symbol: __start, you may have forget to link " + "against your runtime library.\n"; - kStdOut << "ld: undefined entrypoint " << kPefStart << " for executable " << kOutput << "\n"; - } + kStdOut << "ld: undefined entrypoint " << kPefStart << " for executable " + << kOutput << "\n"; + } - // step 4: write some pef commands. + // step 4: write some pef commands. - CompilerKit::PEFCommandHeader date_header{}; + CompilerKit::PEFCommandHeader date_header{}; - time_t timestamp = time(nullptr); + time_t timestamp = time(nullptr); - std::string timestamp_str = "ContainerDate:"; - timestamp_str += std::to_string(timestamp); + std::string timestamp_str = "ContainerDate:"; + timestamp_str += std::to_string(timestamp); - strcpy(date_header.Name, timestamp_str.c_str()); + strcpy(date_header.Name, timestamp_str.c_str()); - date_header.Flags = 0; - date_header.Kind = CompilerKit::kPefData; - date_header.Offset = output_fc.tellp(); - date_header.Size = timestamp_str.size(); + date_header.Flags = 0; + date_header.Kind = CompilerKit::kPefData; + date_header.Offset = output_fc.tellp(); + date_header.Size = timestamp_str.size(); - output_fc << date_header; + output_fc << date_header; - CompilerKit::PEFCommandHeader abi_header{}; + CompilerKit::PEFCommandHeader abi_header{}; - memcpy(abi_header.Name, kPefAbiId, strlen(kPefAbiId)); + memcpy(abi_header.Name, kPefAbiId, strlen(kPefAbiId)); - abi_header.Size = strlen(kPefAbiId); - abi_header.Offset = output_fc.tellp(); - abi_header.Flags = 0; - abi_header.Kind = CompilerKit::kPefLinkerID; + abi_header.Size = strlen(kPefAbiId); + abi_header.Offset = output_fc.tellp(); + abi_header.Flags = 0; + abi_header.Kind = CompilerKit::kPefLinkerID; - output_fc << abi_header; + output_fc << abi_header; - CompilerKit::PEFCommandHeader uuid_header{}; + CompilerKit::PEFCommandHeader uuid_header{}; - uuid_t uuid{0}; - uuid_generate_random(uuid); + uuid_t uuid{0}; + uuid_generate_random(uuid); - memcpy(uuid_header.Name, "UUID_TYPE:4:", strlen("UUID_TYPE:4:")); - memcpy(uuid_header.Name + strlen("UUID_TYPE:4:"), uuid, 16); + memcpy(uuid_header.Name, "UUID_TYPE:4:", strlen("UUID_TYPE:4:")); + memcpy(uuid_header.Name + strlen("UUID_TYPE:4:"), uuid, 16); - uuid_header.Size = 16; - uuid_header.Offset = output_fc.tellp(); - uuid_header.Flags = 0; - uuid_header.Kind = 0; + uuid_header.Size = 16; + uuid_header.Offset = output_fc.tellp(); + uuid_header.Flags = 0; + uuid_header.Kind = 0; - output_fc << uuid_header; + output_fc << uuid_header; - // prepare a symbol vector. - std::vector<std::string> undefined_symbols; - std::vector<std::string> duplicate_symbols; - std::vector<std::string> symbols_to_resolve; + // prepare a symbol vector. + std::vector<std::string> undefined_symbols; + std::vector<std::string> duplicate_symbols; + std::vector<std::string> symbols_to_resolve; - // Finally write down the command headers. - // And check for any duplications - for (size_t cmd_hdr = 0UL; cmd_hdr < pef_command_hdrs.size(); ++cmd_hdr) - { - if (std::string(pef_command_hdrs[cmd_hdr].Name).find(kLdDefineSymbol) != - std::string::npos && - std::string(pef_command_hdrs[cmd_hdr].Name).find(kLdDynamicSym) == - std::string::npos) - { - // ignore :ld: headers, they do not contain code. - continue; - } + // Finally write down the command headers. + // And check for any duplications + for (size_t cmd_hdr = 0UL; cmd_hdr < pef_command_hdrs.size(); ++cmd_hdr) { + if (std::string(pef_command_hdrs[cmd_hdr].Name).find(kLdDefineSymbol) != + std::string::npos && + std::string(pef_command_hdrs[cmd_hdr].Name).find(kLdDynamicSym) == + std::string::npos) { + // ignore :ld: headers, they do not contain code. + continue; + } - std::string sym_name = pef_command_hdrs[cmd_hdr].Name; + std::string sym_name = pef_command_hdrs[cmd_hdr].Name; - if (!sym_name.empty()) - { - undefined_symbols.emplace_back(sym_name); - } + if (!sym_name.empty()) { + undefined_symbols.emplace_back(sym_name); + } - output_fc << pef_command_hdrs[cmd_hdr]; - - for (size_t cmd_hdr_sub = 0UL; cmd_hdr_sub < pef_command_hdrs.size(); ++cmd_hdr_sub) - { - if (cmd_hdr_sub == cmd_hdr) - continue; - - if (std::string(pef_command_hdrs[cmd_hdr_sub].Name).find(kLdDefineSymbol) != - std::string::npos && - std::string(pef_command_hdrs[cmd_hdr_sub].Name).find(kLdDynamicSym) == - std::string::npos) - { - if (kVerbose) - { - kStdOut << "ld: ignore :ld: command header...\n"; - } - - // ignore :ld: headers, they do not contain code. - continue; - } + output_fc << pef_command_hdrs[cmd_hdr]; - auto &pef_command_hdr = pef_command_hdrs[cmd_hdr_sub]; + for (size_t cmd_hdr_sub = 0UL; cmd_hdr_sub < pef_command_hdrs.size(); + ++cmd_hdr_sub) { + if (cmd_hdr_sub == cmd_hdr) continue; - if (pef_command_hdr.Name == std::string(pef_command_hdrs[cmd_hdr].Name)) - { - if (std::find(duplicate_symbols.cbegin(), duplicate_symbols.cend(), pef_command_hdr.Name) == duplicate_symbols.cend()) - { - duplicate_symbols.emplace_back(pef_command_hdr.Name); - } + if (std::string(pef_command_hdrs[cmd_hdr_sub].Name) + .find(kLdDefineSymbol) != std::string::npos && + std::string(pef_command_hdrs[cmd_hdr_sub].Name).find(kLdDynamicSym) == + std::string::npos) { + if (kVerbose) { + kStdOut << "ld: ignore :ld: command header...\n"; + } - if (kVerbose) - kStdOut << "ld: found duplicate symbol: " << pef_command_hdr.Name << "\n"; + // ignore :ld: headers, they do not contain code. + continue; + } - kDuplicateSymbols = true; - } - } - } + auto &pef_command_hdr = pef_command_hdrs[cmd_hdr_sub]; - if (!duplicate_symbols.empty()) - { - for (auto &symbol : duplicate_symbols) - { - kStdOut << "ld: multiple symbols of " << symbol << ".\n"; + if (pef_command_hdr.Name == std::string(pef_command_hdrs[cmd_hdr].Name)) { + if (std::find(duplicate_symbols.cbegin(), duplicate_symbols.cend(), + pef_command_hdr.Name) == duplicate_symbols.cend()) { + duplicate_symbols.emplace_back(pef_command_hdr.Name); } - std::remove(kOutput.c_str()); - return -CXXKIT_EXEC_ERROR; - } + if (kVerbose) + kStdOut << "ld: found duplicate symbol: " << pef_command_hdr.Name + << "\n"; - // step 2.5: write program bytes. + kDuplicateSymbols = true; + } + } + } - for (auto byte : kObjectBytes) - { - output_fc << byte; + if (!duplicate_symbols.empty()) { + for (auto &symbol : duplicate_symbols) { + kStdOut << "ld: multiple symbols of " << symbol << ".\n"; } - if (kVerbose) - kStdOut << "ld: wrote code for: " << kOutput << "\n"; + std::remove(kOutput.c_str()); + return -CXXKIT_EXEC_ERROR; + } - // step 3: check if we have those symbols + // step 2.5: write program bytes. - std::vector<std::string> unreferenced_symbols; + for (auto byte : kObjectBytes) { + output_fc << byte; + } - for (auto &pef_command_hdr : pef_command_hdrs) - { - if (auto it = std::find(not_found.begin(), not_found.end(), std::string(pef_command_hdr.Name)); - it != not_found.end()) - { - unreferenced_symbols.emplace_back(pef_command_hdr.Name); - } + if (kVerbose) kStdOut << "ld: wrote code for: " << kOutput << "\n"; + + // step 3: check if we have those symbols + + std::vector<std::string> unreferenced_symbols; + + for (auto &pef_command_hdr : pef_command_hdrs) { + if (auto it = std::find(not_found.begin(), not_found.end(), + std::string(pef_command_hdr.Name)); + it != not_found.end()) { + unreferenced_symbols.emplace_back(pef_command_hdr.Name); } + } - if (!unreferenced_symbols.empty()) - { - for (auto &unreferenced_symbol : unreferenced_symbols) - { - kStdOut << "ld: undefined symbol " << unreferenced_symbol << "\n"; - } + if (!unreferenced_symbols.empty()) { + for (auto &unreferenced_symbol : unreferenced_symbols) { + kStdOut << "ld: undefined symbol " << unreferenced_symbol << "\n"; } + } - if (!kStartFound || - kDuplicateSymbols && - std::filesystem::exists(kOutput) || - !unreferenced_symbols.empty()) - { - if (kVerbose) - kStdOut << "ld: code for: " << kOutput << ", is corrupt, removing file...\n"; + if (!kStartFound || kDuplicateSymbols && std::filesystem::exists(kOutput) || + !unreferenced_symbols.empty()) { + if (kVerbose) + kStdOut << "ld: code for: " << kOutput + << ", is corrupt, removing file...\n"; - std::remove(kOutput.c_str()); - return -CXXKIT_EXEC_ERROR; - } + std::remove(kOutput.c_str()); + return -CXXKIT_EXEC_ERROR; + } - return 0; + return 0; } -// Last rev 13-1-24
\ No newline at end of file +// Last rev 13-1-24 diff --git a/Public/PDF/325462-sdm-vol-1-2abcd-3abcd-4.pdf b/Public/Documentation/325462-sdm-vol-1-2abcd-3abcd-4.pdf Binary files differindex 2481790..2481790 100644 --- a/Public/PDF/325462-sdm-vol-1-2abcd-3abcd-4.pdf +++ b/Public/Documentation/325462-sdm-vol-1-2abcd-3abcd-4.pdf diff --git a/Public/PDF/ASM_SPECS.TXT b/Public/Documentation/ASM_SPECS.TXT index a0c42bf..a0c42bf 100644 --- a/Public/PDF/ASM_SPECS.TXT +++ b/Public/Documentation/ASM_SPECS.TXT diff --git a/Public/PDF/HAVP.TXT b/Public/Documentation/HAVP.TXT index 12fcec5..12fcec5 100644 --- a/Public/PDF/HAVP.TXT +++ b/Public/Documentation/HAVP.TXT diff --git a/Public/PDF/Inside 64x0.pdf b/Public/Documentation/Inside 64x0.pdf Binary files differindex bcd6782..bcd6782 100644 --- a/Public/PDF/Inside 64x0.pdf +++ b/Public/Documentation/Inside 64x0.pdf diff --git a/Public/PDF/NOTICE.TXT b/Public/Documentation/NOTICE.TXT index 23691da..23691da 100644 --- a/Public/PDF/NOTICE.TXT +++ b/Public/Documentation/NOTICE.TXT diff --git a/Public/PDF/VNRP.TXT b/Public/Documentation/VNRP.TXT index e17b494..e17b494 100644 --- a/Public/PDF/VNRP.TXT +++ b/Public/Documentation/VNRP.TXT |
