// Generate syscall numbers and status codes from the C++ headers so Rust // never becomes another hand-maintained copy of the syscall table. // // programs/include/Api/Syscall.hpp -> pub const SYS_*: u64 // kernel/src/Common/StatusCodes.hpp -> pub enum Status (positive values, // matching montauk/statuscodes.h) use std::env; use std::fs; use std::path::PathBuf; fn main() { let manifest = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()); let repo = manifest.join("../../.."); let syscall_hpp = repo.join("programs/include/Api/Syscall.hpp"); let status_hpp = repo.join("kernel/src/Common/StatusCodes.hpp"); println!("cargo:rerun-if-changed={}", syscall_hpp.display()); println!("cargo:rerun-if-changed={}", status_hpp.display()); let mut out = String::from("// @generated by montauk-rt/build.rs - do not edit.\n\n"); // static constexpr uint64_t SYS_NAME = 123; (decimal literals only) let syscalls = fs::read_to_string(&syscall_hpp).expect("read Syscall.hpp"); let mut count = 0; for line in syscalls.lines() { let line = line.trim(); let Some(rest) = line.strip_prefix("static constexpr uint64_t SYS_") else { continue }; let Some((name, value)) = rest.split_once('=') else { continue }; let value = value.split(';').next().unwrap_or("").trim(); if value.is_empty() || !value.bytes().all(|b| b.is_ascii_digit()) { continue; } out.push_str(&format!("pub const SYS_{}: u64 = {};\n", name.trim(), value)); count += 1; } assert!(count > 100, "parsed only {count} syscalls from {}", syscall_hpp.display()); // enum StatusCodes { Success = 0, GenericFailure = -1, ... }; let status = fs::read_to_string(&status_hpp).expect("read StatusCodes.hpp"); let body = status .split_once("enum StatusCodes") .and_then(|(_, rest)| rest.split_once('{')) .and_then(|(_, rest)| rest.split_once('}')) .map(|(body, _)| body) .expect("enum StatusCodes not found"); out.push_str("\n/// Kernel status codes, stored positive like montauk/statuscodes.h.\n"); out.push_str("/// The kernel returns them negated; see [`Status::from_result`].\n"); out.push_str("#[derive(Clone, Copy, Debug, PartialEq, Eq)]\n#[repr(i32)]\npub enum Status {\n"); let mut variants = Vec::new(); for entry in body.split(',') { let entry = entry.split("//").next().unwrap_or("").trim(); let Some((name, value)) = entry.split_once('=') else { continue }; let value: i32 = value.trim().parse().expect("status value"); out.push_str(&format!(" {} = {},\n", name.trim(), -value)); variants.push((name.trim().to_string(), -value)); } out.push_str("}\n\nimpl Status {\n pub const fn from_code(code: i32) -> Status {\n match code {\n"); for (name, value) in &variants { out.push_str(&format!(" {} => Status::{},\n", value, name)); } out.push_str(" _ => Status::GenericFailure,\n }\n }\n}\n"); let dest = PathBuf::from(env::var("OUT_DIR").unwrap()).join("abi.rs"); fs::write(dest, out).expect("write abi.rs"); }