1#! /bin/sh - 2# $NetBSD: makesyscalls.sh,v 1.52 2001/11/12 14:57:02 lukem 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# sysnames the syscall names file 46# sysnumhdr the syscall numbers file 47# syssw the syscall switch file 48# sysarghdr the syscall argument struct definitions 49# compatopts those syscall types that are for 'compat' syscalls 50# switchname the name for the 'struct sysent' we define 51# namesname the name for the 'const char *[]' we define 52# constprefix the prefix for the system call constants 53# registertype the type for register_t 54# nsysent the size of the sysent table 55# sys_nosys [optional] name of function called for unsupported 56# syscalls, if not sys_nosys() 57# 58# NOTE THAT THIS makesyscalls.sh DOES NOT SUPPORT 'LIBCOMPAT'. 59 60# source the config file. 61sys_nosys="sys_nosys" # default is sys_nosys(), if not specified otherwise 62. ./$1 63 64# tmp files: 65sysdcl="sysent.dcl" 66sysprotos="sys.protos" 67syscompat_pref="sysent." 68sysent="sysent.switch" 69sysnamesbottom="sysnames.bottom" 70 71trap "rm $sysdcl $sysprotos $sysent $sysnamesbottom" 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 # to track already processed syscalls 120 syscallseen[0] = 0 121 122 sysnames = \"$sysnames\" 123 sysprotos = \"$sysprotos\" 124 sysnumhdr = \"$sysnumhdr\" 125 sysarghdr = \"$sysarghdr\" 126 switchname = \"$switchname\" 127 namesname = \"$namesname\" 128 constprefix = \"$constprefix\" 129 registertype = \"$registertype\" 130 if (!registertype) { 131 registertype = \"register_t\" 132 } 133 nsysent = \"$nsysent\" 134 135 sysdcl = \"$sysdcl\" 136 syscompat_pref = \"$syscompat_pref\" 137 sysent = \"$sysent\" 138 sysnamesbottom = \"$sysnamesbottom\" 139 sys_nosys = \"$sys_nosys\" 140 infile = \"$2\" 141 142 compatopts = \"$compatopts\" 143 "' 144 145 printf "/* \$NetBSD\$ */\n\n" > sysdcl 146 printf "/*\n * System call switch table.\n *\n" > sysdcl 147 printf " * DO NOT EDIT-- this file is automatically generated.\n" > sysdcl 148 149 ncompat = split(compatopts,compat) 150 for (i = 1; i <= ncompat; i++) { 151 compat_upper[i] = toupper(compat[i]) 152 153 printf "\n#ifdef %s\n", compat_upper[i] > sysent 154 printf "#define %s(func) __CONCAT(%s_,func)\n", compat[i], \ 155 compat[i] > sysent 156 printf "#else\n" > sysent 157 printf "#define %s(func) %s\n", compat[i], sys_nosys > sysent 158 printf "#endif\n" > sysent 159 } 160 161 printf "\n#define\ts(type)\tsizeof(type)\n\n" > sysent 162 printf "struct sysent %s[] = {\n",switchname > sysent 163 164 printf "/* \$NetBSD\$ */\n\n" > sysnames 165 printf "/*\n * System call names.\n *\n" > sysnames 166 printf " * DO NOT EDIT-- this file is automatically generated.\n" > sysnames 167 168 printf "\n/*\n * System call prototypes.\n */\n\n" > sysprotos 169 170 printf "/* \$NetBSD\$ */\n\n" > sysnumhdr 171 printf "/*\n * System call numbers.\n *\n" > sysnumhdr 172 printf " * DO NOT EDIT-- this file is automatically generated.\n" > sysnumhdr 173 174 printf "/* \$NetBSD\$ */\n\n" > sysarghdr 175 printf "/*\n * System call argument lists.\n *\n" > sysarghdr 176 printf " * DO NOT EDIT-- this file is automatically generated.\n" > sysarghdr 177} 178NR == 1 { 179 printf " * created from%s\n */\n\n", $0 > sysdcl 180 printf "#include <sys/cdefs.h>\n__KERNEL_RCSID(0, \"\$NetBSD\$\");\n\n" > sysdcl 181 182 printf " * created from%s\n */\n\n", $0 > sysnames 183 printf "#include <sys/cdefs.h>\n__KERNEL_RCSID(0, \"\$NetBSD\$\");\n\n" > sysnames 184 185 # System call names are included by userland (kdump(1)), so 186 # hide the include files from it. 187 printf "#if defined(_KERNEL_OPT)\n" > sysnames 188 189 printf "#endif /* _KERNEL_OPT */\n\n" > sysnamesbottom 190 printf "const char *const %s[] = {\n",namesname > sysnamesbottom 191 192 printf " * created from%s\n */\n\n", $0 > sysnumhdr 193 194 printf " * created from%s\n */\n\n", $0 > sysarghdr 195 printf "#ifndef _" constprefix "_SYSCALLARGS_H_\n" > sysarghdr 196 printf "#define _" constprefix "_SYSCALLARGS_H_\n\n" > sysarghdr 197 printf "#ifdef\tsyscallarg\n" > sysarghdr 198 printf "#undef\tsyscallarg\n" > sysarghdr 199 printf "#endif\n\n" > sysarghdr 200 printf "#define\tsyscallarg(x)\t\t\t\t\t\t\t\\\n" > sysarghdr 201 printf "\tunion {\t\t\t\t\t\t\t\t\\\n" > sysarghdr 202 printf "\t\t%s pad;\t\t\t\t\t\t\\\n", registertype > sysarghdr 203 printf "\t\tstruct { x datum; } le;\t\t\t\t\t\\\n" > sysarghdr 204 printf "\t\tstruct { /* LINTED zero array dimension */\t\t\\\n" \ 205 > sysarghdr 206 printf "\t\t\tint8_t pad[ /* CONSTCOND */\t\t\t\\\n" > sysarghdr 207 printf "\t\t\t\t(sizeof (%s) < sizeof (x))\t\\\n", \ 208 registertype > sysarghdr 209 printf "\t\t\t\t? 0\t\t\t\t\t\\\n" > sysarghdr 210 printf "\t\t\t\t: sizeof (%s) - sizeof (x)];\t\\\n", \ 211 registertype > sysarghdr 212 printf "\t\t\tx datum;\t\t\t\t\t\\\n" > sysarghdr 213 printf "\t\t} be;\t\t\t\t\t\t\t\\\n" > sysarghdr 214 printf "\t}\n" > sysarghdr 215 next 216} 217NF == 0 || $1 ~ /^;/ { 218 next 219} 220$0 ~ /^%%$/ { 221 intable = 1 222 next 223} 224$1 ~ /^#[ ]*include/ { 225 print > sysdcl 226 print > sysnames 227 next 228} 229$1 ~ /^#/ && !intable { 230 print > sysdcl 231 print > sysnames 232 next 233} 234$1 ~ /^#/ && intable { 235 if ($1 ~ /^#[ ]*if/) { 236 savedepth++ 237 savesyscall[savedepth] = syscall 238 } 239 if ($1 ~ /^#[ ]*else/) { 240 if (savedepth <= 0) { 241 printf("%s: line %d: unbalanced #else\n", \ 242 infile, NR) 243 exit 1 244 } 245 syscall = savesyscall[savedepth] 246 } 247 if ($1 ~ /^#[ ]*endif/) { 248 if (savedepth <= 0) { 249 printf("%s: line %d: unbalanced #endif\n", \ 250 infile, NR) 251 exit 1 252 } 253 savedepth-- 254 } 255 print > sysent 256 print > sysprotos 257 print > sysnamesbottom 258 next 259} 260syscall != $1 { 261 printf "%s: line %d: syscall number out of sync at %d\n", \ 262 infile, NR, syscall 263 printf "line is:\n" 264 print 265 exit 1 266} 267function parserr(was, wanted) { 268 printf "%s: line %d: unexpected %s (expected %s)\n", \ 269 infile, NR, was, wanted 270 printf "line is:\n" 271 print 272 exit 1 273} 274function parseline() { 275 f=3 # toss number and type 276 sycall_flags="0" 277 if ($NF != "}") { 278 funcalias=$NF 279 end=NF-1 280 } else { 281 funcalias="" 282 end=NF 283 } 284 if ($f == "MPSAFE") { # allow for MP-safe syscalls 285 sycall_flags = sprintf("SYCALL_MPSAFE | %s", sycall_flags) 286 f++ 287 } 288 if ($f ~ /^[a-z0-9_]*$/) { # allow syscall alias 289 funcalias=$f 290 f++ 291 } 292 if ($f != "{") 293 parserr($f, "{") 294 f++ 295 if ($end != "}") 296 parserr($end, "}") 297 end-- 298 if ($end != ";") 299 parserr($end, ";") 300 end-- 301 if ($end != ")") 302 parserr($end, ")") 303 end-- 304 305 returntype = oldf = ""; 306 do { 307 if (returntype != "" && oldf != "*") 308 returntype = returntype" "; 309 returntype = returntype$f; 310 oldf = $f; 311 f++ 312 } while (f < (end - 1) && $(f+1) != "("); 313 if (f == (end - 1)) { 314 parserr($f, "function argument definition (maybe \"(\"?)"); 315 } 316 317 funcname=$f 318 if (funcalias == "") { 319 funcalias=funcname 320 sub(/^([^_]+_)*sys_/, "", funcalias) 321 } 322 f++ 323 324 if ($f != "(") 325 parserr($f, ")") 326 f++ 327 328 argc=0; 329 if (f == end) { 330 if ($f != "void") 331 parserr($f, "argument definition") 332 isvarargs = 0; 333 varargc = 0; 334 return 335 } 336 337 # some system calls (open() and fcntl()) can accept a variable 338 # number of arguments. If syscalls accept a variable number of 339 # arguments, they must still have arguments specified for 340 # the remaining argument "positions," because of the way the 341 # kernel system call argument handling works. 342 # 343 # Indirect system calls, e.g. syscall(), are exceptions to this 344 # rule, since they are handled entirely by machine-dependent code 345 # and do not need argument structures built. 346 347 isvarargs = 0; 348 while (f <= end) { 349 if ($f == "...") { 350 f++; 351 isvarargs = 1; 352 varargc = argc; 353 continue; 354 } 355 argc++ 356 argtype[argc]="" 357 oldf="" 358 while (f < end && $(f+1) != ",") { 359 if (argtype[argc] != "" && oldf != "*") 360 argtype[argc] = argtype[argc]" "; 361 argtype[argc] = argtype[argc]$f; 362 oldf = $f; 363 f++ 364 } 365 if (argtype[argc] == "") 366 parserr($f, "argument definition") 367 argname[argc]=$f; 368 f += 2; # skip name, and any comma 369 } 370 # must see another argument after varargs notice. 371 if (isvarargs) { 372 if (argc == varargc && $2 != "INDIR") 373 parserr($f, "argument definition") 374 } else 375 varargc = argc; 376} 377function putent(nodefs, compatwrap) { 378 # output syscall declaration for switch table. INDIR functions 379 # get none, since they always have sys_nosys() for their table 380 # entries. 381 if (nodefs != "INDIR") { 382 prototype = "(struct proc *, void *, register_t *)" 383 if (compatwrap == "") 384 printf("int\t%s%s;\n", funcname, 385 prototype) > sysprotos 386 else 387 printf("int\t%s_%s%s;\n", compatwrap, funcname, 388 prototype) > sysprotos 389 } 390 391 # output syscall switch entry 392 if (nodefs == "INDIR") { 393 printf("\t{ 0, 0, %s,\n\t %s },\t\t\t/* %d = %s (indir) */\n", \ 394 sycall_flags, sys_nosys, syscall, funcalias) > sysent 395 } else { 396# printf("\t{ { %d", argc) > sysent 397# for (i = 1; i <= argc; i++) { 398# if (i == 5) # wrap the line 399# printf(",\n\t ") > sysent 400# else 401# printf(", ") > sysent 402# printf("s(%s)", argtypenospc[i]) > sysent 403# } 404 printf("\t{ %d, ", argc) > sysent 405 if (argc == 0) 406 printf("0") > sysent 407 else if (compatwrap == "") 408 printf("s(struct %s_args)", funcname) > sysent 409 else 410 printf("s(struct %s_%s_args)", compatwrap, 411 funcname) > sysent 412 if (compatwrap == "") 413 wfn = sprintf("%s", funcname); 414 else 415 wfn = sprintf("%s(%s)", compatwrap, funcname); 416 printf(", %s,\n\t %s },", sycall_flags, wfn) > sysent 417 for (i = 0; i < (33 - length(wfn)) / 8; i++) 418 printf("\t") > sysent 419 if (compatwrap == "") 420 printf("/* %d = %s */\n", syscall, funcalias) > sysent 421 else 422 printf("/* %d = %s %s */\n", syscall, compatwrap, 423 funcalias) > sysent 424 } 425 426 # output syscall name for names table 427 if (compatwrap == "") 428 printf("\t\"%s\",\t\t\t/* %d = %s */\n", funcalias, syscall, 429 funcalias) > sysnamesbottom 430 else 431 printf("\t\"%s_%s\",\t/* %d = %s %s */\n", compatwrap, 432 funcalias, syscall, compatwrap, funcalias) > sysnamesbottom 433 434 # output syscall number of header, if appropriate 435 if (syscallseen[syscall]) { 436 # nop 437 } else if (nodefs == "" || nodefs == "NOARGS" || nodefs == "INDIR") { 438 # output a prototype, to be used to generate lint stubs in 439 # libc. 440 printf("/* syscall: \"%s\" ret: \"%s\" args:", funcalias, 441 returntype) > sysnumhdr 442 for (i = 1; i <= varargc; i++) 443 printf(" \"%s\"", argtype[i]) > sysnumhdr 444 if (isvarargs) 445 printf(" \"...\"") > sysnumhdr 446 printf(" */\n") > sysnumhdr 447 448 printf("#define\t%s%s\t%d\n\n", constprefix, funcalias, 449 syscall) > sysnumhdr 450 } else if (nodefs == "COMPAT") { 451 # Just define the syscall number with a comment. These 452 # may be used by compatibility stubs in libc. 453 printf("#define\t%s%s_%s\t%d\n\n", 454 constprefix, compatwrap, funcalias, syscall) > sysnumhdr 455 } else if (nodefs != "NODEF") 456 printf("\t\t\t\t/* %d is %s %s */\n\n", syscall, 457 compatwrap, funcalias) > sysnumhdr 458 syscallseen[syscall] = 1 459 460 # output syscall argument structure, if it has arguments 461 if (argc != 0 && nodefs != "NOARGS" && nodefs != "INDIR") { 462 if (compatwrap == "") 463 printf("\nstruct %s_args {\n", funcname) > sysarghdr 464 else 465 printf("\nstruct %s_%s_args {\n", compatwrap, 466 funcname) > sysarghdr 467 for (i = 1; i <= argc; i++) 468 printf("\tsyscallarg(%s) %s;\n", argtype[i], 469 argname[i]) > sysarghdr 470 printf("};\n") > sysarghdr 471 } 472} 473$2 == "STD" { 474 parseline() 475 putent("", ""); 476 syscall++ 477 next 478} 479$2 == "NODEF" || $2 == "NOARGS" || $2 == "INDIR" { 480 parseline() 481 putent($2, "") 482 syscall++ 483 next 484} 485$2 == "OBSOL" || $2 == "UNIMPL" || $2 == "EXCL" { 486 if ($2 == "OBSOL") 487 comment="obsolete" 488 else if ($2 == "EXCL") 489 comment="excluded" 490 else 491 comment="unimplemented" 492 for (i = 3; i <= NF; i++) 493 comment=comment " " $i 494 495 printf("\t{ 0, 0, 0,\n\t %s },\t\t\t/* %d = %s */\n", \ 496 sys_nosys, syscall, comment) > sysent 497 printf("\t\"#%d (%s)\",\t\t/* %d = %s */\n", \ 498 syscall, comment, syscall, comment) > sysnamesbottom 499 if ($2 != "UNIMPL") 500 printf("\t\t\t\t/* %d is %s */\n", syscall, comment) > sysnumhdr 501 syscall++ 502 next 503} 504{ 505 for (i = 1; i <= ncompat; i++) { 506 if ($2 == compat_upper[i]) { 507 parseline(); 508 putent("COMPAT", compat[i]) 509 syscall++ 510 next 511 } 512 } 513 printf("%s: line %d: unrecognized keyword %s\n", infile, NR, $2) 514 exit 1 515} 516END { 517 maxsyscall = syscall 518 if (nsysent) { 519 if (syscall > nsysent) { 520 printf("%s: line %d: too many syscalls [%d > %d]\n", infile, NR, syscall, nsysent) 521 exit 1 522 } 523 while (syscall < nsysent) { 524 printf("\t{ 0, 0, 0,\n\t %s },\t\t\t/* %d = filler */\n", \ 525 sys_nosys, syscall) > sysent 526 syscall++ 527 } 528 } 529 printf("};\n\n") > sysent 530 printf("};\n") > sysnamesbottom 531 printf("#define\t%sMAXSYSCALL\t%d\n", constprefix, maxsyscall) > sysnumhdr 532 if (nsysent) 533 printf("#define\t%sNSYSENT\t%d\n", constprefix, nsysent) > sysnumhdr 534} ' 535 536cat $sysprotos >> $sysarghdr 537echo "#endif /* _${constprefix}_SYSCALLARGS_H_ */" >> $sysarghdr 538cat $sysdcl $sysent > $syssw 539cat $sysnamesbottom >> $sysnames 540 541#chmod 444 $sysnames $sysnumhdr $syssw 542