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