[BACK]Return to makesyscalls.sh CVS log [TXT][DIR] Up to [local] / src / sys / kern

File: [local] / src / sys / kern / makesyscalls.sh (download)

Revision 1.22, Sun Jan 7 20:52:44 2024 UTC (5 months ago) by miod
Branch: MAIN
CVS Tags: OPENBSD_7_5_BASE, OPENBSD_7_5, HEAD
Changes since 1.21: +6 -1 lines

Error out if one syscall ever takes more than 6 arguments.

This is not necessarily wrong per se, but would need special consideration,
as not all platforms are currently able to process more than six syscall
arguments (and upcoming diffs will rely upon reasonably-sized argument
lists), so better break now and reconsider later if need be.

ok deraadt@

#! /bin/sh -
#	$OpenBSD: makesyscalls.sh,v 1.22 2024/01/07 20:52:44 miod Exp $
#	$NetBSD: makesyscalls.sh,v 1.26 1998/01/09 06:17:51 thorpej Exp $
#
# Copyright (c) 1994,1996 Christopher G. Demetriou
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
#    must display the following acknowledgement:
#      This product includes software developed for the NetBSD Project
#      by Christopher G. Demetriou.
# 4. The name of the author may not be used to endorse or promote products
#    derived from this software without specific prior written permission
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#	@(#)makesyscalls.sh	8.1 (Berkeley) 6/10/93

set -e

case $# in
    1)	;;
    *)	echo "Usage: $0 input-file" 1>&2
	exit 1
	;;
esac

sysnames="syscalls.c"
sysnumhdr="../sys/syscall.h"
syssw="init_sysent.c"
sysarghdr="../sys/syscallargs.h"

# Any additions to the next line for options that are required for the
# (new) kernel to boot an existing userland must be coordinated with
# the snapshot builders
compatopts=""

switchname="sysent"
namesname="syscallnames"
constprefix="SYS_"

# this script sets the following variables:
#	sysnames	the syscall names file
#	sysnumhdr	the syscall numbers file
#	syssw		the syscall switch file
#	sysarghdr	the syscall argument struct definitions
#	compatopts	those syscall types that are for 'compat' syscalls
#	switchname	the name for the 'const struct sysent' we define
#	namesname	the name for the 'const char *const[]' we define
#	constprefix	the prefix for the system call constants
#
# NOTE THAT THIS makesyscalls.sh DOES NOT SUPPORT 'LIBCOMPAT'.

# tmp files:
sysdcl="sysent.dcl"
sysprotos="sys.protos"
syscompat_pref="sysent."
sysent="sysent.switch"

trap "rm $sysdcl $sysprotos $sysent" 0

# before handing it off to awk, make a few adjustments:
#	(1) insert spaces around {, }, (, ), *, and commas.
#	(2) get rid of any and all dollar signs (so that rcs id use safe)
#
# The awk script will deal with blank lines and lines that
# start with the comment character (';').

sed -e '
s/\$//g
:join
	/\\$/{a\

	N
	s/\\\n//
	b join
	}
2,${
	/^#/!s/\([{}()*,]\)/ \1 /g
}
' < $1 | awk "
BEGIN {
	# to allow nested #if/#else/#endif sets
	savedepth = 0

	sysnames = \"$sysnames\"
	sysprotos = \"$sysprotos\"
	sysnumhdr = \"$sysnumhdr\"
	sysarghdr = \"$sysarghdr\"
	switchname = \"$switchname\"
	namesname = \"$namesname\"
	constprefix = \"$constprefix\"

	sysdcl = \"$sysdcl\"
	syscompat_pref = \"$syscompat_pref\"
	sysent = \"$sysent\"
	infile = \"$1\"

	compatopts = \"$compatopts\"
	"'

	printf "/*\t\$OpenBSD\$\t*/\n\n" > sysdcl
	printf "/*\n * System call switch table.\n *\n" > sysdcl
	printf " * DO NOT EDIT-- this file is automatically generated.\n" > sysdcl

	ncompat = split(compatopts,compat)
	for (i = 1; i <= ncompat; i++) {
		compat_upper[i] = toupper(compat[i])

		printf "\n#ifdef %s\n", compat_upper[i] > sysent
		printf "#define %s(func) __CONCAT(%s_,func)\n", compat[i], \
		    compat[i] > sysent
		printf "#else\n" > sysent
		printf "#define %s(func) sys_nosys\n", compat[i] > sysent
		printf "#endif\n" > sysent
	}

	printf "\n#define\ts(type)\tsizeof(type)\n\n" > sysent
	printf "const struct sysent %s[] = {\n",switchname > sysent

	printf "/*\t\$OpenBSD\$\t*/\n\n" > sysnames
	printf "/*\n * System call names.\n *\n" > sysnames
	printf " * DO NOT EDIT-- this file is automatically generated.\n" > sysnames

	printf "\n/*\n * System call prototypes.\n */\n\n" > sysprotos

	printf "/*\t\$OpenBSD\$\t*/\n\n" > sysnumhdr
	printf "/*\n * System call numbers.\n *\n" > sysnumhdr
	printf " * DO NOT EDIT-- this file is automatically generated.\n" > sysnumhdr

	printf "/*\t\$OpenBSD\$\t*/\n\n" > sysarghdr
	printf "/*\n * System call argument lists.\n *\n" > sysarghdr
	printf " * DO NOT EDIT-- this file is automatically generated.\n" > sysarghdr
}
NR == 1 {
	printf " * created from%s\n */\n\n", $0 > sysdcl

	printf " * created from%s\n */\n\n", $0 > sysnames
	printf "const char *const %s[] = {\n",namesname > sysnames

	printf " * created from%s\n */\n\n", $0 > sysnumhdr

	printf " * created from%s\n */\n\n", $0 > sysarghdr
	printf "#ifdef\tsyscallarg\n" > sysarghdr
	printf "#undef\tsyscallarg\n" > sysarghdr
	printf "#endif\n\n" > sysarghdr
	printf "#define\tsyscallarg(x)\t\t\t\t\t\t\t\\\n" > sysarghdr
	printf "\tunion {\t\t\t\t\t\t\t\t\\\n" > sysarghdr
	printf "\t\tregister_t pad;\t\t\t\t\t\t\\\n" > sysarghdr
	printf "\t\tstruct { x datum; } le;\t\t\t\t\t\\\n" > sysarghdr
	printf "\t\tstruct {\t\t\t\t\t\t\\\n" > sysarghdr
	printf "\t\t\tint8_t pad[ (sizeof (register_t) < sizeof (x))\t\\\n" \
		> sysarghdr
	printf "\t\t\t\t? 0\t\t\t\t\t\\\n" > sysarghdr
	printf "\t\t\t\t: sizeof (register_t) - sizeof (x)];\t\\\n" \
		> sysarghdr
	printf "\t\t\tx datum;\t\t\t\t\t\\\n" > sysarghdr
	printf "\t\t} be;\t\t\t\t\t\t\t\\\n" > sysarghdr
	printf "\t}\n" > sysarghdr
	next
}
NF == 0 || $1 ~ /^;/ {
	next
}
$1 ~ /^#[ 	]*include/ {
	print > sysdcl
	next
}
$1 ~ /^#[ 	]*if/ {
	print > sysent
	print > sysprotos
	print > sysnames
	savesyscall[++savedepth] = syscall
	next
}
$1 ~ /^#[ 	]*else/ {
	print > sysent
	print > sysprotos
	print > sysnames
	if (savedepth <= 0) {
		printf "%s: line %d: unbalanced #else\n", \
		    infile, NR
		exit 1
	}
	syscall = savesyscall[savedepth]
	next
}
$1 ~ /^#/ {
	if ($1 ~ /^#[       ]*endif/) {
		if (savedepth <= 0) {
			printf "%s: line %d: unbalanced #endif\n", \
			    infile, NR
			exit 1
		}
		savedepth--;
	}
	print > sysent
	print > sysprotos
	print > sysnames
	next
}
syscall != $1 {
	printf "%s: line %d: syscall number out of sync at %d\n", \
	   infile, NR, syscall
	printf "line is:\n"
	print
	exit 1
}
function parserr(was, wanted) {
	printf "%s: line %d: unexpected %s (expected %s)\n", \
	    infile, NR, was, wanted
	exit 1
}
function parseline() {
	f=3			# toss number and type
	sycall_flags="0"
	if ($NF != "}") {
		funcalias=$NF
		end=NF-1
	} else {
		funcalias=""
		end=NF
	}
	if ($f == "NOLOCK") {		# syscall does not need locks
		sycall_flags = sprintf("SY_NOLOCK | %s", sycall_flags)
		f++
	}
	if ($f ~ /^[a-z0-9_]*$/) {      # allow syscall alias
		funcalias=$f
		f++
	}
	if ($f != "{")
		parserr($f, "{")
	f++
	if ($end != "}")
		parserr($end, "}")
	end--
	if ($end != ";")
		parserr($end, ";")
	end--
	if ($end != ")")
		parserr($end, ")")
	end--

	returntype = oldf = "";
	do {
		if (returntype != "" && oldf != "*")
			returntype = returntype" ";
		returntype = returntype$f;
		oldf = $f;
		f++
	} while (f < (end - 1) && $(f+1) != "(");
	if (f == (end - 1)) {
		parserr($f, "function argument definition (maybe \"(\"?)");
	}

	funcname=$f
	if (funcalias == "") {
		funcalias=funcname
		sub(/^([^_]+_)*sys_/, "", funcalias)
	}
	f++

	if ($f != "(")
		parserr($f, ")")
	f++

	argc=0;
	if (f == end) {
		if ($f != "void")
			parserr($f, "argument definition")
		isvarargs = 0;
		varargc = 0;
		return
	}

	# some system calls (open() and fcntl()) can accept a variable
	# number of arguments.  If syscalls accept a variable number of
	# arguments, they must still have arguments specified for
	# the remaining argument "positions," because of the way the
	# kernel system call argument handling works.

	isvarargs = 0;
	while (f <= end) {
		if ($f == "...") {
			f++;
			isvarargs = 1;
			varargc = argc;
			continue;
		}
		argc++
		argtype[argc]=""
		oldf=""
		while (f < end && $(f+1) != ",") {
			if (argtype[argc] != "" && oldf != "*")
				argtype[argc] = argtype[argc]" ";
			argtype[argc] = argtype[argc]$f;
			oldf = $f;
			f++
		}
		if (argtype[argc] == "")
			parserr($f, "argument definition")
		argname[argc]=$f;
		f += 2;			# skip name, and any comma
	}
	# must see another argument after varargs notice.
	if (isvarargs) {
		if (argc == varargc)
			parserr($f, "argument definition")
	} else
		varargc = argc;
	if (argc > 6) {
		printf "%s: line %d: too many syscall arguments (%d > 6)\n", \
		    infile, NR, argc
		exit 1
	}
}
function putent(nodefs, compatwrap) {
	# output syscall declaration for switch table.
	prototype = "(struct proc *, void *, register_t *)"
	if (compatwrap == "")
		printf("int\t%s%s;\n", funcname,
		    prototype) > sysprotos
	else
		printf("int\t%s_%s%s;\n", compatwrap, funcname,
		    prototype) > sysprotos

	# output syscall switch entry
#	printf("\t{ { %d", argc) > sysent
#	for (i = 1; i <= argc; i++) {
#		if (i == 5) 		# wrap the line
#			printf(",\n\t    ") > sysent
#		else
#			printf(", ") > sysent
#		printf("s(%s)", argtypenospc[i]) > sysent
#	}
	printf("\t{ %d, ", argc) > sysent
	if (argc == 0)
		printf("0") > sysent
	else if (compatwrap == "")
		printf("s(struct %s_args)", funcname) > sysent
	else
		printf("s(struct %s_%s_args)", compatwrap,
		    funcname) > sysent
	if (compatwrap == "")
		wfn = sprintf("%s", funcname);
	else
		wfn = sprintf("%s(%s)", compatwrap, funcname);
	printf(", %s,\n\t    %s },", sycall_flags, wfn) > sysent
	for (i = 0; i < (33 - length(wfn)) / 8; i++)
		printf("\t") > sysent
	if (compatwrap == "")
		printf("/* %d = %s */\n", syscall, funcalias) > sysent
	else
		printf("/* %d = %s %s */\n", syscall, compatwrap,
		    funcalias) > sysent

	# output syscall name for names table
	if (compatwrap == "")
		printf("\t\"%s\",\t\t\t/* %d = %s */\n", funcalias, syscall,
		    funcalias) > sysnames
	else
		printf("\t\"%s_%s\",\t/* %d = %s %s */\n", compatwrap,
		    funcalias, syscall, compatwrap, funcalias) > sysnames

	# output syscall number of header, if appropriate
	if (nodefs == "" || nodefs == "NOARGS") {
		# output a prototype, to be used to generate lint stubs in
		# libc.
		printf("/* syscall: \"%s\" ret: \"%s\" args:", funcalias,
		    returntype) > sysnumhdr
		for (i = 1; i <= varargc; i++)
			printf(" \"%s\"", argtype[i]) > sysnumhdr
		if (isvarargs) {
			printf(" \"...\"") > sysnumhdr
			for (i = varargc + 1; i <= argc; i++)
				printf(" \"%s\"", argtype[i]) > sysnumhdr
		}
		printf(" */\n") > sysnumhdr

		printf("#define\t%s%s\t%d\n\n", constprefix, funcalias,
		    syscall) > sysnumhdr
	} else if (nodefs != "NODEF")
		printf("\t\t\t\t/* %d is %s %s */\n\n", syscall,
		    compatwrap, funcalias) > sysnumhdr

	# output syscall argument structure, if it has arguments
	if (argc != 0 && nodefs != "NOARGS") {
		if (compatwrap == "")
			printf("\nstruct %s_args {\n", funcname) > sysarghdr
		else
			printf("\nstruct %s_%s_args {\n", compatwrap,
			    funcname) > sysarghdr
		for (i = 1; i <= argc; i++)
			printf("\tsyscallarg(%s) %s;\n", argtype[i],
			    argname[i]) > sysarghdr
		printf("};\n") > sysarghdr
	}
}
$2 == "STD" {
	parseline()
	putent("", "");
	syscall++
	next
}
$2 == "NODEF" || $2 == "NOARGS" {
	parseline()
	putent($2, "")
	syscall++
	next
}
$2 == "OBSOL" || $2 == "UNIMPL" {
	if ($2 == "OBSOL")
		comment="obsolete"
	else
		comment="unimplemented"
	for (i = 3; i <= NF; i++)
		comment=comment " " $i

	printf("\t{ 0, 0, 0,\n\t    sys_nosys },\t\t\t/* %d = %s */\n", \
	    syscall, comment) > sysent
	printf("\t\"#%d (%s)\",\t\t/* %d = %s */\n", \
	    syscall, comment, syscall, comment) > sysnames
	if ($2 != "UNIMPL")
		printf("\t\t\t\t/* %d is %s */\n", syscall, comment) > sysnumhdr
	syscall++
	next
}
{
	for (i = 1; i <= ncompat; i++) {
		if ($2 == compat_upper[i]) {
			parseline();
			putent("COMMENT", compat[i])
			syscall++
			next
		}
	}
	printf "%s: line %d: unrecognized keyword %s\n", infile, NR, $2
	exit 1
}
END {
	printf("};\n\n") > sysent
	printf("};\n") > sysnames
	printf("#define\t%sMAXSYSCALL\t%d\n", constprefix, syscall) > sysnumhdr
} '

cat $sysprotos >> $sysarghdr
cat $sysdcl $sysent > $syssw

#chmod 444 $sysnames $sysnumhdr $syssw