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. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS \`\`AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35" 36SCRIPT_ID='$NetBSD: vnode_if.sh,v 1.30 2001/11/12 14:34:24 lukem Exp $' 37 38# Script to produce VFS front-end sugar. 39# 40# usage: vnode_if.sh srcfile 41# (where srcfile is currently /sys/kern/vnode_if.src) 42# 43 44if [ $# -ne 1 ] ; then 45 echo 'usage: vnode_if.sh srcfile' 46 exit 1 47fi 48 49# Name and revision of the source file. 50src=$1 51SRC_ID=`head -1 $src | sed -e 's/.*\$\(.*\)\$.*/\1/'` 52 53# Names of the created files. 54out_c=vnode_if.c 55out_h=../sys/vnode_if.h 56 57# Awk program (must support nawk extensions) 58# Use "awk" at Berkeley, "nawk" or "gawk" elsewhere. 59awk=${AWK:-awk} 60 61# Does this awk have a "toupper" function? (i.e. is it GNU awk) 62isgawk=`$awk 'BEGIN { print toupper("true"); exit; }' 2>/dev/null` 63 64# If this awk does not define "toupper" then define our own. 65if [ "$isgawk" = TRUE ] ; then 66 # GNU awk provides it. 67 toupper= 68else 69 # Provide our own toupper() 70 toupper=' 71function toupper(str) { 72 _toupper_cmd = "echo "str" |tr a-z A-Z" 73 _toupper_cmd | getline _toupper_str; 74 close(_toupper_cmd); 75 return _toupper_str; 76}' 77fi 78 79# 80# This is the common part of all awk programs that read $src 81# This parses the input for one function into the arrays: 82# argdir, argtype, argname, willrele 83# and calls "doit()" to generate output for the function. 84# 85# Input to this parser is pre-processed slightly by sed 86# so this awk parser doesn't have to work so hard. The 87# changes done by the sed pre-processing step are: 88# insert a space beween * and pointer name 89# replace semicolons with spaces 90# 91sed_prep='s:\*\([^\*/]\):\* \1:g 92s/;/ /' 93awk_parser=' 94# Comment line 95/^#/ { next; } 96# First line of description 97/^vop_/ { 98 name=$1; 99 argc=0; 100 next; 101} 102# Last line of description 103/^}/ { 104 doit(); 105 next; 106} 107# Middle lines of description 108{ 109 argdir[argc] = $1; i=2; 110 if ($2 == "WILLRELE") { 111 willrele[argc] = 1; 112 i++; 113 } else if ($2 == "WILLUNLOCK") { 114 willrele[argc] = 2; 115 i++; 116 } else if ($2 == "WILLPUT") { 117 willrele[argc] = 3; 118 i++; 119 } else 120 willrele[argc] = 0; 121 argtype[argc] = $i; i++; 122 while (i < NF) { 123 argtype[argc] = argtype[argc]" "$i; 124 i++; 125 } 126 argname[argc] = $i; 127 argc++; 128 next; 129} 130' 131 132# This is put before the copyright on each generated file. 133warning="\ 134/* @NetBSD@ */ 135 136/* 137 * Warning: This file is generated automatically. 138 * (Modifications made here may easily be lost!) 139 * 140 * Created from the file: 141 * ${SRC_ID} 142 * by the script: 143 * ${SCRIPT_ID} 144 */ 145" 146 147# This is to satisfy McKusick (get rid of evil spaces 8^) 148anal_retentive='s:\([^/]\*\) :\1:g' 149 150# 151# Redirect stdout to the H file. 152# 153echo "$0: Creating $out_h" 1>&2 154exec > $out_h 155 156# Begin stuff 157echo -n "$warning" | sed -e 's/\$//g;s/@/\$/g' 158echo "" 159echo -n "$copyright" 160echo '' 161echo '#ifndef _SYS_VNODE_IF_H_' 162echo '#define _SYS_VNODE_IF_H_' 163echo '' 164echo '#ifdef _KERNEL' 165echo '#if defined(_LKM) || defined(LKM)' 166echo '/* LKMs always use non-inlined vnode ops. */' 167echo '#define VNODE_OP_NOINLINE' 168echo '#else' 169echo '#include "opt_vnode_op_noinline.h"' 170echo '#endif' 171echo '#endif /* _KERNEL */' 172echo ' 173extern const struct vnodeop_desc vop_default_desc; 174' 175 176# Body stuff 177# This awk program needs toupper() so define it if necessary. 178sed -e "$sed_prep" $src | $awk "$toupper"' 179function doit() { 180 # Declare arg struct, descriptor. 181 printf("\nstruct %s_args {\n", name); 182 printf("\tconst struct vnodeop_desc * a_desc;\n"); 183 for (i=0; i<argc; i++) { 184 printf("\t%s a_%s;\n", argtype[i], argname[i]); 185 } 186 printf("};\n"); 187 printf("extern const struct vnodeop_desc %s_desc;\n", name); 188 # Prototype it. 189 printf("#ifndef VNODE_OP_NOINLINE\n"); 190 printf("static __inline\n"); 191 printf("#endif\n"); 192 protoarg = sprintf("int %s(", toupper(name)); 193 protolen = length(protoarg); 194 printf("%s", protoarg); 195 for (i=0; i<argc; i++) { 196 protoarg = sprintf("%s", argtype[i]); 197 if (i < (argc-1)) protoarg = (protoarg ", "); 198 arglen = length(protoarg); 199 if ((protolen + arglen) > 77) { 200 protoarg = ("\n " protoarg); 201 arglen += 4; 202 protolen = 0; 203 } 204 printf("%s", protoarg); 205 protolen += arglen; 206 } 207 printf(")\n"); 208 printf("#ifndef VNODE_OP_NOINLINE\n"); 209 printf("__attribute__((__unused__))\n"); 210 printf("#endif\n"); 211 printf(";\n"); 212 # Define inline function. 213 printf("#ifndef VNODE_OP_NOINLINE\n"); 214 printf("static __inline int %s(", toupper(name)); 215 for (i=0; i<argc; i++) { 216 printf("%s", argname[i]); 217 if (i < (argc-1)) printf(", "); 218 } 219 printf(")\n"); 220 for (i=0; i<argc; i++) { 221 printf("\t%s %s;\n", argtype[i], argname[i]); 222 } 223 printf("{\n\tstruct %s_args a;\n", name); 224 printf("\ta.a_desc = VDESC(%s);\n", name); 225 for (i=0; i<argc; i++) { 226 printf("\ta.a_%s = %s;\n", argname[i], argname[i]); 227 } 228 printf("\treturn (VCALL(%s%s, VOFFSET(%s), &a));\n}\n", 229 argname[0], arg0special, name); 230 printf("#endif\n"); 231 vops++; 232} 233BEGIN { 234 arg0special=""; 235 vops = 1; # start at 1, to count the 'default' op 236} 237END { 238 printf("\n/* Special cases: */\n#include <sys/buf.h>\n"); 239 argc=1; 240 argtype[0]="struct buf *"; 241 argname[0]="bp"; 242 arg0special="->b_vp"; 243 name="vop_strategy"; 244 doit(); 245 name="vop_bwrite"; 246 doit(); 247 248 printf("\n#define VNODE_OPS_COUNT\t%d\n", vops); 249} 250'"$awk_parser" | sed -e "$anal_retentive" 251 252# End stuff 253echo ' 254/* End of special cases. */' 255echo '' 256echo '#endif /* !_SYS_VNODE_IF_H_ */' 257 258# 259# Redirect stdout to the C file. 260# 261echo "$0: Creating $out_c" 1>&2 262exec > $out_c 263 264# Begin stuff 265echo -n "$warning" | sed -e 's/\$//g;s/@/\$/g' 266echo "" 267echo -n "$copyright" 268echo " 269#include <sys/cdefs.h> 270__KERNEL_RCSID(0, \"\$NetBSD\$\"); 271" 272 273echo ' 274/* 275 * If we have LKM support, always include the non-inline versions for 276 * LKMs. Otherwise, do it based on the option. 277 */ 278#ifdef LKM 279#define VNODE_OP_NOINLINE 280#else 281#include "opt_vnode_op_noinline.h" 282#endif' 283echo ' 284#include <sys/param.h> 285#include <sys/mount.h> 286#include <sys/buf.h> 287#include <sys/vnode.h> 288 289const struct vnodeop_desc vop_default_desc = { 290 0, 291 "default", 292 0, 293 NULL, 294 VDESC_NO_OFFSET, 295 VDESC_NO_OFFSET, 296 VDESC_NO_OFFSET, 297 VDESC_NO_OFFSET, 298 NULL, 299}; 300' 301 302# Body stuff 303sed -e "$sed_prep" $src | $awk ' 304function do_offset(typematch) { 305 for (i=0; i<argc; i++) { 306 if (argtype[i] == typematch) { 307 printf("\tVOPARG_OFFSETOF(struct %s_args, a_%s),\n", 308 name, argname[i]); 309 return i; 310 }; 311 }; 312 print "\tVDESC_NO_OFFSET,"; 313 return -1; 314} 315 316function doit() { 317 # Define offsets array 318 printf("\nconst int %s_vp_offsets[] = {\n", name); 319 for (i=0; i<argc; i++) { 320 if (argtype[i] == "struct vnode *") { 321 printf ("\tVOPARG_OFFSETOF(struct %s_args,a_%s),\n", 322 name, argname[i]); 323 } 324 } 325 print "\tVDESC_NO_OFFSET"; 326 print "};"; 327 # Define F_desc 328 printf("const struct vnodeop_desc %s_desc = {\n", name); 329 # offset 330 printf ("\t%d,\n", vop_offset++); 331 # printable name 332 printf ("\t\"%s\",\n", name); 333 # flags 334 printf("\t0"); 335 vpnum = 0; 336 for (i=0; i<argc; i++) { 337 if (willrele[i]) { 338 if (willrele[i] == 2) { 339 word = "UNLOCK"; 340 } else if (willrele[i] == 3) { 341 word = "PUT"; 342 } else { 343 word = "RELE"; 344 } 345 if (argdir[i] ~ /OUT/) { 346 printf(" | VDESC_VPP_WILL%s", word); 347 } else { 348 printf(" | VDESC_VP%s_WILL%s", vpnum, word); 349 }; 350 vpnum++; 351 } 352 } 353 print ","; 354 # vp offsets 355 printf ("\t%s_vp_offsets,\n", name); 356 # vpp (if any) 357 do_offset("struct vnode **"); 358 # cred (if any) 359 do_offset("struct ucred *"); 360 # proc (if any) 361 do_offset("struct proc *"); 362 # componentname 363 do_offset("struct componentname *"); 364 # transport layer information 365 printf ("\tNULL,\n};\n"); 366 367 # Define function. 368 printf("#ifdef VNODE_OP_NOINLINE\n"); 369 printf("int\n%s(", toupper(name)); 370 for (i=0; i<argc; i++) { 371 printf("%s", argname[i]); 372 if (i < (argc-1)) printf(", "); 373 } 374 printf(")\n"); 375 for (i=0; i<argc; i++) { 376 printf("\t%s %s;\n", argtype[i], argname[i]); 377 } 378 printf("{\n\tstruct %s_args a;\n", name); 379 printf("\ta.a_desc = VDESC(%s);\n", name); 380 for (i=0; i<argc; i++) { 381 printf("\ta.a_%s = %s;\n", argname[i], argname[i]); 382 } 383 printf("\treturn (VCALL(%s%s, VOFFSET(%s), &a));\n}\n", 384 argname[0], arg0special, name); 385 printf("#endif\n"); 386} 387BEGIN { 388 printf("\n/* Special cases: */\n"); 389 # start from 1 (vop_default is at 0) 390 vop_offset=1; 391 argc=1; 392 argdir[0]="IN"; 393 argtype[0]="struct buf *"; 394 argname[0]="bp"; 395 arg0special="->b_vp"; 396 willrele[0]=0; 397 name="vop_strategy"; 398 doit(); 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_strategy_desc, /* XXX: SPECIAL CASE */ 417 &vop_bwrite_desc, /* XXX: SPECIAL CASE */ 418' 419 420# Body stuff 421sed -e "$sed_prep" $src | $awk ' 422function doit() { 423 printf("\t&%s_desc,\n", name); 424} 425'"$awk_parser" 426 427# End stuff 428echo ' NULL 429}; 430' 431 432exit 0 433 434# Local Variables: 435# tab-width: 4 436# End: 437