feat: unify system status codes
This commit is contained in:
1 parent
93894b8fe5
commit
8a3ffb2be1
46 files changed
+1499
-489
No files matched your search
+92
-18
@@ -1,9 +1,12 @@
|
||||
#!/usr/bin/env python3
|
||||
# montauk-syscalls.py - Keep the TCC C API header's syscall numbers in sync
|
||||
# with the canonical syscall ABI.
|
||||
# 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_*)
|
||||
# Generated block : programs/include/libc/montauk.h (#define MTK_SYS_*)
|
||||
# kernel/src/Common/StatusCodes.hpp (enum StatusCodes)
|
||||
# Mirrors : programs/include/montauk/statuscodes.h (must match exactly)
|
||||
# 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
|
||||
@@ -13,10 +16,13 @@
|
||||
#
|
||||
# Usage:
|
||||
# montauk-syscalls.py check Verify every SYS_* has a matching MTK_SYS_* with
|
||||
# the same number. Exits non-zero on any drift.
|
||||
# Run from the build so stale headers fail loudly.
|
||||
# montauk-syscalls.py gen Rewrite the MTK_SYS_* block in montauk.h from the
|
||||
# canonical enum (numbers only; wrappers untouched).
|
||||
# the same number, and that both status code
|
||||
# mirrors match 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).
|
||||
# statuscodes.h is not generated; fix it by hand.
|
||||
|
||||
import os
|
||||
import re
|
||||
@@ -26,9 +32,13 @@ 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")
|
||||
STATUS_MIRROR = os.path.join(REPO_ROOT, "programs/include/montauk/statuscodes.h")
|
||||
|
||||
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.
|
||||
@@ -38,6 +48,11 @@ EXCLUDE = set()
|
||||
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):
|
||||
@@ -62,6 +77,43 @@ def parse_defines(text):
|
||||
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"(?<!^)(?=[A-Z])", "_", name).upper()
|
||||
|
||||
|
||||
def check_status(c_text):
|
||||
"""Print drift between the kernel enum and its two mirrors; return count."""
|
||||
canon = parse_status(STATUS_HDR)
|
||||
problems = 0
|
||||
mirror = parse_status(STATUS_MIRROR)
|
||||
if mirror != canon:
|
||||
problems += 1
|
||||
print("montauk-syscalls: DRIFT between Common/StatusCodes.hpp and "
|
||||
"montauk/statuscodes.h", file=sys.stderr)
|
||||
print(" kernel: %s" % canon, file=sys.stderr)
|
||||
print(" mirror: %s" % mirror, file=sys.stderr)
|
||||
want = {status_macro(n): v for n, v in canon}
|
||||
have = {n: int(v) for n, v in STATUS_DEF_RE.findall(c_text)}
|
||||
if want != have:
|
||||
problems += 1
|
||||
print("montauk-syscalls: DRIFT between Common/StatusCodes.hpp and "
|
||||
"MTK_STATUS_* in libc/montauk.h", file=sys.stderr)
|
||||
for n in sorted(set(want) | set(have)):
|
||||
if want.get(n) != have.get(n):
|
||||
print(" MTK_STATUS_%-22s kernel=%s montauk.h=%s"
|
||||
% (n, want.get(n), have.get(n)), file=sys.stderr)
|
||||
return problems
|
||||
|
||||
|
||||
def diff(abi, defs):
|
||||
"""Return (missing, mismatched, extra) describing drift of defs vs abi."""
|
||||
missing = sorted(n for n in abi if n not in defs)
|
||||
@@ -74,10 +126,17 @@ def diff(abi, defs):
|
||||
|
||||
def cmd_check():
|
||||
abi = parse_abi()
|
||||
defs = parse_defines(read(C_HDR))
|
||||
c_text = read(C_HDR)
|
||||
defs = parse_defines(c_text)
|
||||
missing, mismatched, extra = diff(abi, defs)
|
||||
status_problems = check_status(c_text)
|
||||
if not (missing or mismatched or extra):
|
||||
print("montauk-syscalls: OK (%d syscalls in sync)" % len(abi))
|
||||
if status_problems:
|
||||
print("\n Run 'make gen-syscalls' to regenerate MTK_STATUS_*; "
|
||||
"montauk/statuscodes.h is fixed by hand.", file=sys.stderr)
|
||||
return 1
|
||||
print("montauk-syscalls: OK (%d syscalls, %d status codes in sync)"
|
||||
% (len(abi), len(parse_status(STATUS_HDR))))
|
||||
return 0
|
||||
|
||||
print("montauk-syscalls: DRIFT between Api/Syscall.hpp and libc/montauk.h",
|
||||
@@ -115,18 +174,33 @@ def render_block(abi):
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def render_status_block(codes):
|
||||
width = max(len("MTK_STATUS_" + status_macro(n)) for n, _ in codes) + 1
|
||||
lines = [STATUS_BEGIN_MARKER,
|
||||
" Generated from Common/StatusCodes.hpp by scripts/montauk-syscalls.py.",
|
||||
" Do not edit by hand; run 'make gen-syscalls' to refresh. */"]
|
||||
for name, value in codes:
|
||||
macro = "MTK_STATUS_" + status_macro(name)
|
||||
lines.append("#define %-*s(%d)" % (width, macro, value))
|
||||
lines.append(STATUS_END_MARKER)
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def replace_block(text, begin, end, block):
|
||||
if begin not in text or end not in text:
|
||||
sys.exit("montauk-syscalls: markers not found in %s; add a "
|
||||
"%s ... %s block first" % (C_HDR, begin, end))
|
||||
start = text.index(begin)
|
||||
stop = text.index(end) + len(end)
|
||||
return text[:start] + block + text[stop:]
|
||||
|
||||
|
||||
def cmd_gen():
|
||||
abi = parse_abi()
|
||||
text = read(C_HDR)
|
||||
block = render_block(abi)
|
||||
|
||||
if BEGIN_MARKER in text and END_MARKER in text:
|
||||
start = text.index(BEGIN_MARKER)
|
||||
end = text.index(END_MARKER) + len(END_MARKER)
|
||||
new = text[:start] + block + text[end:]
|
||||
else:
|
||||
sys.exit("montauk-syscalls: markers not found in %s; add a "
|
||||
"%s ... %s block first" % (C_HDR, BEGIN_MARKER, END_MARKER))
|
||||
new = replace_block(text, BEGIN_MARKER, END_MARKER, render_block(abi))
|
||||
new = replace_block(new, STATUS_BEGIN_MARKER, STATUS_END_MARKER,
|
||||
render_status_block(parse_status(STATUS_HDR)))
|
||||
|
||||
if new == text:
|
||||
print("montauk-syscalls: montauk.h already up to date (%d syscalls)"
|
||||
|
||||
Reference in new issue
Block a user