xref: /openbsd/sys/kern/makesyscalls.sh (revision 07ea8d15)
1#! /bin/sh -
2#	$NetBSD: makesyscalls.sh,v 1.18 1996/03/15 01:25:12 cgd Exp $
3#
4# Copyright (c) 1994 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# source the config file.
45. $1
46
47# the config file sets the following variables:
48#	sysnames	the syscall names file
49#	sysnumhdr	the syscall numbers file
50#	syssw		the syscall switch file
51#	sysarghdr	the syscall argument struct definitions
52#	compatopts	those syscall types that are for 'compat' syscalls
53#	switchname	the name for the 'struct sysent' we define
54#	namesname	the name for the 'char *[]' we define
55#	constprefix	the prefix for the system call constants
56#
57# NOTE THAT THIS makesyscalls.sh DOES NOT SUPPORT 'LIBCOMPAT'.
58
59# tmp files:
60sysdcl="sysent.dcl"
61sysprotos="sys.protos"
62syscompat_pref="sysent."
63sysent="sysent.switch"
64
65trap "rm $sysdcl $sysprotos $sysent" 0
66
67# Awk program (must support nawk extensions)
68# Use "awk" at Berkeley, "nawk" or "gawk" elsewhere.
69awk=${AWK:-awk}
70
71# Does this awk have a "toupper" function? (i.e. is it GNU awk)
72isgawk=`$awk 'BEGIN { print toupper("true"); exit; }' 2>/dev/null`
73
74# If this awk does not define "toupper" then define our own.
75if [ "$isgawk" = TRUE ] ; then
76	# GNU awk provides it.
77	toupper=
78else
79	# Provide our own toupper()
80	toupper='
81function toupper(str) {
82	_toupper_cmd = "echo "str" |tr a-z A-Z"
83	_toupper_cmd | getline _toupper_str;
84	close(_toupper_cmd);
85	return _toupper_str;
86}'
87fi
88
89# before handing it off to awk, make a few adjustments:
90#	(1) insert spaces around {, }, (, ), *, and commas.
91#	(2) get rid of any and all dollar signs (so that rcs id use safe)
92#
93# The awk script will deal with blank lines and lines that
94# start with the comment character (';').
95
96sed -e '
97s/\$//g
98:join
99	/\\$/{a\
100
101	N
102	s/\\\n//
103	b join
104	}
1052,${
106	/^#/!s/\([{}()*,]\)/ \1 /g
107}
108' < $2 | $awk "
109$toupper
110BEGIN {
111	# to allow nested #if/#else/#endif sets
112	savedepth = 0
113
114	sysnames = \"$sysnames\"
115	sysprotos = \"$sysprotos\"
116	sysnumhdr = \"$sysnumhdr\"
117	sysarghdr = \"$sysarghdr\"
118	switchname = \"$switchname\"
119	namesname = \"$namesname\"
120	constprefix = \"$constprefix\"
121
122	sysdcl = \"$sysdcl\"
123	syscompat_pref = \"$syscompat_pref\"
124	sysent = \"$sysent\"
125	infile = \"$2\"
126
127	compatopts = \"$compatopts\"
128	"'
129
130	printf "/*\n * System call switch table.\n *\n" > sysdcl
131	printf " * DO NOT EDIT-- this file is automatically generated.\n" > sysdcl
132
133	ncompat = split(compatopts,compat)
134	for (i = 1; i <= ncompat; i++) {
135		compat_upper[i] = toupper(compat[i])
136
137		printf "\n#ifdef %s\n", compat_upper[i] > sysent
138		printf "#define %s(func) __CONCAT(%s_,func)\n", compat[i], \
139		    compat[i] > sysent
140		printf "#else\n" > sysent
141		printf "#define %s(func) sys_nosys\n", compat[i] > sysent
142		printf "#endif\n" > sysent
143	}
144
145	printf "\n#define\ts(type)\tsizeof(type)\n\n" > sysent
146	printf "struct sysent %s[] = {\n",switchname > sysent
147
148	printf "/*\n * System call names.\n *\n" > sysnames
149	printf " * DO NOT EDIT-- this file is automatically generated.\n" > sysnames
150
151	printf "\n/*\n * System call prototypes.\n */\n\n" > sysprotos
152
153	printf "/*\n * System call numbers.\n *\n" > sysnumhdr
154	printf " * DO NOT EDIT-- this file is automatically generated.\n" > sysnumhdr
155
156	printf "/*\n * System call argument lists.\n *\n" > sysarghdr
157	printf " * DO NOT EDIT-- this file is automatically generated.\n" > sysarghdr
158}
159NR == 1 {
160	printf " * created from%s\n */\n\n", $0 > sysdcl
161
162	printf " * created from%s\n */\n\n", $0 > sysnames
163	printf "char *%s[] = {\n",namesname > sysnames
164
165	printf " * created from%s\n */\n\n", $0 > sysnumhdr
166
167	printf " * created from%s\n */\n\n", $0 > sysarghdr
168	printf "#define\tsyscallarg(x)\tunion { x datum; register_t pad; }\n" \
169		> sysarghdr
170	next
171}
172NF == 0 || $1 ~ /^;/ {
173	next
174}
175$1 ~ /^#[ 	]*include/ {
176	print > sysdcl
177	next
178}
179$1 ~ /^#[ 	]*if/ {
180	print > sysent
181	print > sysprotos
182	print > sysnames
183	savesyscall[++savedepth] = syscall
184	next
185}
186$1 ~ /^#[ 	]*else/ {
187	print > sysent
188	print > sysprotos
189	print > sysnames
190	if (savedepth <= 0) {
191		printf "%s: line %d: unbalenced #else\n", \
192		    infile, NR
193		exit 1
194	}
195	syscall = savesyscall[savedepth]
196	next
197}
198$1 ~ /^#/ {
199	if ($1 ~ /^#[       ]*endif/) {
200		if (savedepth <= 0) {
201			printf "%s: line %d: unbalenced #endif\n", \
202			    infile, NR
203			exit 1
204		}
205		savedepth--;
206	}
207	print > sysent
208	print > sysprotos
209	print > sysnames
210	next
211}
212syscall != $1 {
213	printf "%s: line %d: syscall number out of sync at %d\n", \
214	   infile, NR, syscall
215	printf "line is:\n"
216	print
217	exit 1
218}
219function parserr(was, wanted) {
220	printf "%s: line %d: unexpected %s (expected %s)\n", \
221	    infile, NR, was, wanted
222	exit 1
223}
224function parseline() {
225	f=3			# toss number and type
226	if ($NF != "}") {
227		funcalias=$NF
228		end=NF-1
229	} else {
230		funcalias=""
231		end=NF
232	}
233	if ($f != "{")
234		parserr($f, "{")
235	f++
236	if ($end != "}")
237		parserr($end, "}")
238	end--
239	if ($end != ";")
240		parserr($end, ";")
241	end--
242	if ($end != ")")
243		parserr($end, ")")
244	end--
245
246	f++			# toss return type
247
248	funcname=$f
249	if (funcalias == "") {
250		funcalias=funcname
251		sub(/^([^_]+_)*sys_/, "", funcalias)
252	}
253	f++
254
255	if ($f != "(")
256		parserr($f, ")")
257	f++
258
259	argc= 0;
260	if (f == end) {
261		if ($f != "void")
262			parserr($f, "argument definition")
263		return
264	}
265
266	while (f <= end) {
267		argc++
268		argtype[argc]=""
269		oldf=""
270		while (f < end && $(f+1) != ",") {
271			if (argtype[argc] != "" && oldf != "*")
272				argtype[argc] = argtype[argc]" ";
273			argtype[argc] = argtype[argc]$f;
274			oldf = $f;
275			f++
276		}
277		if (argtype[argc] == "")
278			parserr($f, "argument definition")
279		argname[argc]=$f;
280		f += 2;			# skip name, and any comma
281	}
282}
283function putent(nodefs, compatwrap) {
284	# output syscall declaration for switch table
285	prototype = "__P((struct proc *, void *, register_t *))"
286	if (compatwrap == "")
287		printf("int\t%s\t%s;\n", funcname, prototype) > sysprotos
288	else
289		printf("int\t%s_%s\t%s;\n", compatwrap, funcname, prototype) > sysprotos
290
291	# output syscall switch entry
292#	printf("\t{ { %d", argc) > sysent
293#	for (i = 1; i <= argc; i++) {
294#		if (i == 5) 		# wrap the line
295#			printf(",\n\t    ") > sysent
296#		else
297#			printf(", ") > sysent
298#		printf("s(%s)", argtypenospc[i]) > sysent
299#	}
300	printf("\t{ %d, ", argc) > sysent
301	if (argc == 0)
302		printf("0") > sysent
303	else if (compatwrap == "")
304		printf("s(struct %s_args)", funcname) > sysent
305	else
306		printf("s(struct %s_%s_args)", compatwrap, funcname) > sysent
307	if (compatwrap == "")
308		wfn = sprintf("%s", funcname);
309	else
310		wfn = sprintf("%s(%s)", compatwrap, funcname);
311	printf(",\n\t    %s },", wfn) > sysent
312	for (i = 0; i < (33 - length(wfn)) / 8; i++)
313		printf("\t") > sysent
314	if (compatwrap == "")
315		printf("/* %d = %s */\n", syscall, funcalias) > sysent
316	else
317		printf("/* %d = %s %s */\n", syscall, compatwrap,
318		    funcalias) > sysent
319
320	# output syscall name for names table
321	if (compatwrap == "")
322		printf("\t\"%s\",\t\t\t/* %d = %s */\n", funcalias, syscall,
323		    funcalias) > sysnames
324	else
325		printf("\t\"%s_%s\",\t/* %d = %s %s */\n", compatwrap,
326		    funcalias, syscall, compatwrap, funcalias) > sysnames
327
328	# output syscall number of header, if appropriate
329	if (nodefs == "" || nodefs == "NOARGS")
330		printf("#define\t%s%s\t%d\n", constprefix, funcalias,
331		    syscall) > sysnumhdr
332	else if (nodefs != "NODEF")
333		printf("\t\t\t\t/* %d is %s %s */\n", syscall,
334		    compatwrap, funcalias) > sysnumhdr
335
336	# output syscall argument structure, if it has arguments
337	if (argc != 0 && nodefs != "NOARGS") {
338		if (compatwrap == "")
339			printf("\nstruct %s_args {\n", funcname) > sysarghdr
340		else
341			printf("\nstruct %s_%s_args {\n", compatwrap,
342			    funcname) > sysarghdr
343		for (i = 1; i <= argc; i++)
344			printf("\tsyscallarg(%s) %s;\n", argtype[i],
345			    argname[i]) > sysarghdr
346		printf("};\n") > sysarghdr
347	}
348}
349$2 == "STD" {
350	parseline()
351	putent("", "");
352	syscall++
353	next
354}
355$2 == "NODEF" || $2 == "NOARGS" {
356	parseline()
357	putent($2, "")
358	syscall++
359	next
360}
361$2 == "OBSOL" || $2 == "UNIMPL" {
362	if ($2 == "OBSOL")
363		comment="obsolete"
364	else
365		comment="unimplemented"
366	for (i = 3; i <= NF; i++)
367		comment=comment " " $i
368
369	printf("\t{ 0, 0,\n\t    sys_nosys },\t\t\t/* %d = %s */\n", \
370	    syscall, comment) > sysent
371	printf("\t\"#%d (%s)\",\t\t/* %d = %s */\n", \
372	    syscall, comment, syscall, comment) > sysnames
373	if ($2 != "UNIMPL")
374		printf("\t\t\t\t/* %d is %s */\n", syscall, comment) > sysnumhdr
375	syscall++
376	next
377}
378{
379	for (i = 1; i <= ncompat; i++) {
380		if ($2 == compat_upper[i]) {
381			parseline();
382			putent("COMMENT", compat[i])
383			syscall++
384			next
385		}
386	}
387	printf "%s: line %d: unrecognized keyword %s\n", infile, NR, $2
388	exit 1
389}
390END {
391	printf("};\n\n") > sysent
392	printf("};\n") > sysnames
393	printf("#define\t%sMAXSYSCALL\t%d\n", constprefix, syscall) > sysnumhdr
394} '
395
396cat $sysprotos >> $sysarghdr
397cat $sysdcl $sysent > $syssw
398
399#chmod 444 $sysnames $sysnumhdr $syssw
400