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