summaryrefslogtreecommitdiff
path: root/sys/tools/syscalls/core/freebsd-syscall.lua
blob: 2ef0fdea640123233eac9fc11e7a09c052da1d3c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
--
-- SPDX-License-Identifier: BSD-2-Clause
--
-- Copyright (c) 2024 Tyler Baxter <agge@FreeBSD.org>
-- Copyright (c) 2023 Warner Losh <imp@bsdimp.com>
-- Copyright (c) 2019 Kyle Evans <kevans@FreeBSD.org>
--

local syscall = require("core.syscall")
local util = require("tools.util")

local FreeBSDSyscall = {}

FreeBSDSyscall.__index = FreeBSDSyscall

-- For each compat option in the provided config table, process them and insert
-- them into known_flags for class syscall.
function FreeBSDSyscall:processCompat()
	for _, v in pairs(self.config.compat_options) do
		if v.stdcompat ~= nil then
			local stdcompat = v.stdcompat
			v.definition = "COMPAT_" .. stdcompat:upper()
			v.compatlevel = tonumber(stdcompat:match("([0-9]+)$"))
			v.flag = stdcompat:gsub("FREEBSD", "COMPAT")
			v.prefix = stdcompat:lower() .. "_"
			v.descr = stdcompat:lower()
		end

		-- Add compat option to syscall.known_flags.
		table.insert(syscall.known_flags, v.flag)
	end
end

function FreeBSDSyscall:parseSysfile()
	local file = self.sysfile
	local config = self.config
	local commentExpr = "^%s*;.*"

	if file == nil then
		return nil, "No file given"
	end

	self.syscalls = {}

	local fh, msg = io.open(file)
	if fh == nil then
		return nil, msg
	end

	local incs = ""
	local prolog = ""
	local first = true
	local cpp_warned = false
	local s
	for line in fh:lines() do
		line = line:gsub(commentExpr, "") -- Strip any comments.
		-- NOTE: Can't use pure pattern matching here because of
		-- the 's' test and this is shorter than a generic pattern
		-- matching pattern.
		if line == nil or line == "" then
			goto skip	-- Blank line, skip this line.
		elseif s ~= nil then
			-- If we have a partial system call object s,
			-- then feed it one more line.
			if s:add(line) then
				-- Append to system call list.
				for t in s:iter() do
					if t:validate(t.num - 1) then
						table.insert(self.syscalls, t)
					else
						util.abort(1,
						    "Skipped system call " ..
						    "at number " .. t.num)
					end
				end
				s = nil
			end
		elseif line:match("^#%s*include") then
			incs = incs .. line .. "\n"
		elseif line:match("%%ABI_HEADERS%%") then
			local h = self.config.abi_headers
			if h ~= nil and h ~= "" then
				incs = incs .. h .. "\n"
			end
		elseif line:match("^#") then
			if not cpp_warned then
				util.warn("use of non-include cpp " ..
				    "directives is deprecated")
				cpp_warned = true
			end
			prolog = prolog .. line .. "\n"
		else
			s = syscall:new()
			if first then
				self.prolog = prolog
				s.prolog = ""
				first = false
			else
				s.prolog = prolog
			end
			prolog = ""
			if s:add(line) then
				-- Append to system call list.
				for t in s:iter() do
					if t:validate(t.num - 1) then
						table.insert(self.syscalls, t)
					else
						util.abort(1,
						    "Skipped system call " ..
						    "at number " .. t.num)
					end
				end
				s = nil
			end
		end
		::skip::
	end

	-- Special handling for linux nosys.
	if config.syscallprefix:find("LINUX") ~= nil then
		s = nil
	end

	if s ~= nil then
		util.abort(1, "Dangling system call at the end")
	end

	assert(fh:close())
	self.includes = incs
	self.epilog = prolog

	if self.prolog ~= "" then
		util.warn("non-include pre-processor directives in the " ..
		    "config prolog will not appear in generated output:\n" ..
		    self.prolog)
	end
end

function FreeBSDSyscall:findStructs()
	self.structs = {}

	for _, s in pairs(self.syscalls) do
		if s:native() and not s.type.NODEF then
			for _, v in ipairs(s.args) do
				local name = util.structName(v.type)
				if name ~= nil then
					self.structs[name] = name
				end
			end
		end
	end
end

function FreeBSDSyscall:new(obj)
	obj = obj or {}
	setmetatable(obj, self)
	self.__index = self

	obj:processCompat()
	obj:parseSysfile()
	obj:findStructs()

	return obj
end

return FreeBSDSyscall