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