xref: /f-stack/freebsd/tools/makesyscalls.lua (revision 22ce4aff)
1*22ce4affSfengbojiang--
2*22ce4affSfengbojiang-- SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3*22ce4affSfengbojiang--
4*22ce4affSfengbojiang-- Copyright (c) 2019 Kyle Evans <[email protected]>
5*22ce4affSfengbojiang--
6*22ce4affSfengbojiang-- Redistribution and use in source and binary forms, with or without
7*22ce4affSfengbojiang-- modification, are permitted provided that the following conditions
8*22ce4affSfengbojiang-- are met:
9*22ce4affSfengbojiang-- 1. Redistributions of source code must retain the above copyright
10*22ce4affSfengbojiang--    notice, this list of conditions and the following disclaimer.
11*22ce4affSfengbojiang-- 2. Redistributions in binary form must reproduce the above copyright
12*22ce4affSfengbojiang--    notice, this list of conditions and the following disclaimer in the
13*22ce4affSfengbojiang--    documentation and/or other materials provided with the distribution.
14*22ce4affSfengbojiang--
15*22ce4affSfengbojiang-- THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16*22ce4affSfengbojiang-- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17*22ce4affSfengbojiang-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18*22ce4affSfengbojiang-- ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19*22ce4affSfengbojiang-- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20*22ce4affSfengbojiang-- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21*22ce4affSfengbojiang-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22*22ce4affSfengbojiang-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23*22ce4affSfengbojiang-- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24*22ce4affSfengbojiang-- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25*22ce4affSfengbojiang-- SUCH DAMAGE.
26*22ce4affSfengbojiang--
27*22ce4affSfengbojiang-- $FreeBSD$
28*22ce4affSfengbojiang--
29*22ce4affSfengbojiang
30*22ce4affSfengbojiang
31*22ce4affSfengbojiang-- We generally assume that this script will be run by flua, however we've
32*22ce4affSfengbojiang-- carefully crafted modules for it that mimic interfaces provided by modules
33*22ce4affSfengbojiang-- available in ports.  Currently, this script is compatible with lua from ports
34*22ce4affSfengbojiang-- along with the compatible luafilesystem and lua-posix modules.
35*22ce4affSfengbojianglocal lfs = require("lfs")
36*22ce4affSfengbojianglocal unistd = require("posix.unistd")
37*22ce4affSfengbojiang
38*22ce4affSfengbojianglocal savesyscall = -1
39*22ce4affSfengbojianglocal maxsyscall = -1
40*22ce4affSfengbojianglocal generated_tag = "@" .. "generated"
41*22ce4affSfengbojiang
42*22ce4affSfengbojiang-- Default configuration; any of these may get replaced by a configuration file
43*22ce4affSfengbojiang-- optionally specified.
44*22ce4affSfengbojianglocal config = {
45*22ce4affSfengbojiang	os_id_keyword = "FreeBSD",
46*22ce4affSfengbojiang	abi_func_prefix = "",
47*22ce4affSfengbojiang	sysnames = "syscalls.c",
48*22ce4affSfengbojiang	sysproto = "../sys/sysproto.h",
49*22ce4affSfengbojiang	sysproto_h = "_SYS_SYSPROTO_H_",
50*22ce4affSfengbojiang	syshdr = "../sys/syscall.h",
51*22ce4affSfengbojiang	sysmk = "../sys/syscall.mk",
52*22ce4affSfengbojiang	syssw = "init_sysent.c",
53*22ce4affSfengbojiang	syscallprefix = "SYS_",
54*22ce4affSfengbojiang	switchname = "sysent",
55*22ce4affSfengbojiang	namesname = "syscallnames",
56*22ce4affSfengbojiang	systrace = "systrace_args.c",
57*22ce4affSfengbojiang	capabilities_conf = "capabilities.conf",
58*22ce4affSfengbojiang	capenabled = {},
59*22ce4affSfengbojiang	mincompat = 0,
60*22ce4affSfengbojiang	abi_type_suffix = "",
61*22ce4affSfengbojiang	abi_flags = "",
62*22ce4affSfengbojiang	abi_flags_mask = 0,
63*22ce4affSfengbojiang	ptr_intptr_t_cast = "intptr_t",
64*22ce4affSfengbojiang}
65*22ce4affSfengbojiang
66*22ce4affSfengbojianglocal config_modified = {}
67*22ce4affSfengbojianglocal cleantmp = true
68*22ce4affSfengbojianglocal tmpspace = "/tmp/sysent." .. unistd.getpid() .. "/"
69*22ce4affSfengbojiang
70*22ce4affSfengbojianglocal output_files = {
71*22ce4affSfengbojiang	"sysnames",
72*22ce4affSfengbojiang	"syshdr",
73*22ce4affSfengbojiang	"sysmk",
74*22ce4affSfengbojiang	"syssw",
75*22ce4affSfengbojiang	"systrace",
76*22ce4affSfengbojiang	"sysproto",
77*22ce4affSfengbojiang}
78*22ce4affSfengbojiang
79*22ce4affSfengbojiang-- These ones we'll create temporary files for; generation purposes.
80*22ce4affSfengbojianglocal temp_files = {
81*22ce4affSfengbojiang	"sysaue",
82*22ce4affSfengbojiang	"sysdcl",
83*22ce4affSfengbojiang	"syscompat",
84*22ce4affSfengbojiang	"syscompatdcl",
85*22ce4affSfengbojiang	"sysent",
86*22ce4affSfengbojiang	"sysinc",
87*22ce4affSfengbojiang	"sysarg",
88*22ce4affSfengbojiang	"sysprotoend",
89*22ce4affSfengbojiang	"systracetmp",
90*22ce4affSfengbojiang	"systraceret",
91*22ce4affSfengbojiang}
92*22ce4affSfengbojiang
93*22ce4affSfengbojiang-- Opened files
94*22ce4affSfengbojianglocal files = {}
95*22ce4affSfengbojiang
96*22ce4affSfengbojianglocal function cleanup()
97*22ce4affSfengbojiang	for _, v in pairs(files) do
98*22ce4affSfengbojiang		v:close()
99*22ce4affSfengbojiang	end
100*22ce4affSfengbojiang	if cleantmp then
101*22ce4affSfengbojiang		if lfs.dir(tmpspace) then
102*22ce4affSfengbojiang			for fname in lfs.dir(tmpspace) do
103*22ce4affSfengbojiang				os.remove(tmpspace .. "/" .. fname)
104*22ce4affSfengbojiang			end
105*22ce4affSfengbojiang		end
106*22ce4affSfengbojiang
107*22ce4affSfengbojiang		if lfs.attributes(tmpspace) and not lfs.rmdir(tmpspace) then
108*22ce4affSfengbojiang			io.stderr:write("Failed to clean up tmpdir: " ..
109*22ce4affSfengbojiang			    tmpspace .. "\n")
110*22ce4affSfengbojiang		end
111*22ce4affSfengbojiang	else
112*22ce4affSfengbojiang		io.stderr:write("Temp files left in " .. tmpspace .. "\n")
113*22ce4affSfengbojiang	end
114*22ce4affSfengbojiangend
115*22ce4affSfengbojiang
116*22ce4affSfengbojianglocal function abort(status, msg)
117*22ce4affSfengbojiang	io.stderr:write(msg .. "\n")
118*22ce4affSfengbojiang	cleanup()
119*22ce4affSfengbojiang	os.exit(status)
120*22ce4affSfengbojiangend
121*22ce4affSfengbojiang
122*22ce4affSfengbojiang-- Each entry should have a value so we can represent abi flags as a bitmask
123*22ce4affSfengbojiang-- for convenience.  One may also optionally provide an expr; this gets applied
124*22ce4affSfengbojiang-- to each argument type to indicate whether this argument is subject to ABI
125*22ce4affSfengbojiang-- change given the configured flags.
126*22ce4affSfengbojianglocal known_abi_flags = {
127*22ce4affSfengbojiang	long_size = {
128*22ce4affSfengbojiang		value	= 0x00000001,
129*22ce4affSfengbojiang		expr	= "_Contains[a-z_]*_long_",
130*22ce4affSfengbojiang	},
131*22ce4affSfengbojiang	time_t_size = {
132*22ce4affSfengbojiang		value	= 0x00000002,
133*22ce4affSfengbojiang		expr	= "_Contains[a-z_]*_timet_/",
134*22ce4affSfengbojiang	},
135*22ce4affSfengbojiang	pointer_args = {
136*22ce4affSfengbojiang		value	= 0x00000004,
137*22ce4affSfengbojiang	},
138*22ce4affSfengbojiang	pointer_size = {
139*22ce4affSfengbojiang		value	= 0x00000008,
140*22ce4affSfengbojiang		expr	= "_Contains[a-z_]*_ptr_",
141*22ce4affSfengbojiang	},
142*22ce4affSfengbojiang}
143*22ce4affSfengbojiang
144*22ce4affSfengbojianglocal known_flags = {
145*22ce4affSfengbojiang	STD		= 0x00000001,
146*22ce4affSfengbojiang	OBSOL		= 0x00000002,
147*22ce4affSfengbojiang	UNIMPL		= 0x00000004,
148*22ce4affSfengbojiang	NODEF		= 0x00000008,
149*22ce4affSfengbojiang	NOARGS		= 0x00000010,
150*22ce4affSfengbojiang	NOPROTO		= 0x00000020,
151*22ce4affSfengbojiang	NOSTD		= 0x00000040,
152*22ce4affSfengbojiang	NOTSTATIC	= 0x00000080,
153*22ce4affSfengbojiang
154*22ce4affSfengbojiang	-- Compat flags start from here.  We have plenty of space.
155*22ce4affSfengbojiang}
156*22ce4affSfengbojiang
157*22ce4affSfengbojiang-- All compat_options entries should have five entries:
158*22ce4affSfengbojiang--	definition: The preprocessor macro that will be set for this
159*22ce4affSfengbojiang--	compatlevel: The level this compatibility should be included at.  This
160*22ce4affSfengbojiang--	    generally represents the version of FreeBSD that it is compatible
161*22ce4affSfengbojiang--	    with, but ultimately it's just the level of mincompat in which it's
162*22ce4affSfengbojiang--	    included.
163*22ce4affSfengbojiang--	flag: The name of the flag in syscalls.master.
164*22ce4affSfengbojiang--	prefix: The prefix to use for _args and syscall prototype.  This will be
165*22ce4affSfengbojiang--	    used as-is, without "_" or any other character appended.
166*22ce4affSfengbojiang--	descr: The description of this compat option in init_sysent.c comments.
167*22ce4affSfengbojiang-- The special "stdcompat" entry will cause the other five to be autogenerated.
168*22ce4affSfengbojianglocal compat_options = {
169*22ce4affSfengbojiang	{
170*22ce4affSfengbojiang		definition = "COMPAT_43",
171*22ce4affSfengbojiang		compatlevel = 3,
172*22ce4affSfengbojiang		flag = "COMPAT",
173*22ce4affSfengbojiang		prefix = "o",
174*22ce4affSfengbojiang		descr = "old",
175*22ce4affSfengbojiang	},
176*22ce4affSfengbojiang	{ stdcompat = "FREEBSD4" },
177*22ce4affSfengbojiang	{ stdcompat = "FREEBSD6" },
178*22ce4affSfengbojiang	{ stdcompat = "FREEBSD7" },
179*22ce4affSfengbojiang	{ stdcompat = "FREEBSD10" },
180*22ce4affSfengbojiang	{ stdcompat = "FREEBSD11" },
181*22ce4affSfengbojiang	{ stdcompat = "FREEBSD12" },
182*22ce4affSfengbojiang}
183*22ce4affSfengbojiang
184*22ce4affSfengbojianglocal function trim(s, char)
185*22ce4affSfengbojiang	if s == nil then
186*22ce4affSfengbojiang		return nil
187*22ce4affSfengbojiang	end
188*22ce4affSfengbojiang	if char == nil then
189*22ce4affSfengbojiang		char = "%s"
190*22ce4affSfengbojiang	end
191*22ce4affSfengbojiang	return s:gsub("^" .. char .. "+", ""):gsub(char .. "+$", "")
192*22ce4affSfengbojiangend
193*22ce4affSfengbojiang
194*22ce4affSfengbojiang-- We have to io.popen it, making sure it's properly escaped, and grab the
195*22ce4affSfengbojiang-- output from the handle returned.
196*22ce4affSfengbojianglocal function exec(cmd)
197*22ce4affSfengbojiang	cmd = cmd:gsub('"', '\\"')
198*22ce4affSfengbojiang
199*22ce4affSfengbojiang	local shcmd = "/bin/sh -c \"" .. cmd .. "\""
200*22ce4affSfengbojiang	local fh = io.popen(shcmd)
201*22ce4affSfengbojiang	local output = fh:read("a")
202*22ce4affSfengbojiang
203*22ce4affSfengbojiang	fh:close()
204*22ce4affSfengbojiang	return output
205*22ce4affSfengbojiangend
206*22ce4affSfengbojiang
207*22ce4affSfengbojiang-- config looks like a shell script; in fact, the previous makesyscalls.sh
208*22ce4affSfengbojiang-- script actually sourced it in.  It had a pretty common format, so we should
209*22ce4affSfengbojiang-- be fine to make various assumptions
210*22ce4affSfengbojianglocal function process_config(file)
211*22ce4affSfengbojiang	local cfg = {}
212*22ce4affSfengbojiang	local comment_line_expr = "^%s*#.*"
213*22ce4affSfengbojiang	-- We capture any whitespace padding here so we can easily advance to
214*22ce4affSfengbojiang	-- the end of the line as needed to check for any trailing bogus bits.
215*22ce4affSfengbojiang	-- Alternatively, we could drop the whitespace and instead try to
216*22ce4affSfengbojiang	-- use a pattern to strip out the meaty part of the line, but then we
217*22ce4affSfengbojiang	-- would need to sanitize the line for potentially special characters.
218*22ce4affSfengbojiang	local line_expr = "^([%w%p]+%s*)=(%s*[`\"]?[^\"`]+[`\"]?)"
219*22ce4affSfengbojiang
220*22ce4affSfengbojiang	if file == nil then
221*22ce4affSfengbojiang		return nil, "No file given"
222*22ce4affSfengbojiang	end
223*22ce4affSfengbojiang
224*22ce4affSfengbojiang	local fh = io.open(file)
225*22ce4affSfengbojiang	if fh == nil then
226*22ce4affSfengbojiang		return nil, "Could not open file"
227*22ce4affSfengbojiang	end
228*22ce4affSfengbojiang
229*22ce4affSfengbojiang	for nextline in fh:lines() do
230*22ce4affSfengbojiang		-- Strip any whole-line comments
231*22ce4affSfengbojiang		nextline = nextline:gsub(comment_line_expr, "")
232*22ce4affSfengbojiang		-- Parse it into key, value pairs
233*22ce4affSfengbojiang		local key, value = nextline:match(line_expr)
234*22ce4affSfengbojiang		if key ~= nil and value ~= nil then
235*22ce4affSfengbojiang			local kvp = key .. "=" .. value
236*22ce4affSfengbojiang			key = trim(key)
237*22ce4affSfengbojiang			value = trim(value)
238*22ce4affSfengbojiang			local delim = value:sub(1,1)
239*22ce4affSfengbojiang			if delim == '`' or delim == '"' then
240*22ce4affSfengbojiang				local trailing_context
241*22ce4affSfengbojiang				-- Strip off the key/value part
242*22ce4affSfengbojiang				trailing_context = nextline:sub(kvp:len() + 1)
243*22ce4affSfengbojiang				-- Strip off any trailing comment
244*22ce4affSfengbojiang				trailing_context = trailing_context:gsub("#.*$",
245*22ce4affSfengbojiang				    "")
246*22ce4affSfengbojiang				-- Strip off leading/trailing whitespace
247*22ce4affSfengbojiang				trailing_context = trim(trailing_context)
248*22ce4affSfengbojiang				if trailing_context ~= "" then
249*22ce4affSfengbojiang					print(trailing_context)
250*22ce4affSfengbojiang					abort(1, "Malformed line: " .. nextline)
251*22ce4affSfengbojiang				end
252*22ce4affSfengbojiang			end
253*22ce4affSfengbojiang			if delim == '`' then
254*22ce4affSfengbojiang				-- Command substition may use $1 and $2 to mean
255*22ce4affSfengbojiang				-- the syscall definition file and itself
256*22ce4affSfengbojiang				-- respectively.  We'll go ahead and replace
257*22ce4affSfengbojiang				-- $[0-9] with respective arg in case we want to
258*22ce4affSfengbojiang				-- expand this in the future easily...
259*22ce4affSfengbojiang				value = trim(value, delim)
260*22ce4affSfengbojiang				for capture in value:gmatch("$([0-9]+)") do
261*22ce4affSfengbojiang					capture = tonumber(capture)
262*22ce4affSfengbojiang					if capture > #arg then
263*22ce4affSfengbojiang						abort(1, "Not enough args: " ..
264*22ce4affSfengbojiang						    value)
265*22ce4affSfengbojiang					end
266*22ce4affSfengbojiang					value = value:gsub("$" .. capture,
267*22ce4affSfengbojiang					    arg[capture])
268*22ce4affSfengbojiang				end
269*22ce4affSfengbojiang
270*22ce4affSfengbojiang				value = exec(value)
271*22ce4affSfengbojiang			elseif delim == '"' then
272*22ce4affSfengbojiang				value = trim(value, delim)
273*22ce4affSfengbojiang			else
274*22ce4affSfengbojiang				-- Strip off potential comments
275*22ce4affSfengbojiang				value = value:gsub("#.*$", "")
276*22ce4affSfengbojiang				-- Strip off any padding whitespace
277*22ce4affSfengbojiang				value = trim(value)
278*22ce4affSfengbojiang				if value:match("%s") then
279*22ce4affSfengbojiang					abort(1, "Malformed config line: " ..
280*22ce4affSfengbojiang					    nextline)
281*22ce4affSfengbojiang				end
282*22ce4affSfengbojiang			end
283*22ce4affSfengbojiang			cfg[key] = value
284*22ce4affSfengbojiang		elseif not nextline:match("^%s*$") then
285*22ce4affSfengbojiang			-- Make sure format violations don't get overlooked
286*22ce4affSfengbojiang			-- here, but ignore blank lines.  Comments are already
287*22ce4affSfengbojiang			-- stripped above.
288*22ce4affSfengbojiang			abort(1, "Malformed config line: " .. nextline)
289*22ce4affSfengbojiang		end
290*22ce4affSfengbojiang	end
291*22ce4affSfengbojiang
292*22ce4affSfengbojiang	io.close(fh)
293*22ce4affSfengbojiang	return cfg
294*22ce4affSfengbojiangend
295*22ce4affSfengbojiang
296*22ce4affSfengbojianglocal function grab_capenabled(file, open_fail_ok)
297*22ce4affSfengbojiang	local capentries = {}
298*22ce4affSfengbojiang	local commentExpr = "#.*"
299*22ce4affSfengbojiang
300*22ce4affSfengbojiang	if file == nil then
301*22ce4affSfengbojiang		print "No file"
302*22ce4affSfengbojiang		return {}
303*22ce4affSfengbojiang	end
304*22ce4affSfengbojiang
305*22ce4affSfengbojiang	local fh = io.open(file)
306*22ce4affSfengbojiang	if fh == nil then
307*22ce4affSfengbojiang		if not open_fail_ok then
308*22ce4affSfengbojiang			abort(1, "Failed to open " .. file)
309*22ce4affSfengbojiang		end
310*22ce4affSfengbojiang		return {}
311*22ce4affSfengbojiang	end
312*22ce4affSfengbojiang
313*22ce4affSfengbojiang	for nextline in fh:lines() do
314*22ce4affSfengbojiang		-- Strip any comments
315*22ce4affSfengbojiang		nextline = nextline:gsub(commentExpr, "")
316*22ce4affSfengbojiang		if nextline ~= "" then
317*22ce4affSfengbojiang			capentries[nextline] = true
318*22ce4affSfengbojiang		end
319*22ce4affSfengbojiang	end
320*22ce4affSfengbojiang
321*22ce4affSfengbojiang	io.close(fh)
322*22ce4affSfengbojiang	return capentries
323*22ce4affSfengbojiangend
324*22ce4affSfengbojiang
325*22ce4affSfengbojianglocal function process_compat()
326*22ce4affSfengbojiang	local nval = 0
327*22ce4affSfengbojiang	for _, v in pairs(known_flags) do
328*22ce4affSfengbojiang		if v > nval then
329*22ce4affSfengbojiang			nval = v
330*22ce4affSfengbojiang		end
331*22ce4affSfengbojiang	end
332*22ce4affSfengbojiang
333*22ce4affSfengbojiang	nval = nval << 1
334*22ce4affSfengbojiang	for _, v in pairs(compat_options) do
335*22ce4affSfengbojiang		if v["stdcompat"] ~= nil then
336*22ce4affSfengbojiang			local stdcompat = v["stdcompat"]
337*22ce4affSfengbojiang			v["definition"] = "COMPAT_" .. stdcompat:upper()
338*22ce4affSfengbojiang			v["compatlevel"] = tonumber(stdcompat:match("([0-9]+)$"))
339*22ce4affSfengbojiang			v["flag"] = stdcompat:gsub("FREEBSD", "COMPAT")
340*22ce4affSfengbojiang			v["prefix"] = stdcompat:lower() .. "_"
341*22ce4affSfengbojiang			v["descr"] = stdcompat:lower()
342*22ce4affSfengbojiang		end
343*22ce4affSfengbojiang
344*22ce4affSfengbojiang		local tmpname = "sys" .. v["flag"]:lower()
345*22ce4affSfengbojiang		local dcltmpname = tmpname .. "dcl"
346*22ce4affSfengbojiang		files[tmpname] = io.tmpfile()
347*22ce4affSfengbojiang		files[dcltmpname] = io.tmpfile()
348*22ce4affSfengbojiang		v["tmp"] = tmpname
349*22ce4affSfengbojiang		v["dcltmp"] = dcltmpname
350*22ce4affSfengbojiang
351*22ce4affSfengbojiang		known_flags[v["flag"]] = nval
352*22ce4affSfengbojiang		v["mask"] = nval
353*22ce4affSfengbojiang		nval = nval << 1
354*22ce4affSfengbojiang
355*22ce4affSfengbojiang		v["count"] = 0
356*22ce4affSfengbojiang	end
357*22ce4affSfengbojiangend
358*22ce4affSfengbojiang
359*22ce4affSfengbojianglocal function process_abi_flags()
360*22ce4affSfengbojiang	local flags, mask = config["abi_flags"], 0
361*22ce4affSfengbojiang	for txtflag in flags:gmatch("([^|]+)") do
362*22ce4affSfengbojiang		if known_abi_flags[txtflag] == nil then
363*22ce4affSfengbojiang			abort(1, "Unknown abi_flag: " .. txtflag)
364*22ce4affSfengbojiang		end
365*22ce4affSfengbojiang
366*22ce4affSfengbojiang		mask = mask | known_abi_flags[txtflag]["value"]
367*22ce4affSfengbojiang	end
368*22ce4affSfengbojiang
369*22ce4affSfengbojiang	config["abi_flags_mask"] = mask
370*22ce4affSfengbojiangend
371*22ce4affSfengbojiang
372*22ce4affSfengbojianglocal function abi_changes(name)
373*22ce4affSfengbojiang	if known_abi_flags[name] == nil then
374*22ce4affSfengbojiang		abort(1, "abi_changes: unknown flag: " .. name)
375*22ce4affSfengbojiang	end
376*22ce4affSfengbojiang
377*22ce4affSfengbojiang	return config["abi_flags_mask"] & known_abi_flags[name]["value"] ~= 0
378*22ce4affSfengbojiangend
379*22ce4affSfengbojiang
380*22ce4affSfengbojianglocal function strip_abi_prefix(funcname)
381*22ce4affSfengbojiang	local abiprefix = config["abi_func_prefix"]
382*22ce4affSfengbojiang	local stripped_name
383*22ce4affSfengbojiang	if abiprefix ~= "" and funcname:find("^" .. abiprefix) then
384*22ce4affSfengbojiang		stripped_name = funcname:gsub("^" .. abiprefix, "")
385*22ce4affSfengbojiang	else
386*22ce4affSfengbojiang		stripped_name = funcname
387*22ce4affSfengbojiang	end
388*22ce4affSfengbojiang
389*22ce4affSfengbojiang	return stripped_name
390*22ce4affSfengbojiangend
391*22ce4affSfengbojiang
392*22ce4affSfengbojianglocal function read_file(tmpfile)
393*22ce4affSfengbojiang	if files[tmpfile] == nil then
394*22ce4affSfengbojiang		print("Not found: " .. tmpfile)
395*22ce4affSfengbojiang		return
396*22ce4affSfengbojiang	end
397*22ce4affSfengbojiang
398*22ce4affSfengbojiang	local fh = files[tmpfile]
399*22ce4affSfengbojiang	fh:seek("set")
400*22ce4affSfengbojiang	return fh:read("a")
401*22ce4affSfengbojiangend
402*22ce4affSfengbojiang
403*22ce4affSfengbojianglocal function write_line(tmpfile, line)
404*22ce4affSfengbojiang	if files[tmpfile] == nil then
405*22ce4affSfengbojiang		print("Not found: " .. tmpfile)
406*22ce4affSfengbojiang		return
407*22ce4affSfengbojiang	end
408*22ce4affSfengbojiang	files[tmpfile]:write(line)
409*22ce4affSfengbojiangend
410*22ce4affSfengbojiang
411*22ce4affSfengbojianglocal function write_line_pfile(tmppat, line)
412*22ce4affSfengbojiang	for k in pairs(files) do
413*22ce4affSfengbojiang		if k:match(tmppat) ~= nil then
414*22ce4affSfengbojiang			files[k]:write(line)
415*22ce4affSfengbojiang		end
416*22ce4affSfengbojiang	end
417*22ce4affSfengbojiangend
418*22ce4affSfengbojiang
419*22ce4affSfengbojianglocal function isptrtype(type)
420*22ce4affSfengbojiang	return type:find("*") or type:find("caddr_t")
421*22ce4affSfengbojiang	    -- XXX NOTYET: or type:find("intptr_t")
422*22ce4affSfengbojiangend
423*22ce4affSfengbojiang
424*22ce4affSfengbojianglocal process_syscall_def
425*22ce4affSfengbojiang
426*22ce4affSfengbojiang-- These patterns are processed in order on any line that isn't empty.
427*22ce4affSfengbojianglocal pattern_table = {
428*22ce4affSfengbojiang	{
429*22ce4affSfengbojiang		pattern = "%s*$" .. config['os_id_keyword'],
430*22ce4affSfengbojiang		process = function(_, _)
431*22ce4affSfengbojiang			-- Ignore... ID tag
432*22ce4affSfengbojiang		end,
433*22ce4affSfengbojiang	},
434*22ce4affSfengbojiang	{
435*22ce4affSfengbojiang		dump_prevline = true,
436*22ce4affSfengbojiang		pattern = "^#%s*include",
437*22ce4affSfengbojiang		process = function(line)
438*22ce4affSfengbojiang			line = line .. "\n"
439*22ce4affSfengbojiang			write_line('sysinc', line)
440*22ce4affSfengbojiang		end,
441*22ce4affSfengbojiang	},
442*22ce4affSfengbojiang	{
443*22ce4affSfengbojiang		dump_prevline = true,
444*22ce4affSfengbojiang		pattern = "^#",
445*22ce4affSfengbojiang		process = function(line)
446*22ce4affSfengbojiang			if line:find("^#%s*if") then
447*22ce4affSfengbojiang				savesyscall = maxsyscall
448*22ce4affSfengbojiang			elseif line:find("^#%s*else") then
449*22ce4affSfengbojiang				maxsyscall = savesyscall
450*22ce4affSfengbojiang			end
451*22ce4affSfengbojiang			line = line .. "\n"
452*22ce4affSfengbojiang			write_line('sysent', line)
453*22ce4affSfengbojiang			write_line('sysdcl', line)
454*22ce4affSfengbojiang			write_line('sysarg', line)
455*22ce4affSfengbojiang			write_line_pfile('syscompat[0-9]*$', line)
456*22ce4affSfengbojiang			write_line('sysnames', line)
457*22ce4affSfengbojiang			write_line_pfile('systrace.*', line)
458*22ce4affSfengbojiang		end,
459*22ce4affSfengbojiang	},
460*22ce4affSfengbojiang	{
461*22ce4affSfengbojiang		-- Buffer anything else
462*22ce4affSfengbojiang		pattern = ".+",
463*22ce4affSfengbojiang		process = function(line, prevline)
464*22ce4affSfengbojiang			local incomplete = line:find("\\$") ~= nil
465*22ce4affSfengbojiang			-- Lines that end in \ get the \ stripped
466*22ce4affSfengbojiang			-- Lines that start with a syscall number, prepend \n
467*22ce4affSfengbojiang			line = trim(line):gsub("\\$", "")
468*22ce4affSfengbojiang			if line:find("^[0-9]") and prevline then
469*22ce4affSfengbojiang				process_syscall_def(prevline)
470*22ce4affSfengbojiang				prevline = nil
471*22ce4affSfengbojiang			end
472*22ce4affSfengbojiang
473*22ce4affSfengbojiang			prevline = (prevline or '') .. line
474*22ce4affSfengbojiang			incomplete = incomplete or prevline:find(",$") ~= nil
475*22ce4affSfengbojiang			incomplete = incomplete or prevline:find("{") ~= nil and
476*22ce4affSfengbojiang			    prevline:find("}") == nil
477*22ce4affSfengbojiang			if prevline:find("^[0-9]") and not incomplete then
478*22ce4affSfengbojiang				process_syscall_def(prevline)
479*22ce4affSfengbojiang				prevline = nil
480*22ce4affSfengbojiang			end
481*22ce4affSfengbojiang
482*22ce4affSfengbojiang			return prevline
483*22ce4affSfengbojiang		end,
484*22ce4affSfengbojiang	},
485*22ce4affSfengbojiang}
486*22ce4affSfengbojiang
487*22ce4affSfengbojianglocal function process_sysfile(file)
488*22ce4affSfengbojiang	local capentries = {}
489*22ce4affSfengbojiang	local commentExpr = "^%s*;.*"
490*22ce4affSfengbojiang
491*22ce4affSfengbojiang	if file == nil then
492*22ce4affSfengbojiang		print "No file"
493*22ce4affSfengbojiang		return {}
494*22ce4affSfengbojiang	end
495*22ce4affSfengbojiang
496*22ce4affSfengbojiang	local fh = io.open(file)
497*22ce4affSfengbojiang	if fh == nil then
498*22ce4affSfengbojiang		print("Failed to open " .. file)
499*22ce4affSfengbojiang		return {}
500*22ce4affSfengbojiang	end
501*22ce4affSfengbojiang
502*22ce4affSfengbojiang	local function do_match(nextline, prevline)
503*22ce4affSfengbojiang		local pattern, handler, dump
504*22ce4affSfengbojiang		for _, v in pairs(pattern_table) do
505*22ce4affSfengbojiang			pattern = v['pattern']
506*22ce4affSfengbojiang			handler = v['process']
507*22ce4affSfengbojiang			dump = v['dump_prevline']
508*22ce4affSfengbojiang			if nextline:match(pattern) then
509*22ce4affSfengbojiang				if dump and prevline then
510*22ce4affSfengbojiang					process_syscall_def(prevline)
511*22ce4affSfengbojiang					prevline = nil
512*22ce4affSfengbojiang				end
513*22ce4affSfengbojiang
514*22ce4affSfengbojiang				return handler(nextline, prevline)
515*22ce4affSfengbojiang			end
516*22ce4affSfengbojiang		end
517*22ce4affSfengbojiang
518*22ce4affSfengbojiang		abort(1, "Failed to handle: " .. nextline)
519*22ce4affSfengbojiang	end
520*22ce4affSfengbojiang
521*22ce4affSfengbojiang	local prevline
522*22ce4affSfengbojiang	for nextline in fh:lines() do
523*22ce4affSfengbojiang		-- Strip any comments
524*22ce4affSfengbojiang		nextline = nextline:gsub(commentExpr, "")
525*22ce4affSfengbojiang		if nextline ~= "" then
526*22ce4affSfengbojiang			prevline = do_match(nextline, prevline)
527*22ce4affSfengbojiang		end
528*22ce4affSfengbojiang	end
529*22ce4affSfengbojiang
530*22ce4affSfengbojiang	-- Dump any remainder
531*22ce4affSfengbojiang	if prevline ~= nil and prevline:find("^[0-9]") then
532*22ce4affSfengbojiang		process_syscall_def(prevline)
533*22ce4affSfengbojiang	end
534*22ce4affSfengbojiang
535*22ce4affSfengbojiang	io.close(fh)
536*22ce4affSfengbojiang	return capentries
537*22ce4affSfengbojiangend
538*22ce4affSfengbojiang
539*22ce4affSfengbojianglocal function get_mask(flags)
540*22ce4affSfengbojiang	local mask = 0
541*22ce4affSfengbojiang	for _, v in ipairs(flags) do
542*22ce4affSfengbojiang		if known_flags[v] == nil then
543*22ce4affSfengbojiang			abort(1, "Checking for unknown flag " .. v)
544*22ce4affSfengbojiang		end
545*22ce4affSfengbojiang
546*22ce4affSfengbojiang		mask = mask | known_flags[v]
547*22ce4affSfengbojiang	end
548*22ce4affSfengbojiang
549*22ce4affSfengbojiang	return mask
550*22ce4affSfengbojiangend
551*22ce4affSfengbojiang
552*22ce4affSfengbojianglocal function get_mask_pat(pflags)
553*22ce4affSfengbojiang	local mask = 0
554*22ce4affSfengbojiang	for k, v in pairs(known_flags) do
555*22ce4affSfengbojiang		if k:find(pflags) then
556*22ce4affSfengbojiang			mask = mask | v
557*22ce4affSfengbojiang		end
558*22ce4affSfengbojiang	end
559*22ce4affSfengbojiang
560*22ce4affSfengbojiang	return mask
561*22ce4affSfengbojiangend
562*22ce4affSfengbojiang
563*22ce4affSfengbojianglocal function align_sysent_comment(col)
564*22ce4affSfengbojiang	write_line("sysent", "\t")
565*22ce4affSfengbojiang	col = col + 8 - col % 8
566*22ce4affSfengbojiang	while col < 56 do
567*22ce4affSfengbojiang		write_line("sysent", "\t")
568*22ce4affSfengbojiang		col = col + 8
569*22ce4affSfengbojiang	end
570*22ce4affSfengbojiangend
571*22ce4affSfengbojiang
572*22ce4affSfengbojianglocal function strip_arg_annotations(arg)
573*22ce4affSfengbojiang	arg = arg:gsub("_In[^ ]*[_)] ?", "")
574*22ce4affSfengbojiang	arg = arg:gsub("_Out[^ ]*[_)] ?", "")
575*22ce4affSfengbojiang	return trim(arg)
576*22ce4affSfengbojiangend
577*22ce4affSfengbojiang
578*22ce4affSfengbojianglocal function check_abi_changes(arg)
579*22ce4affSfengbojiang	for k, v in pairs(known_abi_flags) do
580*22ce4affSfengbojiang		local expr = v["expr"]
581*22ce4affSfengbojiang		if abi_changes(k) and expr ~= nil and arg:find(expr) then
582*22ce4affSfengbojiang			return true
583*22ce4affSfengbojiang		end
584*22ce4affSfengbojiang	end
585*22ce4affSfengbojiang
586*22ce4affSfengbojiang	return false
587*22ce4affSfengbojiangend
588*22ce4affSfengbojiang
589*22ce4affSfengbojianglocal function process_args(args)
590*22ce4affSfengbojiang	local funcargs = {}
591*22ce4affSfengbojiang
592*22ce4affSfengbojiang	for arg in args:gmatch("([^,]+)") do
593*22ce4affSfengbojiang		local abi_change = not isptrtype(arg) or check_abi_changes(arg)
594*22ce4affSfengbojiang
595*22ce4affSfengbojiang		arg = strip_arg_annotations(arg)
596*22ce4affSfengbojiang
597*22ce4affSfengbojiang		local argname = arg:match("([^* ]+)$")
598*22ce4affSfengbojiang
599*22ce4affSfengbojiang		-- argtype is... everything else.
600*22ce4affSfengbojiang		local argtype = trim(arg:gsub(argname .. "$", ""), nil)
601*22ce4affSfengbojiang
602*22ce4affSfengbojiang		if argtype == "" and argname == "void" then
603*22ce4affSfengbojiang			goto out
604*22ce4affSfengbojiang		end
605*22ce4affSfengbojiang
606*22ce4affSfengbojiang		-- XX TODO: Forward declarations? See: sysstubfwd in CheriBSD
607*22ce4affSfengbojiang		if abi_change then
608*22ce4affSfengbojiang			local abi_type_suffix = config["abi_type_suffix"]
609*22ce4affSfengbojiang			argtype = argtype:gsub("_native ", "")
610*22ce4affSfengbojiang			argtype = argtype:gsub("(struct [^ ]*)", "%1" ..
611*22ce4affSfengbojiang			    abi_type_suffix)
612*22ce4affSfengbojiang			argtype = argtype:gsub("(union [^ ]*)", "%1" ..
613*22ce4affSfengbojiang			    abi_type_suffix)
614*22ce4affSfengbojiang		end
615*22ce4affSfengbojiang
616*22ce4affSfengbojiang		funcargs[#funcargs + 1] = {
617*22ce4affSfengbojiang			type = argtype,
618*22ce4affSfengbojiang			name = argname,
619*22ce4affSfengbojiang		}
620*22ce4affSfengbojiang	end
621*22ce4affSfengbojiang
622*22ce4affSfengbojiang	::out::
623*22ce4affSfengbojiang	return funcargs
624*22ce4affSfengbojiangend
625*22ce4affSfengbojiang
626*22ce4affSfengbojianglocal function handle_noncompat(sysnum, thr_flag, flags, sysflags, rettype,
627*22ce4affSfengbojiang    auditev, syscallret, funcname, funcalias, funcargs, argalias)
628*22ce4affSfengbojiang	local argssize
629*22ce4affSfengbojiang
630*22ce4affSfengbojiang	if #funcargs > 0 or flags & known_flags["NODEF"] ~= 0 then
631*22ce4affSfengbojiang		argssize = "AS(" .. argalias .. ")"
632*22ce4affSfengbojiang	else
633*22ce4affSfengbojiang		argssize = "0"
634*22ce4affSfengbojiang	end
635*22ce4affSfengbojiang
636*22ce4affSfengbojiang	write_line("systrace", string.format([[
637*22ce4affSfengbojiang	/* %s */
638*22ce4affSfengbojiang	case %d: {
639*22ce4affSfengbojiang]], funcname, sysnum))
640*22ce4affSfengbojiang	write_line("systracetmp", string.format([[
641*22ce4affSfengbojiang	/* %s */
642*22ce4affSfengbojiang	case %d:
643*22ce4affSfengbojiang]], funcname, sysnum))
644*22ce4affSfengbojiang	write_line("systraceret", string.format([[
645*22ce4affSfengbojiang	/* %s */
646*22ce4affSfengbojiang	case %d:
647*22ce4affSfengbojiang]], funcname, sysnum))
648*22ce4affSfengbojiang
649*22ce4affSfengbojiang	if #funcargs > 0 then
650*22ce4affSfengbojiang		write_line("systracetmp", "\t\tswitch(ndx) {\n")
651*22ce4affSfengbojiang		write_line("systrace", string.format(
652*22ce4affSfengbojiang		    "\t\tstruct %s *p = params;\n", argalias))
653*22ce4affSfengbojiang
654*22ce4affSfengbojiang		local argtype, argname
655*22ce4affSfengbojiang		for idx, arg in ipairs(funcargs) do
656*22ce4affSfengbojiang			argtype = arg["type"]
657*22ce4affSfengbojiang			argname = arg["name"]
658*22ce4affSfengbojiang
659*22ce4affSfengbojiang			argtype = trim(argtype:gsub("__restrict$", ""), nil)
660*22ce4affSfengbojiang			-- Pointer arg?
661*22ce4affSfengbojiang			if argtype:find("*") then
662*22ce4affSfengbojiang				write_line("systracetmp", string.format(
663*22ce4affSfengbojiang				    "\t\tcase %d:\n\t\t\tp = \"userland %s\";\n\t\t\tbreak;\n",
664*22ce4affSfengbojiang				    idx - 1, argtype))
665*22ce4affSfengbojiang			else
666*22ce4affSfengbojiang				write_line("systracetmp", string.format(
667*22ce4affSfengbojiang				    "\t\tcase %d:\n\t\t\tp = \"%s\";\n\t\t\tbreak;\n",
668*22ce4affSfengbojiang				    idx - 1, argtype))
669*22ce4affSfengbojiang			end
670*22ce4affSfengbojiang
671*22ce4affSfengbojiang			if isptrtype(argtype) then
672*22ce4affSfengbojiang				write_line("systrace", string.format(
673*22ce4affSfengbojiang				    "\t\tuarg[%d] = (%s) p->%s; /* %s */\n",
674*22ce4affSfengbojiang				    idx - 1, config["ptr_intptr_t_cast"],
675*22ce4affSfengbojiang				    argname, argtype))
676*22ce4affSfengbojiang			elseif argtype == "union l_semun" then
677*22ce4affSfengbojiang				write_line("systrace", string.format(
678*22ce4affSfengbojiang				    "\t\tuarg[%d] = p->%s.buf; /* %s */\n",
679*22ce4affSfengbojiang				    idx - 1, argname, argtype))
680*22ce4affSfengbojiang			elseif argtype:sub(1,1) == "u" or argtype == "size_t" then
681*22ce4affSfengbojiang				write_line("systrace", string.format(
682*22ce4affSfengbojiang				    "\t\tuarg[%d] = p->%s; /* %s */\n",
683*22ce4affSfengbojiang				    idx - 1, argname, argtype))
684*22ce4affSfengbojiang			else
685*22ce4affSfengbojiang				write_line("systrace", string.format(
686*22ce4affSfengbojiang				    "\t\tiarg[%d] = p->%s; /* %s */\n",
687*22ce4affSfengbojiang				    idx - 1, argname, argtype))
688*22ce4affSfengbojiang			end
689*22ce4affSfengbojiang		end
690*22ce4affSfengbojiang
691*22ce4affSfengbojiang		write_line("systracetmp",
692*22ce4affSfengbojiang		    "\t\tdefault:\n\t\t\tbreak;\n\t\t};\n")
693*22ce4affSfengbojiang
694*22ce4affSfengbojiang		write_line("systraceret", string.format([[
695*22ce4affSfengbojiang		if (ndx == 0 || ndx == 1)
696*22ce4affSfengbojiang			p = "%s";
697*22ce4affSfengbojiang		break;
698*22ce4affSfengbojiang]], syscallret))
699*22ce4affSfengbojiang	end
700*22ce4affSfengbojiang	write_line("systrace", string.format(
701*22ce4affSfengbojiang	    "\t\t*n_args = %d;\n\t\tbreak;\n\t}\n", #funcargs))
702*22ce4affSfengbojiang	write_line("systracetmp", "\t\tbreak;\n")
703*22ce4affSfengbojiang
704*22ce4affSfengbojiang	local nargflags = get_mask({"NOARGS", "NOPROTO", "NODEF"})
705*22ce4affSfengbojiang	if flags & nargflags == 0 then
706*22ce4affSfengbojiang		if #funcargs > 0 then
707*22ce4affSfengbojiang			write_line("sysarg", string.format("struct %s {\n",
708*22ce4affSfengbojiang			    argalias))
709*22ce4affSfengbojiang			for _, v in ipairs(funcargs) do
710*22ce4affSfengbojiang				local argname, argtype = v["name"], v["type"]
711*22ce4affSfengbojiang				write_line("sysarg", string.format(
712*22ce4affSfengbojiang				    "\tchar %s_l_[PADL_(%s)]; %s %s; char %s_r_[PADR_(%s)];\n",
713*22ce4affSfengbojiang				    argname, argtype,
714*22ce4affSfengbojiang				    argtype, argname,
715*22ce4affSfengbojiang				    argname, argtype))
716*22ce4affSfengbojiang			end
717*22ce4affSfengbojiang			write_line("sysarg", "};\n")
718*22ce4affSfengbojiang		else
719*22ce4affSfengbojiang			write_line("sysarg", string.format(
720*22ce4affSfengbojiang			    "struct %s {\n\tregister_t dummy;\n};\n", argalias))
721*22ce4affSfengbojiang		end
722*22ce4affSfengbojiang	end
723*22ce4affSfengbojiang
724*22ce4affSfengbojiang	local protoflags = get_mask({"NOPROTO", "NODEF"})
725*22ce4affSfengbojiang	if flags & protoflags == 0 then
726*22ce4affSfengbojiang		if funcname == "nosys" or funcname == "lkmnosys" or
727*22ce4affSfengbojiang		    funcname == "sysarch" or funcname:find("^freebsd") or
728*22ce4affSfengbojiang		    funcname:find("^linux") or
729*22ce4affSfengbojiang		    funcname:find("^cloudabi") then
730*22ce4affSfengbojiang			write_line("sysdcl", string.format(
731*22ce4affSfengbojiang			    "%s\t%s(struct thread *, struct %s *)",
732*22ce4affSfengbojiang			    rettype, funcname, argalias))
733*22ce4affSfengbojiang		else
734*22ce4affSfengbojiang			write_line("sysdcl", string.format(
735*22ce4affSfengbojiang			    "%s\tsys_%s(struct thread *, struct %s *)",
736*22ce4affSfengbojiang			    rettype, funcname, argalias))
737*22ce4affSfengbojiang		end
738*22ce4affSfengbojiang		write_line("sysdcl", ";\n")
739*22ce4affSfengbojiang		write_line("sysaue", string.format("#define\t%sAUE_%s\t%s\n",
740*22ce4affSfengbojiang		    config['syscallprefix'], funcalias, auditev))
741*22ce4affSfengbojiang	end
742*22ce4affSfengbojiang
743*22ce4affSfengbojiang	write_line("sysent",
744*22ce4affSfengbojiang	    string.format("\t{ .sy_narg = %s, .sy_call = (sy_call_t *)", argssize))
745*22ce4affSfengbojiang	local column = 8 + 2 + #argssize + 15
746*22ce4affSfengbojiang
747*22ce4affSfengbojiang	if flags & known_flags["NOSTD"] ~= 0 then
748*22ce4affSfengbojiang		write_line("sysent", string.format(
749*22ce4affSfengbojiang		    "lkmressys, .sy_auevent = AUE_NULL, " ..
750*22ce4affSfengbojiang		    ".sy_flags = %s, .sy_thrcnt = SY_THR_ABSENT },",
751*22ce4affSfengbojiang		    sysflags))
752*22ce4affSfengbojiang		column = column + #"lkmressys" + #"AUE_NULL" + 3
753*22ce4affSfengbojiang	else
754*22ce4affSfengbojiang		if funcname == "nosys" or funcname == "lkmnosys" or
755*22ce4affSfengbojiang		    funcname == "sysarch" or funcname:find("^freebsd") or
756*22ce4affSfengbojiang		    funcname:find("^linux") or
757*22ce4affSfengbojiang		    funcname:find("^cloudabi") then
758*22ce4affSfengbojiang			write_line("sysent", string.format(
759*22ce4affSfengbojiang			    "%s, .sy_auevent = %s, .sy_flags = %s, .sy_thrcnt = %s },",
760*22ce4affSfengbojiang			    funcname, auditev, sysflags, thr_flag))
761*22ce4affSfengbojiang			column = column + #funcname + #auditev + #sysflags + 3
762*22ce4affSfengbojiang		else
763*22ce4affSfengbojiang			write_line("sysent", string.format(
764*22ce4affSfengbojiang			    "sys_%s, .sy_auevent = %s, .sy_flags = %s, .sy_thrcnt = %s },",
765*22ce4affSfengbojiang			    funcname, auditev, sysflags, thr_flag))
766*22ce4affSfengbojiang			column = column + #funcname + #auditev + #sysflags + 7
767*22ce4affSfengbojiang		end
768*22ce4affSfengbojiang	end
769*22ce4affSfengbojiang
770*22ce4affSfengbojiang	align_sysent_comment(column)
771*22ce4affSfengbojiang	write_line("sysent", string.format("/* %d = %s */\n",
772*22ce4affSfengbojiang	    sysnum, funcalias))
773*22ce4affSfengbojiang	write_line("sysnames", string.format("\t\"%s\",\t\t\t/* %d = %s */\n",
774*22ce4affSfengbojiang	    funcalias, sysnum, funcalias))
775*22ce4affSfengbojiang
776*22ce4affSfengbojiang	if flags & known_flags["NODEF"] == 0 then
777*22ce4affSfengbojiang		write_line("syshdr", string.format("#define\t%s%s\t%d\n",
778*22ce4affSfengbojiang		    config['syscallprefix'], funcalias, sysnum))
779*22ce4affSfengbojiang		write_line("sysmk", string.format(" \\\n\t%s.o",
780*22ce4affSfengbojiang		    funcalias))
781*22ce4affSfengbojiang	end
782*22ce4affSfengbojiangend
783*22ce4affSfengbojiang
784*22ce4affSfengbojianglocal function handle_obsol(sysnum, funcname, comment)
785*22ce4affSfengbojiang	write_line("sysent",
786*22ce4affSfengbojiang	    "\t{ .sy_narg = 0, .sy_call = (sy_call_t *)nosys, " ..
787*22ce4affSfengbojiang	    ".sy_auevent = AUE_NULL, .sy_flags = 0, .sy_thrcnt = SY_THR_ABSENT },")
788*22ce4affSfengbojiang	align_sysent_comment(34)
789*22ce4affSfengbojiang
790*22ce4affSfengbojiang	write_line("sysent", string.format("/* %d = obsolete %s */\n",
791*22ce4affSfengbojiang	    sysnum, comment))
792*22ce4affSfengbojiang	write_line("sysnames", string.format(
793*22ce4affSfengbojiang	    "\t\"obs_%s\",\t\t\t/* %d = obsolete %s */\n",
794*22ce4affSfengbojiang	    funcname, sysnum, comment))
795*22ce4affSfengbojiang	write_line("syshdr", string.format("\t\t\t\t/* %d is obsolete %s */\n",
796*22ce4affSfengbojiang	    sysnum, comment))
797*22ce4affSfengbojiangend
798*22ce4affSfengbojiang
799*22ce4affSfengbojianglocal function handle_compat(sysnum, thr_flag, flags, sysflags, rettype,
800*22ce4affSfengbojiang    auditev, funcname, funcalias, funcargs, argalias)
801*22ce4affSfengbojiang	local argssize, out, outdcl, wrap, prefix, descr
802*22ce4affSfengbojiang
803*22ce4affSfengbojiang	if #funcargs > 0 or flags & known_flags["NODEF"] ~= 0 then
804*22ce4affSfengbojiang		argssize = "AS(" .. argalias .. ")"
805*22ce4affSfengbojiang	else
806*22ce4affSfengbojiang		argssize = "0"
807*22ce4affSfengbojiang	end
808*22ce4affSfengbojiang
809*22ce4affSfengbojiang	for _, v in pairs(compat_options) do
810*22ce4affSfengbojiang		if flags & v["mask"] ~= 0 then
811*22ce4affSfengbojiang			if config["mincompat"] > v["compatlevel"] then
812*22ce4affSfengbojiang				funcname = strip_abi_prefix(funcname)
813*22ce4affSfengbojiang				funcname = v["prefix"] .. funcname
814*22ce4affSfengbojiang				return handle_obsol(sysnum, funcname, funcname)
815*22ce4affSfengbojiang			end
816*22ce4affSfengbojiang			v["count"] = v["count"] + 1
817*22ce4affSfengbojiang			out = v["tmp"]
818*22ce4affSfengbojiang			outdcl = v["dcltmp"]
819*22ce4affSfengbojiang			wrap = v["flag"]:lower()
820*22ce4affSfengbojiang			prefix = v["prefix"]
821*22ce4affSfengbojiang			descr = v["descr"]
822*22ce4affSfengbojiang			goto compatdone
823*22ce4affSfengbojiang		end
824*22ce4affSfengbojiang	end
825*22ce4affSfengbojiang
826*22ce4affSfengbojiang	::compatdone::
827*22ce4affSfengbojiang	local dprotoflags = get_mask({"NOPROTO", "NODEF"})
828*22ce4affSfengbojiang	local nargflags = dprotoflags | known_flags["NOARGS"]
829*22ce4affSfengbojiang	if #funcargs > 0 and flags & nargflags == 0 then
830*22ce4affSfengbojiang		write_line(out, string.format("struct %s {\n", argalias))
831*22ce4affSfengbojiang		for _, v in ipairs(funcargs) do
832*22ce4affSfengbojiang			local argname, argtype = v["name"], v["type"]
833*22ce4affSfengbojiang			write_line(out, string.format(
834*22ce4affSfengbojiang			    "\tchar %s_l_[PADL_(%s)]; %s %s; char %s_r_[PADR_(%s)];\n",
835*22ce4affSfengbojiang			    argname, argtype,
836*22ce4affSfengbojiang			    argtype, argname,
837*22ce4affSfengbojiang			    argname, argtype))
838*22ce4affSfengbojiang		end
839*22ce4affSfengbojiang		write_line(out, "};\n")
840*22ce4affSfengbojiang	elseif flags & nargflags == 0 then
841*22ce4affSfengbojiang		write_line("sysarg", string.format(
842*22ce4affSfengbojiang		    "struct %s {\n\tregister_t dummy;\n};\n", argalias))
843*22ce4affSfengbojiang	end
844*22ce4affSfengbojiang	if flags & dprotoflags == 0 then
845*22ce4affSfengbojiang		write_line(outdcl, string.format(
846*22ce4affSfengbojiang		    "%s\t%s%s(struct thread *, struct %s *);\n",
847*22ce4affSfengbojiang		    rettype, prefix, funcname, argalias))
848*22ce4affSfengbojiang		write_line("sysaue", string.format(
849*22ce4affSfengbojiang		    "#define\t%sAUE_%s%s\t%s\n", config['syscallprefix'],
850*22ce4affSfengbojiang		    prefix, funcname, auditev))
851*22ce4affSfengbojiang	end
852*22ce4affSfengbojiang
853*22ce4affSfengbojiang	if flags & known_flags['NOSTD'] ~= 0 then
854*22ce4affSfengbojiang		write_line("sysent", string.format(
855*22ce4affSfengbojiang		    "\t{ .sy_narg = %s, .sy_call = (sy_call_t *)%s, " ..
856*22ce4affSfengbojiang		    ".sy_auevent = %s, .sy_flags = 0, " ..
857*22ce4affSfengbojiang		    ".sy_thrcnt = SY_THR_ABSENT },",
858*22ce4affSfengbojiang		    "0", "lkmressys", "AUE_NULL"))
859*22ce4affSfengbojiang		align_sysent_comment(8 + 2 + #"0" + 15 + #"lkmressys" +
860*22ce4affSfengbojiang		    #"AUE_NULL" + 3)
861*22ce4affSfengbojiang	else
862*22ce4affSfengbojiang		write_line("sysent", string.format(
863*22ce4affSfengbojiang		    "\t{ %s(%s,%s), .sy_auevent = %s, .sy_flags = %s, .sy_thrcnt = %s },",
864*22ce4affSfengbojiang		    wrap, argssize, funcname, auditev, sysflags, thr_flag))
865*22ce4affSfengbojiang		align_sysent_comment(8 + 9 + #argssize + 1 + #funcname +
866*22ce4affSfengbojiang		    #auditev + #sysflags + 4)
867*22ce4affSfengbojiang	end
868*22ce4affSfengbojiang
869*22ce4affSfengbojiang	write_line("sysent", string.format("/* %d = %s %s */\n",
870*22ce4affSfengbojiang	    sysnum, descr, funcalias))
871*22ce4affSfengbojiang	write_line("sysnames", string.format(
872*22ce4affSfengbojiang	    "\t\"%s.%s\",\t\t/* %d = %s %s */\n",
873*22ce4affSfengbojiang	    wrap, funcalias, sysnum, descr, funcalias))
874*22ce4affSfengbojiang	-- Do not provide freebsdN_* symbols in libc for < FreeBSD 7
875*22ce4affSfengbojiang	local nosymflags = get_mask({"COMPAT", "COMPAT4", "COMPAT6"})
876*22ce4affSfengbojiang	if flags & nosymflags ~= 0 then
877*22ce4affSfengbojiang		write_line("syshdr", string.format(
878*22ce4affSfengbojiang		    "\t\t\t\t/* %d is %s %s */\n",
879*22ce4affSfengbojiang		    sysnum, descr, funcalias))
880*22ce4affSfengbojiang	elseif flags & known_flags["NODEF"] == 0 then
881*22ce4affSfengbojiang		write_line("syshdr", string.format("#define\t%s%s%s\t%d\n",
882*22ce4affSfengbojiang		    config['syscallprefix'], prefix, funcalias, sysnum))
883*22ce4affSfengbojiang		write_line("sysmk", string.format(" \\\n\t%s%s.o",
884*22ce4affSfengbojiang		    prefix, funcalias))
885*22ce4affSfengbojiang	end
886*22ce4affSfengbojiangend
887*22ce4affSfengbojiang
888*22ce4affSfengbojianglocal function handle_unimpl(sysnum, sysstart, sysend, comment)
889*22ce4affSfengbojiang	if sysstart == nil and sysend == nil then
890*22ce4affSfengbojiang		sysstart = tonumber(sysnum)
891*22ce4affSfengbojiang		sysend = tonumber(sysnum)
892*22ce4affSfengbojiang	end
893*22ce4affSfengbojiang
894*22ce4affSfengbojiang	sysnum = sysstart
895*22ce4affSfengbojiang	while sysnum <= sysend do
896*22ce4affSfengbojiang		write_line("sysent", string.format(
897*22ce4affSfengbojiang		    "\t{ .sy_narg = 0, .sy_call = (sy_call_t *)nosys, " ..
898*22ce4affSfengbojiang		    ".sy_auevent = AUE_NULL, .sy_flags = 0, " ..
899*22ce4affSfengbojiang		    ".sy_thrcnt = SY_THR_ABSENT },\t\t\t/* %d = %s */\n",
900*22ce4affSfengbojiang		    sysnum, comment))
901*22ce4affSfengbojiang		write_line("sysnames", string.format(
902*22ce4affSfengbojiang		    "\t\"#%d\",\t\t\t/* %d = %s */\n",
903*22ce4affSfengbojiang		    sysnum, sysnum, comment))
904*22ce4affSfengbojiang		sysnum = sysnum + 1
905*22ce4affSfengbojiang	end
906*22ce4affSfengbojiangend
907*22ce4affSfengbojiang
908*22ce4affSfengbojiangprocess_syscall_def = function(line)
909*22ce4affSfengbojiang	local sysstart, sysend, flags, funcname, sysflags
910*22ce4affSfengbojiang	local thr_flag, syscallret
911*22ce4affSfengbojiang	local orig = line
912*22ce4affSfengbojiang	flags = 0
913*22ce4affSfengbojiang	thr_flag = "SY_THR_STATIC"
914*22ce4affSfengbojiang
915*22ce4affSfengbojiang	-- Parse out the interesting information first
916*22ce4affSfengbojiang	local initialExpr = "^([^%s]+)%s+([^%s]+)%s+([^%s]+)%s*"
917*22ce4affSfengbojiang	local sysnum, auditev, allflags = line:match(initialExpr)
918*22ce4affSfengbojiang
919*22ce4affSfengbojiang	if sysnum == nil or auditev == nil or allflags == nil then
920*22ce4affSfengbojiang		-- XXX TODO: Better?
921*22ce4affSfengbojiang		abort(1, "Completely malformed: " .. line)
922*22ce4affSfengbojiang	end
923*22ce4affSfengbojiang
924*22ce4affSfengbojiang	if sysnum:find("-") then
925*22ce4affSfengbojiang		sysstart, sysend = sysnum:match("^([%d]+)-([%d]+)$")
926*22ce4affSfengbojiang		if sysstart == nil or sysend == nil then
927*22ce4affSfengbojiang			abort(1, "Malformed range: " .. sysnum)
928*22ce4affSfengbojiang		end
929*22ce4affSfengbojiang		sysnum = nil
930*22ce4affSfengbojiang		sysstart = tonumber(sysstart)
931*22ce4affSfengbojiang		sysend = tonumber(sysend)
932*22ce4affSfengbojiang		if sysstart ~= maxsyscall + 1 then
933*22ce4affSfengbojiang			abort(1, "syscall number out of sync, missing " ..
934*22ce4affSfengbojiang			    maxsyscall + 1)
935*22ce4affSfengbojiang		end
936*22ce4affSfengbojiang	else
937*22ce4affSfengbojiang		sysnum = tonumber(sysnum)
938*22ce4affSfengbojiang		if sysnum ~= maxsyscall + 1 then
939*22ce4affSfengbojiang			abort(1, "syscall number out of sync, missing " ..
940*22ce4affSfengbojiang			    maxsyscall + 1)
941*22ce4affSfengbojiang		end
942*22ce4affSfengbojiang	end
943*22ce4affSfengbojiang
944*22ce4affSfengbojiang	-- Split flags
945*22ce4affSfengbojiang	for flag in allflags:gmatch("([^|]+)") do
946*22ce4affSfengbojiang		if known_flags[flag] == nil then
947*22ce4affSfengbojiang			abort(1, "Unknown flag " .. flag .. " for " ..  sysnum)
948*22ce4affSfengbojiang		end
949*22ce4affSfengbojiang		flags = flags | known_flags[flag]
950*22ce4affSfengbojiang	end
951*22ce4affSfengbojiang
952*22ce4affSfengbojiang	if (flags & known_flags["UNIMPL"]) == 0 and sysnum == nil then
953*22ce4affSfengbojiang		abort(1, "Range only allowed with UNIMPL: " .. line)
954*22ce4affSfengbojiang	end
955*22ce4affSfengbojiang
956*22ce4affSfengbojiang	if (flags & known_flags["NOTSTATIC"]) ~= 0 then
957*22ce4affSfengbojiang		thr_flag = "SY_THR_ABSENT"
958*22ce4affSfengbojiang	end
959*22ce4affSfengbojiang
960*22ce4affSfengbojiang	-- Strip earlier bits out, leave declaration + alt
961*22ce4affSfengbojiang	line = line:gsub("^.+" .. allflags .. "%s*", "")
962*22ce4affSfengbojiang
963*22ce4affSfengbojiang	local decl_fnd = line:find("^{") ~= nil
964*22ce4affSfengbojiang	if decl_fnd and line:find("}") == nil then
965*22ce4affSfengbojiang		abort(1, "Malformed, no closing brace: " .. line)
966*22ce4affSfengbojiang	end
967*22ce4affSfengbojiang
968*22ce4affSfengbojiang	local decl, alt
969*22ce4affSfengbojiang	if decl_fnd then
970*22ce4affSfengbojiang		line = line:gsub("^{", "")
971*22ce4affSfengbojiang		decl, alt = line:match("([^}]*)}[%s]*(.*)$")
972*22ce4affSfengbojiang	else
973*22ce4affSfengbojiang		alt = line
974*22ce4affSfengbojiang	end
975*22ce4affSfengbojiang
976*22ce4affSfengbojiang	if decl == nil and alt == nil then
977*22ce4affSfengbojiang		abort(1, "Malformed bits: " .. line)
978*22ce4affSfengbojiang	end
979*22ce4affSfengbojiang
980*22ce4affSfengbojiang	local funcalias, funcomment, argalias, rettype, args
981*22ce4affSfengbojiang	if not decl_fnd and alt ~= nil and alt ~= "" then
982*22ce4affSfengbojiang		-- Peel off one entry for name
983*22ce4affSfengbojiang		funcname = trim(alt:match("^([^%s]+)"), nil)
984*22ce4affSfengbojiang		alt = alt:gsub("^([^%s]+)[%s]*", "")
985*22ce4affSfengbojiang	end
986*22ce4affSfengbojiang	-- Do we even need it?
987*22ce4affSfengbojiang	if flags & get_mask({"OBSOL", "UNIMPL"}) ~= 0 then
988*22ce4affSfengbojiang		local NF = 0
989*22ce4affSfengbojiang		for _ in orig:gmatch("[^%s]+") do
990*22ce4affSfengbojiang			NF = NF + 1
991*22ce4affSfengbojiang		end
992*22ce4affSfengbojiang
993*22ce4affSfengbojiang		funcomment = funcname or ''
994*22ce4affSfengbojiang		if NF < 6 then
995*22ce4affSfengbojiang			funcomment = funcomment .. " " .. alt
996*22ce4affSfengbojiang		end
997*22ce4affSfengbojiang
998*22ce4affSfengbojiang		funcomment = trim(funcomment)
999*22ce4affSfengbojiang
1000*22ce4affSfengbojiang--		if funcname ~= nil then
1001*22ce4affSfengbojiang--		else
1002*22ce4affSfengbojiang--			funcomment = trim(alt)
1003*22ce4affSfengbojiang--		end
1004*22ce4affSfengbojiang		goto skipalt
1005*22ce4affSfengbojiang	end
1006*22ce4affSfengbojiang
1007*22ce4affSfengbojiang	if alt ~= nil and alt ~= "" then
1008*22ce4affSfengbojiang		local altExpr = "^([^%s]+)%s+([^%s]+)%s+([^%s]+)"
1009*22ce4affSfengbojiang		funcalias, argalias, rettype = alt:match(altExpr)
1010*22ce4affSfengbojiang		funcalias = trim(funcalias)
1011*22ce4affSfengbojiang		if funcalias == nil or argalias == nil or rettype == nil then
1012*22ce4affSfengbojiang			abort(1, "Malformed alt: " .. line)
1013*22ce4affSfengbojiang		end
1014*22ce4affSfengbojiang	end
1015*22ce4affSfengbojiang	if decl_fnd then
1016*22ce4affSfengbojiang		-- Don't clobber rettype set in the alt information
1017*22ce4affSfengbojiang		if rettype == nil then
1018*22ce4affSfengbojiang			rettype = "int"
1019*22ce4affSfengbojiang		end
1020*22ce4affSfengbojiang		-- Peel off the return type
1021*22ce4affSfengbojiang		syscallret = line:match("([^%s]+)%s")
1022*22ce4affSfengbojiang		line = line:match("[^%s]+%s(.+)")
1023*22ce4affSfengbojiang		-- Pointer incoming
1024*22ce4affSfengbojiang		if line:sub(1,1) == "*" then
1025*22ce4affSfengbojiang			syscallret = syscallret .. " "
1026*22ce4affSfengbojiang		end
1027*22ce4affSfengbojiang		while line:sub(1,1) == "*" do
1028*22ce4affSfengbojiang			line = line:sub(2)
1029*22ce4affSfengbojiang			syscallret = syscallret .. "*"
1030*22ce4affSfengbojiang		end
1031*22ce4affSfengbojiang		funcname = line:match("^([^(]+)%(")
1032*22ce4affSfengbojiang		if funcname == nil then
1033*22ce4affSfengbojiang			abort(1, "Not a signature? " .. line)
1034*22ce4affSfengbojiang		end
1035*22ce4affSfengbojiang		args = line:match("^[^(]+%((.+)%)[^)]*$")
1036*22ce4affSfengbojiang		args = trim(args, '[,%s]')
1037*22ce4affSfengbojiang	end
1038*22ce4affSfengbojiang
1039*22ce4affSfengbojiang	::skipalt::
1040*22ce4affSfengbojiang
1041*22ce4affSfengbojiang	if funcname == nil then
1042*22ce4affSfengbojiang		funcname = funcalias
1043*22ce4affSfengbojiang	end
1044*22ce4affSfengbojiang
1045*22ce4affSfengbojiang	funcname = trim(funcname)
1046*22ce4affSfengbojiang
1047*22ce4affSfengbojiang	sysflags = "0"
1048*22ce4affSfengbojiang
1049*22ce4affSfengbojiang	-- NODEF events do not get audited
1050*22ce4affSfengbojiang	if flags & known_flags['NODEF'] ~= 0 then
1051*22ce4affSfengbojiang		auditev = 'AUE_NULL'
1052*22ce4affSfengbojiang	end
1053*22ce4affSfengbojiang
1054*22ce4affSfengbojiang	-- If applicable; strip the ABI prefix from the name
1055*22ce4affSfengbojiang	local stripped_name = strip_abi_prefix(funcname)
1056*22ce4affSfengbojiang
1057*22ce4affSfengbojiang	if config["capenabled"][funcname] ~= nil or
1058*22ce4affSfengbojiang	    config["capenabled"][stripped_name] ~= nil then
1059*22ce4affSfengbojiang		sysflags = "SYF_CAPENABLED"
1060*22ce4affSfengbojiang	end
1061*22ce4affSfengbojiang
1062*22ce4affSfengbojiang	local funcargs = {}
1063*22ce4affSfengbojiang	if args ~= nil then
1064*22ce4affSfengbojiang		funcargs = process_args(args)
1065*22ce4affSfengbojiang	end
1066*22ce4affSfengbojiang
1067*22ce4affSfengbojiang	local argprefix = ''
1068*22ce4affSfengbojiang	if abi_changes("pointer_args") then
1069*22ce4affSfengbojiang		for _, v in ipairs(funcargs) do
1070*22ce4affSfengbojiang			if isptrtype(v["type"]) then
1071*22ce4affSfengbojiang				-- argalias should be:
1072*22ce4affSfengbojiang				--   COMPAT_PREFIX + ABI Prefix + funcname
1073*22ce4affSfengbojiang				argprefix = config['abi_func_prefix']
1074*22ce4affSfengbojiang				funcalias = config['abi_func_prefix'] ..
1075*22ce4affSfengbojiang				    funcname
1076*22ce4affSfengbojiang				goto ptrfound
1077*22ce4affSfengbojiang			end
1078*22ce4affSfengbojiang		end
1079*22ce4affSfengbojiang		::ptrfound::
1080*22ce4affSfengbojiang	end
1081*22ce4affSfengbojiang	if funcalias == nil or funcalias == "" then
1082*22ce4affSfengbojiang		funcalias = funcname
1083*22ce4affSfengbojiang	end
1084*22ce4affSfengbojiang
1085*22ce4affSfengbojiang	if argalias == nil and funcname ~= nil then
1086*22ce4affSfengbojiang		argalias = argprefix .. funcname .. "_args"
1087*22ce4affSfengbojiang		for _, v in pairs(compat_options) do
1088*22ce4affSfengbojiang			local mask = v["mask"]
1089*22ce4affSfengbojiang			if (flags & mask) ~= 0 then
1090*22ce4affSfengbojiang				-- Multiple aliases doesn't seem to make
1091*22ce4affSfengbojiang				-- sense.
1092*22ce4affSfengbojiang				argalias = v["prefix"] .. argalias
1093*22ce4affSfengbojiang				goto out
1094*22ce4affSfengbojiang			end
1095*22ce4affSfengbojiang		end
1096*22ce4affSfengbojiang		::out::
1097*22ce4affSfengbojiang	elseif argalias ~= nil then
1098*22ce4affSfengbojiang		argalias = argprefix .. argalias
1099*22ce4affSfengbojiang	end
1100*22ce4affSfengbojiang
1101*22ce4affSfengbojiang	local ncompatflags = get_mask({"STD", "NODEF", "NOARGS", "NOPROTO",
1102*22ce4affSfengbojiang	    "NOSTD"})
1103*22ce4affSfengbojiang	local compatflags = get_mask_pat("COMPAT.*")
1104*22ce4affSfengbojiang	-- Now try compat...
1105*22ce4affSfengbojiang	if flags & compatflags ~= 0 then
1106*22ce4affSfengbojiang		if flags & known_flags['STD'] ~= 0 then
1107*22ce4affSfengbojiang			abort(1, "Incompatible COMPAT/STD: " .. line)
1108*22ce4affSfengbojiang		end
1109*22ce4affSfengbojiang		handle_compat(sysnum, thr_flag, flags, sysflags, rettype,
1110*22ce4affSfengbojiang		    auditev, funcname, funcalias, funcargs, argalias)
1111*22ce4affSfengbojiang	elseif flags & ncompatflags ~= 0 then
1112*22ce4affSfengbojiang		handle_noncompat(sysnum, thr_flag, flags, sysflags, rettype,
1113*22ce4affSfengbojiang		    auditev, syscallret, funcname, funcalias, funcargs,
1114*22ce4affSfengbojiang		    argalias)
1115*22ce4affSfengbojiang	elseif flags & known_flags["OBSOL"] ~= 0 then
1116*22ce4affSfengbojiang		handle_obsol(sysnum, funcname, funcomment)
1117*22ce4affSfengbojiang	elseif flags & known_flags["UNIMPL"] ~= 0 then
1118*22ce4affSfengbojiang		handle_unimpl(sysnum, sysstart, sysend, funcomment)
1119*22ce4affSfengbojiang	else
1120*22ce4affSfengbojiang		abort(1, "Bad flags? " .. line)
1121*22ce4affSfengbojiang	end
1122*22ce4affSfengbojiang
1123*22ce4affSfengbojiang	if sysend ~= nil then
1124*22ce4affSfengbojiang		maxsyscall = sysend
1125*22ce4affSfengbojiang	elseif sysnum ~= nil then
1126*22ce4affSfengbojiang		maxsyscall = sysnum
1127*22ce4affSfengbojiang	end
1128*22ce4affSfengbojiangend
1129*22ce4affSfengbojiang
1130*22ce4affSfengbojiang-- Entry point
1131*22ce4affSfengbojiang
1132*22ce4affSfengbojiangif #arg < 1 or #arg > 2 then
1133*22ce4affSfengbojiang	abort(1, "usage: " .. arg[0] .. " input-file <config-file>")
1134*22ce4affSfengbojiangend
1135*22ce4affSfengbojiang
1136*22ce4affSfengbojianglocal sysfile, configfile = arg[1], arg[2]
1137*22ce4affSfengbojiang
1138*22ce4affSfengbojiang-- process_config either returns nil and a message, or a
1139*22ce4affSfengbojiang-- table that we should merge into the global config
1140*22ce4affSfengbojiangif configfile ~= nil then
1141*22ce4affSfengbojiang	local res, msg = process_config(configfile)
1142*22ce4affSfengbojiang
1143*22ce4affSfengbojiang	if res == nil then
1144*22ce4affSfengbojiang		-- Error... handle?
1145*22ce4affSfengbojiang		print(msg)
1146*22ce4affSfengbojiang		os.exit(1)
1147*22ce4affSfengbojiang	end
1148*22ce4affSfengbojiang
1149*22ce4affSfengbojiang	for k, v in pairs(res) do
1150*22ce4affSfengbojiang		if v ~= config[k] then
1151*22ce4affSfengbojiang			config[k] = v
1152*22ce4affSfengbojiang			config_modified[k] = true
1153*22ce4affSfengbojiang		end
1154*22ce4affSfengbojiang	end
1155*22ce4affSfengbojiangend
1156*22ce4affSfengbojiang
1157*22ce4affSfengbojiang-- We ignore errors here if we're relying on the default configuration.
1158*22ce4affSfengbojiangif not config_modified["capenabled"] then
1159*22ce4affSfengbojiang	config["capenabled"] = grab_capenabled(config['capabilities_conf'],
1160*22ce4affSfengbojiang	    config_modified["capabilities_conf"] == nil)
1161*22ce4affSfengbojiangelseif config["capenabled"] ~= "" then
1162*22ce4affSfengbojiang	-- Due to limitations in the config format mostly, we'll have a comma
1163*22ce4affSfengbojiang	-- separated list.  Parse it into lines
1164*22ce4affSfengbojiang	local capenabled = {}
1165*22ce4affSfengbojiang	-- print("here: " .. config["capenabled"])
1166*22ce4affSfengbojiang	for sysc in config["capenabled"]:gmatch("([^,]+)") do
1167*22ce4affSfengbojiang		capenabled[sysc] = true
1168*22ce4affSfengbojiang	end
1169*22ce4affSfengbojiang	config["capenabled"] = capenabled
1170*22ce4affSfengbojiangend
1171*22ce4affSfengbojiangprocess_compat()
1172*22ce4affSfengbojiangprocess_abi_flags()
1173*22ce4affSfengbojiang
1174*22ce4affSfengbojiangif not lfs.mkdir(tmpspace) then
1175*22ce4affSfengbojiang	abort(1, "Failed to create tempdir " .. tmpspace)
1176*22ce4affSfengbojiangend
1177*22ce4affSfengbojiang
1178*22ce4affSfengbojiangfor _, v in ipairs(temp_files) do
1179*22ce4affSfengbojiang	local tmpname = tmpspace .. v
1180*22ce4affSfengbojiang	files[v] = io.open(tmpname, "w+")
1181*22ce4affSfengbojiangend
1182*22ce4affSfengbojiang
1183*22ce4affSfengbojiangfor _, v in ipairs(output_files) do
1184*22ce4affSfengbojiang	local tmpname = tmpspace .. v
1185*22ce4affSfengbojiang	files[v] = io.open(tmpname, "w+")
1186*22ce4affSfengbojiangend
1187*22ce4affSfengbojiang
1188*22ce4affSfengbojiang-- Write out all of the preamble bits
1189*22ce4affSfengbojiangwrite_line("sysent", string.format([[
1190*22ce4affSfengbojiang
1191*22ce4affSfengbojiang/* The casts are bogus but will do for now. */
1192*22ce4affSfengbojiangstruct sysent %s[] = {
1193*22ce4affSfengbojiang]], config['switchname']))
1194*22ce4affSfengbojiang
1195*22ce4affSfengbojiangwrite_line("syssw", string.format([[/*
1196*22ce4affSfengbojiang * System call switch table.
1197*22ce4affSfengbojiang *
1198*22ce4affSfengbojiang * DO NOT EDIT-- this file is automatically %s.
1199*22ce4affSfengbojiang * $%s$
1200*22ce4affSfengbojiang */
1201*22ce4affSfengbojiang
1202*22ce4affSfengbojiang]], generated_tag, config['os_id_keyword']))
1203*22ce4affSfengbojiang
1204*22ce4affSfengbojiangwrite_line("sysarg", string.format([[/*
1205*22ce4affSfengbojiang * System call prototypes.
1206*22ce4affSfengbojiang *
1207*22ce4affSfengbojiang * DO NOT EDIT-- this file is automatically %s.
1208*22ce4affSfengbojiang * $%s$
1209*22ce4affSfengbojiang */
1210*22ce4affSfengbojiang
1211*22ce4affSfengbojiang#ifndef %s
1212*22ce4affSfengbojiang#define	%s
1213*22ce4affSfengbojiang
1214*22ce4affSfengbojiang#include <sys/signal.h>
1215*22ce4affSfengbojiang#include <sys/acl.h>
1216*22ce4affSfengbojiang#include <sys/cpuset.h>
1217*22ce4affSfengbojiang#include <sys/domainset.h>
1218*22ce4affSfengbojiang#include <sys/_ffcounter.h>
1219*22ce4affSfengbojiang#include <sys/_semaphore.h>
1220*22ce4affSfengbojiang#include <sys/ucontext.h>
1221*22ce4affSfengbojiang#include <sys/wait.h>
1222*22ce4affSfengbojiang
1223*22ce4affSfengbojiang#include <bsm/audit_kevents.h>
1224*22ce4affSfengbojiang
1225*22ce4affSfengbojiangstruct proc;
1226*22ce4affSfengbojiang
1227*22ce4affSfengbojiangstruct thread;
1228*22ce4affSfengbojiang
1229*22ce4affSfengbojiang#define	PAD_(t)	(sizeof(register_t) <= sizeof(t) ? \
1230*22ce4affSfengbojiang		0 : sizeof(register_t) - sizeof(t))
1231*22ce4affSfengbojiang
1232*22ce4affSfengbojiang#if BYTE_ORDER == LITTLE_ENDIAN
1233*22ce4affSfengbojiang#define	PADL_(t)	0
1234*22ce4affSfengbojiang#define	PADR_(t)	PAD_(t)
1235*22ce4affSfengbojiang#else
1236*22ce4affSfengbojiang#define	PADL_(t)	PAD_(t)
1237*22ce4affSfengbojiang#define	PADR_(t)	0
1238*22ce4affSfengbojiang#endif
1239*22ce4affSfengbojiang
1240*22ce4affSfengbojiang]], generated_tag, config['os_id_keyword'], config['sysproto_h'],
1241*22ce4affSfengbojiang    config['sysproto_h']))
1242*22ce4affSfengbojiangfor _, v in pairs(compat_options) do
1243*22ce4affSfengbojiang	write_line(v["tmp"], string.format("\n#ifdef %s\n\n", v["definition"]))
1244*22ce4affSfengbojiangend
1245*22ce4affSfengbojiang
1246*22ce4affSfengbojiangwrite_line("sysnames", string.format([[/*
1247*22ce4affSfengbojiang * System call names.
1248*22ce4affSfengbojiang *
1249*22ce4affSfengbojiang * DO NOT EDIT-- this file is automatically %s.
1250*22ce4affSfengbojiang * $%s$
1251*22ce4affSfengbojiang */
1252*22ce4affSfengbojiang
1253*22ce4affSfengbojiangconst char *%s[] = {
1254*22ce4affSfengbojiang]], generated_tag, config['os_id_keyword'], config['namesname']))
1255*22ce4affSfengbojiang
1256*22ce4affSfengbojiangwrite_line("syshdr", string.format([[/*
1257*22ce4affSfengbojiang * System call numbers.
1258*22ce4affSfengbojiang *
1259*22ce4affSfengbojiang * DO NOT EDIT-- this file is automatically %s.
1260*22ce4affSfengbojiang * $%s$
1261*22ce4affSfengbojiang */
1262*22ce4affSfengbojiang
1263*22ce4affSfengbojiang]], generated_tag, config['os_id_keyword']))
1264*22ce4affSfengbojiang
1265*22ce4affSfengbojiangwrite_line("sysmk", string.format([[# FreeBSD system call object files.
1266*22ce4affSfengbojiang# DO NOT EDIT-- this file is automatically %s.
1267*22ce4affSfengbojiang# $%s$
1268*22ce4affSfengbojiangMIASM = ]], generated_tag, config['os_id_keyword']))
1269*22ce4affSfengbojiang
1270*22ce4affSfengbojiangwrite_line("systrace", string.format([[/*
1271*22ce4affSfengbojiang * System call argument to DTrace register array converstion.
1272*22ce4affSfengbojiang *
1273*22ce4affSfengbojiang * DO NOT EDIT-- this file is automatically %s.
1274*22ce4affSfengbojiang * $%s$
1275*22ce4affSfengbojiang * This file is part of the DTrace syscall provider.
1276*22ce4affSfengbojiang */
1277*22ce4affSfengbojiang
1278*22ce4affSfengbojiangstatic void
1279*22ce4affSfengbojiangsystrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
1280*22ce4affSfengbojiang{
1281*22ce4affSfengbojiang	int64_t *iarg  = (int64_t *) uarg;
1282*22ce4affSfengbojiang	switch (sysnum) {
1283*22ce4affSfengbojiang]], generated_tag, config['os_id_keyword']))
1284*22ce4affSfengbojiang
1285*22ce4affSfengbojiangwrite_line("systracetmp", [[static void
1286*22ce4affSfengbojiangsystrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
1287*22ce4affSfengbojiang{
1288*22ce4affSfengbojiang	const char *p = NULL;
1289*22ce4affSfengbojiang	switch (sysnum) {
1290*22ce4affSfengbojiang]])
1291*22ce4affSfengbojiang
1292*22ce4affSfengbojiangwrite_line("systraceret", [[static void
1293*22ce4affSfengbojiangsystrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
1294*22ce4affSfengbojiang{
1295*22ce4affSfengbojiang	const char *p = NULL;
1296*22ce4affSfengbojiang	switch (sysnum) {
1297*22ce4affSfengbojiang]])
1298*22ce4affSfengbojiang
1299*22ce4affSfengbojiang-- Processing the sysfile will parse out the preprocessor bits and put them into
1300*22ce4affSfengbojiang-- the appropriate place.  Any syscall-looking lines get thrown into the sysfile
1301*22ce4affSfengbojiang-- buffer, one per line, for later processing once they're all glued together.
1302*22ce4affSfengbojiangprocess_sysfile(sysfile)
1303*22ce4affSfengbojiang
1304*22ce4affSfengbojiangwrite_line("sysinc",
1305*22ce4affSfengbojiang    "\n#define AS(name) (sizeof(struct name) / sizeof(register_t))\n")
1306*22ce4affSfengbojiang
1307*22ce4affSfengbojiangfor _, v in pairs(compat_options) do
1308*22ce4affSfengbojiang	if v["count"] > 0 then
1309*22ce4affSfengbojiang		write_line("sysinc", string.format([[
1310*22ce4affSfengbojiang
1311*22ce4affSfengbojiang#ifdef %s
1312*22ce4affSfengbojiang#define %s(n, name) .sy_narg = n, .sy_call = (sy_call_t *)__CONCAT(%s,name)
1313*22ce4affSfengbojiang#else
1314*22ce4affSfengbojiang#define %s(n, name) .sy_narg = 0, .sy_call = (sy_call_t *)nosys
1315*22ce4affSfengbojiang#endif
1316*22ce4affSfengbojiang]], v["definition"], v["flag"]:lower(), v["prefix"], v["flag"]:lower()))
1317*22ce4affSfengbojiang	end
1318*22ce4affSfengbojiang
1319*22ce4affSfengbojiang	write_line(v["dcltmp"], string.format("\n#endif /* %s */\n\n",
1320*22ce4affSfengbojiang	    v["definition"]))
1321*22ce4affSfengbojiangend
1322*22ce4affSfengbojiang
1323*22ce4affSfengbojiangwrite_line("sysprotoend", string.format([[
1324*22ce4affSfengbojiang
1325*22ce4affSfengbojiang#undef PAD_
1326*22ce4affSfengbojiang#undef PADL_
1327*22ce4affSfengbojiang#undef PADR_
1328*22ce4affSfengbojiang
1329*22ce4affSfengbojiang#endif /* !%s */
1330*22ce4affSfengbojiang]], config["sysproto_h"]))
1331*22ce4affSfengbojiang
1332*22ce4affSfengbojiangwrite_line("sysmk", "\n")
1333*22ce4affSfengbojiangwrite_line("sysent", "};\n")
1334*22ce4affSfengbojiangwrite_line("sysnames", "};\n")
1335*22ce4affSfengbojiang-- maxsyscall is the highest seen; MAXSYSCALL should be one higher
1336*22ce4affSfengbojiangwrite_line("syshdr", string.format("#define\t%sMAXSYSCALL\t%d\n",
1337*22ce4affSfengbojiang    config["syscallprefix"], maxsyscall + 1))
1338*22ce4affSfengbojiangwrite_line("systrace", [[
1339*22ce4affSfengbojiang	default:
1340*22ce4affSfengbojiang		*n_args = 0;
1341*22ce4affSfengbojiang		break;
1342*22ce4affSfengbojiang	};
1343*22ce4affSfengbojiang}
1344*22ce4affSfengbojiang]])
1345*22ce4affSfengbojiang
1346*22ce4affSfengbojiangwrite_line("systracetmp", [[
1347*22ce4affSfengbojiang	default:
1348*22ce4affSfengbojiang		break;
1349*22ce4affSfengbojiang	};
1350*22ce4affSfengbojiang	if (p != NULL)
1351*22ce4affSfengbojiang		strlcpy(desc, p, descsz);
1352*22ce4affSfengbojiang}
1353*22ce4affSfengbojiang]])
1354*22ce4affSfengbojiang
1355*22ce4affSfengbojiangwrite_line("systraceret", [[
1356*22ce4affSfengbojiang	default:
1357*22ce4affSfengbojiang		break;
1358*22ce4affSfengbojiang	};
1359*22ce4affSfengbojiang	if (p != NULL)
1360*22ce4affSfengbojiang		strlcpy(desc, p, descsz);
1361*22ce4affSfengbojiang}
1362*22ce4affSfengbojiang]])
1363*22ce4affSfengbojiang
1364*22ce4affSfengbojiang-- Finish up; output
1365*22ce4affSfengbojiangwrite_line("syssw", read_file("sysinc"))
1366*22ce4affSfengbojiangwrite_line("syssw", read_file("sysent"))
1367*22ce4affSfengbojiang
1368*22ce4affSfengbojiangwrite_line("sysproto", read_file("sysarg"))
1369*22ce4affSfengbojiangwrite_line("sysproto", read_file("sysdcl"))
1370*22ce4affSfengbojiangfor _, v in pairs(compat_options) do
1371*22ce4affSfengbojiang	write_line("sysproto", read_file(v["tmp"]))
1372*22ce4affSfengbojiang	write_line("sysproto", read_file(v["dcltmp"]))
1373*22ce4affSfengbojiangend
1374*22ce4affSfengbojiangwrite_line("sysproto", read_file("sysaue"))
1375*22ce4affSfengbojiangwrite_line("sysproto", read_file("sysprotoend"))
1376*22ce4affSfengbojiang
1377*22ce4affSfengbojiangwrite_line("systrace", read_file("systracetmp"))
1378*22ce4affSfengbojiangwrite_line("systrace", read_file("systraceret"))
1379*22ce4affSfengbojiang
1380*22ce4affSfengbojiangfor _, v in ipairs(output_files) do
1381*22ce4affSfengbojiang	local target = config[v]
1382*22ce4affSfengbojiang	if target ~= "/dev/null" then
1383*22ce4affSfengbojiang		local fh = io.open(target, "w+")
1384*22ce4affSfengbojiang		if fh == nil then
1385*22ce4affSfengbojiang			abort(1, "Failed to open '" .. target .. "'")
1386*22ce4affSfengbojiang		end
1387*22ce4affSfengbojiang		fh:write(read_file(v))
1388*22ce4affSfengbojiang		fh:close()
1389*22ce4affSfengbojiang	end
1390*22ce4affSfengbojiangend
1391*22ce4affSfengbojiang
1392*22ce4affSfengbojiangcleanup()
1393