import sys
import re
import os
ignored_header_filenames = [
"dosasl.h",
"dosextens.h",
"ansiio.h",
"libraries.h",
"ports.h",
"semaphores.h",
"mathffp.h",
"mathieeedp.h",
"mathieeesp.h",
"memory.h",
"copper.h",
"gels.h",
"reaction_macros.h",
"reaction_prefs.h",
]
ignored_names = [
"FOREVER", "NOT",
"INCLUDE_VERSION", "LIBRARY_MINIMUM",
"GLOBAL", "IMPORT", "STATIC", "REGISTER", "VOID", "CONST",
"BBID_DOS", "BBID_KICK",
"GetColorEnd", "GetFileEnd", "GetFontEnd", "GetScreenModeEnd", "EndDateBrowser", "End",
"PI", "TWO_PI", "PI2", "PI4", "E", "LOG10", "FPTEN", "FPONE", "FPHALF", "FPZERO",
"LCLABEL_NOLABEL",
"StartHLayout", "StartVLayout", "VCentered", "TAligned", "BAligned", "HCentered", "LAligned",
"RAligned", "EvenSized",
"ie_X", "ie_Y", "ie_EventAddress", "ie_Prev1DownCode", "ie_Prev1DownQual", "ie_Prev2DownCode",
"ie_Prev2DownQual", "du_Flags", "lh_Node", "pd_PIOR0", "pd_SIOR0", "pd_PIOR1", "pd_SIOR1",
"dfh_TagList",
"PRT_STDARGS",
"lbs_Reverse",
"ChunkyToPlanarPtr",
"tf_Extension",
"opAddMember",
"rf_File", "rf_Dir", "rf_LeftEdge", "rf_TopEdge", "rf_Width", "rf_Height", "rf_NumArgs",
"rf_ArgList", "rf_UserData", "rf_Pat",
"NM_BARLABEL",
"TAG_USER", "io_HighOffset"
]
ignored_values = [
"NewObject(",
"sizeof(",
"(sizeof",
"((struct",
"custom.dmacon",
"custom.intena",
"((void)(custom.dmacon",
"((void)(custom.intena",
]
if len(sys.argv) < 3:
print(f"Usage: {sys.argv[0]} bindings.rs headerfile1.h [headerfile2.h] ...")
exit(1)
binding_consts = {}
bfilename = sys.argv[1]
with open(bfilename, 'r') as file:
for line_number, line in enumerate(file):
if line.startswith("pub const "):
name = line.replace("pub const ", "").split(":")[0]
binding_consts[name] = { "line": line, "line_number": line_number }
print("/* automatically generated by the amiga-sys tools */\n")
print("use crate::*;\n")
print("const fn MAKE_ID(c1: char, c2: char, c3: char, c4: char) -> u32 {")
print(" ((c1 as u32) << 24) | ((c2 as u32) << 16) | ((c3 as u32) << 8) | (c4 as u32)")
print("}")
print("const fn MAKE_SID(c1: char, c2: char, c3: char, c4: char) -> u32 {")
print(" ((c1 as u32) << 24) | ((c2 as u32) << 16) | ((c3 as u32) << 8) | (c4 as u32)")
print("}")
print("pub const TAG_USER: u32 = 1 << 31;")
print("pub const BBID_DOS: [u8; 4] = [ b'D', b'O', b'S', 0 ];")
print("pub const BBID_KICK: [u8; 4] = [ b'K', b'I', b'C', b'K' ];")
used_names = []
for hfilename in sys.argv[2:]:
short_hfilename = os.path.basename(hfilename)
if short_hfilename in ignored_header_filenames:
continue
with open(hfilename, 'r', encoding='iso-8859-1') as file:
for line_number, line in enumerate(file):
line = line.strip()
if not line.startswith("#define"):
continue
def_name_value = line.replace("#define", "").replace("\t", " ").replace("\n", "")
def_name_value = def_name_value.split("/*")[0].split("//")[0]
parts = def_name_value.strip().split(" ", 1)
if len(parts) < 2:
continue
name = parts[0].strip()
value = parts[1].strip()
if "(" in name:
continue
for iv in ignored_values:
if value.startswith(iv):
name = "VOID" if name in ignored_names:
continue
if name in binding_consts or name in used_names:
continue
if value.startswith("(") and value.endswith(")"):
value = value[1:-1]
if re.findall(r'[0-9]L$', value):
value = value[:-1]
if re.findall(r'[0-9]L;$', value):
value = value[:-2]
if value == "(long)1<<SIGBREAKB_CTRL_F":
value = value[6:]
print(f"pub const {name}: u32 = {value};")
used_names.append(name)