vnode_if.awk revision 1541
11541Srgrimes#!/bin/sh -
21541Srgrimes#
31541Srgrimes# Copyright (c) 1992, 1993
41541Srgrimes#	The Regents of the University of California.  All rights reserved.
51541Srgrimes#
61541Srgrimes# Redistribution and use in source and binary forms, with or without
71541Srgrimes# modification, are permitted provided that the following conditions
81541Srgrimes# are met:
91541Srgrimes# 1. Redistributions of source code must retain the above copyright
101541Srgrimes#    notice, this list of conditions and the following disclaimer.
111541Srgrimes# 2. Redistributions in binary form must reproduce the above copyright
121541Srgrimes#    notice, this list of conditions and the following disclaimer in the
131541Srgrimes#    documentation and/or other materials provided with the distribution.
141541Srgrimes# 3. All advertising materials mentioning features or use of this software
151541Srgrimes#    must display the following acknowledgement:
161541Srgrimes#	This product includes software developed by the University of
171541Srgrimes#	California, Berkeley and its contributors.
181541Srgrimes# 4. Neither the name of the University nor the names of its contributors
191541Srgrimes#    may be used to endorse or promote products derived from this software
201541Srgrimes#    without specific prior written permission.
211541Srgrimes#
221541Srgrimes# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
231541Srgrimes# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
241541Srgrimes# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
251541Srgrimes# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
261541Srgrimes# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
271541Srgrimes# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
281541Srgrimes# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
291541Srgrimes# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
301541Srgrimes# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
311541Srgrimes# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
321541Srgrimes# SUCH DAMAGE.
331541Srgrimes#
341541Srgrimes#	@(#)vnode_if.sh	8.1 (Berkeley) 6/10/93
351541Srgrimes#
361541Srgrimes
371541Srgrimes# Script to produce VFS front-end sugar.
381541Srgrimes#
391541Srgrimes# usage: vnode_if.sh srcfile
401541Srgrimes#	(where srcfile is currently /sys/kern/vnode_if.src)
411541Srgrimes#
421541Srgrimes# These awk scripts are not particularly well written, specifically they
431541Srgrimes# don't use arrays well and figure out the same information repeatedly.
441541Srgrimes# Please rewrite them if you actually understand how to use awk.  Note,
451541Srgrimes# they use nawk extensions and gawk's toupper.
461541Srgrimes
471541Srgrimesif [ $# -ne 1 ] ; then
481541Srgrimes	echo 'usage: vnode_if.sh srcfile'
491541Srgrimes	exit 1
501541Srgrimesfi
511541Srgrimes
521541Srgrimes# Name of the source file.
531541SrgrimesSRC=$1
541541Srgrimes
551541Srgrimes# Names of the created files.
561541SrgrimesCFILE=vnode_if.c
571541SrgrimesHEADER=vnode_if.h
581541Srgrimes
591541Srgrimes# Awk program (must support nawk extensions and gawk's "toupper")
601541Srgrimes# Use "awk" at Berkeley, "gawk" elsewhere.
611541SrgrimesAWK=awk
621541Srgrimes
631541Srgrimes# Print out header information for vnode_if.h.
641541Srgrimescat << END_OF_LEADING_COMMENT > $HEADER
651541Srgrimes/*
661541Srgrimes * This file is produced automatically.
671541Srgrimes * Do not modify anything in here by hand.
681541Srgrimes *
691541Srgrimes * Created from @(#)vnode_if.sh	8.1 (Berkeley) 6/10/93
701541Srgrimes */
711541Srgrimes
721541Srgrimesextern struct vnodeop_desc vop_default_desc;
731541SrgrimesEND_OF_LEADING_COMMENT
741541Srgrimes
751541Srgrimes# Awk script to take vnode_if.src and turn it into vnode_if.h.
761541Srgrimes$AWK '
771541Srgrimes	NF == 0 || $0 ~ "^#" {
781541Srgrimes		next;
791541Srgrimes	}
801541Srgrimes	{
811541Srgrimes		# Get the function name.
821541Srgrimes		name = $1;
831541Srgrimes		uname = toupper(name);
841541Srgrimes
851541Srgrimes		# Get the function arguments.
861541Srgrimes		for (c1 = 0;; ++c1) {
871541Srgrimes			if (getline <= 0)
881541Srgrimes				exit
891541Srgrimes			if ($0 ~ "^};")
901541Srgrimes				break;
911541Srgrimes			a[c1] = $0;
921541Srgrimes		}
931541Srgrimes
941541Srgrimes		# Print out the vop_F_args structure.
951541Srgrimes		printf("struct %s_args {\n\tstruct vnodeop_desc *a_desc;\n",
961541Srgrimes		    name);
971541Srgrimes		for (c2 = 0; c2 < c1; ++c2) {
981541Srgrimes			c3 = split(a[c2], t);
991541Srgrimes			printf("\t");
1001541Srgrimes			if (t[2] ~ "WILLRELE")
1011541Srgrimes				c4 = 3;
1021541Srgrimes			else 
1031541Srgrimes				c4 = 2;
1041541Srgrimes			for (; c4 < c3; ++c4)
1051541Srgrimes				printf("%s ", t[c4]);
1061541Srgrimes			beg = match(t[c3], "[^*]");
1071541Srgrimes			printf("%sa_%s\n",
1081541Srgrimes			    substr(t[c4], 0, beg - 1), substr(t[c4], beg));
1091541Srgrimes		}
1101541Srgrimes		printf("};\n");
1111541Srgrimes
1121541Srgrimes		# Print out extern declaration.
1131541Srgrimes		printf("extern struct vnodeop_desc %s_desc;\n", name);
1141541Srgrimes
1151541Srgrimes		# Print out inline struct.
1161541Srgrimes		printf("static inline int %s(", uname);
1171541Srgrimes		sep = ", ";
1181541Srgrimes		for (c2 = 0; c2 < c1; ++c2) {
1191541Srgrimes			if (c2 == c1 - 1)
1201541Srgrimes				sep = ")\n";
1211541Srgrimes			c3 = split(a[c2], t);
1221541Srgrimes			beg = match(t[c3], "[^*]");
1231541Srgrimes			end = match(t[c3], ";");
1241541Srgrimes			printf("%s%s", substr(t[c3], beg, end - beg), sep);
1251541Srgrimes		}
1261541Srgrimes		for (c2 = 0; c2 < c1; ++c2) {
1271541Srgrimes			c3 = split(a[c2], t);
1281541Srgrimes			printf("\t");
1291541Srgrimes			if (t[2] ~ "WILLRELE")
1301541Srgrimes				c4 = 3;
1311541Srgrimes			else
1321541Srgrimes				c4 = 2;
1331541Srgrimes			for (; c4 < c3; ++c4)
1341541Srgrimes				printf("%s ", t[c4]);
1351541Srgrimes			beg = match(t[c3], "[^*]");
1361541Srgrimes			printf("%s%s\n",
1371541Srgrimes			    substr(t[c4], 0, beg - 1), substr(t[c4], beg));
1381541Srgrimes		}
1391541Srgrimes		printf("{\n\tstruct %s_args a;\n\n", name);
1401541Srgrimes		printf("\ta.a_desc = VDESC(%s);\n", name);
1411541Srgrimes		for (c2 = 0; c2 < c1; ++c2) {
1421541Srgrimes			c3 = split(a[c2], t);
1431541Srgrimes			printf("\t");
1441541Srgrimes			beg = match(t[c3], "[^*]");
1451541Srgrimes			end = match(t[c3], ";");
1461541Srgrimes			printf("a.a_%s = %s\n",
1471541Srgrimes			    substr(t[c3], beg, end - beg), substr(t[c3], beg));
1481541Srgrimes		}
1491541Srgrimes		c1 = split(a[0], t);
1501541Srgrimes		beg = match(t[c1], "[^*]");
1511541Srgrimes		end = match(t[c1], ";");
1521541Srgrimes		printf("\treturn (VCALL(%s, VOFFSET(%s), &a));\n}\n",
1531541Srgrimes		    substr(t[c1], beg, end - beg), name);
1541541Srgrimes	}' < $SRC >> $HEADER
1551541Srgrimes
1561541Srgrimes# Print out header information for vnode_if.c.
1571541Srgrimescat << END_OF_LEADING_COMMENT > $CFILE
1581541Srgrimes/*
1591541Srgrimes * This file is produced automatically.
1601541Srgrimes * Do not modify anything in here by hand.
1611541Srgrimes *
1621541Srgrimes * Created from @(#)vnode_if.sh	8.1 (Berkeley) 6/10/93
1631541Srgrimes */
1641541Srgrimes
1651541Srgrimes#include <sys/param.h>
1661541Srgrimes#include <sys/mount.h>
1671541Srgrimes#include <sys/vnode.h>
1681541Srgrimes
1691541Srgrimesstruct vnodeop_desc vop_default_desc = {
1701541Srgrimes	0,
1711541Srgrimes	"default",
1721541Srgrimes	0,
1731541Srgrimes	NULL,
1741541Srgrimes	VDESC_NO_OFFSET,
1751541Srgrimes	VDESC_NO_OFFSET,
1761541Srgrimes	VDESC_NO_OFFSET,
1771541Srgrimes	VDESC_NO_OFFSET,
1781541Srgrimes	NULL,
1791541Srgrimes};
1801541Srgrimes
1811541SrgrimesEND_OF_LEADING_COMMENT
1821541Srgrimes
1831541Srgrimes# Awk script to take vnode_if.src and turn it into vnode_if.c.
1841541Srgrimes$AWK 'function kill_surrounding_ws (s) {
1851541Srgrimes		sub (/^[ \t]*/, "", s);
1861541Srgrimes		sub (/[ \t]*$/, "", s);
1871541Srgrimes		return s;
1881541Srgrimes	}
1891541Srgrimes
1901541Srgrimes	function read_args() {
1911541Srgrimes		numargs = 0;
1921541Srgrimes		while (getline ln) {
1931541Srgrimes			if (ln ~ /}/) {
1941541Srgrimes				break;
1951541Srgrimes			};
1961541Srgrimes	
1971541Srgrimes			# Delete comments, if any.
1981541Srgrimes			gsub (/\/\*.*\*\//, "", ln);
1991541Srgrimes			
2001541Srgrimes			# Delete leading/trailing space.
2011541Srgrimes			ln = kill_surrounding_ws(ln);
2021541Srgrimes	
2031541Srgrimes			# Pick off direction.
2041541Srgrimes			if (1 == sub(/^INOUT[ \t]+/, "", ln))
2051541Srgrimes				dir = "INOUT";
2061541Srgrimes			else if (1 == sub(/^IN[ \t]+/, "", ln))
2071541Srgrimes				dir = "IN";
2081541Srgrimes			else if (1 == sub(/^OUT[ \t]+/, "", ln))
2091541Srgrimes				dir = "OUT";
2101541Srgrimes			else
2111541Srgrimes				bail("No IN/OUT direction for \"" ln "\".");
2121541Srgrimes
2131541Srgrimes			# check for "WILLRELE"
2141541Srgrimes			if (1 == sub(/^WILLRELE[ \t]+/, "", ln)) {
2151541Srgrimes				rele = "WILLRELE";
2161541Srgrimes			} else {
2171541Srgrimes				rele = "WONTRELE";
2181541Srgrimes			};
2191541Srgrimes	
2201541Srgrimes			# kill trailing ;
2211541Srgrimes			if (1 != sub (/;$/, "", ln)) {
2221541Srgrimes				bail("Missing end-of-line ; in \"" ln "\".");
2231541Srgrimes			};
2241541Srgrimes	
2251541Srgrimes			# pick off variable name
2261541Srgrimes			if (!(i = match(ln, /[A-Za-z0-9_]+$/))) {
2271541Srgrimes				bail("Missing var name \"a_foo\" in \"" ln "\".");
2281541Srgrimes			};
2291541Srgrimes			arg = substr (ln, i);
2301541Srgrimes			# Want to <<substr(ln, i) = "";>>, but nawk cannot.
2311541Srgrimes			# Hack around this.
2321541Srgrimes			ln = substr(ln, 1, i-1);
2331541Srgrimes	
2341541Srgrimes			# what is left must be type
2351541Srgrimes			# (put clean it up some)
2361541Srgrimes			type = ln;
2371541Srgrimes			gsub (/[ \t]+/, " ", type);   # condense whitespace
2381541Srgrimes			type = kill_surrounding_ws(type);
2391541Srgrimes	
2401541Srgrimes			# (boy this was easier in Perl)
2411541Srgrimes	
2421541Srgrimes			numargs++;
2431541Srgrimes			dirs[numargs] = dir;
2441541Srgrimes			reles[numargs] = rele;
2451541Srgrimes			types[numargs] = type;
2461541Srgrimes			args[numargs] = arg;
2471541Srgrimes		};
2481541Srgrimes	}
2491541Srgrimes
2501541Srgrimes	function generate_operation_vp_offsets() {
2511541Srgrimes		printf ("int %s_vp_offsets[] = {\n", name);
2521541Srgrimes		# as a side effect, figure out the releflags
2531541Srgrimes		releflags = "";
2541541Srgrimes		vpnum = 0;
2551541Srgrimes		for (i=1; i<=numargs; i++) {
2561541Srgrimes			if (types[i] == "struct vnode *") {
2571541Srgrimes				printf ("\tVOPARG_OFFSETOF(struct %s_args,a_%s),\n",
2581541Srgrimes					name, args[i]);
2591541Srgrimes				if (reles[i] == "WILLRELE") {
2601541Srgrimes					releflags = releflags "|VDESC_VP" vpnum "_WILLRELE";
2611541Srgrimes				};
2621541Srgrimes				vpnum++;
2631541Srgrimes			};
2641541Srgrimes		};
2651541Srgrimes		sub (/^\|/, "", releflags);
2661541Srgrimes		print "\tVDESC_NO_OFFSET";
2671541Srgrimes		print "};";
2681541Srgrimes	}
2691541Srgrimes	
2701541Srgrimes	function find_arg_with_type (type) {
2711541Srgrimes		for (i=1; i<=numargs; i++) {
2721541Srgrimes			if (types[i] == type) {
2731541Srgrimes				return "VOPARG_OFFSETOF(struct " name "_args,a_" args[i] ")";
2741541Srgrimes			};
2751541Srgrimes		};
2761541Srgrimes		return "VDESC_NO_OFFSET";
2771541Srgrimes	}
2781541Srgrimes	
2791541Srgrimes	function generate_operation_desc() {
2801541Srgrimes		printf ("struct vnodeop_desc %s_desc = {\n", name);
2811541Srgrimes		# offset
2821541Srgrimes		printf ("\t0,\n");
2831541Srgrimes		# printable name
2841541Srgrimes		printf ("\t\"%s\",\n", name);
2851541Srgrimes		# flags
2861541Srgrimes		vppwillrele = "";
2871541Srgrimes		for (i=1; i<=numargs; i++) {
2881541Srgrimes			if (types[i] == "struct vnode **" &&
2891541Srgrimes				(reles[i] == "WILLRELE")) {
2901541Srgrimes				vppwillrele = "|VDESC_VPP_WILLRELE";
2911541Srgrimes			};
2921541Srgrimes		};
2931541Srgrimes		if (releflags == "") {
2941541Srgrimes			printf ("\t0%s,\n", vppwillrele);
2951541Srgrimes		} else {
2961541Srgrimes			printf ("\t%s%s,\n", releflags, vppwillrele);
2971541Srgrimes		};
2981541Srgrimes		# vp offsets
2991541Srgrimes		printf ("\t%s_vp_offsets,\n", name);
3001541Srgrimes		# vpp (if any)
3011541Srgrimes		printf ("\t%s,\n", find_arg_with_type("struct vnode **"));
3021541Srgrimes		# cred (if any)
3031541Srgrimes		printf ("\t%s,\n", find_arg_with_type("struct ucred *"));
3041541Srgrimes		# proc (if any)
3051541Srgrimes		printf ("\t%s,\n", find_arg_with_type("struct proc *"));
3061541Srgrimes		# componentname
3071541Srgrimes		printf ("\t%s,\n", find_arg_with_type("struct componentname *"));
3081541Srgrimes		# transport layer information
3091541Srgrimes		printf ("\tNULL,\n};\n");
3101541Srgrimes	}
3111541Srgrimes
3121541Srgrimes	NF == 0 || $0 ~ "^#" {
3131541Srgrimes		next;
3141541Srgrimes	}
3151541Srgrimes	{
3161541Srgrimes		# get the function name
3171541Srgrimes		name = $1;
3181541Srgrimes
3191541Srgrimes		# get the function arguments
3201541Srgrimes		read_args();
3211541Srgrimes
3221541Srgrimes		# Print out the vop_F_vp_offsets structure.  This all depends
3231541Srgrimes		# on naming conventions and nothing else.
3241541Srgrimes		generate_operation_vp_offsets();
3251541Srgrimes
3261541Srgrimes		# Print out the vnodeop_desc structure.
3271541Srgrimes		generate_operation_desc();
3281541Srgrimes
3291541Srgrimes		printf "\n";
3301541Srgrimes
3311541Srgrimes	}' < $SRC >> $CFILE
3321541Srgrimes# THINGS THAT DON'T WORK RIGHT YET.
3331541Srgrimes# 
3341541Srgrimes# Two existing BSD vnodeops (bwrite and strategy) don't take any vnodes as
3351541Srgrimes# arguments.  This means that these operations can't function successfully
3361541Srgrimes# through a bypass routine.
3371541Srgrimes#
3381541Srgrimes# Bwrite and strategy will be replaced when the VM page/buffer cache
3391541Srgrimes# integration happens.
3401541Srgrimes#
3411541Srgrimes# To get around this problem for now we handle these ops as special cases.
3421541Srgrimes
3431541Srgrimescat << END_OF_SPECIAL_CASES >> $HEADER
3441541Srgrimes#include <sys/buf.h>
3451541Srgrimesstruct vop_strategy_args {
3461541Srgrimes	struct vnodeop_desc *a_desc;
3471541Srgrimes	struct buf *a_bp;
3481541Srgrimes};
3491541Srgrimesextern struct vnodeop_desc vop_strategy_desc;
3501541Srgrimesstatic inline int VOP_STRATEGY(bp)
3511541Srgrimes	struct buf *bp;
3521541Srgrimes{
3531541Srgrimes	struct vop_strategy_args a;
3541541Srgrimes
3551541Srgrimes	a.a_desc = VDESC(vop_strategy);
3561541Srgrimes	a.a_bp = bp;
3571541Srgrimes	return (VCALL((bp)->b_vp, VOFFSET(vop_strategy), &a));
3581541Srgrimes}
3591541Srgrimes
3601541Srgrimesstruct vop_bwrite_args {
3611541Srgrimes	struct vnodeop_desc *a_desc;
3621541Srgrimes	struct buf *a_bp;
3631541Srgrimes};
3641541Srgrimesextern struct vnodeop_desc vop_bwrite_desc;
3651541Srgrimesstatic inline int VOP_BWRITE(bp)
3661541Srgrimes	struct buf *bp;
3671541Srgrimes{
3681541Srgrimes	struct vop_bwrite_args a;
3691541Srgrimes
3701541Srgrimes	a.a_desc = VDESC(vop_bwrite);
3711541Srgrimes	a.a_bp = bp;
3721541Srgrimes	return (VCALL((bp)->b_vp, VOFFSET(vop_bwrite), &a));
3731541Srgrimes}
3741541SrgrimesEND_OF_SPECIAL_CASES
3751541Srgrimes
3761541Srgrimescat << END_OF_SPECIAL_CASES >> $CFILE
3771541Srgrimesint vop_strategy_vp_offsets[] = {
3781541Srgrimes	VDESC_NO_OFFSET
3791541Srgrimes};
3801541Srgrimesstruct vnodeop_desc vop_strategy_desc = {
3811541Srgrimes	0,
3821541Srgrimes	"vop_strategy",
3831541Srgrimes	0,
3841541Srgrimes	vop_strategy_vp_offsets,
3851541Srgrimes	VDESC_NO_OFFSET,
3861541Srgrimes	VDESC_NO_OFFSET,
3871541Srgrimes	VDESC_NO_OFFSET,
3881541Srgrimes	VDESC_NO_OFFSET,
3891541Srgrimes	NULL,
3901541Srgrimes};
3911541Srgrimesint vop_bwrite_vp_offsets[] = {
3921541Srgrimes	VDESC_NO_OFFSET
3931541Srgrimes};
3941541Srgrimesstruct vnodeop_desc vop_bwrite_desc = {
3951541Srgrimes	0,
3961541Srgrimes	"vop_bwrite",
3971541Srgrimes	0,
3981541Srgrimes	vop_bwrite_vp_offsets,
3991541Srgrimes	VDESC_NO_OFFSET,
4001541Srgrimes	VDESC_NO_OFFSET,
4011541Srgrimes	VDESC_NO_OFFSET,
4021541Srgrimes	VDESC_NO_OFFSET,
4031541Srgrimes	NULL,
4041541Srgrimes};
4051541SrgrimesEND_OF_SPECIAL_CASES
4061541Srgrimes
4071541Srgrimes# Add the vfs_op_descs array to the C file.
4081541Srgrimes$AWK '
4091541Srgrimes	BEGIN {
4101541Srgrimes		printf("\nstruct vnodeop_desc *vfs_op_descs[] = {\n");
4111541Srgrimes		printf("\t&vop_default_desc,	/* MUST BE FIRST */\n");
4121541Srgrimes		printf("\t&vop_strategy_desc,	/* XXX: SPECIAL CASE */\n");
4131541Srgrimes		printf("\t&vop_bwrite_desc,	/* XXX: SPECIAL CASE */\n");
4141541Srgrimes	}
4151541Srgrimes	END {
4161541Srgrimes		printf("\tNULL\n};\n");
4171541Srgrimes	}
4181541Srgrimes	NF == 0 || $0 ~ "^#" {
4191541Srgrimes		next;
4201541Srgrimes	}
4211541Srgrimes	{
4221541Srgrimes		# Get the function name.
4231541Srgrimes		printf("\t&%s_desc,\n", $1);
4241541Srgrimes
4251541Srgrimes		# Skip the function arguments.
4261541Srgrimes		for (;;) {
4271541Srgrimes			if (getline <= 0)
4281541Srgrimes				exit
4291541Srgrimes			if ($0 ~ "^};")
4301541Srgrimes				break;
4311541Srgrimes		}
4321541Srgrimes	}' < $SRC >> $CFILE
4331541Srgrimes
434