1#! /bin/sh - 2# $NetBSD: makesyscalls.sh,v 1.43 2000/12/12 17:32:45 jdolecek 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# 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 'const char *[]' we define 55# constprefix the prefix for the system call constants 56# registertype the type for register_t 57# nsysent the size of the sysent table 58# 59# NOTE THAT THIS makesyscalls.sh DOES NOT SUPPORT 'LIBCOMPAT'. 60 61# tmp files: 62sysdcl="sysent.dcl" 63sysprotos="sys.protos" 64syscompat_pref="sysent." 65sysent="sysent.switch" 66sysnamesbottom="sysnames.bottom" 67 68trap "rm $sysdcl $sysprotos $sysent $sysnamesbottom" 0 69 70# Awk program (must support nawk extensions) 71# Use "awk" at Berkeley, "nawk" or "gawk" elsewhere. 72awk=${AWK:-awk} 73 74# Does this awk have a "toupper" function? (i.e. is it GNU awk) 75isgawk=`$awk 'BEGIN { print toupper("true"); exit; }' 2>/dev/null` 76 77# If this awk does not define "toupper" then define our own. 78if [ "$isgawk" = TRUE ] ; then 79 # GNU awk provides it. 80 toupper= 81else 82 # Provide our own toupper() 83 toupper=' 84function toupper(str) { 85 _toupper_cmd = "echo "str" |tr a-z A-Z" 86 _toupper_cmd | getline _toupper_str; 87 close(_toupper_cmd); 88 return _toupper_str; 89}' 90fi 91 92# before handing it off to awk, make a few adjustments: 93# (1) insert spaces around {, }, (, ), *, and commas. 94# (2) get rid of any and all dollar signs (so that rcs id use safe) 95# 96# The awk script will deal with blank lines and lines that 97# start with the comment character (';'). 98 99sed -e ' 100s/\$//g 101:join 102 /\\$/{a\ 103 104 N 105 s/\\\n// 106 b join 107 } 1082,${ 109 /^#/!s/\([{}()*,]\)/ \1 /g 110} 111' < $2 | $awk " 112$toupper 113BEGIN { 114 # to allow nested #if/#else/#endif sets 115 savedepth = 0 116 117 sysnames = \"$sysnames\" 118 sysprotos = \"$sysprotos\" 119 sysnumhdr = \"$sysnumhdr\" 120 sysarghdr = \"$sysarghdr\" 121 switchname = \"$switchname\" 122 namesname = \"$namesname\" 123 constprefix = \"$constprefix\" 124 registertype = \"$registertype\" 125 if (!registertype) { 126 registertype = \"register_t\" 127 } 128 nsysent = \"$nsysent\" 129 130 sysdcl = \"$sysdcl\" 131 syscompat_pref = \"$syscompat_pref\" 132 sysent = \"$sysent\" 133 sysnamesbottom = \"$sysnamesbottom\" 134 infile = \"$2\" 135 136 compatopts = \"$compatopts\" 137 "' 138 139 printf "/* \$NetBSD\$ */\n\n" > sysdcl 140 printf "/*\n * System call switch table.\n *\n" > sysdcl 141 printf " * DO NOT EDIT-- this file is automatically generated.\n" > sysdcl 142 143 ncompat = split(compatopts,compat) 144 for (i = 1; i <= ncompat; i++) { 145 compat_upper[i] = toupper(compat[i]) 146 147 printf "\n#ifdef %s\n", compat_upper[i] > sysent 148 printf "#define %s(func) __CONCAT(%s_,func)\n", compat[i], \ 149 compat[i] > sysent 150 printf "#else\n" > sysent 151 printf "#define %s(func) sys_nosys\n", compat[i] > sysent 152 printf "#endif\n" > sysent 153 } 154 155 printf "\n#define\ts(type)\tsizeof(type)\n\n" > sysent 156 printf "struct sysent %s[] = {\n",switchname > sysent 157 158 printf "/* \$NetBSD\$ */\n\n" > sysnames 159 printf "/*\n * System call names.\n *\n" > sysnames 160 printf " * DO NOT EDIT-- this file is automatically generated.\n" > sysnames 161 162 printf "\n/*\n * System call prototypes.\n */\n\n" > sysprotos 163 164 printf "/* \$NetBSD\$ */\n\n" > sysnumhdr 165 printf "/*\n * System call numbers.\n *\n" > sysnumhdr 166 printf " * DO NOT EDIT-- this file is automatically generated.\n" > sysnumhdr 167 168 printf "/* \$NetBSD\$ */\n\n" > sysarghdr 169 printf "/*\n * System call argument lists.\n *\n" > sysarghdr 170 printf " * DO NOT EDIT-- this file is automatically generated.\n" > sysarghdr 171} 172NR == 1 { 173 printf " * created from%s\n */\n\n", $0 > sysdcl 174 175 printf " * created from%s\n */\n\n", $0 > sysnames 176 177 # System call names are included by userland (kdump(1)), so 178 # hide the include files from it. 179 printf "#if defined(_KERNEL) && !defined(_LKM)\n" > sysnames 180 181 printf "#endif /* _KERNEL && ! _LKM */\n\n" > sysnamesbottom 182 printf "const char *const %s[] = {\n",namesname > sysnamesbottom 183 184 printf " * created from%s\n */\n\n", $0 > sysnumhdr 185 186 printf " * created from%s\n */\n\n", $0 > sysarghdr 187 printf "#ifndef _" constprefix "_SYSCALLARGS_H_\n" > sysarghdr 188 printf "#define _" constprefix "_SYSCALLARGS_H_\n\n" > sysarghdr 189 printf "#ifdef\tsyscallarg\n" > sysarghdr 190 printf "#undef\tsyscallarg\n" > sysarghdr 191 printf "#endif\n\n" > sysarghdr 192 printf "#define\tsyscallarg(x)\t\t\t\t\t\t\t\\\n" > sysarghdr 193 printf "\tunion {\t\t\t\t\t\t\t\t\\\n" > sysarghdr 194 printf "\t\t%s pad;\t\t\t\t\t\t\\\n", registertype > sysarghdr 195 printf "\t\tstruct { x datum; } le;\t\t\t\t\t\\\n" > sysarghdr 196 printf "\t\tstruct {\t\t\t\t\t\t\\\n" > sysarghdr 197 printf "\t\t\tint8_t pad[ (sizeof (%s) < sizeof (x))\t\\\n", \ 198 registertype > sysarghdr 199 printf "\t\t\t\t? 0\t\t\t\t\t\\\n" > sysarghdr 200 printf "\t\t\t\t: sizeof (%s) - sizeof (x)];\t\\\n", \ 201 registertype > sysarghdr 202 printf "\t\t\tx datum;\t\t\t\t\t\\\n" > sysarghdr 203 printf "\t\t} be;\t\t\t\t\t\t\t\\\n" > sysarghdr 204 printf "\t}\n" > sysarghdr 205 next 206} 207NF == 0 || $1 ~ /^;/ { 208 next 209} 210$0 ~ /^%%$/ { 211 intable = 1 212 next 213} 214$1 ~ /^#[ ]*include/ { 215 print > sysdcl 216 print > sysnames 217 next 218} 219$1 ~ /^#/ && !intable { 220 print > sysdcl 221 print > sysnames 222 next 223} 224$1 ~ /^#/ && intable { 225 if ($1 ~ /^#[ ]*if/) { 226 savedepth++ 227 savesyscall[savedepth] = syscall 228 } 229 if ($1 ~ /^#[ ]*else/) { 230 if (savedepth <= 0) { 231 printf("%s: line %d: unbalanced #else\n", \ 232 infile, NR) 233 exit 1 234 } 235 syscall = savesyscall[savedepth] 236 } 237 if ($1 ~ /^#[ ]*endif/) { 238 if (savedepth <= 0) { 239 printf("%s: line %d: unbalanced #endif\n", \ 240 infile, NR) 241 exit 1 242 } 243 savedepth-- 244 } 245 print > sysent 246 print > sysprotos 247 print > sysnamesbottom 248 next 249} 250syscall != $1 { 251 printf "%s: line %d: syscall number out of sync at %d\n", \ 252 infile, NR, syscall 253 printf "line is:\n" 254 print 255 exit 1 256} 257function parserr(was, wanted) { 258 printf "%s: line %d: unexpected %s (expected %s)\n", \ 259 infile, NR, was, wanted 260 printf "line is:\n" 261 print 262 exit 1 263} 264function parseline() { 265 f=3 # toss number and type 266 if ($NF != "}") { 267 funcalias=$NF 268 end=NF-1 269 } else { 270 funcalias="" 271 end=NF 272 } 273 if ($f ~ /^[a-z0-9_]*$/) { # allow syscall alias 274 funcalias=$f 275 f++ 276 } 277 if ($f != "{") 278 parserr($f, "{") 279 f++ 280 if ($end != "}") 281 parserr($end, "}") 282 end-- 283 if ($end != ";") 284 parserr($end, ";") 285 end-- 286 if ($end != ")") 287 parserr($end, ")") 288 end-- 289 290 returntype = oldf = ""; 291 do { 292 if (returntype != "" && oldf != "*") 293 returntype = returntype" "; 294 returntype = returntype$f; 295 oldf = $f; 296 f++ 297 } while (f < (end - 1) && $(f+1) != "("); 298 if (f == (end - 1)) { 299 parserr($f, "function argument definition (maybe \"(\"?)"); 300 } 301 302 funcname=$f 303 if (funcalias == "") { 304 funcalias=funcname 305 sub(/^([^_]+_)*sys_/, "", funcalias) 306 } 307 f++ 308 309 if ($f != "(") 310 parserr($f, ")") 311 f++ 312 313 argc=0; 314 if (f == end) { 315 if ($f != "void") 316 parserr($f, "argument definition") 317 isvarargs = 0; 318 varargc = 0; 319 return 320 } 321 322 # some system calls (open() and fcntl()) can accept a variable 323 # number of arguments. If syscalls accept a variable number of 324 # arguments, they must still have arguments specified for 325 # the remaining argument "positions," because of the way the 326 # kernel system call argument handling works. 327 # 328 # Indirect system calls, e.g. syscall(), are exceptions to this 329 # rule, since they are handled entirely by machine-dependent code 330 # and do not need argument structures built. 331 332 isvarargs = 0; 333 while (f <= end) { 334 if ($f == "...") { 335 f++; 336 isvarargs = 1; 337 varargc = argc; 338 continue; 339 } 340 argc++ 341 argtype[argc]="" 342 oldf="" 343 while (f < end && $(f+1) != ",") { 344 if (argtype[argc] != "" && oldf != "*") 345 argtype[argc] = argtype[argc]" "; 346 argtype[argc] = argtype[argc]$f; 347 oldf = $f; 348 f++ 349 } 350 if (argtype[argc] == "") 351 parserr($f, "argument definition") 352 argname[argc]=$f; 353 f += 2; # skip name, and any comma 354 } 355 # must see another argument after varargs notice. 356 if (isvarargs) { 357 if (argc == varargc && $2 != "INDIR") 358 parserr($f, "argument definition") 359 } else 360 varargc = argc; 361} 362function putent(nodefs, compatwrap) { 363 # output syscall declaration for switch table. INDIR functions 364 # get none, since they always have sys_nosys() for their table 365 # entries. 366 if (nodefs != "INDIR") { 367 prototype = "(struct proc *, void *, register_t *)" 368 if (compatwrap == "") 369 printf("int\t%s%s;\n", funcname, 370 prototype) > sysprotos 371 else 372 printf("int\t%s_%s%s;\n", compatwrap, funcname, 373 prototype) > sysprotos 374 } 375 376 # output syscall switch entry 377 if (nodefs == "INDIR") { 378 printf("\t{ 0, 0,\n\t sys_nosys },\t\t\t/* %d = %s (indir) */\n", \ 379 syscall, funcalias) > sysent 380 } else { 381# printf("\t{ { %d", argc) > sysent 382# for (i = 1; i <= argc; i++) { 383# if (i == 5) # wrap the line 384# printf(",\n\t ") > sysent 385# else 386# printf(", ") > sysent 387# printf("s(%s)", argtypenospc[i]) > sysent 388# } 389 printf("\t{ %d, ", argc) > sysent 390 if (argc == 0) 391 printf("0") > sysent 392 else if (compatwrap == "") 393 printf("s(struct %s_args)", funcname) > sysent 394 else 395 printf("s(struct %s_%s_args)", compatwrap, 396 funcname) > sysent 397 if (compatwrap == "") 398 wfn = sprintf("%s", funcname); 399 else 400 wfn = sprintf("%s(%s)", compatwrap, funcname); 401 printf(",\n\t %s },", wfn) > sysent 402 for (i = 0; i < (33 - length(wfn)) / 8; i++) 403 printf("\t") > sysent 404 if (compatwrap == "") 405 printf("/* %d = %s */\n", syscall, funcalias) > sysent 406 else 407 printf("/* %d = %s %s */\n", syscall, compatwrap, 408 funcalias) > sysent 409 } 410 411 # output syscall name for names table 412 if (compatwrap == "") 413 printf("\t\"%s\",\t\t\t/* %d = %s */\n", funcalias, syscall, 414 funcalias) > sysnamesbottom 415 else 416 printf("\t\"%s_%s\",\t/* %d = %s %s */\n", compatwrap, 417 funcalias, syscall, compatwrap, funcalias) > sysnamesbottom 418 419 # output syscall number of header, if appropriate 420 if (nodefs == "" || nodefs == "NOARGS" || nodefs == "INDIR") { 421 # output a prototype, to be used to generate lint stubs in 422 # libc. 423 printf("/* syscall: \"%s\" ret: \"%s\" args:", funcalias, 424 returntype) > sysnumhdr 425 for (i = 1; i <= varargc; i++) 426 printf(" \"%s\"", argtype[i]) > sysnumhdr 427 if (isvarargs) 428 printf(" \"...\"") > sysnumhdr 429 printf(" */\n") > sysnumhdr 430 431 printf("#define\t%s%s\t%d\n\n", constprefix, funcalias, 432 syscall) > sysnumhdr 433 } else if (nodefs == "COMPAT") { 434 # Just define the syscall number with a comment. These 435 # may be used by compatibility stubs in libc. 436 printf("#define\t%s%s_%s\t%d\n\n", 437 constprefix, compatwrap, funcalias, syscall) > sysnumhdr 438 } else if (nodefs != "NODEF") 439 printf("\t\t\t\t/* %d is %s %s */\n\n", syscall, 440 compatwrap, funcalias) > sysnumhdr 441 442 # output syscall argument structure, if it has arguments 443 if (argc != 0 && nodefs != "NOARGS" && nodefs != "INDIR") { 444 if (compatwrap == "") 445 printf("\nstruct %s_args {\n", funcname) > sysarghdr 446 else 447 printf("\nstruct %s_%s_args {\n", compatwrap, 448 funcname) > sysarghdr 449 for (i = 1; i <= argc; i++) 450 printf("\tsyscallarg(%s) %s;\n", argtype[i], 451 argname[i]) > sysarghdr 452 printf("};\n") > sysarghdr 453 } 454} 455$2 == "STD" { 456 parseline() 457 putent("", ""); 458 syscall++ 459 next 460} 461$2 == "NODEF" || $2 == "NOARGS" || $2 == "INDIR" { 462 parseline() 463 putent($2, "") 464 syscall++ 465 next 466} 467$2 == "OBSOL" || $2 == "UNIMPL" || $2 == "EXCL" { 468 if ($2 == "OBSOL") 469 comment="obsolete" 470 else if ($2 == "EXCL") 471 comment="excluded" 472 else 473 comment="unimplemented" 474 for (i = 3; i <= NF; i++) 475 comment=comment " " $i 476 477 printf("\t{ 0, 0,\n\t sys_nosys },\t\t\t/* %d = %s */\n", \ 478 syscall, comment) > sysent 479 printf("\t\"#%d (%s)\",\t\t/* %d = %s */\n", \ 480 syscall, comment, syscall, comment) > sysnamesbottom 481 if ($2 != "UNIMPL") 482 printf("\t\t\t\t/* %d is %s */\n", syscall, comment) > sysnumhdr 483 syscall++ 484 next 485} 486{ 487 for (i = 1; i <= ncompat; i++) { 488 if ($2 == compat_upper[i]) { 489 parseline(); 490 putent("COMPAT", compat[i]) 491 syscall++ 492 next 493 } 494 } 495 printf("%s: line %d: unrecognized keyword %s\n", infile, NR, $2) 496 exit 1 497} 498END { 499 maxsyscall = syscall 500 if (nsysent) { 501 if (syscall > nsysent) { 502 printf("%s: line %d: too many syscalls\n", infile, NR) 503 exit 1 504 } 505 while (syscall < nsysent) { 506 printf("\t{ 0, 0,\n\t sys_nosys },\t\t\t/* %d = filler */\n", \ 507 syscall) > sysent 508 syscall++ 509 } 510 } 511 printf("};\n\n") > sysent 512 printf("};\n") > sysnamesbottom 513 printf("#define\t%sMAXSYSCALL\t%d\n", constprefix, maxsyscall) > sysnumhdr 514 if (nsysent) 515 printf("#define\t%sNSYSENT\t%d\n", constprefix, nsysent) > sysnumhdr 516} ' 517 518cat $sysprotos >> $sysarghdr 519echo "#endif /* _${constprefix}_SYSCALLARGS_H_ */" >> $sysarghdr 520cat $sysdcl $sysent > $syssw 521cat $sysnamesbottom >> $sysnames 522 523#chmod 444 $sysnames $sysnumhdr $syssw 524