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