xref: /freebsd/sys/tools/syscalls/tools/generator.lua (revision 9ded074e875c29cb92d5f643801990d7bb23cca4)
1--
2-- SPDX-License-Identifier: BSD-2-Clause
3--
4-- Copyright (c) 2024 Tyler Baxter <agge@FreeBSD.org>
5-- Copyright (c) 2019 Kyle Evans <kevans@FreeBSD.org>
6--
7
8local util = require("tools.util")
9
10local generator = {}
11
12generator.__index = generator
13
14-- Wrapper for Lua write() best practice, for a simpler write call.
15function generator:write(line)
16	assert(self.gen:write(line))
17end
18
19--
20-- A write macro for the PAD64 preprocessor directive.
21-- Used for 32-bit configurations by passing config.abiChanges("pair_64bit") and
22-- padding will be done if necessary.
23--
24-- PARAM: bool, TRUE to pad.
25--
26function generator:pad64(bool)
27	if bool then
28		self:write([[
29#if !defined(PAD64_REQUIRED) && !defined(__amd64__)
30#define PAD64_REQUIRED
31#endif
32]])
33	end
34end
35
36-- Returns the generated tag.
37function generator:tag()
38	return self.tag
39end
40
41generator.storage_levels = {}
42
43-- Optional level to specify which order to store in, which defaults to one if
44-- not provided.
45function generator:store(str, level)
46	level = level or 1
47	self.storage_levels[level] = self.storage_levels[level] or {}
48	table.insert(self.storage_levels[level], str)
49end
50
51-- Write all storage in the order it was stored.
52function generator:writeStorage()
53	if self.storage_levels ~= nil then
54		for _, v in util.ipairsSparse(self.storage_levels) do
55			for _, line in ipairs(v) do
56				generator:write(line)
57			end
58		end
59	end
60end
61
62--
63-- Writes the generated preamble. Default comment is C comments.
64--
65-- PARAM: String str, the title for the file.
66--
67-- PARAM: String comment, nil or optional to change comment (e.g., "#" for sh
68-- comments).
69--
70-- SEE: style(9)
71--
72function generator:preamble(str, comment)
73	if str ~= nil then
74		local comment_start = comment or "/*"
75		local comment_middle = comment or " *"
76		local comment_end = comment or " */"
77		self:write(string.format("%s\n", comment_start))
78		-- Splits our string into lines split by newline, or is just the
79		-- original string if there's no newlines.
80		for line in str:gmatch("[^\n]*") do
81			-- Only add a space after the comment if there's
82			-- text on this line.
83			local space
84			if line ~= "" then
85				space = " "
86			else
87				space = ""
88			end
89			-- Make sure to append the newline back.
90			self:write(string.format("%s%s%s\n", comment_middle,
91			    space, line))
92		end
93		self:write(string.format([[%s
94%s DO NOT EDIT-- this file is automatically %s.
95%s
96
97]], comment_middle, comment_middle, self.tag, comment_end))
98	end
99end
100
101-- generator binds to the parameter file.
102function generator:new(obj, fh)
103	obj = obj or { }
104	setmetatable(obj, self)
105	self.__index = self
106
107	self.gen = assert(io.open(fh, "w+"))
108	self.tag = "@" .. "generated"
109
110	return obj
111end
112
113return generator
114