summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAmlal <amlalelmahrouss@icloud.com>2024-07-28 16:12:39 +0000
committerAmlal <amlalelmahrouss@icloud.com>2024-07-28 16:12:39 +0000
commit6f54c8fb68063ffac8ff88bb146914df28cb8134 (patch)
treeb1fa96a4211a1563b3ebc7724aa3c281ea8fa56f
parent7a6ac1d9cd3128a9ef96bf675a06963a617b5673 (diff)
parent231899b44a7294bb968c2a930c97f76990376f41 (diff)
Merged in MHR-36 (pull request #6)
MHR-36
-rw-r--r--.gitignore24
-rw-r--r--.vscode/c_cpp_properties.json60
-rw-r--r--64asm.rsrc27
-rw-r--r--64x0-cc.rsrc27
-rw-r--r--Doxyfile8
-rw-r--r--Examples/Example64k.s3
-rw-r--r--Examples/ExampleAMD64.asm6
-rw-r--r--Examples/ExampleAMD64_Return.asm6
-rw-r--r--Examples/ExampleCDialect.S28
-rw-r--r--Examples/ExampleCDialect.c20
-rw-r--r--Examples/ExamplePowerPC.S8
-rw-r--r--Examples/ExamplePowerPC.S.pp11
-rw-r--r--Examples/ExamplePowerPC.dmp5
-rw-r--r--Headers/Version.hxx3
-rw-r--r--Icons/app-logo.icobin108478 -> 0 bytes
-rw-r--r--NDKKit/AsmKit/AsmKit.hpp (renamed from Headers/AsmKit/AsmKit.hpp)8
-rw-r--r--NDKKit/AsmKit/CPU/32x0.hpp (renamed from Headers/AsmKit/CPU/32x0.hpp)4
-rw-r--r--NDKKit/AsmKit/CPU/64x0.hpp (renamed from Headers/AsmKit/CPU/64x0.hpp)26
-rw-r--r--NDKKit/AsmKit/CPU/amd64.hpp (renamed from Headers/AsmKit/CPU/amd64.hpp)26
-rw-r--r--NDKKit/AsmKit/CPU/arm64.hpp26
-rw-r--r--NDKKit/AsmKit/CPU/ppc.hpp (renamed from Headers/AsmKit/CPU/ppc.hpp)20
-rw-r--r--NDKKit/Defines.hpp (renamed from Headers/Defines.hpp)12
-rw-r--r--NDKKit/Macros.hpp (renamed from Headers/CompilerKit.hpp)4
-rw-r--r--NDKKit/NFC/AE.hpp (renamed from Headers/StdKit/AE.hpp)38
-rw-r--r--NDKKit/NFC/ELF.hpp (renamed from Headers/StdKit/ELF.hpp)0
-rw-r--r--NDKKit/NFC/ErrorID.hpp (renamed from Headers/StdKit/ErrorID.hpp)6
-rw-r--r--NDKKit/NFC/ErrorOr.hpp (renamed from Headers/StdKit/ErrorOr.hpp)6
-rw-r--r--NDKKit/NFC/PEF.hpp (renamed from Headers/StdKit/PEF.hpp)8
-rw-r--r--NDKKit/NFC/Ref.hpp (renamed from Headers/StdKit/Ref.hpp)28
-rw-r--r--NDKKit/NFC/String.hpp (renamed from Headers/StdKit/String.hpp)18
-rw-r--r--NDKKit/NFC/XCOFF.hxx (renamed from Headers/StdKit/XCOFF.hxx)14
-rw-r--r--NDKKit/Parser.hpp (renamed from Headers/ParserKit.hpp)63
-rw-r--r--NDKKit/Public/SDK/CRT/__mpcc_alloca.hxx (renamed from SDK/__mpcc_alloca.hxx)2
-rw-r--r--NDKKit/Public/SDK/CRT/__mpcc_defines.hxx (renamed from SDK/__mpcc_defines.hxx)32
-rw-r--r--NDKKit/Public/SDK/CRT/__mpcc_exception.hxx27
-rw-r--r--NDKKit/Public/SDK/CRT/__mpcc_hint.hxx20
-rw-r--r--NDKKit/Public/SDK/CRT/__mpcc_malloc.hxx30
-rw-r--r--NDKKit/Public/SDK/CRT/__mpcc_power.inc (renamed from SDK/__mpcc_power.inc)2
-rw-r--r--NDKKit/Sources/32asm.cxx (renamed from Sources/32asm.cc)14
-rw-r--r--NDKKit/Sources/64asm.cxx (renamed from Sources/64asm.cc)56
-rw-r--r--NDKKit/Sources/64x0-cc.cxx1627
-rw-r--r--NDKKit/Sources/AssemblyFactory.cxx59
-rw-r--r--NDKKit/Sources/Detail/ReadMe.md (renamed from Sources/Detail/ReadMe.md)0
-rw-r--r--NDKKit/Sources/Detail/asmutils.hxx (renamed from Sources/Detail/asmutils.h)22
-rw-r--r--NDKKit/Sources/Detail/compilerutils.hxx (renamed from Sources/Detail/compilerutils.h)6
-rw-r--r--NDKKit/Sources/String.cxx (renamed from Sources/String.cc)24
-rw-r--r--NDKKit/Sources/bpp.cxx (renamed from Sources/bpp.cc)43
-rw-r--r--NDKKit/Sources/coff2ae.cxx (renamed from Sources/coff2ae.cc)13
-rw-r--r--NDKKit/Sources/compile_flags.txt (renamed from Sources/compile_flags.txt)2
-rw-r--r--NDKKit/Sources/cplusplus.cxx1025
-rw-r--r--NDKKit/Sources/elf2ae.cxx (renamed from Sources/elf2ae.cc)10
-rw-r--r--NDKKit/Sources/i64asm.cxx1484
-rw-r--r--NDKKit/Sources/link.cxx741
-rw-r--r--NDKKit/Sources/power-as.cxx (renamed from Sources/ppcasm.cc)163
-rw-r--r--NDKKit/Sources/power-cc.cxx1645
-rw-r--r--NDKKit/UUID.hpp (renamed from Headers/UUID.hpp)0
-rw-r--r--NDKKit/Version.hpp4
-rw-r--r--Notes/ASM specs.txt (renamed from Documentation/ASM_SPECS.TXT)0
-rw-r--r--Notes/HAVP DSP.txt (renamed from Documentation/HAVP.TXT)0
-rw-r--r--Notes/Inside 64x0.pdf (renamed from Documentation/Inside 64x0.pdf)bin64675 -> 64675 bytes
-rw-r--r--Notes/Notice.txt (renamed from Documentation/NOTICE.TXT)0
-rw-r--r--Notes/RISC CPU.txt (renamed from Documentation/VNRP.TXT)0
-rw-r--r--ReadMe.md16
-rw-r--r--SDK/__mpcc_exception.hxx27
-rw-r--r--SDK/__mpcc_malloc.hxx29
-rw-r--r--Sources/64x0-cc.cc1354
-rw-r--r--Sources/AsmKit.cc51
-rw-r--r--Sources/amd64-cplusplus.cc397
-rw-r--r--Sources/i64asm.cc1247
-rw-r--r--Sources/link.cc641
-rw-r--r--Sources/ppc-cc.cc1368
-rw-r--r--bpp.rsrc27
-rw-r--r--i64asm.rsrc27
-rw-r--r--link.rsrc27
-rw-r--r--posix.make59
-rw-r--r--ppc-cc.rsrc27
-rw-r--r--ppcasm.rsrc27
-rw-r--r--win64.make60
78 files changed, 7173 insertions, 5805 deletions
diff --git a/.gitignore b/.gitignore
index ee93641..8ae6805 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,12 +8,14 @@ local.properties
.loadpath
.recommenders
+*.creator.user
+
+Examples/
+
# NewOS/MP-UX executable
*.exec
*.bin
-docs/
-
# Compiled class file
*.class
@@ -64,8 +66,24 @@ replay_pid*
Drivers/Output/Tests/*.masm
+Output/32link
+Output/64asm
+Output/64link
+Output/64x0-cc
+Output/bpp
+Output/cplusplus
+Output/i64asm
+Output/i64link
+Output/link
+Output/power-cc
+Output/ppc-cc
+Output/power-as
+Output/ppclink
+
.vs
+docs/html
+docs/latex
docs/doxygen
*.pc
@@ -129,7 +147,7 @@ Cloud9.creator.user
.cproject
.settings/org.eclipse.cdt.codan.core.prefs
.settings/org.eclipse.core.resources.prefs
-.settings/org.eclipse.core.runtime.prefs
+.settings/org.eclipse.core.runtime.prefs
# HDD
*.hdd
diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json
index 8059633..cd1cb3d 100644
--- a/.vscode/c_cpp_properties.json
+++ b/.vscode/c_cpp_properties.json
@@ -1,31 +1,31 @@
{
- "configurations": [
- {
- "name": "Macintosh (CLang)",
- "includePath": [
- "${workspaceFolder}/Headers/**",
- "${workspaceFolder}/Sources/Detail/**",
- "${workspaceFolder}/**"
- ],
- "defines": [],
- "compilerPath": "/usr/bin/clang",
- "cStandard": "c17",
- "cppStandard": "c++20",
- "intelliSenseMode": "macos-clang-arm64"
- },
- {
- "name": "Windows (Cygwin)",
- "includePath": [
- "${workspaceFolder}/Headers/**",
- "${workspaceFolder}/Sources/Detail/**",
- "${workspaceFolder}/**"
- ],
- "defines": [],
- "compilerPath": "C:/cygwin64/bin/g++.exe",
- "cStandard": "c17",
- "cppStandard": "c++20",
- "intelliSenseMode": "windows-gcc-x64"
- }
- ],
- "version": 4
-} \ No newline at end of file
+ "configurations": [
+ {
+ "name": "Macintosh (CLang)",
+ "includePath": [
+ "${workspaceFolder}/NDKKit/**",
+ "${workspaceFolder}/Sources/Detail/**",
+ "${workspaceFolder}/**"
+ ],
+ "defines": [],
+ "compilerPath": "/usr/bin/clang",
+ "cStandard": "c17",
+ "cppStandard": "c++20",
+ "intelliSenseMode": "macos-clang-arm64"
+ },
+ {
+ "name": "Windows (Cygwin)",
+ "includePath": [
+ "${workspaceFolder}/NDKKit/**",
+ "${workspaceFolder}/Sources/Detail/**",
+ "${workspaceFolder}/**"
+ ],
+ "defines": [],
+ "compilerPath": "C:/cygwin64/bin/g++.exe",
+ "cStandard": "c17",
+ "cppStandard": "c++20",
+ "intelliSenseMode": "windows-gcc-x64"
+ }
+ ],
+ "version": 4
+}
diff --git a/64asm.rsrc b/64asm.rsrc
deleted file mode 100644
index 44ae486..0000000
--- a/64asm.rsrc
+++ /dev/null
@@ -1,27 +0,0 @@
-#include "Headers/Version.hxx"
-
-1 ICON "Icons/app-logo.ico"
-
-1 VERSIONINFO
-FILEVERSION 1,0,0,0
-PRODUCTVERSION 1,0,0,0
-BEGIN
- BLOCK "StringFileInfo"
- BEGIN
- BLOCK "080904E4"
- BEGIN
- VALUE "CompanyName", "Mahrouss-Logic"
- VALUE "FileDescription", "NewOS 64x0 assembler."
- VALUE "FileVersion", kDistVersion
- VALUE "InternalName", "NewAssembler"
- VALUE "LegalCopyright", "Mahrouss-Logic"
- VALUE "OriginalFilename", "64asm.exe"
- VALUE "ProductName", "NewAssembler"
- VALUE "ProductVersion", kDistVersion
- END
- END
- BLOCK "VarFileInfo"
- BEGIN
- VALUE "Translation", 0x809, 1252
- END
-END
diff --git a/64x0-cc.rsrc b/64x0-cc.rsrc
deleted file mode 100644
index afa07df..0000000
--- a/64x0-cc.rsrc
+++ /dev/null
@@ -1,27 +0,0 @@
-#include "Headers/Version.hxx"
-
-1 ICON "Icons/app-logo.ico"
-
-1 VERSIONINFO
-FILEVERSION 1,0,0,0
-PRODUCTVERSION 1,0,0,0
-BEGIN
- BLOCK "StringFileInfo"
- BEGIN
- BLOCK "080904E4"
- BEGIN
- VALUE "CompanyName", "Mahrouss-Logic"
- VALUE "FileDescription", "NewOS 64x0 C compiler."
- VALUE "FileVersion", kDistVersion
- VALUE "InternalName", "NewC"
- VALUE "LegalCopyright", "Mahrouss-Logic"
- VALUE "OriginalFilename", "64x0-cc.exe"
- VALUE "ProductName", "NewC"
- VALUE "ProductVersion", kDistVersion
- END
- END
- BLOCK "VarFileInfo"
- BEGIN
- VALUE "Translation", 0x809, 1252
- END
-END
diff --git a/Doxyfile b/Doxyfile
index b033032..c91e98b 100644
--- a/Doxyfile
+++ b/Doxyfile
@@ -42,7 +42,7 @@ DOXYFILE_ENCODING = UTF-8
# title of most generated pages and in a few other places.
# The default value is: My Project.
-PROJECT_NAME = NewOS Programmer Workshop
+PROJECT_NAME = NDK
# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
# could be handy for archiving the generated documentation or if some version
@@ -54,7 +54,7 @@ PROJECT_NUMBER = 2.0.0
# for a project that appears at the top of each page and should give viewer a
# quick idea about the purpose of the project. Keep the description short.
-PROJECT_BRIEF = "CodeTools"
+PROJECT_BRIEF = "NewOS Developer Kit"
# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
# in the documentation. The maximum height of the logo should not exceed 55
@@ -1017,7 +1017,7 @@ RECURSIVE = YES
# Note that relative paths are relative to the directory from which doxygen is
# run.
-EXCLUDE =
+EXCLUDE = Meta
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
# directories that are symbolic links (a Unix file system feature) are excluded
@@ -1693,7 +1693,7 @@ DISABLE_INDEX = NO
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
-GENERATE_TREEVIEW = NO
+GENERATE_TREEVIEW = YES
# When both GENERATE_TREEVIEW and DISABLE_INDEX are set to YES, then the
# FULL_SIDEBAR option determines if the side bar is limited to only the treeview
diff --git a/Examples/Example64k.s b/Examples/Example64k.s
deleted file mode 100644
index b56003a..0000000
--- a/Examples/Example64k.s
+++ /dev/null
@@ -1,3 +0,0 @@
-mv r0, r3
-lda r19, 0x10000
-jlr
diff --git a/Examples/ExampleAMD64.asm b/Examples/ExampleAMD64.asm
deleted file mode 100644
index cc649be..0000000
--- a/Examples/ExampleAMD64.asm
+++ /dev/null
@@ -1,6 +0,0 @@
-#bits 64
-
-export .code64 __ImageStart
-
-mov rax, rdx
-ret
diff --git a/Examples/ExampleAMD64_Return.asm b/Examples/ExampleAMD64_Return.asm
deleted file mode 100644
index 0ecbaf7..0000000
--- a/Examples/ExampleAMD64_Return.asm
+++ /dev/null
@@ -1,6 +0,0 @@
-#bits 64
-
-export .code64 __RaiseInterrupt
-
-int 13
-ret
diff --git a/Examples/ExampleCDialect.S b/Examples/ExampleCDialect.S
deleted file mode 100644
index d937aed..0000000
--- a/Examples/ExampleCDialect.S
+++ /dev/null
@@ -1,28 +0,0 @@
-# Path: Examples/ExampleCDialect.c
-# Language: POWER Assembly (Generated from C)
-# Build Date: 2024-4-28
-
-
-
-
-
-
-
-dword export .code64 __ImageStart
-
-
- li r3,0x1000
-
- cmpw r10, r11
- beq import __MPCC_IF_PROC_6099380296
-dword export .code64 __MPCC_IF_PROC_6099380296
-
-
-
- mr r31, r3
- blr
-
-
- mr r31, r0
- blr
-
diff --git a/Examples/ExampleCDialect.c b/Examples/ExampleCDialect.c
deleted file mode 100644
index e6d92fb..0000000
--- a/Examples/ExampleCDialect.c
+++ /dev/null
@@ -1,20 +0,0 @@
-struct
-{
- int a;
- int b;
- int c;
-};
-
-int __ImageStart(int argc, char const* argv[])
-{
- int* foo = 0x1000;
-
- if (foo == 57)
- {
- foo = 0x2000;
- *foo = 5;
- return foo;
- }
-
- return 57;
-}
diff --git a/Examples/ExamplePowerPC.S b/Examples/ExamplePowerPC.S
deleted file mode 100644
index b9de796..0000000
--- a/Examples/ExamplePowerPC.S
+++ /dev/null
@@ -1,8 +0,0 @@
-; you you can never say!
-
-b 0x1000
-mflr r21
-mtlr r21
-li r3, 0
-cmpw r10, r11
-stw r7, r5+36
diff --git a/Examples/ExamplePowerPC.S.pp b/Examples/ExamplePowerPC.S.pp
deleted file mode 100644
index 5eeb07f..0000000
--- a/Examples/ExamplePowerPC.S.pp
+++ /dev/null
@@ -1,11 +0,0 @@
-# Path: Examples/ExamplePowerPC.S.pp
-# Language: POWER Assembly
-# Build Date: 2024-6-4
-
-bl 0x1000
-
-
-li r1, 0x500
-mr r2, r1
-sc
-blr
diff --git a/Examples/ExamplePowerPC.dmp b/Examples/ExamplePowerPC.dmp
deleted file mode 100644
index 5986d03..0000000
--- a/Examples/ExamplePowerPC.dmp
+++ /dev/null
@@ -1,5 +0,0 @@
-0x0000000000000000: 00 10 00 48 b 0x1000
-0x0000000000000004: 00 05 20 38 li r1, 0x500
-0x0000000000000008: 78 13 21 7C or r1, r1, r2
-0x000000000000000c: 02 00 00 44 sc
-0x0000000000000010: 20 00 80 4E blr \ No newline at end of file
diff --git a/Headers/Version.hxx b/Headers/Version.hxx
deleted file mode 100644
index 377a688..0000000
--- a/Headers/Version.hxx
+++ /dev/null
@@ -1,3 +0,0 @@
-#pragma once
-
-#define kDistVersion "v1.20"
diff --git a/Icons/app-logo.ico b/Icons/app-logo.ico
deleted file mode 100644
index dbdcdee..0000000
--- a/Icons/app-logo.ico
+++ /dev/null
Binary files differ
diff --git a/Headers/AsmKit/AsmKit.hpp b/NDKKit/AsmKit/AsmKit.hpp
index 2ea4796..6074efc 100644
--- a/Headers/AsmKit/AsmKit.hpp
+++ b/NDKKit/AsmKit/AsmKit.hpp
@@ -1,14 +1,14 @@
/* -------------------------------------------
- Copyright Mahrouss Logic
+ Copyright ZKA Technologies
------------------------------------------- */
#pragma once
-#include <Headers/CompilerKit.hpp>
-#include <Headers/Defines.hpp>
-#include <Headers/StdKit/String.hpp>
+#include <NDKKit/Macros.hpp>
+#include <NDKKit/Defines.hpp>
+#include <NDKKit/NFC/String.hpp>
namespace CompilerKit
{
diff --git a/Headers/AsmKit/CPU/32x0.hpp b/NDKKit/AsmKit/CPU/32x0.hpp
index a78a04b..7fa02ad 100644
--- a/Headers/AsmKit/CPU/32x0.hpp
+++ b/NDKKit/AsmKit/CPU/32x0.hpp
@@ -1,12 +1,12 @@
/* -------------------------------------------
- Copyright Mahrouss Logic
+ Copyright ZKA Technologies
------------------------------------------- */
#pragma once
-#include <Headers/Defines.hpp>
+#include <NDKKit/Defines.hpp>
// @brief 32x0 support.
// @file CPU/32x0.hpp
diff --git a/Headers/AsmKit/CPU/64x0.hpp b/NDKKit/AsmKit/CPU/64x0.hpp
index a72f72f..3bd1f80 100644
--- a/Headers/AsmKit/CPU/64x0.hpp
+++ b/NDKKit/AsmKit/CPU/64x0.hpp
@@ -1,12 +1,12 @@
/* -------------------------------------------
- Copyright Mahrouss Logic
+ Copyright ZKA Technologies
------------------------------------------- */
#pragma once
-#include <Headers/Defines.hpp>
+#include <NDKKit/Defines.hpp>
#include <vector>
// @brief 64x0 support.
@@ -42,18 +42,20 @@ inline std::vector<CpuOpcode64x0> kOpcodes64x0 = {
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("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("sub", 0b0101011, 0b101, kAsmImmediate)
// add/sub with carry flag
kAsmOpcodeDecl("addc", 0b0101011, 0b110, kAsmImmediate)
kAsmOpcodeDecl("decc", 0b0101011, 0b111, kAsmImmediate)
diff --git a/Headers/AsmKit/CPU/amd64.hpp b/NDKKit/AsmKit/CPU/amd64.hpp
index 5a8f72a..3edd5ca 100644
--- a/Headers/AsmKit/CPU/amd64.hpp
+++ b/NDKKit/AsmKit/CPU/amd64.hpp
@@ -1,12 +1,12 @@
/* -------------------------------------------
- Copyright Mahrouss Logic
+ Copyright ZKA Technologies
------------------------------------------- */
#pragma once
-#include <Headers/Defines.hpp>
+#include <NDKKit/Defines.hpp>
// @brief AMD64 support.
// @file CPU/amd64.hpp
@@ -38,12 +38,20 @@ struct CpuOpcodeAMD64
#define kJumpLimitStandardLimit 0xEB
inline std::vector<CpuOpcodeAMD64> kOpcodesAMD64 = {
- kAsmOpcodeDecl("int", 0xCD) kAsmOpcodeDecl("into", 0xCE) kAsmOpcodeDecl(
- "intd", 0xF1) kAsmOpcodeDecl("int3", 0xC3) kAsmOpcodeDecl("iret", 0xCF)
- kAsmOpcodeDecl("retf", 0xCB) kAsmOpcodeDecl("retn", 0xC3)
- kAsmOpcodeDecl("ret", 0xC3) kAsmOpcodeDecl("sti", 0xfb)
- kAsmOpcodeDecl("cli", 0xfa) kAsmOpcodeDecl("hlt", 0xf4)
- kAsmOpcodeDecl("nop", 0x90) kAsmOpcodeDecl("mov", 0x48)
- kAsmOpcodeDecl("call", 0xFF)};
+ kAsmOpcodeDecl("int", 0xCD)
+ kAsmOpcodeDecl("into", 0xCE)
+ kAsmOpcodeDecl("intd", 0xF1)
+ kAsmOpcodeDecl("int3", 0xC3)
+ kAsmOpcodeDecl("iret", 0xCF)
+ kAsmOpcodeDecl("retf", 0xCB)
+ kAsmOpcodeDecl("retn", 0xC3)
+ kAsmOpcodeDecl("ret", 0xC3)
+ kAsmOpcodeDecl("sti", 0xfb)
+ kAsmOpcodeDecl("cli", 0xfa)
+ kAsmOpcodeDecl("hlt", 0xf4)
+ kAsmOpcodeDecl("nop", 0x90)
+ kAsmOpcodeDecl("mov", 0x48)
+ kAsmOpcodeDecl("call", 0xFF)
+};
#define kAsmRegisterLimit 15
diff --git a/NDKKit/AsmKit/CPU/arm64.hpp b/NDKKit/AsmKit/CPU/arm64.hpp
new file mode 100644
index 0000000..a63ddfb
--- /dev/null
+++ b/NDKKit/AsmKit/CPU/arm64.hpp
@@ -0,0 +1,26 @@
+/* -------------------------------------------
+
+Copyright ZKA Technologies
+
+------------------------------------------- */
+
+#pragma once
+
+#include <NDKKit/Defines.hpp>
+
+/// @brief ARM64 encoding support.
+/// @file CPU/arm64.hpp
+
+struct CpuOpcodeArm64;
+
+/// @brief ARM64 opcode header.
+struct CpuOpcodeArm64 final
+{
+ uint8_t fOpcode; // opcode
+ uint8_t fRegisterLeft; // left register index
+ uint8_t fRegisterRight; // right register index
+ bool fRegisterLeftHooked;
+ bool fRegisterRightHooked;
+ uint32_t fImmediateValue; // immediate 32-bit value
+ bool fImmediateValueHooked;
+};
diff --git a/Headers/AsmKit/CPU/ppc.hpp b/NDKKit/AsmKit/CPU/ppc.hpp
index c29286d..e3ea6c5 100644
--- a/Headers/AsmKit/CPU/ppc.hpp
+++ b/NDKKit/AsmKit/CPU/ppc.hpp
@@ -1,3 +1,13 @@
+/* -------------------------------------------
+
+ Some modifications are copyrighted under:
+ ZKA Technologies
+
+ Original author:
+ Apple Inc
+
+------------------------------------------- */
+
#pragma once
#include <cstdint>
@@ -242,7 +252,7 @@ inline CpuOpcodePPC kOpcodesPowerPC[] = {
{0x4c800421, "bfctrl", {{16, 5, BCND}, {11, 2, NUM}}},
/* branch mnemonics incorporating conditions (assember extended mnemonics)
- */
+ */
{0x41800000, "blt", {{16, 5, CRF}, {2, 14, PCREL}}},
{0x41800000, "blt", {{2, 14, PCREL}}},
{0x41800001, "bltl", {{16, 5, CRF}, {2, 14, PCREL}}},
@@ -1548,10 +1558,10 @@ inline CpuOpcodePPC kOpcodesPowerPC[] = {
{0x7c000426, "clcs", {{21, 5, GREG}, {16, 5, GREG}}, CPU601},
/* Added from the POWER 603 book.
- * These are really 603 specific instructions but we mark them as OPTIONAL
- * so that the -force_cpusubtype_ALL flag as to be used. This makes it so
- * only 601 instructions will cause the cputype to be set to other an ALL.
- */
+ * These are really 603 specific instructions but we mark them as OPTIONAL
+ * so that the -force_cpusubtype_ALL flag as to be used. This makes it so
+ * only 601 instructions will cause the cputype to be set to other an ALL.
+ */
{0x7c0007a4, "tlbld", {{11, 5, GREG}}, OPTIONAL},
{0x7c0007e4, "tlbli", {{11, 5, GREG}}, OPTIONAL},
diff --git a/Headers/Defines.hpp b/NDKKit/Defines.hpp
index 01230e6..31c1998 100644
--- a/Headers/Defines.hpp
+++ b/NDKKit/Defines.hpp
@@ -1,6 +1,6 @@
/* -------------------------------------------
- Copyright Mahrouss Logic
+ Copyright ZKA Technologies
------------------------------------------- */
@@ -136,12 +136,12 @@ typedef char char_type;
".64x", ".32x", ".masm", ".s", ".S", ".asm" \
}
-#ifdef __MODULE_NEED__
-#define MPCC_MODULE(name) int name(int argc, char** argv)
+#ifdef __NDK_MODULE__
+#define NDK_MODULE(name) int name(int argc, char** argv)
#else
-#define MPCC_MODULE(name) int main(int argc, char** argv)
-#endif /* ifdef __MODULE_NEED__ */
+#define NDK_MODULE(name) int main(int argc, char** argv)
+#endif /* ifdef __NDK_MODULE__ */
-#pragma scalar_storage_order big - endian
+#pragma scalar_storage_order big-endian
#endif /* ifndef __MPCC_DEFINES_HPP__ */
diff --git a/Headers/CompilerKit.hpp b/NDKKit/Macros.hpp
index 9e37666..c190cda 100644
--- a/Headers/CompilerKit.hpp
+++ b/NDKKit/Macros.hpp
@@ -1,10 +1,10 @@
/* -------------------------------------------
- Copyright Mahrouss Logic
+ Copyright ZKA Technologies
------------------------------------------- */
-//! provide support for CompilerKit.hpp header.
+/// @brief provide support for Macros.hpp header.
#ifndef _CK_CL_HPP
#define _CK_CL_HPP
diff --git a/Headers/StdKit/AE.hpp b/NDKKit/NFC/AE.hpp
index ca54671..1c929f9 100644
--- a/Headers/StdKit/AE.hpp
+++ b/NDKKit/NFC/AE.hpp
@@ -1,15 +1,15 @@
/*
* ========================================================
*
- * MPCC
- * Copyright Mahrouss Logic, all rights reserved.
+ * NDK
+ * Copyright ZKA Technologies, all rights reserved.
*
* ========================================================
*/
#pragma once
-#include <Headers/Defines.hpp>
+#include <NDKKit/Defines.hpp>
#define kAEMag0 'A'
#define kAEMag1 'E'
@@ -95,9 +95,9 @@ std::ifstream& operator>>(std::ifstream& fp,
namespace CompilerKit::Utils
{
/**
- * @brief AE Reader protocol
- *
- */
+ * @brief AE Reader protocol
+ *
+ */
class AEReadableProtocol final
{
public:
@@ -110,12 +110,12 @@ namespace CompilerKit::Utils
MPCC_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
- */
+ * @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)
@@ -126,13 +126,13 @@ namespace CompilerKit::Utils
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.
- */
+ * @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)
{
diff --git a/Headers/StdKit/ELF.hpp b/NDKKit/NFC/ELF.hpp
index 4f0d0ae..4f0d0ae 100644
--- a/Headers/StdKit/ELF.hpp
+++ b/NDKKit/NFC/ELF.hpp
diff --git a/Headers/StdKit/ErrorID.hpp b/NDKKit/NFC/ErrorID.hpp
index 363f4d5..c45b4b0 100644
--- a/Headers/StdKit/ErrorID.hpp
+++ b/NDKKit/NFC/ErrorID.hpp
@@ -2,15 +2,15 @@
* ========================================================
*
* CompilerKit
- * Copyright Mahrouss Logic, all rights reserved.
+ * Copyright ZKA Technologies, all rights reserved.
*
* ========================================================
*/
#pragma once
-#include <Headers/Defines.hpp>
-#include <Headers/StdKit/ErrorOr.hpp>
+#include <NDKKit/Defines.hpp>
+#include <NDKKit/NFC/ErrorOr.hpp>
#define MPCC_EXEC_ERROR -30
#define MPCC_FILE_NOT_FOUND -31
diff --git a/Headers/StdKit/ErrorOr.hpp b/NDKKit/NFC/ErrorOr.hpp
index dbd83ce..ed134a7 100644
--- a/Headers/StdKit/ErrorOr.hpp
+++ b/NDKKit/NFC/ErrorOr.hpp
@@ -2,15 +2,15 @@
* ========================================================
*
* CompilerKit
- * Copyright Mahrouss Logic, all rights reserved.
+ * Copyright ZKA Technologies, all rights reserved.
*
* ========================================================
*/
#pragma once
-#include <Headers/Defines.hpp>
-#include <Headers/StdKit/Ref.hpp>
+#include <NDKKit/Defines.hpp>
+#include <NDKKit/NFC/Ref.hpp>
namespace CompilerKit
{
diff --git a/Headers/StdKit/PEF.hpp b/NDKKit/NFC/PEF.hpp
index 6f0602c..2f460b7 100644
--- a/Headers/StdKit/PEF.hpp
+++ b/NDKKit/NFC/PEF.hpp
@@ -1,12 +1,12 @@
/* -------------------------------------------
- Copyright Mahrouss Logic
+ Copyright ZKA Technologies
------------------------------------------- */
#pragma once
-#include <Headers/Defines.hpp>
+#include <NDKKit/Defines.hpp>
// @file PEF.hpp
// @brief Preferred Executable Format
@@ -33,12 +33,14 @@ namespace CompilerKit
{
enum
{
+ kPefArchStart = 99,
kPefArchIntel86S = 100,
kPefArchAMD64,
kPefArchRISCV,
kPefArch64000, /* 64x0 RISC architecture. */
kPefArch32000,
kPefArchPowerPC, /* 64-bit POWER architecture. */
+ kPefArchARM64,
kPefArchCount = (kPefArchPowerPC - kPefArchIntel86S) + 1,
kPefArchInvalid = 0xFF,
};
@@ -47,7 +49,7 @@ namespace CompilerKit
{
kPefSubArchAMD,
kPefSubArchIntel,
- kPefSubArchARM,
+ kPefSubArchGeneric,
kPefSubArchIBM,
};
diff --git a/Headers/StdKit/Ref.hpp b/NDKKit/NFC/Ref.hpp
index c4aa2d3..0f9c0e3 100644
--- a/Headers/StdKit/Ref.hpp
+++ b/NDKKit/NFC/Ref.hpp
@@ -3,7 +3,7 @@
* ========================================================
*
* CompilerKit
- * Copyright Mahrouss Logic, all rights reserved.
+ * Copyright ZKA Technologies, all rights reserved.
*
* ========================================================
*/
@@ -12,18 +12,25 @@
namespace CompilerKit
{
- // @author Amlal EL Mahrouss
- // @brief Reference class, refers to a pointer of data in static memory.
+ // @author Amlal
+ // @brief Reference holder class, refers to a pointer of data in static memory.
template <typename T>
class Ref final
{
public:
explicit Ref() = default;
- ~Ref() = default;
+
+ ~Ref()
+ {
+ if (m_Strong)
+ {
+ (*m_Class).~T();
+ }
+ }
public:
explicit Ref(T cls, const bool& strong = false)
- : m_Class(cls), m_Strong(strong)
+ : m_Class(&cls), m_Strong(strong)
{
}
@@ -41,12 +48,12 @@ namespace CompilerKit
T& Leak()
{
- return m_Class;
+ return *m_Class;
}
T operator*()
{
- return m_Class;
+ return *m_Class;
}
bool IsStrong() const
@@ -56,11 +63,11 @@ namespace CompilerKit
operator bool()
{
- return m_Class;
+ return *m_Class;
}
private:
- T m_Class;
+ T* m_Class;
bool m_Strong{false};
};
@@ -68,8 +75,7 @@ namespace CompilerKit
class NonNullRef final
{
public:
- NonNullRef() = delete;
- NonNullRef(nullPtr) = delete;
+ explicit NonNullRef() = delete;
explicit NonNullRef(T* ref)
: m_Ref(ref, true)
diff --git a/Headers/StdKit/String.hpp b/NDKKit/NFC/String.hpp
index adc6a9d..200bf2c 100644
--- a/Headers/StdKit/String.hpp
+++ b/NDKKit/NFC/String.hpp
@@ -2,22 +2,22 @@
* ========================================================
*
* CompilerKit
- * Copyright Mahrouss Logic, all rights reserved.
+ * Copyright ZKA Technologies, all rights reserved.
*
* ========================================================
*/
#pragma once
-#include <Headers/Defines.hpp>
-#include <Headers/StdKit/ErrorOr.hpp>
+#include <NDKKit/Defines.hpp>
+#include <NDKKit/NFC/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.
- */
+ * @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
{
@@ -76,9 +76,9 @@ namespace CompilerKit
};
/**
- * @brief StringBuilder class
- * @note These results shall call delete[] after they're used.
- */
+ * @brief StringBuilder class
+ * @note These results shall call delete[] after they're used.
+ */
struct StringBuilder final
{
static StringView Construct(const CharType* data);
diff --git a/Headers/StdKit/XCOFF.hxx b/NDKKit/NFC/XCOFF.hxx
index e21a380..57ecfd2 100644
--- a/Headers/StdKit/XCOFF.hxx
+++ b/NDKKit/NFC/XCOFF.hxx
@@ -1,20 +1,20 @@
/* -------------------------------------------
- Copyright Mahrouss Logic
+ Copyright ZKA Technologies
- File: XCOFF.hpp
- Purpose: XCOFF for NewOS.
+ File: XCOFF.hpp
+ Purpose: XCOFF for NewOS.
- Revision History:
+ Revision History:
- 04/07/24: Added file (amlel)
+ 04/07/24: Added file (amlel)
------------------------------------------- */
#ifndef __XCOFF__
#define __XCOFF__
-#include <Headers/Defines.hpp>
+#include <NDKKit/Defines.hpp>
#define kXCOFF64Magic 0x01F7
@@ -38,4 +38,4 @@ namespace CompilerKit
} XCoffFileHeader;
} // namespace CompilerKit
-#endif // ifndef __XCOFF__ \ No newline at end of file
+#endif // ifndef __XCOFF__
diff --git a/Headers/ParserKit.hpp b/NDKKit/Parser.hpp
index e4277c6..c67057d 100644
--- a/Headers/ParserKit.hpp
+++ b/NDKKit/Parser.hpp
@@ -1,17 +1,17 @@
/* -------------------------------------------
- Copyright Mahrouss Logic
+ Copyright ZKA Technologies
------------------------------------------- */
#pragma once
-#include <Headers/AsmKit/AsmKit.hpp>
+#include <NDKKit/AsmKit/AsmKit.hpp>
#include <vector>
-namespace ParserKit
+namespace CompilerKit
{
- using namespace CompilerKit;
+ inline auto cInvalidLang = "?";
/// @brief Compiler backend, implements a frontend, such as C, C++...
/// See Toolchain, for some examples.
@@ -34,7 +34,12 @@ namespace ParserKit
//! @brief What language are we dealing with?
virtual const char* Language()
{
- return "Invalid Language";
+ return cInvalidLang;
+ }
+
+ virtual bool IsValid()
+ {
+ return strcmp(this->Language(), cInvalidLang);
}
};
@@ -43,20 +48,50 @@ namespace ParserKit
struct CompilerKeyword;
/// we want to do that because to separate keywords.
- enum
+ enum KeywordKind
{
+ eKeywordKindNamespace,
+ eKeywordKindFunctionStart,
+ eKeywordKindFunctionEnd,
+ eKeywordKindVariable,
+ eKeywordKindVariablePtr,
+ eKeywordKindType,
+ eKeywordKindTypePtr,
+ eKeywordKindExpressionBegin,
+ eKeywordKindExpressionEnd,
+ eKeywordKindArgSeparator,
+ eKeywordKindBodyStart,
+ eKeywordKindBodyEnd,
+ eKeywordKindClass,
+ eKeywordKindPtrAccess,
eKeywordKindAccess,
- eKeywordKindObject,
- eKeywordKindDataType,
- eKeywordKindCompilerAttribute,
- eKeywordKindKeyword,
+ eKeywordKindIf,
+ eKeywordKindElse,
+ eKeywordKindElseIf,
+ eKeywordKindVariableAssign,
+ eKeywordKindVariableDec,
+ eKeywordKindVariableInc,
+ eKeywordKindConstant,
+ eKeywordKindTypedef,
+ eKeywordKindEndInstr,
+ eKeywordKindSpecifier,
+ eKeywordKindInvalid,
+ eKeywordKindReturn,
+ eKeywordKindCommentInline,
+ eKeywordKindCommentMultiLineStart,
+ eKeywordKindCommentMultiLineEnd,
+ eKeywordKindEq,
+ eKeywordKindNotEq,
+ eKeywordKindGreaterEq,
+ eKeywordKindLessEq,
+ eKeywordKindPtr,
};
/// \brief Compiler keyword information struct.
struct CompilerKeyword
{
std::string keyword_name;
- int32_t keyword_kind = eKeywordKindKeyword;
+ KeywordKind keyword_kind = eKeywordKindInvalid;
};
struct SyntaxLeafList final
{
@@ -65,11 +100,11 @@ namespace ParserKit
Int32 fUserType;
#ifdef __PK_USE_STRUCT_INSTEAD__
CompilerKeyword fUserData;
- CompilerKeyword fUserValue;
#else
std::string fUserData;
- std::string fUserValue;
#endif
+
+ std::string fUserValue;
struct SyntaxLeaf* fNext;
};
@@ -140,4 +175,4 @@ namespace ParserKit
return false;
}
-} // namespace ParserKit
+} // namespace CompilerKit
diff --git a/SDK/__mpcc_alloca.hxx b/NDKKit/Public/SDK/CRT/__mpcc_alloca.hxx
index f56da9f..02b3123 100644
--- a/SDK/__mpcc_alloca.hxx
+++ b/NDKKit/Public/SDK/CRT/__mpcc_alloca.hxx
@@ -1,6 +1,6 @@
/* -------------------------------------------
- Copyright Mahrouss Logic
+ Copyright ZKA Technologies
------------------------------------------- */
diff --git a/SDK/__mpcc_defines.hxx b/NDKKit/Public/SDK/CRT/__mpcc_defines.hxx
index c87f570..19ed8a4 100644
--- a/SDK/__mpcc_defines.hxx
+++ b/NDKKit/Public/SDK/CRT/__mpcc_defines.hxx
@@ -1,6 +1,6 @@
/* -------------------------------------------
- Copyright Mahrouss Logic
+ Copyright ZKA Technologies
------------------------------------------- */
@@ -30,8 +30,9 @@ typedef char* caddr_t;
#ifdef __GNUC__
#include <CRT/__mpcc_alloca.hxx>
#define __mpcc_alloca(sz) __mpcc_alloca_gcc(sz)
+#define __packed__ __attribute__((packed))
#elif defined(__MPCC__)
-
+#define __packed__ __mpcc_packed__
#define __alloca(sz) __mpcc_alloca(sz)
#endif
@@ -41,29 +42,21 @@ typedef char* caddr_t;
#define __init_decl() \
extern "C" \
{
+
+
#define __fini_decl() \
- } \
- ;
+ }; \
+
+
#else
#define __init_decl()
#define __fini_decl()
#endif
-#if __has_builtin(__builtin_alloca)
-#define alloca(sz) __builtin_alloca(sz)
-#ifdef __alloca
-#undef __alloca
-#endif
-#define __alloca alloca
-#else
-#warning alloca not detected (MPCC)
-#endif
-
typedef long long off_t;
typedef unsigned long long uoff_t;
-typedef union float_cast
-{
+typedef union float_cast {
struct
{
unsigned int mantissa : 23;
@@ -72,10 +65,9 @@ typedef union float_cast
};
float f;
-} __attribute__((packed)) float_cast_t;
+} __packed__ float_cast_t;
-typedef union double_cast
-{
+typedef union double_cast {
struct
{
unsigned long long int mantissa : 52;
@@ -84,7 +76,7 @@ typedef union double_cast
};
double f;
-} __attribute__((packed)) double_cast_t;
+} __packed__ double_cast_t;
#endif // ifndef __GNUC__
diff --git a/NDKKit/Public/SDK/CRT/__mpcc_exception.hxx b/NDKKit/Public/SDK/CRT/__mpcc_exception.hxx
new file mode 100644
index 0000000..dac42ad
--- /dev/null
+++ b/NDKKit/Public/SDK/CRT/__mpcc_exception.hxx
@@ -0,0 +1,27 @@
+/* -------------------------------------------
+
+ Copyright ZKA Technologies
+
+------------------------------------------- */
+
+#pragma once
+
+/// This file is an implementation of __throw* family of functions.
+
+#include <exception>
+#include <iostream>
+#include <stdexcept>
+
+namespace std
+{
+ inline void __throw_general(void)
+ {
+ throw std::runtime_error("NDK C++ Runtime error.");
+ }
+
+ inline void __throw_domain_error(const char* error)
+ {
+ std::cout << "NDK C++: Domain error: " << error << "\r";
+ __throw_general();
+ }
+} // namespace std
diff --git a/NDKKit/Public/SDK/CRT/__mpcc_hint.hxx b/NDKKit/Public/SDK/CRT/__mpcc_hint.hxx
new file mode 100644
index 0000000..02dbc94
--- /dev/null
+++ b/NDKKit/Public/SDK/CRT/__mpcc_hint.hxx
@@ -0,0 +1,20 @@
+/* -------------------------------------------
+
+ Copyright ZKA Technologies
+
+------------------------------------------- */
+
+#pragma once
+
+#pragma compiler(hint_manifest)
+
+#define _Input
+#define _Output
+
+#define _Optional
+
+#define _StrictCheckInput
+#define _StrictCheckOutput
+
+#define _InOut
+#define _StrictInOut
diff --git a/NDKKit/Public/SDK/CRT/__mpcc_malloc.hxx b/NDKKit/Public/SDK/CRT/__mpcc_malloc.hxx
new file mode 100644
index 0000000..eeaa67b
--- /dev/null
+++ b/NDKKit/Public/SDK/CRT/__mpcc_malloc.hxx
@@ -0,0 +1,30 @@
+/* -------------------------------------------
+
+ Copyright ZKA Technologies
+
+------------------------------------------- */
+
+#pragma once
+
+#include <algorithm>
+
+namespace stdx
+{
+ /// @brief allocate a new class.
+ /// @tparam KindClass the class type to allocate.
+ template <typename KindClass, typename... Args>
+ inline void* allocate(Args&&... args)
+ {
+ return new KindClass(std::forward(args)...);
+ }
+
+ /// @brief free a class.
+ /// @tparam KindClass the class type to allocate.
+ template <typename KindClass>
+ inline void release(KindClass ptr)
+ {
+ if (!ptr)
+ return;
+ delete ptr;
+ }
+} // namespace stdx
diff --git a/SDK/__mpcc_power.inc b/NDKKit/Public/SDK/CRT/__mpcc_power.inc
index 96403a4..90b1364 100644
--- a/SDK/__mpcc_power.inc
+++ b/NDKKit/Public/SDK/CRT/__mpcc_power.inc
@@ -1,5 +1,5 @@
# Path: SDK/__mpcc_power.inc
-# Language: Mahrouss POWER Assembly support for GNU.
+# Language: NDK POWER Assembly support for GNU.
# Build Date: 2024-6-4
%ifdef __CODETOOLS__
diff --git a/Sources/32asm.cc b/NDKKit/Sources/32asm.cxx
index e5aa500..23111bc 100644
--- a/Sources/32asm.cc
+++ b/NDKKit/Sources/32asm.cxx
@@ -1,6 +1,6 @@
/* -------------------------------------------
- Copyright Mahrouss Logic
+ Copyright ZKA Technologies
------------------------------------------- */
@@ -9,7 +9,7 @@
/////////////////////////////////////////////////////////////////////////////////////////
// @file 32asm.cxx
-// @author Amlal El Mahrouss
+// @author ZKA Technologies
// @brief 32x0 Assembler.
// REMINDER: when dealing with an undefined symbol use (string
@@ -19,10 +19,10 @@
#define __ASM_NEED_32x0__ 1
-#include <Headers/AsmKit/CPU/32x0.hpp>
-#include <Headers/ParserKit.hpp>
-#include <Headers/StdKit/AE.hpp>
-#include <Headers/StdKit/PEF.hpp>
+#include <NDKKit/AsmKit/CPU/32x0.hpp>
+#include <NDKKit/Parser.hpp>
+#include <NDKKit/NFC/AE.hpp>
+#include <NDKKit/NFC/PEF.hpp>
#include <filesystem>
#include <fstream>
#include <iostream>
@@ -49,4 +49,4 @@
/////////////////////////////////////////////////////////////////////////////////////////
-MPCC_MODULE(NewOSAssembler32000) { return 0; }
+NDK_MODULE(NewOSAssembler32000) { return 0; }
diff --git a/Sources/64asm.cc b/NDKKit/Sources/64asm.cxx
index d2568e2..0a92157 100644
--- a/Sources/64asm.cc
+++ b/NDKKit/Sources/64asm.cxx
@@ -1,6 +1,6 @@
/* -------------------------------------------
- Copyright Mahrouss Logic
+ Copyright ZKA Technologies
------------------------------------------- */
@@ -9,8 +9,8 @@
/////////////////////////////////////////////////////////////////////////////////////////
// @file 64asm.cxx
-// @author Amlal El Mahrouss
-// @brief 64x0 Assembler.
+// @author Amlal EL Mahrouss
+// @brief 64x000 Assembler.
// REMINDER: when dealing with an undefined symbol use (string
// size):LinkerFindSymbol:(string) so that ld will look for it.
@@ -19,10 +19,10 @@
#define __ASM_NEED_64x0__ 1
-#include <Headers/AsmKit/CPU/64x0.hpp>
-#include <Headers/ParserKit.hpp>
-#include <Headers/StdKit/AE.hpp>
-#include <Headers/StdKit/PEF.hpp>
+#include <NDKKit/AsmKit/CPU/64x0.hpp>
+#include <NDKKit/Parser.hpp>
+#include <NDKKit/NFC/AE.hpp>
+#include <NDKKit/NFC/PEF.hpp>
#include <algorithm>
#include <filesystem>
#include <fstream>
@@ -105,26 +105,26 @@ void print_warning(std::string reason, const std::string &file) noexcept {
/////////////////////////////////////////////////////////////////////////////////////////
-MPCC_MODULE(NewOSAssembler64000) {
+NDK_MODULE(NewOSAssembler64000) {
for (size_t i = 1; i < argc; ++i) {
- if (argv[i][0] == '-') {
- if (strcmp(argv[i], "-version") == 0 || strcmp(argv[i], "-v") == 0) {
+ 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";
+ "ZKA Technologies.\n";
return 0;
- } else if (strcmp(argv[i], "-h") == 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";
+ 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) {
+ } else if (strcmp(argv[i], "/binary") == 0) {
kOutputAsBinary = true;
continue;
- } else if (strcmp(argv[i], "-verbose") == 0) {
+ } else if (strcmp(argv[i], "/verbose") == 0) {
kVerbose = true;
continue;
}
@@ -303,7 +303,7 @@ 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 (CompilerKit::find_word(line, "import")) {
if (kOutputAsBinary) {
detail::print_error("Invalid import directive in flat binary mode.",
"64asm");
@@ -314,7 +314,7 @@ static bool asm_read_attributes(std::string &line) {
/// sanity check to avoid stupid linker errors.
if (name.size() == 0) {
- detail::print_error("Invalid import", "ppcasm");
+ detail::print_error("Invalid import", "power-as");
throw std::runtime_error("invalid_import");
}
@@ -364,7 +364,7 @@ static bool asm_read_attributes(std::string &line) {
// export is a special keyword used by 64asm to tell the AE output stage to
// mark this section as a header. it currently supports .code64, .data64.,
// .zero64
- else if (ParserKit::find_word(line, "export")) {
+ else if (CompilerKit::find_word(line, "export")) {
if (kOutputAsBinary) {
detail::print_error("Invalid export directive in flat binary mode.",
"64asm");
@@ -454,9 +454,9 @@ std::string CompilerKit::Encoder64x0::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") ||
- line.find('#') != std::string::npos || ParserKit::find_word(line, ";")) {
+ if (line.empty() || CompilerKit::find_word(line, "import") ||
+ CompilerKit::find_word(line, "export") ||
+ line.find('#') != std::string::npos || CompilerKit::find_word(line, ";")) {
if (line.find('#') != std::string::npos) {
line.erase(line.find('#'));
} else if (line.find(';') != std::string::npos) {
@@ -539,7 +539,7 @@ std::string CompilerKit::Encoder64x0::CheckLine(std::string &line,
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 (CompilerKit::find_word(line, opcode64x0.fName)) {
if (!isspace(line[line.find(opcode64x0.fName) +
strlen(opcode64x0.fName)])) {
err_str += "\nMissing space between ";
@@ -668,11 +668,11 @@ bool CompilerKit::Encoder64x0::WriteNumber(const std::size_t &pos,
bool CompilerKit::Encoder64x0::WriteLine(std::string &line,
const std::string &file) {
- if (ParserKit::find_word(line, "export ")) return true;
+ if (CompilerKit::find_word(line, "export ")) return true;
for (auto &opcode64x0 : kOpcodes64x0) {
// strict check here
- if (ParserKit::find_word(line, opcode64x0.fName) &&
+ if (CompilerKit::find_word(line, opcode64x0.fName) &&
detail::algorithm::is_valid(line)) {
std::string name(opcode64x0.fName);
std::string jump_label, cpy_jump_label;
@@ -763,7 +763,7 @@ bool CompilerKit::Encoder64x0::WriteLine(std::string &line,
"invalid combination of opcode and registers.\nline: " + line,
file);
throw std::runtime_error("invalid_comb_op_reg");
- } else if (found_some == 1 && name == "dec") {
+ } else if (found_some == 1 && name == "sub") {
detail::print_error(
"invalid combination of opcode and registers.\nline: " + line,
file);
diff --git a/NDKKit/Sources/64x0-cc.cxx b/NDKKit/Sources/64x0-cc.cxx
new file mode 100644
index 0000000..19d995d
--- /dev/null
+++ b/NDKKit/Sources/64x0-cc.cxx
@@ -0,0 +1,1627 @@
+/*
+ * ========================================================
+ *
+ * cc
+ * Copyright ZKA Technologies, all rights reserved.
+ *
+ * ========================================================
+ */
+
+/// BUGS: 0
+/// TODO: none
+
+#include <NDKKit/AsmKit/CPU/64x0.hpp>
+#include <NDKKit/Parser.hpp>
+#include <NDKKit/UUID.hpp>
+#include <filesystem>
+#include <cstdio>
+#include <fstream>
+#include <iostream>
+#include <memory>
+#include <random>
+#include <string>
+#include <utility>
+#include <vector>
+
+/* C driver */
+/* This is part of the NDK. */
+/* (c) ZKA Technologies */
+
+/// @author Amlal El Mahrouss (amlel)
+/// @file 64x0-cc.cxx
+/// @brief 64x0 C Compiler.
+
+/// TODO: support structures, else if, else, . and ->
+
+/////////////////////
+
+// ANSI ESCAPE CODES
+
+/////////////////////
+
+#define kOk (0)
+
+#define kBlank "\e[0;30m"
+#define kRed "\e[0;31m"
+#define kWhite "\e[0;97m"
+
+/////////////////////////////////////
+
+// INTERNAL STUFF OF THE C COMPILER
+
+/////////////////////////////////////
+
+namespace detail
+{
+ // \brief name to register struct.
+ struct CompilerRegisterMap final
+ {
+ std::string fName;
+ std::string fReg;
+ };
+
+ // \brief Map for C 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<CompilerKit::SyntaxLeafList> fSyntaxTreeList;
+ std::vector<CompilerRegisterMap> kStackFrame;
+ std::vector<CompilerStructMap> kStructMap;
+ CompilerKit::SyntaxLeafList* fSyntaxTree{nullptr};
+ std::unique_ptr<std::ofstream> fOutputAssembly;
+ std::string fLastFile;
+ std::string fLastError;
+ bool fVerbose;
+ };
+} // namespace detail
+
+static detail::CompilerState kState;
+static SizeType kErrorLimit = 100;
+static std::string kIfFunction = "";
+static Int32 kAcceptableErrors = 0;
+
+namespace detail
+{
+ /// @brief prints an error into stdout.
+ /// @param reason the reason of the error.
+ /// @param file where does it originate from?
+ 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 (kState.fLastFile != file)
+ {
+ std::cout << kRed << "[ cc ] " << kWhite
+ << ((file == "cc") ? "internal compiler error "
+ : ("in file, " + file))
+ << kBlank << std::endl;
+ std::cout << kRed << "[ cc ] " << kWhite << reason << kBlank << std::endl;
+
+ kState.fLastFile = file;
+ }
+ else
+ {
+ std::cout << kRed << "[ cc ] [ " << kState.fLastFile << " ] " << kWhite
+ << reason << kBlank << std::endl;
+ }
+
+ if (kAcceptableErrors > kErrorLimit)
+ std::exit(3);
+
+ ++kAcceptableErrors;
+ }
+
+ struct CompilerType final
+ {
+ std::string fName;
+ std::string fValue;
+ };
+} // namespace detail
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+// Target architecture.
+static int kMachine = 0;
+
+/////////////////////////////////////////
+
+// REGISTERS ACCORDING TO USED ASSEMBLER
+
+/////////////////////////////////////////
+
+static size_t kRegisterCnt = kAsmRegisterLimit;
+static size_t kStartUsable = 2;
+static size_t kUsableLimit = 15;
+static size_t kRegisterCounter = kStartUsable;
+static std::string kRegisterPrefix = kAsmRegisterPrefix;
+
+/////////////////////////////////////////
+
+// COMPILER PARSING UTILITIES/STATES.
+
+/////////////////////////////////////////
+
+static std::vector<std::string> kFileList;
+static CompilerKit::AssemblyFactory kFactory;
+static bool kInStruct = false;
+static bool kOnWhileLoop = false;
+static bool kOnForLoop = false;
+static bool kInBraces = false;
+static bool kIfFound = false;
+static size_t kBracesCount = 0UL;
+
+/* @brief C compiler backend for C */
+class CompilerBackendCLang final : public CompilerKit::CompilerBackend
+{
+public:
+ explicit CompilerBackendCLang() = default;
+ ~CompilerBackendCLang() override = default;
+
+ MPCC_COPY_DEFAULT(CompilerBackendCLang);
+
+ std::string Check(const char* text, const char* file);
+ bool Compile(const std::string& text, const char* file) override;
+
+ const char* Language() override
+ {
+ return "64k C";
+ }
+};
+
+static CompilerBackendCLang* kCompilerBackend = nullptr;
+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
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+// @name Compile
+// @brief Generate MASM from a C assignement.
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+bool CompilerBackendCLang::Compile(const std::string& text, const char* file)
+{
+ std::string textBuffer = text;
+
+ bool typeFound = false;
+ bool fnFound = false;
+
+ // setup generator.
+ std::random_device rd;
+
+ auto seed_data = std::array<int, std::mt19937::state_size>{};
+ std::generate(std::begin(seed_data), std::end(seed_data), std::ref(rd));
+ std::seed_seq seq(std::begin(seed_data), std::end(seed_data));
+ std::mt19937 generator(seq);
+
+ // start parsing
+ for (size_t text_index = 0; text_index < textBuffer.size(); ++text_index)
+ {
+ auto syntaxLeaf = CompilerKit::SyntaxLeafList::SyntaxLeaf();
+
+ auto gen = uuids::uuid_random_generator{generator};
+ uuids::uuid out = gen();
+
+ detail::number_cast time_off = (UInt64)out.as_bytes().data();
+
+ if (!typeFound)
+ {
+ auto substr = textBuffer.substr(text_index);
+ std::string match_type;
+
+ 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(' '));
+ }
+
+ for (auto& clType : kCompilerTypes)
+ {
+ if (clType.fName == match_type)
+ {
+ match_type.clear();
+
+ std::string buf;
+
+ buf += clType.fValue;
+ buf += ' ';
+
+ if (substr.find('=') != std::string::npos)
+ {
+ break;
+ }
+
+ if (textBuffer.find('(') != std::string::npos)
+ {
+ syntaxLeaf.fUserValue = buf;
+
+ kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
+ }
+
+ typeFound = true;
+ break;
+ }
+ }
+
+ break;
+ }
+
+ match_type += substr[y];
+ }
+ }
+
+ if (textBuffer[text_index] == '{')
+ {
+ if (kInStruct)
+ {
+ continue;
+ }
+
+ kInBraces = true;
+ ++kBracesCount;
+
+ kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
+ }
+
+ // return keyword handler
+ if (textBuffer[text_index] == 'r')
+ {
+ std::string return_keyword;
+ return_keyword += "return";
+
+ std::size_t index = 0UL;
+
+ std::string value;
+
+ for (size_t return_index = text_index; return_index < textBuffer.size();
+ ++return_index)
+ {
+ if (textBuffer[return_index] != return_keyword[index])
+ {
+ for (size_t value_index = return_index;
+ value_index < textBuffer.size(); ++value_index)
+ {
+ if (textBuffer[value_index] == ';')
+ break;
+
+ value += textBuffer[value_index];
+ }
+
+ break;
+ }
+
+ ++index;
+ }
+
+ if (index == return_keyword.size())
+ {
+ if (!value.empty())
+ {
+ if (value.find('(') != std::string::npos)
+ {
+ value.erase(value.find('('));
+ }
+
+ if (!isdigit(value[value.find('(') + 2]))
+ {
+ std::string tmp = value;
+ bool reg_to_reg = false;
+
+ value.clear();
+
+ value += " import";
+ value += tmp;
+ }
+
+ syntaxLeaf.fUserValue = "\tldw r19, ";
+
+ // make it pretty.
+ if (value.find('\t') != std::string::npos)
+ value.erase(value.find('\t'), 1);
+
+ syntaxLeaf.fUserValue += value + "\n";
+ }
+
+ syntaxLeaf.fUserValue += "\tjlr";
+
+ kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
+
+ break;
+ }
+ }
+
+ if (textBuffer[text_index] == 'i' && textBuffer[text_index + 1] == 'f')
+ {
+ auto expr = textBuffer.substr(text_index + 2);
+ textBuffer.erase(text_index, 2);
+
+ if (expr.find("{") != std::string::npos)
+ {
+ expr.erase(expr.find("{"));
+ }
+
+ if (expr.find("(") != std::string::npos)
+ expr.erase(expr.find("("));
+
+ if (expr.find(")") != std::string::npos)
+ expr.erase(expr.find(")"));
+
+ kIfFunction = "__MPCC_IF_PROC_";
+ kIfFunction += std::to_string(time_off._Raw);
+
+ syntaxLeaf.fUserValue = "\tlda r12, import ";
+ syntaxLeaf.fUserValue +=
+ kIfFunction +
+ "\n\t#r12 = Code to jump on, r11 right cond, r10 left cond.\n\tbeq "
+ "r10, r11, r12\ndword export .code64 " +
+ kIfFunction + "\n";
+ kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
+
+ kIfFound = true;
+ }
+
+ // Parse expressions and instructions here.
+ // what does this mean?
+ // we encounter an assignment, or we reached the end of an expression.
+ if (textBuffer[text_index] == '=' || textBuffer[text_index] == ';')
+ {
+ if (fnFound)
+ continue;
+ if (kIfFound)
+ continue;
+
+ if (textBuffer[text_index] == ';' && kInStruct)
+ continue;
+
+ if (textBuffer.find("typedef ") != std::string::npos)
+ continue;
+
+ if (textBuffer[text_index] == '=' && kInStruct)
+ {
+ detail::print_error("assignement of value in struct " + textBuffer,
+ file);
+ continue;
+ }
+
+ if (textBuffer[text_index] == ';' && kInStruct)
+ {
+ bool space_found_ = false;
+ std::string sym;
+
+ for (auto& ch : textBuffer)
+ {
+ if (ch == ' ')
+ {
+ space_found_ = true;
+ }
+
+ if (ch == ';')
+ break;
+
+ if (space_found_)
+ sym.push_back(ch);
+ }
+
+ kState.kStructMap[kState.kStructMap.size() - 1].fOffsets.push_back(
+ std::make_pair(
+ kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt + 4,
+ sym));
+
+ kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt =
+ kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt + 4;
+
+ continue;
+ }
+
+ if (textBuffer[text_index] == '=' && kInStruct)
+ {
+ continue;
+ }
+
+ if (textBuffer[text_index + 1] == '=' ||
+ textBuffer[text_index - 1] == '!' ||
+ textBuffer[text_index - 1] == '<' ||
+ textBuffer[text_index - 1] == '>')
+ {
+ continue;
+ }
+
+ std::string substr;
+
+ if (textBuffer.find('=') != std::string::npos && kInBraces && !kIfFound)
+ {
+ if (textBuffer.find("*") != std::string::npos)
+ {
+ if (textBuffer.find("=") > textBuffer.find("*"))
+ substr += "\tlda ";
+ else
+ substr += "\tldw ";
+ }
+ else
+ {
+ substr += "\tldw ";
+ }
+ }
+ else if (textBuffer.find('=') != std::string::npos && !kInBraces)
+ {
+ substr += "stw export .data64 ";
+ }
+
+ int first_encountered = 0;
+
+ std::string str_name;
+
+ for (size_t text_index_2 = 0; text_index_2 < textBuffer.size();
+ ++text_index_2)
+ {
+ if (textBuffer[text_index_2] == '\"')
+ {
+ ++text_index_2;
+
+ // want to add this, so that the parser recognizes that this is a
+ // string.
+ substr += '"';
+
+ for (; text_index_2 < textBuffer.size(); ++text_index_2)
+ {
+ if (textBuffer[text_index_2] == '\"')
+ break;
+
+ substr += textBuffer[text_index_2];
+ }
+ }
+
+ if (textBuffer[text_index_2] == '{' || textBuffer[text_index_2] == '}')
+ continue;
+
+ if (textBuffer[text_index_2] == ';')
+ {
+ break;
+ }
+
+ if (textBuffer[text_index_2] == ' ' ||
+ textBuffer[text_index_2] == '\t')
+ {
+ if (first_encountered != 2)
+ {
+ if (textBuffer[text_index] != '=' &&
+ substr.find("export .data64") == std::string::npos &&
+ !kInStruct)
+ substr += "export .data64 ";
+ }
+
+ ++first_encountered;
+
+ continue;
+ }
+
+ if (textBuffer[text_index_2] == '=')
+ {
+ if (!kInBraces)
+ {
+ substr.replace(substr.find("export .data64"),
+ strlen("export .data64"), "export .zero64 ");
+ }
+
+ substr += ",";
+ continue;
+ }
+
+ substr += textBuffer[text_index_2];
+ }
+
+ for (auto& clType : kCompilerTypes)
+ {
+ if (substr.find(clType.fName) != std::string::npos)
+ {
+ if (substr.find(clType.fName) > substr.find('"'))
+ continue;
+
+ 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 (clType.fName == "const")
+ continue;
+
+ substr.erase(substr.find(clType.fValue), clType.fValue.size());
+ }
+ }
+
+ if (substr.find("extern") != std::string::npos)
+ {
+ substr.replace(substr.find("extern"), strlen("extern"), "import ");
+
+ if (substr.find("export .data64") != std::string::npos)
+ substr.erase(substr.find("export .data64"), strlen("export .data64"));
+ }
+
+ auto var_to_find =
+ std::find_if(kCompilerVariables.cbegin(), kCompilerVariables.cend(),
+ [&](detail::CompilerType type) {
+ return type.fName.find(substr) != std::string::npos;
+ });
+
+ if (kRegisterCounter == 5 || kRegisterCounter == 6)
+ ++kRegisterCounter;
+
+ std::string reg = kAsmRegisterPrefix;
+ reg += std::to_string(kRegisterCounter);
+
+ if (var_to_find == kCompilerVariables.cend())
+ {
+ ++kRegisterCounter;
+
+ kState.kStackFrame.push_back({.fName = substr, .fReg = reg});
+ kCompilerVariables.push_back({.fName = substr});
+ }
+
+ syntaxLeaf.fUserValue += substr;
+ kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
+
+ if (textBuffer[text_index] == '=')
+ break;
+ }
+
+ // function handler.
+
+ if (textBuffer[text_index] == '(' && !fnFound && !kIfFound)
+ {
+ std::string substr;
+ std::string args_buffer;
+ std::string args;
+
+ bool type_crossed = false;
+
+ for (size_t idx = textBuffer.find('(') + 1; idx < textBuffer.size();
+ ++idx)
+ {
+ if (textBuffer[idx] == ',')
+ continue;
+
+ if (textBuffer[idx] == ' ')
+ continue;
+
+ if (textBuffer[idx] == ')')
+ break;
+ }
+
+ for (char substr_first_index : textBuffer)
+ {
+ if (substr_first_index != ',')
+ args_buffer += substr_first_index;
+ else
+ args_buffer += '$';
+
+ 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 (!args_buffer.empty())
+ args += "\tldw r6, ";
+
+ std::string register_type;
+ std::size_t index = 7UL;
+
+ while (args_buffer.find("$") != std::string::npos)
+ {
+ register_type = kRegisterPrefix;
+ register_type += std::to_string(index);
+
+ ++index;
+
+ args_buffer.replace(args_buffer.find('$'), 1,
+ "\n\tldw " + register_type + ",");
+ }
+
+ args += args_buffer;
+ args += "\n\tlda r19, ";
+ }
+ }
+
+ for (char _text_i : textBuffer)
+ {
+ if (_text_i == '\t' || _text_i == ' ')
+ {
+ if (!type_crossed)
+ {
+ substr.clear();
+ type_crossed = true;
+ }
+
+ continue;
+ }
+
+ if (_text_i == '(')
+ break;
+
+ substr += _text_i;
+ }
+
+ if (kInBraces)
+ {
+ syntaxLeaf.fUserValue = args;
+ syntaxLeaf.fUserValue += substr;
+ syntaxLeaf.fUserValue += "\n\tjrl\n";
+
+ kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
+
+ fnFound = true;
+ }
+ else
+ {
+ syntaxLeaf.fUserValue.clear();
+
+ syntaxLeaf.fUserValue += "export .code64 ";
+
+ syntaxLeaf.fUserValue += substr;
+ syntaxLeaf.fUserValue += "\n";
+
+ kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
+
+ fnFound = true;
+ }
+
+ kCompilerFunctions.push_back(textBuffer);
+ }
+
+ if (textBuffer[text_index] == '-' && textBuffer[text_index + 1] == '-')
+ {
+ textBuffer = textBuffer.replace(textBuffer.find("--"), strlen("--"), "");
+
+ for (int _text_i = 0; _text_i < textBuffer.size(); ++_text_i)
+ {
+ if (textBuffer[_text_i] == '\t' || textBuffer[_text_i] == ' ')
+ textBuffer.erase(_text_i, 1);
+ }
+
+ syntaxLeaf.fUserValue += "sub ";
+ syntaxLeaf.fUserValue += textBuffer;
+
+ kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
+ break;
+ }
+
+ if (textBuffer[text_index] == '}')
+ {
+ kRegisterCounter = kStartUsable;
+
+ --kBracesCount;
+
+ if (kBracesCount < 1)
+ {
+ kInBraces = false;
+ kBracesCount = 0;
+ }
+
+ if (kIfFound)
+ kIfFound = false;
+
+ if (kInStruct)
+ kInStruct = false;
+
+ kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
+ }
+
+ syntaxLeaf.fUserValue.clear();
+ }
+
+ auto syntaxLeaf = CompilerKit::SyntaxLeafList::SyntaxLeaf();
+ syntaxLeaf.fUserValue = "\n";
+ kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
+
+ return true;
+}
+
+static bool kShouldHaveBraces = false;
+static std::string kFnName;
+
+std::string CompilerBackendCLang::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;
+
+ for (int i = 0; i < ln.size(); ++i)
+ {
+ if (isalnum(ln[i]))
+ {
+ non_ascii_found = true;
+ break;
+ }
+ }
+
+ if (kShouldHaveBraces && ln.find('{') != std::string::npos)
+ {
+ kShouldHaveBraces = false;
+ }
+
+ if (!non_ascii_found)
+ return err_str;
+
+ size_t string_index = 1UL;
+
+ 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);
+ }
+
+ 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("class");
+ 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;
+ }
+ }
+ }
+
+ 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;
+ }
+
+ keyword.push_back(ln[string_index]);
+ }
+
+ goto cc_next_loop;
+
+ cc_check_done:
+
+ // skip digit value.
+ if (isdigit(keyword[0]) || keyword[0] == '"')
+ {
+ goto cc_next_loop;
+ }
+
+ while (keyword.find(' ') != std::string::npos)
+ keyword.erase(keyword.find(' '), 1);
+
+ for (auto& var : kCompilerVariables)
+ {
+ if (var.fValue.find(keyword) != std::string::npos)
+ {
+ err_str.clear();
+ goto cc_next;
+ }
+ }
+
+ 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;
+ }
+ }
+ }
+
+ cc_error_value:
+ if (keyword.find("->") != std::string::npos)
+ return err_str;
+
+ if (keyword.find(".") != std::string::npos)
+ return err_str;
+
+ if (isalnum(keyword[0]))
+ err_str += "\nUndefined value: " + keyword;
+
+ return err_str;
+ }
+
+ cc_next_loop:
+ continue;
+ }
+
+cc_next:
+
+ // extern does not declare anything, it imports a variable.
+ // so that's why it's not declare upper.
+ if (CompilerKit::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 (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;
+ }
+ }
+
+skip_braces_check:
+
+ for (auto& key : kCompilerTypes)
+ {
+ if (CompilerKit::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[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;
+
+ 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;
+ }
+ }
+
+ next:
+
+ 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;
+ }
+
+ 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 (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 && !CompilerKit::find_word(ln, "|") &&
+ !CompilerKit::find_word(ln, "||") && !CompilerKit::find_word(ln, "&") &&
+ !CompilerKit::find_word(ln, "&&") && !CompilerKit::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;
+
+ bool space_found = false;
+
+ for (int i = 0; i < ln.size(); ++i)
+ {
+ if (ln[i] == ')' && !space_found)
+ {
+ space_found = true;
+ continue;
+ }
+
+ if (space_found)
+ {
+ if (ln[i] == ' ' && isalnum(ln[i + 1]))
+ {
+ err_str += "\nBad function format 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)
+ {
+ 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('}') != 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;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * @brief C To Assembly mount-point.
+ */
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+class AssemblyCCInterface final : public CompilerKit::AssemblyInterface
+{
+public:
+ explicit AssemblyCCInterface() = default;
+ ~AssemblyCCInterface() override = default;
+
+ MPCC_COPY_DEFAULT(AssemblyCCInterface);
+
+ [[maybe_unused]] static Int32 Arch() noexcept
+ {
+ return CompilerKit::AssemblyFactory::kArch64x0;
+ }
+
+ Int32 CompileToFormat(std::string& src, Int32 arch) override
+ {
+ if (arch != AssemblyCCInterface::Arch())
+ return -1;
+
+ if (kCompilerBackend == nullptr)
+ return -1;
+
+ /* @brief copy contents wihtout extension */
+ std::string src_file = src.data();
+ std::ifstream src_fp = std::ifstream(src_file, std::ios::in);
+ std::string dest;
+
+ for (auto& ch : src_file)
+ {
+ if (ch == '.')
+ {
+ break;
+ }
+
+ dest += ch;
+ }
+
+ /* According to PEF ABI. */
+ std::vector<const char*> exts = kAsmFileExts;
+ dest += exts[4];
+
+ kState.fOutputAssembly = std::make_unique<std::ofstream>(dest);
+
+ auto fmt = CompilerKit::current_date();
+
+ (*kState.fOutputAssembly) << "# Path: " << src_file << "\n";
+ (*kState.fOutputAssembly)
+ << "# Language: 64x0 Assembly (Generated from ANSI C)\n";
+ (*kState.fOutputAssembly) << "# Date: " << fmt << "\n\n";
+
+ CompilerKit::SyntaxLeafList syntax;
+
+ kState.fSyntaxTreeList.push_back(syntax);
+ kState.fSyntaxTree =
+ &kState.fSyntaxTreeList[kState.fSyntaxTreeList.size() - 1];
+
+ std::string line_src;
+
+ while (std::getline(src_fp, line_src))
+ {
+ if (auto err = kCompilerBackend->Check(line_src.c_str(), src.data());
+ err.empty())
+ {
+ kCompilerBackend->Compile(line_src, src.data());
+ }
+ else
+ {
+ detail::print_error(err, src.data());
+ }
+ }
+
+ if (kAcceptableErrors > 0)
+ return -1;
+
+ std::vector<std::string> keywords = {"ldw", "stw", "lda", "sta",
+ "add", "sub", "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 (CompilerKit::find_word(leaf.fUserValue, access_ident))
+ {
+ for (auto& struc : kState.kStructMap)
+ {
+ /// TODO:
+ }
+ }
+ }
+
+ for (auto& keyword : keywords)
+ {
+ if (CompilerKit::find_word(leaf.fUserValue, keyword))
+ {
+ std::size_t cnt = 0UL;
+
+ for (auto& reg : 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 (CompilerKit::find_word(leaf.fUserValue, needle))
+ {
+ if (leaf.fUserValue.find("import " + needle) !=
+ std::string::npos)
+ {
+ std::string range = "import " + needle;
+ leaf.fUserValue.replace(
+ leaf.fUserValue.find("import " + needle), range.size(),
+ 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 != "sub")
+ {
+ leaf.fUserValue.replace(leaf.fUserValue.find(keyword),
+ keyword.size(), "mv");
+ }
+ }
+ }
+ }
+
+ for (auto& leaf : kState.fSyntaxTree->fLeafList)
+ {
+ (*kState.fOutputAssembly) << leaf.fUserValue;
+ }
+
+ kState.fSyntaxTree = nullptr;
+
+ kState.fOutputAssembly->flush();
+ kState.fOutputAssembly.reset();
+
+ return kOk;
+ }
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Version.hpp>
+
+#define kPrintF printf
+#define kSplashCxx() \
+ kPrintF(kWhite "ZKA C Driver, %s, (c) ZKA Technologies\n", kDistVersion)
+
+static void cc_print_help()
+{
+ kSplashCxx();
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+#define kExt ".c"
+
+NDK_MODULE(NewOSCompilerCLang64x0)
+{
+ 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"});
+ kCompilerTypes.push_back({.fName = "*", .fValue = "offset"});
+
+ bool skip = false;
+
+ kFactory.Mount(new AssemblyCCInterface());
+ kMachine = CompilerKit::AssemblyFactory::kArch64x0;
+ kCompilerBackend = new CompilerBackendCLang();
+
+ 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 (strcmp(argv[index], "/verbose") == 0)
+ {
+ kState.fVerbose = true;
+
+ continue;
+ }
+
+ if (strcmp(argv[index], "/h") == 0 || strcmp(argv[index], "/help") == 0)
+ {
+ cc_print_help();
+
+ return kOk;
+ }
+
+ if (strcmp(argv[index], "/dialect") == 0)
+ {
+ if (kCompilerBackend)
+ std::cout << kCompilerBackend->Language() << "\n";
+
+ return kOk;
+ }
+
+ if (strcmp(argv[index], "/fmax-exceptions") == 0)
+ {
+ try
+ {
+ kErrorLimit = std::strtol(argv[index + 1], nullptr, 10);
+ }
+ // catch anything here
+ catch (...)
+ {
+ kErrorLimit = 0;
+ }
+
+ skip = true;
+
+ continue;
+ }
+
+ std::string err = "Unknown command: ";
+ err += argv[index];
+
+ detail::print_error(err, "cc");
+
+ continue;
+ }
+
+ kFileList.emplace_back(argv[index]);
+
+ std::string srcFile = argv[index];
+
+ if (strstr(argv[index], kExt) == nullptr)
+ {
+ if (kState.fVerbose)
+ {
+ detail::print_error(srcFile + " is not a valid C source.\n", "cc");
+ }
+
+ return 1;
+ }
+
+ if (kFactory.Compile(srcFile, kMachine) != kOk)
+ return -1;
+ }
+
+ return kOk;
+}
+
+// Last rev 8-1-24
diff --git a/NDKKit/Sources/AssemblyFactory.cxx b/NDKKit/Sources/AssemblyFactory.cxx
new file mode 100644
index 0000000..9f1b768
--- /dev/null
+++ b/NDKKit/Sources/AssemblyFactory.cxx
@@ -0,0 +1,59 @@
+/* -------------------------------------------
+
+ Copyright ZKA Technologies
+
+------------------------------------------- */
+
+#include <NDKKit/AsmKit/AsmKit.hpp>
+#include <NDKKit/NFC/ErrorID.hpp>
+
+/**
+ * @file AssemblyFactory.cxx
+ * @author amlal (amlal@zeta.com)
+ * @brief Assembler Kit
+ * @version 0.1
+ * @date 2024-01-27
+ *
+ * @copyright Copyright (c) 2024, ZKA Technologies
+ *
+ */
+
+#include <iostream>
+
+//! @file AsmKit.cpp
+//! @brief AssemblyKit source implementation.
+
+namespace CompilerKit
+{
+ ///! @brief Compile for specific format (ELF, PEF, ZBIN)
+ Int32 AssemblyFactory::Compile(std::string& sourceFile,
+ const Int32& arch) noexcept
+ {
+ if (sourceFile.length() < 1 || !fMounted)
+ return MPCC_UNIMPLEMENTED;
+
+ return fMounted->CompileToFormat(sourceFile, arch);
+ }
+
+ ///! @brief mount assembly backend.
+ void AssemblyFactory::Mount(AssemblyInterface* mountPtr) noexcept
+ {
+ if (mountPtr)
+ {
+ fMounted = mountPtr;
+ }
+ }
+
+ ///! @brief Unmount assembler.
+ AssemblyInterface* AssemblyFactory::Unmount() noexcept
+ {
+ auto mount_prev = fMounted;
+
+ if (mount_prev)
+ {
+ fMounted = nullptr;
+ }
+
+ return mount_prev;
+ }
+} // namespace CompilerKit
diff --git a/Sources/Detail/ReadMe.md b/NDKKit/Sources/Detail/ReadMe.md
index e9d0a2c..e9d0a2c 100644
--- a/Sources/Detail/ReadMe.md
+++ b/NDKKit/Sources/Detail/ReadMe.md
diff --git a/Sources/Detail/asmutils.h b/NDKKit/Sources/Detail/asmutils.hxx
index 2408998..abb7f82 100644
--- a/Sources/Detail/asmutils.h
+++ b/NDKKit/Sources/Detail/asmutils.hxx
@@ -1,13 +1,13 @@
/* -------------------------------------------
- Copyright Mahrouss Logic
+ Copyright ZKA Technologies
------------------------------------------- */
#pragma once
-#include <Headers/AsmKit/AsmKit.hpp>
-#include <Headers/ParserKit.hpp>
+#include <NDKKit/AsmKit/AsmKit.hpp>
+#include <NDKKit/Parser.hpp>
using namespace CompilerKit;
@@ -32,7 +32,7 @@ static NumberCast32 GetNumber32(std::string lineBuffer, std::string numberKey)
{
if (errno != 0)
{
- detail::print_error("invalid hex number: " + lineBuffer, "ppcasm");
+ detail::print_error("invalid hex number: " + lineBuffer, "asm");
throw std::runtime_error("invalid_hex");
}
}
@@ -41,7 +41,7 @@ static NumberCast32 GetNumber32(std::string lineBuffer, std::string numberKey)
if (kVerbose)
{
- kStdOut << "ppcasm: found a base 16 number here: " << lineBuffer.substr(pos)
+ kStdOut << "asm: found a base 16 number here: " << lineBuffer.substr(pos)
<< "\n";
}
@@ -52,7 +52,7 @@ static NumberCast32 GetNumber32(std::string lineBuffer, std::string numberKey)
{
if (errno != 0)
{
- detail::print_error("invalid binary number:" + lineBuffer, "ppcasm");
+ detail::print_error("invalid binary number:" + lineBuffer, "asm");
throw std::runtime_error("invalid_bin");
}
}
@@ -61,7 +61,7 @@ static NumberCast32 GetNumber32(std::string lineBuffer, std::string numberKey)
if (kVerbose)
{
- kStdOut << "ppcasm: found a base 2 number here:" << lineBuffer.substr(pos)
+ kStdOut << "asm: found a base 2 number here:" << lineBuffer.substr(pos)
<< "\n";
}
@@ -72,7 +72,7 @@ static NumberCast32 GetNumber32(std::string lineBuffer, std::string numberKey)
{
if (errno != 0)
{
- detail::print_error("invalid octal number: " + lineBuffer, "ppcasm");
+ detail::print_error("invalid octal number: " + lineBuffer, "asm");
throw std::runtime_error("invalid_octal");
}
}
@@ -81,7 +81,7 @@ static NumberCast32 GetNumber32(std::string lineBuffer, std::string numberKey)
if (kVerbose)
{
- kStdOut << "ppcasm: found a base 8 number here:" << lineBuffer.substr(pos)
+ kStdOut << "asm: found a base 8 number here:" << lineBuffer.substr(pos)
<< "\n";
}
@@ -92,7 +92,7 @@ static NumberCast32 GetNumber32(std::string lineBuffer, std::string numberKey)
{
if (errno != 0)
{
- detail::print_error("invalid hex number: " + lineBuffer, "ppcasm");
+ detail::print_error("invalid hex number: " + lineBuffer, "asm");
throw std::runtime_error("invalid_hex");
}
}
@@ -101,7 +101,7 @@ static NumberCast32 GetNumber32(std::string lineBuffer, std::string numberKey)
if (kVerbose)
{
- kStdOut << "ppcasm: found a base 10 number here:" << lineBuffer.substr(pos)
+ kStdOut << "asm: found a base 10 number here:" << lineBuffer.substr(pos)
<< "\n";
}
diff --git a/Sources/Detail/compilerutils.h b/NDKKit/Sources/Detail/compilerutils.hxx
index 038f3cf..fd2b6d2 100644
--- a/Sources/Detail/compilerutils.h
+++ b/NDKKit/Sources/Detail/compilerutils.hxx
@@ -1,13 +1,13 @@
/* -------------------------------------------
- Copyright Mahrouss Logic
+ Copyright ZKA Technologies
------------------------------------------- */
#pragma once
-#include <Headers/AsmKit/AsmKit.hpp>
-#include <Headers/ParserKit.hpp>
+#include <NDKKit/AsmKit/AsmKit.hpp>
+#include <NDKKit/Parser.hpp>
#define kZero64Section ".zero64"
#define kCode64Section ".code64"
diff --git a/Sources/String.cc b/NDKKit/Sources/String.cxx
index 449c933..f69f9b9 100644
--- a/Sources/String.cc
+++ b/NDKKit/Sources/String.cxx
@@ -2,24 +2,23 @@
* ========================================================
*
* CompilerKit
- * Copyright Mahrouss Logic, all rights reserved.
+ * Copyright ZKA Technologies, all rights reserved.
*
* ========================================================
*/
/**
- * @file String.cc
+ * @file String.cxx
* @author Amlal (amlal@mahrouss-logic.com)
* @brief C++ string manipulation API.
* @version 0.2
* @date 2024-01-23
*
- * @copyright Copyright (c) 2024 Mahrouss Logic
+ * @copyright Copyright (c) ZKA Technologies
*
*/
-#include <Headers/StdKit/String.hpp>
-#include <utility>
+#include <NDKKit/NFC/String.hpp>
namespace CompilerKit {
CharType *StringView::Data() { return m_Data; }
@@ -80,10 +79,13 @@ StringView StringBuilder::Construct(const CharType *data) {
const char *StringBuilder::FromInt(const char *fmt, int i) {
if (!fmt) return ("-1");
- char *ret = new char[8 + string_length(fmt)];
+ auto ret_len = 8 + string_length(fmt);
+ char *ret = new char[ret_len];
if (!ret) return ("-1");
+ memset(ret, 0, ret_len);
+
CharType result[8];
if (!to_str(result, sizeof(int), i)) {
delete[] ret;
@@ -150,18 +152,18 @@ bool StringBuilder::Equals(const char *lhs, const char *rhs) {
return true;
}
-const char *StringBuilder::Format(const char *fmt, const char *fmt2) {
- if (!fmt || !fmt2) return ("?");
+const char *StringBuilder::Format(const char *fmt, const char *fmtRight) {
+ if (!fmt || !fmtRight) return ("?");
- char *ret = new char[string_length(fmt2) + string_length(fmt2)];
+ char *ret = new char[string_length(fmtRight) + string_length(fmtRight)];
if (!ret) return ("?");
for (SizeType idx = 0; idx < string_length(fmt); ++idx) {
if (fmt[idx] == '%') {
SizeType result_cnt = idx;
- for (SizeType y_idx = 0; y_idx < string_length(fmt2); ++y_idx) {
- ret[result_cnt] = fmt2[y_idx];
+ for (SizeType y_idx = 0; y_idx < string_length(fmtRight); ++y_idx) {
+ ret[result_cnt] = fmtRight[y_idx];
++result_cnt;
}
diff --git a/Sources/bpp.cc b/NDKKit/Sources/bpp.cxx
index 1e15366..9a2943c 100644
--- a/Sources/bpp.cc
+++ b/NDKKit/Sources/bpp.cxx
@@ -2,15 +2,15 @@
* ========================================================
*
* bpp
- * Copyright Mahrouss Logic, all rights reserved.
+ * Copyright ZKA Technologies, all rights reserved.
*
* ========================================================
*/
/// BUGS: 0
-#include <Headers/ParserKit.hpp>
-#include <Headers/StdKit/ErrorID.hpp>
+#include <NDKKit/Parser.hpp>
+#include <NDKKit/NFC/ErrorID.hpp>
#include <algorithm>
#include <filesystem>
#include <fstream>
@@ -19,9 +19,9 @@
#define kMacroPrefix '%'
-// @author Amlal El Mahrouss (amlel)
-// @file bpp.cc
-// @brief C preprocessor.
+/// @author Amlal El Mahrouss (amlel)
+/// @file bpp.cxx
+/// @brief Preprocessor.
typedef Int32 (*bpp_parser_fn_t)(std::string &line, std::ifstream &hdr_file,
std::ofstream &pp_out);
@@ -279,7 +279,7 @@ void bpp_parse_file(std::ifstream &hdr_file, std::ofstream &pp_out) {
}
for (auto macro : kMacros) {
- if (ParserKit::find_word(hdr_line, macro.fName) &&
+ if (CompilerKit::find_word(hdr_line, macro.fName) &&
hdr_line.find("%def") == std::string::npos) {
auto value = macro.fValue;
@@ -775,7 +775,7 @@ void bpp_parse_file(std::ifstream &hdr_file, std::ofstream &pp_out) {
/////////////////////////////////////////////////////////////////////////////////////////
-MPCC_MODULE(NewOSPreprocessor) {
+NDK_MODULE(NewOSPreprocessor) {
try {
bool skip = false;
bool double_skip = false;
@@ -810,23 +810,24 @@ MPCC_MODULE(NewOSPreprocessor) {
continue;
}
- if (argv[index][0] == '-') {
- if (strcmp(argv[index], "-v") == 0) {
- printf("%s\n", "bpp v1.11, (c) Mahrouss Logic");
+ if (argv[index][0] == '/') {
+ if (strcmp(argv[index], "/version") == 0) {
+ printf("%s\n", "bpp v1.11, (c) ZKA Technologies");
return 0;
}
- if (strcmp(argv[index], "-h") == 0) {
- printf("%s\n", "bpp v1.11, (c) Mahrouss Logic");
- printf("%s\n", "-working-dir <path>: set directory to working path.");
- printf("%s\n", "-include-dir <path>: add directory to include path.");
- printf("%s\n", "-def <name> <value>: def macro.");
- printf("%s\n", "-version: print the version.");
+ if (strcmp(argv[index], "/help") == 0) {
+ printf("%s\n", "ZKA Preprocessor Driver v1.11, (c) ZKA Technologies");
+ printf("%s\n", "/working-dir <path>: set directory to working path.");
+ printf("%s\n", "/include-dir <path>: add directory to include path.");
+ printf("%s\n", "/def <name> <value>: def macro.");
+ printf("%s\n", "/version: print the version.");
+ printf("%s\n", "/help: show help.");
return 0;
}
- if (strcmp(argv[index], "-include-dir") == 0) {
+ if (strcmp(argv[index], "/include-dir") == 0) {
std::string inc = argv[index + 1];
skip = true;
@@ -834,13 +835,13 @@ MPCC_MODULE(NewOSPreprocessor) {
kIncludes.push_back(inc);
}
- if (strcmp(argv[index], "-working-dir") == 0) {
+ if (strcmp(argv[index], "/working-dir") == 0) {
std::string inc = argv[index + 1];
skip = true;
kWorkingDir = inc;
}
- if (strcmp(argv[index], "-def") == 0 && argv[index + 1] != nullptr &&
+ if (strcmp(argv[index], "/def") == 0 && argv[index + 1] != nullptr &&
argv[index + 2] != nullptr) {
std::string macro_key = argv[index + 1];
@@ -892,7 +893,7 @@ MPCC_MODULE(NewOSPreprocessor) {
std::cout << e.what() << '\n';
}
- return 0;
+ return 1;
}
// Last rev 8-1-24
diff --git a/Sources/coff2ae.cc b/NDKKit/Sources/coff2ae.cxx
index 952be69..c9ea8c0 100644
--- a/Sources/coff2ae.cc
+++ b/NDKKit/Sources/coff2ae.cxx
@@ -1,12 +1,12 @@
/* -------------------------------------------
- Copyright Mahrouss Logic
+ Copyright ZKA Technologies
------------------------------------------- */
-#include <Headers/ParserKit.hpp>
-#include <Headers/StdKit/AE.hpp>
-#include <Headers/StdKit/PEF.hpp>
+#include <NDKKit/Parser.hpp>
+#include <NDKKit/NFC/AE.hpp>
+#include <NDKKit/NFC/PEF.hpp>
#include <filesystem>
#include <fstream>
#include <iostream>
@@ -15,8 +15,9 @@
/////////////////////////////////////////////////////////////////////////////////////////
-/// @brief COFF To AE entrypoint, the program/module starts here.
+/// @file coff2ae.cxx
+/// @brief COFF To AE, the program/module starts here.
/////////////////////////////////////////////////////////////////////////////////////////
-MPCC_MODULE(NewOSCOFFToAE) { return 0; }
+NDK_MODULE(NewOSCOFFToAE) { return 0; }
diff --git a/Sources/compile_flags.txt b/NDKKit/Sources/compile_flags.txt
index 028be9d..6ec6b8a 100644
--- a/Sources/compile_flags.txt
+++ b/NDKKit/Sources/compile_flags.txt
@@ -1,5 +1,5 @@
-std=c++20
-I../
--I../StdKit
+-I../Headers
-I./
-I./Detail/
diff --git a/NDKKit/Sources/cplusplus.cxx b/NDKKit/Sources/cplusplus.cxx
new file mode 100644
index 0000000..ae4a300
--- /dev/null
+++ b/NDKKit/Sources/cplusplus.cxx
@@ -0,0 +1,1025 @@
+/*
+ * ========================================================
+ *
+ * cplusplus
+ * Copyright ZKA Technologies, all rights reserved.
+ *
+ * ========================================================
+ */
+
+/// bugs: 0
+
+#define __PK_USE_STRUCT_INSTEAD__ 1
+
+#define kPrintF printf
+
+#define kOk (0)
+
+#define kSplashCxx() \
+ kPrintF(kWhite "%s\n", "ZKA C++ Compiler Driver, (c) 2024 ZKA Electronics, all rights reserved.")
+
+// import, @MLAutoRelease { ... }, fn foo() -> auto { ... }
+
+#include <NDKKit/AsmKit/CPU/amd64.hpp>
+#include <NDKKit/Parser.hpp>
+#include <UUID.hpp>
+
+#include <cctype>
+#include <cstdio>
+#include <fstream>
+#include <iostream>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+/* ZKA C++ driver */
+/* This is part of NDK. */
+/* (c) ZKA Technologies */
+
+/// @author Amlal El Mahrouss (amlel)
+/// @file cc.cxx
+/// @brief Optimized C++ Compiler.
+/// @todo Throw error for scoped inside scoped variables when they get referenced outside.
+/// @todo Add class/struct/enum support.
+
+/////////////////////
+
+// ANSI ESCAPE CODES
+
+/////////////////////
+
+#define kBlank "\e[0;30m"
+#define kRed "\e[0;31m"
+#define kWhite "\e[0;97m"
+
+/////////////////////////////////////
+
+// INTERNALS OF THE C COMPILER
+
+/////////////////////////////////////
+
+/// @internal
+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;
+ };
+
+ struct CompilerState final
+ {
+ std::vector<CompilerKit::SyntaxLeafList> fSyntaxTreeList;
+ std::vector<CompilerRegisterMap> kStackFrame;
+ std::vector<CompilerStructMap> kStructMap;
+ CompilerKit::SyntaxLeafList* fSyntaxTree{nullptr};
+ std::unique_ptr<std::ofstream> fOutputAssembly;
+ std::string fLastFile;
+ std::string fLastError;
+ bool fVerbose;
+ };
+} // namespace detail
+
+static detail::CompilerState kState;
+static SizeType kErrorLimit = 100;
+
+static Int32 kAcceptableErrors = 0;
+
+namespace detail
+{
+ /// @brief prints an error into stdout.
+ /// @param reason the reason of the error.
+ /// @param file where does it originate from?
+ 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 (kState.fLastFile != file)
+ {
+ std::cout << kRed << "[ cplusplus ] " << kWhite
+ << ((file == "cplusplus") ? "internal compiler error "
+ : ("in file, " + file))
+ << kBlank << std::endl;
+ std::cout << kRed << "[ cplusplus ] " << kWhite << reason << kBlank
+ << std::endl;
+
+ kState.fLastFile = file;
+ }
+ else
+ {
+ std::cout << kRed << "[ cplusplus ] [ " << kState.fLastFile << " ] " << kWhite
+ << reason << kBlank << std::endl;
+ }
+
+ if (kAcceptableErrors > kErrorLimit)
+ std::exit(3);
+
+ ++kAcceptableErrors;
+ }
+
+ struct CompilerType
+ {
+ std::string fName;
+ std::string fValue;
+ };
+} // namespace detail
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+// Target architecture.
+static int kMachine = CompilerKit::AssemblyFactory::kArchAMD64;
+
+/////////////////////////////////////////
+
+// ARGUMENTS REGISTERS (R8, R15)
+
+/////////////////////////////////////////
+
+static size_t kRegisterCnt = kAsmRegisterLimit;
+static size_t kStartUsable = 8;
+static size_t kUsableLimit = 15;
+static size_t kRegisterCounter = kStartUsable;
+static std::vector<CompilerKit::CompilerKeyword> kKeywords;
+
+/////////////////////////////////////////
+
+// COMPILER PARSING UTILITIES/STATES.
+
+/////////////////////////////////////////
+
+static std::vector<std::string> kFileList;
+static CompilerKit::AssemblyFactory kFactory;
+static bool kInStruct = false;
+static bool kOnWhileLoop = false;
+static bool kOnForLoop = false;
+static bool kInBraces = false;
+static size_t kBracesCount = 0UL;
+
+/* @brief C++ compiler backend for the ZKA C++ driver */
+class CompilerBackendCPlusPlus final : public CompilerKit::CompilerBackend
+{
+public:
+ explicit CompilerBackendCPlusPlus() = default;
+ ~CompilerBackendCPlusPlus() override = default;
+
+ MPCC_COPY_DEFAULT(CompilerBackendCPlusPlus);
+
+ bool Compile(const std::string& text, const char* file) override;
+
+ const char* Language() override;
+};
+
+/// @internal compiler variables
+
+static CompilerBackendCPlusPlus* kCompilerBackend = nullptr;
+static std::vector<detail::CompilerType> kCompilerVariables;
+static std::vector<std::string> kCompilerFunctions;
+
+static std::vector<std::string> kRegisterMap;
+
+static std::vector<std::string> cRegisters = {
+ "rbx",
+ "rsi",
+ "r10",
+ "r11",
+ "r12",
+ "r13",
+ "r14",
+ "r15",
+ "xmm12",
+ "xmm13",
+ "xmm14",
+ "xmm15",
+};
+
+/// @brief The PEF calling convention (caller must save rax, rbp)
+/// @note callee must return via **rax**.
+static std::vector<std::string> cRegistersCall = {
+ "rcx",
+ "rdx",
+ "r8",
+ "r9",
+ "xmm8",
+ "xmm9",
+ "xmm10",
+ "xmm11",
+};
+
+static size_t kLevelFunction = 0UL;
+
+/// detail namespaces
+
+const char* CompilerBackendCPlusPlus::Language()
+{
+ return "ZKA C++";
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+/// @name Compile
+/// @brief Generate MASM assembly from a C++ source.
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+bool CompilerBackendCPlusPlus::Compile(const std::string& text,
+ const char* file)
+{
+ if (text.empty())
+ return false;
+
+ // if (expr)
+ // int name = expr;
+ // expr;
+
+ std::size_t index = 0UL;
+ std::vector<std::pair<CompilerKit::CompilerKeyword, std::size_t>> keywords_list;
+
+ bool found = false;
+ static bool commentBlock = false;
+
+ for (auto& keyword : kKeywords)
+ {
+ if (text.find(keyword.keyword_name) != std::string::npos)
+ {
+ switch (keyword.keyword_kind)
+ {
+ case CompilerKit::eKeywordKindCommentMultiLineStart: {
+ commentBlock = true;
+ return true;
+ }
+ case CompilerKit::eKeywordKindCommentMultiLineEnd: {
+ commentBlock = false;
+ break;
+ }
+ case CompilerKit::eKeywordKindCommentInline: {
+ break;
+ }
+ default:
+ break;
+ }
+
+ if (text[text.find(keyword.keyword_name) - 1] == '+' &&
+ keyword.keyword_kind == CompilerKit::KeywordKind::eKeywordKindVariableAssign)
+ continue;
+
+ if (text[text.find(keyword.keyword_name) - 1] == '-' &&
+ keyword.keyword_kind == CompilerKit::KeywordKind::eKeywordKindVariableAssign)
+ continue;
+
+ if (text[text.find(keyword.keyword_name) + 1] == '=' &&
+ keyword.keyword_kind == CompilerKit::KeywordKind::eKeywordKindVariableAssign)
+ continue;
+
+ keywords_list.emplace_back(std::make_pair(keyword, index));
+ ++index;
+
+ found = true;
+ }
+ }
+
+ if (!found && !commentBlock)
+ {
+ for (size_t i = 0; i < text.size(); i++)
+ {
+ if (isalnum(text[i]))
+ {
+ detail::print_error("syntax error: " + text, file);
+ return false;
+ }
+ }
+ }
+
+ for (auto& keyword : keywords_list)
+ {
+ auto syntax_tree = CompilerKit::SyntaxLeafList::SyntaxLeaf();
+
+ switch (keyword.first.keyword_kind)
+ {
+ case CompilerKit::KeywordKind::eKeywordKindIf: {
+ auto expr = text.substr(text.find(keyword.first.keyword_name) + keyword.first.keyword_name.size() + 1, text.find(")") - 1);
+
+ if (expr.find(">=") != std::string::npos)
+ {
+ auto left = text.substr(text.find(keyword.first.keyword_name) + keyword.first.keyword_name.size() + 2, expr.find("<=") + strlen("<="));
+ auto right = text.substr(expr.find(">=") + strlen(">="), text.find(")") - 1);
+
+ size_t i = right.size() - 1;
+
+ try
+ {
+ while (!std::isalnum(right[i]))
+ {
+ right.erase(i, 1);
+ --i;
+ }
+
+ right.erase(0, i);
+ }
+ catch (...)
+ {
+ right.erase(0, i);
+ }
+
+ i = left.size() - 1;
+ try
+ {
+
+ while (!std::isalnum(left[i]))
+ {
+ left.erase(i, 1);
+ --i;
+ }
+
+ left.erase(0, i);
+ }
+ catch (...)
+ {
+ left.erase(0, i);
+ }
+
+ if (!isdigit(left[0]) ||
+ !isdigit(right[0]))
+ {
+ auto indexRight = 0UL;
+
+ auto& valueOfVar = !isdigit(left[0]) ? left : right;
+
+ for (auto pairRight : kRegisterMap)
+ {
+ ++indexRight;
+
+ if (pairRight != valueOfVar)
+ {
+
+ auto& valueOfVarOpposite = isdigit(left[0]) ? left : right;
+
+ syntax_tree.fUserValue += "mov " + cRegisters[indexRight + 1] + ", " + valueOfVarOpposite + "\n";
+
+ syntax_tree.fUserValue += "mov " + cRegisters[kRegisterMap.size() - 1] + ", " + valueOfVar + "\n";
+ syntax_tree.fUserValue += "cmp " + cRegisters[kRegisterMap.size() - 1] + "," + cRegisters[indexRight + 1] + "\n";
+
+ goto done_iterarting_on_if;
+ }
+
+ auto& valueOfVarOpposite = isdigit(left[0]) ? left : right;
+
+ syntax_tree.fUserValue += "mov " + cRegisters[indexRight + 1] + ", " + valueOfVarOpposite + "\n";
+ syntax_tree.fUserValue += "mov " + cRegisters[kRegisterMap.size() - 1] + ", " + valueOfVar + "\n";
+ syntax_tree.fUserValue += "cmp " + cRegisters[kRegisterMap.size() - 1] + ", " + cRegisters[indexRight + 1] + "\n";
+
+ break;
+ }
+ }
+
+ done_iterarting_on_if:
+
+ std::string fnName = text;
+ fnName.erase(fnName.find(keyword.first.keyword_name));
+
+ for (auto& ch : fnName)
+ {
+ if (ch == ' ')
+ ch = '_';
+ }
+
+ syntax_tree.fUserValue += "jge offset [rsp + 4]\n";
+ }
+
+ break;
+ }
+ case CompilerKit::KeywordKind::eKeywordKindFunctionStart: {
+ if (text.ends_with(";"))
+ {
+ break;
+ }
+
+ for (auto& ch : text)
+ {
+ if (isdigit(ch))
+ {
+ goto dont_accept;
+ }
+ }
+
+ goto accept;
+
+ dont_accept:
+ return true;
+
+ accept:
+ std::string fnName = text;
+
+ for (auto& ch : fnName)
+ {
+ if (ch == ' ')
+ ch = '_';
+ }
+
+ syntax_tree.fUserValue = "export .code64 __MPCC_" + fnName + "\n";
+
+ ++kLevelFunction;
+ }
+ case CompilerKit::KeywordKind::eKeywordKindFunctionEnd: {
+ if (text.ends_with(";"))
+ break;
+
+ --kLevelFunction;
+
+ if (kRegisterMap.size() > cRegisters.size())
+ {
+ --kLevelFunction;
+ }
+
+ if (kLevelFunction < 1)
+ kRegisterMap.clear();
+ break;
+ }
+ case CompilerKit::KeywordKind::eKeywordKindEndInstr:
+ case CompilerKit::KeywordKind::eKeywordKindVariableInc:
+ case CompilerKit::KeywordKind::eKeywordKindVariableDec:
+ case CompilerKit::KeywordKind::eKeywordKindVariableAssign: {
+ std::string valueOfVar = "";
+
+ if (keyword.first.keyword_kind == CompilerKit::KeywordKind::eKeywordKindVariableInc)
+ {
+ valueOfVar = text.substr(text.find("+=") + 2);
+ }
+ else if (keyword.first.keyword_kind == CompilerKit::KeywordKind::eKeywordKindVariableDec)
+ {
+ valueOfVar = text.substr(text.find("-=") + 2);
+ }
+ else if (keyword.first.keyword_kind == CompilerKit::KeywordKind::eKeywordKindVariableAssign)
+ {
+ valueOfVar = text.substr(text.find("=") + 1);
+ }
+ else if (keyword.first.keyword_kind == CompilerKit::KeywordKind::eKeywordKindEndInstr)
+ {
+ break;
+ }
+
+ while (valueOfVar.find(";") != std::string::npos &&
+ keyword.first.keyword_kind != CompilerKit::KeywordKind::eKeywordKindEndInstr)
+ {
+ valueOfVar.erase(valueOfVar.find(";"));
+ }
+
+ std::string varName = text;
+
+ if (keyword.first.keyword_kind == CompilerKit::KeywordKind::eKeywordKindVariableInc)
+ {
+ varName.erase(varName.find("+="));
+ }
+ else if (keyword.first.keyword_kind == CompilerKit::KeywordKind::eKeywordKindVariableDec)
+ {
+ varName.erase(varName.find("-="));
+ }
+ else if (keyword.first.keyword_kind == CompilerKit::KeywordKind::eKeywordKindVariableAssign)
+ {
+ varName.erase(varName.find("="));
+ }
+ else if (keyword.first.keyword_kind == CompilerKit::KeywordKind::eKeywordKindEndInstr)
+ {
+ varName.erase(varName.find(";"));
+ }
+
+ static bool typeFound = false;
+
+ for (auto& keyword : kKeywords)
+ {
+ if (keyword.keyword_kind == CompilerKit::eKeywordKindType)
+ {
+ if (text.find(keyword.keyword_name) != std::string::npos)
+ {
+ if (text[text.find(keyword.keyword_name)] == ' ')
+ {
+ typeFound = false;
+ continue;
+ }
+
+ typeFound = true;
+ }
+ }
+ }
+
+ std::string instr = "mov ";
+
+ if (typeFound)
+ {
+ if (keyword.first.keyword_kind == CompilerKit::KeywordKind::eKeywordKindVariableInc)
+ {
+ detail::print_error("Can't increment variable when it's being created.", file);
+ }
+ else if (keyword.first.keyword_kind == CompilerKit::KeywordKind::eKeywordKindVariableDec)
+ {
+ detail::print_error("Can't decrement variable when it's being created.", file);
+ }
+
+ if (kRegisterMap.size() > cRegisters.size())
+ {
+ ++kLevelFunction;
+ }
+
+ while (varName.find(" ") != std::string::npos)
+ {
+ varName.erase(varName.find(" "), 1);
+ }
+
+ while (varName.find("\t") != std::string::npos)
+ {
+ varName.erase(varName.find("\t"), 1);
+ }
+
+ for (size_t i = 0; !isalnum(valueOfVar[i]); i++)
+ {
+ if (i > valueOfVar.size())
+ break;
+
+ valueOfVar.erase(i, 1);
+ }
+
+ constexpr auto cTrueVal = "true";
+ constexpr auto cFalseVal = "false";
+
+ if (valueOfVar == cTrueVal)
+ {
+ valueOfVar = "1";
+ }
+ else if (valueOfVar == cFalseVal)
+ {
+ valueOfVar = "0";
+ }
+
+ std::size_t indexRight = 0UL;
+
+ for (auto pairRight : kRegisterMap)
+ {
+ ++indexRight;
+
+ if (pairRight != valueOfVar)
+ {
+ syntax_tree.fUserValue = instr + cRegisters[kRegisterMap.size() - 1] + ", " + valueOfVar + "\n";
+ goto done;
+ }
+
+ syntax_tree.fUserValue = instr + cRegisters[kRegisterMap.size() - 1] + ", " + valueOfVar + "\n";
+ break;
+ }
+
+ if (((int)indexRight - 1) < 0)
+ {
+ syntax_tree.fUserValue = instr + cRegisters[kRegisterMap.size()] + ", " + valueOfVar + "\n";
+ }
+
+ done:
+ kRegisterMap.push_back(varName);
+ }
+ else
+ {
+ if (kKeywords[keyword.second - 1].keyword_kind == CompilerKit::eKeywordKindType ||
+ kKeywords[keyword.second - 1].keyword_kind == CompilerKit::eKeywordKindTypePtr)
+ {
+ syntax_tree.fUserValue = "\n";
+ continue;
+ }
+
+ if (keyword.first.keyword_kind == CompilerKit::KeywordKind::eKeywordKindEndInstr)
+ {
+ syntax_tree.fUserValue = "\n";
+ continue;
+ }
+
+ if (keyword.first.keyword_kind == CompilerKit::KeywordKind::eKeywordKindVariableInc)
+ {
+ instr = "add ";
+ }
+ else if (keyword.first.keyword_kind == CompilerKit::KeywordKind::eKeywordKindVariableDec)
+ {
+ instr = "sub ";
+ }
+
+ std::string varErrCpy = varName;
+
+ while (varName.find(" ") != std::string::npos)
+ {
+ varName.erase(varName.find(" "), 1);
+ }
+
+ while (varName.find("\t") != std::string::npos)
+ {
+ varName.erase(varName.find("\t"), 1);
+ }
+
+ std::size_t indxReg = 0UL;
+
+ for (size_t i = 0; !isalnum(valueOfVar[i]); i++)
+ {
+ if (i > valueOfVar.size())
+ break;
+
+ valueOfVar.erase(i, 1);
+ }
+
+ while (valueOfVar.find(" ") != std::string::npos)
+ {
+ valueOfVar.erase(valueOfVar.find(" "), 1);
+ }
+
+ while (valueOfVar.find("\t") != std::string::npos)
+ {
+ valueOfVar.erase(valueOfVar.find("\t"), 1);
+ }
+
+ constexpr auto cTrueVal = "true";
+ constexpr auto cFalseVal = "false";
+
+ /// interpet boolean values, since we're on C++
+
+ if (valueOfVar == cTrueVal)
+ {
+ valueOfVar = "1";
+ }
+ else if (valueOfVar == cFalseVal)
+ {
+ valueOfVar = "0";
+ }
+
+ for (auto pair : kRegisterMap)
+ {
+ ++indxReg;
+
+ if (pair != varName)
+ continue;
+
+ std::size_t indexRight = 0ul;
+
+ for (auto pairRight : kRegisterMap)
+ {
+ ++indexRight;
+
+ if (pairRight != varName)
+ {
+ syntax_tree.fUserValue = instr + cRegisters[kRegisterMap.size()] + ", " + valueOfVar + "\n";
+ continue;
+ }
+
+ syntax_tree.fUserValue = instr + cRegisters[indexRight - 1] + ", " + valueOfVar + "\n";
+ break;
+ }
+
+ break;
+ }
+
+ if (syntax_tree.fUserValue.empty())
+ {
+ detail::print_error("Variable not declared: " + varErrCpy, file);
+ }
+ }
+
+ break;
+ }
+ case CompilerKit::KeywordKind::eKeywordKindReturn: {
+ auto pos = text.find("return") + strlen("return") + 1;
+ std::string subText = text.substr(pos);
+ subText = subText.erase(subText.find(";"));
+ size_t indxReg = 0UL;
+
+ if (subText[0] != '\"' &&
+ subText[0] != '\'')
+ {
+ if (!isdigit(subText[0]))
+ {
+ for (auto pair : kRegisterMap)
+ {
+ ++indxReg;
+
+ if (pair != subText)
+ continue;
+
+ syntax_tree.fUserValue = "mov rax, " + cRegisters[indxReg] + "\r\nret\n";
+ break;
+ }
+
+ if (syntax_tree.fUserValue.empty())
+ {
+ detail::print_error("Variable not declared: " + subText, file);
+ }
+ }
+ else
+ {
+ syntax_tree.fUserValue = "mov rax, " + subText + "\r\nret\n";
+ }
+ }
+ else
+ {
+ syntax_tree.fUserValue = "mov rcx, " + subText + "\n";
+ syntax_tree.fUserValue = "mov rax, rcx\r\nret\n";
+ }
+
+ break;
+ }
+ default:
+ break;
+ }
+
+ syntax_tree.fUserData = keyword.first;
+ kState.fSyntaxTree->fLeafList.emplace_back(syntax_tree);
+ }
+
+_MpccOkay:
+ return true;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * @brief C To Assembly mount-point.
+ */
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+class AssemblyCPlusPlusInterface final : public CompilerKit::AssemblyInterface
+{
+public:
+ explicit AssemblyCPlusPlusInterface() = default;
+ ~AssemblyCPlusPlusInterface() override = default;
+
+ MPCC_COPY_DEFAULT(AssemblyCPlusPlusInterface);
+
+ [[maybe_unused]]
+ static Int32 Arch() noexcept
+ {
+ return CompilerKit::AssemblyFactory::kArchAMD64;
+ }
+
+ Int32 CompileToFormat(std::string& src, Int32 arch) override
+ {
+ if (arch != AssemblyCPlusPlusInterface::Arch())
+ return -1;
+
+ if (kCompilerBackend == nullptr)
+ return -1;
+
+ /* @brief copy contents wihtout extension */
+ std::string src_file = src.data();
+ std::ifstream src_fp = std::ifstream(src_file, std::ios::in);
+
+ const char* cExts[] = kAsmFileExts;
+
+ std::string dest = src_file;
+ dest += cExts[4];
+
+ if (dest.empty())
+ {
+ dest = "CXX-NDK-";
+
+ std::random_device rd;
+ auto seed_data = std::array<int, std::mt19937::state_size>{};
+
+ std::generate(std::begin(seed_data), std::end(seed_data), std::ref(rd));
+
+ std::seed_seq seq(std::begin(seed_data), std::end(seed_data));
+ std::mt19937 generator(seq);
+
+ auto gen = uuids::uuid_random_generator(generator);
+
+ auto id = gen();
+ dest += uuids::to_string(id);
+ }
+
+ kState.fOutputAssembly = std::make_unique<std::ofstream>(dest);
+
+ auto fmt = CompilerKit::current_date();
+
+ (*kState.fOutputAssembly) << "; Path: " << src_file << "\n";
+ (*kState.fOutputAssembly)
+ << "; Language: AMD64 assembly. (Generated from C++)\n";
+ (*kState.fOutputAssembly) << "; Date: " << fmt << "\n";
+ (*kState.fOutputAssembly) << "#bits 64\n#org 0x1000000"
+ << "\n";
+
+ CompilerKit::SyntaxLeafList syntax;
+
+ kState.fSyntaxTreeList.emplace_back(syntax);
+ kState.fSyntaxTree =
+ &kState.fSyntaxTreeList[kState.fSyntaxTreeList.size() - 1];
+
+ std::string source;
+
+ while (std::getline(src_fp, source))
+ {
+ // Compile into an object file.
+ kCompilerBackend->Compile(source.c_str(), src.c_str());
+ }
+
+ for (auto& ast : kState.fSyntaxTree->fLeafList)
+ {
+ (*kState.fOutputAssembly) << ast.fUserValue;
+ }
+
+ if (kAcceptableErrors > 0)
+ return -1;
+
+ return kOk;
+ }
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static void cxx_print_help()
+{
+ kSplashCxx();
+ kPrintF("%s", "No help available, see:\n");
+ kPrintF("%s", "www.zeta.com/developer/cplusplus\n");
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+#define kExtListCxx \
+ { \
+ ".cpp", ".cxx", ".cc", ".c++", ".cp" \
+ }
+
+NDK_MODULE(CompilerCPlusPlus)
+{
+ bool skip = false;
+
+ kKeywords.push_back({.keyword_name = "if", .keyword_kind = CompilerKit::eKeywordKindIf});
+ kKeywords.push_back({.keyword_name = "else", .keyword_kind = CompilerKit::eKeywordKindElse});
+ kKeywords.push_back({.keyword_name = "else if", .keyword_kind = CompilerKit::eKeywordKindElseIf});
+
+ kKeywords.push_back({.keyword_name = "class", .keyword_kind = CompilerKit::eKeywordKindClass});
+ kKeywords.push_back({.keyword_name = "struct", .keyword_kind = CompilerKit::eKeywordKindClass});
+ kKeywords.push_back({.keyword_name = "namespace", .keyword_kind = CompilerKit::eKeywordKindNamespace});
+ kKeywords.push_back({.keyword_name = "typedef", .keyword_kind = CompilerKit::eKeywordKindTypedef});
+ kKeywords.push_back({.keyword_name = "using", .keyword_kind = CompilerKit::eKeywordKindTypedef});
+ kKeywords.push_back({.keyword_name = "{", .keyword_kind = CompilerKit::eKeywordKindBodyStart});
+ kKeywords.push_back({.keyword_name = "}", .keyword_kind = CompilerKit::eKeywordKindBodyEnd});
+ kKeywords.push_back({.keyword_name = "auto", .keyword_kind = CompilerKit::eKeywordKindVariable});
+ kKeywords.push_back({.keyword_name = "int", .keyword_kind = CompilerKit::eKeywordKindType});
+ kKeywords.push_back({.keyword_name = "bool", .keyword_kind = CompilerKit::eKeywordKindType});
+ kKeywords.push_back({.keyword_name = "unsigned", .keyword_kind = CompilerKit::eKeywordKindType});
+ kKeywords.push_back({.keyword_name = "short", .keyword_kind = CompilerKit::eKeywordKindType});
+ kKeywords.push_back({.keyword_name = "char", .keyword_kind = CompilerKit::eKeywordKindType});
+ kKeywords.push_back({.keyword_name = "long", .keyword_kind = CompilerKit::eKeywordKindType});
+ kKeywords.push_back({.keyword_name = "float", .keyword_kind = CompilerKit::eKeywordKindType});
+ kKeywords.push_back({.keyword_name = "double", .keyword_kind = CompilerKit::eKeywordKindType});
+ kKeywords.push_back({.keyword_name = "void", .keyword_kind = CompilerKit::eKeywordKindType});
+
+ kKeywords.push_back({.keyword_name = "auto*", .keyword_kind = CompilerKit::eKeywordKindVariablePtr});
+ kKeywords.push_back({.keyword_name = "int*", .keyword_kind = CompilerKit::eKeywordKindTypePtr});
+ kKeywords.push_back({.keyword_name = "bool*", .keyword_kind = CompilerKit::eKeywordKindTypePtr});
+ kKeywords.push_back({.keyword_name = "unsigned*", .keyword_kind = CompilerKit::eKeywordKindTypePtr});
+ kKeywords.push_back({.keyword_name = "short*", .keyword_kind = CompilerKit::eKeywordKindTypePtr});
+ kKeywords.push_back({.keyword_name = "char*", .keyword_kind = CompilerKit::eKeywordKindTypePtr});
+ kKeywords.push_back({.keyword_name = "long*", .keyword_kind = CompilerKit::eKeywordKindTypePtr});
+ kKeywords.push_back({.keyword_name = "float*", .keyword_kind = CompilerKit::eKeywordKindTypePtr});
+ kKeywords.push_back({.keyword_name = "double*", .keyword_kind = CompilerKit::eKeywordKindTypePtr});
+ kKeywords.push_back({.keyword_name = "void*", .keyword_kind = CompilerKit::eKeywordKindTypePtr});
+
+ kKeywords.push_back({.keyword_name = "(", .keyword_kind = CompilerKit::eKeywordKindFunctionStart});
+ kKeywords.push_back({.keyword_name = ")", .keyword_kind = CompilerKit::eKeywordKindFunctionEnd});
+ kKeywords.push_back({.keyword_name = "=", .keyword_kind = CompilerKit::eKeywordKindVariableAssign});
+ kKeywords.push_back({.keyword_name = "+=", .keyword_kind = CompilerKit::eKeywordKindVariableInc});
+ kKeywords.push_back({.keyword_name = "-=", .keyword_kind = CompilerKit::eKeywordKindVariableDec});
+ kKeywords.push_back({.keyword_name = "const", .keyword_kind = CompilerKit::eKeywordKindConstant});
+ kKeywords.push_back({.keyword_name = "*", .keyword_kind = CompilerKit::eKeywordKindPtr});
+ kKeywords.push_back({.keyword_name = "->", .keyword_kind = CompilerKit::eKeywordKindPtrAccess});
+ kKeywords.push_back({.keyword_name = ".", .keyword_kind = CompilerKit::eKeywordKindAccess});
+ kKeywords.push_back({.keyword_name = ",", .keyword_kind = CompilerKit::eKeywordKindArgSeparator});
+ kKeywords.push_back({.keyword_name = ";", .keyword_kind = CompilerKit::eKeywordKindEndInstr});
+ kKeywords.push_back({.keyword_name = ":", .keyword_kind = CompilerKit::eKeywordKindSpecifier});
+ kKeywords.push_back({.keyword_name = "public:", .keyword_kind = CompilerKit::eKeywordKindSpecifier});
+ kKeywords.push_back({.keyword_name = "private:", .keyword_kind = CompilerKit::eKeywordKindSpecifier});
+ kKeywords.push_back({.keyword_name = "protected:", .keyword_kind = CompilerKit::eKeywordKindSpecifier});
+ kKeywords.push_back({.keyword_name = "final", .keyword_kind = CompilerKit::eKeywordKindSpecifier});
+ kKeywords.push_back({.keyword_name = "return", .keyword_kind = CompilerKit::eKeywordKindReturn});
+ kKeywords.push_back({.keyword_name = "/*", .keyword_kind = CompilerKit::eKeywordKindCommentMultiLineStart});
+ kKeywords.push_back({.keyword_name = "*/", .keyword_kind = CompilerKit::eKeywordKindCommentMultiLineStart});
+ kKeywords.push_back({.keyword_name = "//", .keyword_kind = CompilerKit::eKeywordKindCommentInline});
+ kKeywords.push_back({.keyword_name = "==", .keyword_kind = CompilerKit::eKeywordKindEq});
+ kKeywords.push_back({.keyword_name = "!=", .keyword_kind = CompilerKit::eKeywordKindNotEq});
+ kKeywords.push_back({.keyword_name = ">=", .keyword_kind = CompilerKit::eKeywordKindGreaterEq});
+ kKeywords.push_back({.keyword_name = "<=", .keyword_kind = CompilerKit::eKeywordKindLessEq});
+
+ kFactory.Mount(new AssemblyCPlusPlusInterface());
+ kCompilerBackend = new CompilerBackendCPlusPlus();
+
+ for (auto index = 1UL; index < argc; ++index)
+ {
+ if (argv[index][0] == '/')
+ {
+ if (skip)
+ {
+ skip = false;
+ continue;
+ }
+
+ if (strcmp(argv[index], "/v") == 0 ||
+ strcmp(argv[index], "/version") == 0)
+ {
+ kSplashCxx();
+ return kOk;
+ }
+
+ if (strcmp(argv[index], "/verbose") == 0)
+ {
+ kState.fVerbose = true;
+
+ continue;
+ }
+
+ if (strcmp(argv[index], "/h") == 0 || strcmp(argv[index], "/help") == 0)
+ {
+ cxx_print_help();
+
+ return kOk;
+ }
+
+ if (strcmp(argv[index], "/dialect") == 0)
+ {
+ if (kCompilerBackend)
+ std::cout << kCompilerBackend->Language() << "\n";
+
+ return kOk;
+ }
+
+ if (strcmp(argv[index], "/max-errors") == 0)
+ {
+ try
+ {
+ kErrorLimit = std::strtol(argv[index + 1], nullptr, 10);
+ }
+ // catch anything here
+ catch (...)
+ {
+ kErrorLimit = 0;
+ }
+
+ skip = true;
+
+ continue;
+ }
+
+ std::string err = "Unknown option: ";
+ err += argv[index];
+
+ detail::print_error(err, "cplusplus");
+
+ continue;
+ }
+
+ kFileList.emplace_back(argv[index]);
+
+ std::string argv_i = argv[index];
+
+ std::vector exts = kExtListCxx;
+ bool found = false;
+
+ for (std::string ext : exts)
+ {
+ if (argv_i.find(ext) != std::string::npos)
+ {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ {
+ if (kState.fVerbose)
+ {
+ detail::print_error(argv_i + " is not a valid C++ source.\n", "cplusplus");
+ }
+
+ return 1;
+ }
+
+ if (kFactory.Compile(argv_i, kMachine) != kOk)
+ return -1;
+ }
+
+ return kOk;
+}
+
+// Last rev 8-1-24
+//
diff --git a/Sources/elf2ae.cc b/NDKKit/Sources/elf2ae.cxx
index 77568dc..451c706 100644
--- a/Sources/elf2ae.cc
+++ b/NDKKit/Sources/elf2ae.cxx
@@ -1,12 +1,12 @@
/* -------------------------------------------
- Copyright Mahrouss Logic
+ Copyright ZKA Technologies
------------------------------------------- */
-#include <Headers/ParserKit.hpp>
-#include <Headers/StdKit/AE.hpp>
-#include <Headers/StdKit/PEF.hpp>
+#include <NDKKit/Parser.hpp>
+#include <NDKKit/NFC/AE.hpp>
+#include <NDKKit/NFC/PEF.hpp>
#include <filesystem>
#include <fstream>
#include <iostream>
@@ -19,4 +19,4 @@
/////////////////////////////////////////////////////////////////////////////////////////
-MPCC_MODULE(NewOSELFToAE) { return 0; }
+NDK_MODULE(NewOSELFToAE) { return 0; }
diff --git a/NDKKit/Sources/i64asm.cxx b/NDKKit/Sources/i64asm.cxx
new file mode 100644
index 0000000..ed77988
--- /dev/null
+++ b/NDKKit/Sources/i64asm.cxx
@@ -0,0 +1,1484 @@
+/* -------------------------------------------
+
+ Copyright ZKA Technologies
+
+------------------------------------------- */
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+/// @file i64asm.cxx
+/// @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.
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+/// bugs: 0
+
+/// feature request: 1
+/// Encode registers in mov, add, xor...
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+#define __ASM_NEED_AMD64__ 1
+
+#define kAssemblerPragmaSymStr "#"
+#define kAssemblerPragmaSym '#'
+
+#include <NDKKit/AsmKit/CPU/amd64.hpp>
+#include <NDKKit/Parser.hpp>
+#include <NDKKit/NFC/AE.hpp>
+#include <NDKKit/NFC/PEF.hpp>
+#include <algorithm>
+#include <cstdlib>
+#include <filesystem>
+#include <fstream>
+#include <iostream>
+#include <memory>
+#include <vector>
+
+/////////////////////
+
+// ANSI ESCAPE CODES
+
+/////////////////////
+
+#define kBlank "\e[0;30m"
+#define kRed "\e[0;31m"
+#define kWhite "\e[0;97m"
+#define kYellow "\e[0;33m"
+
+#define kStdOut (std::cout << kWhite)
+#define kStdErr (std::cout << kRed)
+
+static char kOutputArch = CompilerKit::kPefArchAMD64;
+static Boolean kOutputAsBinary = false;
+
+static UInt32 kErrorLimit = 10;
+static UInt32 kAcceptableErrors = 0;
+
+constexpr auto cAMD64IPAlignment = 0x4U;
+
+static std::size_t kCounter = 1UL;
+
+static std::uintptr_t kOrigin = kPefBaseOrigin;
+static std::vector<std::pair<std::string, std::uintptr_t>> kOriginLabel;
+
+/// @brief keep it simple by default.
+static std::int32_t kRegisterBitWidth = 16U;
+
+static bool kVerbose = false;
+
+static std::vector<i64_byte_t> kAppBytes;
+
+static CompilerKit::AERecordHeader kCurrentRecord{
+ .fName = "", .fKind = CompilerKit::kPefCode, .fSize = 0, .fOffset = 0};
+
+static std::vector<CompilerKit::AERecordHeader> kRecords;
+static std::vector<std::string> kDefinedSymbols;
+static std::vector<std::string> kUndefinedSymbols;
+
+static const std::string kUndefinedSymbol = ":UndefinedSymbol:";
+static const std::string kRelocSymbol = ":RuntimeSymbol:";
+
+// \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);
+
+ 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);
+
+ ++kAcceptableErrors;
+ }
+
+ 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;
+ }
+
+ kStdOut << kYellow << "[ i64asm ] " << kWhite << reason << kBlank
+ << std::endl;
+ }
+} // namespace detail
+
+#include <asmutils.hxx>
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+// @brief AMD64 assembler entrypoint, the program/module starts here.
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+NDK_MODULE(NewOSAssemblerAMD64)
+{
+ //////////////// 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"};
+
+ for (i64_hword_t i = 0; i < kJumpLimit; i++)
+ {
+ CpuOpcodeAMD64 code{
+ .fName = opcodes_jump[i],
+ .fOpcode = static_cast<i64_hword_t>(kAsmJumpOpcode + i)};
+ kOpcodesAMD64.push_back(code);
+ }
+
+ CpuOpcodeAMD64 code{.fName = "jcxz", .fOpcode = 0xE3};
+ kOpcodesAMD64.push_back(code);
+
+ for (i64_hword_t i = kJumpLimitStandard; i < kJumpLimitStandardLimit; i++)
+ {
+ CpuOpcodeAMD64 code{.fName = "jmp", .fOpcode = i};
+ kOpcodesAMD64.push_back(code);
+ }
+
+ CpuOpcodeAMD64 lahf{.fName = "lahf", .fOpcode = 0x9F};
+ kOpcodesAMD64.push_back(lahf);
+
+ CpuOpcodeAMD64 lds{.fName = "lds", .fOpcode = 0xC5};
+ kOpcodesAMD64.push_back(lds);
+
+ CpuOpcodeAMD64 lea{.fName = "lea", .fOpcode = 0x8D};
+ kOpcodesAMD64.push_back(lea);
+
+ CpuOpcodeAMD64 nop{.fName = "nop", .fOpcode = 0x90};
+ kOpcodesAMD64.push_back(nop);
+
+ //////////////// CPU OPCODES END ////////////////
+
+ 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 Driver.\ni64asm: v1.10\ni64asm: Copyright "
+ "(c) ZKA Technologies.\n";
+ return 0;
+ }
+ else if (strcmp(argv[i], "/h") == 0)
+ {
+ kStdOut << "i64asm: AMD64 Assembler Driver.\ni64asm: Copyright (c) 2024 "
+ "ZKA Technologies.\n";
+ kStdOut << "/version: Print program version.\n";
+ kStdOut << "/verbose: Print verbose output.\n";
+ kStdOut << "/binary: Output as flat binary.\n";
+
+ 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;
+ }
+
+ if (!std::filesystem::exists(argv[i]))
+ {
+ kStdOut << "i64asm: can't open: " << argv[i] << std::endl;
+ goto asm_fail_exit;
+ }
+
+ std::string object_output(argv[i]);
+
+ for (auto& ext : kAsmFileExts)
+ {
+ if (object_output.find(ext) != std::string::npos)
+ {
+ object_output.erase(object_output.find(ext), std::strlen(ext));
+ }
+ }
+
+ object_output += kOutputAsBinary ? kBinaryFileExt : kObjectFileExt;
+
+ std::ifstream file_ptr(argv[i]);
+ std::ofstream file_ptr_out(object_output, std::ofstream::binary);
+
+ if (file_ptr_out.bad())
+ {
+ if (kVerbose)
+ {
+ kStdOut << "i64asm: error: " << strerror(errno) << "\n";
+ }
+ }
+
+ std::string line;
+
+ CompilerKit::AEHeader hdr{0};
+
+ memset(hdr.fPad, kAEInvalidOpcode, kAEPad);
+
+ hdr.fMagic[0] = kAEMag0;
+ hdr.fMagic[1] = kAEMag1;
+ hdr.fSize = sizeof(CompilerKit::AEHeader);
+ hdr.fArch = kOutputArch;
+
+ /////////////////////////////////////////////////////////////////////////////////////////
+
+ // COMPILATION LOOP
+
+ /////////////////////////////////////////////////////////////////////////////////////////
+
+ CompilerKit::EncoderAMD64 asm64;
+
+ 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");
+ }
+
+ try
+ {
+ std::filesystem::remove(object_output);
+ }
+ catch (...)
+ {
+ }
+
+ goto asm_fail_exit;
+ }
+ }
+
+ if (!kOutputAsBinary)
+ {
+ if (kVerbose)
+ {
+ kStdOut << "i64asm: Writing object file...\n";
+ }
+
+ // this is the final step, write everything to the file.
+
+ auto pos = file_ptr_out.tellp();
+
+ hdr.fCount = kRecords.size() + kUndefinedSymbols.size();
+
+ file_ptr_out << hdr;
+
+ if (kRecords.empty())
+ {
+ kStdErr << "i64asm: At least one record is needed to write an object "
+ "file.\ni64asm: Make one using `export .code64 foo_bar`.\n";
+
+ std::filesystem::remove(object_output);
+ return -1;
+ }
+
+ kRecords[kRecords.size() - 1].fSize = kAppBytes.size();
+
+ std::size_t record_count = 0UL;
+
+ for (auto& rec : kRecords)
+ {
+ if (kVerbose)
+ kStdOut << "i64asm: Wrote record " << rec.fName << " to file...\n";
+
+ rec.fFlags |= CompilerKit::kKindRelocationAtRuntime;
+ rec.fOffset = record_count;
+ ++record_count;
+
+ file_ptr_out << rec;
+ }
+
+ // increment once again, so that we won't lie about the kUndefinedSymbols.
+ ++record_count;
+
+ for (auto& sym : kUndefinedSymbols)
+ {
+ CompilerKit::AERecordHeader _record_hdr{0};
+
+ if (kVerbose)
+ kStdOut << "i64asm: Wrote symbol " << sym << " to file...\n";
+
+ _record_hdr.fKind = kAEInvalidOpcode;
+ _record_hdr.fSize = sym.size();
+ _record_hdr.fOffset = record_count;
+
+ ++record_count;
+
+ memset(_record_hdr.fPad, kAEInvalidOpcode, kAEPad);
+ memcpy(_record_hdr.fName, sym.c_str(), sym.size());
+
+ file_ptr_out << _record_hdr;
+
+ ++kCounter;
+ }
+
+ auto pos_end = file_ptr_out.tellp();
+
+ file_ptr_out.seekp(pos);
+
+ hdr.fStartCode = pos_end;
+ hdr.fCodeSize = kAppBytes.size();
+
+ file_ptr_out << hdr;
+
+ file_ptr_out.seekp(pos_end);
+ }
+ else
+ {
+ if (kVerbose)
+ {
+ kStdOut << "i64asm: Write raw binary...\n";
+ }
+ }
+
+ // byte from byte, we write this.
+ for (auto& byte : kAppBytes)
+ {
+ if (byte == 0)
+ continue;
+
+ if (byte == 0xFF)
+ {
+ byte = 0;
+ }
+
+ file_ptr_out << reinterpret_cast<const char*>(&byte)[0];
+ }
+
+ if (kVerbose)
+ kStdOut << "i64asm: Wrote file with program in it.\n";
+
+ file_ptr_out.flush();
+ file_ptr_out.close();
+
+ if (kVerbose)
+ kStdOut << "i64asm: Exit succeeded.\n";
+
+ return 0;
+ }
+
+asm_fail_exit:
+
+ if (kVerbose)
+ kStdOut << "i64asm: Exit failed.\n";
+
+ return -1;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+// @brief Check for attributes
+// returns true if any was found.
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+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 (CompilerKit::find_word(line, "import"))
+ {
+ if (kOutputAsBinary)
+ {
+ detail::print_error("Invalid directive in flat binary mode.", "i64asm");
+ throw std::runtime_error("invalid_import_bin");
+ }
+
+ auto name = line.substr(line.find("import") + strlen("import") + 1);
+
+ if (name.size() == 0)
+ {
+ detail::print_error("Invalid import", "power-as");
+ throw std::runtime_error("invalid_import");
+ }
+
+ std::string result = std::to_string(name.size());
+ result += kUndefinedSymbol;
+
+ // mangle this
+ for (char& j : name)
+ {
+ if (j == ' ' || j == ',')
+ j = '$';
+ }
+
+ result += name;
+
+ if (name.find(".code64") != std::string::npos)
+ {
+ // data is treated as code.
+ kCurrentRecord.fKind = CompilerKit::kPefCode;
+ }
+ else if (name.find(".data64") != std::string::npos)
+ {
+ // no code will be executed from here.
+ kCurrentRecord.fKind = CompilerKit::kPefData;
+ }
+ else if (name.find(".zero64") != 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.
+
+ if (name == kPefStart)
+ {
+ kCurrentRecord.fKind = CompilerKit::kPefCode;
+ }
+
+ // now we can tell the code size of the previous kCurrentRecord.
+
+ if (!kRecords.empty())
+ kRecords[kRecords.size() - 1].fSize = kAppBytes.size();
+
+ memset(kCurrentRecord.fName, 0, kAESymbolLen);
+ memcpy(kCurrentRecord.fName, result.c_str(), result.size());
+
+ ++kCounter;
+
+ memset(kCurrentRecord.fPad, kAEInvalidOpcode, kAEPad);
+
+ kRecords.emplace_back(kCurrentRecord);
+
+ 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 .code64, .data64 and
+ // .zero64.
+ else if (CompilerKit::find_word(line, "export"))
+ {
+ if (kOutputAsBinary)
+ {
+ detail::print_error("Invalid directive in flat binary mode.", "i64asm");
+ throw std::runtime_error("invalid_export_bin");
+ }
+
+ auto name = line.substr(line.find("export") + strlen("export") + 1);
+
+ std::string name_copy = name;
+
+ for (char& j : name)
+ {
+ if (j == ' ')
+ j = '$';
+ }
+
+ if (std::find(kDefinedSymbols.begin(), kDefinedSymbols.end(), name) !=
+ kDefinedSymbols.end())
+ {
+ detail::print_error("Symbol already defined.", "i64asm");
+ throw std::runtime_error("invalid_export_bin");
+ }
+
+ kDefinedSymbols.push_back(name);
+
+ if (name.find(".code64") != std::string::npos)
+ {
+ // data is treated as code.
+
+ name_copy.erase(name_copy.find(".code64"), strlen(".code64"));
+ kCurrentRecord.fKind = CompilerKit::kPefCode;
+ }
+ else if (name.find(".data64") != std::string::npos)
+ {
+ // no code will be executed from here.
+
+ name_copy.erase(name_copy.find(".data64"), strlen(".data64"));
+ kCurrentRecord.fKind = CompilerKit::kPefData;
+ }
+ else if (name.find(".zero64") != std::string::npos)
+ {
+ // this is a bss section.
+
+ name_copy.erase(name_copy.find(".zero64"), strlen(".zero64"));
+ kCurrentRecord.fKind = CompilerKit::kPefZero;
+ }
+
+ // this is a special case for the start stub.
+ // we want this so that ld can find it.
+
+ if (name == kPefStart)
+ {
+ kCurrentRecord.fKind = CompilerKit::kPefCode;
+ }
+
+ while (name_copy.find(" ") != std::string::npos)
+ name_copy.erase(name_copy.find(" "), 1);
+
+ kOriginLabel.push_back(std::make_pair(name_copy, kOrigin));
+ ++kOrigin;
+
+ // now we can tell the code size of the previous kCurrentRecord.
+
+ if (!kRecords.empty())
+ kRecords[kRecords.size() - 1].fSize = kAppBytes.size();
+
+ memset(kCurrentRecord.fName, 0, kAESymbolLen);
+ memcpy(kCurrentRecord.fName, name.c_str(), name.size());
+
+ ++kCounter;
+
+ memset(kCurrentRecord.fPad, kAEInvalidOpcode, kAEPad);
+
+ kRecords.emplace_back(kCurrentRecord);
+
+ return true;
+ }
+
+ 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 == '.') || (c == '#'));
+ }
+
+ bool is_valid(const std::string& str)
+ {
+ return std::find_if(str.begin(), str.end(), is_not_alnum_space) == str.end();
+ }
+} // namespace detail::algorithm
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+// @brief Check for line (syntax check)
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+std::string CompilerKit::EncoderAMD64::CheckLine(std::string& line,
+ const std::string& file)
+{
+ std::string err_str;
+
+ if (line.empty() || CompilerKit::find_word(line, "import") ||
+ CompilerKit::find_word(line, "export") ||
+ CompilerKit::find_word(line, kAssemblerPragmaSymStr) ||
+ CompilerKit::find_word(line, ";") || line[0] == kAssemblerPragmaSym)
+ {
+ 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 valid characters.\nhere -> ";
+ err_str += line;
+ }
+ }
+
+ return err_str;
+ }
+
+ 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.
+
+ 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(','));
+
+ return err_str;
+ }
+ else
+ {
+ bool nothing_on_right = true;
+
+ if (line.find(',') + 1 > line.size())
+ {
+ err_str += "\nInstruction not complete, here -> ";
+ err_str += line;
+
+ 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;
+ }
+ }
+ }
+ for (auto& opcodeAMD64 : kOpcodesAMD64)
+ {
+ if (CompilerKit::find_word(line, opcodeAMD64.fName))
+ {
+ return err_str;
+ }
+ }
+
+ err_str += "\nUnrecognized instruction -> " + line;
+
+ return err_str;
+}
+
+bool CompilerKit::EncoderAMD64::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 = strtol(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(
+ strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16));
+
+ for (char& i : num.number)
+ {
+ if (i == 0)
+ i = 0xFF;
+
+ kAppBytes.push_back(i);
+ }
+
+ if (kVerbose)
+ {
+ kStdOut << "i64asm: Found a base 16 number here: "
+ << jump_label.substr(pos) << "\n";
+ }
+
+ return true;
+ }
+ case 'b': {
+ if (auto res = strtol(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(
+ strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2));
+
+ 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;
+
+ kAppBytes.push_back(i);
+ }
+
+ return true;
+ }
+ case 'o': {
+ if (auto res = strtol(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(
+ strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7));
+
+ 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;
+
+ kAppBytes.push_back(i);
+ }
+
+ return true;
+ }
+ default: {
+ break;
+ }
+ }
+
+ /* check for errno and stuff like that */
+ if (auto res = strtol(jump_label.substr(pos).c_str(), nullptr, 10); !res)
+ {
+ if (errno != 0)
+ {
+ return false;
+ }
+ }
+
+ CompilerKit::NumberCast64 num = CompilerKit::NumberCast64(
+ strtol(jump_label.substr(pos).c_str(), nullptr, 10));
+
+ for (char& i : num.number)
+ {
+ if (i == 0)
+ i = 0xFF;
+
+ kAppBytes.push_back(i);
+ }
+
+ if (kVerbose)
+ {
+ kStdOut << "i64asm: Found a base 10 number here: " << jump_label.substr(pos)
+ << "\n";
+ }
+
+ return true;
+}
+
+bool CompilerKit::EncoderAMD64::WriteNumber32(const std::size_t& pos,
+ std::string& jump_label)
+{
+ if (!isdigit(jump_label[pos]))
+ return false;
+
+ switch (jump_label[pos + 1])
+ {
+ case 'x': {
+ auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16);
+ res += kOrigin;
+
+ if (errno != 0)
+ {
+ return false;
+ }
+
+ CompilerKit::NumberCast32 num = CompilerKit::NumberCast32(res);
+
+ for (char& i : num.number)
+ {
+ if (i == 0)
+ i = 0xFF;
+
+ kAppBytes.push_back(i);
+ }
+
+ if (kVerbose)
+ {
+ kStdOut << "i64asm: Found a base 16 number here: "
+ << jump_label.substr(pos) << "\n";
+ }
+
+ return true;
+ }
+ case 'b': {
+ auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2);
+ res += kOrigin;
+
+ if (errno != 0)
+ {
+ return false;
+ }
+
+ CompilerKit::NumberCast32 num = CompilerKit::NumberCast32(res);
+
+ 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;
+
+ kAppBytes.push_back(i);
+ }
+
+ return true;
+ }
+ case 'o': {
+ auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7);
+ res += kOrigin;
+
+ if (errno != 0)
+ {
+ return false;
+ }
+
+ CompilerKit::NumberCast32 num = CompilerKit::NumberCast32(res);
+
+ 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;
+
+ kAppBytes.push_back(i);
+ }
+
+ return true;
+ }
+ default: {
+ break;
+ }
+ }
+
+ auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 10);
+ res += kOrigin;
+
+ if (errno != 0)
+ {
+ return false;
+ }
+
+ CompilerKit::NumberCast32 num = CompilerKit::NumberCast32(res);
+
+ for (char& i : num.number)
+ {
+ if (i == 0)
+ i = 0xFF;
+
+ kAppBytes.push_back(i);
+ }
+
+ if (kVerbose)
+ {
+ kStdOut << "i64asm: Found a base 10 number here: " << jump_label.substr(pos)
+ << "\n";
+ }
+
+ return true;
+}
+
+bool CompilerKit::EncoderAMD64::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 = strtol(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(
+ strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16));
+
+ for (char& i : num.number)
+ {
+ if (i == 0)
+ i = 0xFF;
+
+ kAppBytes.push_back(i);
+ }
+
+ if (kVerbose)
+ {
+ kStdOut << "i64asm: Found a base 16 number here: "
+ << jump_label.substr(pos) << "\n";
+ }
+
+ return true;
+ }
+ case 'b': {
+ if (auto res = strtol(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(
+ strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2));
+
+ 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;
+
+ kAppBytes.push_back(i);
+ }
+
+ return true;
+ }
+ case 'o': {
+ if (auto res = strtol(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(
+ strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7));
+
+ 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;
+
+ kAppBytes.push_back(i);
+ }
+
+ return true;
+ }
+ default: {
+ break;
+ }
+ }
+
+ /* check for errno and stuff like that */
+ if (auto res = strtol(jump_label.substr(pos).c_str(), nullptr, 10); !res)
+ {
+ if (errno != 0)
+ {
+ return false;
+ }
+ }
+
+ CompilerKit::NumberCast16 num = CompilerKit::NumberCast16(
+ strtol(jump_label.substr(pos).c_str(), nullptr, 10));
+
+ for (char& i : num.number)
+ {
+ if (i == 0)
+ i = 0xFF;
+
+ kAppBytes.push_back(i);
+ }
+
+ if (kVerbose)
+ {
+ kStdOut << "i64asm: Found a base 10 number here: " << jump_label.substr(pos)
+ << "\n";
+ }
+
+ return true;
+}
+
+bool CompilerKit::EncoderAMD64::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 = strtol(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(
+ strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16));
+
+ kAppBytes.push_back(num.number);
+
+ if (kVerbose)
+ {
+ kStdOut << "i64asm: Found a base 16 number here: "
+ << jump_label.substr(pos) << "\n";
+ }
+
+ return true;
+ }
+ case 'b': {
+ if (auto res = strtol(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(
+ strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2));
+
+ if (kVerbose)
+ {
+ kStdOut << "i64asm: Found a base 2 number here: "
+ << jump_label.substr(pos) << "\n";
+ }
+
+ kAppBytes.push_back(num.number);
+
+ return true;
+ }
+ case 'o': {
+ if (auto res = strtol(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(
+ strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7));
+
+ if (kVerbose)
+ {
+ kStdOut << "i64asm: Found a base 8 number here: "
+ << jump_label.substr(pos) << "\n";
+ }
+
+ kAppBytes.push_back(num.number);
+
+ return true;
+ }
+ default: {
+ break;
+ }
+ }
+
+ /* check for errno and stuff like that */
+ if (auto res = strtol(jump_label.substr(pos).c_str(), nullptr, 10); !res)
+ {
+ if (errno != 0)
+ {
+ return false;
+ }
+ }
+
+ CompilerKit::NumberCast8 num = CompilerKit::NumberCast8(
+ strtol(jump_label.substr(pos).c_str(), nullptr, 10));
+
+ kAppBytes.push_back(num.number);
+
+ if (kVerbose)
+ {
+ kStdOut << "i64asm: Found a base 10 number here: " << jump_label.substr(pos)
+ << "\n";
+ }
+
+ return true;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+// @brief Read and write an instruction to the output array.
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+bool CompilerKit::EncoderAMD64::WriteLine(std::string& line,
+ const std::string& file)
+{
+ if (CompilerKit::find_word(line, "export "))
+ return true;
+
+ struct RegMapAMD64
+ {
+ std::string fName;
+ i64_byte_t fModRM;
+ };
+
+ std::vector<RegMapAMD64> REGISTER_LIST{
+ {.fName = "ax", .fModRM = 0x0},
+ {.fName = "cx", .fModRM = 1},
+ {.fName = "dx", .fModRM = 0x2},
+ {.fName = "bx", .fModRM = 3},
+ {.fName = "sp", .fModRM = 0x4},
+ {.fName = "bp", .fModRM = 5},
+ {.fName = "si", .fModRM = 0x6},
+ {.fName = "di", .fModRM = 7},
+ {.fName = "r8", .fModRM = 8},
+ {.fName = "r13", .fModRM = 9},
+ {.fName = "r9", .fModRM = 10},
+ {.fName = "r14", .fModRM = 11},
+ {.fName = "r10", .fModRM = 12},
+ {.fName = "r15", .fModRM = 13},
+ {.fName = "r11", .fModRM = 14},
+ };
+
+ bool foundInstruction = false;
+
+ for (auto& opcodeAMD64 : kOpcodesAMD64)
+ {
+ // strict check here
+ if (CompilerKit::find_word(line, opcodeAMD64.fName) &&
+ detail::algorithm::is_valid(line))
+ {
+ foundInstruction = true;
+ std::string name(opcodeAMD64.fName);
+
+ /// Move instruction handler.
+ if (name.find("mov") != std::string::npos)
+ {
+ std::string substr = line.substr(line.find(name) + name.size());
+
+ uint64_t bits = kRegisterBitWidth;
+
+ if (substr.find(",") == std::string::npos)
+ {
+ detail::print_error("Syntax error.", "i64asm");
+ throw std::runtime_error("syntax_err");
+ }
+
+ bool onlyOneReg = true;
+
+ std::vector<RegMapAMD64> currentRegList;
+
+ for (auto& reg : REGISTER_LIST)
+ {
+ std::vector<char> regExt = {'e', 'r'};
+
+ for (auto& ext : regExt)
+ {
+ std::string registerName;
+
+ if (bits > 16)
+ registerName.push_back(ext);
+
+ registerName += reg.fName;
+
+ while (line.find(registerName) != std::string::npos)
+ {
+ line.erase(line.find(registerName), registerName.size());
+
+ if (bits == 16)
+ {
+ if (registerName[0] == 'r')
+ {
+ detail::print_error(
+ "invalid size for register, current bit width is: " +
+ std::to_string(kRegisterBitWidth),
+ file);
+ throw std::runtime_error("invalid_reg_size");
+ }
+ }
+
+ currentRegList.push_back(
+ {.fName = registerName, .fModRM = reg.fModRM});
+ }
+ }
+ }
+
+ if (currentRegList.size() > 1)
+ onlyOneReg = false;
+
+ bool hasRBasedRegs = false;
+
+ if (!onlyOneReg)
+ {
+ /// very tricky to understand.
+ /// but this checks for a r8 through r15 register.
+ if (currentRegList[0].fName[0] == 'r' ||
+ currentRegList[1].fName[0] == 'r')
+ {
+ if (isdigit(currentRegList[0].fName[1]) &&
+ isdigit(currentRegList[1].fName[1]))
+ {
+ kAppBytes.emplace_back(0x4d);
+ hasRBasedRegs = true;
+ }
+ else if (isdigit(currentRegList[0].fName[1]) ||
+ isdigit(currentRegList[1].fName[1]))
+ {
+ kAppBytes.emplace_back(0x4c);
+ hasRBasedRegs = true;
+ }
+ }
+ }
+
+ if (bits == 64 || bits == 32)
+ {
+ if (!hasRBasedRegs && bits >= 32)
+ {
+ kAppBytes.emplace_back(opcodeAMD64.fOpcode);
+ }
+
+ kAppBytes.emplace_back(0x89);
+ }
+ else if (bits == 16)
+ {
+ if (hasRBasedRegs)
+ {
+ detail::print_error(
+ "Invalid combination of operands and registers.", "i64asm");
+ throw std::runtime_error("comb_op_reg");
+ }
+
+ kAppBytes.emplace_back(0x66);
+ kAppBytes.emplace_back(0x89);
+ }
+
+ if (currentRegList[1].fName[0] == 'r' &&
+ currentRegList[0].fName[0] == 'e')
+ {
+ detail::print_error("Invalid combination of operands and registers.",
+ "i64asm");
+ throw std::runtime_error("comb_op_reg");
+ }
+
+ if (currentRegList[0].fName[0] == 'r' &&
+ currentRegList[1].fName[0] == 'e')
+ {
+ detail::print_error("Invalid combination of operands and registers.",
+ "i64asm");
+ throw std::runtime_error("comb_op_reg");
+ }
+
+ if (bits == 16)
+ {
+ if (currentRegList[0].fName[0] == 'r' ||
+ currentRegList[0].fName[0] == 'e')
+ {
+ detail::print_error("Invalid combination of operands and registers.",
+ "i64asm");
+ throw std::runtime_error("comb_op_reg");
+ }
+
+ if (currentRegList[1].fName[0] == 'r' ||
+ currentRegList[1].fName[0] == 'e')
+ {
+ detail::print_error("Invalid combination of operands and registers.",
+ "i64asm");
+ throw std::runtime_error("comb_op_reg");
+ }
+ }
+ else
+ {
+ if (currentRegList[0].fName[0] != 'r' ||
+ currentRegList[0].fName[0] == 'e')
+ {
+ detail::print_error("Invalid combination of operands and registers.",
+ "i64asm");
+ throw std::runtime_error("comb_op_reg");
+ }
+
+ if (currentRegList[1].fName[0] != 'r' ||
+ currentRegList[1].fName[0] == 'e')
+ {
+ detail::print_error("Invalid combination of operands and registers.",
+ "i64asm");
+ throw std::runtime_error("comb_op_reg");
+ }
+ }
+
+ /// encode register using the modrm encoding.
+
+ auto modrm = (0x3 << 6 | currentRegList[1].fModRM << 3 |
+ currentRegList[0].fModRM);
+
+ kAppBytes.emplace_back(modrm);
+
+ break;
+ }
+ else if (name == "int" || name == "into" || name == "intd")
+ {
+ kAppBytes.emplace_back(opcodeAMD64.fOpcode);
+ this->WriteNumber8(line.find(name) + name.size() + 1, line);
+
+ break;
+ }
+ else if (name == "jmp" || name == "call")
+ {
+ kAppBytes.emplace_back(opcodeAMD64.fOpcode);
+
+ if (!this->WriteNumber32(line.find(name) + name.size() + 1, line))
+ {
+ throw std::runtime_error("BUG: WriteNumber32");
+ }
+
+ break;
+ }
+ else
+ {
+ kAppBytes.emplace_back(opcodeAMD64.fOpcode);
+
+ break;
+ }
+ }
+ }
+
+ if (line[0] == kAssemblerPragmaSym)
+ {
+ if (foundInstruction)
+ {
+ detail::print_error("Syntax error: " + line, "i64asm");
+ throw std::runtime_error("syntax_err");
+ }
+
+ if (line.find("bits 64") != std::string::npos)
+ {
+ kRegisterBitWidth = 64U;
+ }
+ else if (line.find("bits 32") != std::string::npos)
+ {
+ kRegisterBitWidth = 32U;
+ }
+ else if (line.find("bits 16") != std::string::npos)
+ {
+ kRegisterBitWidth = 16U;
+ }
+ else 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 << "i64asm: origin set: " << kOrigin << std::endl;
+ }
+
+ break;
+ }
+ }
+ }
+ }
+ }
+ /// write a dword
+ else if (line.find(".dword") != std::string::npos)
+ {
+ this->WriteNumber32(line.find(".dword") + strlen(".dword") + 1, line);
+ }
+ /// write a long
+ else if (line.find(".long") != std::string::npos)
+ {
+ this->WriteNumber(line.find(".long") + strlen(".long") + 1, line);
+ }
+ /// write a 16-bit number
+ else if (line.find(".word") != std::string::npos)
+ {
+ this->WriteNumber16(line.find(".word") + strlen(".word") + 1, line);
+ }
+
+ kOrigin += cAMD64IPAlignment;
+
+ return true;
+}
+
+// Last rev 13-1-24
diff --git a/NDKKit/Sources/link.cxx b/NDKKit/Sources/link.cxx
new file mode 100644
index 0000000..0708bd0
--- /dev/null
+++ b/NDKKit/Sources/link.cxx
@@ -0,0 +1,741 @@
+/* -------------------------------------------
+
+ Copyright ZKA Technologies
+
+------------------------------------------- */
+
+/// @file link.cxx
+/// @author Amlal EL Mahrouss (amlel)
+/// @brief ZKA Technologies Linker.
+
+/// Last Rev: Sat Feb 24 CET 2024
+
+/// @note Do not look up for anything with .code64/.data64/.zero64!
+/// It will be loaded when program will start up!
+
+#include <NDKKit/NFC/ErrorID.hpp>
+
+//! Assembler Kit
+#include <NDKKit/AsmKit/AsmKit.hpp>
+
+//! Preferred Executable Format
+#include <NDKKit/NFC/PEF.hpp>
+#include <NDKKit/UUID.hpp>
+#include <filesystem>
+#include <random>
+#include <vector>
+
+//! Dist version
+#include <NDKKit/Version.hpp>
+
+//! Advanced Executable Object Format
+#include <NDKKit/NFC/AE.hpp>
+
+//! C++ I/O headers.
+#include <fstream>
+#include <iostream>
+
+#define kLinkerVersion "ZKA Linker Driver %s, (c) ZKA Technologies 2024, all rights reserved.\n"
+
+#define StringCompare(DST, SRC) strcmp(DST, SRC)
+
+#define kPefNoCpu 0U
+#define kPefNoSubCpu 0U
+
+#define kWhite "\e[0;97m"
+#define kStdOut (std::cout << kWhite)
+
+#define kLinkerDefaultOrigin kPefBaseOrigin
+#define kLinkerId 0x5046FF
+#define kLinkerAbiContainer "Container:Abi:"
+
+enum
+{
+ eABIStart = 0x1010, /* Invalid ABI start of ABI list. */
+ eABINewOS = 0x5046, /* PF (NewOSKrnl) */
+ eABIMTL = 0x4650, /* FP (MTL firmware) */
+ eABIInvalid = 1,
+};
+
+static std::string kOutput = "";
+static Int32 kAbi = eABINewOS;
+static Int32 kSubArch = kPefNoSubCpu;
+static Int32 kArch = CompilerKit::kPefArchInvalid;
+static Bool kFatBinaryEnable = false;
+static Bool kStartFound = false;
+static Bool kDuplicateSymbols = false;
+static Bool kVerbose = false;
+
+/* link is to be found, mld is to be found at runtime. */
+static const char* kLdDefineSymbol = ":UndefinedSymbol:";
+static const char* kLdDynamicSym = ":RuntimeSymbol:";
+
+/* object code and list. */
+static std::vector<std::string> kObjectList;
+static std::vector<char> kObjectBytes;
+
+#define kPrintF printf
+#define kLinkerSplash() kPrintF(kWhite kLinkerVersion, kDistVersion)
+
+NDK_MODULE(NewOSLinker)
+{
+ bool is_executable = true;
+
+ /**
+ * @brief parse flags and such.
+ *
+ */
+ for (size_t i = 1; i < argc; ++i)
+ {
+ if (StringCompare(argv[i], "/help") == 0)
+ {
+ kLinkerSplash();
+ kStdOut << "/version: Show linker version.\n";
+ kStdOut << "/help: Show linker help.\n";
+ kStdOut << "/verbose: Enable linker trace.\n";
+ kStdOut << "/shared: Output as a shared PEF.\n";
+ kStdOut << "/fat-bin: Output as a FAT PEF.\n";
+ kStdOut << "/32x0: Output as a 32x0 PEF.\n";
+ kStdOut << "/64x0: Output as a 64x0 PEF.\n";
+ kStdOut << "/amd64: Output as a AMD64 PEF.\n";
+ kStdOut << "/rv64: Output as a RISC-V PEF.\n";
+ kStdOut << "/power64: Output as a POWER PEF.\n";
+ kStdOut << "/arm64: Output as a ARM64 PEF.\n";
+ kStdOut << "/output-file: Select the output file name.\n";
+
+ return 0;
+ }
+ else if (StringCompare(argv[i], "/version") == 0)
+ {
+ kLinkerSplash();
+ 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], "/amd64") == 0)
+ {
+ kArch = CompilerKit::kPefArchAMD64;
+
+ continue;
+ }
+ else if (StringCompare(argv[i], "/32x0") == 0)
+ {
+ kArch = CompilerKit::kPefArch32000;
+
+ continue;
+ }
+ else if (StringCompare(argv[i], "/power64") == 0)
+ {
+ kArch = CompilerKit::kPefArchPowerPC;
+
+ continue;
+ }
+ else if (StringCompare(argv[i], "/arm64") == 0)
+ {
+ kArch = CompilerKit::kPefArchARM64;
+
+ continue;
+ }
+ else if (StringCompare(argv[i], "/verbose") == 0)
+ {
+ kVerbose = true;
+
+ continue;
+ }
+ else if (StringCompare(argv[i], "/shared") == 0)
+ {
+ if (kOutput.empty())
+ {
+ continue;
+ }
+
+ 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 << "link: unknown flag: " << argv[i] << "\n";
+ return MPCC_EXEC_ERROR;
+ }
+
+ kObjectList.emplace_back(argv[i]);
+
+ continue;
+ }
+ }
+
+ if (kOutput.empty())
+ {
+ kStdOut << "link: no output filename set." << std::endl;
+ return MPCC_EXEC_ERROR;
+ }
+
+ // sanity check.
+ if (kObjectList.empty())
+ {
+ kStdOut << "link: no input files." << std::endl;
+ return MPCC_EXEC_ERROR;
+ }
+ else
+ {
+ namespace fs = std::filesystem;
+
+ // check for existing files, if they don't throw an error.
+ for (auto& obj : kObjectList)
+ {
+ if (!fs::exists(obj))
+ {
+ // if filesystem doesn't find file
+ // -> throw error.
+ kStdOut << "link: no such file: " << obj << std::endl;
+ return MPCC_EXEC_ERROR;
+ }
+ }
+ }
+
+ // PEF expects a valid architecture when outputing a binary.
+ if (kArch == 0)
+ {
+ kStdOut << "link: no target architecture set, can't continue." << std::endl;
+ return MPCC_EXEC_ERROR;
+ }
+
+ CompilerKit::PEFContainer pef_container{};
+
+ int32_t archs = kArch;
+
+ pef_container.Count = 0UL;
+ pef_container.Kind = CompilerKit::kPefKindExec;
+ pef_container.SubCpu = kSubArch;
+ pef_container.Linker = kLinkerId; // ZKA Technologies 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.Magic[3] = kPefMagic[3];
+ pef_container.Version = kPefVersion;
+
+ // specify the start address, can be 0x10000
+ pef_container.Start = kLinkerDefaultOrigin;
+ pef_container.HdrSz = sizeof(CompilerKit::PEFContainer);
+
+ std::ofstream outputFc(kOutput, std::ofstream::binary);
+
+ if (outputFc.bad())
+ {
+ if (kVerbose)
+ {
+ kStdOut << "link: error: " << strerror(errno) << "\n";
+ }
+
+ return MPCC_FILE_NOT_FOUND;
+ }
+
+ //! Read AE to convert as PEF.
+
+ std::vector<CompilerKit::PEFCommandHeader> commandHdrsList;
+ 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 << "link: info: is this a FAT binary? : ";
+
+ if (!kFatBinaryEnable)
+ {
+ if (kVerbose)
+ kStdOut << "No.\n";
+
+ kStdOut << "link: error: object " << i
+ << " is a different kind of architecture and output isn't "
+ "treated as a FAT binary."
+ << std::endl;
+
+ std::remove(kOutput.c_str());
+ return MPCC_FAT_ERROR;
+ }
+ else
+ {
+ if (kVerbose)
+ {
+ kStdOut << "Yes.\n";
+ }
+ }
+ }
+
+ // append arch type to archs varaible.
+ archs |= ae_header.fArch;
+ std::size_t cnt = ae_header.fCount;
+
+ if (kVerbose)
+ kStdOut << "link: object header found, record count: " << cnt << "\n";
+
+ pef_container.Count = cnt;
+
+ char_type* raw_ae_records =
+ new char_type[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};
+ size_t offsetOfData = ae_records[ae_record_index].fOffset + ae_header.fSize;
+
+ 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(".code64") ==
+ std::string::npos &&
+ std::string(command_header.Name).find(".data64") ==
+ std::string::npos &&
+ std::string(command_header.Name).find(".zero64") ==
+ 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(".code64") !=
+ std::string::npos)
+ {
+ kStartFound = true;
+ }
+
+ ld_mark_header:
+ command_header.Offset = offsetOfData;
+ command_header.Kind = ae_records[ae_record_index].fKind;
+ command_header.Size = ae_records[ae_record_index].fSize;
+ command_header.Cpu = ae_header.fArch;
+ command_header.SubCpu = ae_header.fSubArch;
+
+ if (kVerbose)
+ {
+ kStdOut << "link: object record: "
+ << ae_records[ae_record_index].fName << " was marked.\n";
+
+ kStdOut << "link: object record offset: " << command_header.Offset << "\n";
+ }
+
+ commandHdrsList.emplace_back(command_header);
+ }
+
+ delete[] raw_ae_records;
+
+ 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;
+ }
+
+ kStdOut << "link: not an object: " << i << std::endl;
+ std::remove(kOutput.c_str());
+
+ // don't continue, it is a fatal error.
+ return MPCC_EXEC_ERROR;
+ }
+
+ pef_container.Cpu = archs;
+
+ outputFc << pef_container;
+
+ if (kVerbose)
+ {
+ kStdOut << "link: wrote container header.\n";
+ }
+
+ outputFc.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)
+
+ for (auto& commandHdr : commandHdrsList)
+ {
+ // check if this symbol needs to be resolved.
+ if (std::string(commandHdr.Name).find(kLdDefineSymbol) !=
+ std::string::npos &&
+ std::string(commandHdr.Name).find(kLdDynamicSym) == std::string::npos)
+ {
+ if (kVerbose)
+ kStdOut << "link: found undefined symbol: " << commandHdr.Name << "\n";
+
+ if (auto it = std::find(not_found.begin(), not_found.end(),
+ std::string(commandHdr.Name));
+ it == not_found.end())
+ {
+ not_found.emplace_back(commandHdr.Name);
+ }
+ }
+
+ symbols.emplace_back(commandHdr.Name);
+ }
+
+ // Now try to solve these symbols.
+
+ for (size_t not_found_idx = 0; not_found_idx < commandHdrsList.size();
+ ++not_found_idx)
+ {
+ if (auto it = std::find(not_found.begin(), not_found.end(),
+ std::string(commandHdrsList[not_found_idx].Name));
+ it != not_found.end())
+ {
+ std::string symbol_imp = *it;
+
+ if (symbol_imp.find(kLdDefineSymbol) == std::string::npos)
+ continue;
+
+ // erase the lookup prefix.
+ symbol_imp.erase(
+ 0, symbol_imp.find(kLdDefineSymbol) + strlen(kLdDefineSymbol));
+
+ // demangle everything.
+ while (symbol_imp.find('$') != std::string::npos)
+ symbol_imp.erase(symbol_imp.find('$'), 1);
+
+ // the reason we do is because, this may not match the symbol, and we need
+ // to look for other matching symbols.
+ for (auto& commandHdr : commandHdrsList)
+ {
+ if (std::string(commandHdr.Name).find(symbol_imp) !=
+ std::string::npos &&
+ std::string(commandHdr.Name).find(kLdDefineSymbol) ==
+ std::string::npos)
+ {
+ std::string undefined_symbol = commandHdr.Name;
+ auto result_of_sym =
+ undefined_symbol.substr(undefined_symbol.find(symbol_imp));
+
+ for (int i = 0; result_of_sym[i] != 0; ++i)
+ {
+ if (result_of_sym[i] != symbol_imp[i])
+ goto ld_continue_search;
+ }
+
+ not_found.erase(it);
+
+ if (kVerbose)
+ kStdOut << "link: found symbol: " << commandHdr.Name << "\n";
+
+ break;
+ }
+ }
+
+ ld_continue_search:
+ continue;
+ }
+ }
+
+ // step 3: check for errors (recheck if we have those symbols.)
+
+ if (!kStartFound && is_executable)
+ {
+ if (kVerbose)
+ kStdOut
+ << "link: undefined entrypoint: " << kPefStart << ", you may have forget to link "
+ "against your compiler's runtime library.\n";
+
+ kStdOut << "link: undefined entrypoint " << kPefStart
+ << " for executable: " << kOutput << "\n";
+ }
+
+ // step 4: write all PEF commands.
+
+ CompilerKit::PEFCommandHeader dateHeader{};
+
+ time_t timestamp = time(nullptr);
+
+ std::string timeStampStr = "Container:BuildEpoch:";
+ timeStampStr += std::to_string(timestamp);
+
+ strcpy(dateHeader.Name, timeStampStr.c_str());
+
+ dateHeader.Flags = 0;
+ dateHeader.Kind = CompilerKit::kPefZero;
+ dateHeader.Offset = outputFc.tellp();
+ dateHeader.Size = timeStampStr.size();
+
+ commandHdrsList.push_back(dateHeader);
+
+ CompilerKit::PEFCommandHeader abiHeader{};
+
+ std::string abi = kLinkerAbiContainer;
+
+ switch (kArch)
+ {
+ case CompilerKit::kPefArchAMD64: {
+ abi += "MSFT";
+ break;
+ }
+ case CompilerKit::kPefArchPowerPC: {
+ abi += "SYSV";
+ break;
+ }
+ case CompilerKit::kPefArch32000:
+ case CompilerKit::kPefArch64000: {
+ abi += "MHRA";
+ break;
+ }
+ default: {
+ abi += " IDK";
+ break;
+ }
+ }
+
+ memcpy(abiHeader.Name, abi.c_str(), abi.size());
+
+ abiHeader.Size = abi.size();
+ abiHeader.Offset = outputFc.tellp();
+ abiHeader.Flags = 0;
+ abiHeader.Kind = CompilerKit::kPefLinkerID;
+
+ commandHdrsList.push_back(abiHeader);
+
+ CompilerKit::PEFCommandHeader uuidHeader{};
+
+ std::random_device rd;
+
+ auto seedData = std::array<int, std::mt19937::state_size>{};
+ std::generate(std::begin(seedData), std::end(seedData), std::ref(rd));
+ std::seed_seq seq(std::begin(seedData), std::end(seedData));
+ std::mt19937 generator(seq);
+
+ auto gen = uuids::uuid_random_generator{generator};
+ uuids::uuid id = gen();
+ auto uuidStr = uuids::to_string(id);
+
+ memcpy(uuidHeader.Name, "Container:GUID:4:", strlen("Container:GUID:4:"));
+ memcpy(uuidHeader.Name + strlen("Container:GUID:4:"), uuidStr.c_str(),
+ uuidStr.size());
+
+ uuidHeader.Size = 16;
+ uuidHeader.Offset = outputFc.tellp();
+ uuidHeader.Flags = 0;
+ uuidHeader.Kind = CompilerKit::kPefZero;
+
+ commandHdrsList.push_back(uuidHeader);
+
+ // prepare a symbol vector.
+ std::vector<std::string> undefSymbols;
+ std::vector<std::string> duplSymbols;
+ std::vector<std::string> resolveSymbols;
+
+ constexpr Int32 cPaddingOffset = 16;
+
+ size_t previousOffset = (commandHdrsList.size() * sizeof(CompilerKit::PEFCommandHeader)) + cPaddingOffset;
+
+ // Finally write down the command headers.
+ // And check for any duplications
+ for (size_t commandHeaderIndex = 0UL;
+ commandHeaderIndex < commandHdrsList.size(); ++commandHeaderIndex)
+ {
+ if (std::string(commandHdrsList[commandHeaderIndex].Name)
+ .find(kLdDefineSymbol) != std::string::npos &&
+ std::string(commandHdrsList[commandHeaderIndex].Name)
+ .find(kLdDynamicSym) == std::string::npos)
+ {
+ // ignore :UndefinedSymbol: headers, they do not contain code.
+ continue;
+ }
+
+ std::string symbolName = commandHdrsList[commandHeaderIndex].Name;
+
+ if (!symbolName.empty())
+ {
+ undefSymbols.emplace_back(symbolName);
+ }
+
+ commandHdrsList[commandHeaderIndex].Offset += previousOffset;
+ previousOffset += commandHdrsList[commandHeaderIndex].Size;
+
+ std::string name = commandHdrsList[commandHeaderIndex].Name;
+
+ /// so this is valid when we get to the entrypoint.
+ /// it is always a code64 container. And should equal to kPefStart as well.
+ /// this chunk of code updates the pef_container.Start with the updated offset.
+ if (name.find(kPefStart) != std::string::npos &&
+ name.find(".code64") != std::string::npos)
+ {
+ pef_container.Start = commandHdrsList[commandHeaderIndex].Offset;
+ auto tellCurPos = outputFc.tellp();
+
+ outputFc.seekp(0);
+ outputFc << pef_container;
+
+ outputFc.seekp(tellCurPos);
+ }
+
+ if (kVerbose)
+ {
+ kStdOut << "link: command header name: " << name << "\n";
+ kStdOut << "link: real address of command header content: " << commandHdrsList[commandHeaderIndex].Offset << "\n";
+ }
+
+ outputFc << commandHdrsList[commandHeaderIndex];
+
+ for (size_t subCommandHeaderIndex = 0UL;
+ subCommandHeaderIndex < commandHdrsList.size();
+ ++subCommandHeaderIndex)
+ {
+ if (subCommandHeaderIndex == commandHeaderIndex)
+ continue;
+
+ if (std::string(commandHdrsList[subCommandHeaderIndex].Name)
+ .find(kLdDefineSymbol) != std::string::npos &&
+ std::string(commandHdrsList[subCommandHeaderIndex].Name)
+ .find(kLdDynamicSym) == std::string::npos)
+ {
+ if (kVerbose)
+ {
+ kStdOut << "link: ignore :UndefinedSymbol: command header...\n";
+ }
+
+ // ignore :UndefinedSymbol: headers, they do not contain code.
+ continue;
+ }
+
+ auto& commandHdr = commandHdrsList[subCommandHeaderIndex];
+
+ if (commandHdr.Name ==
+ std::string(commandHdrsList[commandHeaderIndex].Name))
+ {
+ if (std::find(duplSymbols.cbegin(), duplSymbols.cend(),
+ commandHdr.Name) == duplSymbols.cend())
+ {
+ duplSymbols.emplace_back(commandHdr.Name);
+ }
+
+ if (kVerbose)
+ kStdOut << "link: found duplicate symbol: " << commandHdr.Name
+ << "\n";
+
+ kDuplicateSymbols = true;
+ }
+ }
+ }
+
+ if (!duplSymbols.empty())
+ {
+ for (auto& symbol : duplSymbols)
+ {
+ kStdOut << "link: multiple symbols of " << symbol << ".\n";
+ }
+
+ std::remove(kOutput.c_str());
+ return MPCC_EXEC_ERROR;
+ }
+
+ // step 2.5: write program bytes.
+
+ for (auto byte : kObjectBytes)
+ {
+ outputFc << byte;
+ }
+
+ if (kVerbose)
+ kStdOut << "link: wrote contents of: " << kOutput << "\n";
+
+ // step 3: check if we have those symbols
+
+ std::vector<std::string> unrefSyms;
+
+ for (auto& commandHdr : commandHdrsList)
+ {
+ if (auto it = std::find(not_found.begin(), not_found.end(),
+ std::string(commandHdr.Name));
+ it != not_found.end())
+ {
+ unrefSyms.emplace_back(commandHdr.Name);
+ }
+ }
+
+ if (!unrefSyms.empty())
+ {
+ for (auto& unreferenced_symbol : unrefSyms)
+ {
+ kStdOut << "link: undefined symbol " << unreferenced_symbol << "\n";
+ }
+ }
+
+ if (!kStartFound || kDuplicateSymbols && std::filesystem::exists(kOutput) ||
+ !unrefSyms.empty())
+ {
+ if (kVerbose)
+ kStdOut << "link: file: " << kOutput
+ << ", is corrupt, removing file...\n";
+
+ std::remove(kOutput.c_str());
+ return MPCC_EXEC_ERROR;
+ }
+
+ return 0;
+}
+
+// Last rev 13-1-24
diff --git a/Sources/ppcasm.cc b/NDKKit/Sources/power-as.cxx
index fcf0a5d..8a6b7ef 100644
--- a/Sources/ppcasm.cc
+++ b/NDKKit/Sources/power-as.cxx
@@ -1,13 +1,13 @@
/* -------------------------------------------
- Copyright Mahrouss Logic
+ Copyright ZKA Technologies
------------------------------------------- */
/////////////////////////////////////////////////////////////////////////////////////////
-/// @file ppcasm.cxx
-/// @author Amlal El Mahrouss
+/// @file power-as.cxx
+/// @author Amlal EL Mahrouss
/// @brief POWER Assembler.
/// REMINDER: when dealing with an undefined symbol use (string
@@ -17,16 +17,16 @@
#define __ASM_NEED_PPC__ 1
-#include <Headers/AsmKit/CPU/ppc.hpp>
-#include <Headers/ParserKit.hpp>
-#include <Headers/StdKit/AE.hpp>
-#include <Headers/StdKit/PEF.hpp>
-#include <Headers/Version.hxx>
-#include <algorithm>
+#include <NDKKit/NFC/ErrorID.hpp>
+#include <NDKKit/AsmKit/CPU/ppc.hpp>
+#include <NDKKit/NFC/PEF.hpp>
+#include <NDKKit/Parser.hpp>
+#include <NDKKit/NFC/AE.hpp>
+#include <NDKKit/Version.hpp>
#include <filesystem>
-#include <fstream>
+#include <algorithm>
#include <iostream>
-#include <memory>
+#include <fstream>
#include <vector>
/////////////////////
@@ -43,11 +43,11 @@
#define kStdOut (std::cout << kWhite)
#define kStdErr (std::cout << kRed)
+constexpr auto cPowerIPAlignment = 0x4U;
+
static CharType kOutputArch = CompilerKit::kPefArchPowerPC;
static Boolean kOutputAsBinary = false;
-constexpr auto cPowerIPAlignment = 0x4U;
-
static UInt32 kErrorLimit = 10;
static UInt32 kAcceptableErrors = 0;
@@ -76,11 +76,11 @@ namespace detail {
void print_error(std::string reason, const std::string &file) noexcept {
if (reason[0] == '\n') reason.erase(0, 1);
- kStdErr << kRed << "[ ppcasm ] " << kWhite
- << ((file == "ppcasm") ? "internal assembler error "
+ kStdErr << kRed << "[ power-as ] " << kWhite
+ << ((file == "power-as") ? "internal assembler error "
: ("in file, " + file))
<< kBlank << std::endl;
- kStdErr << kRed << "[ ppcasm ] " << kWhite << reason << kBlank << std::endl;
+ kStdErr << kRed << "[ power-as ] " << kWhite << reason << kBlank << std::endl;
if (kAcceptableErrors > kErrorLimit) std::exit(3);
@@ -94,13 +94,13 @@ void print_warning(std::string reason, const std::string &file) noexcept {
kStdOut << kYellow << "[ file ] " << kWhite << file << kBlank << std::endl;
}
- kStdOut << kYellow << "[ ppcasm ] " << kWhite << reason << kBlank
+ kStdOut << kYellow << "[ power-as ] " << kWhite << reason << kBlank
<< std::endl;
}
} // namespace detail
/// Do not move it on top! it uses the assembler detail namespace!
-#include <asmutils.h>
+#include <asmutils.hxx>
/////////////////////////////////////////////////////////////////////////////////////////
@@ -108,37 +108,36 @@ void print_warning(std::string reason, const std::string &file) noexcept {
/////////////////////////////////////////////////////////////////////////////////////////
-MPCC_MODULE(NewOSAssemblerPowerPC) {
+NDK_MODULE(NewOSAssemblerPowerPC) {
for (size_t i = 1; i < argc; ++i) {
- if (argv[i][0] == '-') {
- if (strcmp(argv[i], "-version") == 0 || strcmp(argv[i], "-v") == 0) {
- kStdOut << "ppcasm: POWER Assembler.\nppcasm: " << kDistVersion << "\nppcasm: "
+ if (argv[i][0] == '/') {
+ if (strcmp(argv[i], "/version") == 0 || strcmp(argv[i], "/v") == 0) {
+ kStdOut << "power-as: POWER64 Assembler Driver.\npower-as: " << kDistVersion << "\npower-as: "
"Copyright (c) "
- "2024 Mahrouss Logic.\n";
+ "ZKA Technologies.\n";
return 0;
- } else if (strcmp(argv[i], "-h") == 0) {
- kStdOut << "ppcasm: POWER Assembler.\nppcasm: 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";
+ } else if (strcmp(argv[i], "/h") == 0) {
+ kStdOut << "power-as: POWER64 Assembler Driver.\npower-as: Copyright (c) 2024 "
+ "ZKA Technologies.\n";
+ kStdOut << "/version,/v: print program version.\n";
+ kStdOut << "/verbose: print verbose output.\n";
+ kStdOut << "/binary: output as flat binary.\n";
return 0;
- } else if (strcmp(argv[i], "-binary") == 0) {
+ } else if (strcmp(argv[i], "/binary") == 0) {
kOutputAsBinary = true;
continue;
- } else if (strcmp(argv[i], "-verbose") == 0) {
+ } else if (strcmp(argv[i], "/verbose") == 0) {
kVerbose = true;
continue;
}
- kStdOut << "ppcasm: ignore " << argv[i] << "\n";
+ kStdOut << "power-as: ignore " << argv[i] << "\n";
continue;
}
if (!std::filesystem::exists(argv[i])) {
- kStdOut << "ppcasm: can't open: " << argv[i] << std::endl;
+ kStdOut << "power-as: can't open: " << argv[i] << std::endl;
goto asm_fail_exit;
}
@@ -157,7 +156,7 @@ MPCC_MODULE(NewOSAssemblerPowerPC) {
if (file_ptr_out.bad()) {
if (kVerbose) {
- kStdOut << "ppcasm: error: " << strerror(errno) << "\n";
+ kStdOut << "power-as: error: " << strerror(errno) << "\n";
}
}
@@ -192,7 +191,7 @@ MPCC_MODULE(NewOSAssemblerPowerPC) {
} catch (const std::exception &e) {
if (kVerbose) {
std::string what = e.what();
- detail::print_warning("exit because of: " + what, "ppcasm");
+ detail::print_warning("exit because of: " + what, "power-as");
}
std::filesystem::remove(object_output);
@@ -202,7 +201,7 @@ MPCC_MODULE(NewOSAssemblerPowerPC) {
if (!kOutputAsBinary) {
if (kVerbose) {
- kStdOut << "ppcasm: Writing object file...\n";
+ kStdOut << "power-as: Writing object file...\n";
}
// this is the final step, write everything to the file.
@@ -214,8 +213,8 @@ MPCC_MODULE(NewOSAssemblerPowerPC) {
file_ptr_out << hdr;
if (kRecords.empty()) {
- kStdErr << "ppcasm: At least one record is needed to write an object "
- "file.\nppcasm: Make one using `export .code64 foo_bar`.\n";
+ kStdErr << "power-as: At least one record is needed to write an object "
+ "file.\npower-as: Make one using `export .code64 foo_bar`.\n";
std::filesystem::remove(object_output);
return -1;
@@ -225,36 +224,36 @@ MPCC_MODULE(NewOSAssemblerPowerPC) {
std::size_t record_count = 0UL;
- for (auto &rec : kRecords) {
- if (kVerbose)
- kStdOut << "ppcasm: Wrote record " << rec.fName << " to file...\n";
-
- rec.fFlags |= CompilerKit::kKindRelocationAtRuntime;
- rec.fOffset = record_count;
+ for (auto &record_hdr : kRecords) {
+ record_hdr.fFlags |= CompilerKit::kKindRelocationAtRuntime;
+ record_hdr.fOffset = record_count;
++record_count;
- file_ptr_out << rec;
+ file_ptr_out << record_hdr;
+
+ if (kVerbose)
+ kStdOut << "power-as: Wrote record " << record_hdr.fName << "...\n";
}
// increment once again, so that we won't lie about the kUndefinedSymbols.
++record_count;
for (auto &sym : kUndefinedSymbols) {
- CompilerKit::AERecordHeader _record_hdr{0};
+ CompilerKit::AERecordHeader undefined_sym{0};
if (kVerbose)
- kStdOut << "ppcasm: Wrote symbol " << sym << " to file...\n";
+ kStdOut << "power-as: Wrote symbol " << sym << " to file...\n";
- _record_hdr.fKind = kAEInvalidOpcode;
- _record_hdr.fSize = sym.size();
- _record_hdr.fOffset = record_count;
+ undefined_sym.fKind = kAEInvalidOpcode;
+ undefined_sym.fSize = sym.size();
+ undefined_sym.fOffset = record_count;
++record_count;
- memset(_record_hdr.fPad, kAEInvalidOpcode, kAEPad);
- memcpy(_record_hdr.fName, sym.c_str(), sym.size());
+ memset(undefined_sym.fPad, kAEInvalidOpcode, kAEPad);
+ memcpy(undefined_sym.fName, sym.c_str(), sym.size());
- file_ptr_out << _record_hdr;
+ file_ptr_out << undefined_sym;
++kCounter;
}
@@ -271,7 +270,7 @@ MPCC_MODULE(NewOSAssemblerPowerPC) {
file_ptr_out.seekp(pos_end);
} else {
if (kVerbose) {
- kStdOut << "ppcasm: Write raw binary...\n";
+ kStdOut << "power-as: Write raw binary...\n";
}
}
@@ -280,21 +279,21 @@ MPCC_MODULE(NewOSAssemblerPowerPC) {
file_ptr_out.write(reinterpret_cast<const char *>(&byte), sizeof(byte));
}
- if (kVerbose) kStdOut << "ppcasm: Wrote file with program in it.\n";
+ if (kVerbose) kStdOut << "power-as: Wrote file with program in it.\n";
file_ptr_out.flush();
file_ptr_out.close();
- if (kVerbose) kStdOut << "ppcasm: Exit succeeded.\n";
+ if (kVerbose) kStdOut << "power-as: Exit succeeded.\n";
return 0;
}
asm_fail_exit:
- if (kVerbose) kStdOut << "ppcasm: Exit failed.\n";
+ if (kVerbose) kStdOut << "power-as: Exit failed.\n";
- return -1;
+ return MPCC_EXEC_ERROR;
}
/////////////////////////////////////////////////////////////////////////////////////////
@@ -307,17 +306,17 @@ asm_fail_exit:
static bool asm_read_attributes(std::string &line) {
// import is the opposite of export, it signals to the li
// that we need this symbol.
- if (ParserKit::find_word(line, "import")) {
+ if (CompilerKit::find_word(line, "import")) {
if (kOutputAsBinary) {
detail::print_error("Invalid import directive in flat binary mode.",
- "ppcasm");
+ "power-as");
throw std::runtime_error("invalid_import_bin");
}
auto name = line.substr(line.find("import") + strlen("import") + 1);
if (name.size() == 0) {
- detail::print_error("Invalid import", "ppcasm");
+ detail::print_error("Invalid import", "power-as");
throw std::runtime_error("invalid_import");
}
@@ -364,13 +363,13 @@ static bool asm_read_attributes(std::string &line) {
return true;
}
- // export is a special keyword used by ppcasm to tell the AE output stage to
+ // export is a special keyword used by power-as to tell the AE output stage to
// mark this section as a header. it currently supports .code64, .data64.,
// .zero64
- else if (ParserKit::find_word(line, "export")) {
+ else if (CompilerKit::find_word(line, "export")) {
if (kOutputAsBinary) {
detail::print_error("Invalid export directive in flat binary mode.",
- "ppcasm");
+ "power-as");
throw std::runtime_error("invalid_export_bin");
}
@@ -457,9 +456,9 @@ std::string CompilerKit::EncoderPowerPC::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") ||
- line.find('#') != std::string::npos || ParserKit::find_word(line, ";")) {
+ if (line.empty() || CompilerKit::find_word(line, "import") ||
+ CompilerKit::find_word(line, "export") ||
+ line.find('#') != std::string::npos || CompilerKit::find_word(line, ";")) {
if (line.find('#') != std::string::npos) {
line.erase(line.find('#'));
} else if (line.find(';') != std::string::npos) {
@@ -525,7 +524,7 @@ std::string CompilerKit::EncoderPowerPC::CheckLine(std::string &line,
std::vector<std::string> filter_inst = {"blr", "bl", "sc"};
for (auto &opcodePPC : kOpcodesPowerPC) {
- if (ParserKit::find_word(line, opcodePPC.name)) {
+ if (CompilerKit::find_word(line, opcodePPC.name)) {
for (auto &op : operands_inst) {
// if only the instruction was found.
if (line == op) {
@@ -540,7 +539,7 @@ std::string CompilerKit::EncoderPowerPC::CheckLine(std::string &line,
if (auto it =
std::find(filter_inst.begin(), filter_inst.end(), opcodePPC.name);
it == filter_inst.cend()) {
- if (ParserKit::find_word(line, opcodePPC.name)) {
+ if (CompilerKit::find_word(line, opcodePPC.name)) {
if (!isspace(
line[line.find(opcodePPC.name) + strlen(opcodePPC.name)])) {
err_str += "\nMissing space between ";
@@ -569,7 +568,7 @@ bool CompilerKit::EncoderPowerPC::WriteNumber(const std::size_t &pos,
if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16);
!res) {
if (errno != 0) {
- detail::print_error("invalid hex number: " + jump_label, "ppcasm");
+ detail::print_error("invalid hex number: " + jump_label, "power-as");
throw std::runtime_error("invalid_hex");
}
}
@@ -582,7 +581,7 @@ bool CompilerKit::EncoderPowerPC::WriteNumber(const std::size_t &pos,
}
if (kVerbose) {
- kStdOut << "ppcasm: found a base 16 number here: "
+ kStdOut << "power-as: found a base 16 number here: "
<< jump_label.substr(pos) << "\n";
}
@@ -592,7 +591,7 @@ bool CompilerKit::EncoderPowerPC::WriteNumber(const std::size_t &pos,
if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2);
!res) {
if (errno != 0) {
- detail::print_error("invalid binary number: " + jump_label, "ppcasm");
+ detail::print_error("invalid binary number: " + jump_label, "power-as");
throw std::runtime_error("invalid_bin");
}
}
@@ -601,7 +600,7 @@ bool CompilerKit::EncoderPowerPC::WriteNumber(const std::size_t &pos,
strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2));
if (kVerbose) {
- kStdOut << "ppcasm: found a base 2 number here: "
+ kStdOut << "power-as: found a base 2 number here: "
<< jump_label.substr(pos) << "\n";
}
@@ -615,7 +614,7 @@ bool CompilerKit::EncoderPowerPC::WriteNumber(const std::size_t &pos,
if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7);
!res) {
if (errno != 0) {
- detail::print_error("invalid octal number: " + jump_label, "ppcasm");
+ detail::print_error("invalid octal number: " + jump_label, "power-as");
throw std::runtime_error("invalid_octal");
}
}
@@ -624,7 +623,7 @@ bool CompilerKit::EncoderPowerPC::WriteNumber(const std::size_t &pos,
strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7));
if (kVerbose) {
- kStdOut << "ppcasm: found a base 8 number here: "
+ kStdOut << "power-as: found a base 8 number here: "
<< jump_label.substr(pos) << "\n";
}
@@ -654,7 +653,7 @@ bool CompilerKit::EncoderPowerPC::WriteNumber(const std::size_t &pos,
}
if (kVerbose) {
- kStdOut << "ppcasm: found a base 10 number here: " << jump_label.substr(pos)
+ kStdOut << "power-as: found a base 10 number here: " << jump_label.substr(pos)
<< "\n";
}
@@ -669,12 +668,12 @@ bool CompilerKit::EncoderPowerPC::WriteNumber(const std::size_t &pos,
bool CompilerKit::EncoderPowerPC::WriteLine(std::string &line,
const std::string &file) {
- if (ParserKit::find_word(line, "export")) return true;
+ if (CompilerKit::find_word(line, "export")) return true;
if (!detail::algorithm::is_valid(line)) return true;
for (auto &opcodePPC : kOpcodesPowerPC) {
// strict check here
- if (ParserKit::find_word(line, opcodePPC.name)) {
+ if (CompilerKit::find_word(line, opcodePPC.name)) {
std::string name(opcodePPC.name);
std::string jump_label, cpy_jump_label;
std::vector<size_t> found_registers_index;
@@ -878,9 +877,9 @@ bool CompilerKit::EncoderPowerPC::WriteLine(std::string &line,
}
if (kVerbose) {
- kStdOut << "ppcasm: Found register: " << register_syntax
+ kStdOut << "power-as: Found register: " << register_syntax
<< "\n";
- kStdOut << "ppcasm: Amount of registers in instruction: "
+ kStdOut << "power-as: Amount of registers in instruction: "
<< found_some_count << "\n";
}
@@ -946,7 +945,7 @@ bool CompilerKit::EncoderPowerPC::WriteLine(std::string &line,
// remember! register to register!
if (found_some_count == 1) {
detail::print_error(
- "Unrecognized register found.\ntip: each ppcasm register "
+ "Unrecognized register found.\ntip: each power-as register "
"starts with 'r'.\nline: " +
line,
file);
diff --git a/NDKKit/Sources/power-cc.cxx b/NDKKit/Sources/power-cc.cxx
new file mode 100644
index 0000000..4c07a04
--- /dev/null
+++ b/NDKKit/Sources/power-cc.cxx
@@ -0,0 +1,1645 @@
+/*
+ * ========================================================
+ *
+ * cc
+ * Copyright ZKA Technologies, all rights reserved.
+ *
+ * ========================================================
+ */
+
+#include <NDKKit/AsmKit/CPU/ppc.hpp>
+#include <NDKKit/Parser.hpp>
+#include <NDKKit/UUID.hpp>
+#include <filesystem>
+#include <fstream>
+#include <iostream>
+#include <memory>
+#include <random>
+#include <string>
+#include <utility>
+#include <vector>
+#include <cstdio>
+
+#define kOk 0
+
+/// @author Amlal El Mahrouss (amlel)
+/// @file cc.cxx
+/// @brief POWER C Compiler.
+
+/////////////////////
+
+/// ANSI ESCAPE CODES
+
+/////////////////////
+
+#define kBlank "\e[0;30m"
+#define kRed "\e[0;31m"
+#define kWhite "\e[0;97m"
+
+/////////////////////////////////////
+
+/// INTERNAL STRUCT OF THE C COMPILER
+
+/////////////////////////////////////
+
+namespace detail
+{
+ // \brief name to register struct.
+ struct CompilerRegisterMap final
+ {
+ std::string fName;
+ std::string fReg;
+ };
+
+ // \brief Map for C structs
+ // \author amlel
+ struct CompilerStructMap final
+ {
+ /// 'struct::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<CompilerKit::SyntaxLeafList> fSyntaxTreeList;
+ std::vector<CompilerRegisterMap> kStackFrame;
+ std::vector<CompilerStructMap> kStructMap;
+ CompilerKit::SyntaxLeafList* fSyntaxTree{nullptr};
+ std::unique_ptr<std::ofstream> fOutputAssembly;
+ std::string fLastFile;
+ std::string fLastError;
+ bool fVerbose;
+ };
+} // namespace detail
+
+static detail::CompilerState kState;
+static SizeType kErrorLimit = 100;
+static std::string kIfFunction = "";
+static Int32 kAcceptableErrors = 0;
+
+namespace detail
+{
+ /// @brief prints an error into stdout.
+ /// @param reason the reason of the error.
+ /// @param file where does it originate from?
+ 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 (kState.fLastFile != file)
+ {
+ std::cout << kRed << "[ cc ] " << kWhite
+ << ((file == "cc") ? "internal compiler error "
+ : ("in file, " + file))
+ << kBlank << std::endl;
+ std::cout << kRed << "[ cc ] " << kWhite << reason << kBlank << std::endl;
+
+ kState.fLastFile = file;
+ }
+ else
+ {
+ std::cout << kRed << "[ cc ] [ " << kState.fLastFile << " ] " << kWhite
+ << reason << kBlank << std::endl;
+ }
+
+ if (kAcceptableErrors > kErrorLimit)
+ std::exit(3);
+
+ ++kAcceptableErrors;
+ }
+
+ struct CompilerType final
+ {
+ std::string fName;
+ std::string fValue;
+ };
+} // namespace detail
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+// Target architecture.
+static int kMachine = 0;
+
+/////////////////////////////////////////
+
+// REGISTERS ACCORDING TO USED ASSEMBLER
+
+/////////////////////////////////////////
+
+static size_t kRegisterCnt = kAsmRegisterLimit;
+static size_t kStartUsable = 2;
+static size_t kUsableLimit = 15;
+static size_t kRegisterCounter = kStartUsable;
+static std::string kRegisterPrefix = kAsmRegisterPrefix;
+
+/////////////////////////////////////////
+
+// COMPILER PARSING UTILITIES/STATES.
+
+/////////////////////////////////////////
+
+static std::vector<std::string> kFileList;
+static CompilerKit::AssemblyFactory kFactory;
+static bool kInStruct = false;
+static bool kOnWhileLoop = false;
+static bool kOnForLoop = false;
+static bool kInBraces = false;
+static bool kIfFound = false;
+static size_t kBracesCount = 0UL;
+
+/* @brief C compiler backend for C */
+class CompilerBackendCLang final : public CompilerKit::CompilerBackend
+{
+public:
+ explicit CompilerBackendCLang() = default;
+ ~CompilerBackendCLang() override = default;
+
+ MPCC_COPY_DEFAULT(CompilerBackendCLang);
+
+ std::string Check(const char* text, const char* file);
+ bool Compile(const std::string& text, const char* file) override;
+
+ const char* Language() override
+ {
+ return "POWER C";
+ }
+};
+
+static CompilerBackendCLang* kCompilerBackend = nullptr;
+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
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+// @name Compile
+// @brief Generate MASM from a C assignement.
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+bool CompilerBackendCLang::Compile(const std::string& text, const char* file)
+{
+ std::string textBuffer = text;
+
+ bool typeFound = false;
+ bool fnFound = false;
+
+ // setup generator.
+ std::random_device rd;
+
+ auto seed_data = std::array<int, std::mt19937::state_size>{};
+ std::generate(std::begin(seed_data), std::end(seed_data), std::ref(rd));
+ std::seed_seq seq(std::begin(seed_data), std::end(seed_data));
+ std::mt19937 generator(seq);
+
+ // start parsing
+ for (size_t text_index = 0; text_index < textBuffer.size(); ++text_index)
+ {
+ auto syntaxLeaf = CompilerKit::SyntaxLeafList::SyntaxLeaf();
+
+ auto gen = uuids::uuid_random_generator{generator};
+ uuids::uuid out = gen();
+
+ detail::number_cast time_off = (UInt64)out.as_bytes().data();
+
+ if (!typeFound)
+ {
+ auto substr = textBuffer.substr(text_index);
+ std::string match_type;
+
+ 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(' '));
+ }
+
+ for (auto& clType : kCompilerTypes)
+ {
+ if (clType.fName == match_type)
+ {
+ match_type.clear();
+
+ std::string buf;
+
+ buf += clType.fValue;
+ buf += ' ';
+
+ if (substr.find('=') != std::string::npos)
+ {
+ break;
+ }
+
+ if (textBuffer.find('(') != std::string::npos)
+ {
+ syntaxLeaf.fUserValue = buf;
+
+ kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
+ }
+
+ typeFound = true;
+ break;
+ }
+ }
+
+ break;
+ }
+
+ match_type += substr[y];
+ }
+ }
+
+ if (textBuffer[text_index] == '{')
+ {
+ if (kInStruct)
+ {
+ continue;
+ }
+
+ kInBraces = true;
+ ++kBracesCount;
+
+ kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
+ }
+
+ // return keyword handler
+ if (textBuffer[text_index] == 'r')
+ {
+ std::string return_keyword;
+ return_keyword += "return";
+
+ std::size_t index = 0UL;
+
+ std::string value;
+
+ for (size_t return_index = text_index; return_index < textBuffer.size();
+ ++return_index)
+ {
+ if (textBuffer[return_index] != return_keyword[index])
+ {
+ for (size_t value_index = return_index;
+ value_index < textBuffer.size(); ++value_index)
+ {
+ if (textBuffer[value_index] == ';')
+ break;
+
+ value += textBuffer[value_index];
+ }
+
+ break;
+ }
+
+ ++index;
+ }
+
+ if (index == return_keyword.size())
+ {
+ if (!value.empty())
+ {
+ if (value.find('(') != std::string::npos)
+ {
+ value.erase(value.find('('));
+ }
+
+ if (!isdigit(value[value.find('(') + 2]))
+ {
+ std::string tmp = value;
+ bool reg_to_reg = false;
+
+ value.clear();
+
+ value += " import";
+ value += tmp;
+ }
+
+ syntaxLeaf.fUserValue = "\tmr r31, ";
+
+ // make it pretty.
+ while (value.find('\t') != std::string::npos)
+ value.erase(value.find('\t'), 1);
+
+ while (value.find(' ') != std::string::npos)
+ value.erase(value.find(' '), 1);
+
+ while (value.find("import") != std::string::npos)
+ value.erase(value.find("import"), strlen("import"));
+
+ bool found = false;
+
+ for (auto& reg : kState.kStackFrame)
+ {
+ if (value.find(reg.fName) != std::string::npos)
+ {
+ found = true;
+ syntaxLeaf.fUserValue += reg.fReg;
+ break;
+ }
+ }
+
+ if (!found)
+ syntaxLeaf.fUserValue += "r0";
+ }
+
+ syntaxLeaf.fUserValue += "\n\tblr";
+
+ kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
+
+ break;
+ }
+ }
+
+ if (textBuffer[text_index] == 'i' && textBuffer[text_index + 1] == 'f')
+ {
+ auto expr = textBuffer.substr(text_index + 2);
+ textBuffer.erase(text_index, 2);
+
+ if (expr.find("{") != std::string::npos)
+ {
+ expr.erase(expr.find("{"));
+ }
+
+ if (expr.find("(") != std::string::npos)
+ expr.erase(expr.find("("));
+
+ if (expr.find(")") != std::string::npos)
+ expr.erase(expr.find(")"));
+
+ kIfFunction = "__MPCC_IF_PROC_";
+ kIfFunction += std::to_string(time_off._Raw);
+
+ syntaxLeaf.fUserValue =
+ "\tcmpw "
+ "r10, r11";
+
+ syntaxLeaf.fUserValue += "\n\tbeq import " + kIfFunction +
+ " \ndword export .code64 " + kIfFunction + "\n";
+
+ kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
+
+ kIfFound = true;
+ }
+
+ // Parse expressions and instructions here.
+ // what does this mean?
+ // we encounter an assignment, or we reached the end of an expression.
+ if (textBuffer[text_index] == '=' || textBuffer[text_index] == ';')
+ {
+ if (fnFound)
+ continue;
+ if (kIfFound)
+ continue;
+
+ if (textBuffer[text_index] == ';' && kInStruct)
+ continue;
+
+ if (textBuffer.find("typedef ") != std::string::npos)
+ continue;
+
+ if (textBuffer[text_index] == '=' && kInStruct)
+ {
+ detail::print_error(
+ "assignement of value inside a struct " + textBuffer, file);
+ continue;
+ }
+
+ if (textBuffer[text_index] == ';' && kInStruct)
+ {
+ bool space_found_ = false;
+ std::string sym;
+
+ for (auto& ch : textBuffer)
+ {
+ if (ch == ' ')
+ {
+ space_found_ = true;
+ }
+
+ if (ch == ';')
+ break;
+
+ if (space_found_)
+ sym.push_back(ch);
+ }
+
+ kState.kStructMap[kState.kStructMap.size() - 1].fOffsets.push_back(
+ std::make_pair(
+ kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt + 4,
+ sym));
+
+ kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt =
+ kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt + 4;
+
+ continue;
+ }
+
+ if (textBuffer[text_index] == '=' && kInStruct)
+ {
+ continue;
+ }
+
+ if (textBuffer[text_index + 1] == '=' ||
+ textBuffer[text_index - 1] == '!' ||
+ textBuffer[text_index - 1] == '<' ||
+ textBuffer[text_index - 1] == '>')
+ {
+ continue;
+ }
+
+ std::string substr;
+
+ if (textBuffer.find('=') != std::string::npos && kInBraces && !kIfFound)
+ {
+ if (textBuffer.find("*") != std::string::npos)
+ {
+ if (textBuffer.find("=") > textBuffer.find("*"))
+ substr += "\tli ";
+ else
+ substr += "\tli ";
+ }
+ else
+ {
+ substr += "\tli ";
+ }
+ }
+ else if (textBuffer.find('=') != std::string::npos && !kInBraces)
+ {
+ substr += "stw export .data64 ";
+ }
+
+ int first_encountered = 0;
+
+ std::string str_name;
+
+ for (size_t text_index_2 = 0; text_index_2 < textBuffer.size();
+ ++text_index_2)
+ {
+ if (textBuffer[text_index_2] == '\"')
+ {
+ ++text_index_2;
+
+ // want to add this, so that the parser recognizes that this is a
+ // string.
+ substr += '"';
+
+ for (; text_index_2 < textBuffer.size(); ++text_index_2)
+ {
+ if (textBuffer[text_index_2] == '\"')
+ break;
+
+ substr += textBuffer[text_index_2];
+ }
+ }
+
+ if (textBuffer[text_index_2] == '{' || textBuffer[text_index_2] == '}')
+ continue;
+
+ if (textBuffer[text_index_2] == ';')
+ {
+ break;
+ }
+
+ if (textBuffer[text_index_2] == ' ' ||
+ textBuffer[text_index_2] == '\t')
+ {
+ if (first_encountered != 2)
+ {
+ if (textBuffer[text_index] != '=' &&
+ substr.find("export .data64") == std::string::npos &&
+ !kInStruct)
+ substr += "export .data64 ";
+ }
+
+ ++first_encountered;
+
+ continue;
+ }
+
+ if (textBuffer[text_index_2] == '=')
+ {
+ if (!kInBraces)
+ {
+ substr.replace(substr.find("export .data64"),
+ strlen("export .data64"), "export .zero64 ");
+ }
+
+ substr += ",";
+ continue;
+ }
+
+ substr += textBuffer[text_index_2];
+ }
+
+ for (auto& clType : kCompilerTypes)
+ {
+ if (substr.find(clType.fName) != std::string::npos)
+ {
+ if (substr.find(clType.fName) > substr.find('"'))
+ continue;
+
+ 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 (clType.fName == "const")
+ continue;
+
+ substr.erase(substr.find(clType.fValue), clType.fValue.size());
+ }
+ }
+
+ if (substr.find("extern") != std::string::npos)
+ {
+ substr.replace(substr.find("extern"), strlen("extern"), "import ");
+
+ if (substr.find("export .data64") != std::string::npos)
+ substr.erase(substr.find("export .data64"), strlen("export .data64"));
+ }
+
+ auto var_to_find =
+ std::find_if(kCompilerVariables.cbegin(), kCompilerVariables.cend(),
+ [&](detail::CompilerType type) {
+ return type.fName.find(substr) != std::string::npos;
+ });
+
+ kCompilerVariables.push_back({.fName = substr});
+
+ if (textBuffer[text_index] == ';')
+ break;
+
+ std::string reg = kAsmRegisterPrefix;
+
+ ++kRegisterCounter;
+ reg += std::to_string(kRegisterCounter);
+
+ auto newSubstr = substr.substr(substr.find(" "));
+
+ std::string symbol;
+
+ for (size_t start = 0; start < newSubstr.size(); ++start)
+ {
+ if (newSubstr[start] == ',')
+ break;
+
+ if (newSubstr[start] == ' ')
+ continue;
+
+ symbol += (newSubstr[start]);
+ }
+
+ kState.kStackFrame.push_back({.fName = symbol, .fReg = reg});
+
+ syntaxLeaf.fUserValue +=
+ "\n\tli " + reg + substr.substr(substr.find(','));
+ kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
+ }
+
+ // function handler.
+
+ if (textBuffer[text_index] == '(' && !fnFound && !kIfFound)
+ {
+ std::string substr;
+ std::string args_buffer;
+ std::string args;
+
+ bool type_crossed = false;
+
+ for (size_t idx = textBuffer.find('(') + 1; idx < textBuffer.size();
+ ++idx)
+ {
+ if (textBuffer[idx] == ',')
+ continue;
+
+ if (textBuffer[idx] == ' ')
+ continue;
+
+ if (textBuffer[idx] == ')')
+ break;
+ }
+
+ for (char substr_first_index : textBuffer)
+ {
+ if (substr_first_index != ',')
+ args_buffer += substr_first_index;
+ else
+ args_buffer += '$';
+
+ 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 (!args_buffer.empty())
+ args += "\tldw r6, ";
+
+ std::string register_type;
+ std::size_t index = 7UL;
+
+ while (args_buffer.find("$") != std::string::npos)
+ {
+ register_type = kRegisterPrefix;
+ register_type += std::to_string(index);
+
+ ++index;
+
+ args_buffer.replace(args_buffer.find('$'), 1,
+ "\n\tldw " + register_type + ",");
+ }
+
+ args += args_buffer;
+ args += "\n\tli r31, ";
+ }
+ }
+
+ for (char _text_i : textBuffer)
+ {
+ if (_text_i == '\t' || _text_i == ' ')
+ {
+ if (!type_crossed)
+ {
+ substr.clear();
+ type_crossed = true;
+ }
+
+ continue;
+ }
+
+ if (_text_i == '(')
+ break;
+
+ substr += _text_i;
+ }
+
+ if (kInBraces)
+ {
+ syntaxLeaf.fUserValue = args;
+ syntaxLeaf.fUserValue += substr;
+
+ syntaxLeaf.fUserValue += "\n\tblr\n";
+
+ kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
+
+ fnFound = true;
+ }
+ else
+ {
+ syntaxLeaf.fUserValue.clear();
+
+ syntaxLeaf.fUserValue += "export .code64 ";
+
+ syntaxLeaf.fUserValue += substr;
+ syntaxLeaf.fUserValue += "\n";
+
+ kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
+
+ fnFound = true;
+ }
+
+ kCompilerFunctions.push_back(textBuffer);
+ }
+
+ if (textBuffer[text_index] == '-' && textBuffer[text_index + 1] == '-')
+ {
+ textBuffer = textBuffer.replace(textBuffer.find("--"), strlen("--"), "");
+
+ for (int _text_i = 0; _text_i < textBuffer.size(); ++_text_i)
+ {
+ if (textBuffer[_text_i] == '\t' || textBuffer[_text_i] == ' ')
+ textBuffer.erase(_text_i, 1);
+ }
+
+ syntaxLeaf.fUserValue += "dec ";
+ syntaxLeaf.fUserValue += textBuffer;
+
+ kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
+ break;
+ }
+
+ if (textBuffer[text_index] == '}')
+ {
+ kRegisterCounter = kStartUsable;
+
+ --kBracesCount;
+
+ if (kBracesCount < 1)
+ {
+ kInBraces = false;
+ kBracesCount = 0;
+ }
+
+ if (kIfFound)
+ kIfFound = false;
+
+ if (kInStruct)
+ kInStruct = false;
+
+ kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
+ }
+
+ syntaxLeaf.fUserValue.clear();
+ }
+
+ auto syntaxLeaf = CompilerKit::SyntaxLeafList::SyntaxLeaf();
+ syntaxLeaf.fUserValue = "\n";
+ kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
+
+ return true;
+}
+
+static bool kShouldHaveBraces = false;
+static std::string kFnName;
+
+std::string CompilerBackendCLang::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;
+
+ for (int i = 0; i < ln.size(); ++i)
+ {
+ if (isalnum(ln[i]))
+ {
+ non_ascii_found = true;
+ break;
+ }
+ }
+
+ if (kShouldHaveBraces && ln.find('{') != std::string::npos)
+ {
+ kShouldHaveBraces = false;
+ }
+
+ if (!non_ascii_found)
+ return err_str;
+
+ size_t string_index = 1UL;
+
+ 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);
+ }
+
+ 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("class");
+ 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;
+ }
+ }
+ }
+
+ 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;
+ }
+
+ keyword.push_back(ln[string_index]);
+ }
+
+ goto cc_next_loop;
+
+ cc_check_done:
+
+ // skip digit value.
+ if (isdigit(keyword[0]) || keyword[0] == '"')
+ {
+ goto cc_next_loop;
+ }
+
+ while (keyword.find(' ') != std::string::npos)
+ keyword.erase(keyword.find(' '), 1);
+
+ for (auto& var : kCompilerVariables)
+ {
+ if (var.fValue.find(keyword) != std::string::npos)
+ {
+ err_str.clear();
+ goto cc_next;
+ }
+ }
+
+ 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;
+ }
+ }
+ }
+
+ cc_error_value:
+ if (keyword.find("->") != std::string::npos)
+ return err_str;
+
+ if (keyword.find(".") != std::string::npos)
+ return err_str;
+
+ if (isalnum(keyword[0]))
+ err_str += "\nUndefined value: " + keyword;
+
+ return err_str;
+ }
+
+ cc_next_loop:
+ continue;
+ }
+
+cc_next:
+
+ // extern does not declare anything, it imports a variable.
+ // so that's why it's not declare upper.
+ if (CompilerKit::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 (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;
+ }
+ }
+
+skip_braces_check:
+
+ for (auto& key : kCompilerTypes)
+ {
+ if (CompilerKit::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[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;
+
+ 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;
+ }
+ }
+
+ next:
+
+ 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;
+ }
+
+ 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 (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 && !CompilerKit::find_word(ln, "|") &&
+ !CompilerKit::find_word(ln, "||") && !CompilerKit::find_word(ln, "&") &&
+ !CompilerKit::find_word(ln, "&&") && !CompilerKit::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;
+
+ bool space_found = false;
+
+ for (int i = 0; i < ln.size(); ++i)
+ {
+ if (ln[i] == ')' && !space_found)
+ {
+ space_found = true;
+ continue;
+ }
+
+ if (space_found)
+ {
+ if (ln[i] == ' ' && isalnum(ln[i + 1]))
+ {
+ err_str += "\nBad function format 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)
+ {
+ 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('}') != 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;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * @brief C To Assembly mount-point.
+ */
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+class AssemblyMountpointCLang final : public CompilerKit::AssemblyInterface
+{
+public:
+ explicit AssemblyMountpointCLang() = default;
+ ~AssemblyMountpointCLang() override = default;
+
+ MPCC_COPY_DEFAULT(AssemblyMountpointCLang);
+
+ [[maybe_unused]] static Int32 Arch() noexcept
+ {
+ return CompilerKit::AssemblyFactory::kArchPowerPC;
+ }
+
+ Int32 CompileToFormat(std::string& src, Int32 arch) override
+ {
+ if (arch != AssemblyMountpointCLang::Arch())
+ return -1;
+
+ if (kCompilerBackend == nullptr)
+ return -1;
+
+ /* @brief copy contents wihtout extension */
+ std::string src_file = src.data();
+ std::ifstream src_fp = std::ifstream(src_file, std::ios::in);
+ std::string dest;
+
+ for (auto& ch : src_file)
+ {
+ if (ch == '.')
+ {
+ break;
+ }
+
+ dest += ch;
+ }
+
+ /* According to PEF ABI. */
+ std::vector<const char*> exts = kAsmFileExts;
+ dest += exts[4];
+
+ kState.fOutputAssembly = std::make_unique<std::ofstream>(dest);
+
+ auto fmt = CompilerKit::current_date();
+
+ (*kState.fOutputAssembly) << "# Path: " << src_file << "\n";
+ (*kState.fOutputAssembly)
+ << "# Language: POWER Assembly (Generated from C)\n";
+ (*kState.fOutputAssembly) << "# Date: " << fmt << "\n\n";
+
+ CompilerKit::SyntaxLeafList syntax;
+
+ kState.fSyntaxTreeList.push_back(syntax);
+ kState.fSyntaxTree =
+ &kState.fSyntaxTreeList[kState.fSyntaxTreeList.size() - 1];
+
+ std::string line_src;
+
+ while (std::getline(src_fp, line_src))
+ {
+ if (auto err = kCompilerBackend->Check(line_src.c_str(), src.data());
+ err.empty())
+ {
+ kCompilerBackend->Compile(line_src, src.data());
+ }
+ else
+ {
+ detail::print_error(err, src.data());
+ }
+ }
+
+ if (kAcceptableErrors > 0)
+ return -1;
+
+ std::vector<std::string> keywords = {"ld", "stw", "add", "sub", "or"};
+
+ ///
+ /// Replace, optimize, fix assembly output.
+ ///
+
+ for (auto& leaf : kState.fSyntaxTree->fLeafList)
+ {
+ std::vector<std::string> access_keywords = {"->", "."};
+
+ for (auto& access_ident : access_keywords)
+ {
+ if (CompilerKit::find_word(leaf.fUserValue, access_ident))
+ {
+ for (auto& struc : kState.kStructMap)
+ {
+ /// TODO:
+ }
+ }
+ }
+
+ for (auto& keyword : keywords)
+ {
+ if (CompilerKit::find_word(leaf.fUserValue, keyword))
+ {
+ std::size_t cnt = 0UL;
+
+ for (auto& reg : 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 (CompilerKit::find_word(leaf.fUserValue, needle))
+ {
+ if (leaf.fUserValue.find("import ") != std::string::npos)
+ {
+ std::string range = "import ";
+ leaf.fUserValue.replace(leaf.fUserValue.find(range),
+ range.size(), "");
+ }
+
+ 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"), "mr");
+ }
+ }
+
+ leaf.fUserValue.replace(leaf.fUserValue.find(needle),
+ needle.size(), reg.fReg);
+
+ ++cnt;
+ }
+ }
+
+ if (cnt > 1 && keyword != "mr" && keyword != "add" &&
+ keyword != "dec")
+ {
+ leaf.fUserValue.replace(leaf.fUserValue.find(keyword),
+ keyword.size(), "mr");
+ }
+ }
+ }
+ }
+
+ for (auto& leaf : kState.fSyntaxTree->fLeafList)
+ {
+ (*kState.fOutputAssembly) << leaf.fUserValue;
+ }
+
+ kState.fSyntaxTree = nullptr;
+
+ kState.fOutputAssembly->flush();
+ kState.fOutputAssembly.reset();
+
+ return kOk;
+ }
+};
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+#include <Version.hpp>
+
+#define kPrintF printf
+#define kSplashCxx() \
+ kPrintF(kWhite "cc, %s, (c) ZKA Technologies\n", kDistVersion)
+
+static void cc_print_help()
+{
+ kSplashCxx();
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+#define kExt ".c"
+
+NDK_MODULE(NewOSCompilerCLangPowerPC)
+{
+ 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"});
+ kCompilerTypes.push_back({.fName = "*", .fValue = "offset"});
+
+ bool skip = false;
+
+ kFactory.Mount(new AssemblyMountpointCLang());
+ kMachine = CompilerKit::AssemblyFactory::kArchPowerPC;
+ kCompilerBackend = new CompilerBackendCLang();
+
+ 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 (strcmp(argv[index], "-verbose") == 0)
+ {
+ kState.fVerbose = true;
+
+ continue;
+ }
+
+ if (strcmp(argv[index], "-h") == 0 || strcmp(argv[index], "-help") == 0)
+ {
+ cc_print_help();
+
+ return kOk;
+ }
+
+ if (strcmp(argv[index], "-dialect") == 0)
+ {
+ if (kCompilerBackend)
+ std::cout << kCompilerBackend->Language() << "\n";
+
+ return kOk;
+ }
+
+ if (strcmp(argv[index], "-fmax-exceptions") == 0)
+ {
+ try
+ {
+ kErrorLimit = std::strtol(argv[index + 1], nullptr, 10);
+ }
+ // catch anything here
+ catch (...)
+ {
+ kErrorLimit = 0;
+ }
+
+ skip = true;
+
+ continue;
+ }
+
+ std::string err = "Unknown command: ";
+ err += argv[index];
+
+ detail::print_error(err, "cc");
+
+ continue;
+ }
+
+ kFileList.emplace_back(argv[index]);
+
+ std::string srcFile = argv[index];
+
+ if (strstr(argv[index], kExt) == nullptr)
+ {
+ if (kState.fVerbose)
+ {
+ detail::print_error(srcFile + " is not a valid C source.\n", "cc");
+ }
+
+ return 1;
+ }
+
+ if (kFactory.Compile(srcFile, kMachine) != kOk)
+ return -1;
+ }
+
+ return kOk;
+}
+
+// Last rev 8-1-24
diff --git a/Headers/UUID.hpp b/NDKKit/UUID.hpp
index 00b153b..00b153b 100644
--- a/Headers/UUID.hpp
+++ b/NDKKit/UUID.hpp
diff --git a/NDKKit/Version.hpp b/NDKKit/Version.hpp
new file mode 100644
index 0000000..38fd537
--- /dev/null
+++ b/NDKKit/Version.hpp
@@ -0,0 +1,4 @@
+#pragma once
+
+#define kDistVersion "v1.22"
+#define kDistRelease "Havok" \ No newline at end of file
diff --git a/Documentation/ASM_SPECS.TXT b/Notes/ASM specs.txt
index a0c42bf..a0c42bf 100644
--- a/Documentation/ASM_SPECS.TXT
+++ b/Notes/ASM specs.txt
diff --git a/Documentation/HAVP.TXT b/Notes/HAVP DSP.txt
index 12fcec5..12fcec5 100644
--- a/Documentation/HAVP.TXT
+++ b/Notes/HAVP DSP.txt
diff --git a/Documentation/Inside 64x0.pdf b/Notes/Inside 64x0.pdf
index bcd6782..bcd6782 100644
--- a/Documentation/Inside 64x0.pdf
+++ b/Notes/Inside 64x0.pdf
Binary files differ
diff --git a/Documentation/NOTICE.TXT b/Notes/Notice.txt
index 23691da..23691da 100644
--- a/Documentation/NOTICE.TXT
+++ b/Notes/Notice.txt
diff --git a/Documentation/VNRP.TXT b/Notes/RISC CPU.txt
index e17b494..e17b494 100644
--- a/Documentation/VNRP.TXT
+++ b/Notes/RISC CPU.txt
diff --git a/ReadMe.md b/ReadMe.md
index 2dc803a..14dfacf 100644
--- a/ReadMe.md
+++ b/ReadMe.md
@@ -1,17 +1,21 @@
-# CodeTools
+# NDKKit, C++ SDK for ZKA.
-Start by cloning the repo:
+## Installing:
+
+Start by cloning the repo.
```
git clone git@bitbucket.org:mahrouss/codetools.git
```
-and
+## Running makefiles:
+
+And then run the makefile according to your platform.
```
-make all
+make -f <platform>.make all
```
-Author: Amlal El Mahrouss
+You can now use the programs.
-##### Copyright Mahrouss Logic, all rights reserved.
+###### Copyright ZKA Technologies, all rights reserved.
diff --git a/SDK/__mpcc_exception.hxx b/SDK/__mpcc_exception.hxx
deleted file mode 100644
index 0cd439d..0000000
--- a/SDK/__mpcc_exception.hxx
+++ /dev/null
@@ -1,27 +0,0 @@
-/* -------------------------------------------
-
- Copyright Mahrouss Logic
-
-------------------------------------------- */
-
-#pragma once
-
-/// This file is an implementation of __throw* family of functions.
-
-#include <exception>
-#include <iostream>
-#include <stdexcept>
-
-namespace std
-{
- inline void __throw_general(void)
- {
- throw std::runtime_error("MPCC C++ Runtime error.");
- }
-
- inline void __throw_domain_error(const char* error)
- {
- std::cout << "MPCC C++: Domain error: " << error << "\r";
- __throw_general();
- }
-}
diff --git a/SDK/__mpcc_malloc.hxx b/SDK/__mpcc_malloc.hxx
deleted file mode 100644
index b1ee2a7..0000000
--- a/SDK/__mpcc_malloc.hxx
+++ /dev/null
@@ -1,29 +0,0 @@
-/* -------------------------------------------
-
- Copyright Mahrouss Logic
-
-------------------------------------------- */
-
-#pragma once
-
-#include <algorithm>
-
-namespace stdx
-{
-/// @brief allocate a new class.
-/// @tparam KindClass the class type to allocate.
-template <typename KindClass, typename... Args>
-inline void* allocate(Args&&... args)
-{
- return new KindClass(std::forward(args)...);
-}
-
-/// @brief free a class.
-/// @tparam KindClass the class type to allocate.
-template <typename KindClass>
-inline void release(KindClass ptr)
-{
- if (!ptr) return;
- delete ptr;
-}
-} // namespace stdx
diff --git a/Sources/64x0-cc.cc b/Sources/64x0-cc.cc
deleted file mode 100644
index c23e3c1..0000000
--- a/Sources/64x0-cc.cc
+++ /dev/null
@@ -1,1354 +0,0 @@
-/*
- * ========================================================
- *
- * cc
- * Copyright Mahrouss Logic, all rights reserved.
- *
- * ========================================================
- */
-
-/// BUGS: ?
-/// TODO:
-
-#include <Headers/AsmKit/CPU/64x0.hpp>
-#include <Headers/ParserKit.hpp>
-#include <Headers/UUID.hpp>
-#include <cstdio>
-#include <filesystem>
-#include <fstream>
-#include <iostream>
-#include <memory>
-#include <random>
-#include <string>
-#include <utility>
-#include <vector>
-
-#define kOk 0
-
-/* C driver */
-/* This is part of CodeTools C SDK. */
-/* (c) Mahrouss Logic */
-
-/// @author Amlal El Mahrouss (amlel)
-/// @file 64x0-cc.cc
-/// @brief 64x0 C Compiler.
-
-/// TODO: support structures, else if, else, . and ->
-
-/////////////////////
-
-// ANSI ESCAPE CODES
-
-/////////////////////
-
-#define kBlank "\e[0;30m"
-#define kRed "\e[0;31m"
-#define kWhite "\e[0;97m"
-
-/////////////////////////////////////
-
-// INTERNAL STUFF OF THE C COMPILER
-
-/////////////////////////////////////
-
-namespace detail {
-// \brief name to register struct.
-struct CompilerRegisterMap final {
- std::string fName;
- std::string fReg;
-};
-
-// \brief Map for C 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 fVerbose;
-};
-} // namespace detail
-
-static detail::CompilerState kState;
-static SizeType kErrorLimit = 100;
-static std::string kIfFunction = "";
-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);
- }
-
- if (kState.fLastFile != file) {
- std::cout << kRed << "[ cc ] " << kWhite
- << ((file == "cc") ? "internal compiler error "
- : ("in file, " + file))
- << kBlank << std::endl;
- std::cout << kRed << "[ cc ] " << kWhite << reason << kBlank << std::endl;
-
- kState.fLastFile = file;
- } else {
- std::cout << kRed << "[ cc ] [ " << kState.fLastFile << " ] " << kWhite
- << reason << kBlank << std::endl;
- }
-
- if (kAcceptableErrors > kErrorLimit) std::exit(3);
-
- ++kAcceptableErrors;
-}
-
-struct CompilerType final {
- std::string fName;
- std::string fValue;
-};
-} // namespace detail
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-// Target architecture.
-static int kMachine = 0;
-
-/////////////////////////////////////////
-
-// REGISTERS ACCORDING TO USED ASSEMBLER
-
-/////////////////////////////////////////
-
-static size_t kRegisterCnt = kAsmRegisterLimit;
-static size_t kStartUsable = 2;
-static size_t kUsableLimit = 15;
-static size_t kRegisterCounter = kStartUsable;
-static std::string kRegisterPrefix = kAsmRegisterPrefix;
-
-/////////////////////////////////////////
-
-// COMPILER PARSING UTILITIES/STATES.
-
-/////////////////////////////////////////
-
-static std::vector<std::string> kFileList;
-static CompilerKit::AssemblyFactory kFactory;
-static bool kInStruct = false;
-static bool kOnWhileLoop = false;
-static bool kOnForLoop = false;
-static bool kInBraces = false;
-static bool kIfFound = false;
-static size_t kBracesCount = 0UL;
-
-/* @brief C compiler backend for C */
-class CompilerBackendCLang final : public ParserKit::CompilerBackend {
- public:
- explicit CompilerBackendCLang() = default;
- ~CompilerBackendCLang() override = default;
-
- MPCC_COPY_DEFAULT(CompilerBackendCLang);
-
- std::string Check(const char *text, const char *file);
- bool Compile(const std::string &text, const char *file) override;
-
- const char *Language() override { return "64k C"; }
-};
-
-static CompilerBackendCLang *kCompilerBackend = nullptr;
-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
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-// @name Compile
-// @brief Generate MASM from a C assignement.
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-bool CompilerBackendCLang::Compile(const std::string &text, const char *file) {
- std::string textBuffer = text;
-
- bool typeFound = false;
- bool fnFound = false;
-
- // setup generator.
- std::random_device rd;
-
- auto seed_data = std::array<int, std::mt19937::state_size>{};
- std::generate(std::begin(seed_data), std::end(seed_data), std::ref(rd));
- std::seed_seq seq(std::begin(seed_data), std::end(seed_data));
- std::mt19937 generator(seq);
-
- // start parsing
- for (size_t text_index = 0; text_index < textBuffer.size(); ++text_index) {
- auto syntaxLeaf = ParserKit::SyntaxLeafList::SyntaxLeaf();
-
- auto gen = uuids::uuid_random_generator{generator};
- uuids::uuid out = gen();
-
- detail::number_cast time_off = (UInt64)out.as_bytes().data();
-
- if (!typeFound) {
- auto substr = textBuffer.substr(text_index);
- std::string match_type;
-
- 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(' '));
- }
-
- for (auto &clType : kCompilerTypes) {
- if (clType.fName == match_type) {
- match_type.clear();
-
- std::string buf;
-
- buf += clType.fValue;
- buf += ' ';
-
- if (substr.find('=') != std::string::npos) {
- break;
- }
-
- if (textBuffer.find('(') != std::string::npos) {
- syntaxLeaf.fUserValue = buf;
-
- kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
- }
-
- typeFound = true;
- break;
- }
- }
-
- break;
- }
-
- match_type += substr[y];
- }
- }
-
- if (textBuffer[text_index] == '{') {
- if (kInStruct) {
- continue;
- }
-
- kInBraces = true;
- ++kBracesCount;
-
- kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
- }
-
- // return keyword handler
- if (textBuffer[text_index] == 'r') {
- std::string return_keyword;
- return_keyword += "return";
-
- std::size_t index = 0UL;
-
- std::string value;
-
- for (size_t return_index = text_index; return_index < textBuffer.size();
- ++return_index) {
- if (textBuffer[return_index] != return_keyword[index]) {
- for (size_t value_index = return_index;
- value_index < textBuffer.size(); ++value_index) {
- if (textBuffer[value_index] == ';') break;
-
- value += textBuffer[value_index];
- }
-
- break;
- }
-
- ++index;
- }
-
- if (index == return_keyword.size()) {
- if (!value.empty()) {
- if (value.find('(') != std::string::npos) {
- value.erase(value.find('('));
- }
-
- if (!isdigit(value[value.find('(') + 2])) {
- std::string tmp = value;
- bool reg_to_reg = false;
-
- value.clear();
-
- value += " import";
- value += tmp;
- }
-
- syntaxLeaf.fUserValue = "\tldw r19, ";
-
- // make it pretty.
- if (value.find('\t') != std::string::npos)
- value.erase(value.find('\t'), 1);
-
- syntaxLeaf.fUserValue += value + "\n";
- }
-
- syntaxLeaf.fUserValue += "\tjlr";
-
- kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
-
- break;
- }
- }
-
- if (textBuffer[text_index] == 'i' && textBuffer[text_index + 1] == 'f') {
- auto expr = textBuffer.substr(text_index + 2);
- textBuffer.erase(text_index, 2);
-
- if (expr.find("{") != std::string::npos) {
- expr.erase(expr.find("{"));
- }
-
- if (expr.find("(") != std::string::npos) expr.erase(expr.find("("));
-
- if (expr.find(")") != std::string::npos) expr.erase(expr.find(")"));
-
- kIfFunction = "__MPCC_IF_PROC_";
- kIfFunction += std::to_string(time_off._Raw);
-
- syntaxLeaf.fUserValue = "\tlda r12, import ";
- syntaxLeaf.fUserValue +=
- kIfFunction +
- "\n\t#r12 = Code to jump on, r11 right cond, r10 left cond.\n\tbeq "
- "r10, r11, r12\ndword export .code64 " +
- kIfFunction + "\n";
- kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
-
- kIfFound = true;
- }
-
- // Parse expressions and instructions here.
- // what does this mean?
- // we encounter an assignment, or we reached the end of an expression.
- if (textBuffer[text_index] == '=' || textBuffer[text_index] == ';') {
- if (fnFound) continue;
- if (kIfFound) continue;
-
- if (textBuffer[text_index] == ';' && kInStruct) continue;
-
- if (textBuffer.find("typedef ") != std::string::npos) continue;
-
- if (textBuffer[text_index] == '=' && kInStruct) {
- detail::print_error("assignement of value in struct " + textBuffer,
- file);
- continue;
- }
-
- if (textBuffer[text_index] == ';' && kInStruct) {
- bool space_found_ = false;
- std::string sym;
-
- for (auto &ch : textBuffer) {
- if (ch == ' ') {
- space_found_ = true;
- }
-
- if (ch == ';') break;
-
- if (space_found_) sym.push_back(ch);
- }
-
- kState.kStructMap[kState.kStructMap.size() - 1].fOffsets.push_back(
- std::make_pair(
- kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt + 4,
- sym));
-
- kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt =
- kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt + 4;
-
- continue;
- }
-
- if (textBuffer[text_index] == '=' && kInStruct) {
- continue;
- }
-
- if (textBuffer[text_index + 1] == '=' ||
- textBuffer[text_index - 1] == '!' ||
- textBuffer[text_index - 1] == '<' ||
- textBuffer[text_index - 1] == '>') {
- continue;
- }
-
- std::string substr;
-
- if (textBuffer.find('=') != std::string::npos && kInBraces && !kIfFound) {
- if (textBuffer.find("*") != std::string::npos) {
- if (textBuffer.find("=") > textBuffer.find("*"))
- substr += "\tlda ";
- else
- substr += "\tldw ";
- } else {
- substr += "\tldw ";
- }
- } else if (textBuffer.find('=') != std::string::npos && !kInBraces) {
- substr += "stw export .data64 ";
- }
-
- int first_encountered = 0;
-
- std::string str_name;
-
- for (size_t text_index_2 = 0; text_index_2 < textBuffer.size();
- ++text_index_2) {
- if (textBuffer[text_index_2] == '\"') {
- ++text_index_2;
-
- // want to add this, so that the parser recognizes that this is a
- // string.
- substr += '"';
-
- for (; text_index_2 < textBuffer.size(); ++text_index_2) {
- if (textBuffer[text_index_2] == '\"') break;
-
- substr += textBuffer[text_index_2];
- }
- }
-
- if (textBuffer[text_index_2] == '{' || textBuffer[text_index_2] == '}')
- continue;
-
- if (textBuffer[text_index_2] == ';') {
- break;
- }
-
- if (textBuffer[text_index_2] == ' ' ||
- textBuffer[text_index_2] == '\t') {
- if (first_encountered != 2) {
- if (textBuffer[text_index] != '=' &&
- substr.find("export .data64") == std::string::npos &&
- !kInStruct)
- substr += "export .data64 ";
- }
-
- ++first_encountered;
-
- continue;
- }
-
- if (textBuffer[text_index_2] == '=') {
- if (!kInBraces) {
- substr.replace(substr.find("export .data64"),
- strlen("export .data64"), "export .zero64 ");
- }
-
- substr += ",";
- continue;
- }
-
- substr += textBuffer[text_index_2];
- }
-
- for (auto &clType : kCompilerTypes) {
- if (substr.find(clType.fName) != std::string::npos) {
- if (substr.find(clType.fName) > substr.find('"')) continue;
-
- 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 (clType.fName == "const") continue;
-
- substr.erase(substr.find(clType.fValue), clType.fValue.size());
- }
- }
-
- if (substr.find("extern") != std::string::npos) {
- substr.replace(substr.find("extern"), strlen("extern"), "import ");
-
- if (substr.find("export .data64") != std::string::npos)
- substr.erase(substr.find("export .data64"), strlen("export .data64"));
- }
-
- auto var_to_find =
- std::find_if(kCompilerVariables.cbegin(), kCompilerVariables.cend(),
- [&](detail::CompilerType type) {
- return type.fName.find(substr) != std::string::npos;
- });
-
- if (kRegisterCounter == 5 || kRegisterCounter == 6) ++kRegisterCounter;
-
- std::string reg = kAsmRegisterPrefix;
- reg += std::to_string(kRegisterCounter);
-
- if (var_to_find == kCompilerVariables.cend()) {
- ++kRegisterCounter;
-
- kState.kStackFrame.push_back({.fName = substr, .fReg = reg});
- kCompilerVariables.push_back({.fName = substr});
- }
-
- syntaxLeaf.fUserValue += substr;
- kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
-
- if (textBuffer[text_index] == '=') break;
- }
-
- // function handler.
-
- if (textBuffer[text_index] == '(' && !fnFound && !kIfFound) {
- std::string substr;
- std::string args_buffer;
- std::string args;
-
- bool type_crossed = false;
-
- for (size_t idx = textBuffer.find('(') + 1; idx < textBuffer.size();
- ++idx) {
- if (textBuffer[idx] == ',') continue;
-
- if (textBuffer[idx] == ' ') continue;
-
- if (textBuffer[idx] == ')') break;
- }
-
- for (char substr_first_index : textBuffer) {
- if (substr_first_index != ',')
- args_buffer += substr_first_index;
- else
- args_buffer += '$';
-
- 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 (!args_buffer.empty()) args += "\tldw r6, ";
-
- std::string register_type;
- std::size_t index = 7UL;
-
- while (args_buffer.find("$") != std::string::npos) {
- register_type = kRegisterPrefix;
- register_type += std::to_string(index);
-
- ++index;
-
- args_buffer.replace(args_buffer.find('$'), 1,
- "\n\tldw " + register_type + ",");
- }
-
- args += args_buffer;
- args += "\n\tlda r19, ";
- }
- }
-
- for (char _text_i : textBuffer) {
- if (_text_i == '\t' || _text_i == ' ') {
- if (!type_crossed) {
- substr.clear();
- type_crossed = true;
- }
-
- continue;
- }
-
- if (_text_i == '(') break;
-
- substr += _text_i;
- }
-
- if (kInBraces) {
- syntaxLeaf.fUserValue = args;
- syntaxLeaf.fUserValue += substr;
- syntaxLeaf.fUserValue += "\n\tjrl\n";
-
- kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
-
- fnFound = true;
- } else {
- syntaxLeaf.fUserValue.clear();
-
- syntaxLeaf.fUserValue += "export .code64 ";
-
- syntaxLeaf.fUserValue += substr;
- syntaxLeaf.fUserValue += "\n";
-
- kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
-
- fnFound = true;
- }
-
- kCompilerFunctions.push_back(textBuffer);
- }
-
- if (textBuffer[text_index] == '-' && textBuffer[text_index + 1] == '-') {
- textBuffer = textBuffer.replace(textBuffer.find("--"), strlen("--"), "");
-
- for (int _text_i = 0; _text_i < textBuffer.size(); ++_text_i) {
- if (textBuffer[_text_i] == '\t' || textBuffer[_text_i] == ' ')
- textBuffer.erase(_text_i, 1);
- }
-
- syntaxLeaf.fUserValue += "dec ";
- syntaxLeaf.fUserValue += textBuffer;
-
- kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
- break;
- }
-
- if (textBuffer[text_index] == '}') {
- kRegisterCounter = kStartUsable;
-
- --kBracesCount;
-
- if (kBracesCount < 1) {
- kInBraces = false;
- kBracesCount = 0;
- }
-
- if (kIfFound) kIfFound = false;
-
- if (kInStruct) kInStruct = false;
-
- kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
- }
-
- syntaxLeaf.fUserValue.clear();
- }
-
- auto syntaxLeaf = ParserKit::SyntaxLeafList::SyntaxLeaf();
- syntaxLeaf.fUserValue = "\n";
- kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
-
- return true;
-}
-
-static bool kShouldHaveBraces = false;
-static std::string kFnName;
-
-std::string CompilerBackendCLang::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;
-
- for (int i = 0; i < ln.size(); ++i) {
- if (isalnum(ln[i])) {
- non_ascii_found = true;
- break;
- }
- }
-
- if (kShouldHaveBraces && ln.find('{') != std::string::npos) {
- kShouldHaveBraces = false;
- }
-
- if (!non_ascii_found) return err_str;
-
- size_t string_index = 1UL;
-
- 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);
- }
-
- 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("class");
- 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;
- }
- }
- }
-
- 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;
- }
-
- keyword.push_back(ln[string_index]);
- }
-
- goto cc_next_loop;
-
- cc_check_done:
-
- // skip digit value.
- if (isdigit(keyword[0]) || keyword[0] == '"') {
- goto cc_next_loop;
- }
-
- while (keyword.find(' ') != std::string::npos)
- keyword.erase(keyword.find(' '), 1);
-
- for (auto &var : kCompilerVariables) {
- if (var.fValue.find(keyword) != std::string::npos) {
- err_str.clear();
- goto cc_next;
- }
- }
-
- 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;
- }
- }
- }
-
- cc_error_value:
- if (keyword.find("->") != std::string::npos) return err_str;
-
- if (keyword.find(".") != std::string::npos) return err_str;
-
- if (isalnum(keyword[0])) err_str += "\nUndefined value: " + keyword;
-
- return err_str;
- }
-
- cc_next_loop:
- continue;
- }
-
-cc_next:
-
- // 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 (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;
- }
- }
-
-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;
- }
-
- 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()] == '\t')
- type_not_found = false;
-
- 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;
- }
- }
-
- next:
-
- 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;
- }
-
- 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 (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[i] == '(') {
- opens.push_back(1);
- }
- }
-
- if (closes.size() != opens.size())
- err_str += "Unterminated (), here -> " + ln;
-
- bool space_found = false;
-
- for (int i = 0; i < ln.size(); ++i) {
- if (ln[i] == ')' && !space_found) {
- space_found = true;
- continue;
- }
-
- if (space_found) {
- if (ln[i] == ' ' && isalnum(ln[i + 1])) {
- err_str += "\nBad function format 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) {
- 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('}') != 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;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-/**
- * @brief C To Assembly mount-point.
- */
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-class AssemblyMountpointCLang final : public CompilerKit::AssemblyInterface {
- public:
- explicit AssemblyMountpointCLang() = default;
- ~AssemblyMountpointCLang() override = default;
-
- MPCC_COPY_DEFAULT(AssemblyMountpointCLang);
-
- [[maybe_unused]] static Int32 Arch() noexcept {
- return CompilerKit::AssemblyFactory::kArch64x0;
- }
-
- Int32 CompileToFormat(std::string &src, Int32 arch) override {
- if (arch != AssemblyMountpointCLang::Arch()) return -1;
-
- if (kCompilerBackend == nullptr) return -1;
-
- /* @brief copy contents wihtout extension */
- std::string src_file = src.data();
- std::ifstream src_fp = std::ifstream(src_file, std::ios::in);
- std::string dest;
-
- for (auto &ch : src_file) {
- if (ch == '.') {
- break;
- }
-
- dest += ch;
- }
-
- /* According to PEF ABI. */
- std::vector<const char *> exts = kAsmFileExts;
- dest += exts[4];
-
- kState.fOutputAssembly = std::make_unique<std::ofstream>(dest);
-
- auto fmt = CompilerKit::current_date();
-
- (*kState.fOutputAssembly) << "# Path: " << src_file << "\n";
- (*kState.fOutputAssembly)
- << "# Language: 64x0 Assembly (Generated from ANSI C)\n";
- (*kState.fOutputAssembly) << "# Date: " << fmt << "\n\n";
-
- ParserKit::SyntaxLeafList syntax;
-
- kState.fSyntaxTreeList.push_back(syntax);
- kState.fSyntaxTree =
- &kState.fSyntaxTreeList[kState.fSyntaxTreeList.size() - 1];
-
- std::string line_src;
-
- while (std::getline(src_fp, line_src)) {
- if (auto err = kCompilerBackend->Check(line_src.c_str(), src.data());
- err.empty()) {
- kCompilerBackend->Compile(line_src, src.data());
- } else {
- detail::print_error(err, src.data());
- }
- }
-
- 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) {
- /// TODO:
- }
- }
- }
-
- for (auto &keyword : keywords) {
- if (ParserKit::find_word(leaf.fUserValue, keyword)) {
- std::size_t cnt = 0UL;
-
- for (auto &reg : 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("import " + needle) !=
- std::string::npos) {
- std::string range = "import " + needle;
- leaf.fUserValue.replace(
- leaf.fUserValue.find("import " + needle), range.size(),
- 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");
- }
- }
- }
- }
-
- for (auto &leaf : kState.fSyntaxTree->fLeafList) {
- (*kState.fOutputAssembly) << leaf.fUserValue;
- }
-
- kState.fSyntaxTree = nullptr;
-
- kState.fOutputAssembly->flush();
- kState.fOutputAssembly.reset();
-
- return kOk;
- }
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-#include <Version.hxx>
-
-#define kPrintF printf
-#define kSplashCxx() \
- kPrintF(kWhite "cc, %s, (c) Mahrouss Logic\n", kDistVersion)
-
-static void cc_print_help() { kSplashCxx(); }
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-#define kExt ".c"
-
-MPCC_MODULE(NewOSCompilerCLang64x0) {
- 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"});
- kCompilerTypes.push_back({.fName = "*", .fValue = "offset"});
-
- bool skip = false;
-
- kFactory.Mount(new AssemblyMountpointCLang());
- kMachine = CompilerKit::AssemblyFactory::kArch64x0;
- kCompilerBackend = new CompilerBackendCLang();
-
- 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 (strcmp(argv[index], "-verbose") == 0) {
- kState.fVerbose = true;
-
- continue;
- }
-
- if (strcmp(argv[index], "-h") == 0 || strcmp(argv[index], "-help") == 0) {
- cc_print_help();
-
- return kOk;
- }
-
- if (strcmp(argv[index], "-dialect") == 0) {
- if (kCompilerBackend) std::cout << kCompilerBackend->Language() << "\n";
-
- return kOk;
- }
-
- if (strcmp(argv[index], "-fmax-exceptions") == 0) {
- try {
- kErrorLimit = std::strtol(argv[index + 1], nullptr, 10);
- }
- // catch anything here
- catch (...) {
- kErrorLimit = 0;
- }
-
- skip = true;
-
- continue;
- }
-
- std::string err = "Unknown command: ";
- err += argv[index];
-
- detail::print_error(err, "cc");
-
- continue;
- }
-
- kFileList.emplace_back(argv[index]);
-
- std::string srcFile = argv[index];
-
- if (strstr(argv[index], kExt) == nullptr) {
- if (kState.fVerbose) {
- detail::print_error(srcFile + " is not a valid C source.\n", "cc");
- }
-
- return 1;
- }
-
- if (kFactory.Compile(srcFile, kMachine) != kOk) return -1;
- }
-
- return kOk;
-}
-
-// Last rev 8-1-24
diff --git a/Sources/AsmKit.cc b/Sources/AsmKit.cc
deleted file mode 100644
index b4af817..0000000
--- a/Sources/AsmKit.cc
+++ /dev/null
@@ -1,51 +0,0 @@
-/* -------------------------------------------
-
- Copyright Mahrouss Logic
-
-------------------------------------------- */
-
-#include <Headers/AsmKit/AsmKit.hpp>
-#include <Headers/StdKit/ErrorID.hpp>
-
-/**
- * @file AsmKit.cc
- * @author Amlal El Mahrouss (amlal@mahrouss.com)
- * @brief Assembler Kit
- * @version 0.1
- * @date 2024-01-27
- *
- * @copyright Copyright (c) 2024, Mahrouss Logic
- *
- */
-
-#include <iostream>
-
-//! @file AsmKit.cpp
-//! @brief AssemblyKit source implementation.
-
-namespace CompilerKit {
-//! @brief Compile for specific format (ELF, PEF, ZBIN)
-Int32 AssemblyFactory::Compile(std::string& sourceFile,
- const Int32& arch) noexcept {
- if (sourceFile.length() < 1 || !fMounted) return MPCC_UNIMPLEMENTED;
-
- return fMounted->CompileToFormat(sourceFile, arch);
-}
-
-//! @brief mount assembly backend.
-void AssemblyFactory::Mount(AssemblyInterface* mountPtr) noexcept {
- if (mountPtr) {
- fMounted = mountPtr;
- }
-}
-
-AssemblyInterface* AssemblyFactory::Unmount() noexcept {
- auto mount_prev = fMounted;
-
- if (mount_prev) {
- fMounted = nullptr;
- }
-
- return mount_prev;
-}
-} // namespace CompilerKit
diff --git a/Sources/amd64-cplusplus.cc b/Sources/amd64-cplusplus.cc
deleted file mode 100644
index 60e6435..0000000
--- a/Sources/amd64-cplusplus.cc
+++ /dev/null
@@ -1,397 +0,0 @@
-/*
- * ========================================================
- *
- * ccplus
- * Copyright Mahrouss Logic, all rights reserved.
- *
- * ========================================================
- */
-
-/// bugs: 0
-
-#define __PK_USE_STRUCT_INSTEAD__ 1
-
-#define kPrintF printf
-
-#define kSplashCxx() \
- kPrintF(kWhite "%s\n", "Mahrouss C++ Compiler, Copyright Mahrouss Logic.")
-
-#include <Headers/AsmKit/CPU/amd64.hpp>
-#include <Headers/ParserKit.hpp>
-#include <cstdio>
-#include <filesystem>
-#include <fstream>
-#include <iostream>
-#include <memory>
-#include <string>
-#include <utility>
-#include <vector>
-
-#define kOk 0
-
-/* Mahrouss Logic C++ driver */
-/* This is part of CodeTools C++ compiler. */
-/* (c) Mahrouss Logic */
-
-// @author Amlal El Mahrouss (amlel)
-// @file cc.cc
-// @brief Optimized C++ Compiler.
-
-/////////////////////
-
-// ANSI ESCAPE CODES
-
-/////////////////////
-
-#define kBlank "\e[0;30m"
-#define kRed "\e[0;31m"
-#define kWhite "\e[0;97m"
-
-/////////////////////////////////////
-
-// INTERNAL STUFF OF THE C COMPILER
-
-/////////////////////////////////////
-
-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;
-};
-
-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 fVerbose;
-};
-} // 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);
- }
-
- 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;
-
- kState.fLastFile = file;
- } else {
- std::cout << kRed << "[ ccplus ] [ " << kState.fLastFile << " ] " << kWhite
- << reason << kBlank << std::endl;
- }
-
- if (kAcceptableErrors > kErrorLimit) std::exit(3);
-
- ++kAcceptableErrors;
-}
-
-struct CompilerType {
- std::string fName;
- std::string fValue;
-};
-} // namespace detail
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-// Target architecture.
-static int kMachine = CompilerKit::AssemblyFactory::kArchAMD64;
-
-/////////////////////////////////////////
-
-// ARGUMENTS REGISTERS (R8, R15)
-
-/////////////////////////////////////////
-
-static size_t kRegisterCnt = kAsmRegisterLimit;
-static size_t kStartUsable = 8;
-static size_t kUsableLimit = 15;
-static size_t kRegisterCounter = kStartUsable;
-static std::vector<ParserKit::CompilerKeyword> kKeywords;
-
-/////////////////////////////////////////
-
-// COMPILER PARSING UTILITIES/STATES.
-
-/////////////////////////////////////////
-
-static std::vector<std::string> kFileList;
-static CompilerKit::AssemblyFactory kFactory;
-static bool kInStruct = false;
-static bool kOnWhileLoop = false;
-static bool kOnForLoop = false;
-static bool kInBraces = false;
-static size_t kBracesCount = 0UL;
-
-/* @brief C++ compiler backend for Mahrouss Logic C++ */
-class CompilerBackendCPlusPlus final : public ParserKit::CompilerBackend {
- public:
- explicit CompilerBackendCPlusPlus() = default;
- ~CompilerBackendCPlusPlus() override = default;
-
- MPCC_COPY_DEFAULT(CompilerBackendCPlusPlus);
-
- bool Compile(const std::string& text, const char* file) override;
-
- const char* Language() override;
-};
-
-/// compiler variables
-
-static CompilerBackendCPlusPlus* 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
-
-const char* CompilerBackendCPlusPlus::Language() { return "C++"; }
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-// @name Compile
-// @brief Generate MASM from a C++ source.
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-bool CompilerBackendCPlusPlus::Compile(const std::string& text,
- const char* file) {
- if (text.empty()) return false;
-
- // if (expr)
- // int name = expr;
- // expr;
-
- std::size_t index = 0UL;
-
- std::vector<std::pair<ParserKit::CompilerKeyword, std::size_t>> keywords_list;
-
- for (auto& keyword : kKeywords) {
- while (text.find(keyword.keyword_name) != std::string::npos) {
- keywords_list.emplace_back(std::make_pair(keyword, index));
- ++index;
- }
- }
-
- // TODO: sort keywords
-
- for (auto& keyword : keywords_list) {
- auto syntax_tree = ParserKit::SyntaxLeafList::SyntaxLeaf();
-
- syntax_tree.fUserData = keyword.first;
- kState.fSyntaxTree->fLeafList.emplace_back(syntax_tree);
- }
-
- return true;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-/**
- * @brief C To Assembly mount-point.
- */
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-class AssemblyMountpointClang final : public CompilerKit::AssemblyInterface {
- public:
- explicit AssemblyMountpointClang() = default;
- ~AssemblyMountpointClang() override = default;
-
- MPCC_COPY_DEFAULT(AssemblyMountpointClang);
-
- [[maybe_unused]] static Int32 Arch() noexcept {
- return CompilerKit::AssemblyFactory::kArchAMD64;
- }
-
- Int32 CompileToFormat(std::string& src, Int32 arch) override {
- if (arch != AssemblyMountpointClang::Arch()) return -1;
-
- if (kCompilerBackend == nullptr) return -1;
-
- /* @brief copy contents wihtout extension */
- std::string src_file = src.data();
- std::ifstream src_fp = std::ifstream(src_file, std::ios::in);
- std::string dest;
-
- for (auto& ch : src_file) {
- if (ch == '.') {
- break;
- }
-
- dest += ch;
- }
-
- /* According to PEF ABI. */
-
- std::vector<const char*> exts = kAsmFileExts;
- dest += exts[3];
-
- kState.fOutputAssembly = std::make_unique<std::ofstream>(dest);
-
- auto fmt = CompilerKit::current_date();
-
- (*kState.fOutputAssembly) << "; Path: " << src_file << "\n";
- (*kState.fOutputAssembly)
- << "; Language: CodeTools assembly. (Generated from C++)\n";
- (*kState.fOutputAssembly) << "; Date: " << fmt << "\n\n";
- (*kState.fOutputAssembly) << "#bits 64\n\n#org 0x1000000"
- << "\n\n";
-
- ParserKit::SyntaxLeafList syntax;
-
- kState.fSyntaxTreeList.emplace_back(syntax);
- kState.fSyntaxTree =
- &kState.fSyntaxTreeList[kState.fSyntaxTreeList.size() - 1];
-
- std::string source;
-
- while (std::getline(src_fp, source)) {
- // Compile into an AST format.
- kCompilerBackend->Compile(source.c_str(), src.data());
- }
-
- if (kAcceptableErrors > 0) return -1;
-
- return kOk;
- }
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-static void cxx_print_help() {
- kSplashCxx();
- kPrintF("%s", "No help available, see:\r\n");
- kPrintF("%s", "www.el-mahrouss-logic.com/developer/newos/cplusplus\r\n");
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-#define kExtListCxx \
- { ".cpp", ".cxx", ".cc", ".c++", ".cp" }
-
-MPCC_MODULE(CompilerCPlusPlus) {
- bool skip = false;
-
- kFactory.Mount(new AssemblyMountpointClang());
- kCompilerBackend = new CompilerBackendCPlusPlus();
-
- for (auto index = 1UL; index < argc; ++index) {
- if (argv[index][0] == '-') {
- if (skip) {
- skip = false;
- continue;
- }
-
- if (strcmp(argv[index], "-v") == 0 ||
- strcmp(argv[index], "-version") == 0) {
- kSplashCxx();
- return kOk;
- }
-
- if (strcmp(argv[index], "-verbose") == 0) {
- kState.fVerbose = true;
-
- continue;
- }
-
- if (strcmp(argv[index], "-h") == 0 || strcmp(argv[index], "-help") == 0) {
- cxx_print_help();
-
- return kOk;
- }
-
- if (strcmp(argv[index], "-dialect") == 0) {
- if (kCompilerBackend) std::cout << kCompilerBackend->Language() << "\n";
-
- return kOk;
- }
-
- if (strcmp(argv[index], "-max-errors") == 0) {
- try {
- kErrorLimit = std::strtol(argv[index + 1], nullptr, 10);
- }
- // catch anything here
- catch (...) {
- kErrorLimit = 0;
- }
-
- skip = true;
-
- continue;
- }
-
- std::string err = "Unknown option: ";
- err += argv[index];
-
- detail::print_error(err, "ccplus");
-
- continue;
- }
-
- kFileList.emplace_back(argv[index]);
-
- std::string argv_i = argv[index];
-
- std::vector exts = kExtListCxx;
- bool found = false;
-
- for (std::string ext : exts) {
- if (argv_i.find(ext) != std::string::npos) {
- found = true;
- break;
- }
- }
-
- if (!found) {
- if (kState.fVerbose) {
- detail::print_error(argv_i + " is not a valid C++ source.\n", "ccplus");
- }
-
- return 1;
- }
-
- if (kFactory.Compile(argv_i, kMachine) != kOk) return -1;
- }
-
- return kOk;
-}
-
-// Last rev 8-1-24
diff --git a/Sources/i64asm.cc b/Sources/i64asm.cc
deleted file mode 100644
index 4f5d885..0000000
--- a/Sources/i64asm.cc
+++ /dev/null
@@ -1,1247 +0,0 @@
-/* -------------------------------------------
-
- Copyright Mahrouss Logic
-
-------------------------------------------- */
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-/// @file i64asm.cxx
-/// @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.
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-/// bugs: 0
-
-/// feature request: 1
-/// Encode registers in mov, add, xor...
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-#define __ASM_NEED_AMD64__ 1
-
-#define kAssemblerPragmaSymStr "#"
-#define kAssemblerPragmaSym '#'
-
-#include <Headers/AsmKit/CPU/amd64.hpp>
-#include <Headers/ParserKit.hpp>
-#include <Headers/StdKit/AE.hpp>
-#include <Headers/StdKit/PEF.hpp>
-#include <algorithm>
-#include <cstdlib>
-#include <filesystem>
-#include <fstream>
-#include <iostream>
-#include <memory>
-#include <vector>
-
-/////////////////////
-
-// ANSI ESCAPE CODES
-
-/////////////////////
-
-#define kBlank "\e[0;30m"
-#define kRed "\e[0;31m"
-#define kWhite "\e[0;97m"
-#define kYellow "\e[0;33m"
-
-#define kStdOut (std::cout << kWhite)
-#define kStdErr (std::cout << kRed)
-
-static char kOutputArch = CompilerKit::kPefArchAMD64;
-static Boolean kOutputAsBinary = false;
-
-static UInt32 kErrorLimit = 10;
-static UInt32 kAcceptableErrors = 0;
-
-constexpr auto cAMD64IPAlignment = 0x4U;
-
-static std::size_t kCounter = 1UL;
-
-static std::uintptr_t kOrigin = kPefBaseOrigin;
-static std::vector<std::pair<std::string, std::uintptr_t>> kOriginLabel;
-
-/// @brief keep it simple by default.
-static std::int32_t kRegisterBitWidth = 16U;
-
-static bool kVerbose = false;
-
-static std::vector<i64_byte_t> kAppBytes;
-
-static CompilerKit::AERecordHeader kCurrentRecord{
- .fName = "", .fKind = CompilerKit::kPefCode, .fSize = 0, .fOffset = 0};
-
-static std::vector<CompilerKit::AERecordHeader> kRecords;
-static std::vector<std::string> kDefinedSymbols;
-static std::vector<std::string> kUndefinedSymbols;
-
-static const std::string kUndefinedSymbol = ":UndefinedSymbol:";
-static const std::string kRelocSymbol = ":RuntimeSymbol:";
-
-// \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);
-
- 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);
-
- ++kAcceptableErrors;
-}
-
-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;
- }
-
- kStdOut << kYellow << "[ i64asm ] " << kWhite << reason << kBlank
- << std::endl;
-}
-} // namespace detail
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-// @brief AMD64 assembler entrypoint, the program/module starts here.
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-MPCC_MODULE(NewOSAssemblerAMD64) {
- //////////////// 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"};
-
- for (i64_hword_t i = 0; i < kJumpLimit; i++) {
- CpuOpcodeAMD64 code{
- .fName = opcodes_jump[i],
- .fOpcode = static_cast<i64_hword_t>(kAsmJumpOpcode + i)};
- kOpcodesAMD64.push_back(code);
- }
-
- CpuOpcodeAMD64 code{.fName = "jcxz", .fOpcode = 0xE3};
- kOpcodesAMD64.push_back(code);
-
- for (i64_hword_t i = kJumpLimitStandard; i < kJumpLimitStandardLimit; i++) {
- CpuOpcodeAMD64 code{.fName = "jmp", .fOpcode = i};
- kOpcodesAMD64.push_back(code);
- }
-
- CpuOpcodeAMD64 lahf{.fName = "lahf", .fOpcode = 0x9F};
- kOpcodesAMD64.push_back(lahf);
-
- CpuOpcodeAMD64 lds{.fName = "lds", .fOpcode = 0xC5};
- kOpcodesAMD64.push_back(lds);
-
- CpuOpcodeAMD64 lea{.fName = "lea", .fOpcode = 0x8D};
- kOpcodesAMD64.push_back(lea);
-
- CpuOpcodeAMD64 nop{.fName = "nop", .fOpcode = 0x90};
- kOpcodesAMD64.push_back(nop);
-
- //////////////// CPU OPCODES END ////////////////
-
- 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";
-
- 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;
- }
-
- if (!std::filesystem::exists(argv[i])) {
- kStdOut << "i64asm: can't open: " << argv[i] << std::endl;
- goto asm_fail_exit;
- }
-
- std::string object_output(argv[i]);
-
- for (auto &ext : kAsmFileExts) {
- if (object_output.find(ext) != std::string::npos) {
- object_output.erase(object_output.find(ext), std::strlen(ext));
- }
- }
-
- object_output += kOutputAsBinary ? kBinaryFileExt : kObjectFileExt;
-
- std::ifstream file_ptr(argv[i]);
- std::ofstream file_ptr_out(object_output, std::ofstream::binary);
-
- if (file_ptr_out.bad()) {
- if (kVerbose) {
- kStdOut << "i64asm: error: " << strerror(errno) << "\n";
- }
- }
-
- std::string line;
-
- CompilerKit::AEHeader hdr{0};
-
- memset(hdr.fPad, kAEInvalidOpcode, kAEPad);
-
- hdr.fMagic[0] = kAEMag0;
- hdr.fMagic[1] = kAEMag1;
- hdr.fSize = sizeof(CompilerKit::AEHeader);
- hdr.fArch = kOutputArch;
-
- /////////////////////////////////////////////////////////////////////////////////////////
-
- // COMPILATION LOOP
-
- /////////////////////////////////////////////////////////////////////////////////////////
-
- CompilerKit::EncoderAMD64 asm64;
-
- 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");
- }
-
- try {
- std::filesystem::remove(object_output);
- } catch (...) {
- }
-
- goto asm_fail_exit;
- }
- }
-
- if (!kOutputAsBinary) {
- if (kVerbose) {
- kStdOut << "i64asm: Writing object file...\n";
- }
-
- // this is the final step, write everything to the file.
-
- auto pos = file_ptr_out.tellp();
-
- hdr.fCount = kRecords.size() + kUndefinedSymbols.size();
-
- file_ptr_out << hdr;
-
- if (kRecords.empty()) {
- kStdErr << "i64asm: At least one record is needed to write an object "
- "file.\ni64asm: Make one using `export .code64 foo_bar`.\n";
-
- std::filesystem::remove(object_output);
- return -1;
- }
-
- kRecords[kRecords.size() - 1].fSize = kAppBytes.size();
-
- std::size_t record_count = 0UL;
-
- for (auto &rec : kRecords) {
- if (kVerbose)
- kStdOut << "i64asm: Wrote record " << rec.fName << " to file...\n";
-
- rec.fFlags |= CompilerKit::kKindRelocationAtRuntime;
- rec.fOffset = record_count;
- ++record_count;
-
- file_ptr_out << rec;
- }
-
- // increment once again, so that we won't lie about the kUndefinedSymbols.
- ++record_count;
-
- for (auto &sym : kUndefinedSymbols) {
- CompilerKit::AERecordHeader _record_hdr{0};
-
- if (kVerbose)
- kStdOut << "i64asm: Wrote symbol " << sym << " to file...\n";
-
- _record_hdr.fKind = kAEInvalidOpcode;
- _record_hdr.fSize = sym.size();
- _record_hdr.fOffset = record_count;
-
- ++record_count;
-
- memset(_record_hdr.fPad, kAEInvalidOpcode, kAEPad);
- memcpy(_record_hdr.fName, sym.c_str(), sym.size());
-
- file_ptr_out << _record_hdr;
-
- ++kCounter;
- }
-
- auto pos_end = file_ptr_out.tellp();
-
- file_ptr_out.seekp(pos);
-
- hdr.fStartCode = pos_end;
- hdr.fCodeSize = kAppBytes.size();
-
- file_ptr_out << hdr;
-
- file_ptr_out.seekp(pos_end);
- } else {
- if (kVerbose) {
- kStdOut << "i64asm: Write raw binary...\n";
- }
- }
-
- // byte from byte, we write this.
- for (auto &byte : kAppBytes) {
- if (byte == 0) continue;
-
- if (byte == 0xFF) {
- byte = 0;
- }
-
- file_ptr_out << reinterpret_cast<const char *>(&byte)[0];
- }
-
- if (kVerbose) kStdOut << "i64asm: Wrote file with program in it.\n";
-
- file_ptr_out.flush();
- file_ptr_out.close();
-
- if (kVerbose) kStdOut << "i64asm: Exit succeeded.\n";
-
- return 0;
- }
-
-asm_fail_exit:
-
- if (kVerbose) kStdOut << "i64asm: Exit failed.\n";
-
- return -1;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-// @brief Check for attributes
-// returns true if any was found.
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-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 directive in flat binary mode.", "i64asm");
- throw std::runtime_error("invalid_import_bin");
- }
-
- auto name = line.substr(line.find("import") + strlen("import") + 1);
-
- if (name.size() == 0) {
- detail::print_error("Invalid import", "ppcasm");
- throw std::runtime_error("invalid_import");
- }
-
- std::string result = std::to_string(name.size());
- result += kUndefinedSymbol;
-
- // mangle this
- for (char &j : name) {
- if (j == ' ' || j == ',') j = '$';
- }
-
- result += name;
-
- if (name.find(".code64") != std::string::npos) {
- // data is treated as code.
- kCurrentRecord.fKind = CompilerKit::kPefCode;
- } else if (name.find(".data64") != std::string::npos) {
- // no code will be executed from here.
- kCurrentRecord.fKind = CompilerKit::kPefData;
- } else if (name.find(".zero64") != 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.
-
- if (name == kPefStart) {
- kCurrentRecord.fKind = CompilerKit::kPefCode;
- }
-
- // now we can tell the code size of the previous kCurrentRecord.
-
- if (!kRecords.empty())
- kRecords[kRecords.size() - 1].fSize = kAppBytes.size();
-
- memset(kCurrentRecord.fName, 0, kAESymbolLen);
- memcpy(kCurrentRecord.fName, result.c_str(), result.size());
-
- ++kCounter;
-
- memset(kCurrentRecord.fPad, kAEInvalidOpcode, kAEPad);
-
- kRecords.emplace_back(kCurrentRecord);
-
- 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 .code64, .data64 and
- // .zero64.
- else if (ParserKit::find_word(line, "export")) {
- if (kOutputAsBinary) {
- detail::print_error("Invalid directive in flat binary mode.", "i64asm");
- throw std::runtime_error("invalid_export_bin");
- }
-
- auto name = line.substr(line.find("export") + strlen("export") + 1);
-
- std::string name_copy = name;
-
- for (char &j : name) {
- if (j == ' ') j = '$';
- }
-
- if (std::find(kDefinedSymbols.begin(), kDefinedSymbols.end(), name) !=
- kDefinedSymbols.end()) {
- detail::print_error("Symbol already defined.", "i64asm");
- throw std::runtime_error("invalid_export_bin");
- }
-
- kDefinedSymbols.push_back(name);
-
- if (name.find(".code64") != std::string::npos) {
- // data is treated as code.
-
- name_copy.erase(name_copy.find(".code64"), strlen(".code64"));
- kCurrentRecord.fKind = CompilerKit::kPefCode;
- } else if (name.find(".data64") != std::string::npos) {
- // no code will be executed from here.
-
- name_copy.erase(name_copy.find(".data64"), strlen(".data64"));
- kCurrentRecord.fKind = CompilerKit::kPefData;
- } else if (name.find(".zero64") != std::string::npos) {
- // this is a bss section.
-
- name_copy.erase(name_copy.find(".zero64"), strlen(".zero64"));
- kCurrentRecord.fKind = CompilerKit::kPefZero;
- }
-
- // this is a special case for the start stub.
- // we want this so that ld can find it.
-
- if (name == kPefStart) {
- kCurrentRecord.fKind = CompilerKit::kPefCode;
- }
-
- while (name_copy.find(" ") != std::string::npos)
- name_copy.erase(name_copy.find(" "), 1);
-
- kOriginLabel.push_back(std::make_pair(name_copy, kOrigin));
- ++kOrigin;
-
- // now we can tell the code size of the previous kCurrentRecord.
-
- if (!kRecords.empty())
- kRecords[kRecords.size() - 1].fSize = kAppBytes.size();
-
- memset(kCurrentRecord.fName, 0, kAESymbolLen);
- memcpy(kCurrentRecord.fName, name.c_str(), name.size());
-
- ++kCounter;
-
- memset(kCurrentRecord.fPad, kAEInvalidOpcode, kAEPad);
-
- kRecords.emplace_back(kCurrentRecord);
-
- return true;
- }
-
- 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 == '.') || (c == '#'));
-}
-
-bool is_valid(const std::string &str) {
- return std::find_if(str.begin(), str.end(), is_not_alnum_space) == str.end();
-}
-} // namespace detail::algorithm
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-// @brief Check for line (syntax check)
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-std::string CompilerKit::EncoderAMD64::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, kAssemblerPragmaSymStr) ||
- ParserKit::find_word(line, ";") || line[0] == kAssemblerPragmaSym) {
- 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 valid characters.\nhere -> ";
- err_str += line;
- }
- }
-
- return err_str;
- }
-
- 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.
-
- 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(','));
-
- return err_str;
- } else {
- bool nothing_on_right = true;
-
- if (line.find(',') + 1 > line.size()) {
- err_str += "\nInstruction not complete, here -> ";
- err_str += line;
-
- 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;
- }
- }
- }
- for (auto &opcodeAMD64 : kOpcodesAMD64) {
- if (ParserKit::find_word(line, opcodeAMD64.fName)) {
- return err_str;
- }
- }
-
- err_str += "\nUnrecognized instruction -> " + line;
-
- return err_str;
-}
-
-bool CompilerKit::EncoderAMD64::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 = strtol(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(
- strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16));
-
- for (char &i : num.number) {
- if (i == 0) i = 0xFF;
-
- kAppBytes.push_back(i);
- }
-
- if (kVerbose) {
- kStdOut << "i64asm: Found a base 16 number here: "
- << jump_label.substr(pos) << "\n";
- }
-
- return true;
- }
- case 'b': {
- if (auto res = strtol(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(
- strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2));
-
- 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;
-
- kAppBytes.push_back(i);
- }
-
- return true;
- }
- case 'o': {
- if (auto res = strtol(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(
- strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7));
-
- 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;
-
- kAppBytes.push_back(i);
- }
-
- return true;
- }
- default: {
- break;
- }
- }
-
- /* check for errno and stuff like that */
- if (auto res = strtol(jump_label.substr(pos).c_str(), nullptr, 10); !res) {
- if (errno != 0) {
- return false;
- }
- }
-
- CompilerKit::NumberCast64 num = CompilerKit::NumberCast64(
- strtol(jump_label.substr(pos).c_str(), nullptr, 10));
-
- for (char &i : num.number) {
- if (i == 0) i = 0xFF;
-
- kAppBytes.push_back(i);
- }
-
- if (kVerbose) {
- kStdOut << "i64asm: Found a base 10 number here: " << jump_label.substr(pos)
- << "\n";
- }
-
- return true;
-}
-
-bool CompilerKit::EncoderAMD64::WriteNumber32(const std::size_t &pos,
- std::string &jump_label) {
- if (!isdigit(jump_label[pos])) return false;
-
- switch (jump_label[pos + 1]) {
- case 'x': {
- auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16);
- res += kOrigin;
-
- if (errno != 0) {
- return false;
- }
-
- CompilerKit::NumberCast32 num = CompilerKit::NumberCast32(res);
-
- for (char &i : num.number) {
- if (i == 0) i = 0xFF;
-
- kAppBytes.push_back(i);
- }
-
- if (kVerbose) {
- kStdOut << "i64asm: Found a base 16 number here: "
- << jump_label.substr(pos) << "\n";
- }
-
- return true;
- }
- case 'b': {
- auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2);
- res += kOrigin;
-
- if (errno != 0) {
- return false;
- }
-
- CompilerKit::NumberCast32 num = CompilerKit::NumberCast32(res);
-
- 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;
-
- kAppBytes.push_back(i);
- }
-
- return true;
- }
- case 'o': {
- auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7);
- res += kOrigin;
-
- if (errno != 0) {
- return false;
- }
-
- CompilerKit::NumberCast32 num = CompilerKit::NumberCast32(res);
-
- 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;
-
- kAppBytes.push_back(i);
- }
-
- return true;
- }
- default: {
- break;
- }
- }
-
- auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 10);
- res += kOrigin;
-
- if (errno != 0) {
- return false;
- }
-
- CompilerKit::NumberCast32 num = CompilerKit::NumberCast32(res);
-
- for (char &i : num.number) {
- if (i == 0) i = 0xFF;
-
- kAppBytes.push_back(i);
- }
-
- if (kVerbose) {
- kStdOut << "i64asm: Found a base 10 number here: " << jump_label.substr(pos)
- << "\n";
- }
-
- return true;
-}
-
-bool CompilerKit::EncoderAMD64::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 = strtol(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(
- strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16));
-
- for (char &i : num.number) {
- if (i == 0) i = 0xFF;
-
- kAppBytes.push_back(i);
- }
-
- if (kVerbose) {
- kStdOut << "i64asm: Found a base 16 number here: "
- << jump_label.substr(pos) << "\n";
- }
-
- return true;
- }
- case 'b': {
- if (auto res = strtol(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(
- strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2));
-
- 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;
-
- kAppBytes.push_back(i);
- }
-
- return true;
- }
- case 'o': {
- if (auto res = strtol(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(
- strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7));
-
- 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;
-
- kAppBytes.push_back(i);
- }
-
- return true;
- }
- default: {
- break;
- }
- }
-
- /* check for errno and stuff like that */
- if (auto res = strtol(jump_label.substr(pos).c_str(), nullptr, 10); !res) {
- if (errno != 0) {
- return false;
- }
- }
-
- CompilerKit::NumberCast16 num = CompilerKit::NumberCast16(
- strtol(jump_label.substr(pos).c_str(), nullptr, 10));
-
- for (char &i : num.number) {
- if (i == 0) i = 0xFF;
-
- kAppBytes.push_back(i);
- }
-
- if (kVerbose) {
- kStdOut << "i64asm: Found a base 10 number here: " << jump_label.substr(pos)
- << "\n";
- }
-
- return true;
-}
-
-bool CompilerKit::EncoderAMD64::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 = strtol(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(
- strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16));
-
- kAppBytes.push_back(num.number);
-
- if (kVerbose) {
- kStdOut << "i64asm: Found a base 16 number here: "
- << jump_label.substr(pos) << "\n";
- }
-
- return true;
- }
- case 'b': {
- if (auto res = strtol(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(
- strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2));
-
- if (kVerbose) {
- kStdOut << "i64asm: Found a base 2 number here: "
- << jump_label.substr(pos) << "\n";
- }
-
- kAppBytes.push_back(num.number);
-
- return true;
- }
- case 'o': {
- if (auto res = strtol(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(
- strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7));
-
- if (kVerbose) {
- kStdOut << "i64asm: Found a base 8 number here: "
- << jump_label.substr(pos) << "\n";
- }
-
- kAppBytes.push_back(num.number);
-
- return true;
- }
- default: {
- break;
- }
- }
-
- /* check for errno and stuff like that */
- if (auto res = strtol(jump_label.substr(pos).c_str(), nullptr, 10); !res) {
- if (errno != 0) {
- return false;
- }
- }
-
- CompilerKit::NumberCast8 num = CompilerKit::NumberCast8(
- strtol(jump_label.substr(pos).c_str(), nullptr, 10));
-
- kAppBytes.push_back(num.number);
-
- if (kVerbose) {
- kStdOut << "i64asm: Found a base 10 number here: " << jump_label.substr(pos)
- << "\n";
- }
-
- return true;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-// @brief Read and write an instruction to the output array.
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-bool CompilerKit::EncoderAMD64::WriteLine(std::string &line,
- const std::string &file) {
- if (ParserKit::find_word(line, "export ")) return true;
-
- struct RegMapAMD64 {
- std::string fName;
- i64_byte_t fModRM;
- };
-
- std::vector<RegMapAMD64> REGISTER_LIST{
- {.fName = "ax", .fModRM = 0x0}, {.fName = "cx", .fModRM = 1},
- {.fName = "dx", .fModRM = 0x2}, {.fName = "bx", .fModRM = 3},
- {.fName = "sp", .fModRM = 0x4}, {.fName = "bp", .fModRM = 5},
- {.fName = "si", .fModRM = 0x6}, {.fName = "di", .fModRM = 7},
- {.fName = "r8", .fModRM = 8}, {.fName = "r13", .fModRM = 9},
- {.fName = "r9", .fModRM = 10}, {.fName = "r14", .fModRM = 11},
- {.fName = "r10", .fModRM = 12}, {.fName = "r15", .fModRM = 13},
- {.fName = "r11", .fModRM = 14},
- };
-
- bool foundInstruction = false;
-
- for (auto &opcodeAMD64 : kOpcodesAMD64) {
- // strict check here
- if (ParserKit::find_word(line, opcodeAMD64.fName) &&
- detail::algorithm::is_valid(line)) {
- foundInstruction = true;
- std::string name(opcodeAMD64.fName);
-
- /// Move instruction handler.
- if (name.find("mov") != std::string::npos) {
- std::string substr = line.substr(line.find(name) + name.size());
-
- uint64_t bits = kRegisterBitWidth;
-
- if (substr.find(",") == std::string::npos) {
- detail::print_error("Syntax error.", "i64asm");
- throw std::runtime_error("syntax_err");
- }
-
- bool onlyOneReg = true;
-
- std::vector<RegMapAMD64> currentRegList;
-
- for (auto &reg : REGISTER_LIST) {
- std::vector<char> regExt = {'e', 'r'};
-
- for (auto &ext : regExt) {
- std::string registerName;
-
- if (bits > 16) registerName.push_back(ext);
-
- registerName += reg.fName;
-
- while (line.find(registerName) != std::string::npos) {
- line.erase(line.find(registerName), registerName.size());
-
- if (bits == 16) {
- if (registerName[0] == 'r') {
- detail::print_error(
- "invalid size for register, current bit width is: " +
- std::to_string(kRegisterBitWidth),
- file);
- throw std::runtime_error("invalid_reg_size");
- }
- }
-
- currentRegList.push_back(
- {.fName = registerName, .fModRM = reg.fModRM});
- }
- }
- }
-
- if (currentRegList.size() > 1) onlyOneReg = false;
-
- bool hasRBasedRegs = false;
-
- if (!onlyOneReg) {
- /// very tricky to understand.
- /// this checks for a r8 through r15 register.
- if (currentRegList[0].fName[0] == 'r' ||
- currentRegList[1].fName[0] == 'r') {
- if (isdigit(currentRegList[0].fName[1]) &&
- isdigit(currentRegList[1].fName[1])) {
- kAppBytes.emplace_back(0x4d);
- hasRBasedRegs = true;
- } else if (isdigit(currentRegList[0].fName[1]) ||
- isdigit(currentRegList[1].fName[1])) {
- kAppBytes.emplace_back(0x4c);
- hasRBasedRegs = true;
- }
- }
- }
-
- if (bits == 64 || bits == 32) {
- if (!hasRBasedRegs && bits >= 32) {
- kAppBytes.emplace_back(opcodeAMD64.fOpcode);
- }
-
- kAppBytes.emplace_back(0x89);
- } else if (bits == 16) {
- if (hasRBasedRegs) {
- detail::print_error(
- "Invalid combination of operands and registers.", "i64asm");
- throw std::runtime_error("comb_op_reg");
- }
-
- kAppBytes.emplace_back(0x66);
- kAppBytes.emplace_back(0x89);
- }
-
- if (currentRegList[1].fName[0] == 'r' &&
- currentRegList[0].fName[0] == 'e') {
- detail::print_error("Invalid combination of operands and registers.",
- "i64asm");
- throw std::runtime_error("comb_op_reg");
- }
-
- if (currentRegList[0].fName[0] == 'r' &&
- currentRegList[1].fName[0] == 'e') {
- detail::print_error("Invalid combination of operands and registers.",
- "i64asm");
- throw std::runtime_error("comb_op_reg");
- }
-
- if (bits == 16) {
- if (currentRegList[0].fName[0] == 'r' ||
- currentRegList[0].fName[0] == 'e') {
- detail::print_error("Invalid combination of operands and registers.",
- "i64asm");
- throw std::runtime_error("comb_op_reg");
- }
-
- if (currentRegList[1].fName[0] == 'r' ||
- currentRegList[1].fName[0] == 'e') {
- detail::print_error("Invalid combination of operands and registers.",
- "i64asm");
- throw std::runtime_error("comb_op_reg");
- }
- } else {
- if (currentRegList[0].fName[0] != 'r' ||
- currentRegList[0].fName[0] == 'e') {
- detail::print_error("Invalid combination of operands and registers.",
- "i64asm");
- throw std::runtime_error("comb_op_reg");
- }
-
- if (currentRegList[1].fName[0] != 'r' ||
- currentRegList[1].fName[0] == 'e') {
- detail::print_error("Invalid combination of operands and registers.",
- "i64asm");
- throw std::runtime_error("comb_op_reg");
- }
- }
-
- /// encode register using the modrm encoding.
-
- auto modrm = (0x3 << 6 | currentRegList[1].fModRM << 3 |
- currentRegList[0].fModRM);
-
- kAppBytes.emplace_back(modrm);
-
- break;
- } else if (name == "int" || name == "into" || name == "intd") {
- kAppBytes.emplace_back(opcodeAMD64.fOpcode);
- this->WriteNumber8(line.find(name) + name.size() + 1, line);
-
- break;
- } else if (name == "jmp" || name == "call") {
- kAppBytes.emplace_back(opcodeAMD64.fOpcode);
-
- if (!this->WriteNumber32(line.find(name) + name.size() + 1, line)) {
- throw std::runtime_error("BUG: WriteNumber32");
- }
-
- break;
- } else {
- kAppBytes.emplace_back(opcodeAMD64.fOpcode);
-
- break;
- }
- }
- }
-
- if (line[0] == kAssemblerPragmaSym) {
- if (foundInstruction) {
- detail::print_error("Syntax error.", "i64asm");
- throw std::runtime_error("syntax_err");
- }
-
- if (line.find("bits 64") != std::string::npos) {
- kRegisterBitWidth = 64U;
- } else if (line.find("bits 32") != std::string::npos) {
- kRegisterBitWidth = 32U;
- } else if (line.find("bits 16") != std::string::npos) {
- kRegisterBitWidth = 16U;
- } else 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 << "i64asm: origin set: " << kOrigin << std::endl;
- }
-
- break;
- }
- }
- }
- }
- }
- /// write a dword
- else if (line.find(".dword") != std::string::npos) {
- this->WriteNumber32(line.find(".dword") + strlen(".dword") + 1, line);
- }
- /// write a long
- else if (line.find(".long") != std::string::npos) {
- this->WriteNumber(line.find(".long") + strlen(".long") + 1, line);
- }
- /// write a 16-bit number
- else if (line.find(".word") != std::string::npos) {
- this->WriteNumber16(line.find(".word") + strlen(".word") + 1, line);
- }
-
- kOrigin += cAMD64IPAlignment;
-
- return true;
-}
-
-// Last rev 13-1-24
diff --git a/Sources/link.cc b/Sources/link.cc
deleted file mode 100644
index c44350a..0000000
--- a/Sources/link.cc
+++ /dev/null
@@ -1,641 +0,0 @@
-/* -------------------------------------------
-
- Copyright Mahrouss Logic
-
-------------------------------------------- */
-
-/// @file link.cc
-/// @author Amlal El Mahrouss (amlel)
-/// @brief Mahrouss Linker.
-
-/// Last Rev: Sat Feb 24 CET 2024
-
-/// note: Do not look up for anything with .code64/.data64/.zero64!
-/// It will be loaded when program will start up!
-
-#include <Headers/StdKit/ErrorID.hpp>
-
-//! Assembler Kit
-#include <Headers/AsmKit/AsmKit.hpp>
-
-//! Preferred Executable Format
-#include <Headers/StdKit/PEF.hpp>
-#include <Headers/UUID.hpp>
-#include <filesystem>
-#include <random>
-#include <vector>
-
-//! Dist version
-#include <Headers/Version.hxx>
-
-//! Advanced Executable Object Format
-#include <Headers/StdKit/AE.hpp>
-
-//! C++ I/O headers.
-#include <fstream>
-#include <iostream>
-
-#define kLinkerVersion "Mahrouss Linker %s, (c) Mahrouss Logic 2024\n"
-
-#define StringCompare(DST, SRC) strcmp(DST, SRC)
-
-#define kPefNoCpu 0U
-#define kPefNoSubCpu 0U
-
-#define kWhite "\e[0;97m"
-#define kStdOut (std::cout << kWhite)
-
-#define kLinkerDefaultOrigin kPefBaseOrigin
-#define kLinkerId 0x5046FF
-#define kLinkerAbiContainer "Container:Abi:"
-
-enum { kStandardAbi = 0x5046 /* PF */ };
-
-static std::string kOutput;
-static Int32 kAbi = kStandardAbi;
-static Int32 kSubArch = kPefNoSubCpu;
-static Int32 kArch = CompilerKit::kPefArch64000;
-static Bool kFatBinaryEnable = false;
-static Bool kStartFound = false;
-static Bool kDuplicateSymbols = false;
-static Bool kVerbose = false;
-
-/* link is to be found, mld is to be found at runtime. */
-static const char *kLdDefineSymbol = ":UndefinedSymbol:";
-static const char *kLdDynamicSym = ":RuntimeSymbol:";
-
-/* object code and list. */
-static std::vector<std::string> kObjectList;
-static std::vector<char> kObjectBytes;
-
-#define kPrintF printf
-#define kLinkerSplash() kPrintF(kWhite kLinkerVersion, kDistVersion)
-
-MPCC_MODULE(NewOSLinker) {
- bool is_executable = true;
-
- /**
- * @brief parse flags and such.
- *
- */
- for (size_t i = 1; i < argc; ++i) {
- if (StringCompare(argv[i], "-h") == 0) {
- kLinkerSplash();
- 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 << "-amd64: Output as AMD64 PEF.\n";
- kStdOut << "-rv64: Output as RISC-V 64 PEF.\n";
- kStdOut << "-ppc64: Output as POWER 64 PEF.\n";
- kStdOut << "-output-file: Select output file name.\n";
-
- return 0;
- } else if (StringCompare(argv[i], "-v") == 0) {
- kLinkerSplash();
- 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], "-amd64") == 0) {
- kArch = CompilerKit::kPefArchAMD64;
-
- continue;
- } else if (StringCompare(argv[i], "-32x0") == 0) {
- kArch = CompilerKit::kPefArch32000;
-
- continue;
- } else if (StringCompare(argv[i], "-power64") == 0) {
- kArch = CompilerKit::kPefArchPowerPC;
-
- continue;
- } else if (StringCompare(argv[i], "-verbose") == 0) {
- kVerbose = true;
-
- continue;
- } else if (StringCompare(argv[i], "-shared") == 0) {
- if (kOutput.empty()) {
- continue;
- }
-
- 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 << "link: unknown flag: " << argv[i] << "\n";
- return -MPCC_EXEC_ERROR;
- }
-
- kObjectList.emplace_back(argv[i]);
-
- continue;
- }
- }
-
- if (kOutput.empty()) {
- kStdOut << "link: no output filename set." << std::endl;
- return MPCC_EXEC_ERROR;
- }
-
- // sanity check.
- if (kObjectList.empty()) {
- kStdOut << "link: no input files." << std::endl;
- return MPCC_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 << "link: no such file: " << obj << std::endl;
- return MPCC_EXEC_ERROR;
- }
- }
- }
-
- // PEF expects a valid architecture when outputing a binary.
- if (kArch == 0) {
- kStdOut << "link: no target architecture set, can't continue." << std::endl;
- return MPCC_EXEC_ERROR;
- }
-
- CompilerKit::PEFContainer pef_container{};
-
- int32_t archs = kArch;
-
- pef_container.Count = 0UL;
- pef_container.Kind = CompilerKit::kPefKindExec;
- pef_container.SubCpu = kSubArch;
- pef_container.Linker = kLinkerId; // 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.Magic[3] = kPefMagic[3];
- pef_container.Version = kPefVersion;
-
- // specify the start address, can be 0x10000
- pef_container.Start = kLinkerDefaultOrigin;
- pef_container.HdrSz = sizeof(CompilerKit::PEFContainer);
-
- std::ofstream outputFc(kOutput, std::ofstream::binary);
-
- if (outputFc.bad()) {
- if (kVerbose) {
- kStdOut << "link: error: " << strerror(errno) << "\n";
- }
-
- return -MPCC_FILE_NOT_FOUND;
- }
-
- //! Read AE to convert as PEF.
-
- std::vector<CompilerKit::PEFCommandHeader> commandHdrsList;
- 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 << "link: info: is this a FAT binary? : ";
-
- if (!kFatBinaryEnable) {
- if (kVerbose) kStdOut << "No.\n";
-
- kStdOut << "link: error: object " << i
- << " is a different kind of architecture and output isn't "
- "treated as a FAT binary."
- << std::endl;
-
- std::remove(kOutput.c_str());
- return -MPCC_FAT_ERROR;
- } else {
- if (kVerbose) {
- kStdOut << "Yes.\n";
- }
- }
- }
-
- // append arch type to archs varaible.
- archs |= ae_header.fArch;
- std::size_t cnt = ae_header.fCount;
-
- if (kVerbose)
- kStdOut << "link: object header found, record count: " << cnt << "\n";
-
- pef_container.Count = cnt;
-
- char_type *raw_ae_records =
- new char_type[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};
- size_t offsetOfData = ae_records[ae_record_index].fOffset + ae_header.fSize;
-
- 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(".code64") ==
- std::string::npos &&
- std::string(command_header.Name).find(".data64") ==
- std::string::npos &&
- std::string(command_header.Name).find(".zero64") ==
- 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(".code64") !=
- std::string::npos) {
- kStartFound = true;
- }
-
- ld_mark_header:
- command_header.Offset = offsetOfData;
- command_header.Kind = ae_records[ae_record_index].fKind;
- command_header.Size = ae_records[ae_record_index].fSize;
- command_header.Cpu = ae_header.fArch;
- command_header.SubCpu = ae_header.fSubArch;
-
- if (kVerbose) {
- kStdOut << "link: object record: "
- << ae_records[ae_record_index].fName << " was marked.\n";
-
- kStdOut << "link: object record offset: " << command_header.Offset << "\n";
- }
-
- commandHdrsList.emplace_back(command_header);
- }
-
- delete[] raw_ae_records;
-
- 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;
- }
-
- kStdOut << "link: not an object: " << i << std::endl;
- std::remove(kOutput.c_str());
-
- // don't continue, it is a fatal error.
- return -MPCC_EXEC_ERROR;
- }
-
- pef_container.Cpu = archs;
-
- outputFc << pef_container;
-
- if (kVerbose) {
- kStdOut << "link: wrote container header.\n";
- }
-
- outputFc.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)
-
- for (auto &commandHdr : commandHdrsList) {
- // check if this symbol needs to be resolved.
- if (std::string(commandHdr.Name).find(kLdDefineSymbol) !=
- std::string::npos &&
- std::string(commandHdr.Name).find(kLdDynamicSym) == std::string::npos) {
- if (kVerbose)
- kStdOut << "link: found undefined symbol: " << commandHdr.Name << "\n";
-
- if (auto it = std::find(not_found.begin(), not_found.end(),
- std::string(commandHdr.Name));
- it == not_found.end()) {
- not_found.emplace_back(commandHdr.Name);
- }
- }
-
- symbols.emplace_back(commandHdr.Name);
- }
-
- // Now try to solve these symbols.
-
- for (size_t not_found_idx = 0; not_found_idx < commandHdrsList.size();
- ++not_found_idx) {
- if (auto it = std::find(not_found.begin(), not_found.end(),
- std::string(commandHdrsList[not_found_idx].Name));
- it != not_found.end()) {
- std::string symbol_imp = *it;
-
- if (symbol_imp.find(kLdDefineSymbol) == std::string::npos) continue;
-
- // erase the lookup prefix.
- symbol_imp.erase(
- 0, symbol_imp.find(kLdDefineSymbol) + strlen(kLdDefineSymbol));
-
- // demangle everything.
- while (symbol_imp.find('$') != std::string::npos)
- symbol_imp.erase(symbol_imp.find('$'), 1);
-
- // the reason we do is because, this may not match the symbol, and we need
- // to look for other matching symbols.
- for (auto &commandHdr : commandHdrsList) {
- if (std::string(commandHdr.Name).find(symbol_imp) !=
- std::string::npos &&
- std::string(commandHdr.Name).find(kLdDefineSymbol) ==
- std::string::npos) {
- std::string undefined_symbol = commandHdr.Name;
- auto result_of_sym =
- undefined_symbol.substr(undefined_symbol.find(symbol_imp));
-
- for (int i = 0; result_of_sym[i] != 0; ++i) {
- if (result_of_sym[i] != symbol_imp[i]) goto ld_continue_search;
- }
-
- not_found.erase(it);
-
- if (kVerbose)
- kStdOut << "link: found symbol: " << commandHdr.Name << "\n";
-
- break;
- }
- }
-
- ld_continue_search:
- continue;
- }
- }
-
- // step 3: check for errors (recheck if we have those symbols.)
-
- if (!kStartFound && is_executable) {
- if (kVerbose)
- kStdOut
- << "link: undefined entrypoint: " << kPefStart << ", you may have forget to link "
- "against your compiler's runtime library.\n";
-
- kStdOut << "link: undefined entrypoint " << kPefStart
- << " for executable: " << kOutput << "\n";
- }
-
- // step 4: write all PEF commands.
-
- CompilerKit::PEFCommandHeader dateHeader{};
-
- time_t timestamp = time(nullptr);
-
- std::string timeStampStr = "Container:BuildEpoch:";
- timeStampStr += std::to_string(timestamp);
-
- strcpy(dateHeader.Name, timeStampStr.c_str());
-
- dateHeader.Flags = 0;
- dateHeader.Kind = CompilerKit::kPefZero;
- dateHeader.Offset = outputFc.tellp();
- dateHeader.Size = timeStampStr.size();
-
- commandHdrsList.push_back(dateHeader);
-
- CompilerKit::PEFCommandHeader abiHeader{};
-
- std::string abi = kLinkerAbiContainer;
-
- switch (kArch) {
- case CompilerKit::kPefArchAMD64: {
- abi += "MSFT";
- break;
- }
- case CompilerKit::kPefArchPowerPC: {
- abi += "SYSV";
- break;
- }
- case CompilerKit::kPefArch32000:
- case CompilerKit::kPefArch64000: {
- abi += "MHRA";
- break;
- }
- default: {
- abi += " IDK";
- break;
- }
- }
-
- memcpy(abiHeader.Name, abi.c_str(), abi.size());
-
- abiHeader.Size = abi.size();
- abiHeader.Offset = outputFc.tellp();
- abiHeader.Flags = 0;
- abiHeader.Kind = CompilerKit::kPefLinkerID;
-
- commandHdrsList.push_back(abiHeader);
-
- CompilerKit::PEFCommandHeader uuidHeader{};
-
- std::random_device rd;
-
- auto seedData = std::array<int, std::mt19937::state_size>{};
- std::generate(std::begin(seedData), std::end(seedData), std::ref(rd));
- std::seed_seq seq(std::begin(seedData), std::end(seedData));
- std::mt19937 generator(seq);
-
- auto gen = uuids::uuid_random_generator{generator};
- uuids::uuid id = gen();
- auto uuidStr = uuids::to_string(id);
-
- memcpy(uuidHeader.Name, "Container:GUID:4:", strlen("Container:GUID:4:"));
- memcpy(uuidHeader.Name + strlen("Container:GUID:4:"), uuidStr.c_str(),
- uuidStr.size());
-
- uuidHeader.Size = 16;
- uuidHeader.Offset = outputFc.tellp();
- uuidHeader.Flags = 0;
- uuidHeader.Kind = CompilerKit::kPefZero;
-
- commandHdrsList.push_back(uuidHeader);
-
- // prepare a symbol vector.
- std::vector<std::string> undefSymbols;
- std::vector<std::string> duplSymbols;
- std::vector<std::string> resolveSymbols;
-
- constexpr Int32 cPaddingOffset = 16;
-
- size_t previousOffset = (commandHdrsList.size() * sizeof(CompilerKit::PEFCommandHeader)) + cPaddingOffset;
-
- // Finally write down the command headers.
- // And check for any duplications
- for (size_t commandHeaderIndex = 0UL;
- commandHeaderIndex < commandHdrsList.size(); ++commandHeaderIndex) {
- if (std::string(commandHdrsList[commandHeaderIndex].Name)
- .find(kLdDefineSymbol) != std::string::npos &&
- std::string(commandHdrsList[commandHeaderIndex].Name)
- .find(kLdDynamicSym) == std::string::npos) {
- // ignore :UndefinedSymbol: headers, they do not contain code.
- continue;
- }
-
- std::string symbolName = commandHdrsList[commandHeaderIndex].Name;
-
- if (!symbolName.empty()) {
- undefSymbols.emplace_back(symbolName);
- }
-
- commandHdrsList[commandHeaderIndex].Offset += previousOffset;
- previousOffset += commandHdrsList[commandHeaderIndex].Size;
-
- std::string name = commandHdrsList[commandHeaderIndex].Name;
-
- /// so this is valid when we get to the entrypoint.
- /// it is always a code64 container. And should equal to kPefStart as well.
- /// this chunk of code updates the pef_container.Start with the updated offset.
- if (name.find(kPefStart) != std::string::npos &&
- name.find(".code64") != std::string::npos) {
- pef_container.Start = commandHdrsList[commandHeaderIndex].Offset;
- auto tellCurPos = outputFc.tellp();
-
- outputFc.seekp(0);
- outputFc << pef_container;
-
- outputFc.seekp(tellCurPos);
- }
-
- if (kVerbose) {
- kStdOut << "link: command header name: " <<
- name << "\n";
- kStdOut << "link: real address of command header content: " <<
- commandHdrsList[commandHeaderIndex].Offset << "\n";
- }
-
- outputFc << commandHdrsList[commandHeaderIndex];
-
- for (size_t subCommandHeaderIndex = 0UL;
- subCommandHeaderIndex < commandHdrsList.size();
- ++subCommandHeaderIndex) {
- if (subCommandHeaderIndex == commandHeaderIndex) continue;
-
- if (std::string(commandHdrsList[subCommandHeaderIndex].Name)
- .find(kLdDefineSymbol) != std::string::npos &&
- std::string(commandHdrsList[subCommandHeaderIndex].Name)
- .find(kLdDynamicSym) == std::string::npos) {
- if (kVerbose) {
- kStdOut << "link: ignore :UndefinedSymbol: command header...\n";
- }
-
- // ignore :UndefinedSymbol: headers, they do not contain code.
- continue;
- }
-
- auto &commandHdr = commandHdrsList[subCommandHeaderIndex];
-
- if (commandHdr.Name ==
- std::string(commandHdrsList[commandHeaderIndex].Name)) {
- if (std::find(duplSymbols.cbegin(), duplSymbols.cend(),
- commandHdr.Name) == duplSymbols.cend()) {
- duplSymbols.emplace_back(commandHdr.Name);
- }
-
- if (kVerbose)
- kStdOut << "link: found duplicate symbol: " << commandHdr.Name
- << "\n";
-
- kDuplicateSymbols = true;
- }
- }
- }
-
- if (!duplSymbols.empty()) {
- for (auto &symbol : duplSymbols) {
- kStdOut << "link: multiple symbols of " << symbol << ".\n";
- }
-
- std::remove(kOutput.c_str());
- return -MPCC_EXEC_ERROR;
- }
-
- // step 2.5: write program bytes.
-
- for (auto byte : kObjectBytes) {
- outputFc << byte;
- }
-
- if (kVerbose) kStdOut << "link: wrote contents of: " << kOutput << "\n";
-
- // step 3: check if we have those symbols
-
- std::vector<std::string> unrefSyms;
-
- for (auto &commandHdr : commandHdrsList) {
- if (auto it = std::find(not_found.begin(), not_found.end(),
- std::string(commandHdr.Name));
- it != not_found.end()) {
- unrefSyms.emplace_back(commandHdr.Name);
- }
- }
-
- if (!unrefSyms.empty()) {
- for (auto &unreferenced_symbol : unrefSyms) {
- kStdOut << "link: undefined symbol " << unreferenced_symbol << "\n";
- }
- }
-
- if (!kStartFound || kDuplicateSymbols && std::filesystem::exists(kOutput) ||
- !unrefSyms.empty()) {
- if (kVerbose)
- kStdOut << "link: file: " << kOutput
- << ", is corrupt, removing file...\n";
-
- std::remove(kOutput.c_str());
- return -MPCC_EXEC_ERROR;
- }
-
- return 0;
-}
-
-// Last rev 13-1-24
diff --git a/Sources/ppc-cc.cc b/Sources/ppc-cc.cc
deleted file mode 100644
index 44489da..0000000
--- a/Sources/ppc-cc.cc
+++ /dev/null
@@ -1,1368 +0,0 @@
-/*
- * ========================================================
- *
- * cc
- * Copyright Mahrouss Logic, all rights reserved.
- *
- * ========================================================
- */
-
-#include <Headers/AsmKit/CPU/ppc.hpp>
-#include <Headers/ParserKit.hpp>
-#include <Headers/UUID.hpp>
-#include <cstdio>
-#include <filesystem>
-#include <fstream>
-#include <iostream>
-#include <memory>
-#include <random>
-#include <string>
-#include <utility>
-#include <vector>
-
-#define kOk 0
-
-/// @author Amlal El Mahrouss (amlel)
-/// @file cc.cc
-/// @brief POWER C Compiler.
-
-/////////////////////
-
-/// ANSI ESCAPE CODES
-
-/////////////////////
-
-#define kBlank "\e[0;30m"
-#define kRed "\e[0;31m"
-#define kWhite "\e[0;97m"
-
-/////////////////////////////////////
-
-/// INTERNAL STRUCT OF THE C COMPILER
-
-/////////////////////////////////////
-
-namespace detail {
-// \brief name to register struct.
-struct CompilerRegisterMap final {
- std::string fName;
- std::string fReg;
-};
-
-// \brief Map for C structs
-// \author amlel
-struct CompilerStructMap final {
- /// 'struct::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 fVerbose;
-};
-} // namespace detail
-
-static detail::CompilerState kState;
-static SizeType kErrorLimit = 100;
-static std::string kIfFunction = "";
-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);
-
- if (kState.fLastFile != file) {
- std::cout << kRed << "[ cc ] " << kWhite
- << ((file == "cc") ? "internal compiler error "
- : ("in file, " + file))
- << kBlank << std::endl;
- std::cout << kRed << "[ cc ] " << kWhite << reason << kBlank << std::endl;
-
- kState.fLastFile = file;
- } else {
- std::cout << kRed << "[ cc ] [ " << kState.fLastFile << " ] " << kWhite
- << reason << kBlank << std::endl;
- }
-
- if (kAcceptableErrors > kErrorLimit) std::exit(3);
-
- ++kAcceptableErrors;
-}
-
-struct CompilerType final {
- std::string fName;
- std::string fValue;
-};
-} // namespace detail
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-// Target architecture.
-static int kMachine = 0;
-
-/////////////////////////////////////////
-
-// REGISTERS ACCORDING TO USED ASSEMBLER
-
-/////////////////////////////////////////
-
-static size_t kRegisterCnt = kAsmRegisterLimit;
-static size_t kStartUsable = 2;
-static size_t kUsableLimit = 15;
-static size_t kRegisterCounter = kStartUsable;
-static std::string kRegisterPrefix = kAsmRegisterPrefix;
-
-/////////////////////////////////////////
-
-// COMPILER PARSING UTILITIES/STATES.
-
-/////////////////////////////////////////
-
-static std::vector<std::string> kFileList;
-static CompilerKit::AssemblyFactory kFactory;
-static bool kInStruct = false;
-static bool kOnWhileLoop = false;
-static bool kOnForLoop = false;
-static bool kInBraces = false;
-static bool kIfFound = false;
-static size_t kBracesCount = 0UL;
-
-/* @brief C compiler backend for C */
-class CompilerBackendCLang final : public ParserKit::CompilerBackend {
- public:
- explicit CompilerBackendCLang() = default;
- ~CompilerBackendCLang() override = default;
-
- MPCC_COPY_DEFAULT(CompilerBackendCLang);
-
- std::string Check(const char *text, const char *file);
- bool Compile(const std::string &text, const char *file) override;
-
- const char *Language() override { return "POWER C"; }
-};
-
-static CompilerBackendCLang *kCompilerBackend = nullptr;
-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
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-// @name Compile
-// @brief Generate MASM from a C assignement.
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-bool CompilerBackendCLang::Compile(const std::string &text, const char *file) {
- std::string textBuffer = text;
-
- bool typeFound = false;
- bool fnFound = false;
-
- // setup generator.
- std::random_device rd;
-
- auto seed_data = std::array<int, std::mt19937::state_size>{};
- std::generate(std::begin(seed_data), std::end(seed_data), std::ref(rd));
- std::seed_seq seq(std::begin(seed_data), std::end(seed_data));
- std::mt19937 generator(seq);
-
- // start parsing
- for (size_t text_index = 0; text_index < textBuffer.size(); ++text_index) {
- auto syntaxLeaf = ParserKit::SyntaxLeafList::SyntaxLeaf();
-
- auto gen = uuids::uuid_random_generator{generator};
- uuids::uuid out = gen();
-
- detail::number_cast time_off = (UInt64)out.as_bytes().data();
-
- if (!typeFound) {
- auto substr = textBuffer.substr(text_index);
- std::string match_type;
-
- 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(' '));
- }
-
- for (auto &clType : kCompilerTypes) {
- if (clType.fName == match_type) {
- match_type.clear();
-
- std::string buf;
-
- buf += clType.fValue;
- buf += ' ';
-
- if (substr.find('=') != std::string::npos) {
- break;
- }
-
- if (textBuffer.find('(') != std::string::npos) {
- syntaxLeaf.fUserValue = buf;
-
- kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
- }
-
- typeFound = true;
- break;
- }
- }
-
- break;
- }
-
- match_type += substr[y];
- }
- }
-
- if (textBuffer[text_index] == '{') {
- if (kInStruct) {
- continue;
- }
-
- kInBraces = true;
- ++kBracesCount;
-
- kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
- }
-
- // return keyword handler
- if (textBuffer[text_index] == 'r') {
- std::string return_keyword;
- return_keyword += "return";
-
- std::size_t index = 0UL;
-
- std::string value;
-
- for (size_t return_index = text_index; return_index < textBuffer.size();
- ++return_index) {
- if (textBuffer[return_index] != return_keyword[index]) {
- for (size_t value_index = return_index;
- value_index < textBuffer.size(); ++value_index) {
- if (textBuffer[value_index] == ';') break;
-
- value += textBuffer[value_index];
- }
-
- break;
- }
-
- ++index;
- }
-
- if (index == return_keyword.size()) {
- if (!value.empty()) {
- if (value.find('(') != std::string::npos) {
- value.erase(value.find('('));
- }
-
- if (!isdigit(value[value.find('(') + 2])) {
- std::string tmp = value;
- bool reg_to_reg = false;
-
- value.clear();
-
- value += " import";
- value += tmp;
- }
-
- syntaxLeaf.fUserValue = "\tmr r31, ";
-
- // make it pretty.
- while (value.find('\t') != std::string::npos)
- value.erase(value.find('\t'), 1);
-
- while (value.find(' ') != std::string::npos)
- value.erase(value.find(' '), 1);
-
- while (value.find("import") != std::string::npos)
- value.erase(value.find("import"), strlen("import"));
-
- bool found = false;
-
- for (auto &reg : kState.kStackFrame) {
- if (value.find(reg.fName) != std::string::npos) {
- found = true;
- syntaxLeaf.fUserValue += reg.fReg;
- break;
- }
- }
-
- if (!found) syntaxLeaf.fUserValue += "r0";
- }
-
- syntaxLeaf.fUserValue += "\n\tblr";
-
- kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
-
- break;
- }
- }
-
- if (textBuffer[text_index] == 'i' && textBuffer[text_index + 1] == 'f') {
- auto expr = textBuffer.substr(text_index + 2);
- textBuffer.erase(text_index, 2);
-
- if (expr.find("{") != std::string::npos) {
- expr.erase(expr.find("{"));
- }
-
- if (expr.find("(") != std::string::npos) expr.erase(expr.find("("));
-
- if (expr.find(")") != std::string::npos) expr.erase(expr.find(")"));
-
- kIfFunction = "__MPCC_IF_PROC_";
- kIfFunction += std::to_string(time_off._Raw);
-
- syntaxLeaf.fUserValue =
- "\tcmpw "
- "r10, r11";
-
- syntaxLeaf.fUserValue += "\n\tbeq import " + kIfFunction +
- " \ndword export .code64 " + kIfFunction + "\n";
-
- kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
-
- kIfFound = true;
- }
-
- // Parse expressions and instructions here.
- // what does this mean?
- // we encounter an assignment, or we reached the end of an expression.
- if (textBuffer[text_index] == '=' || textBuffer[text_index] == ';') {
- if (fnFound) continue;
- if (kIfFound) continue;
-
- if (textBuffer[text_index] == ';' && kInStruct) continue;
-
- if (textBuffer.find("typedef ") != std::string::npos) continue;
-
- if (textBuffer[text_index] == '=' && kInStruct) {
- detail::print_error(
- "assignement of value inside a struct " + textBuffer, file);
- continue;
- }
-
- if (textBuffer[text_index] == ';' && kInStruct) {
- bool space_found_ = false;
- std::string sym;
-
- for (auto &ch : textBuffer) {
- if (ch == ' ') {
- space_found_ = true;
- }
-
- if (ch == ';') break;
-
- if (space_found_) sym.push_back(ch);
- }
-
- kState.kStructMap[kState.kStructMap.size() - 1].fOffsets.push_back(
- std::make_pair(
- kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt + 4,
- sym));
-
- kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt =
- kState.kStructMap[kState.kStructMap.size() - 1].fOffsetsCnt + 4;
-
- continue;
- }
-
- if (textBuffer[text_index] == '=' && kInStruct) {
- continue;
- }
-
- if (textBuffer[text_index + 1] == '=' ||
- textBuffer[text_index - 1] == '!' ||
- textBuffer[text_index - 1] == '<' ||
- textBuffer[text_index - 1] == '>') {
- continue;
- }
-
- std::string substr;
-
- if (textBuffer.find('=') != std::string::npos && kInBraces && !kIfFound) {
- if (textBuffer.find("*") != std::string::npos) {
- if (textBuffer.find("=") > textBuffer.find("*"))
- substr += "\tli ";
- else
- substr += "\tli ";
- } else {
- substr += "\tli ";
- }
- } else if (textBuffer.find('=') != std::string::npos && !kInBraces) {
- substr += "stw export .data64 ";
- }
-
- int first_encountered = 0;
-
- std::string str_name;
-
- for (size_t text_index_2 = 0; text_index_2 < textBuffer.size();
- ++text_index_2) {
- if (textBuffer[text_index_2] == '\"') {
- ++text_index_2;
-
- // want to add this, so that the parser recognizes that this is a
- // string.
- substr += '"';
-
- for (; text_index_2 < textBuffer.size(); ++text_index_2) {
- if (textBuffer[text_index_2] == '\"') break;
-
- substr += textBuffer[text_index_2];
- }
- }
-
- if (textBuffer[text_index_2] == '{' || textBuffer[text_index_2] == '}')
- continue;
-
- if (textBuffer[text_index_2] == ';') {
- break;
- }
-
- if (textBuffer[text_index_2] == ' ' ||
- textBuffer[text_index_2] == '\t') {
- if (first_encountered != 2) {
- if (textBuffer[text_index] != '=' &&
- substr.find("export .data64") == std::string::npos &&
- !kInStruct)
- substr += "export .data64 ";
- }
-
- ++first_encountered;
-
- continue;
- }
-
- if (textBuffer[text_index_2] == '=') {
- if (!kInBraces) {
- substr.replace(substr.find("export .data64"),
- strlen("export .data64"), "export .zero64 ");
- }
-
- substr += ",";
- continue;
- }
-
- substr += textBuffer[text_index_2];
- }
-
- for (auto &clType : kCompilerTypes) {
- if (substr.find(clType.fName) != std::string::npos) {
- if (substr.find(clType.fName) > substr.find('"')) continue;
-
- 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 (clType.fName == "const") continue;
-
- substr.erase(substr.find(clType.fValue), clType.fValue.size());
- }
- }
-
- if (substr.find("extern") != std::string::npos) {
- substr.replace(substr.find("extern"), strlen("extern"), "import ");
-
- if (substr.find("export .data64") != std::string::npos)
- substr.erase(substr.find("export .data64"), strlen("export .data64"));
- }
-
- auto var_to_find =
- std::find_if(kCompilerVariables.cbegin(), kCompilerVariables.cend(),
- [&](detail::CompilerType type) {
- return type.fName.find(substr) != std::string::npos;
- });
-
- kCompilerVariables.push_back({.fName = substr});
-
- if (textBuffer[text_index] == ';') break;
-
- std::string reg = kAsmRegisterPrefix;
-
- ++kRegisterCounter;
- reg += std::to_string(kRegisterCounter);
-
- auto newSubstr = substr.substr(substr.find(" "));
-
- std::string symbol;
-
- for (size_t start = 0; start < newSubstr.size(); ++start) {
- if (newSubstr[start] == ',') break;
-
- if (newSubstr[start] == ' ') continue;
-
- symbol += (newSubstr[start]);
- }
-
- kState.kStackFrame.push_back({.fName = symbol, .fReg = reg});
-
- syntaxLeaf.fUserValue +=
- "\n\tli " + reg + substr.substr(substr.find(','));
- kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
- }
-
- // function handler.
-
- if (textBuffer[text_index] == '(' && !fnFound && !kIfFound) {
- std::string substr;
- std::string args_buffer;
- std::string args;
-
- bool type_crossed = false;
-
- for (size_t idx = textBuffer.find('(') + 1; idx < textBuffer.size();
- ++idx) {
- if (textBuffer[idx] == ',') continue;
-
- if (textBuffer[idx] == ' ') continue;
-
- if (textBuffer[idx] == ')') break;
- }
-
- for (char substr_first_index : textBuffer) {
- if (substr_first_index != ',')
- args_buffer += substr_first_index;
- else
- args_buffer += '$';
-
- 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 (!args_buffer.empty()) args += "\tldw r6, ";
-
- std::string register_type;
- std::size_t index = 7UL;
-
- while (args_buffer.find("$") != std::string::npos) {
- register_type = kRegisterPrefix;
- register_type += std::to_string(index);
-
- ++index;
-
- args_buffer.replace(args_buffer.find('$'), 1,
- "\n\tldw " + register_type + ",");
- }
-
- args += args_buffer;
- args += "\n\tli r31, ";
- }
- }
-
- for (char _text_i : textBuffer) {
- if (_text_i == '\t' || _text_i == ' ') {
- if (!type_crossed) {
- substr.clear();
- type_crossed = true;
- }
-
- continue;
- }
-
- if (_text_i == '(') break;
-
- substr += _text_i;
- }
-
- if (kInBraces) {
- syntaxLeaf.fUserValue = args;
- syntaxLeaf.fUserValue += substr;
-
- syntaxLeaf.fUserValue += "\n\tblr\n";
-
- kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
-
- fnFound = true;
- } else {
- syntaxLeaf.fUserValue.clear();
-
- syntaxLeaf.fUserValue += "export .code64 ";
-
- syntaxLeaf.fUserValue += substr;
- syntaxLeaf.fUserValue += "\n";
-
- kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
-
- fnFound = true;
- }
-
- kCompilerFunctions.push_back(textBuffer);
- }
-
- if (textBuffer[text_index] == '-' && textBuffer[text_index + 1] == '-') {
- textBuffer = textBuffer.replace(textBuffer.find("--"), strlen("--"), "");
-
- for (int _text_i = 0; _text_i < textBuffer.size(); ++_text_i) {
- if (textBuffer[_text_i] == '\t' || textBuffer[_text_i] == ' ')
- textBuffer.erase(_text_i, 1);
- }
-
- syntaxLeaf.fUserValue += "dec ";
- syntaxLeaf.fUserValue += textBuffer;
-
- kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
- break;
- }
-
- if (textBuffer[text_index] == '}') {
- kRegisterCounter = kStartUsable;
-
- --kBracesCount;
-
- if (kBracesCount < 1) {
- kInBraces = false;
- kBracesCount = 0;
- }
-
- if (kIfFound) kIfFound = false;
-
- if (kInStruct) kInStruct = false;
-
- kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
- }
-
- syntaxLeaf.fUserValue.clear();
- }
-
- auto syntaxLeaf = ParserKit::SyntaxLeafList::SyntaxLeaf();
- syntaxLeaf.fUserValue = "\n";
- kState.fSyntaxTree->fLeafList.push_back(syntaxLeaf);
-
- return true;
-}
-
-static bool kShouldHaveBraces = false;
-static std::string kFnName;
-
-std::string CompilerBackendCLang::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;
-
- for (int i = 0; i < ln.size(); ++i) {
- if (isalnum(ln[i])) {
- non_ascii_found = true;
- break;
- }
- }
-
- if (kShouldHaveBraces && ln.find('{') != std::string::npos) {
- kShouldHaveBraces = false;
- }
-
- if (!non_ascii_found) return err_str;
-
- size_t string_index = 1UL;
-
- 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);
- }
-
- 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("class");
- 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;
- }
- }
- }
-
- 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;
- }
-
- keyword.push_back(ln[string_index]);
- }
-
- goto cc_next_loop;
-
- cc_check_done:
-
- // skip digit value.
- if (isdigit(keyword[0]) || keyword[0] == '"') {
- goto cc_next_loop;
- }
-
- while (keyword.find(' ') != std::string::npos)
- keyword.erase(keyword.find(' '), 1);
-
- for (auto &var : kCompilerVariables) {
- if (var.fValue.find(keyword) != std::string::npos) {
- err_str.clear();
- goto cc_next;
- }
- }
-
- 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;
- }
- }
- }
-
- cc_error_value:
- if (keyword.find("->") != std::string::npos) return err_str;
-
- if (keyword.find(".") != std::string::npos) return err_str;
-
- if (isalnum(keyword[0])) err_str += "\nUndefined value: " + keyword;
-
- return err_str;
- }
-
- cc_next_loop:
- continue;
- }
-
-cc_next:
-
- // 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 (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;
- }
- }
-
-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;
- }
-
- 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()] == '\t')
- type_not_found = false;
-
- 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;
- }
- }
-
- next:
-
- 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;
- }
-
- 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 (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[i] == '(') {
- opens.push_back(1);
- }
- }
-
- if (closes.size() != opens.size())
- err_str += "Unterminated (), here -> " + ln;
-
- bool space_found = false;
-
- for (int i = 0; i < ln.size(); ++i) {
- if (ln[i] == ')' && !space_found) {
- space_found = true;
- continue;
- }
-
- if (space_found) {
- if (ln[i] == ' ' && isalnum(ln[i + 1])) {
- err_str += "\nBad function format 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) {
- 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('}') != 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;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-/**
- * @brief C To Assembly mount-point.
- */
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-class AssemblyMountpointCLang final : public CompilerKit::AssemblyInterface {
- public:
- explicit AssemblyMountpointCLang() = default;
- ~AssemblyMountpointCLang() override = default;
-
- MPCC_COPY_DEFAULT(AssemblyMountpointCLang);
-
- [[maybe_unused]] static Int32 Arch() noexcept {
- return CompilerKit::AssemblyFactory::kArchPowerPC;
- }
-
- Int32 CompileToFormat(std::string &src, Int32 arch) override {
- if (arch != AssemblyMountpointCLang::Arch()) return -1;
-
- if (kCompilerBackend == nullptr) return -1;
-
- /* @brief copy contents wihtout extension */
- std::string src_file = src.data();
- std::ifstream src_fp = std::ifstream(src_file, std::ios::in);
- std::string dest;
-
- for (auto &ch : src_file) {
- if (ch == '.') {
- break;
- }
-
- dest += ch;
- }
-
- /* According to PEF ABI. */
- std::vector<const char *> exts = kAsmFileExts;
- dest += exts[4];
-
- kState.fOutputAssembly = std::make_unique<std::ofstream>(dest);
-
- auto fmt = CompilerKit::current_date();
-
- (*kState.fOutputAssembly) << "# Path: " << src_file << "\n";
- (*kState.fOutputAssembly)
- << "# Language: POWER Assembly (Generated from C)\n";
- (*kState.fOutputAssembly) << "# Date: " << fmt << "\n\n";
-
- ParserKit::SyntaxLeafList syntax;
-
- kState.fSyntaxTreeList.push_back(syntax);
- kState.fSyntaxTree =
- &kState.fSyntaxTreeList[kState.fSyntaxTreeList.size() - 1];
-
- std::string line_src;
-
- while (std::getline(src_fp, line_src)) {
- if (auto err = kCompilerBackend->Check(line_src.c_str(), src.data());
- err.empty()) {
- kCompilerBackend->Compile(line_src, src.data());
- } else {
- detail::print_error(err, src.data());
- }
- }
-
- if (kAcceptableErrors > 0) return -1;
-
- std::vector<std::string> keywords = {"ld", "stw", "add", "sub", "or"};
-
- ///
- /// 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) {
- /// TODO:
- }
- }
- }
-
- for (auto &keyword : keywords) {
- if (ParserKit::find_word(leaf.fUserValue, keyword)) {
- std::size_t cnt = 0UL;
-
- for (auto &reg : 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("import ") != std::string::npos) {
- std::string range = "import ";
- leaf.fUserValue.replace(leaf.fUserValue.find(range),
- range.size(), "");
- }
-
- 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"), "mr");
- }
- }
-
- leaf.fUserValue.replace(leaf.fUserValue.find(needle),
- needle.size(), reg.fReg);
-
- ++cnt;
- }
- }
-
- if (cnt > 1 && keyword != "mr" && keyword != "add" &&
- keyword != "dec") {
- leaf.fUserValue.replace(leaf.fUserValue.find(keyword),
- keyword.size(), "mr");
- }
- }
- }
- }
-
- for (auto &leaf : kState.fSyntaxTree->fLeafList) {
- (*kState.fOutputAssembly) << leaf.fUserValue;
- }
-
- kState.fSyntaxTree = nullptr;
-
- kState.fOutputAssembly->flush();
- kState.fOutputAssembly.reset();
-
- return kOk;
- }
-};
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-#include <Version.hxx>
-
-#define kPrintF printf
-#define kSplashCxx() \
- kPrintF(kWhite "cc, %s, (c) Mahrouss Logic\n", kDistVersion)
-
-static void cc_print_help() { kSplashCxx(); }
-
-/////////////////////////////////////////////////////////////////////////////////////////
-
-#define kExt ".c"
-
-MPCC_MODULE(NewOSCompilerCLangPowerPC) {
- 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"});
- kCompilerTypes.push_back({.fName = "*", .fValue = "offset"});
-
- bool skip = false;
-
- kFactory.Mount(new AssemblyMountpointCLang());
- kMachine = CompilerKit::AssemblyFactory::kArchPowerPC;
- kCompilerBackend = new CompilerBackendCLang();
-
- 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 (strcmp(argv[index], "-verbose") == 0) {
- kState.fVerbose = true;
-
- continue;
- }
-
- if (strcmp(argv[index], "-h") == 0 || strcmp(argv[index], "-help") == 0) {
- cc_print_help();
-
- return kOk;
- }
-
- if (strcmp(argv[index], "-dialect") == 0) {
- if (kCompilerBackend) std::cout << kCompilerBackend->Language() << "\n";
-
- return kOk;
- }
-
- if (strcmp(argv[index], "-fmax-exceptions") == 0) {
- try {
- kErrorLimit = std::strtol(argv[index + 1], nullptr, 10);
- }
- // catch anything here
- catch (...) {
- kErrorLimit = 0;
- }
-
- skip = true;
-
- continue;
- }
-
- std::string err = "Unknown command: ";
- err += argv[index];
-
- detail::print_error(err, "cc");
-
- continue;
- }
-
- kFileList.emplace_back(argv[index]);
-
- std::string srcFile = argv[index];
-
- if (strstr(argv[index], kExt) == nullptr) {
- if (kState.fVerbose) {
- detail::print_error(srcFile + " is not a valid C source.\n", "cc");
- }
-
- return 1;
- }
-
- if (kFactory.Compile(srcFile, kMachine) != kOk) return -1;
- }
-
- return kOk;
-}
-
-// Last rev 8-1-24
diff --git a/bpp.rsrc b/bpp.rsrc
deleted file mode 100644
index 255f805..0000000
--- a/bpp.rsrc
+++ /dev/null
@@ -1,27 +0,0 @@
-#include "Headers/Version.hxx"
-
-1 ICON "Icons/app-logo.ico"
-
-1 VERSIONINFO
-FILEVERSION 1,0,0,0
-PRODUCTVERSION 1,0,0,0
-BEGIN
- BLOCK "StringFileInfo"
- BEGIN
- BLOCK "080904E4"
- BEGIN
- VALUE "CompanyName", "Mahrouss-Logic"
- VALUE "FileDescription", "NewOS Assembler Preprocessor."
- VALUE "FileVersion", kDistVersion
- VALUE "InternalName", "NewPreprocessor"
- VALUE "LegalCopyright", "Mahrouss-Logic"
- VALUE "OriginalFilename", "bpp.exe"
- VALUE "ProductName", "NewPreprocessor"
- VALUE "ProductVersion", kDistVersion
- END
- END
- BLOCK "VarFileInfo"
- BEGIN
- VALUE "Translation", 0x809, 1252
- END
-END
diff --git a/i64asm.rsrc b/i64asm.rsrc
deleted file mode 100644
index 0a76070..0000000
--- a/i64asm.rsrc
+++ /dev/null
@@ -1,27 +0,0 @@
-#include "Headers/Version.hxx"
-
-1 ICON "Icons/app-logo.ico"
-
-1 VERSIONINFO
-FILEVERSION 1,0,0,0
-PRODUCTVERSION 1,0,0,0
-BEGIN
- BLOCK "StringFileInfo"
- BEGIN
- BLOCK "080904E4"
- BEGIN
- VALUE "CompanyName", "Mahrouss-Logic"
- VALUE "FileDescription", "NewOS AMD64 assembler."
- VALUE "FileVersion", kDistVersion
- VALUE "InternalName", "NewAssembler"
- VALUE "LegalCopyright", "Mahrouss-Logic"
- VALUE "OriginalFilename", "i64asm.exe"
- VALUE "ProductName", "NewAssembler"
- VALUE "ProductVersion", kDistVersion
- END
- END
- BLOCK "VarFileInfo"
- BEGIN
- VALUE "Translation", 0x809, 1252
- END
-END
diff --git a/link.rsrc b/link.rsrc
deleted file mode 100644
index 4a0ad5d..0000000
--- a/link.rsrc
+++ /dev/null
@@ -1,27 +0,0 @@
-#include "Headers/Version.hxx"
-
-1 ICON "Icons/app-logo.ico"
-
-1 VERSIONINFO
-FILEVERSION 1,0,0,0
-PRODUCTVERSION 1,0,0,0
-BEGIN
- BLOCK "StringFileInfo"
- BEGIN
- BLOCK "080904E4"
- BEGIN
- VALUE "CompanyName", "Mahrouss-Logic"
- VALUE "FileDescription", "NewOS linker."
- VALUE "FileVersion", kDistVersion
- VALUE "InternalName", "NewLinker"
- VALUE "LegalCopyright", "Mahrouss-Logic"
- VALUE "OriginalFilename", "link.exe"
- VALUE "ProductName", "NewLinker"
- VALUE "ProductVersion", kDistVersion
- END
- END
- BLOCK "VarFileInfo"
- BEGIN
- VALUE "Translation", 0x809, 1252
- END
-END
diff --git a/posix.make b/posix.make
index a00272f..832eb70 100644
--- a/posix.make
+++ b/posix.make
@@ -1,48 +1,49 @@
#
# ========================================================
#
- # MPCC
- # Copyright Mahrouss Logic, all rights reserved.
+ # NDK
+ # Copyright ZKA Technologies, all rights reserved.
#
# ========================================================
#
-COMMON_INC=-I./Headers -I./ -I./Sources/Detail
-LINK_CC=g++ -std=c++20
-LINK_SRC=Sources/link.cc
-LINK_OUTPUT=Output/link.exec
-LINK_ALT_OUTPUT=Output/64link.exec
-LINK_ALT_3_OUTPUT=Output/i64link.exec
-LINK_ALT_2_OUTPUT=Output/32link.exec
+COMMON_INC=-I./NDKKit -I./ -I./NDKKit/Sources/Detail
+LINK_CC=clang++ -std=c++20
+LINK_SRC=NDKKit/Sources/link.cxx
+LINK_OUTPUT=Output/link
+LINK_ALT_OUTPUT=Output/64link
+LINK_ALT_3_OUTPUT=Output/i64link
+LINK_ALT_2_OUTPUT=Output/32link
+LINK_ALT_4_OUTPUT=Output/ppclink
-PP_SRC=Sources/bpp.cc
-PP_OUTPUT=Output/bpp.exec
+PP_SRC=NDKKit/Sources/bpp.cxx
+PP_OUTPUT=Output/bpp
-SRC_COMMON=Sources/String.cc Sources/AsmKit.cc
+SRC_COMMON=NDKKit/Sources/String.cxx NDKKit/Sources/AssemblyFactory.cxx
# C++ Compiler (AMD64)
-AMD64_CXX_SRC=Sources/amd64-cplusplus.cc $(SRC_COMMON)
-AMD64_CXX_OUTPUT=Output/amd64-cplusplus.exec
+AMD64_CXX_SRC=NDKKit/Sources/cplusplus.cxx $(SRC_COMMON)
+AMD64_CXX_OUTPUT=Output/cplusplus
# C Compiler (POWER)
-64X0_CC_SRC=Sources/64x0-cc.cc $(SRC_COMMON)
-64X0_CC_OUTPUT=Output/64x0-cc.exec
+64X0_CC_SRC=NDKKit/Sources/64x0-cc.cxx $(SRC_COMMON)
+64X0_CC_OUTPUT=Output/64x0-cc
# C Compiler (Our own RISC)
-PPC_CC_SRC=Sources/ppc-cc.cc $(SRC_COMMON)
-PPC_CC_OUTPUT=Output/ppc-cc.exec
+PPC_CC_SRC=NDKKit/Sources/power-cc.cxx $(SRC_COMMON)
+PPC_CC_OUTPUT=Output/power-cc
# 64x0 Assembler (Our Own RISC)
-ASM_SRC=Sources/64asm.cc $(SRC_COMMON)
-ASM_OUTPUT=Output/64asm.exec
+ASM_SRC=NDKKit/Sources/64asm.cxx $(SRC_COMMON)
+ASM_OUTPUT=Output/64asm
# AMD64 Assembler (Intel CISC)
-IASM_SRC=Sources/i64asm.cc $(SRC_COMMON)
-IASM_OUTPUT=Output/i64asm.exec
+IASM_SRC=NDKKit/Sources/i64asm.cxx $(SRC_COMMON)
+IASM_OUTPUT=Output/i64asm
# Power4 Assembler (IBM RISC)
-PPCASM_SRC=Sources/ppcasm.cc $(SRC_COMMON)
-PPCASM_OUTPUT=Output/ppcasm.exec
+PPCASM_SRC=NDKKit/Sources/power-as.cxx $(SRC_COMMON)
+PPCASM_OUTPUT=Output/power-as
.PHONY: all
all: pre-processor compiler linker
@@ -67,12 +68,13 @@ linker:
cp $(LINK_OUTPUT) $(LINK_ALT_OUTPUT)
cp $(LINK_OUTPUT) $(LINK_ALT_2_OUTPUT)
cp $(LINK_OUTPUT) $(LINK_ALT_3_OUTPUT)
+ cp $(LINK_OUTPUT) $(LINK_ALT_4_OUTPUT)
.PHONY: help
help:
- @echo "Compiler - Mahrouss Compilers."
- @echo "Preprocessor - Mahrouss Preprocessors."
- @echo "linker - Mahrouss Linkers."
+ @echo "compiler - ZKA Technologies Compiler Suite."
+ @echo "pre-processor - ZKA Technologies Preprocessor Suite."
+ @echo "linker - ZKA Technologies Linkers."
@echo "clean - Clean objects and executables."
.PHONY: clean
@@ -84,6 +86,5 @@ clean:
rm -f $(IASM_OUTPUT)
rm -f $(LINK_OUTPUT)
rm -rf *.obj
- rm -rf *.exec
-
+
# Last rev 8-1-24
diff --git a/ppc-cc.rsrc b/ppc-cc.rsrc
deleted file mode 100644
index ea941f1..0000000
--- a/ppc-cc.rsrc
+++ /dev/null
@@ -1,27 +0,0 @@
-#include "Headers/Version.hxx"
-
-1 ICON "Icons/app-logo.ico"
-
-1 VERSIONINFO
-FILEVERSION 1,0,0,0
-PRODUCTVERSION 1,0,0,0
-BEGIN
- BLOCK "StringFileInfo"
- BEGIN
- BLOCK "080904E4"
- BEGIN
- VALUE "CompanyName", "Mahrouss-Logic"
- VALUE "FileDescription", "NewOS POWER C compiler."
- VALUE "FileVersion", kDistVersion
- VALUE "InternalName", "NewC"
- VALUE "LegalCopyright", "Mahrouss-Logic"
- VALUE "OriginalFilename", "ppc-cc.exe"
- VALUE "ProductName", "NewC"
- VALUE "ProductVersion", kDistVersion
- END
- END
- BLOCK "VarFileInfo"
- BEGIN
- VALUE "Translation", 0x809, 1252
- END
-END
diff --git a/ppcasm.rsrc b/ppcasm.rsrc
deleted file mode 100644
index 552479f..0000000
--- a/ppcasm.rsrc
+++ /dev/null
@@ -1,27 +0,0 @@
-#include "Headers/Version.hxx"
-
-1 ICON "Icons/app-logo.ico"
-
-1 VERSIONINFO
-FILEVERSION 1,0,0,0
-PRODUCTVERSION 1,0,0,0
-BEGIN
- BLOCK "StringFileInfo"
- BEGIN
- BLOCK "080904E4"
- BEGIN
- VALUE "CompanyName", "Mahrouss-Logic"
- VALUE "FileDescription", "NewOS POWER assembler."
- VALUE "FileVersion", kDistVersion
- VALUE "InternalName", "NewAssembler"
- VALUE "LegalCopyright", "Mahrouss-Logic"
- VALUE "OriginalFilename", "ppcasm.exe"
- VALUE "ProductName", "NewAssembler"
- VALUE "ProductVersion", kDistVersion
- END
- END
- BLOCK "VarFileInfo"
- BEGIN
- VALUE "Translation", 0x809, 1252
- END
-END
diff --git a/win64.make b/win64.make
index cbd470c..7fca096 100644
--- a/win64.make
+++ b/win64.make
@@ -1,49 +1,48 @@
#
# ========================================================
#
- # MPCC
- # Copyright Mahrouss Logic, all rights reserved.
+ # NDK
+ # Copyright ZKA Technologies, all rights reserved.
#
# ========================================================
#
-COMMON_INC=-I./Headers -I./ -I./Sources/Detail
-LINK_CC=x86_64-w64-mingw32-g++.exe -std=c++20 -Xlinker -s
-WINRES=x86_64-w64-mingw32-windres
-LINK_SRC=Sources/link.cc
+COMMON_INC=-I./NDKKit -I./ -I./NDKKit/Sources/Detail
+LINK_CC=clang++ -std=c++20 -Xlinker -s
+LINK_SRC=NDKKit/Sources/link.cxx
LINK_OUTPUT=Output/link.exe
LINK_ALT_OUTPUT=Output/64link.exe
LINK_ALT_3_OUTPUT=Output/i64link.exe
LINK_ALT_2_OUTPUT=Output/32link.exe
-PP_SRC=Sources/bpp.cc
+PP_SRC=NDKKit/Sources/bpp.cxx
PP_OUTPUT=Output/bpp.exe
-SRC_COMMON=Sources/String.cc Sources/AsmKit.cc
+SRC_COMMON=NDKKit/Sources/String.cxx NDKKit/Sources/AssemblyFactory.cxx
# C++ Compiler (AMD64)
-AMD64_CXX_SRC=Sources/amd64-cplusplus.cc $(SRC_COMMON)
-AMD64_CXX_OUTPUT=Output/amd64-cplusplus.exe
+AMD64_CXX_SRC=NDKKit/Sources/cplusplus.cxx $(SRC_COMMON)
+AMD64_CXX_OUTPUT=Output/cplusplus.exe
# C Compiler (POWER)
-64X0_CC_SRC=Sources/64x0-cc.cc $(SRC_COMMON)
+64X0_CC_SRC=NDKKit/Sources/64x0-cc.cxx $(SRC_COMMON)
64X0_CC_OUTPUT=Output/64x0-cc.exe
# C Compiler
-PPC_CC_SRC=Sources/ppc-cc.cc $(SRC_COMMON)
-PPC_CC_OUTPUT=Output/ppc-cc.exe
+PPC_CC_SRC=NDKKit/Sources/power-cc.cxx $(SRC_COMMON)
+PPC_CC_OUTPUT=Output/power-cc.exe
# 64x0 Assembler
-ASM_SRC=Sources/64asm.cc $(SRC_COMMON)
+ASM_SRC=NDKKit/Sources/64asm.cxx $(SRC_COMMON)
ASM_OUTPUT=Output/64asm.exe
# AMD64 Assembler
-IASM_SRC=Sources/i64asm.cc $(SRC_COMMON)
+IASM_SRC=NDKKit/Sources/i64asm.cxx $(SRC_COMMON)
IASM_OUTPUT=Output/i64asm.exe
# POWER Assembler
-PPCASM_SRC=Sources/ppcasm.cc $(SRC_COMMON)
-PPCASM_OUTPUT=Output/ppcasm.exe
+PPCASM_SRC=NDKKit/Sources/power-as.cxx $(SRC_COMMON)
+PPCASM_OUTPUT=Output/power-as.exe
.PHONY: all
all: pre-processor compiler linker
@@ -51,36 +50,29 @@ all: pre-processor compiler linker
.PHONY: pre-processor
pre-processor:
- $(WINRES) bpp.rsrc -O coff -o bpp.obj
- $(LINK_CC) $(COMMON_INC) $(PP_SRC) bpp.obj -o $(PP_OUTPUT)
+ $(LINK_CC) $(COMMON_INC) $(PP_SRC) -o $(PP_OUTPUT)
.PHONY: compiler
compiler:
- $(WINRES) i64asm.rsrc -O coff -o i64asm.obj
- $(WINRES) 64asm.rsrc -O coff -o 64asm.obj
- $(WINRES) ppcasm.rsrc -O coff -o ppcasm.obj
- $(WINRES) 64x0-cc.rsrc -O coff -o 64x0-cc.obj
- $(WINRES) ppc-cc.rsrc -O coff -o ppc-cc.obj
- $(LINK_CC) $(COMMON_INC) 64x0-cc.obj $(64X0_CC_SRC) -o $(64X0_CC_OUTPUT)
+ $(LINK_CC) $(COMMON_INC) $(64X0_CC_SRC) -o $(64X0_CC_OUTPUT)
$(LINK_CC) $(COMMON_INC) $(AMD64_CXX_SRC) -o $(AMD64_CXX_OUTPUT)
- $(LINK_CC) $(COMMON_INC) ppc-cc.obj $(PPC_CC_SRC) -o $(PPC_CC_OUTPUT)
- $(LINK_CC) $(COMMON_INC) i64asm.obj $(IASM_SRC) -o $(IASM_OUTPUT)
- $(LINK_CC) $(COMMON_INC) 64asm.obj $(ASM_SRC) -o $(ASM_OUTPUT)
- $(LINK_CC) $(COMMON_INC) ppcasm.obj $(PPCASM_SRC) -o $(PPCASM_OUTPUT)
+ $(LINK_CC) $(COMMON_INC) $(PPC_CC_SRC) -o $(PPC_CC_OUTPUT)
+ $(LINK_CC) $(COMMON_INC) $(IASM_SRC) -o $(IASM_OUTPUT)
+ $(LINK_CC) $(COMMON_INC) $(ASM_SRC) -o $(ASM_OUTPUT)
+ $(LINK_CC) $(COMMON_INC) $(PPCASM_SRC) -o $(PPCASM_OUTPUT)
.PHONY: linker
linker:
- $(WINRES) link.rsrc -O coff -o link.obj
- $(LINK_CC) $(COMMON_INC) link.obj $(LINK_SRC) -o $(LINK_OUTPUT)
+ $(LINK_CC) $(COMMON_INC) $(LINK_SRC) -o $(LINK_OUTPUT)
cp $(LINK_OUTPUT) $(LINK_ALT_OUTPUT)
cp $(LINK_OUTPUT) $(LINK_ALT_2_OUTPUT)
cp $(LINK_OUTPUT) $(LINK_ALT_3_OUTPUT)
.PHONY: help
help:
- @echo "Compiler - Mahrouss Compilers."
- @echo "Preprocessor - Mahrouss Preprocessors."
- @echo "linker - Mahrouss Linkers."
+ @echo "compiler - ZKA Compiler Suite."
+ @echo "pre-processor - ZKA Preprocessor Suite."
+ @echo "linker - ZKA Linkers."
@echo "clean - Clean objects and executables."
.PHONY: clean