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