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