xref: /freebsd/sys/tools/syscalls/core/freebsd-syscall.lua (revision f29905cab576a0ccf454ee2e215f590e0e656d70)
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