xref: /netbsd-src/sys/kern/makesyscalls.sh (revision a5847cc334d9a7029f6352b847e9e8d71a0f9e0c)
1#! /bin/sh -
2#	$NetBSD: makesyscalls.sh,v 1.119 2011/06/26 16:42:42 christos Exp $
3#
4# Copyright (c) 1994, 1996, 2000 Christopher G. Demetriou
5# All rights reserved.
6#
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions
9# are met:
10# 1. Redistributions of source code must retain the above copyright
11#    notice, this list of conditions and the following disclaimer.
12# 2. Redistributions in binary form must reproduce the above copyright
13#    notice, this list of conditions and the following disclaimer in the
14#    documentation and/or other materials provided with the distribution.
15# 3. All advertising materials mentioning features or use of this software
16#    must display the following acknowledgement:
17#      This product includes software developed for the NetBSD Project
18#      by Christopher G. Demetriou.
19# 4. The name of the author may not be used to endorse or promote products
20#    derived from this software without specific prior written permission
21#
22# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
33#	@(#)makesyscalls.sh	8.1 (Berkeley) 6/10/93
34
35set -e
36
37case $# in
38    2)	;;
39    *)	echo "Usage: $0 config-file input-file" 1>&2
40	exit 1
41	;;
42esac
43
44# the config file sets the following variables:
45#	sysalign	check for alignment of off_t
46#	sysnames	the syscall names file
47#	sysnumhdr	the syscall numbers file
48#	syssw		the syscall switch file
49#	sysarghdr	the syscall argument struct definitions
50#	compatopts	those syscall types that are for 'compat' syscalls
51#	switchname	the name for the 'struct sysent' we define
52#	namesname	the name for the 'const char *[]' we define
53#	constprefix	the prefix for the system call constants
54#	registertype	the type for register_t
55#	nsysent		the size of the sysent table
56#	sys_nosys	[optional] name of function called for unsupported
57#			syscalls, if not sys_nosys()
58#       maxsysargs	[optiona] the maximum number or arguments
59#
60# NOTE THAT THIS makesyscalls.sh DOES NOT SUPPORT 'SYSLIBCOMPAT'.
61
62# source the config file.
63sys_nosys="sys_nosys"	# default is sys_nosys(), if not specified otherwise
64maxsysargs=8		# default limit is 8 (32bit) arguments
65rumpcalls="/dev/null"
66rumpcallshdr="/dev/null"
67rumpsysent="rumpsysent.tmp"
68. ./$1
69
70# tmp files:
71sysdcl="sysent.dcl"
72sysprotos="sys.protos"
73syscompat_pref="sysent."
74sysent="sysent.switch"
75sysnamesbottom="sysnames.bottom"
76rumptypes="rumphdr.types"
77rumpprotos="rumphdr.protos"
78
79trap "rm $sysdcl $sysprotos $sysent $sysnamesbottom $rumpsysent $rumptypes $rumpprotos" 0
80
81# Awk program (must support nawk extensions)
82# Use "awk" at Berkeley, "nawk" or "gawk" elsewhere.
83awk=${AWK:-awk}
84
85# Does this awk have a "toupper" function?
86have_toupper=`$awk 'BEGIN { print toupper("true"); exit; }' 2>/dev/null`
87
88# If this awk does not define "toupper" then define our own.
89if [ "$have_toupper" = TRUE ] ; then
90	# Used awk (GNU awk or nawk) provides it
91	toupper=
92else
93	# Provide our own toupper()
94	toupper='
95function toupper(str) {
96	_toupper_cmd = "echo "str" |tr a-z A-Z"
97	_toupper_cmd | getline _toupper_str;
98	close(_toupper_cmd);
99	return _toupper_str;
100}'
101fi
102
103# before handing it off to awk, make a few adjustments:
104#	(1) insert spaces around {, }, (, ), *, and commas.
105#	(2) get rid of any and all dollar signs (so that rcs id use safe)
106#
107# The awk script will deal with blank lines and lines that
108# start with the comment character (';').
109
110sed -e '
111s/\$//g
112:join
113	/\\$/{a\
114
115	N
116	s/\\\n//
117	b join
118	}
1192,${
120	/^#/!s/\([{}()*,|]\)/ \1 /g
121}
122' < $2 | $awk "
123$toupper
124BEGIN {
125	# Create a NetBSD tag that does not get expanded when checking
126	# this script out of CVS.  (This part of the awk script is in a
127	# shell double-quoted string, so the backslashes are eaten by
128	# the shell.)
129	tag = \"\$\" \"NetBSD\" \"\$\"
130
131	# to allow nested #if/#else/#endif sets
132	savedepth = 0
133	# to track already processed syscalls
134
135	sysnames = \"$sysnames\"
136	sysprotos = \"$sysprotos\"
137	sysnumhdr = \"$sysnumhdr\"
138	sysarghdr = \"$sysarghdr\"
139	sysarghdrextra = \"$sysarghdrextra\"
140	rumpcalls = \"$rumpcalls\"
141	rumpcallshdr = \"$rumpcallshdr\"
142	rumpsysent = \"$rumpsysent\"
143	switchname = \"$switchname\"
144	namesname = \"$namesname\"
145	constprefix = \"$constprefix\"
146	registertype = \"$registertype\"
147	sysalign=\"$sysalign\"
148	if (!registertype) {
149	    registertype = \"register_t\"
150	}
151	nsysent = \"$nsysent\"
152
153	sysdcl = \"$sysdcl\"
154	syscompat_pref = \"$syscompat_pref\"
155	sysent = \"$sysent\"
156	sysnamesbottom = \"$sysnamesbottom\"
157	rumpprotos = \"$rumpprotos\"
158	rumptypes = \"$rumptypes\"
159	sys_nosys = \"$sys_nosys\"
160	maxsysargs = \"$maxsysargs\"
161	infile = \"$2\"
162
163	compatopts = \"$compatopts\"
164	"'
165
166	printf "/* %s */\n\n", tag > sysdcl
167	printf "/*\n * System call switch table.\n *\n" > sysdcl
168	printf " * DO NOT EDIT-- this file is automatically generated.\n" > sysdcl
169
170	ncompat = split(compatopts,compat)
171	for (i = 1; i <= ncompat; i++) {
172		compat_upper[i] = toupper(compat[i])
173
174		printf "\n#ifdef %s\n", compat_upper[i] > sysent
175		printf "#define	%s(func) __CONCAT(%s_,func)\n", compat[i], \
176		    compat[i] > sysent
177		printf "#else\n" > sysent
178		printf "#define	%s(func) %s\n", compat[i], sys_nosys > sysent
179		printf "#endif\n" > sysent
180	}
181
182	printf "\n#define\ts(type)\tsizeof(type)\n" > sysent
183	printf "#define\tn(type)\t(sizeof(type)/sizeof (%s))\n", registertype > sysent
184	printf "#define\tns(type)\tn(type), s(type)\n\n", registertype > sysent
185	printf "struct sysent %s[] = {\n",switchname > sysent
186
187	printf "/* %s */\n\n", tag > sysnames
188	printf "/*\n * System call names.\n *\n" > sysnames
189	printf " * DO NOT EDIT-- this file is automatically generated.\n" > sysnames
190
191	printf "\n/*\n * System call prototypes.\n */\n\n" > sysprotos
192
193	printf "/* %s */\n\n", tag > sysnumhdr
194	printf "/*\n * System call numbers.\n *\n" > sysnumhdr
195	printf " * DO NOT EDIT-- this file is automatically generated.\n" > sysnumhdr
196
197	printf "/* %s */\n\n", tag > sysarghdr
198	printf "/*\n * System call argument lists.\n *\n" > sysarghdr
199	printf " * DO NOT EDIT-- this file is automatically generated.\n" > sysarghdr
200
201	printf "/* %s */\n\n", tag > rumpcalls
202	printf "/*\n * System call vector and marshalling for rump.\n *\n" > rumpcalls
203	printf " * DO NOT EDIT-- this file is automatically generated.\n" > rumpcalls
204
205	printf "/* %s */\n\n", tag > rumpcallshdr
206	printf "/*\n * System call protos in rump namespace.\n *\n" > rumpcallshdr
207	printf " * DO NOT EDIT-- this file is automatically generated.\n" > rumpcallshdr
208}
209NR == 1 {
210	sub(/ $/, "")
211	printf " * created from%s\n */\n\n", $0 > sysdcl
212	printf "#include <sys/cdefs.h>\n__KERNEL_RCSID(0, \"%s\");\n\n", tag > sysdcl
213
214	printf " * created from%s\n */\n\n", $0 > sysnames
215	printf "#include <sys/cdefs.h>\n__KERNEL_RCSID(0, \"%s\");\n\n", tag > sysnames
216
217	printf " * created from%s\n */\n\n", $0 > rumpcalls
218	printf "#include <sys/cdefs.h>\n__KERNEL_RCSID(0, \"%s\");\n\n", tag > rumpcalls
219
220	printf "#include <sys/param.h>\n" > rumpcalls
221	printf "#include <sys/fstypes.h>\n" > rumpcalls
222	printf "#include <sys/proc.h>\n" > rumpcalls
223	printf "#ifdef RUMP_CLIENT\n" > rumpcalls
224	printf "#include <srcsys/syscall.h>\n" > rumpcalls
225	printf "#include <srcsys/syscallargs.h>\n\n" > rumpcalls
226	printf "#include <errno.h>\n" > rumpcalls
227	printf "#include <rump/rumpclient.h>\n\n" > rumpcalls
228	printf "#define rsys_syscall(num, data, dlen, retval)\t\\\n" > rumpcalls
229	printf "    rumpclient_syscall(num, data, dlen, retval)\n" > rumpcalls
230	printf "#define rsys_seterrno(error) errno = error\n" > rumpcalls
231	printf "#define rsys_alias(a,b)\n#else\n" > rumpcalls
232	printf "#include <sys/syscall.h>\n" > rumpcalls
233	printf "#include <sys/syscallargs.h>\n\n" > rumpcalls
234	printf "#include <sys/syscallvar.h>\n\n" > rumpcalls
235	printf "#include <rump/rumpuser.h>\n" > rumpcalls
236	printf "#include \"rump_private.h\"\n\n" > rumpcalls
237	printf "static int\nrsys_syscall" > rumpcalls
238	printf "(int num, void *data, size_t dlen, register_t *retval)" > rumpcalls
239	printf "\n{\n\tstruct sysent *callp = rump_sysent + num;\n" > rumpcalls
240	printf "\tint rv;\n" > rumpcalls
241	printf "\n\tKASSERT(num > 0 && num < SYS_NSYSENT);\n\n" > rumpcalls
242	printf "\trump_schedule();\n" > rumpcalls
243	printf "\trv = sy_call(callp, curlwp, data, retval);\n" > rumpcalls
244	printf "\trump_unschedule();\n\n\treturn rv;\n}\n\n" > rumpcalls
245	printf "#define rsys_seterrno(error) rumpuser_seterrno(error)\n" > rumpcalls
246	printf "#define rsys_alias(a,b) __weak_alias(a,b);\n#endif\n\n" > rumpcalls
247
248	printf "#if\tBYTE_ORDER == BIG_ENDIAN\n" > rumpcalls
249	printf "#define SPARG(p,k)\t((p)->k.be.datum)\n" > rumpcalls
250	printf "#else /* LITTLE_ENDIAN, I hope dearly */\n" > rumpcalls
251	printf "#define SPARG(p,k)\t((p)->k.le.datum)\n" > rumpcalls
252	printf "#endif\n\n" > rumpcalls
253	printf "#ifndef RUMP_CLIENT\n" > rumpcalls
254	printf "int rump_enosys(void);\n" > rumpcalls
255	printf "int\nrump_enosys()\n{\n\n\treturn ENOSYS;\n}\n" > rumpcalls
256	printf "#endif\n" > rumpcalls
257
258	printf "\n#ifndef RUMP_CLIENT\n" > rumpsysent
259	printf "#define\ts(type)\tsizeof(type)\n" > rumpsysent
260	printf "#define\tn(type)\t(sizeof(type)/sizeof (%s))\n", registertype > rumpsysent
261	printf "#define\tns(type)\tn(type), s(type)\n\n", registertype > rumpsysent
262	printf "struct sysent rump_sysent[] = {\n" > rumpsysent
263
264	# System call names are included by userland (kdump(1)), so
265	# hide the include files from it.
266	printf "#if defined(_KERNEL_OPT)\n" > sysnames
267
268	printf "#endif /* _KERNEL_OPT */\n\n" > sysnamesbottom
269	printf "const char *const %s[] = {\n",namesname > sysnamesbottom
270
271	printf " * created from%s\n */\n\n", $0 > sysnumhdr
272	printf "#ifndef _" constprefix "SYSCALL_H_\n" > sysnumhdr
273	printf "#define	_" constprefix "SYSCALL_H_\n\n" > sysnumhdr
274
275	printf " * created from%s\n */\n\n", $0 > sysarghdr
276	printf "#ifndef _" constprefix "SYSCALLARGS_H_\n" > sysarghdr
277	printf "#define	_" constprefix "SYSCALLARGS_H_\n\n" > sysarghdr
278
279	printf " * created from%s\n */\n\n", $0 > rumpcallshdr
280	printf "#ifndef _RUMP_RUMP_SYSCALLS_H_\n" > rumpcallshdr
281	printf "#define _RUMP_RUMP_SYSCALLS_H_\n\n" > rumpcallshdr
282	printf "#ifdef _KERNEL\n" > rumpcallshdr
283	printf "#error Interface not supported inside kernel\n" > rumpcallshdr
284	printf "#endif /* _KERNEL */\n\n" > rumpcallshdr
285	printf "#include <sys/types.h> /* typedefs */\n" > rumpcallshdr
286	printf "#include <sys/select.h> /* typedefs */\n" > rumpcallshdr
287	printf "#include <sys/sigtypes.h> /* typedefs */\n" > rumpcallshdr
288	printf "#include <sys/socket.h> /* typedefs */\n\n" > rumpcallshdr
289	printf "#include <rump/rump_syscalls_compat.h>\n\n" > rumpcallshdr
290
291	printf "%s", sysarghdrextra > sysarghdr
292	# Write max number of system call arguments to both headers
293	printf("#define\t%sMAXSYSARGS\t%d\n\n", constprefix, maxsysargs) \
294		> sysnumhdr
295	printf("#define\t%sMAXSYSARGS\t%d\n\n", constprefix, maxsysargs) \
296		> sysarghdr
297	printf "#undef\tsyscallarg\n" > sysarghdr
298	printf "#define\tsyscallarg(x)\t\t\t\t\t\t\t\\\n" > sysarghdr
299	printf "\tunion {\t\t\t\t\t\t\t\t\\\n" > sysarghdr
300	printf "\t\t%s pad;\t\t\t\t\t\t\\\n", registertype > sysarghdr
301	printf "\t\tstruct { x datum; } le;\t\t\t\t\t\\\n" > sysarghdr
302	printf "\t\tstruct { /* LINTED zero array dimension */\t\t\\\n" \
303		> sysarghdr
304	printf "\t\t\tint8_t pad[  /* CONSTCOND */\t\t\t\\\n" > sysarghdr
305	printf "\t\t\t\t(sizeof (%s) < sizeof (x))\t\\\n", \
306		registertype > sysarghdr
307	printf "\t\t\t\t? 0\t\t\t\t\t\\\n" > sysarghdr
308	printf "\t\t\t\t: sizeof (%s) - sizeof (x)];\t\\\n", \
309		registertype > sysarghdr
310	printf "\t\t\tx datum;\t\t\t\t\t\\\n" > sysarghdr
311	printf "\t\t} be;\t\t\t\t\t\t\t\\\n" > sysarghdr
312	printf "\t}\n" > sysarghdr
313	printf("\n#undef check_syscall_args\n") >sysarghdr
314	printf("#define check_syscall_args(call) /*LINTED*/ \\\n" \
315		"\ttypedef char call##_check_args" \
316		    "[sizeof (struct call##_args) \\\n" \
317		"\t\t<= %sMAXSYSARGS * sizeof (%s) ? 1 : -1];\n", \
318		constprefix, registertype) >sysarghdr
319
320	# compat types from syscalls.master.  this is slightly ugly,
321	# but given that we have so few compats from over 17 years,
322	# a more complicated solution is not currently warranted.
323	uncompattypes["struct timeval50"] = "struct timeval";
324	uncompattypes["struct timespec50"] = "struct timespec";
325	uncompattypes["struct stat30"] = "struct stat";
326
327	next
328}
329NF == 0 || $1 ~ /^;/ {
330	next
331}
332$0 ~ /^%%$/ {
333	intable = 1
334	next
335}
336$1 ~ /^#[ 	]*include/ {
337	print > sysdcl
338	print > sysnames
339	next
340}
341$1 ~ /^#/ && !intable {
342	print > sysdcl
343	print > sysnames
344	next
345}
346$1 ~ /^#/ && intable {
347	if ($1 ~ /^#[ 	]*if/) {
348		savedepth++
349		savesyscall[savedepth] = syscall
350	}
351	if ($1 ~ /^#[ 	]*else/) {
352		if (savedepth <= 0) {
353			printf("%s: line %d: unbalanced #else\n", \
354			    infile, NR)
355			exit 1
356		}
357		syscall = savesyscall[savedepth]
358	}
359	if ($1 ~ /^#[       ]*endif/) {
360		if (savedepth <= 0) {
361			printf("%s: line %d: unbalanced #endif\n", \
362			    infile, NR)
363			exit 1
364		}
365		savedepth--
366	}
367	print > sysent
368	print > sysarghdr
369	print > sysnumhdr
370	print > sysprotos
371	print > sysnamesbottom
372
373	# XXX: technically we do not want to have conditionals in rump,
374	# but it is easier to just let the cpp handle them than try to
375	# figure out what we want here in this script
376	print > rumpsysent
377	next
378}
379syscall != $1 {
380	printf "%s: line %d: syscall number out of sync at %d\n", \
381	   infile, NR, syscall
382	printf "line is:\n"
383	print
384	exit 1
385}
386function parserr(was, wanted) {
387	printf "%s: line %d: unexpected %s (expected <%s>)\n", \
388	    infile, NR, was, wanted
389	printf "line is:\n"
390	print
391	exit 1
392}
393function parseline() {
394	f=3			# toss number and type
395	if ($2 == "INDIR")
396		sycall_flags="SYCALL_INDIRECT"
397	else
398		sycall_flags="0"
399	if ($NF != "}") {
400		funcalias=$NF
401		end=NF-1
402	} else {
403		funcalias=""
404		end=NF
405	}
406	if ($f == "INDIR") {		# allow for "NOARG INDIR"
407		sycall_flags = "SYCALL_INDIRECT | " sycall_flags
408		f++
409	}
410	if ($f == "MODULAR") {		# registered at runtime
411		modular = 1
412		f++
413	} else {
414		modular =  0;
415	}
416	if ($f == "RUMP") {
417		rumpable = 1
418		f++
419	} else {
420		rumpable = 0
421	}
422	if ($f ~ /^[a-z0-9_]*$/) {	# allow syscall alias
423		funcalias=$f
424		f++
425	}
426	if ($f != "{")
427		parserr($f, "{")
428	f++
429	if ($end != "}")
430		parserr($end, "}")
431	end--
432	if ($end != ";")
433		parserr($end, ";")
434	end--
435	if ($end != ")")
436		parserr($end, ")")
437	end--
438
439	returntype = oldf = "";
440	do {
441		if (returntype != "" && oldf != "*")
442			returntype = returntype" ";
443		returntype = returntype$f;
444		oldf = $f;
445		f++
446	} while ($f != "|" && f < (end-1))
447	if (f == (end - 1)) {
448		parserr($f, "function argument definition (maybe \"|\"?)");
449	}
450	f++
451
452	fprefix=$f
453	f++
454	if ($f != "|") {
455		parserr($f, "function compat delimiter (maybe \"|\"?)");
456	}
457	f++
458
459	fcompat=""
460	if ($f != "|") {
461		fcompat=$f
462		f++
463	}
464
465	if ($f != "|") {
466		parserr($f, "function name delimiter (maybe \"|\"?)");
467	}
468	f++
469	fbase=$f
470
471	# pipe is special in how to returns its values.
472	# So just generate it manually if present.
473	if (rumpable == 1 && fbase == "pipe") {
474		rumpable = 0;
475		rumphaspipe = 1;
476	}
477
478	if (fcompat != "") {
479		funcname=fprefix "___" fbase "" fcompat
480	} else {
481		funcname=fprefix "_" fbase
482	}
483	if (returntype == "quad_t" || returntype == "off_t") {
484		if (sycall_flags == "0")
485			sycall_flags = "SYCALL_RET_64";
486		else
487			sycall_flags = "SYCALL_RET_64 | " sycall_flags;
488	}
489
490	if (funcalias == "") {
491		funcalias=funcname
492		sub(/^([^_]+_)*sys_/, "", funcalias)
493		realname=fbase
494	} else {
495		realname=funcalias
496	}
497	rumpfname=realname "" fcompat
498	f++
499
500	if ($f != "(")
501		parserr($f, "(")
502	f++
503
504	argc=0;
505	argalign=0;
506	if (f == end) {
507		if ($f != "void")
508			parserr($f, "argument definition")
509		isvarargs = 0;
510		varargc = 0;
511		argtype[0]="void";
512		return
513	}
514
515	# some system calls (open() and fcntl()) can accept a variable
516	# number of arguments.  If syscalls accept a variable number of
517	# arguments, they must still have arguments specified for
518	# the remaining argument "positions," because of the way the
519	# kernel system call argument handling works.
520	#
521	# Indirect system calls, e.g. syscall(), are exceptions to this
522	# rule, since they are handled entirely by machine-dependent code
523	# and do not need argument structures built.
524
525	isvarargs = 0;
526	args64 = 0;
527	while (f <= end) {
528		if ($f == "...") {
529			f++;
530			isvarargs = 1;
531			varargc = argc;
532			continue;
533		}
534		argc++
535		argtype[argc]=""
536		oldf=""
537		while (f < end && $(f+1) != ",") {
538			if (argtype[argc] != "" && oldf != "*")
539				argtype[argc] = argtype[argc]" ";
540			argtype[argc] = argtype[argc]$f;
541			oldf = $f;
542			f++
543		}
544		if (argtype[argc] == "")
545			parserr($f, "argument definition")
546		if (argtype[argc] == "off_t"  \
547		  || argtype[argc] == "dev_t" \
548		  || argtype[argc] == "time_t") {
549			if ((argalign % 2) != 0 && sysalign &&
550			    funcname != "sys_posix_fadvise") # XXX for now
551				parserr($f, "a padding argument")
552		} else {
553			argalign++;
554		}
555		if (argtype[argc] == "quad_t" || argtype[argc] == "off_t" \
556		  || argtype[argc] == "dev_t" || argtype[argc] == "time_t") {
557			if (sycall_flags == "0")
558				sycall_flags = "SYCALL_ARG"argc-1"_64";
559			else
560				sycall_flags = "SYCALL_ARG"argc-1"_64 | " sycall_flags;
561			args64++;
562		}
563		argname[argc]=$f;
564		f += 2;			# skip name, and any comma
565	}
566	if (args64 > 0)
567		sycall_flags = "SYCALL_NARGS64_VAL("args64") | " sycall_flags;
568	# must see another argument after varargs notice.
569	if (isvarargs) {
570		if (argc == varargc)
571			parserr($f, "argument definition")
572	} else
573		varargc = argc;
574}
575
576function printproto(wrap) {
577	printf("/* syscall: \"%s%s\" ret: \"%s\" args:", wrap, funcalias,
578	    returntype) > sysnumhdr
579	for (i = 1; i <= varargc; i++)
580		printf(" \"%s\"", argtype[i]) > sysnumhdr
581	if (isvarargs)
582		printf(" \"...\"") > sysnumhdr
583	printf(" */\n") > sysnumhdr
584	printf("#define\t%s%s%s\t%d\n\n", constprefix, wrap, funcalias,
585	    syscall) > sysnumhdr
586
587	# rumpalooza
588	if (!rumpable)
589		return
590
591	# accumulate fbases we have seen.  we want the last
592	# occurence for the default __RENAME()
593	seen = funcseen[fbase]
594	funcseen[fbase] = rumpfname
595	if (seen)
596		return
597
598	printf("%s rump_sys_%s(", returntype, realname) > rumpprotos
599
600	for (i = 1; i < varargc; i++)
601		if (argname[i] != "PAD")
602			printf("%s, ", uncompattype(argtype[i])) > rumpprotos
603
604	if (isvarargs)
605		printf("%s, ...)", uncompattype(argtype[varargc]))>rumpprotos
606	else
607		printf("%s)", uncompattype(argtype[argc])) > rumpprotos
608
609	printf(" __RENAME(RUMP_SYS_RENAME_%s)", toupper(fbase))> rumpprotos
610	printf(";\n") > rumpprotos
611
612	# generate forward-declares for types, apart from the
613	# braindead typedef jungle we cannot easily handle here
614	for (i = 1; i <= varargc; i++) {
615		type=uncompattype(argtype[i])
616		sub("const ", "", type)
617		if (!typeseen[type] && \
618		    match(type, "struct") && match(type, "\\*")) {
619			typeseen[type] = 1
620			sub(" *\\*", "", type);
621			printf("%s;\n", type) > rumptypes
622		}
623	}
624}
625
626function printrumpsysent(insysent, compatwrap) {
627	if (!insysent) {
628		eno[0] = "rump_enosys"
629		eno[1] = "sys_nomodule"
630		flags[0] = "SYCALL_NOSYS"
631		flags[1] = "0"
632		printf("\t{ 0, 0, %s,\n\t    (sy_call_t *)%s }, \t"	\
633		    "/* %d = %s */\n",					\
634		    flags[modular], eno[modular], syscall, funcalias)	\
635		    > rumpsysent
636		return
637	}
638
639	printf("\t{ ") > rumpsysent
640	if (argc == 0) {
641		printf("0, 0, ") > rumpsysent
642	} else {
643		printf("ns(struct %ssys_%s_args), ", compatwrap_, funcalias) > rumpsysent
644	}
645
646	if (compatwrap == "") {
647		if (modular)
648			rfn = "(sy_call_t *)sys_nomodule"
649		else
650			rfn = "(sy_call_t *)" funcname
651	} else {
652		rfn = "(sy_call_t *)" compatwrap "_" funcname
653	}
654
655	printf("0,\n\t    %s },", rfn) > rumpsysent
656	for (i = 0; i < (33 - length(rfn)) / 8; i++)
657		printf("\t") > rumpsysent
658	printf("/* %d = %s%s */\n", syscall, compatwrap_, funcalias) > rumpsysent
659}
660
661function iscompattype(type) {
662	for (var in uncompattypes) {
663		if (match(type, var)) {
664			return 1
665		}
666	}
667
668	return 0
669}
670
671function uncompattype(type) {
672	for (var in uncompattypes) {
673		if (match(type, var)) {
674			sub(var, uncompattypes[var], type)
675			return type
676		}
677	}
678
679	return type
680}
681
682function putent(type, compatwrap) {
683	# output syscall declaration for switch table.
684	if (compatwrap == "")
685		compatwrap_ = ""
686	else
687		compatwrap_ = compatwrap "_"
688	if (argc == 0)
689		arg_type = "void";
690	else {
691		arg_type = "struct " compatwrap_ funcname "_args";
692	}
693	proto = "int\t" compatwrap_ funcname "(struct lwp *, const " \
694	    arg_type " *, register_t *);\n"
695	if (sysmap[proto] != 1) {
696		sysmap[proto] = 1;
697		print proto > sysprotos;
698	}
699
700	# output syscall switch entry
701	printf("\t{ ") > sysent
702	if (argc == 0) {
703		printf("0, 0, ") > sysent
704	} else {
705		printf("ns(struct %s%s_args), ", compatwrap_, funcname) > sysent
706	}
707	if (modular)
708		wfn = "(sy_call_t *)sys_nomodule";
709	else if (compatwrap == "")
710		wfn = "(sy_call_t *)" funcname;
711	else
712		wfn = "(sy_call_t *)" compatwrap "(" funcname ")";
713	printf("%s,\n\t    %s },", sycall_flags, wfn) > sysent
714	for (i = 0; i < (33 - length(wfn)) / 8; i++)
715		printf("\t") > sysent
716	printf("/* %d = %s%s */\n", syscall, compatwrap_, funcalias) > sysent
717
718	# output syscall name for names table
719	printf("\t/* %3d */\t\"%s%s\",\n", syscall, compatwrap_, funcalias) \
720	    > sysnamesbottom
721
722	# output syscall number of header, if appropriate
723	if (type == "STD" || type == "NOARGS" || type == "INDIR" || \
724	    type == "NOERR") {
725		# output a prototype, to be used to generate lint stubs in
726		# libc.
727		printproto("")
728	} else if (type == "COMPAT") {
729		# Just define the syscall number with a comment.  These
730		# may be used by compatibility stubs in libc.
731		printproto(compatwrap_)
732	}
733
734	# output syscall argument structure, if it has arguments
735	if (argc != 0) {
736		printf("\nstruct %s%s_args", compatwrap_, funcname) > sysarghdr
737		if (type != "NOARGS") {
738			print " {" >sysarghdr;
739			for (i = 1; i <= argc; i++)
740				printf("\tsyscallarg(%s) %s;\n", argtype[i],
741				    argname[i]) > sysarghdr
742			printf "}" >sysarghdr;
743		}
744		printf(";\n") > sysarghdr
745		if (type != "NOARGS" && type != "INDIR") {
746			printf("check_syscall_args(%s%s)\n", compatwrap_,
747			    funcname) >sysarghdr
748		}
749	}
750
751	if (!rumpable) {
752		if (funcname == "sys_pipe" && rumphaspipe == 1)
753			insysent = 1
754		else
755			insysent = 0
756	} else {
757		insysent = 1
758	}
759	printrumpsysent(insysent, compatwrap)
760
761	# output rump marshalling code if necessary
762	if (!rumpable) {
763		return
764	}
765
766	# need a local prototype, we export the re-re-named one in .h
767	printf("\n%s rump___sysimpl_%s(", returntype, rumpfname) \
768	    > rumpcalls
769	for (i = 1; i < argc; i++) {
770		if (argname[i] != "PAD")
771			printf("%s, ", uncompattype(argtype[i])) > rumpcalls
772	}
773	printf("%s);", uncompattype(argtype[argc])) > rumpcalls
774
775	printf("\n%s\nrump___sysimpl_%s(", returntype, rumpfname) > rumpcalls
776	for (i = 1; i < argc; i++) {
777		if (argname[i] != "PAD")
778			printf("%s %s, ", uncompattype(argtype[i]), \
779			    argname[i]) > rumpcalls
780	}
781	printf("%s %s)\n", uncompattype(argtype[argc]), argname[argc]) \
782	    > rumpcalls
783	printf("{\n\tregister_t retval[2] = {0, 0};\n") > rumpcalls
784	if (returntype != "void") {
785		if (type != "NOERR") {
786			printf("\tint error = 0;\n") > rumpcalls
787		}
788		# assume rumpcalls return only integral types
789		printf("\t%s rv = -1;\n", returntype) > rumpcalls
790	}
791
792	argarg = "NULL"
793	argsize = 0;
794	if (argc) {
795		argarg = "&callarg"
796		argsize = "sizeof(callarg)"
797		printf("\tstruct %s%s_args callarg;\n\n",compatwrap_,funcname) \
798		    > rumpcalls
799		for (i = 1; i <= argc; i++) {
800			if (argname[i] == "PAD") {
801				printf("\tSPARG(&callarg, %s) = 0;\n", \
802				    argname[i]) > rumpcalls
803			} else {
804				if (iscompattype(argtype[i])) {
805					printf("\tSPARG(&callarg, %s) = "    \
806					"(%s)%s;\n", argname[i], argtype[i], \
807					argname[i]) > rumpcalls
808				} else {
809					printf("\tSPARG(&callarg, %s) = %s;\n",\
810					    argname[i], argname[i]) > rumpcalls
811				}
812			}
813		}
814		printf("\n") > rumpcalls
815	} else {
816		printf("\n") > rumpcalls
817	}
818	printf("\t") > rumpcalls
819	if (returntype != "void" && type != "NOERR")
820		printf("error = ") > rumpcalls
821	printf("rsys_syscall(%s%s%s, " \
822	    "%s, %s, retval);\n", constprefix, compatwrap_, funcalias, \
823	    argarg, argsize) > rumpcalls
824	if (type != "NOERR") {
825		printf("\trsys_seterrno(error);\n") > rumpcalls
826		printf("\tif (error == 0) {\n") > rumpcalls
827		indent="\t\t"
828		ending="\t}\n"
829	} else {
830		indent="\t"
831		ending=""
832	}
833	if (returntype != "void") {
834		printf("%sif (sizeof(%s) > sizeof(register_t))\n", \
835		    indent, returntype) > rumpcalls
836		printf("%s\trv = *(%s *)retval;\n", \
837		    indent, returntype) > rumpcalls
838		printf("%selse\n", indent, indent) > rumpcalls
839		printf("%s\trv = *retval;\n", indent, returntype) > rumpcalls
840		printf("%s", ending) > rumpcalls
841		printf("\treturn rv;\n") > rumpcalls
842	}
843	printf("}\n") > rumpcalls
844	printf("rsys_alias(%s%s,rump_enosys)\n", \
845	    compatwrap_, funcname) > rumpcalls
846
847}
848$2 == "STD" || $2 == "NODEF" || $2 == "NOARGS" || $2 == "INDIR" \
849    || $2 == "NOERR" {
850	parseline()
851	putent($2, "")
852	syscall++
853	next
854}
855$2 == "OBSOL" || $2 == "UNIMPL" || $2 == "EXCL" || $2 == "IGNORED" {
856	if ($2 == "OBSOL")
857		comment="obsolete"
858	else if ($2 == "EXCL")
859		comment="excluded"
860	else if ($2 == "IGNORED")
861		comment="ignored"
862	else
863		comment="unimplemented"
864	for (i = 3; i <= NF; i++)
865		comment=comment " " $i
866
867	if ($2 == "IGNORED")
868		sys_stub = "(sy_call_t *)nullop";
869	else
870		sys_stub = sys_nosys;
871
872	printf("\t{ 0, 0, 0,\n\t    %s },\t\t\t/* %d = %s */\n", \
873	    sys_stub, syscall, comment) > sysent
874	printf("\t{ 0, 0, SYCALL_NOSYS,\n\t    %s },\t\t/* %d = %s */\n", \
875	    "(sy_call_t *)rump_enosys", syscall, comment) > rumpsysent
876	printf("\t/* %3d */\t\"#%d (%s)\",\n", syscall, syscall, comment) \
877	    > sysnamesbottom
878	if ($2 != "UNIMPL")
879		printf("\t\t\t\t/* %d is %s */\n", syscall, comment) > sysnumhdr
880	syscall++
881	next
882}
883{
884	for (i = 1; i <= ncompat; i++) {
885		if ($2 == compat_upper[i]) {
886			parseline();
887			putent("COMPAT", compat[i])
888			syscall++
889			next
890		}
891	}
892	printf("%s: line %d: unrecognized keyword %s\n", infile, NR, $2)
893	exit 1
894}
895END {
896	# output pipe() syscall with its special retval[2] handling
897	if (rumphaspipe) {
898		printf("int rump_sys_pipe(int *);\n") > rumpprotos
899		printf("\nint rump_sys_pipe(int *);\n") > rumpcalls
900		printf("int\nrump_sys_pipe(int *fd)\n{\n") > rumpcalls
901		printf("\tregister_t retval[2] = {0, 0};\n") > rumpcalls
902		printf("\tint error = 0;\n") > rumpcalls
903		printf("\n\terror = rsys_syscall(SYS_pipe, ") > rumpcalls
904		printf("NULL, 0, retval);\n") > rumpcalls
905		printf("\tif (error) {\n") > rumpcalls
906		printf("\t\trsys_seterrno(error);\n") > rumpcalls
907		printf("\t} else {\n\t\tfd[0] = retval[0];\n") > rumpcalls
908		printf("\t\tfd[1] = retval[1];\n\t}\n") > rumpcalls
909		printf("\treturn error ? -1 : 0;\n}\n") > rumpcalls
910	}
911
912	# print default rump syscall interfaces
913	for (var in funcseen) {
914		printf("#ifndef RUMP_SYS_RENAME_%s\n", \
915		    toupper(var)) > rumpcallshdr
916		printf("#define RUMP_SYS_RENAME_%s rump___sysimpl_%s\n", \
917		    toupper(var), funcseen[var]) > rumpcallshdr
918		printf("#endif\n\n") > rumpcallshdr
919	}
920
921	maxsyscall = syscall
922	if (nsysent) {
923		if (syscall > nsysent) {
924			printf("%s: line %d: too many syscalls [%d > %d]\n", infile, NR, syscall, nsysent)
925			exit 1
926		}
927		while (syscall < nsysent) {
928			printf("\t{ 0, 0, 0,\n\t    %s },\t\t\t/* %d = filler */\n", \
929			    sys_nosys, syscall) > sysent
930			printf("\t{ 0, 0, SYCALL_NOSYS,\n\t    %s },\t\t/* %d = filler */\n", \
931			    "(sy_call_t *)rump_enosys", syscall) > rumpsysent
932			printf("\t/* %3d */\t\"# filler\",\n", syscall) \
933			    > sysnamesbottom
934			syscall++
935		}
936	}
937	printf("};\n") > sysent
938	printf("};\n") > rumpsysent
939	printf("CTASSERT(__arraycount(rump_sysent) == SYS_NSYSENT);\n") > rumpsysent
940	printf("#endif /* RUMP_CLIENT */\n") > rumpsysent
941	printf("};\n") > sysnamesbottom
942	printf("#define\t%sMAXSYSCALL\t%d\n", constprefix, maxsyscall) > sysnumhdr
943	if (nsysent)
944		printf("#define\t%sNSYSENT\t%d\n", constprefix, nsysent) > sysnumhdr
945} '
946
947cat $sysprotos >> $sysarghdr
948echo "#endif /* _${constprefix}SYSCALL_H_ */" >> $sysnumhdr
949echo "#endif /* _${constprefix}SYSCALLARGS_H_ */" >> $sysarghdr
950printf "\n#endif /* _RUMP_RUMP_SYSCALLS_H_ */\n" >> $rumpprotos
951cat $sysdcl $sysent > $syssw
952cat $sysnamesbottom >> $sysnames
953cat $rumpsysent >> $rumpcalls
954
955touch $rumptypes
956cat $rumptypes >> $rumpcallshdr
957echo >> $rumpcallshdr
958cat $rumpprotos >> $rumpcallshdr
959
960#chmod 444 $sysnames $sysnumhdr $syssw
961