1-- 2-- SPDX-License-Identifier: BSD-2-Clause 3-- 4-- Copyright (c) 2024 Tyler Baxter <agge@FreeBSD.org> 5-- Copyright (c) 2023 Warner Losh <imp@bsdimp.com> 6-- Copyright (c) 2019 Kyle Evans <kevans@FreeBSD.org> 7-- 8 9local syscall = require("core.syscall") 10local util = require("tools.util") 11 12local FreeBSDSyscall = {} 13 14FreeBSDSyscall.__index = FreeBSDSyscall 15 16-- For each compat option in the provided config table, process them and insert 17-- them into known_flags for class syscall. 18function FreeBSDSyscall:processCompat() 19 for _, v in pairs(self.config.compat_options) do 20 if v.stdcompat ~= nil then 21 local stdcompat = v.stdcompat 22 v.definition = "COMPAT_" .. stdcompat:upper() 23 v.compatlevel = tonumber(stdcompat:match("([0-9]+)$")) 24 v.flag = stdcompat:gsub("FREEBSD", "COMPAT") 25 v.prefix = stdcompat:lower() .. "_" 26 v.descr = stdcompat:lower() 27 end 28 29 -- Add compat option to syscall.known_flags. 30 table.insert(syscall.known_flags, v.flag) 31 end 32end 33 34function FreeBSDSyscall:parseSysfile() 35 local file = self.sysfile 36 local config = self.config 37 local commentExpr = "^%s*;.*" 38 39 if file == nil then 40 return nil, "No file given" 41 end 42 43 self.syscalls = {} 44 45 local fh, msg = io.open(file) 46 if fh == nil then 47 return nil, msg 48 end 49 50 local incs = "" 51 local prolog = "" 52 local first = true 53 local cpp_warned = false 54 local s 55 for line in fh:lines() do 56 line = line:gsub(commentExpr, "") -- Strip any comments. 57 -- NOTE: Can't use pure pattern matching here because of 58 -- the 's' test and this is shorter than a generic pattern 59 -- matching pattern. 60 if line == nil or line == "" then 61 goto skip -- Blank line, skip this line. 62 elseif s ~= nil then 63 -- If we have a partial system call object s, 64 -- then feed it one more line. 65 if s:add(line) then 66 -- Append to system call list. 67 for t in s:iter() do 68 if t:validate(t.num - 1) then 69 table.insert(self.syscalls, t) 70 else 71 util.abort(1, 72 "Skipped system call " .. 73 "at number " .. t.num) 74 end 75 end 76 s = nil 77 end 78 elseif line:match("^#%s*include") then 79 incs = incs .. line .. "\n" 80 elseif line:match("%%ABI_HEADERS%%") then 81 local h = self.config.abi_headers 82 if h ~= nil and h ~= "" then 83 incs = incs .. h .. "\n" 84 end 85 elseif line:match("^#") then 86 if not cpp_warned then 87 util.warn("use of non-include cpp " .. 88 "directives is deprecated") 89 cpp_warned = true 90 end 91 prolog = prolog .. line .. "\n" 92 else 93 s = syscall:new() 94 if first then 95 self.prolog = prolog 96 s.prolog = "" 97 first = false 98 else 99 s.prolog = prolog 100 end 101 prolog = "" 102 if s:add(line) then 103 -- Append to system call list. 104 for t in s:iter() do 105 if t:validate(t.num - 1) then 106 table.insert(self.syscalls, t) 107 else 108 util.abort(1, 109 "Skipped system call " .. 110 "at number " .. t.num) 111 end 112 end 113 s = nil 114 end 115 end 116 ::skip:: 117 end 118 119 -- Special handling for linux nosys. 120 if config.syscallprefix:find("LINUX") ~= nil then 121 s = nil 122 end 123 124 if s ~= nil then 125 util.abort(1, "Dangling system call at the end") 126 end 127 128 assert(fh:close()) 129 self.includes = incs 130 self.epilog = prolog 131 132 if self.prolog ~= "" then 133 util.warn("non-include pre-processor directives in the " .. 134 "config prolog will not appear in generated output:\n" .. 135 self.prolog) 136 end 137end 138 139function FreeBSDSyscall:findStructs() 140 self.structs = {} 141 142 for _, s in pairs(self.syscalls) do 143 if s:native() and not s.type.NODEF then 144 for _, v in ipairs(s.args) do 145 local name = util.structName(v.type) 146 if name ~= nil then 147 self.structs[name] = name 148 end 149 end 150 end 151 end 152end 153 154function FreeBSDSyscall:new(obj) 155 obj = obj or {} 156 setmetatable(obj, self) 157 self.__index = self 158 159 obj:processCompat() 160 obj:parseSysfile() 161 obj:findStructs() 162 163 return obj 164end 165 166return FreeBSDSyscall 167