xref: /freebsd/sys/tools/syscalls/tools/util.lua (revision 42d075f4b7b74eb3c4f943d6bdcc2aeb56be6388)
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 util = {}
10
11--
12-- Returns a trimmed string. Default is to trim whitespace.
13--
14-- PARAM: String s, the string to trim.
15--
16-- PARAM: char, nil or optional character to trim.
17--
18function util.trim(s, char)
19	if s == nil then
20		return nil
21	end
22	if char == nil then
23		char = "%s"
24	end
25	return s:gsub("^" .. char .. "+", ""):gsub(char .. "+$", "")
26end
27
28-- Returns a table (list) of strings.
29function util.split(s, re)
30	local t = { }
31
32	for v in s:gmatch(re) do
33		table.insert(t, v)
34	end
35	return t
36end
37
38-- Prints a warning to stderr
39function util.warn(msg)
40	assert(io.stderr:write("WARNING: " .. msg .. "\n"))
41end
42
43-- Aborts with a message and does a clean exit procedure.
44function util.abort(status, msg)
45	assert(io.stderr:write(msg .. "\n"))
46	-- cleanup
47	os.exit(status)
48end
49
50--
51-- Returns a set.
52--
53-- PARAM: t, a list.
54--
55-- EXAMPLE: param: {"foo", "bar"}, return: {foo = true, bar = true}
56--
57function util.set(t)
58	local s = { }
59
60	for _,v in pairs(t) do
61		s[v] = true
62	end
63	return s
64end
65
66--
67-- Returns a set.
68--
69-- PARAM: str, a string.
70-- PARAM: re, the pattern to construct keys from.
71--
72function util.setFromString(str, re)
73	local s = { }
74
75	for v in str:gmatch(re) do
76		s[v] = true
77	end
78	return s
79end
80
81function util.isEmpty(tbl)
82	if tbl ~= nil then
83		if next(tbl) == nil then
84			return true
85		end
86		return false
87	end
88	return true
89end
90
91--
92--  Iterator that traverses a table following the order of its keys.
93--  An optional parameter f allows the specification of an alternative order.
94--
95--  CREDIT: https://www.lua.org/pil/19.3.html
96--  LICENSE: MIT
97--
98function util.pairsByKeys(t, f)
99	local a = {}
100	for n in pairs(t) do table.insert(a, n) end
101	table.sort(a, f)
102	local i = 0	  -- iterator variable
103	local iter = function ()   -- iterator function
104		i = i + 1
105		if a[i] == nil then
106			return nil
107		else
108			return a[i], t[a[i]]
109		end
110	end
111	return iter
112end
113
114--
115-- Checks for pointer types: '*', caddr_t, or intptr_t.
116--
117-- PARAM: type, the type to check.
118--
119-- PARAM: abi, nil or optional ABI-specified intptr_t.
120--
121function util.isPtrType(type, abi)
122	local default = abi or "intptr_t"
123	return type:find("*") or type:find("caddr_t") or type:find(default)
124end
125
126function util.isPtrArrayType(type)
127	return type:find("[*][*]") or type:find("[*][ ]*const[ ]*[*]")
128end
129
130-- Find types that are always 64-bits wide.
131function util.is64bitType(type)
132	return type:find("^dev_t[ ]*$") or type:find("^id_t[ ]*$") or
133	    type:find("^off_t[ ]*$")
134end
135
136--
137-- Returns the name of the struct pointed to by the argument or nil.
138--
139-- PARAM: type, the type to check.
140--
141function util.structName(type)
142	if util.isPtrType(type) then
143		local is_struct = false
144		for word in type:gmatch("[^ *]+") do
145			if is_struct then
146				return word
147			end
148			if word == "struct" then
149				-- next word is the struct name
150				is_struct = true
151			end
152		end
153	end
154	return nil
155end
156
157-- Strip the ABI function prefix if it exists (e.g., "freebsd32_"). Returns the
158-- function name with the ABI prefix stripped, or the original function name if
159-- there was no ABI function prefix.
160function util.stripAbiPrefix(funcname, abiprefix)
161	local stripped_name
162	if funcname == nil then
163		return nil
164	end
165	if abiprefix ~= "" and funcname:find("^" .. abiprefix) then
166		stripped_name = funcname:gsub("^" .. abiprefix, "")
167	else
168		stripped_name = funcname
169	end
170
171	return stripped_name
172end
173
174-- ipairs for a sparse array.
175-- CREDIT: Lua Game Development Cookbook, Mario Kasuba
176function util.ipairsSparse(t)
177	-- tmp_index will hold sorted indices, otherwise
178	-- this iterator would be no different from pairs iterator
179	local tmp_index = {}
180	local index, _ = next(t)
181	while index do
182		tmp_index[#tmp_index + 1] = index
183		index, _ = next(t, index)
184	end
185	-- sort table indices
186	table.sort(tmp_index)
187	local j = 1
188
189	return function()
190		-- get index value
191		local i = tmp_index[j]
192		j = j + 1
193		if i then
194			return i, t[i]
195		end
196	end
197end
198
199return util
200