1#! /bin/sh -
2#	$OpenBSD: makesyscalls.sh,v 1.22 2024/01/07 20:52:44 miod 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    1)	;;
40    *)	echo "Usage: $0 input-file" 1>&2
41	exit 1
42	;;
43esac
44
45sysnames="syscalls.c"
46sysnumhdr="../sys/syscall.h"
47syssw="init_sysent.c"
48sysarghdr="../sys/syscallargs.h"
49
50# Any additions to the next line for options that are required for the
51# (new) kernel to boot an existing userland must be coordinated with
52# the snapshot builders
53compatopts=""
54
55switchname="sysent"
56namesname="syscallnames"
57constprefix="SYS_"
58
59# this script sets the following variables:
60#	sysnames	the syscall names file
61#	sysnumhdr	the syscall numbers file
62#	syssw		the syscall switch file
63#	sysarghdr	the syscall argument struct definitions
64#	compatopts	those syscall types that are for 'compat' syscalls
65#	switchname	the name for the 'const struct sysent' we define
66#	namesname	the name for the 'const char *const[]' we define
67#	constprefix	the prefix for the system call constants
68#
69# NOTE THAT THIS makesyscalls.sh DOES NOT SUPPORT 'LIBCOMPAT'.
70
71# tmp files:
72sysdcl="sysent.dcl"
73sysprotos="sys.protos"
74syscompat_pref="sysent."
75sysent="sysent.switch"
76
77trap "rm $sysdcl $sysprotos $sysent" 0
78
79# before handing it off to awk, make a few adjustments:
80#	(1) insert spaces around {, }, (, ), *, and commas.
81#	(2) get rid of any and all dollar signs (so that rcs id use safe)
82#
83# The awk script will deal with blank lines and lines that
84# start with the comment character (';').
85
86sed -e '
87s/\$//g
88:join
89	/\\$/{a\
90
91	N
92	s/\\\n//
93	b join
94	}
952,${
96	/^#/!s/\([{}()*,]\)/ \1 /g
97}
98' < $1 | awk "
99BEGIN {
100	# to allow nested #if/#else/#endif sets
101	savedepth = 0
102
103	sysnames = \"$sysnames\"
104	sysprotos = \"$sysprotos\"
105	sysnumhdr = \"$sysnumhdr\"
106	sysarghdr = \"$sysarghdr\"
107	switchname = \"$switchname\"
108	namesname = \"$namesname\"
109	constprefix = \"$constprefix\"
110
111	sysdcl = \"$sysdcl\"
112	syscompat_pref = \"$syscompat_pref\"
113	sysent = \"$sysent\"
114	infile = \"$1\"
115
116	compatopts = \"$compatopts\"
117	"'
118
119	printf "/*\t\$OpenBSD\$\t*/\n\n" > sysdcl
120	printf "/*\n * System call switch table.\n *\n" > sysdcl
121	printf " * DO NOT EDIT-- this file is automatically generated.\n" > sysdcl
122
123	ncompat = split(compatopts,compat)
124	for (i = 1; i <= ncompat; i++) {
125		compat_upper[i] = toupper(compat[i])
126
127		printf "\n#ifdef %s\n", compat_upper[i] > sysent
128		printf "#define %s(func) __CONCAT(%s_,func)\n", compat[i], \
129		    compat[i] > sysent
130		printf "#else\n" > sysent
131		printf "#define %s(func) sys_nosys\n", compat[i] > sysent
132		printf "#endif\n" > sysent
133	}
134
135	printf "\n#define\ts(type)\tsizeof(type)\n\n" > sysent
136	printf "const struct sysent %s[] = {\n",switchname > sysent
137
138	printf "/*\t\$OpenBSD\$\t*/\n\n" > sysnames
139	printf "/*\n * System call names.\n *\n" > sysnames
140	printf " * DO NOT EDIT-- this file is automatically generated.\n" > sysnames
141
142	printf "\n/*\n * System call prototypes.\n */\n\n" > sysprotos
143
144	printf "/*\t\$OpenBSD\$\t*/\n\n" > sysnumhdr
145	printf "/*\n * System call numbers.\n *\n" > sysnumhdr
146	printf " * DO NOT EDIT-- this file is automatically generated.\n" > sysnumhdr
147
148	printf "/*\t\$OpenBSD\$\t*/\n\n" > sysarghdr
149	printf "/*\n * System call argument lists.\n *\n" > sysarghdr
150	printf " * DO NOT EDIT-- this file is automatically generated.\n" > sysarghdr
151}
152NR == 1 {
153	printf " * created from%s\n */\n\n", $0 > sysdcl
154
155	printf " * created from%s\n */\n\n", $0 > sysnames
156	printf "const char *const %s[] = {\n",namesname > sysnames
157
158	printf " * created from%s\n */\n\n", $0 > sysnumhdr
159
160	printf " * created from%s\n */\n\n", $0 > sysarghdr
161	printf "#ifdef\tsyscallarg\n" > sysarghdr
162	printf "#undef\tsyscallarg\n" > sysarghdr
163	printf "#endif\n\n" > sysarghdr
164	printf "#define\tsyscallarg(x)\t\t\t\t\t\t\t\\\n" > sysarghdr
165	printf "\tunion {\t\t\t\t\t\t\t\t\\\n" > sysarghdr
166	printf "\t\tregister_t pad;\t\t\t\t\t\t\\\n" > sysarghdr
167	printf "\t\tstruct { x datum; } le;\t\t\t\t\t\\\n" > sysarghdr
168	printf "\t\tstruct {\t\t\t\t\t\t\\\n" > sysarghdr
169	printf "\t\t\tint8_t pad[ (sizeof (register_t) < sizeof (x))\t\\\n" \
170		> sysarghdr
171	printf "\t\t\t\t? 0\t\t\t\t\t\\\n" > sysarghdr
172	printf "\t\t\t\t: sizeof (register_t) - sizeof (x)];\t\\\n" \
173		> sysarghdr
174	printf "\t\t\tx datum;\t\t\t\t\t\\\n" > sysarghdr
175	printf "\t\t} be;\t\t\t\t\t\t\t\\\n" > sysarghdr
176	printf "\t}\n" > sysarghdr
177	next
178}
179NF == 0 || $1 ~ /^;/ {
180	next
181}
182$1 ~ /^#[ 	]*include/ {
183	print > sysdcl
184	next
185}
186$1 ~ /^#[ 	]*if/ {
187	print > sysent
188	print > sysprotos
189	print > sysnames
190	savesyscall[++savedepth] = syscall
191	next
192}
193$1 ~ /^#[ 	]*else/ {
194	print > sysent
195	print > sysprotos
196	print > sysnames
197	if (savedepth <= 0) {
198		printf "%s: line %d: unbalanced #else\n", \
199		    infile, NR
200		exit 1
201	}
202	syscall = savesyscall[savedepth]
203	next
204}
205$1 ~ /^#/ {
206	if ($1 ~ /^#[       ]*endif/) {
207		if (savedepth <= 0) {
208			printf "%s: line %d: unbalanced #endif\n", \
209			    infile, NR
210			exit 1
211		}
212		savedepth--;
213	}
214	print > sysent
215	print > sysprotos
216	print > sysnames
217	next
218}
219syscall != $1 {
220	printf "%s: line %d: syscall number out of sync at %d\n", \
221	   infile, NR, syscall
222	printf "line is:\n"
223	print
224	exit 1
225}
226function parserr(was, wanted) {
227	printf "%s: line %d: unexpected %s (expected %s)\n", \
228	    infile, NR, was, wanted
229	exit 1
230}
231function parseline() {
232	f=3			# toss number and type
233	sycall_flags="0"
234	if ($NF != "}") {
235		funcalias=$NF
236		end=NF-1
237	} else {
238		funcalias=""
239		end=NF
240	}
241	if ($f == "NOLOCK") {		# syscall does not need locks
242		sycall_flags = sprintf("SY_NOLOCK | %s", sycall_flags)
243		f++
244	}
245	if ($f ~ /^[a-z0-9_]*$/) {      # allow syscall alias
246		funcalias=$f
247		f++
248	}
249	if ($f != "{")
250		parserr($f, "{")
251	f++
252	if ($end != "}")
253		parserr($end, "}")
254	end--
255	if ($end != ";")
256		parserr($end, ";")
257	end--
258	if ($end != ")")
259		parserr($end, ")")
260	end--
261
262	returntype = oldf = "";
263	do {
264		if (returntype != "" && oldf != "*")
265			returntype = returntype" ";
266		returntype = returntype$f;
267		oldf = $f;
268		f++
269	} while (f < (end - 1) && $(f+1) != "(");
270	if (f == (end - 1)) {
271		parserr($f, "function argument definition (maybe \"(\"?)");
272	}
273
274	funcname=$f
275	if (funcalias == "") {
276		funcalias=funcname
277		sub(/^([^_]+_)*sys_/, "", funcalias)
278	}
279	f++
280
281	if ($f != "(")
282		parserr($f, ")")
283	f++
284
285	argc=0;
286	if (f == end) {
287		if ($f != "void")
288			parserr($f, "argument definition")
289		isvarargs = 0;
290		varargc = 0;
291		return
292	}
293
294	# some system calls (open() and fcntl()) can accept a variable
295	# number of arguments.  If syscalls accept a variable number of
296	# arguments, they must still have arguments specified for
297	# the remaining argument "positions," because of the way the
298	# kernel system call argument handling works.
299
300	isvarargs = 0;
301	while (f <= end) {
302		if ($f == "...") {
303			f++;
304			isvarargs = 1;
305			varargc = argc;
306			continue;
307		}
308		argc++
309		argtype[argc]=""
310		oldf=""
311		while (f < end && $(f+1) != ",") {
312			if (argtype[argc] != "" && oldf != "*")
313				argtype[argc] = argtype[argc]" ";
314			argtype[argc] = argtype[argc]$f;
315			oldf = $f;
316			f++
317		}
318		if (argtype[argc] == "")
319			parserr($f, "argument definition")
320		argname[argc]=$f;
321		f += 2;			# skip name, and any comma
322	}
323	# must see another argument after varargs notice.
324	if (isvarargs) {
325		if (argc == varargc)
326			parserr($f, "argument definition")
327	} else
328		varargc = argc;
329	if (argc > 6) {
330		printf "%s: line %d: too many syscall arguments (%d > 6)\n", \
331		    infile, NR, argc
332		exit 1
333	}
334}
335function putent(nodefs, compatwrap) {
336	# output syscall declaration for switch table.
337	prototype = "(struct proc *, void *, register_t *)"
338	if (compatwrap == "")
339		printf("int\t%s%s;\n", funcname,
340		    prototype) > sysprotos
341	else
342		printf("int\t%s_%s%s;\n", compatwrap, funcname,
343		    prototype) > sysprotos
344
345	# output syscall switch entry
346#	printf("\t{ { %d", argc) > sysent
347#	for (i = 1; i <= argc; i++) {
348#		if (i == 5) 		# wrap the line
349#			printf(",\n\t    ") > sysent
350#		else
351#			printf(", ") > sysent
352#		printf("s(%s)", argtypenospc[i]) > sysent
353#	}
354	printf("\t{ %d, ", argc) > sysent
355	if (argc == 0)
356		printf("0") > sysent
357	else if (compatwrap == "")
358		printf("s(struct %s_args)", funcname) > sysent
359	else
360		printf("s(struct %s_%s_args)", compatwrap,
361		    funcname) > sysent
362	if (compatwrap == "")
363		wfn = sprintf("%s", funcname);
364	else
365		wfn = sprintf("%s(%s)", compatwrap, funcname);
366	printf(", %s,\n\t    %s },", sycall_flags, wfn) > sysent
367	for (i = 0; i < (33 - length(wfn)) / 8; i++)
368		printf("\t") > sysent
369	if (compatwrap == "")
370		printf("/* %d = %s */\n", syscall, funcalias) > sysent
371	else
372		printf("/* %d = %s %s */\n", syscall, compatwrap,
373		    funcalias) > sysent
374
375	# output syscall name for names table
376	if (compatwrap == "")
377		printf("\t\"%s\",\t\t\t/* %d = %s */\n", funcalias, syscall,
378		    funcalias) > sysnames
379	else
380		printf("\t\"%s_%s\",\t/* %d = %s %s */\n", compatwrap,
381		    funcalias, syscall, compatwrap, funcalias) > sysnames
382
383	# output syscall number of header, if appropriate
384	if (nodefs == "" || nodefs == "NOARGS") {
385		# output a prototype, to be used to generate lint stubs in
386		# libc.
387		printf("/* syscall: \"%s\" ret: \"%s\" args:", funcalias,
388		    returntype) > sysnumhdr
389		for (i = 1; i <= varargc; i++)
390			printf(" \"%s\"", argtype[i]) > sysnumhdr
391		if (isvarargs) {
392			printf(" \"...\"") > sysnumhdr
393			for (i = varargc + 1; i <= argc; i++)
394				printf(" \"%s\"", argtype[i]) > sysnumhdr
395		}
396		printf(" */\n") > sysnumhdr
397
398		printf("#define\t%s%s\t%d\n\n", constprefix, funcalias,
399		    syscall) > sysnumhdr
400	} else if (nodefs != "NODEF")
401		printf("\t\t\t\t/* %d is %s %s */\n\n", syscall,
402		    compatwrap, funcalias) > sysnumhdr
403
404	# output syscall argument structure, if it has arguments
405	if (argc != 0 && nodefs != "NOARGS") {
406		if (compatwrap == "")
407			printf("\nstruct %s_args {\n", funcname) > sysarghdr
408		else
409			printf("\nstruct %s_%s_args {\n", compatwrap,
410			    funcname) > sysarghdr
411		for (i = 1; i <= argc; i++)
412			printf("\tsyscallarg(%s) %s;\n", argtype[i],
413			    argname[i]) > sysarghdr
414		printf("};\n") > sysarghdr
415	}
416}
417$2 == "STD" {
418	parseline()
419	putent("", "");
420	syscall++
421	next
422}
423$2 == "NODEF" || $2 == "NOARGS" {
424	parseline()
425	putent($2, "")
426	syscall++
427	next
428}
429$2 == "OBSOL" || $2 == "UNIMPL" {
430	if ($2 == "OBSOL")
431		comment="obsolete"
432	else
433		comment="unimplemented"
434	for (i = 3; i <= NF; i++)
435		comment=comment " " $i
436
437	printf("\t{ 0, 0, 0,\n\t    sys_nosys },\t\t\t/* %d = %s */\n", \
438	    syscall, comment) > sysent
439	printf("\t\"#%d (%s)\",\t\t/* %d = %s */\n", \
440	    syscall, comment, syscall, comment) > sysnames
441	if ($2 != "UNIMPL")
442		printf("\t\t\t\t/* %d is %s */\n", syscall, comment) > sysnumhdr
443	syscall++
444	next
445}
446{
447	for (i = 1; i <= ncompat; i++) {
448		if ($2 == compat_upper[i]) {
449			parseline();
450			putent("COMMENT", compat[i])
451			syscall++
452			next
453		}
454	}
455	printf "%s: line %d: unrecognized keyword %s\n", infile, NR, $2
456	exit 1
457}
458END {
459	printf("};\n\n") > sysent
460	printf("};\n") > sysnames
461	printf("#define\t%sMAXSYSCALL\t%d\n", constprefix, syscall) > sysnumhdr
462} '
463
464cat $sysprotos >> $sysarghdr
465cat $sysdcl $sysent > $syssw
466
467#chmod 444 $sysnames $sysnumhdr $syssw
468