vnode_if.sh revision 1.37
1#!/bin/sh - 2copyright="\ 3/* 4 * Copyright (c) 1992, 1993, 1994, 1995 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 * 3. 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" 32SCRIPT_ID='$NetBSD: vnode_if.sh,v 1.37 2005/02/26 21:40:45 perry Exp $' 33 34# Script to produce VFS front-end sugar. 35# 36# usage: vnode_if.sh srcfile 37# (where srcfile is currently /sys/kern/vnode_if.src) 38# 39 40if [ $# -ne 1 ] ; then 41 echo 'usage: vnode_if.sh srcfile' 42 exit 1 43fi 44 45# Name and revision of the source file. 46src=$1 47SRC_ID=`head -1 $src | sed -e 's/.*\$\(.*\)\$.*/\1/'` 48 49# Names of the created files. 50out_c=vnode_if.c 51out_h=../sys/vnode_if.h 52 53# Awk program (must support nawk extensions) 54# Use "awk" at Berkeley, "nawk" or "gawk" elsewhere. 55awk=${AWK:-awk} 56 57# Does this awk have a "toupper" function? (i.e. is it GNU awk) 58isgawk=`$awk 'BEGIN { print toupper("true"); exit; }' 2>/dev/null` 59 60# If this awk does not define "toupper" then define our own. 61if [ "$isgawk" = TRUE ] ; then 62 # GNU awk provides it. 63 toupper= 64else 65 # Provide our own toupper() 66 toupper=' 67function toupper(str) { 68 _toupper_cmd = "echo "str" |tr a-z A-Z" 69 _toupper_cmd | getline _toupper_str; 70 close(_toupper_cmd); 71 return _toupper_str; 72}' 73fi 74 75# 76# This is the common part of all awk programs that read $src 77# This parses the input for one function into the arrays: 78# argdir, argtype, argname, willrele 79# and calls "doit()" to generate output for the function. 80# 81# Input to this parser is pre-processed slightly by sed 82# so this awk parser doesn't have to work so hard. The 83# changes done by the sed pre-processing step are: 84# insert a space beween * and pointer name 85# replace semicolons with spaces 86# 87sed_prep='s:\*\([^\*/]\):\* \1:g 88s/;/ /' 89awk_parser=' 90# Comment line 91/^#/ { next; } 92# First line of description 93/^vop_/ { 94 name=$1; 95 argc=0; 96 next; 97} 98# Last line of description 99/^}/ { 100 doit(); 101 next; 102} 103# Middle lines of description 104{ 105 argdir[argc] = $1; i=2; 106 107 if ($2 == "LOCKED=YES") { 108 lockstate[argc] = 1; 109 i++; 110 } else if ($2 == "LOCKED=NO") { 111 lockstate[argc] = 0; 112 i++; 113 } else 114 lockstate[argc] = -1; 115 116 if ($2 == "WILLRELE" || 117 $3 == "WILLRELE") { 118 willrele[argc] = 1; 119 i++; 120 } else if ($2 == "WILLUNLOCK" || 121 $3 == "WILLUNLOCK") { 122 willrele[argc] = 2; 123 i++; 124 } else if ($2 == "WILLPUT" || 125 $3 == "WILLPUT") { 126 willrele[argc] = 3; 127 i++; 128 } else 129 willrele[argc] = 0; 130 argtype[argc] = $i; i++; 131 while (i < NF) { 132 argtype[argc] = argtype[argc]" "$i; 133 i++; 134 } 135 argname[argc] = $i; 136 argc++; 137 next; 138} 139' 140 141# This is put before the copyright on each generated file. 142warning="\ 143/* @NetBSD@ */ 144 145/* 146 * Warning: DO NOT EDIT! This file is automatically generated! 147 * (Modifications made here may easily be lost!) 148 * 149 * Created from the file: 150 * ${SRC_ID} 151 * by the script: 152 * ${SCRIPT_ID} 153 */ 154" 155 156# This is to satisfy McKusick (get rid of evil spaces 8^) 157anal_retentive='s:\([^/]\*\) :\1:g' 158 159# 160# Redirect stdout to the H file. 161# 162echo "$0: Creating $out_h" 1>&2 163exec > $out_h 164 165# Begin stuff 166echo -n "$warning" | sed -e 's/\$//g;s/@/\$/g' 167echo "" 168echo -n "$copyright" 169echo '' 170echo '#ifndef _SYS_VNODE_IF_H_' 171echo '#define _SYS_VNODE_IF_H_' 172echo '' 173echo '#ifdef _KERNEL' 174echo '#if defined(_LKM) || defined(LKM)' 175echo '/* LKMs always use non-inlined vnode ops. */' 176echo '#define VNODE_OP_NOINLINE' 177echo '#else' 178echo '#include "opt_vnode_op_noinline.h"' 179echo '#endif /* _LKM || LKM */' 180echo '#ifdef _KERNEL_OPT' 181echo '#include "opt_vnode_lockdebug.h"' 182echo '#endif /* _KERNEL_OPT */' 183echo '#endif /* _KERNEL */' 184echo ' 185extern const struct vnodeop_desc vop_default_desc; 186' 187 188# Body stuff 189# This awk program needs toupper() so define it if necessary. 190sed -e "$sed_prep" $src | $awk "$toupper"' 191function doit() { 192 # Declare arg struct, descriptor. 193 printf("\nstruct %s_args {\n", name); 194 printf("\tconst struct vnodeop_desc * a_desc;\n"); 195 for (i=0; i<argc; i++) { 196 printf("\t%s a_%s;\n", argtype[i], argname[i]); 197 } 198 printf("};\n"); 199 printf("extern const struct vnodeop_desc %s_desc;\n", name); 200 # Prototype it. 201 printf("#ifndef VNODE_OP_NOINLINE\n"); 202 printf("static __inline\n"); 203 printf("#endif\n"); 204 protoarg = sprintf("int %s(", toupper(name)); 205 protolen = length(protoarg); 206 printf("%s", protoarg); 207 for (i=0; i<argc; i++) { 208 protoarg = sprintf("%s", argtype[i]); 209 if (i < (argc-1)) protoarg = (protoarg ", "); 210 arglen = length(protoarg); 211 if ((protolen + arglen) > 77) { 212 protoarg = ("\n " protoarg); 213 arglen += 4; 214 protolen = 0; 215 } 216 printf("%s", protoarg); 217 protolen += arglen; 218 } 219 printf(")\n"); 220 printf("#ifndef VNODE_OP_NOINLINE\n"); 221 printf("__attribute__((__unused__))\n"); 222 printf("#endif\n"); 223 printf(";\n"); 224 # Define inline function. 225 printf("#ifndef VNODE_OP_NOINLINE\n"); 226 printf("static __inline int %s(", toupper(name)); 227 for (i=0; i<argc; i++) { 228 printf("%s", argname[i]); 229 if (i < (argc-1)) printf(", "); 230 } 231 printf(")\n"); 232 for (i=0; i<argc; i++) { 233 printf("\t%s %s;\n", argtype[i], argname[i]); 234 } 235 printf("{\n\tstruct %s_args a;\n", name); 236 printf("#ifdef VNODE_LOCKDEBUG\n"); 237 for (i=0; i<argc; i++) { 238 if (lockstate[i] != -1) 239 printf("\tint islocked_%s;\n", argname[i]); 240 } 241 printf("#endif\n"); 242 printf("\ta.a_desc = VDESC(%s);\n", name); 243 for (i=0; i<argc; i++) { 244 printf("\ta.a_%s = %s;\n", argname[i], argname[i]); 245 if (lockstate[i] != -1) { 246 printf("#ifdef VNODE_LOCKDEBUG\n"); 247 printf("\tislocked_%s = (%s->v_flag & VLOCKSWORK) ? (VOP_ISLOCKED(%s) == LK_EXCLUSIVE) : %d;\n", 248 argname[i], argname[i], argname[i], lockstate[i]); 249 printf("\tif (islocked_%s != %d)\n", argname[i], 250 lockstate[i]); 251 printf("\t\tpanic(\"%s: %s: locked %%d, expected %%d\", islocked_%s, %d);\n", name, argname[i], argname[i], lockstate[i]); 252 printf("#endif\n"); 253 } 254 } 255 printf("\treturn (VCALL(%s%s, VOFFSET(%s), &a));\n}\n", 256 argname[0], arg0special, name); 257 printf("#endif\n"); 258 vops++; 259} 260BEGIN { 261 arg0special=""; 262 vops = 1; # start at 1, to count the 'default' op 263} 264END { 265 printf("\n/* Special cases: */\n#include <sys/buf.h>\n"); 266 argc=1; 267 argtype[0]="struct buf *"; 268 argname[0]="bp"; 269 lockstate[0] = -1; 270 arg0special="->b_vp"; 271 name="vop_bwrite"; 272 doit(); 273 274 printf("\n#define VNODE_OPS_COUNT\t%d\n", vops); 275} 276'"$awk_parser" | sed -e "$anal_retentive" 277 278# End stuff 279echo ' 280/* End of special cases. */' 281echo '' 282echo '#endif /* !_SYS_VNODE_IF_H_ */' 283 284# 285# Redirect stdout to the C file. 286# 287echo "$0: Creating $out_c" 1>&2 288exec > $out_c 289 290# Begin stuff 291echo -n "$warning" | sed -e 's/\$//g;s/@/\$/g' 292echo "" 293echo -n "$copyright" 294echo " 295#include <sys/cdefs.h> 296__KERNEL_RCSID(0, \"\$NetBSD\$\"); 297" 298 299echo ' 300/* 301 * If we have LKM support, always include the non-inline versions for 302 * LKMs. Otherwise, do it based on the option. 303 */ 304#ifdef LKM 305#define VNODE_OP_NOINLINE 306#else 307#include "opt_vnode_op_noinline.h" 308#endif 309#include "opt_vnode_lockdebug.h"' 310echo ' 311#include <sys/param.h> 312#include <sys/mount.h> 313#include <sys/buf.h> 314#include <sys/vnode.h> 315 316const struct vnodeop_desc vop_default_desc = { 317 0, 318 "default", 319 0, 320 NULL, 321 VDESC_NO_OFFSET, 322 VDESC_NO_OFFSET, 323 VDESC_NO_OFFSET, 324 VDESC_NO_OFFSET, 325 NULL, 326}; 327' 328 329# Body stuff 330sed -e "$sed_prep" $src | $awk ' 331function do_offset(typematch) { 332 for (i=0; i<argc; i++) { 333 if (argtype[i] == typematch) { 334 printf("\tVOPARG_OFFSETOF(struct %s_args, a_%s),\n", 335 name, argname[i]); 336 return i; 337 }; 338 }; 339 print "\tVDESC_NO_OFFSET,"; 340 return -1; 341} 342 343function doit() { 344 # Define offsets array 345 printf("\nconst int %s_vp_offsets[] = {\n", name); 346 for (i=0; i<argc; i++) { 347 if (argtype[i] == "struct vnode *") { 348 printf ("\tVOPARG_OFFSETOF(struct %s_args,a_%s),\n", 349 name, argname[i]); 350 } 351 } 352 print "\tVDESC_NO_OFFSET"; 353 print "};"; 354 # Define F_desc 355 printf("const struct vnodeop_desc %s_desc = {\n", name); 356 # offset 357 printf ("\t%d,\n", vop_offset++); 358 # printable name 359 printf ("\t\"%s\",\n", name); 360 # flags 361 printf("\t0"); 362 vpnum = 0; 363 for (i=0; i<argc; i++) { 364 if (willrele[i]) { 365 if (willrele[i] == 2) { 366 word = "UNLOCK"; 367 } else if (willrele[i] == 3) { 368 word = "PUT"; 369 } else { 370 word = "RELE"; 371 } 372 if (argdir[i] ~ /OUT/) { 373 printf(" | VDESC_VPP_WILL%s", word); 374 } else { 375 printf(" | VDESC_VP%s_WILL%s", vpnum, word); 376 }; 377 vpnum++; 378 } 379 } 380 print ","; 381 # vp offsets 382 printf ("\t%s_vp_offsets,\n", name); 383 # vpp (if any) 384 do_offset("struct vnode **"); 385 # cred (if any) 386 do_offset("struct ucred *"); 387 # proc (if any) 388 do_offset("struct proc *"); 389 # componentname 390 do_offset("struct componentname *"); 391 # transport layer information 392 printf ("\tNULL,\n};\n"); 393 394 # Define function. 395 printf("#ifdef VNODE_OP_NOINLINE\n"); 396 printf("int\n%s(", toupper(name)); 397 for (i=0; i<argc; i++) { 398 printf("%s", argname[i]); 399 if (i < (argc-1)) printf(", "); 400 } 401 printf(")\n"); 402 for (i=0; i<argc; i++) { 403 printf("\t%s %s;\n", argtype[i], argname[i]); 404 } 405 printf("{\n\tstruct %s_args a;\n", name); 406 printf("#ifdef VNODE_LOCKDEBUG\n"); 407 for (i=0; i<argc; i++) { 408 if (lockstate[i] != -1) 409 printf("\tint islocked_%s;\n", argname[i]); 410 } 411 printf("#endif\n"); 412 printf("\ta.a_desc = VDESC(%s);\n", name); 413 for (i=0; i<argc; i++) { 414 printf("\ta.a_%s = %s;\n", argname[i], argname[i]); 415 if (lockstate[i] != -1) { 416 printf("#ifdef VNODE_LOCKDEBUG\n"); 417 printf("\tislocked_%s = (%s->v_flag & VLOCKSWORK) ? (VOP_ISLOCKED(%s) == LK_EXCLUSIVE) : %d;\n", 418 argname[i], argname[i], argname[i], lockstate[i]); 419 printf("\tif (islocked_%s != %d)\n", argname[i], 420 lockstate[i]); 421 printf("\t\tpanic(\"%s: %s: locked %%d, expected %%d\", islocked_%s, %d);\n", name, argname[i], argname[i], lockstate[i]); 422 printf("#endif\n"); 423 } 424 } 425 printf("\treturn (VCALL(%s%s, VOFFSET(%s), &a));\n}\n", 426 argname[0], arg0special, name); 427 printf("#endif\n"); 428} 429BEGIN { 430 printf("\n/* Special cases: */\n"); 431 # start from 1 (vop_default is at 0) 432 vop_offset=1; 433 argc=1; 434 argdir[0]="IN"; 435 argtype[0]="struct buf *"; 436 argname[0]="bp"; 437 lockstate[0] = -1; 438 arg0special="->b_vp"; 439 willrele[0]=0; 440 name="vop_bwrite"; 441 doit(); 442 printf("\n/* End of special cases */\n"); 443 444 arg0special=""; 445} 446'"$awk_parser" | sed -e "$anal_retentive" 447 448# End stuff 449echo ' 450/* End of special cases. */' 451 452# Add the vfs_op_descs array to the C file. 453# Begin stuff 454echo ' 455const struct vnodeop_desc * const vfs_op_descs[] = { 456 &vop_default_desc, /* MUST BE FIRST */ 457 &vop_bwrite_desc, /* XXX: SPECIAL CASE */ 458' 459 460# Body stuff 461sed -e "$sed_prep" $src | $awk ' 462function doit() { 463 printf("\t&%s_desc,\n", name); 464} 465'"$awk_parser" 466 467# End stuff 468echo ' NULL 469}; 470' 471 472exit 0 473 474# Local Variables: 475# tab-width: 4 476# End: 477