# Copyright (c) 1992, 1993
# The Regents of the University of California. All rights reserved.
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
# must display the following acknowledgement:
# This product includes software developed by the University of
# California, Berkeley and its contributors.
# 4. Neither the name of the University nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# @(#)vnode_if.sh 8.1 (Berkeley) 6/10/93
# Script to produce VFS front-end sugar.
# usage: vnode_if.sh srcfile
# (where srcfile is currently /sys/kern/vnode_if.src)
# These awk scripts are not particularly well written, specifically they
# don't use arrays well and figure out the same information repeatedly.
# Please rewrite them if you actually understand how to use awk. Note,
# they use nawk extensions and gawk's toupper.
echo 'usage: vnode_if.sh srcfile'
# Name of the source file.
# Names of the created files.
# Awk program (must support nawk extensions and gawk's "toupper")
# Use "awk" at Berkeley, "gawk" elsewhere.
# Print out header information for vnode_if.h.
cat << END_OF_LEADING_COMMENT > $HEADER
* This file is produced automatically.
* Do not modify anything in here by hand.
* Created from @(#)vnode_if.sh 8.1 (Berkeley) 6/10/93
extern struct vnodeop_desc vop_default_desc;
# Awk script to take vnode_if.src and turn it into vnode_if.h.
# Get the function arguments.
# Print out the vop_F_args structure.
printf("struct %s_args {\n\tstruct vnodeop_desc *a_desc;\n",
for (c2 = 0; c2 < c1; ++c2) {
beg = match(t[c3], "[^*]");
substr(t[c4], 0, beg - 1), substr(t[c4], beg));
# Print out extern declaration.
printf("extern struct vnodeop_desc %s_desc;\n", name);
# Print out inline struct.
printf("static inline int %s(", uname);
for (c2 = 0; c2 < c1; ++c2) {
beg = match(t[c3], "[^*]");
printf("%s%s", substr(t[c3], beg, end - beg), sep);
for (c2 = 0; c2 < c1; ++c2) {
beg = match(t[c3], "[^*]");
substr(t[c4], 0, beg - 1), substr(t[c4], beg));
printf("{\n\tstruct %s_args a;\n\n", name);
printf("\ta.a_desc = VDESC(%s);\n", name);
for (c2 = 0; c2 < c1; ++c2) {
beg = match(t[c3], "[^*]");
substr(t[c3], beg, end - beg), substr(t[c3], beg));
beg = match(t[c1], "[^*]");
printf("\treturn (VCALL(%s, VOFFSET(%s), &a));\n}\n",
substr(t[c1], beg, end - beg), name);
# Print out header information for vnode_if.c.
cat << END_OF_LEADING_COMMENT > $CFILE
* This file is produced automatically.
* Do not modify anything in here by hand.
* Created from @(#)vnode_if.sh 8.1 (Berkeley) 6/10/93
struct vnodeop_desc vop_default_desc = {
# Awk script to take vnode_if.src and turn it into vnode_if.c.
$AWK 'function kill_surrounding_ws (s) {
# Delete comments, if any.
gsub (/\/\*.*\*\//, "", ln);
# Delete leading/trailing space.
ln = kill_surrounding_ws(ln);
if (1 == sub(/^INOUT[ \t]+/, "", ln))
else if (1 == sub(/^IN[ \t]+/, "", ln))
else if (1 == sub(/^OUT[ \t]+/, "", ln))
bail("No IN/OUT direction for \"" ln "\".");
if (1 == sub(/^WILLRELE[ \t]+/, "", ln)) {
if (1 != sub (/;$/, "", ln)) {
bail("Missing end-of-line ; in \"" ln "\".");
if (!(i = match(ln, /[A-Za-z0-9_]+$/))) {
bail("Missing var name \"a_foo\" in \"" ln "\".");
# Want to <<substr(ln, i) = "";>>, but nawk cannot.
# what is left must be type
gsub (/[ \t]+/, " ", type); # condense whitespace
type = kill_surrounding_ws(type);
# (boy this was easier in Perl)
function generate_operation_vp_offsets() {
printf ("int %s_vp_offsets[] = {\n", name);
# as a side effect, figure out the releflags
for (i=1; i<=numargs; i++) {
if (types[i] == "struct vnode *") {
printf ("\tVOPARG_OFFSETOF(struct %s_args,a_%s),\n",
if (reles[i] == "WILLRELE") {
releflags = releflags "|VDESC_VP" vpnum "_WILLRELE";
sub (/^\|/, "", releflags);
print "\tVDESC_NO_OFFSET";
function find_arg_with_type (type) {
for (i=1; i<=numargs; i++) {
return "VOPARG_OFFSETOF(struct " name "_args,a_" args[i] ")";
return "VDESC_NO_OFFSET";
function generate_operation_desc() {
printf ("struct vnodeop_desc %s_desc = {\n", name);
printf ("\t\"%s\",\n", name);
for (i=1; i<=numargs; i++) {
if (types[i] == "struct vnode **" &&
(reles[i] == "WILLRELE")) {
vppwillrele = "|VDESC_VPP_WILLRELE";
printf ("\t0%s,\n", vppwillrele);
printf ("\t%s%s,\n", releflags, vppwillrele);
printf ("\t%s_vp_offsets,\n", name);
printf ("\t%s,\n", find_arg_with_type("struct vnode **"));
printf ("\t%s,\n", find_arg_with_type("struct ucred *"));
printf ("\t%s,\n", find_arg_with_type("struct proc *"));
printf ("\t%s,\n", find_arg_with_type("struct componentname *"));
# transport layer information
printf ("\tNULL,\n};\n");
# get the function arguments
# Print out the vop_F_vp_offsets structure. This all depends
# on naming conventions and nothing else.
generate_operation_vp_offsets();
# Print out the vnodeop_desc structure.
generate_operation_desc();
# THINGS THAT DON'T WORK RIGHT YET.
# Two existing BSD vnodeops (bwrite and strategy) don't take any vnodes as
# arguments. This means that these operations can't function successfully
# through a bypass routine.
# Bwrite and strategy will be replaced when the VM page/buffer cache
# To get around this problem for now we handle these ops as special cases.
cat << END_OF_SPECIAL_CASES >> $HEADER
struct vop_strategy_args {
struct vnodeop_desc *a_desc;
extern struct vnodeop_desc vop_strategy_desc;
static inline int VOP_STRATEGY(bp)
struct vop_strategy_args a;
a.a_desc = VDESC(vop_strategy);
return (VCALL((bp)->b_vp, VOFFSET(vop_strategy), &a));
struct vnodeop_desc *a_desc;
extern struct vnodeop_desc vop_bwrite_desc;
static inline int VOP_BWRITE(bp)
struct vop_bwrite_args a;
a.a_desc = VDESC(vop_bwrite);
return (VCALL((bp)->b_vp, VOFFSET(vop_bwrite), &a));
cat << END_OF_SPECIAL_CASES >> $CFILE
int vop_strategy_vp_offsets[] = {
struct vnodeop_desc vop_strategy_desc = {
int vop_bwrite_vp_offsets[] = {
struct vnodeop_desc vop_bwrite_desc = {
# Add the vfs_op_descs array to the C file.
printf("\nstruct vnodeop_desc *vfs_op_descs[] = {\n");
printf("\t&vop_default_desc, /* MUST BE FIRST */\n");
printf("\t&vop_strategy_desc, /* XXX: SPECIAL CASE */\n");
printf("\t&vop_bwrite_desc, /* XXX: SPECIAL CASE */\n");
printf("\t&%s_desc,\n", $1);
# Skip the function arguments.