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.46 2007/11/06 21:59:43 ad 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 VDESC_NO_OFFSET, 277 NULL, 278}; 279' 280 281# Body stuff 282sed -e "$sed_prep" $src | $awk ' 283function do_offset(typematch) { 284 for (i=0; i<argc; i++) { 285 if (argtype[i] == typematch) { 286 printf("\tVOPARG_OFFSETOF(struct %s_args, a_%s),\n", 287 name, argname[i]); 288 return i; 289 }; 290 }; 291 print "\tVDESC_NO_OFFSET,"; 292 return -1; 293} 294 295function doit() { 296 # Define offsets array 297 printf("\nconst int %s_vp_offsets[] = {\n", name); 298 for (i=0; i<argc; i++) { 299 if (argtype[i] == "struct vnode *") { 300 printf ("\tVOPARG_OFFSETOF(struct %s_args,a_%s),\n", 301 name, argname[i]); 302 } 303 } 304 print "\tVDESC_NO_OFFSET"; 305 print "};"; 306 # Define F_desc 307 printf("const struct vnodeop_desc %s_desc = {\n", name); 308 # offset 309 printf ("\t%s_DESCOFFSET,\n", toupper(name)); 310 # printable name 311 printf ("\t\"%s\",\n", name); 312 # flags 313 printf("\t0"); 314 vpnum = 0; 315 for (i=0; i<argc; i++) { 316 if (willrele[i]) { 317 if (willrele[i] == 2) { 318 word = "UNLOCK"; 319 } else if (willrele[i] == 3) { 320 word = "PUT"; 321 } else { 322 word = "RELE"; 323 } 324 if (argdir[i] ~ /OUT/) { 325 printf(" | VDESC_VPP_WILL%s", word); 326 } else { 327 printf(" | VDESC_VP%s_WILL%s", vpnum, word); 328 }; 329 vpnum++; 330 } 331 } 332 print ","; 333 # vp offsets 334 printf ("\t%s_vp_offsets,\n", name); 335 # vpp (if any) 336 do_offset("struct vnode **"); 337 # cred (if any) 338 do_offset("kauth_cred_t"); 339 # lwp (if any) 340 do_offset("struct lwp *"); 341 # componentname 342 do_offset("struct componentname *"); 343 # transport layer information 344 printf ("\tNULL,\n};\n"); 345 346 # Define function. 347 printf("int\n%s(", toupper(name)); 348 for (i=0; i<argc; i++) { 349 printf("%s %s", argtype[i], argname[i]); 350 if (i < (argc-1)) printf(",\n "); 351 } 352 printf(")\n"); 353 printf("{\n\tint error;\n\tbool mpsafe;\n\tstruct %s_args a;\n", name); 354 printf("#ifdef VNODE_LOCKDEBUG\n"); 355 for (i=0; i<argc; i++) { 356 if (lockstate[i] != -1) 357 printf("\tint islocked_%s;\n", argname[i]); 358 } 359 printf("#endif\n"); 360 printf("\ta.a_desc = VDESC(%s);\n", name); 361 for (i=0; i<argc; i++) { 362 printf("\ta.a_%s = %s;\n", argname[i], argname[i]); 363 if (lockstate[i] != -1) { 364 printf("#ifdef VNODE_LOCKDEBUG\n"); 365 printf("\tislocked_%s = (%s->v_vflag & VV_LOCKSWORK) ? (VOP_ISLOCKED(%s) == LK_EXCLUSIVE) : %d;\n", 366 argname[i], argname[i], argname[i], lockstate[i]); 367 printf("\tif (islocked_%s != %d)\n", argname[i], 368 lockstate[i]); 369 printf("\t\tpanic(\"%s: %s: locked %%d, expected %%d\", islocked_%s, %d);\n", name, argname[i], argname[i], lockstate[i]); 370 printf("#endif\n"); 371 } 372 } 373 printf("\tmpsafe = (%s%s->v_vflag & VV_MPSAFE);\n", argname[0], arg0special); 374 printf("\tif (!mpsafe) { KERNEL_LOCK(1, curlwp); }\n"); 375 printf("\terror = (VCALL(%s%s, VOFFSET(%s), &a));\n", 376 argname[0], arg0special, name); 377 printf("\tif (!mpsafe) { KERNEL_UNLOCK_ONE(curlwp); }\n"); 378 if (willmake != -1) { 379 printf("#ifdef DIAGNOSTIC\n"); 380 printf("\tif (error == 0)\n" \ 381 "\t\tKASSERT((*%s)->v_size != VSIZENOTSET\n" \ 382 "\t\t && (*%s)->v_writesize != VSIZENOTSET);\n", 383 argname[willmake], argname[willmake]); 384 printf("#endif /* DIAGNOSTIC */\n"); 385 } 386 printf("\treturn error;\n}\n"); 387} 388BEGIN { 389 printf("\n/* Special cases: */\n"); 390 # start from 1 (vop_default is at 0) 391 argc=1; 392 willmake=-1; 393 argdir[0]="IN"; 394 argtype[0]="struct buf *"; 395 argname[0]="bp"; 396 lockstate[0] = -1; 397 arg0special="->b_vp"; 398 willrele[0]=0; 399 name="vop_bwrite"; 400 doit(); 401 printf("\n/* End of special cases */\n"); 402 403 arg0special=""; 404} 405'"$awk_parser" | sed -e "$anal_retentive" 406 407# End stuff 408echo ' 409/* End of special cases. */' 410 411# Add the vfs_op_descs array to the C file. 412# Begin stuff 413echo ' 414const struct vnodeop_desc * const vfs_op_descs[] = { 415 &vop_default_desc, /* MUST BE FIRST */ 416 &vop_bwrite_desc, /* XXX: SPECIAL CASE */ 417' 418 419# Body stuff 420sed -e "$sed_prep" $src | $awk ' 421function doit() { 422 printf("\t&%s_desc,\n", name); 423} 424'"$awk_parser" 425 426# End stuff 427echo ' NULL 428}; 429' 430 431exit 0 432 433# Local Variables: 434# tab-width: 4 435# End: 436