1#!/bin/sh - 2# 3# Copyright (c) 1992, 1993 4# The Regents of the University of California. All rights reserved. 5# 6# Redistribution and use in source and binary forms, with or without 7# modification, are permitted provided that the following conditions 8# are met: 9# 1. Redistributions of source code must retain the above copyright 10# notice, this list of conditions and the following disclaimer. 11# 2. Redistributions in binary form must reproduce the above copyright 12# notice, this list of conditions and the following disclaimer in the 13# documentation and/or other materials provided with the distribution. 14# 3. All advertising materials mentioning features or use of this software 15# must display the following acknowledgement: 16# This product includes software developed by the University of 17# California, Berkeley and its contributors. 18# 4. Neither the name of the University nor the names of its contributors 19# may be used to endorse or promote products derived from this software 20# without specific prior written permission. 21# 22# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32# SUCH DAMAGE. 33# 34# @(#)vnode_if.sh 8.1 (Berkeley) 6/10/93 35# 36 37# Script to produce VFS front-end sugar. 38# 39# usage: vnode_if.sh srcfile 40# (where srcfile is currently /sys/kern/vnode_if.src) 41# 42# These awk scripts are not particularly well written, specifically they 43# don't use arrays well and figure out the same information repeatedly. 44# Please rewrite them if you actually understand how to use awk. Note, 45# they use nawk extensions and gawk's toupper. 46 47if [ $# -ne 1 ] ; then 48 echo 'usage: vnode_if.sh srcfile' 49 exit 1 50fi 51 52# Name of the source file. 53SRC=$1 54 55# Names of the created files. 56CFILE=vnode_if.c 57HEADER=vnode_if.h 58 59# Awk program (must support nawk extensions and gawk's "toupper") 60# Use "awk" at Berkeley, "gawk" elsewhere. 61AWK=awk 62 63# Print out header information for vnode_if.h. 64cat << END_OF_LEADING_COMMENT > $HEADER 65/* 66 * This file is produced automatically. 67 * Do not modify anything in here by hand. 68 * 69 * Created from @(#)vnode_if.sh 8.1 (Berkeley) 6/10/93 70 */ 71 72extern struct vnodeop_desc vop_default_desc; 73END_OF_LEADING_COMMENT 74 75# Awk script to take vnode_if.src and turn it into vnode_if.h. 76$AWK ' 77 NF == 0 || $0 ~ "^#" { 78 next; 79 } 80 { 81 # Get the function name. 82 name = $1; 83 uname = toupper(name); 84 85 # Get the function arguments. 86 for (c1 = 0;; ++c1) { 87 if (getline <= 0) 88 exit 89 if ($0 ~ "^};") 90 break; 91 a[c1] = $0; 92 } 93 94 # Print out the vop_F_args structure. 95 printf("struct %s_args {\n\tstruct vnodeop_desc *a_desc;\n", 96 name); 97 for (c2 = 0; c2 < c1; ++c2) { 98 c3 = split(a[c2], t); 99 printf("\t"); 100 if (t[2] ~ "WILLRELE") 101 c4 = 3; 102 else 103 c4 = 2; 104 for (; c4 < c3; ++c4) 105 printf("%s ", t[c4]); 106 beg = match(t[c3], "[^*]"); 107 printf("%sa_%s\n", 108 substr(t[c4], 0, beg - 1), substr(t[c4], beg)); 109 } 110 printf("};\n"); 111 112 # Print out extern declaration. 113 printf("extern struct vnodeop_desc %s_desc;\n", name); 114 115 # Print out inline struct. 116 printf("static inline int %s(", uname); 117 sep = ", "; 118 for (c2 = 0; c2 < c1; ++c2) { 119 if (c2 == c1 - 1) 120 sep = ")\n"; 121 c3 = split(a[c2], t); 122 beg = match(t[c3], "[^*]"); 123 end = match(t[c3], ";"); 124 printf("%s%s", substr(t[c3], beg, end - beg), sep); 125 } 126 for (c2 = 0; c2 < c1; ++c2) { 127 c3 = split(a[c2], t); 128 printf("\t"); 129 if (t[2] ~ "WILLRELE") 130 c4 = 3; 131 else 132 c4 = 2; 133 for (; c4 < c3; ++c4) 134 printf("%s ", t[c4]); 135 beg = match(t[c3], "[^*]"); 136 printf("%s%s\n", 137 substr(t[c4], 0, beg - 1), substr(t[c4], beg)); 138 } 139 printf("{\n\tstruct %s_args a;\n\n", name); 140 printf("\ta.a_desc = VDESC(%s);\n", name); 141 for (c2 = 0; c2 < c1; ++c2) { 142 c3 = split(a[c2], t); 143 printf("\t"); 144 beg = match(t[c3], "[^*]"); 145 end = match(t[c3], ";"); 146 printf("a.a_%s = %s\n", 147 substr(t[c3], beg, end - beg), substr(t[c3], beg)); 148 } 149 c1 = split(a[0], t); 150 beg = match(t[c1], "[^*]"); 151 end = match(t[c1], ";"); 152 printf("\treturn (VCALL(%s, VOFFSET(%s), &a));\n}\n", 153 substr(t[c1], beg, end - beg), name); 154 }' < $SRC >> $HEADER 155 156# Print out header information for vnode_if.c. 157cat << END_OF_LEADING_COMMENT > $CFILE 158/* 159 * This file is produced automatically. 160 * Do not modify anything in here by hand. 161 * 162 * Created from @(#)vnode_if.sh 8.1 (Berkeley) 6/10/93 163 */ 164 165#include <sys/param.h> 166#include <sys/mount.h> 167#include <sys/vnode.h> 168 169struct vnodeop_desc vop_default_desc = { 170 0, 171 "default", 172 0, 173 NULL, 174 VDESC_NO_OFFSET, 175 VDESC_NO_OFFSET, 176 VDESC_NO_OFFSET, 177 VDESC_NO_OFFSET, 178 NULL, 179}; 180 181END_OF_LEADING_COMMENT 182 183# Awk script to take vnode_if.src and turn it into vnode_if.c. 184$AWK 'function kill_surrounding_ws (s) { 185 sub (/^[ \t]*/, "", s); 186 sub (/[ \t]*$/, "", s); 187 return s; 188 } 189 190 function read_args() { 191 numargs = 0; 192 while (getline ln) { 193 if (ln ~ /}/) { 194 break; 195 }; 196 197 # Delete comments, if any. 198 gsub (/\/\*.*\*\//, "", ln); 199 200 # Delete leading/trailing space. 201 ln = kill_surrounding_ws(ln); 202 203 # Pick off direction. 204 if (1 == sub(/^INOUT[ \t]+/, "", ln)) 205 dir = "INOUT"; 206 else if (1 == sub(/^IN[ \t]+/, "", ln)) 207 dir = "IN"; 208 else if (1 == sub(/^OUT[ \t]+/, "", ln)) 209 dir = "OUT"; 210 else 211 bail("No IN/OUT direction for \"" ln "\"."); 212 213 # check for "WILLRELE" 214 if (1 == sub(/^WILLRELE[ \t]+/, "", ln)) { 215 rele = "WILLRELE"; 216 } else { 217 rele = "WONTRELE"; 218 }; 219 220 # kill trailing ; 221 if (1 != sub (/;$/, "", ln)) { 222 bail("Missing end-of-line ; in \"" ln "\"."); 223 }; 224 225 # pick off variable name 226 if (!(i = match(ln, /[A-Za-z0-9_]+$/))) { 227 bail("Missing var name \"a_foo\" in \"" ln "\"."); 228 }; 229 arg = substr (ln, i); 230 # Want to <<substr(ln, i) = "";>>, but nawk cannot. 231 # Hack around this. 232 ln = substr(ln, 1, i-1); 233 234 # what is left must be type 235 # (put clean it up some) 236 type = ln; 237 gsub (/[ \t]+/, " ", type); # condense whitespace 238 type = kill_surrounding_ws(type); 239 240 # (boy this was easier in Perl) 241 242 numargs++; 243 dirs[numargs] = dir; 244 reles[numargs] = rele; 245 types[numargs] = type; 246 args[numargs] = arg; 247 }; 248 } 249 250 function generate_operation_vp_offsets() { 251 printf ("int %s_vp_offsets[] = {\n", name); 252 # as a side effect, figure out the releflags 253 releflags = ""; 254 vpnum = 0; 255 for (i=1; i<=numargs; i++) { 256 if (types[i] == "struct vnode *") { 257 printf ("\tVOPARG_OFFSETOF(struct %s_args,a_%s),\n", 258 name, args[i]); 259 if (reles[i] == "WILLRELE") { 260 releflags = releflags "|VDESC_VP" vpnum "_WILLRELE"; 261 }; 262 vpnum++; 263 }; 264 }; 265 sub (/^\|/, "", releflags); 266 print "\tVDESC_NO_OFFSET"; 267 print "};"; 268 } 269 270 function find_arg_with_type (type) { 271 for (i=1; i<=numargs; i++) { 272 if (types[i] == type) { 273 return "VOPARG_OFFSETOF(struct " name "_args,a_" args[i] ")"; 274 }; 275 }; 276 return "VDESC_NO_OFFSET"; 277 } 278 279 function generate_operation_desc() { 280 printf ("struct vnodeop_desc %s_desc = {\n", name); 281 # offset 282 printf ("\t0,\n"); 283 # printable name 284 printf ("\t\"%s\",\n", name); 285 # flags 286 vppwillrele = ""; 287 for (i=1; i<=numargs; i++) { 288 if (types[i] == "struct vnode **" && 289 (reles[i] == "WILLRELE")) { 290 vppwillrele = "|VDESC_VPP_WILLRELE"; 291 }; 292 }; 293 if (releflags == "") { 294 printf ("\t0%s,\n", vppwillrele); 295 } else { 296 printf ("\t%s%s,\n", releflags, vppwillrele); 297 }; 298 # vp offsets 299 printf ("\t%s_vp_offsets,\n", name); 300 # vpp (if any) 301 printf ("\t%s,\n", find_arg_with_type("struct vnode **")); 302 # cred (if any) 303 printf ("\t%s,\n", find_arg_with_type("struct ucred *")); 304 # proc (if any) 305 printf ("\t%s,\n", find_arg_with_type("struct proc *")); 306 # componentname 307 printf ("\t%s,\n", find_arg_with_type("struct componentname *")); 308 # transport layer information 309 printf ("\tNULL,\n};\n"); 310 } 311 312 NF == 0 || $0 ~ "^#" { 313 next; 314 } 315 { 316 # get the function name 317 name = $1; 318 319 # get the function arguments 320 read_args(); 321 322 # Print out the vop_F_vp_offsets structure. This all depends 323 # on naming conventions and nothing else. 324 generate_operation_vp_offsets(); 325 326 # Print out the vnodeop_desc structure. 327 generate_operation_desc(); 328 329 printf "\n"; 330 331 }' < $SRC >> $CFILE 332# THINGS THAT DON'T WORK RIGHT YET. 333# 334# Two existing BSD vnodeops (bwrite and strategy) don't take any vnodes as 335# arguments. This means that these operations can't function successfully 336# through a bypass routine. 337# 338# Bwrite and strategy will be replaced when the VM page/buffer cache 339# integration happens. 340# 341# To get around this problem for now we handle these ops as special cases. 342 343cat << END_OF_SPECIAL_CASES >> $HEADER 344#include <sys/buf.h> 345struct vop_strategy_args { 346 struct vnodeop_desc *a_desc; 347 struct buf *a_bp; 348}; 349extern struct vnodeop_desc vop_strategy_desc; 350static inline int VOP_STRATEGY(bp) 351 struct buf *bp; 352{ 353 struct vop_strategy_args a; 354 355 a.a_desc = VDESC(vop_strategy); 356 a.a_bp = bp; 357 return (VCALL((bp)->b_vp, VOFFSET(vop_strategy), &a)); 358} 359 360struct vop_bwrite_args { 361 struct vnodeop_desc *a_desc; 362 struct buf *a_bp; 363}; 364extern struct vnodeop_desc vop_bwrite_desc; 365static inline int VOP_BWRITE(bp) 366 struct buf *bp; 367{ 368 struct vop_bwrite_args a; 369 370 a.a_desc = VDESC(vop_bwrite); 371 a.a_bp = bp; 372 return (VCALL((bp)->b_vp, VOFFSET(vop_bwrite), &a)); 373} 374END_OF_SPECIAL_CASES 375 376cat << END_OF_SPECIAL_CASES >> $CFILE 377int vop_strategy_vp_offsets[] = { 378 VDESC_NO_OFFSET 379}; 380struct vnodeop_desc vop_strategy_desc = { 381 0, 382 "vop_strategy", 383 0, 384 vop_strategy_vp_offsets, 385 VDESC_NO_OFFSET, 386 VDESC_NO_OFFSET, 387 VDESC_NO_OFFSET, 388 VDESC_NO_OFFSET, 389 NULL, 390}; 391int vop_bwrite_vp_offsets[] = { 392 VDESC_NO_OFFSET 393}; 394struct vnodeop_desc vop_bwrite_desc = { 395 0, 396 "vop_bwrite", 397 0, 398 vop_bwrite_vp_offsets, 399 VDESC_NO_OFFSET, 400 VDESC_NO_OFFSET, 401 VDESC_NO_OFFSET, 402 VDESC_NO_OFFSET, 403 NULL, 404}; 405END_OF_SPECIAL_CASES 406 407# Add the vfs_op_descs array to the C file. 408$AWK ' 409 BEGIN { 410 printf("\nstruct vnodeop_desc *vfs_op_descs[] = {\n"); 411 printf("\t&vop_default_desc, /* MUST BE FIRST */\n"); 412 printf("\t&vop_strategy_desc, /* XXX: SPECIAL CASE */\n"); 413 printf("\t&vop_bwrite_desc, /* XXX: SPECIAL CASE */\n"); 414 } 415 END { 416 printf("\tNULL\n};\n"); 417 } 418 NF == 0 || $0 ~ "^#" { 419 next; 420 } 421 { 422 # Get the function name. 423 printf("\t&%s_desc,\n", $1); 424 425 # Skip the function arguments. 426 for (;;) { 427 if (getline <= 0) 428 exit 429 if ($0 ~ "^};") 430 break; 431 } 432 }' < $SRC >> $CFILE 433 434