* Add this nice filesystem testing tool that I've recently
[dragonfly.git] / sys / kern / vnode_if.pl
1 #!/usr/bin/perl
2 eval '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: src/sys/kern/vnode_if.pl,v 1.21.2.1 2002/01/06 06:46:21 silby Exp $
39 # $DragonFly: src/sys/kern/Attic/vnode_if.pl,v 1.3 2003/08/26 21:09:02 rob Exp $
40 #
41 # Script to produce VFS front-end sugar.
42 #
43 # usage: vnode_if.pl srcfile
44 #       (where srcfile is currently /sys/kern/vnode_if.src)
45 #
46
47 my %lockdata;
48
49 $cfile = 0;
50 $hfile = 0;
51
52 # Process the command line
53 #
54 while ($arg = shift @ARGV) {
55     if ($arg eq '-c') {
56         $cfile = 1;
57     } elsif ($arg eq '-h') {
58         $hfile = 1;
59     } elsif ($arg eq '-ch' || $arg eq '-hc') {
60         $cfile = 1;
61         $hfile = 1;
62     } elsif ($arg =~ m/\.src$/) {
63         $SRC = $arg;
64     } else {
65         print "usage: vnode_if.pl [-c] [-h] srcfile\n";
66         exit(1);
67     }
68 }
69 if (!$cfile and !$hfile) {
70     exit(0);            # nothing asked for..
71 }
72
73 # Names of the created files.
74 $CFILE='vnode_if.c';
75 $HEADER='vnode_if.h';
76
77 open(SRC,     "<$SRC")   || die "Unable to open input file";
78
79 if ($hfile) {
80     open(HEADER, ">$HEADER") || die "Unable to create $HEADER";
81     # Print out header information for vnode_if.h.
82     print HEADER <<'END_OF_LEADING_COMMENT'
83 /*
84  * This file is produced automatically.
85  * Do not modify anything in here by hand.
86  *
87  * Created from $FreeBSD: src/sys/kern/vnode_if.pl,v 1.21.2.1 2002/01/06 06:46:21 silby Exp $
88  */
89
90 extern struct vnodeop_desc vop_default_desc;
91 END_OF_LEADING_COMMENT
92     ;
93 }
94
95 if ($cfile) {
96     open(CFILE,   ">$CFILE") || die "Unable to create $CFILE";
97     # Print out header information for vnode_if.c.
98     print CFILE <<'END_OF_LEADING_COMMENT'
99 /*
100  * This file is produced automatically.
101  * Do not modify anything in here by hand.
102  *
103  * Created from $FreeBSD: src/sys/kern/vnode_if.pl,v 1.21.2.1 2002/01/06 06:46:21 silby Exp $
104  */
105
106 #include <sys/param.h>
107 #include <sys/vnode.h>
108
109 struct vnodeop_desc vop_default_desc = {
110         1,                      /* special case, vop_default => 1 */
111         "default",
112         0,
113         NULL,
114         VDESC_NO_OFFSET,
115         VDESC_NO_OFFSET,
116         VDESC_NO_OFFSET,
117         VDESC_NO_OFFSET,
118         NULL,
119 };
120
121 END_OF_LEADING_COMMENT
122     ;
123 }
124
125 line: while (<SRC>) {
126     chop;       # strip record separator
127     @Fld = split ' ';
128     if (@Fld == 0) {
129         next line;
130     }
131     if (/^#/) {
132         if (!/^#%\s+([a-z]+)\s+([a-z]+)\s+(.)\s(.)\s(.)/) {
133             next;
134         }
135         if (!defined($lockdata{"vop_$1"})) {
136             $lockdata{"vop_$1"} = {};
137         }
138         $lockdata{"vop_$1"}->{$2} = {
139             'Entry' => $3,
140             'OK'    => $4,
141             'Error' => $5,
142         };
143         next;
144     }
145
146     # Get the function name.
147     $name = $Fld[0];
148     $uname = uc($name);
149
150     # Get the function arguments.
151     for ($numargs = 0; ; ++$numargs) {
152         if ($ln = <SRC>) {
153             chomp;
154         } else {
155             die "Unable to read through the arguments for \"$name\"";
156         }
157         if ($ln =~ /^\};/) {
158             last;
159         }
160         # For the header file
161         $a{$numargs} = $ln;
162
163         # The rest of this loop is for the C file
164         # Delete comments, if any.
165         $ln =~ s/\/\*.*\*\///g;
166
167         # Delete leading/trailing space.
168         $ln =~ s/^\s*(.*?)\s*$/$1/;
169
170         # Pick off direction.
171         if ($ln =~ s/^INOUT\s+//) {
172             $dir = 'INOUT';
173         } elsif ($ln =~ s/^IN\s+//) {
174             $dir = 'IN';
175         } elsif ($ln =~ s/^OUT\s+//) {
176             $dir = 'OUT';
177         } else {
178              die "No IN/OUT direction for \"$ln\".";
179         }
180         if ($ln =~ s/^WILLRELE\s+//) {
181             $rele = 'WILLRELE';
182         } else {
183             $rele = 'WONTRELE';
184         }
185
186         # kill trailing ;
187         if ($ln !~ s/;$//) {
188             &bail("Missing end-of-line ; in \"$ln\".");
189         }
190
191         # pick off variable name
192         if ($ln !~ s/([A-Za-z0-9_]+)$//) {
193             &bail("Missing var name \"a_foo\" in \"$ln\".");
194         }
195         $arg = $1;
196
197         # what is left must be type
198         # (put clean it up some)
199         $type = $ln;
200         # condense whitespace
201         $type =~ s/\s+/ /g;
202         $type =~ s/^\s*(.*?)\s*$/$1/;
203
204         $dirs{$numargs} = $dir;
205         $reles{$numargs} = $rele;
206         $types{$numargs} = $type;
207         $args{$numargs} = $arg;
208     }
209
210     if ($hfile) {
211         # Print out the vop_F_args structure.
212         print HEADER "struct ${name}_args {\n\tstruct vnodeop_desc *a_desc;\n";
213         for ($c2 = 0; $c2 < $numargs; ++$c2) {
214             $a{$c2} =~ /^\s*(INOUT|OUT|IN)(\s+WILLRELE)?\s+(.*?)\s+(\**)(\S*\;)/;
215             print HEADER "\t$3 $4a_$5\n", 
216         }
217         print HEADER "};\n";
218
219         # Print out extern declaration.
220         print HEADER "extern struct vnodeop_desc ${name}_desc;\n";
221
222         # Print out prototype.
223         print HEADER "static __inline int ${uname} (\n";
224         for ($c2 = 0; $c2 < $numargs; ++$c2) {
225             $a{$c2} =~ /^\s*(INOUT|OUT|IN)(\s+WILLRELE)?\s+(.*?)\s+(\**\S*)\;/;
226             print HEADER "\t$3 $4" .
227                 ($c2 < $numargs-1 ? "," : ");") . "\n";
228         }
229
230         # Print out function.
231         print HEADER "static __inline int ${uname}(";
232         for ($c2 = 0; $c2 < $numargs; ++$c2) {
233             $a{$c2} =~ /\**([^;\s]*)\;[^\s]*$/;
234             print HEADER "$1" . ($c2 < $numargs - 1 ? ', ' : ")\n");
235         }
236         for ($c2 = 0; $c2 < $numargs; ++$c2) {
237             $a{$c2} =~ /^\s*(INOUT|OUT|IN)(\s+WILLRELE)?\s+(.*?)\s+(\**\S*\;)/;
238             print HEADER "\t$3 $4\n";
239         }
240         print HEADER "{\n\tstruct ${name}_args a;\n";
241         print HEADER "\tint rc;\n";
242         print HEADER "\ta.a_desc = VDESC(${name});\n";
243         for ($c2 = 0; $c2 < $numargs; ++$c2) {
244             $a{$c2} =~ /(\**)([^;\s]*)([^\s]*)$/;
245             print HEADER "\ta.a_$2 = $2$3\n", 
246         }
247         for ($c2 = 0; $c2 < $numargs; ++$c2) {
248             if (!exists($args{$c2})) {
249                 die "Internal error";
250             }
251             if (exists($lockdata{$name}) &&
252                 exists($lockdata{$name}->{$args{$c2}})) {
253                 if ($ENV{'DEBUG_ALL_VFS_LOCKS'} =~ /yes/i) {
254                     # Add assertions for locking
255                     if ($lockdata{$name}->{$args{$c2}}->{Entry} eq "L") {
256                         print HEADER
257                             "\tASSERT_VOP_LOCKED($args{$c2}, \"$uname\");\n";
258                     } elsif ($lockdata{$name}->{$args{$c2}}->{Entry} eq "U") {
259                         print HEADER
260                             "\tASSERT_VOP_UNLOCKED($args{$c2}, \"$uname\");\n";
261                     } elsif (0) {
262                         # XXX More checks!
263                     }
264                 }
265             }
266         }
267         $a{0} =~ /\s\**([^;\s]*);/;
268         print HEADER "\trc = VCALL($1, VOFFSET(${name}), &a);\n";
269         print HEADER "\treturn (rc);\n";
270         print HEADER "}\n";
271     }
272
273
274     if ($cfile) {
275         # Print out the vop_F_vp_offsets structure.  This all depends
276         # on naming conventions and nothing else.
277         printf CFILE "static int %s_vp_offsets[] = {\n", $name;
278         # as a side effect, figure out the releflags
279         $releflags = '';
280         $vpnum = 0;
281         for ($i = 0; $i < $numargs; $i++) {
282             if ($types{$i} eq 'struct vnode *') {
283                 printf CFILE "\tVOPARG_OFFSETOF(struct %s_args,a_%s),\n", 
284                 $name, $args{$i};
285                 if ($reles{$i} eq 'WILLRELE') {
286                     $releflags = $releflags . '|VDESC_VP' . $vpnum . '_WILLRELE';
287                 }
288
289                 $vpnum++;
290             }
291         }
292
293         $releflags =~ s/^\|//;
294         print CFILE "\tVDESC_NO_OFFSET\n";
295         print CFILE "};\n";
296
297         # Print out the vnodeop_desc structure.
298         print CFILE "struct vnodeop_desc ${name}_desc = {\n";
299         # offset
300         print CFILE "\t0,\n";
301         # printable name
302         printf CFILE "\t\"%s\",\n", $name;
303         # flags
304         $vppwillrele = '';
305         for ($i = 0; $i < $numargs; $i++) {
306             if ($types{$i} eq 'struct vnode **' && 
307                 ($reles{$i} eq 'WILLRELE')) {
308                 $vppwillrele = '|VDESC_VPP_WILLRELE';
309             }
310         }
311
312         if ($releflags eq '') {
313             printf CFILE "\t0%s,\n", $vppwillrele;
314         }
315         else {
316             printf CFILE "\t%s%s,\n", $releflags, $vppwillrele;
317         }
318
319         # vp offsets
320         printf CFILE "\t%s_vp_offsets,\n", $name;
321         # vpp (if any)
322         printf CFILE "\t%s,\n", &find_arg_with_type('struct vnode **');
323         # cred (if any)
324         printf CFILE "\t%s,\n", &find_arg_with_type('struct ucred *');
325         # proc (if any)
326         printf CFILE "\t%s,\n", &find_arg_with_type('struct proc *');
327         # componentname
328         printf CFILE "\t%s,\n", &find_arg_with_type('struct componentname *');
329         # transport layer information
330         print CFILE "\tNULL,\n};\n\n";
331     }
332 }
333  
334 if ($hfile) {
335     close(HEADER) || die "Unable to close $HEADER";
336 }
337 if ($cfile) {
338     close(CFILE)  || die "Unable to close $CFILE";
339 }
340 close(SRC) || die;
341
342 exit 0;
343
344 sub find_arg_with_type {
345     my $type = shift;
346     my $i;
347
348     for ($i=0; $i < $numargs; $i++) {
349         if ($types{$i} eq $type) {
350             return "VOPARG_OFFSETOF(struct ${name}_args,a_" . $args{$i} . ")";
351         }
352     }
353
354     return "VDESC_NO_OFFSET";
355 }