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