#!/usr/bin/env python3 # montauk-syscalls.py - Keep the TCC C API header's syscall numbers and status # codes in sync with the canonical syscall ABI. # # Source of truth : programs/include/Api/Syscall.hpp (montauk::abi::SYS_*) # kernel/src/Common/StatusCodes.hpp (enum StatusCodes) # Generated blocks: programs/include/libc/montauk.h (#define MTK_SYS_*, # #define MTK_STATUS_*) # # The libc/montauk.h header is a hand-maintained, TCC-compatible C mirror of the # syscall surface. Its typed wrapper functions stay hand-written (their argument # types are not machine-derivable from the enum), but the raw "#define MTK_SYS_*" # number table is mechanical and lives between the @SYSCALLS-BEGIN/END markers, # which this script regenerates. # # Usage: # montauk-syscalls.py check Verify every SYS_* has a matching MTK_SYS_* with # the same number, and that MTK_STATUS_* matches # the kernel enum. Exits non-zero on any drift. # Run from the build so stale headers fail loudly. # montauk-syscalls.py gen Rewrite the MTK_SYS_* and MTK_STATUS_* blocks in # montauk.h (numbers only; wrappers untouched). import os import re import sys SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) REPO_ROOT = os.path.dirname(SCRIPT_DIR) ABI_HDR = os.path.join(REPO_ROOT, "programs/include/Api/Syscall.hpp") C_HDR = os.path.join(REPO_ROOT, "programs/include/libc/montauk.h") STATUS_HDR = os.path.join(REPO_ROOT, "kernel/src/Common/StatusCodes.hpp") BEGIN_MARKER = "/* @SYSCALLS-BEGIN" END_MARKER = "/* @SYSCALLS-END */" STATUS_BEGIN_MARKER = "/* @STATUS-BEGIN" STATUS_END_MARKER = "/* @STATUS-END */" # Canonical SYS_* names intentionally NOT exposed in the C API. Empty by default; # add a name here (without the SYS_ prefix) to suppress a kernel-internal syscall. EXCLUDE = set() # static constexpr uint64_t SYS_FOO = 42; ABI_RE = re.compile(r"constexpr\s+\w+\s+SYS_([A-Z0-9_]+)\s*=\s*(\d+)\s*;") # #define MTK_SYS_FOO 42 DEF_RE = re.compile(r"#define\s+MTK_SYS_([A-Z0-9_]+)\s+(\d+)\b") # enum StatusCodes { Name = -3, ... }; ENUM_RE = re.compile(r"enum\s+StatusCodes\s*\{([^}]*)\}", re.S) ENUM_ENTRY_RE = re.compile(r"([A-Za-z_]\w*)\s*=\s*(-?\d+)") # #define MTK_STATUS_FOO (-3) STATUS_DEF_RE = re.compile(r"#define\s+MTK_STATUS_([A-Z0-9_]+)\s+\(?(-?\d+)\)?") def read(path): with open(path, "r") as f: return f.read() def parse_abi(): """Return {NAME: number} for every canonical syscall, minus EXCLUDE.""" out = {} for name, num in ABI_RE.findall(read(ABI_HDR)): if name in EXCLUDE: continue out[name] = int(num) if not out: sys.exit("montauk-syscalls: no SYS_* entries found in %s" % ABI_HDR) return out def parse_defines(text): """Return {NAME: number} for every MTK_SYS_* define in the C header.""" return {name: int(num) for name, num in DEF_RE.findall(text)} def parse_status(path): """Return [(Name, value)] from the StatusCodes enum in path, in order.""" m = ENUM_RE.search(read(path)) if not m: sys.exit("montauk-syscalls: no enum StatusCodes found in %s" % path) return [(n, int(v)) for n, v in ENUM_ENTRY_RE.findall(m.group(1))] def status_macro(name): """GenericFailure -> GENERIC_FAILURE.""" return re.sub(r"(?