3 # Copyright (c) 1992, 1993
4 # The Regents of the University of California. All rights reserved.
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
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.
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
34 # From @(#)vnode_if.sh 8.1 (Berkeley) 6/10/93
35 # From @(#)makedevops.sh 1.1 1998/06/14 13:53:12 dfr Exp $
36 # From @(#)makedevops.sh ?.? 1998/10/05
37 # From src/sys/kern/makedevops.pl,v 1.12 1999/11/22 14:40:04 n_hibma Exp
42 # Script to produce kobj front-end sugar.
47 use vars qw($opt_c $opt_d $opt_h $opt_l $opt_p);
57 # Process the command line
62 warn "Will produce files in original not in current directory"
65 if (defined($opt_l)) {
66 die("Invalid line width '$opt_l'\n")
67 unless ($opt_l =~ m/^\d*$/ && $opt_l > 0);
69 warn "Line width set to $line_width"
73 foreach my $arg (@ARGV) {
74 die("Invalid input filename '$arg'\n")
75 unless ($arg =~ m/\.m$/);
78 push @filenames, $arg;
82 # Validate the command line parameters
85 unless ($opt_c or $opt_h)
86 and $#filenames != -1;
88 # FIXME should be able to do this more easily
90 $tmpdir = $ENV{'TMPDIR'}; # environment variables
93 $tmpdir = $ENV{'TEMP'}
95 $tmpdir = '/tmp' # look for a physical directory
96 if !$tmpdir and -d '/tmp';
98 if !$tmpdir and -d '/usr/tmp';
100 if !$tmpdir and -d '/var/tmp';
101 $tmpdir = '.' # give up and use current dir
104 foreach my $src (@filenames) {
105 # Names of the created files
106 my $ctmpname = "$tmpdir/ctmp.$$";
107 my $htmpname = "$tmpdir/htmp.$$";
109 my ($name, $path, $suffix) = &fileparse($src, '.m');
113 my $cfilename="$path/$name.c";
114 my $hfilename="$path/$name.h";
116 warn "Processing from $src to $cfilename / $hfilename via $ctmpname / $htmpname"
119 die "Could not open $src for reading, $!"
120 if !open SRC, "$src";
121 die "Could not open $ctmpname for writing, $!"
122 if $opt_c and !open CFILE, ">$ctmpname";
123 die "Could not open $htmpname for writing, $!"
124 if $opt_h and !open HFILE, ">$htmpname";
127 # Produce the header of the C file
130 print CFILE " * This file is produced automatically.\n";
131 print CFILE " * Do not modify anything in here by hand.\n";
133 print CFILE " * Created from source file\n";
134 print CFILE " * $src\n";
135 print CFILE " * with\n";
136 print CFILE " * $0\n";
138 print CFILE " * See the source file for legal information\n";
141 print CFILE "#include <sys/param.h>\n";
142 print CFILE "#include <sys/queue.h>\n";
143 print CFILE "#include <sys/kernel.h>\n";
144 print CFILE "#include <sys/kobj.h>\n";
148 # Produce the header of the H file
151 print HFILE " * This file is produced automatically.\n";
152 print HFILE " * Do not modify anything in here by hand.\n";
154 print HFILE " * Created from source file\n";
155 print HFILE " * $src\n";
156 print HFILE " * with\n";
157 print HFILE " * $0\n";
159 print HFILE " * See the source file for legal information\n";
164 my %methods = (); # clear list of methods
166 my @defaultmethods = ();
168 my $error = 0; # to signal clean up and gerror setting
170 LINE: while (my $line = <SRC>) {
173 # take special notice of include directives.
175 if ($line =~ m/^#\s*include\s+(["<])([^">]+)([">]).*/i) {
176 warn "Included file: $1$2" . ($1 eq '<'? '>':'"')
178 print CFILE "#include $1$2" . ($1 eq '<'? '>':'"') . "\n"
182 $line =~ s/#.*//; # remove comments
183 $line =~ s/^\s+//; # remove leading ...
184 $line =~ s/\s+$//; # remove trailing whitespace
186 if ($line =~ m/^$/) { # skip empty lines
188 } elsif ($line =~ m/^INTERFACE\s*([^\s;]*)(\s*;?)/i) {
191 unless ($intname =~ m/^[a-z_][a-z0-9_]*$/) {
194 warn "$src:$lineno: Invalid interface name '$intname', use [a-z_][a-z0-9_]*";
199 warn "$src:$lineno: semicolon missing at end of line, no problem"
200 if $semicolon !~ s/;$//;
202 warn "Interface $intname"
205 print HFILE '#ifndef _'.$intname."_if_h_\n"
207 print HFILE '#define _'.$intname."_if_h_\n\n"
209 print CFILE '#include "'.$intname.'_if.h"'."\n\n"
211 } elsif ($line =~ m/^CODE\s*{$/i) {
215 my $indent = $1; # find the indent used
216 while ($line !~ m/^}/) {
217 $line =~ s/^$indent//g; # remove the indent
222 print CFILE "\n".$code."\n"
224 } elsif ($line =~ m/^HEADER\s*{$/i) {
228 my $indent = $1; # find the indent used
229 while ($line !~ m/^}/) {
230 $line =~ s/^$indent//g; # remove the indent
237 } elsif ($line =~ m/^(STATIC|)METHOD/i) {
240 # Get the return type function name and delete that from
241 # the line. What is left is the possibly first function argument
242 # if it is on the same line.
245 warn "$src:$lineno: No interface name defined";
249 $line =~ s/^(STATIC|)METHOD\s+([^\{]+?)\s*\{\s*//i;
251 my @ret = split m/\s+/, $2;
252 $name = pop @ret; # last element is name of method
253 my $ret = join(" ", @ret); # return type
255 warn "Method: name=$name return type=$ret"
258 if (!$name or !$ret) {
261 warn "$src:$lineno: Invalid method specification";
266 unless ($name =~ m/^[a-z_][a-z_0-9]*$/) {
269 warn "$src:$lineno: Invalid method name '$name', use [a-z_][a-z0-9_]*";
274 if (defined($methods{$name})) {
275 warn "$src:$lineno: Duplicate method name";
280 $methods{$name} = $name;
283 while ($line !~ m/}/ and $line .= <SRC>) {
288 if ($line !~ s/};?(.*)//) { # remove first '}' and trailing garbage
289 # The '}' was not there (the rest is optional), so complain
290 warn "$src:$lineno: Premature end of file";
295 if ($extra =~ /\s*DEFAULT\s*([a-zA-Z_][a-zA-Z_0-9]*)\s*;/) {
298 warn "$src:$lineno: Ignored '$1'" # warn about garbage at end of line
302 # Create a list of variables without the types prepended
304 $line =~ s/^\s+//; # remove leading ...
305 $line =~ s/\s+$//; # ... and trailing whitespace
306 $line =~ s/\s+/ /g; # remove double spaces
308 my @arguments = split m/\s*;\s*/, $line;
309 my @varnames = (); # list of varnames
310 foreach my $argument (@arguments) {
311 next # skip argument if argument is empty
314 my @ar = split m/[*\s]+/, $argument;
315 if ($#ar == 0) { # only 1 word in argument?
316 warn "$src:$lineno: no type for '$argument'";
321 push @varnames, $ar[-1]; # last element is name of variable
324 warn 'Arguments: ' . join(', ', @arguments) . "\n"
325 . 'Varnames: ' . join(', ', @varnames)
328 my $mname = $intname.'_'.$name; # method name
329 my $umname = uc($mname); # uppercase method name
331 my $arguments = join(", ", @arguments);
332 my $firstvar = $varnames[0];
333 my $varnames = join(", ", @varnames);
335 $default = "0" if $default eq "";
336 push @defaultmethods, $default;
339 # the method description
340 print HFILE "extern struct kobjop_desc $mname\_desc;\n";
342 my $prototype = "typedef $ret $mname\_t(";
343 print HFILE &format_line("$prototype$arguments);",
345 ',',' ' x length($prototype))
350 # Print out the method desc
351 print CFILE "struct kobjop_desc $mname\_desc = {\n";
352 print CFILE "\t0, (kobjop_t) $default\n";
353 print CFILE "};\n\n";
357 # Print out the method itself
358 if (0) { # haven't chosen the format yet
359 print HFILE "static __inline $ret $umname($varnames)\n";
360 print HFILE "\t".join(";\n\t", @arguments).";\n";
362 my $prototype = "static __inline $ret $umname(";
363 print HFILE &format_line("$prototype$arguments)",
365 ',', ' ' x length($prototype)) . "\n";
368 print HFILE "\tkobjop_t _m;\n";
370 print HFILE "\tKOBJOPLOOKUP($firstvar->ops,$mname);\n";
372 print HFILE "\tKOBJOPLOOKUP(((kobj_t)$firstvar)->ops,$mname);\n";
375 if ($ret ne 'void') {
376 print HFILE "return ";
378 print HFILE "(($mname\_t *) _m)($varnames);\n";
384 warn "$src:$lineno: Invalid line encountered";
390 # print the final '#endif' in the header file
392 print HFILE "#endif /* _".$intname."_if_h_ */\n"
404 ($rc = system("mv $ctmpname $cfilename"))
405 and warn "mv $ctmpname $cfilename failed, $rc";
409 ($rc = system("mv $htmpname $hfilename"))
410 and warn "mv $htmpname $hfilename failed, $rc";
413 warn 'Output skipped';
414 ($rc = system("rm -f $htmpname $ctmpname"))
415 and warn "rm -f $htmpname $ctmpname failed, $rc";
425 "usage: $0 [-d] [-p] [-l <nr>] [-c|-h] srcfile",
426 "where -c produce only .c files",
427 " -h produce only .h files",
428 " -p use the path component in the source file for destination dir",
429 " -l set line width for output files [80]",
430 " -d switch on debugging")
435 my ($line, $maxlength, $break, $new_end, $new_start) = @_;
439 while (length($line) > $maxlength
440 and ($i = rindex $line, $break, $maxlength-length($new_end)) != -1) {
441 $rline .= substr($line, 0, $i) . $new_end . "\n";
442 $line = $new_start . substr($line, $i+length($break));
445 return $rline . $line;
448 # This routine is a crude replacement for one in File::Basename. We
449 # cannot use any library code because it fouls up the Perl bootstrap
450 # when we update a perl version. MarkM
453 my ($filename, @suffix) = @_;
454 my ($dir, $name, $type, $i);
457 foreach $i (@suffix) {
458 if ($filename =~ m|$i$|) {
459 $filename =~ s|$i$||;
463 if ($filename =~ m|/|) {
464 $filename =~ m|([^/]*)$|;
472 ($name, $dir, $type);