1#!/usr/libexec/flua 2-- 3-- SPDX-License-Identifier: BSD-2-Clause 4-- 5-- Copyright (c) 2026 Warner Losh <imp@bsdimp.com> 6-- 7 8-- Setup to be a module, or ran as its own script. 9local syscall_json = {} 10local script = not pcall(debug.getlocal, 4, 1) -- TRUE if script. 11if script then 12 -- Add library root to the package path. 13 local path = arg[0]:gsub("/[^/]+.lua$", "") 14 package.path = package.path .. ";" .. path .. "/../?.lua" 15end 16 17local FreeBSDSyscall = require("core.freebsd-syscall") 18local ucl = require("ucl") 19 20-- Convert the type flags set (table with flag=true entries) to a sorted list. 21local function flagsToList(typetbl) 22 local flags = {} 23 for k, _ in pairs(typetbl) do 24 table.insert(flags, k) 25 end 26 table.sort(flags) 27 return flags 28end 29 30-- Convert a single syscall object to a plain table suitable for JSON export. 31-- Much of the data is available only as a method call. 32local function syscallToTable(v) 33 local entry = { 34 num = v.num, 35 name = v.name or "", 36 alias = v.alias or "", 37 audit = v.audit or "", 38 flags = flagsToList(v.type), 39 compat_level = v:compatLevel(), 40 compat_prefix = v:compatPrefix(), 41 symbol = v:symbol(), 42 rettype = v.rettype or "int", 43 cap = v.cap or "0", 44 thr = v.thr or "SY_THR_STATIC", 45 changes_abi = v.changes_abi or false, 46 noproto = v.noproto or false, 47 args_size = v.args_size or "0", 48 arg_alias = v.arg_alias or "", 49 } 50 51 -- Export arguments with annotations. 52 local args = {} 53 if v.args ~= nil then 54 for _, a in ipairs(v.args) do 55 arg = { 56 type = a.type, 57 name = a.name, 58 } 59 if a.annotation ~= nil and a.annotation ~= "" then 60 arg.annotation = a.annotation 61 end 62 table.insert(args, arg) 63 end 64 end 65 entry.args = args 66 67 -- Export altname/alttag/rettype if present (loadable syscalls). 68 if v.altname ~= nil then 69 entry.altname = v.altname 70 end 71 if v.alttag ~= nil then 72 entry.alttag = v.alttag 73 end 74 75 return entry 76end 77 78function syscall_json.generate(tbl, config) 79 -- Build the syscalls array. 80 local syscalls = {} 81 for _, v in pairs(tbl.syscalls) do 82 table.insert(syscalls, syscallToTable(v)) 83 end 84 85 -- Build the structs data into a nicer structure 86 local structs = {} 87 if tbl.structs ~= nil then 88 for k, _ in pairs(tbl.structs) do 89 table.insert(structs, k) 90 end 91 table.sort(structs) 92 end 93 94 local root = { 95 syscalls = syscalls, 96 structs = structs, 97 } 98 99 local json = ucl.to_json(root) 100 101 -- Write to stdout. 102 io.write(json) 103 io.write("\n") 104end 105 106-- Entry of script: 107if script then 108 local config = require("config") 109 110 if #arg < 1 or #arg > 2 then 111 error("usage: " .. arg[0] .. " syscall.master [config]") 112 end 113 114 local sysfile, configfile = arg[1], arg[2] 115 116 config.merge(configfile) 117 config.mergeCompat() 118 119 -- The parsed system call table. 120 local tbl = FreeBSDSyscall:new{sysfile = sysfile, config = config} 121 122 syscall_json.generate(tbl, config) 123end 124 125-- Return the module. 126return syscall_json 127