xref: /openbsd/sys/kern/makesyscalls.sh (revision d89ec533)
1#! /bin/sh -
2#	$OpenBSD: makesyscalls.sh,v 1.15 2021/12/09 00:26:10 guenther Exp $
3#	$NetBSD: makesyscalls.sh,v 1.26 1998/01/09 06:17:51 thorpej Exp $
4#
5# Copyright (c) 1994,1996 Christopher G. Demetriou
6# All rights reserved.
7#
8# Redistribution and use in source and binary forms, with or without
9# modification, are permitted provided that the following conditions
10# are met:
11# 1. Redistributions of source code must retain the above copyright
12#    notice, this list of conditions and the following disclaimer.
13# 2. Redistributions in binary form must reproduce the above copyright
14#    notice, this list of conditions and the following disclaimer in the
15#    documentation and/or other materials provided with the distribution.
16# 3. All advertising materials mentioning features or use of this software
17#    must display the following acknowledgement:
18#      This product includes software developed for the NetBSD Project
19#      by Christopher G. Demetriou.
20# 4. The name of the author may not be used to endorse or promote products
21#    derived from this software without specific prior written permission
22#
23# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
34#	@(#)makesyscalls.sh	8.1 (Berkeley) 6/10/93
35
36set -e
37
38case $# in
39    2)	;;
40    *)	echo "Usage: $0 config-file input-file" 1>&2
41	exit 1
42	;;
43esac
44
45# source the config file.
46case $1 in
47    /*)	. $1
48	;;
49    *)	. ./$1
50	;;
51esac
52
53# the config file sets the following variables:
54#	sysnames	the syscall names file
55#	sysnumhdr	the syscall numbers file
56#	syssw		the syscall switch file
57#	sysarghdr	the syscall argument struct definitions
58#	compatopts	those syscall types that are for 'compat' syscalls
59#	switchname	the name for the 'const struct sysent' we define
60#	namesname	the name for the 'const char *const[]' we define
61#	constprefix	the prefix for the system call constants
62#
63# NOTE THAT THIS makesyscalls.sh DOES NOT SUPPORT 'LIBCOMPAT'.
64
65# tmp files:
66sysdcl="sysent.dcl"
67sysprotos="sys.protos"
68syscompat_pref="sysent."
69sysent="sysent.switch"
70
71trap "rm $sysdcl $sysprotos $sysent" 0
72
73# Awk program (must support nawk extensions)
74# Use "awk" at Berkeley, "nawk" or "gawk" elsewhere.
75awk=${AWK:-awk}
76
77# Does this awk have a "toupper" function? (i.e. is it GNU awk)
78isgawk=`$awk 'BEGIN { print toupper("true"); exit; }' 2>/dev/null`
79
80# If this awk does not define "toupper" then define our own.
81if [ "$isgawk" = TRUE ] ; then
82	# GNU awk provides it.
83	toupper=
84else
85	# Provide our own toupper()
86	toupper='
87function toupper(str) {
88	_toupper_cmd = "echo "str" |tr a-z A-Z"
89	_toupper_cmd | getline _toupper_str;
90	close(_toupper_cmd);
91	return _toupper_str;
92}'
93fi
94
95# before handing it off to awk, make a few adjustments:
96#	(1) insert spaces around {, }, (, ), *, and commas.
97#	(2) get rid of any and all dollar signs (so that rcs id use safe)
98#
99# The awk script will deal with blank lines and lines that
100# start with the comment character (';').
101
102sed -e '
103s/\$//g
104:join
105	/\\$/{a\
106
107	N
108	s/\\\n//
109	b join
110	}
1112,${
112	/^#/!s/\([{}()*,]\)/ \1 /g
113}
114' < $2 | $awk "
115$toupper
116BEGIN {
117	# to allow nested #if/#else/#endif sets
118	savedepth = 0
119
120	sysnames = \"$sysnames\"
121	sysprotos = \"$sysprotos\"
122	sysnumhdr = \"$sysnumhdr\"
123	sysarghdr = \"$sysarghdr\"
124	switchname = \"$switchname\"
125	namesname = \"$namesname\"
126	constprefix = \"$constprefix\"
127
128	sysdcl = \"$sysdcl\"
129	syscompat_pref = \"$syscompat_pref\"
130	sysent = \"$sysent\"
131	infile = \"$2\"
132
133	compatopts = \"$compatopts\"
134	"'
135
136	printf "/*\t\$OpenBSD\$\t*/\n\n" > sysdcl
137	printf "/*\n * System call switch table.\n *\n" > sysdcl
138	printf " * DO NOT EDIT-- this file is automatically generated.\n" > sysdcl
139
140	ncompat = split(compatopts,compat)
141	for (i = 1; i <= ncompat; i++) {
142		compat_upper[i] = toupper(compat[i])
143
144		printf "\n#ifdef %s\n", compat_upper[i] > sysent
145		printf "#define %s(func) __CONCAT(%s_,func)\n", compat[i], \
146		    compat[i] > sysent
147		printf "#else\n" > sysent
148		printf "#define %s(func) sys_nosys\n", compat[i] > sysent
149		printf "#endif\n" > sysent
150	}
151
152	printf "\n#define\ts(type)\tsizeof(type)\n\n" > sysent
153	printf "const struct sysent %s[] = {\n",switchname > sysent
154
155	printf "/*\t\$OpenBSD\$\t*/\n\n" > sysnames
156	printf "/*\n * System call names.\n *\n" > sysnames
157	printf " * DO NOT EDIT-- this file is automatically generated.\n" > sysnames
158
159	printf "\n/*\n * System call prototypes.\n */\n\n" > sysprotos
160
161	printf "/*\t\$OpenBSD\$\t*/\n\n" > sysnumhdr
162	printf "/*\n * System call numbers.\n *\n" > sysnumhdr
163	printf " * DO NOT EDIT-- this file is automatically generated.\n" > sysnumhdr
164
165	printf "/*\t\$OpenBSD\$\t*/\n\n" > sysarghdr
166	printf "/*\n * System call argument lists.\n *\n" > sysarghdr
167	printf " * DO NOT EDIT-- this file is automatically generated.\n" > sysarghdr
168}
169NR == 1 {
170	printf " * created from%s\n */\n\n", $0 > sysdcl
171
172	printf " * created from%s\n */\n\n", $0 > sysnames
173	printf "const char *const %s[] = {\n",namesname > sysnames
174
175	printf " * created from%s\n */\n\n", $0 > sysnumhdr
176
177	printf " * created from%s\n */\n\n", $0 > sysarghdr
178	printf "#ifdef\tsyscallarg\n" > sysarghdr
179	printf "#undef\tsyscallarg\n" > sysarghdr
180	printf "#endif\n\n" > sysarghdr
181	printf "#define\tsyscallarg(x)\t\t\t\t\t\t\t\\\n" > sysarghdr
182	printf "\tunion {\t\t\t\t\t\t\t\t\\\n" > sysarghdr
183	printf "\t\tregister_t pad;\t\t\t\t\t\t\\\n" > sysarghdr
184	printf "\t\tstruct { x datum; } le;\t\t\t\t\t\\\n" > sysarghdr
185	printf "\t\tstruct {\t\t\t\t\t\t\\\n" > sysarghdr
186	printf "\t\t\tint8_t pad[ (sizeof (register_t) < sizeof (x))\t\\\n" \
187		> sysarghdr
188	printf "\t\t\t\t? 0\t\t\t\t\t\\\n" > sysarghdr
189	printf "\t\t\t\t: sizeof (register_t) - sizeof (x)];\t\\\n" \
190		> sysarghdr
191	printf "\t\t\tx datum;\t\t\t\t\t\\\n" > sysarghdr
192	printf "\t\t} be;\t\t\t\t\t\t\t\\\n" > sysarghdr
193	printf "\t}\n" > sysarghdr
194	next
195}
196NF == 0 || $1 ~ /^;/ {
197	next
198}
199$1 ~ /^#[ 	]*include/ {
200	print > sysdcl
201	next
202}
203$1 ~ /^#[ 	]*if/ {
204	print > sysent
205	print > sysprotos
206	print > sysnames
207	savesyscall[++savedepth] = syscall
208	next
209}
210$1 ~ /^#[ 	]*else/ {
211	print > sysent
212	print > sysprotos
213	print > sysnames
214	if (savedepth <= 0) {
215		printf "%s: line %d: unbalanced #else\n", \
216		    infile, NR
217		exit 1
218	}
219	syscall = savesyscall[savedepth]
220	next
221}
222$1 ~ /^#/ {
223	if ($1 ~ /^#[       ]*endif/) {
224		if (savedepth <= 0) {
225			printf "%s: line %d: unbalanced #endif\n", \
226			    infile, NR
227			exit 1
228		}
229		savedepth--;
230	}
231	print > sysent
232	print > sysprotos
233	print > sysnames
234	next
235}
236syscall != $1 {
237	printf "%s: line %d: syscall number out of sync at %d\n", \
238	   infile, NR, syscall
239	printf "line is:\n"
240	print
241	exit 1
242}
243function parserr(was, wanted) {
244	printf "%s: line %d: unexpected %s (expected %s)\n", \
245	    infile, NR, was, wanted
246	exit 1
247}
248function parseline() {
249	f=3			# toss number and type
250	sycall_flags="0"
251	if ($NF != "}") {
252		funcalias=$NF
253		end=NF-1
254	} else {
255		funcalias=""
256		end=NF
257	}
258	if ($f == "NOLOCK") {		# syscall does not need locks
259		sycall_flags = sprintf("SY_NOLOCK | %s", sycall_flags)
260		f++
261	}
262	if ($f ~ /^[a-z0-9_]*$/) {      # allow syscall alias
263		funcalias=$f
264		f++
265	}
266	if ($f != "{")
267		parserr($f, "{")
268	f++
269	if ($end != "}")
270		parserr($end, "}")
271	end--
272	if ($end != ";")
273		parserr($end, ";")
274	end--
275	if ($end != ")")
276		parserr($end, ")")
277	end--
278
279	returntype = oldf = "";
280	do {
281		if (returntype != "" && oldf != "*")
282			returntype = returntype" ";
283		returntype = returntype$f;
284		oldf = $f;
285		f++
286	} while (f < (end - 1) && $(f+1) != "(");
287	if (f == (end - 1)) {
288		parserr($f, "function argument definition (maybe \"(\"?)");
289	}
290
291	funcname=$f
292	if (funcalias == "") {
293		funcalias=funcname
294		sub(/^([^_]+_)*sys_/, "", funcalias)
295	}
296	f++
297
298	if ($f != "(")
299		parserr($f, ")")
300	f++
301
302	argc=0;
303	if (f == end) {
304		if ($f != "void")
305			parserr($f, "argument definition")
306		isvarargs = 0;
307		varargc = 0;
308		return
309	}
310
311	# some system calls (open() and fcntl()) can accept a variable
312	# number of arguments.  If syscalls accept a variable number of
313	# arguments, they must still have arguments specified for
314	# the remaining argument "positions," because of the way the
315	# kernel system call argument handling works.
316	#
317	# Indirect system calls, e.g. syscall(), are exceptions to this
318	# rule, since they are handled entirely by machine-dependent code
319	# and do not need argument structures built.
320
321	isvarargs = 0;
322	while (f <= end) {
323		if ($f == "...") {
324			f++;
325			isvarargs = 1;
326			varargc = argc;
327			continue;
328		}
329		argc++
330		argtype[argc]=""
331		oldf=""
332		while (f < end && $(f+1) != ",") {
333			if (argtype[argc] != "" && oldf != "*")
334				argtype[argc] = argtype[argc]" ";
335			argtype[argc] = argtype[argc]$f;
336			oldf = $f;
337			f++
338		}
339		if (argtype[argc] == "")
340			parserr($f, "argument definition")
341		argname[argc]=$f;
342		f += 2;			# skip name, and any comma
343	}
344	# must see another argument after varargs notice.
345	if (isvarargs) {
346		if (argc == varargc && $2 != "INDIR")
347			parserr($f, "argument definition")
348	} else
349		varargc = argc;
350}
351function putent(nodefs, compatwrap) {
352	# output syscall declaration for switch table.  INDIR functions
353	# get none, since they always have sys_nosys() for their table
354	# entries.
355	if (nodefs != "INDIR") {
356		prototype = "(struct proc *, void *, register_t *)"
357		if (compatwrap == "")
358			printf("int\t%s%s;\n", funcname,
359			    prototype) > sysprotos
360		else
361			printf("int\t%s_%s%s;\n", compatwrap, funcname,
362			    prototype) > sysprotos
363	}
364
365	# output syscall switch entry
366	if (nodefs == "INDIR") {
367		printf("\t{ 0, 0, %s,\n\t    sys_nosys },\t\t\t/* %d = %s (indir) */\n", \
368		    sycall_flags, syscall, funcalias) > sysent
369	} else {
370#		printf("\t{ { %d", argc) > sysent
371#		for (i = 1; i <= argc; i++) {
372#			if (i == 5) 		# wrap the line
373#				printf(",\n\t    ") > sysent
374#			else
375#				printf(", ") > sysent
376#			printf("s(%s)", argtypenospc[i]) > sysent
377#		}
378		printf("\t{ %d, ", argc) > sysent
379		if (argc == 0)
380			printf("0") > sysent
381		else if (compatwrap == "")
382			printf("s(struct %s_args)", funcname) > sysent
383		else
384			printf("s(struct %s_%s_args)", compatwrap,
385			    funcname) > sysent
386		if (compatwrap == "")
387			wfn = sprintf("%s", funcname);
388		else
389			wfn = sprintf("%s(%s)", compatwrap, funcname);
390		printf(", %s,\n\t    %s },", sycall_flags, wfn) > sysent
391		for (i = 0; i < (33 - length(wfn)) / 8; i++)
392			printf("\t") > sysent
393		if (compatwrap == "")
394			printf("/* %d = %s */\n", syscall, funcalias) > sysent
395		else
396			printf("/* %d = %s %s */\n", syscall, compatwrap,
397			    funcalias) > sysent
398	}
399
400	# output syscall name for names table
401	if (compatwrap == "")
402		printf("\t\"%s\",\t\t\t/* %d = %s */\n", funcalias, syscall,
403		    funcalias) > sysnames
404	else
405		printf("\t\"%s_%s\",\t/* %d = %s %s */\n", compatwrap,
406		    funcalias, syscall, compatwrap, funcalias) > sysnames
407
408	# output syscall number of header, if appropriate
409	if (nodefs == "" || nodefs == "NOARGS" || nodefs == "INDIR") {
410		# output a prototype, to be used to generate lint stubs in
411		# libc.
412		printf("/* syscall: \"%s\" ret: \"%s\" args:", funcalias,
413		    returntype) > sysnumhdr
414		for (i = 1; i <= varargc; i++)
415			printf(" \"%s\"", argtype[i]) > sysnumhdr
416		if (isvarargs)
417			printf(" \"...\"") > sysnumhdr
418		printf(" */\n") > sysnumhdr
419
420		printf("#define\t%s%s\t%d\n\n", constprefix, funcalias,
421		    syscall) > sysnumhdr
422	} else if (nodefs != "NODEF")
423		printf("\t\t\t\t/* %d is %s %s */\n\n", syscall,
424		    compatwrap, funcalias) > sysnumhdr
425
426	# output syscall argument structure, if it has arguments
427	if (argc != 0 && nodefs != "NOARGS" && nodefs != "INDIR") {
428		if (compatwrap == "")
429			printf("\nstruct %s_args {\n", funcname) > sysarghdr
430		else
431			printf("\nstruct %s_%s_args {\n", compatwrap,
432			    funcname) > sysarghdr
433		for (i = 1; i <= argc; i++)
434			printf("\tsyscallarg(%s) %s;\n", argtype[i],
435			    argname[i]) > sysarghdr
436		printf("};\n") > sysarghdr
437	}
438}
439$2 == "STD" {
440	parseline()
441	putent("", "");
442	syscall++
443	next
444}
445$2 == "NODEF" || $2 == "NOARGS" || $2 == "INDIR" {
446	parseline()
447	putent($2, "")
448	syscall++
449	next
450}
451$2 == "OBSOL" || $2 == "UNIMPL" {
452	if ($2 == "OBSOL")
453		comment="obsolete"
454	else
455		comment="unimplemented"
456	for (i = 3; i <= NF; i++)
457		comment=comment " " $i
458
459	printf("\t{ 0, 0, 0,\n\t    sys_nosys },\t\t\t/* %d = %s */\n", \
460	    syscall, comment) > sysent
461	printf("\t\"#%d (%s)\",\t\t/* %d = %s */\n", \
462	    syscall, comment, syscall, comment) > sysnames
463	if ($2 != "UNIMPL")
464		printf("\t\t\t\t/* %d is %s */\n", syscall, comment) > sysnumhdr
465	syscall++
466	next
467}
468{
469	for (i = 1; i <= ncompat; i++) {
470		if ($2 == compat_upper[i]) {
471			parseline();
472			putent("COMMENT", compat[i])
473			syscall++
474			next
475		}
476	}
477	printf "%s: line %d: unrecognized keyword %s\n", infile, NR, $2
478	exit 1
479}
480END {
481	printf("};\n\n") > sysent
482	printf("};\n") > sysnames
483	printf("#define\t%sMAXSYSCALL\t%d\n", constprefix, syscall) > sysnumhdr
484} '
485
486cat $sysprotos >> $sysarghdr
487cat $sysdcl $sysent > $syssw
488
489#chmod 444 $sysnames $sysnumhdr $syssw
490