1#!/usr/bin/awk -f 2 3#- 4# Copyright (c) 1992, 1993 5# The Regents of the University of California. 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# 4. Neither the name of the University nor the names of its contributors 16# may be used to endorse or promote products derived from this software 17# without specific prior written permission. 18# 19# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29# SUCH DAMAGE. 30 31# 32# @(#)vnode_if.sh 8.1 (Berkeley) 6/10/93 33# $FreeBSD$ 34# 35# Script to produce VFS front-end sugar. 36# 37# usage: vnode_if.awk <srcfile> [-c | -h] 38# (where <srcfile> is currently /sys/kern/vnode_if.src) 39# 40 41function usage() 42{ 43 print "usage: vnode_if.awk <srcfile> [-c|-h|-p|-q]"; 44 exit 1; 45} 46 47function die(msg, what) 48{ 49 printf msg "\n", what > "/dev/stderr"; 50 exit 1; 51} 52 53function t_spc(type) 54{ 55 # Append a space if the type is not a pointer 56 return (type ~ /\*$/) ? type : type " "; 57} 58 59# These are just for convenience ... 60function printc(s) {print s > cfile;} 61function printh(s) {print s > hfile;} 62function printp(s) {print s > pfile;} 63function printq(s) {print s > qfile;} 64 65function add_debug_code(name, arg, pos, ind) 66{ 67 if (arg == "vpp") 68 star = "*"; 69 else 70 star = ""; 71 if (lockdata[name, arg, pos] && (lockdata[name, arg, pos] != "-")) { 72 if (arg ~ /^\*/) { 73 printc(ind"if ("substr(arg, 2)" != NULL) {"); 74 } 75 printc(ind"ASSERT_VI_UNLOCKED("star"a->a_"arg", \""uname"\");"); 76 # Add assertions for locking 77 if (lockdata[name, arg, pos] == "L") 78 printc(ind"ASSERT_VOP_LOCKED(" star "a->a_"arg", \""uname"\");"); 79 else if (lockdata[name, arg, pos] == "U") 80 printc(ind"ASSERT_VOP_UNLOCKED(" star "a->a_"arg", \""uname"\");"); 81 else if (lockdata[name, arg, pos] == "E") 82 printc(ind"ASSERT_VOP_ELOCKED(" star "a->a_"arg", \""uname"\");"); 83 else if (0) { 84 # XXX More checks! 85 } 86 if (arg ~ /^\*/) { 87 printc("ind}"); 88 } 89 } 90} 91 92function add_debug_pre(name) 93{ 94 if (lockdata[name, "pre"]) { 95 printc("#ifdef DEBUG_VFS_LOCKS"); 96 printc("\t"lockdata[name, "pre"]"(a);"); 97 printc("#endif"); 98 } 99} 100 101function add_debug_post(name) 102{ 103 if (lockdata[name, "post"]) { 104 printc("#ifdef DEBUG_VFS_LOCKS"); 105 printc("\t"lockdata[name, "post"]"(a, rc);"); 106 printc("#endif"); 107 } 108} 109 110function find_arg_with_type (type) 111{ 112 for (jj = 0; jj < numargs; jj++) { 113 if (types[jj] == type) { 114 return "VOPARG_OFFSETOF(struct " \ 115 name "_args,a_" args[jj] ")"; 116 } 117 } 118 119 return "VDESC_NO_OFFSET"; 120} 121 122BEGIN{ 123 124# Process the command line 125for (i = 1; i < ARGC; i++) { 126 arg = ARGV[i]; 127 if (arg !~ /^-[chpq]+$/ && arg !~ /\.src$/) 128 usage(); 129 if (arg ~ /^-.*c/) 130 cfile = "vnode_if.c"; 131 if (arg ~ /^-.*h/) 132 hfile = "vnode_if.h"; 133 if (arg ~ /^-.*p/) 134 pfile = "vnode_if_newproto.h"; 135 if (arg ~ /^-.*q/) 136 qfile = "vnode_if_typedef.h"; 137 if (arg ~ /\.src$/) 138 srcfile = arg; 139} 140ARGC = 1; 141 142if (!cfile && !hfile && !pfile && !qfile) 143 exit 0; 144 145if (!srcfile) 146 usage(); 147 148common_head = \ 149 "/*\n" \ 150 " * This file is produced automatically.\n" \ 151 " * Do not modify anything in here by hand.\n" \ 152 " *\n" \ 153 " * Created from $FreeBSD$\n" \ 154 " */\n" \ 155 "\n"; 156 157if (pfile) { 158 printp(common_head) 159 printp("struct vop_vector {") 160 printp("\tstruct vop_vector\t*vop_default;") 161 printp("\tvop_bypass_t\t*vop_bypass;") 162} 163 164if (qfile) { 165 printq(common_head) 166} 167 168if (hfile) { 169 printh(common_head "extern struct vnodeop_desc vop_default_desc;"); 170 printh("#include \"vnode_if_typedef.h\"") 171 printh("#include \"vnode_if_newproto.h\"") 172} 173 174if (cfile) { 175 printc(common_head \ 176 "#include <sys/param.h>\n" \ 177 "#include <sys/systm.h>\n" \ 178 "#include <sys/vnode.h>\n" \ 179 "#include <sys/systm.h>\n" \ 180 "\n" \ 181 "struct vnodeop_desc vop_default_desc = {\n" \ 182 " \"default\",\n" \ 183 " 0,\n" \ 184 " (void *)(uintptr_t)vop_panic,\n" \ 185 " NULL,\n" \ 186 " VDESC_NO_OFFSET,\n" \ 187 " VDESC_NO_OFFSET,\n" \ 188 " VDESC_NO_OFFSET,\n" \ 189 " VDESC_NO_OFFSET,\n" \ 190 " NULL,\n" \ 191 "};\n"); 192} 193 194while ((getline < srcfile) > 0) { 195 if (NF == 0) 196 continue; 197 if ($1 ~ /^#%/) { 198 if (NF != 6 || $1 != "#%" || \ 199 $2 !~ /^[a-z]+$/ || $3 !~ /^[a-z]+$/ || \ 200 $4 !~ /^.$/ || $5 !~ /^.$/ || $6 !~ /^.$/) 201 continue; 202 lockdata["vop_" $2, $3, "Entry"] = $4; 203 lockdata["vop_" $2, $3, "OK"] = $5; 204 lockdata["vop_" $2, $3, "Error"] = $6; 205 continue; 206 } 207 208 if ($1 ~ /^#!/) { 209 if (NF != 4 || $1 != "#!") 210 continue; 211 if ($3 != "pre" && $3 != "post") 212 continue; 213 lockdata["vop_" $2, $3] = $4; 214 continue; 215 } 216 if ($1 ~ /^#/) 217 continue; 218 219 # Get the function name. 220 name = $1; 221 uname = toupper(name); 222 223 # Start constructing a ktrpoint string 224 ctrstr = "\"" uname; 225 # Get the function arguments. 226 for (numargs = 0; ; ++numargs) { 227 if ((getline < srcfile) <= 0) { 228 die("Unable to read through the arguments for \"%s\"", 229 name); 230 } 231 if ($1 ~ /^\};/) 232 break; 233 234 # Delete comments, if any. 235 gsub (/\/\*.*\*\//, ""); 236 237 # Condense whitespace and delete leading/trailing space. 238 gsub(/[[:space:]]+/, " "); 239 sub(/^ /, ""); 240 sub(/ $/, ""); 241 242 # Pick off direction. 243 if ($1 != "INOUT" && $1 != "IN" && $1 != "OUT") 244 die("No IN/OUT direction for \"%s\".", $0); 245 dirs[numargs] = $1; 246 sub(/^[A-Z]* /, ""); 247 248 if ((reles[numargs] = $1) == "WILLRELE") 249 sub(/^[A-Z]* /, ""); 250 else 251 reles[numargs] = "WONTRELE"; 252 253 # kill trailing ; 254 if (sub(/;$/, "") < 1) 255 die("Missing end-of-line ; in \"%s\".", $0); 256 257 # pick off variable name 258 if ((argp = match($0, /[A-Za-z0-9_]+$/)) < 1) 259 die("Missing var name \"a_foo\" in \"%s\".", $0); 260 args[numargs] = substr($0, argp); 261 $0 = substr($0, 1, argp - 1); 262 263 # what is left must be type 264 # remove trailing space (if any) 265 sub(/ $/, ""); 266 types[numargs] = $0; 267 268 # We can do a maximum of 6 arguments to CTR* 269 if (numargs <= 6) { 270 if (numargs == 0) 271 ctrstr = ctrstr "(" args[numargs]; 272 else 273 ctrstr = ctrstr ", " args[numargs]; 274 if (types[numargs] ~ /\*/) 275 ctrstr = ctrstr " 0x%lX"; 276 else 277 ctrstr = ctrstr " %ld"; 278 } 279 } 280 if (numargs > 6) 281 ctrargs = 6; 282 else 283 ctrargs = numargs; 284 ctrstr = "\tCTR" ctrargs "(KTR_VOP,\n\t " ctrstr ")\",\n\t "; 285 ctrstr = ctrstr "a->a_" args[0]; 286 for (i = 1; i < ctrargs; ++i) 287 ctrstr = ctrstr ", a->a_" args[i]; 288 ctrstr = ctrstr ");"; 289 290 if (pfile) { 291 printp("\t"name"_t\t*"name";") 292 } 293 if (qfile) { 294 printq("struct "name"_args;") 295 printq("typedef int "name"_t(struct "name"_args *);\n") 296 } 297 298 if (hfile) { 299 # Print out the vop_F_args structure. 300 printh("struct "name"_args {\n\tstruct vop_generic_args a_gen;"); 301 for (i = 0; i < numargs; ++i) 302 printh("\t" t_spc(types[i]) "a_" args[i] ";"); 303 printh("};"); 304 printh(""); 305 306 # Print out extern declaration. 307 printh("extern struct vnodeop_desc " name "_desc;"); 308 printh(""); 309 310 # Print out function prototypes. 311 printh("int " uname "_AP(struct " name "_args *);"); 312 printh("int " uname "_APV(struct vop_vector *vop, struct " name "_args *);"); 313 printh(""); 314 printh("static __inline int " uname "("); 315 for (i = 0; i < numargs; ++i) { 316 printh("\t" t_spc(types[i]) args[i] \ 317 (i < numargs - 1 ? "," : ")")); 318 } 319 printh("{"); 320 printh("\tstruct " name "_args a;"); 321 printh(""); 322 printh("\ta.a_gen.a_desc = &" name "_desc;"); 323 for (i = 0; i < numargs; ++i) 324 printh("\ta.a_" args[i] " = " args[i] ";"); 325 printh("\treturn (" uname "_APV("args[0]"->v_op, &a));"); 326 printh("}"); 327 328 printh(""); 329 } 330 331 if (cfile) { 332 # Print out the vop_F_vp_offsets structure. This all depends 333 # on naming conventions and nothing else. 334 printc("static int " name "_vp_offsets[] = {"); 335 # as a side effect, figure out the releflags 336 releflags = ""; 337 vpnum = 0; 338 for (i = 0; i < numargs; i++) { 339 if (types[i] == "struct vnode *") { 340 printc("\tVOPARG_OFFSETOF(struct " name \ 341 "_args,a_" args[i] "),"); 342 if (reles[i] == "WILLRELE") { 343 releflags = releflags \ 344 "|VDESC_VP" vpnum "_WILLRELE"; 345 } 346 vpnum++; 347 } 348 } 349 350 sub(/^\|/, "", releflags); 351 printc("\tVDESC_NO_OFFSET"); 352 printc("};"); 353 354 # Print out function. 355 printc("\nint\n" uname "_AP(struct " name "_args *a)"); 356 printc("{"); 357 printc(""); 358 printc("\treturn(" uname "_APV(a->a_" args[0] "->v_op, a));"); 359 printc("}"); 360 printc("\nint\n" uname "_APV(struct vop_vector *vop, struct " name "_args *a)"); 361 printc("{"); 362 printc("\tint rc;"); 363 printc(""); 364 printc("\tVNASSERT(a->a_gen.a_desc == &" name "_desc, a->a_" args[0]","); 365 printc("\t (\"Wrong a_desc in " name "(%p, %p)\", a->a_" args[0]", a));"); 366 printc("\twhile(vop != NULL && \\"); 367 printc("\t vop->"name" == NULL && vop->vop_bypass == NULL)") 368 printc("\t\tvop = vop->vop_default;") 369 printc("\tVNASSERT(vop != NULL, a->a_" args[0]", (\"No "name"(%p, %p)\", a->a_" args[0]", a));") 370 for (i = 0; i < numargs; ++i) 371 add_debug_code(name, args[i], "Entry", "\t"); 372 add_debug_pre(name); 373 printc("\tif (vop->"name" != NULL)") 374 printc("\t\trc = vop->"name"(a);") 375 printc("\telse") 376 printc("\t\trc = vop->vop_bypass(&a->a_gen);") 377 printc(ctrstr); 378 printc("\tif (rc == 0) {"); 379 for (i = 0; i < numargs; ++i) 380 add_debug_code(name, args[i], "OK", "\t\t"); 381 printc("\t} else {"); 382 for (i = 0; i < numargs; ++i) 383 add_debug_code(name, args[i], "Error", "\t\t"); 384 printc("\t}"); 385 add_debug_post(name); 386 printc("\treturn (rc);"); 387 printc("}\n"); 388 389 # Print out the vnodeop_desc structure. 390 printc("struct vnodeop_desc " name "_desc = {"); 391 # printable name 392 printc("\t\"" name "\","); 393 # flags 394 vppwillrele = ""; 395 for (i = 0; i < numargs; i++) { 396 if (types[i] == "struct vnode **" && \ 397 reles[i] == "WILLRELE") { 398 vppwillrele = "|VDESC_VPP_WILLRELE"; 399 } 400 } 401 402 if (!releflags) 403 releflags = "0"; 404 printc("\t" releflags vppwillrele ","); 405 406 # function to call 407 printc("\t(void*)(uintptr_t)" uname "_AP,"); 408 # vp offsets 409 printc("\t" name "_vp_offsets,"); 410 # vpp (if any) 411 printc("\t" find_arg_with_type("struct vnode **") ","); 412 # cred (if any) 413 printc("\t" find_arg_with_type("struct ucred *") ","); 414 # thread (if any) 415 printc("\t" find_arg_with_type("struct thread *") ","); 416 # componentname 417 printc("\t" find_arg_with_type("struct componentname *") ","); 418 # transport layer information 419 printc("\tNULL,\n};\n"); 420 } 421} 422 423if (pfile) 424 printp("};") 425 426if (hfile) 427 close(hfile); 428if (cfile) 429 close(cfile); 430if (pfile) 431 close(pfile); 432close(srcfile); 433 434exit 0; 435 436} 437