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