vnode_if.awk revision 99482
1#!/usr/bin/awk -f
2
3#
4# Copyright (c) 1992, 1993
5#	The Regents of the University of California.  All rights reserved.
6#
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions
9# are met:
10# 1. Redistributions of source code must retain the above copyright
11#    notice, this list of conditions and the following disclaimer.
12# 2. Redistributions in binary form must reproduce the above copyright
13#    notice, this list of conditions and the following disclaimer in the
14#    documentation and/or other materials provided with the distribution.
15# 3. All advertising materials mentioning features or use of this software
16#    must display the following acknowledgement:
17#	This product includes software developed by the University of
18#	California, Berkeley and its contributors.
19# 4. Neither the name of the University nor the names of its contributors
20#    may be used to endorse or promote products derived from this software
21#    without specific prior written permission.
22#
23# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33# SUCH DAMAGE.
34#
35#	@(#)vnode_if.sh	8.1 (Berkeley) 6/10/93
36# $FreeBSD: head/sys/tools/vnode_if.awk 99482 2002-07-06 03:46:36Z jeff $
37#
38# Script to produce VFS front-end sugar.
39#
40# usage: vnode_if.awk <srcfile> [-c | -h]
41#	(where <srcfile> is currently /sys/kern/vnode_if.src)
42#
43
44function usage()
45{
46	print "usage: vnode_if.awk <srcfile> [-c|-h]";
47	exit 1;
48}
49
50function die(msg, what)
51{
52	printf msg "\n", what > "/dev/stderr";
53	exit 1;
54}
55
56function t_spc(type)
57{
58	# Append a space if the type is not a pointer
59	return (type ~ /\*$/) ? type : type " ";
60}
61
62# These are just for convenience ...
63function printc(s) {print s > cfile;}
64function printh(s) {print s > hfile;}
65
66function add_debug_code(name, arg)
67{
68	if (debug_all_vfs_locks && lockdata[name, arg, "Entry"]) {
69		# Add assertions for locking
70		if (lockdata[name, arg, "Entry"] == "L")
71			printh("\tASSERT_VOP_LOCKED("arg", \""uname"\");");
72		else if (lockdata[name, arg, "Entry"] == "U")
73			printh("\tASSERT_VOP_UNLOCKED("arg", \""uname"\");");
74		else if (0) {
75			# XXX More checks!
76		}
77	}
78}
79
80function add_debug_pre(name)
81{
82	if (debug_all_vfs_locks && lockdata[name, "pre"]) {
83		printh("\t"lockdata[name, "pre"]"(&a);");
84	}
85}
86
87function add_debug_post(name)
88{
89	if (debug_all_vfs_locks && lockdata[name, "post"]) {
90		printh("\t"lockdata[name, "post"]"(&a, rc);");
91	}
92}
93
94function find_arg_with_type (type)
95{
96	for (jj = 0; jj < numargs; jj++) {
97		if (types[jj] == type) {
98			return "VOPARG_OFFSETOF(struct " \
99			    name "_args,a_" args[jj] ")";
100		}
101	}
102
103	return "VDESC_NO_OFFSET";
104}
105
106BEGIN{
107
108# Process the command line
109for (i = 1; i < ARGC; i++) {
110	arg = ARGV[i];
111	if (arg !~ /^-[ch]+$/ && arg !~ /\.src$/)
112		usage();
113	if (arg ~ /^-.*c/)
114		cfile = "vnode_if.c";
115	if (arg ~ /^-.*h/)
116		hfile = "vnode_if.h";
117	if (arg ~ /\.src$/)
118		srcfile = arg;
119}
120ARGC = 1;
121
122if (!cfile && !hfile)
123	exit 0;
124
125if (!srcfile)
126	usage();
127
128debug_all_vfs_locks = (ENVIRON["DEBUG_ALL_VFS_LOCKS"] ~ /[Yy][Ee][Ss]/);
129
130common_head = \
131    "/*\n" \
132    " * This file is produced automatically.\n" \
133    " * Do not modify anything in here by hand.\n" \
134    " *\n" \
135    " * Created from $FreeBSD: head/sys/tools/vnode_if.awk 99482 2002-07-06 03:46:36Z jeff $\n" \
136    " */\n" \
137    "\n";
138
139if (hfile)
140	printh(common_head "extern struct vnodeop_desc vop_default_desc;");
141
142if (cfile) {
143	printc(common_head \
144	    "#include <sys/param.h>\n" \
145	    "#include <sys/systm.h>\n" \
146	    "#include <sys/vnode.h>\n" \
147	    "\n" \
148	    "struct vnodeop_desc vop_default_desc = {\n" \
149	    "	1,\t\t\t/* special case, vop_default => 1 */\n" \
150	    "	\"default\",\n" \
151	    "	0,\n" \
152	    "	NULL,\n" \
153	    "	VDESC_NO_OFFSET,\n" \
154	    "	VDESC_NO_OFFSET,\n" \
155	    "	VDESC_NO_OFFSET,\n" \
156	    "	VDESC_NO_OFFSET,\n" \
157	    "	NULL,\n" \
158	    "};\n");
159}
160
161while ((getline < srcfile) > 0) {
162	if (NF == 0)
163		continue;
164	if ($1 ~ /^#%/) {
165		if (NF != 6  ||  $1 != "#%"  || \
166		    $2 !~ /^[a-z]+$/  ||  $3 !~ /^[a-z]+$/  || \
167		    $4 !~ /^.$/  ||  $5 !~ /^.$/  ||  $6 !~ /^.$/)
168			continue;
169		lockdata["vop_" $2, $3, "Entry"] = $4;
170		lockdata["vop_" $2, $3, "OK"]    = $5;
171		lockdata["vop_" $2, $3, "Error"] = $6;			
172		continue;
173	}
174
175	if ($1 ~ /^#!/) {
176		if (NF != 4 || $1 != "#!")
177			continue;
178		if ($3 != "pre" && $3 != "post")
179			continue;
180		lockdata["vop_" $2, $3] = $4;
181		continue;
182	}
183	if ($1 ~ /^#/)
184		continue;
185
186	# Get the function name.
187	name = $1;
188	uname = toupper(name);
189	# Get the function arguments.
190	for (numargs = 0; ; ++numargs) {
191		if ((getline < srcfile) <= 0) {
192			die("Unable to read through the arguments for \"%s\"",
193			    name);
194		}
195		if ($1 ~ /^\};/)
196			break;
197
198		# Delete comments, if any.
199		gsub (/\/\*.*\*\//, "");
200
201		# Condense whitespace and delete leading/trailing space.
202		gsub(/[[:space:]]+/, " ");
203		sub(/^ /, "");
204		sub(/ $/, "");
205
206		# Pick off direction.
207		if ($1 != "INOUT" && $1 != "IN" && $1 != "OUT")
208			die("No IN/OUT direction for \"%s\".", $0);
209		dirs[numargs] = $1;
210		sub(/^[A-Z]* /, "");
211
212		if ((reles[numargs] = $1) == "WILLRELE")
213			sub(/^[A-Z]* /, "");
214		else
215			reles[numargs] = "WONTRELE";
216
217		# kill trailing ;
218		if (sub(/;$/, "") < 1)
219			die("Missing end-of-line ; in \"%s\".", $0);
220
221		# pick off variable name
222		if ((argp = match($0, /[A-Za-z0-9_]+$/)) < 1)
223			die("Missing var name \"a_foo\" in \"%s\".", $0);
224		args[numargs] = substr($0, argp);
225		$0 = substr($0, 1, argp - 1);
226
227		# what is left must be type
228		# remove trailing space (if any)
229		sub(/ $/, "");
230		types[numargs] = $0;
231	}
232
233	if (hfile) {
234		# Print out the vop_F_args structure.
235		printh("struct "name"_args {\n\tstruct vnodeop_desc *a_desc;");
236		for (i = 0; i < numargs; ++i)
237			printh("\t" t_spc(types[i]) "a_" args[i] ";");
238		printh("};");
239
240		# Print out extern declaration.
241		printh("extern struct vnodeop_desc " name "_desc;");
242
243		# Print out function.
244		printh("static __inline int " uname "(");
245		for (i = 0; i < numargs; ++i) {
246			printh("\t" t_spc(types[i]) args[i] \
247			    (i < numargs - 1 ? "," : ")"));
248		}
249		printh("{\n\tstruct " name "_args a;");
250		printh("\tint rc;");
251		printh("\ta.a_desc = VDESC(" name ");");
252		for (i = 0; i < numargs; ++i)
253			printh("\ta.a_" args[i] " = " args[i] ";");
254		for (i = 0; i < numargs; ++i)
255			add_debug_code(name, args[i]);
256		add_debug_pre(name);
257		printh("\trc = VCALL(" args[0] ", VOFFSET(" name "), &a);");
258		add_debug_post(name);
259		printh("\treturn (rc);\n}");
260	}
261
262	if (cfile) {
263		# Print out the vop_F_vp_offsets structure.  This all depends
264		# on naming conventions and nothing else.
265		printc("static int " name "_vp_offsets[] = {");
266		# as a side effect, figure out the releflags
267		releflags = "";
268		vpnum = 0;
269		for (i = 0; i < numargs; i++) {
270			if (types[i] == "struct vnode *") {
271				printc("\tVOPARG_OFFSETOF(struct " name \
272				    "_args,a_" args[i] "),");
273				if (reles[i] == "WILLRELE") {
274					releflags = releflags \
275					    "|VDESC_VP" vpnum "_WILLRELE";
276				}
277				vpnum++;
278			}
279		}
280
281		sub(/^\|/, "", releflags);
282		printc("\tVDESC_NO_OFFSET");
283		printc("};");
284
285		# Print out the vnodeop_desc structure.
286		printc("struct vnodeop_desc " name "_desc = {");
287		# offset
288		printc("\t0,");
289		# printable name
290		printc("\t\"" name "\",");
291		# flags
292		vppwillrele = "";
293		for (i = 0; i < numargs; i++) {
294			if (types[i] == "struct vnode **" && \
295			    reles[i] == "WILLRELE") {
296				vppwillrele = "|VDESC_VPP_WILLRELE";
297			}
298		}
299
300		if (!releflags)
301			releflags = "0";
302		printc("\t" releflags vppwillrele ",");
303
304		# vp offsets
305		printc("\t" name "_vp_offsets,");
306		# vpp (if any)
307		printc("\t" find_arg_with_type("struct vnode **") ",");
308		# cred (if any)
309		printc("\t" find_arg_with_type("struct ucred *") ",");
310		# thread (if any)
311		printc("\t" find_arg_with_type("struct thread *") ",");
312		# componentname
313		printc("\t" find_arg_with_type("struct componentname *") ",");
314		# transport layer information
315		printc("\tNULL,\n};\n");
316	}
317}
318 
319if (hfile)
320	close(hfile);
321if (cfile)
322	close(cfile);
323close(srcfile);
324
325exit 0;
326
327}
328