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.47 2007/11/26 19:02:11 pooka 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 willmake=-1; 97 next; 98} 99# Last line of description 100/^}/ { 101 doit(); 102 next; 103} 104# Middle lines of description 105{ 106 argdir[argc] = $1; i=2; 107 108 if ($2 == "LOCKED=YES") { 109 lockstate[argc] = 1; 110 i++; 111 } else if ($2 == "LOCKED=NO") { 112 lockstate[argc] = 0; 113 i++; 114 } else 115 lockstate[argc] = -1; 116 117 if ($2 == "WILLRELE" || 118 $3 == "WILLRELE") { 119 willrele[argc] = 1; 120 i++; 121 } else if ($2 == "WILLUNLOCK" || 122 $3 == "WILLUNLOCK") { 123 willrele[argc] = 2; 124 i++; 125 } else if ($2 == "WILLPUT" || 126 $3 == "WILLPUT") { 127 willrele[argc] = 3; 128 i++; 129 } else 130 willrele[argc] = 0; 131 132 if ($2 == "WILLMAKE") { 133 willmake=argc; 134 i++; 135 } 136 137 argtype[argc] = $i; i++; 138 while (i < NF) { 139 argtype[argc] = argtype[argc]" "$i; 140 i++; 141 } 142 argname[argc] = $i; 143 argc++; 144 next; 145} 146' 147 148# This is put before the copyright on each generated file. 149warning="\ 150/* @NetBSD@ */ 151 152/* 153 * Warning: DO NOT EDIT! This file is automatically generated! 154 * (Modifications made here may easily be lost!) 155 * 156 * Created from the file: 157 * ${SRC_ID} 158 * by the script: 159 * ${SCRIPT_ID} 160 */ 161" 162 163# This is to satisfy McKusick (get rid of evil spaces 8^) 164anal_retentive='s:\([^/]\*\) :\1:g' 165 166# 167# Redirect stdout to the H file. 168# 169echo "$0: Creating $out_h" 1>&2 170exec > $out_h 171 172# Begin stuff 173echo -n "$warning" | sed -e 's/\$//g;s/@/\$/g;s/ $//' 174echo "" 175echo -n "$copyright" 176echo '' 177echo '#ifndef _SYS_VNODE_IF_H_' 178echo '#define _SYS_VNODE_IF_H_' 179echo '' 180echo '#ifdef _KERNEL_OPT' 181echo '#include "opt_vnode_lockdebug.h"' 182echo '#endif /* _KERNEL_OPT */' 183echo ' 184extern const struct vnodeop_desc vop_default_desc; 185' 186 187# Body stuff 188# This awk program needs toupper() so define it if necessary. 189sed -e "$sed_prep" $src | $awk "$toupper"' 190function doit() { 191 # Declare arg struct, descriptor. 192 printf("\n#define %s_DESCOFFSET %d\n", toupper(name), vop_offset++); 193 printf("struct %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 protoarg = sprintf("int %s(", toupper(name)); 202 protolen = length(protoarg); 203 printf("%s", protoarg); 204 for (i=0; i<argc; i++) { 205 protoarg = sprintf("%s", argtype[i]); 206 if (i < (argc-1)) protoarg = (protoarg ", "); 207 arglen = length(protoarg); 208 if ((protolen + arglen) > 77) { 209 protoarg = ("\n " protoarg); 210 arglen += 4; 211 protolen = 0; 212 } 213 printf("%s", protoarg); 214 protolen += arglen; 215 } 216 printf(");\n"); 217} 218BEGIN { 219 arg0special=""; 220 vop_offset = 1; # start at 1, to count the 'default' op 221 222 printf("\n/* Special cases: */\n#include <sys/buf.h>\n"); 223 argc=1; 224 argtype[0]="struct buf *"; 225 argname[0]="bp"; 226 lockstate[0] = -1; 227 arg0special="->b_vp"; 228 name="vop_bwrite"; 229 doit(); 230 printf("/* End of special cases */\n"); 231} 232END { 233 printf("\n#define VNODE_OPS_COUNT\t%d\n", vop_offset); 234} 235'"$awk_parser" | sed -e "$anal_retentive" 236 237# End stuff 238echo ' 239/* End of special cases. */' 240echo '' 241echo '#endif /* !_SYS_VNODE_IF_H_ */' 242 243# 244# Redirect stdout to the C file. 245# 246echo "$0: Creating $out_c" 1>&2 247exec > $out_c 248 249# Begin stuff 250echo -n "$warning" | sed -e 's/\$//g;s/@/\$/g;s/ $//' 251echo "" 252echo -n "$copyright" 253echo " 254#include <sys/cdefs.h> 255__KERNEL_RCSID(0, \"\$NetBSD\$\"); 256" 257 258echo ' 259#include "opt_vnode_lockdebug.h" 260#include "opt_multiprocessor.h"' 261echo ' 262#include <sys/param.h> 263#include <sys/mount.h> 264#include <sys/buf.h> 265#include <sys/vnode.h> 266#include <sys/lock.h> 267 268const struct vnodeop_desc vop_default_desc = { 269 0, 270 "default", 271 0, 272 NULL, 273 VDESC_NO_OFFSET, 274 VDESC_NO_OFFSET, 275 VDESC_NO_OFFSET, 276 NULL, 277}; 278' 279 280# Body stuff 281sed -e "$sed_prep" $src | $awk ' 282function do_offset(typematch) { 283 for (i=0; i<argc; i++) { 284 if (argtype[i] == typematch) { 285 printf("\tVOPARG_OFFSETOF(struct %s_args, a_%s),\n", 286 name, argname[i]); 287 return i; 288 }; 289 }; 290 print "\tVDESC_NO_OFFSET,"; 291 return -1; 292} 293 294function doit() { 295 # Define offsets array 296 printf("\nconst int %s_vp_offsets[] = {\n", name); 297 for (i=0; i<argc; i++) { 298 if (argtype[i] == "struct vnode *") { 299 printf ("\tVOPARG_OFFSETOF(struct %s_args,a_%s),\n", 300 name, argname[i]); 301 } 302 } 303 print "\tVDESC_NO_OFFSET"; 304 print "};"; 305 # Define F_desc 306 printf("const struct vnodeop_desc %s_desc = {\n", name); 307 # offset 308 printf ("\t%s_DESCOFFSET,\n", toupper(name)); 309 # printable name 310 printf ("\t\"%s\",\n", name); 311 # flags 312 printf("\t0"); 313 vpnum = 0; 314 for (i=0; i<argc; i++) { 315 if (willrele[i]) { 316 if (willrele[i] == 2) { 317 word = "UNLOCK"; 318 } else if (willrele[i] == 3) { 319 word = "PUT"; 320 } else { 321 word = "RELE"; 322 } 323 if (argdir[i] ~ /OUT/) { 324 printf(" | VDESC_VPP_WILL%s", word); 325 } else { 326 printf(" | VDESC_VP%s_WILL%s", vpnum, word); 327 }; 328 vpnum++; 329 } 330 } 331 print ","; 332 # vp offsets 333 printf ("\t%s_vp_offsets,\n", name); 334 # vpp (if any) 335 do_offset("struct vnode **"); 336 # cred (if any) 337 do_offset("kauth_cred_t"); 338 # componentname 339 do_offset("struct componentname *"); 340 # transport layer information 341 printf ("\tNULL,\n};\n"); 342 343 # Define function. 344 printf("int\n%s(", toupper(name)); 345 for (i=0; i<argc; i++) { 346 printf("%s %s", argtype[i], argname[i]); 347 if (i < (argc-1)) printf(",\n "); 348 } 349 printf(")\n"); 350 printf("{\n\tint error;\n\tbool mpsafe;\n\tstruct %s_args a;\n", name); 351 printf("#ifdef VNODE_LOCKDEBUG\n"); 352 for (i=0; i<argc; i++) { 353 if (lockstate[i] != -1) 354 printf("\tint islocked_%s;\n", argname[i]); 355 } 356 printf("#endif\n"); 357 printf("\ta.a_desc = VDESC(%s);\n", name); 358 for (i=0; i<argc; i++) { 359 printf("\ta.a_%s = %s;\n", argname[i], argname[i]); 360 if (lockstate[i] != -1) { 361 printf("#ifdef VNODE_LOCKDEBUG\n"); 362 printf("\tislocked_%s = (%s->v_vflag & VV_LOCKSWORK) ? (VOP_ISLOCKED(%s) == LK_EXCLUSIVE) : %d;\n", 363 argname[i], argname[i], argname[i], lockstate[i]); 364 printf("\tif (islocked_%s != %d)\n", argname[i], 365 lockstate[i]); 366 printf("\t\tpanic(\"%s: %s: locked %%d, expected %%d\", islocked_%s, %d);\n", name, argname[i], argname[i], lockstate[i]); 367 printf("#endif\n"); 368 } 369 } 370 printf("\tmpsafe = (%s%s->v_vflag & VV_MPSAFE);\n", argname[0], arg0special); 371 printf("\tif (!mpsafe) { KERNEL_LOCK(1, curlwp); }\n"); 372 printf("\terror = (VCALL(%s%s, VOFFSET(%s), &a));\n", 373 argname[0], arg0special, name); 374 printf("\tif (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }\n"); 375 if (willmake != -1) { 376 printf("#ifdef DIAGNOSTIC\n"); 377 printf("\tif (error == 0)\n" \ 378 "\t\tKASSERT((*%s)->v_size != VSIZENOTSET\n" \ 379 "\t\t && (*%s)->v_writesize != VSIZENOTSET);\n", 380 argname[willmake], argname[willmake]); 381 printf("#endif /* DIAGNOSTIC */\n"); 382 } 383 printf("\treturn error;\n}\n"); 384} 385BEGIN { 386 printf("\n/* Special cases: */\n"); 387 # start from 1 (vop_default is at 0) 388 argc=1; 389 willmake=-1; 390 argdir[0]="IN"; 391 argtype[0]="struct buf *"; 392 argname[0]="bp"; 393 lockstate[0] = -1; 394 arg0special="->b_vp"; 395 willrele[0]=0; 396 name="vop_bwrite"; 397 doit(); 398 printf("\n/* End of special cases */\n"); 399 400 arg0special=""; 401} 402'"$awk_parser" | sed -e "$anal_retentive" 403 404# End stuff 405echo ' 406/* End of special cases. */' 407 408# Add the vfs_op_descs array to the C file. 409# Begin stuff 410echo ' 411const struct vnodeop_desc * const vfs_op_descs[] = { 412 &vop_default_desc, /* MUST BE FIRST */ 413 &vop_bwrite_desc, /* XXX: SPECIAL CASE */ 414' 415 416# Body stuff 417sed -e "$sed_prep" $src | $awk ' 418function doit() { 419 printf("\t&%s_desc,\n", name); 420} 421'"$awk_parser" 422 423# End stuff 424echo ' NULL 425}; 426' 427 428exit 0 429 430# Local Variables: 431# tab-width: 4 432# End: 433