vnode_if.awk revision 116614
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 116614 2003-06-20 12:15:37Z se $
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, pos)
67{
68	if (arg == "vpp")
69		arg = "*vpp";
70	if (lockdata[name, arg, pos]) {
71		printh("\tASSERT_VI_UNLOCKED("arg", \""uname"\");");
72		# Add assertions for locking
73		if (lockdata[name, arg, pos] == "L")
74			printh("\tASSERT_VOP_LOCKED("arg", \""uname"\");");
75		else if (lockdata[name, arg, pos] == "U")
76			printh("\tASSERT_VOP_UNLOCKED("arg", \""uname"\");");
77		else if (0) {
78			# XXX More checks!
79		}
80	}
81}
82
83function add_debug_pre(name)
84{
85	if (lockdata[name, "pre"]) {
86		printh("#ifdef	DEBUG_VFS_LOCKS");
87		printh("\t"lockdata[name, "pre"]"(&a);");
88		printh("#endif");
89	}
90}
91
92function add_debug_post(name)
93{
94	if (lockdata[name, "post"]) {
95		printh("#ifdef	DEBUG_VFS_LOCKS");
96		printh("\t"lockdata[name, "post"]"(&a, rc);");
97		printh("#endif");
98	}
99}
100
101function find_arg_with_type (type)
102{
103	for (jj = 0; jj < numargs; jj++) {
104		if (types[jj] == type) {
105			return "VOPARG_OFFSETOF(struct " \
106			    name "_args,a_" args[jj] ")";
107		}
108	}
109
110	return "VDESC_NO_OFFSET";
111}
112
113BEGIN{
114
115# Process the command line
116for (i = 1; i < ARGC; i++) {
117	arg = ARGV[i];
118	if (arg !~ /^-[ch]+$/ && arg !~ /\.src$/)
119		usage();
120	if (arg ~ /^-.*c/)
121		cfile = "vnode_if.c";
122	if (arg ~ /^-.*h/)
123		hfile = "vnode_if.h";
124	if (arg ~ /\.src$/)
125		srcfile = arg;
126}
127ARGC = 1;
128
129if (!cfile && !hfile)
130	exit 0;
131
132if (!srcfile)
133	usage();
134
135common_head = \
136    "/*\n" \
137    " * This file is produced automatically.\n" \
138    " * Do not modify anything in here by hand.\n" \
139    " *\n" \
140    " * Created from $FreeBSD: head/sys/tools/vnode_if.awk 116614 2003-06-20 12:15:37Z se $\n" \
141    " */\n" \
142    "\n";
143
144if (hfile)
145	printh(common_head "extern struct vnodeop_desc vop_default_desc;");
146
147if (cfile) {
148	printc(common_head \
149	    "#include <sys/param.h>\n" \
150	    "#include <sys/systm.h>\n" \
151	    "#include <sys/vnode.h>\n" \
152	    "\n" \
153	    "struct vnodeop_desc vop_default_desc = {\n" \
154	    "	1,\t\t\t/* special case, vop_default => 1 */\n" \
155	    "	\"default\",\n" \
156	    "	0,\n" \
157	    "	NULL,\n" \
158	    "	VDESC_NO_OFFSET,\n" \
159	    "	VDESC_NO_OFFSET,\n" \
160	    "	VDESC_NO_OFFSET,\n" \
161	    "	VDESC_NO_OFFSET,\n" \
162	    "	NULL,\n" \
163	    "};\n");
164}
165
166while ((getline < srcfile) > 0) {
167	if (NF == 0)
168		continue;
169	if ($1 ~ /^#%/) {
170		if (NF != 6  ||  $1 != "#%"  || \
171		    $2 !~ /^[a-z]+$/  ||  $3 !~ /^[a-z]+$/  || \
172		    $4 !~ /^.$/  ||  $5 !~ /^.$/  ||  $6 !~ /^.$/)
173			continue;
174		if ($3 == "vpp")
175			$3 = "*vpp";
176		lockdata["vop_" $2, $3, "Entry"] = $4;
177		lockdata["vop_" $2, $3, "OK"]    = $5;
178		lockdata["vop_" $2, $3, "Error"] = $6;			
179		continue;
180	}
181
182	if ($1 ~ /^#!/) {
183		if (NF != 4 || $1 != "#!")
184			continue;
185		if ($3 != "pre" && $3 != "post")
186			continue;
187		lockdata["vop_" $2, $3] = $4;
188		continue;
189	}
190	if ($1 ~ /^#/)
191		continue;
192
193	# Get the function name.
194	name = $1;
195	uname = toupper(name);
196
197	# Start constructing a ktrpoint string
198	ctrstr = "\"" uname;
199	# Get the function arguments.
200	for (numargs = 0; ; ++numargs) {
201		if ((getline < srcfile) <= 0) {
202			die("Unable to read through the arguments for \"%s\"",
203			    name);
204		}
205		if ($1 ~ /^\};/)
206			break;
207
208		# Delete comments, if any.
209		gsub (/\/\*.*\*\//, "");
210
211		# Condense whitespace and delete leading/trailing space.
212		gsub(/[[:space:]]+/, " ");
213		sub(/^ /, "");
214		sub(/ $/, "");
215
216		# Pick off direction.
217		if ($1 != "INOUT" && $1 != "IN" && $1 != "OUT")
218			die("No IN/OUT direction for \"%s\".", $0);
219		dirs[numargs] = $1;
220		sub(/^[A-Z]* /, "");
221
222		if ((reles[numargs] = $1) == "WILLRELE")
223			sub(/^[A-Z]* /, "");
224		else
225			reles[numargs] = "WONTRELE";
226
227		# kill trailing ;
228		if (sub(/;$/, "") < 1)
229			die("Missing end-of-line ; in \"%s\".", $0);
230
231		# pick off variable name
232		if ((argp = match($0, /[A-Za-z0-9_]+$/)) < 1)
233			die("Missing var name \"a_foo\" in \"%s\".", $0);
234		args[numargs] = substr($0, argp);
235		$0 = substr($0, 1, argp - 1);
236
237		# what is left must be type
238		# remove trailing space (if any)
239		sub(/ $/, "");
240		types[numargs] = $0;
241
242		# We can do a maximum of 6 arguments to CTR*
243		if (numargs <= 6) {
244			if (numargs == 0)
245				ctrstr = ctrstr "(" args[numargs];
246			else
247				ctrstr = ctrstr ", " args[numargs];
248			if (types[numargs] ~ /\*/)
249				ctrstr = ctrstr " 0x%lX";
250			else
251				ctrstr = ctrstr " %ld";
252		}
253	}
254	if (numargs > 6)
255		ctrargs = 6;
256	else
257		ctrargs = numargs;
258	ctrstr = "\tCTR" ctrargs "(KTR_VOP, " ctrstr ")\"";
259	for (i = 0; i < ctrargs; ++i)
260		ctrstr = ctrstr ", " args[i];
261	ctrstr = ctrstr ");";
262
263	if (hfile) {
264		# Print out the vop_F_args structure.
265		printh("struct "name"_args {\n\tstruct vnodeop_desc *a_desc;");
266		for (i = 0; i < numargs; ++i)
267			printh("\t" t_spc(types[i]) "a_" args[i] ";");
268		printh("};");
269
270		# Print out extern declaration.
271		printh("extern struct vnodeop_desc " name "_desc;");
272
273		# Print out function.
274		printh("static __inline int " uname "(");
275		for (i = 0; i < numargs; ++i) {
276			printh("\t" t_spc(types[i]) args[i] \
277			    (i < numargs - 1 ? "," : ")"));
278		}
279		printh("{\n\tstruct " name "_args a;");
280		printh("\tint rc;");
281		printh("\ta.a_desc = VDESC(" name ");");
282		for (i = 0; i < numargs; ++i)
283			printh("\ta.a_" args[i] " = " args[i] ";");
284		for (i = 0; i < numargs; ++i)
285			add_debug_code(name, args[i], "Entry");
286		add_debug_pre(name);
287		printh("\trc = VCALL(" args[0] ", VOFFSET(" name "), &a);");
288		printh(ctrstr);
289		printh("if (rc == 0) {");
290		for (i = 0; i < numargs; ++i)
291			add_debug_code(name, args[i], "OK");
292		printh("} else {");
293		for (i = 0; i < numargs; ++i)
294			add_debug_code(name, args[i], "Error");
295		printh("}");
296		add_debug_post(name);
297		printh("\treturn (rc);\n}");
298	}
299
300	if (cfile) {
301		# Print out the vop_F_vp_offsets structure.  This all depends
302		# on naming conventions and nothing else.
303		printc("static int " name "_vp_offsets[] = {");
304		# as a side effect, figure out the releflags
305		releflags = "";
306		vpnum = 0;
307		for (i = 0; i < numargs; i++) {
308			if (types[i] == "struct vnode *") {
309				printc("\tVOPARG_OFFSETOF(struct " name \
310				    "_args,a_" args[i] "),");
311				if (reles[i] == "WILLRELE") {
312					releflags = releflags \
313					    "|VDESC_VP" vpnum "_WILLRELE";
314				}
315				vpnum++;
316			}
317		}
318
319		sub(/^\|/, "", releflags);
320		printc("\tVDESC_NO_OFFSET");
321		printc("};");
322
323		# Print out the vnodeop_desc structure.
324		printc("struct vnodeop_desc " name "_desc = {");
325		# offset
326		printc("\t0,");
327		# printable name
328		printc("\t\"" name "\",");
329		# flags
330		vppwillrele = "";
331		for (i = 0; i < numargs; i++) {
332			if (types[i] == "struct vnode **" && \
333			    reles[i] == "WILLRELE") {
334				vppwillrele = "|VDESC_VPP_WILLRELE";
335			}
336		}
337
338		if (!releflags)
339			releflags = "0";
340		printc("\t" releflags vppwillrele ",");
341
342		# vp offsets
343		printc("\t" name "_vp_offsets,");
344		# vpp (if any)
345		printc("\t" find_arg_with_type("struct vnode **") ",");
346		# cred (if any)
347		printc("\t" find_arg_with_type("struct ucred *") ",");
348		# thread (if any)
349		printc("\t" find_arg_with_type("struct thread *") ",");
350		# componentname
351		printc("\t" find_arg_with_type("struct componentname *") ",");
352		# transport layer information
353		printc("\tNULL,\n};\n");
354	}
355}
356 
357if (hfile)
358	close(hfile);
359if (cfile)
360	close(cfile);
361close(srcfile);
362
363exit 0;
364
365}
366