makedevops.pl

来自「基于组件方式开发操作系统的OSKIT源代码」· PL 代码 · 共 423 行

PL
423
字号
#!/usr/bin/perl## Copyright (c) 1992, 1993#	The Regents of the University of California.  All rights reserved.## Redistribution and use in source and binary forms, with or without# modification, are permitted provided that the following conditions# are met:# 1. Redistributions of source code must retain the above copyright#    notice, this list of conditions and the following disclaimer.# 2. Redistributions in binary form must reproduce the above copyright#    notice, this list of conditions and the following disclaimer in the#    documentation and/or other materials provided with the distribution.# 3. All advertising materials mentioning features or use of this software#    must display the following acknowledgement:#	This product includes software developed by the University of#	California, Berkeley and its contributors.# 4. Neither the name of the University nor the names of its contributors#    may be used to endorse or promote products derived from this software#    without specific prior written permission.## THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF# SUCH DAMAGE.## From @(#)vnode_if.sh	8.1 (Berkeley) 6/10/93# From @(#)makedevops.sh 1.1 1998/06/14 13:53:12 dfr Exp $# From @(#)makedevops.sh ?.? 1998/10/05## $Id: makedevops.pl,v 1.2.2.1 1999/05/05 13:24:14 markm Exp $## Script to produce device front-end sugar.#$debug = 0;$cfile = 0;          # by default do not produce any file type$hfile = 0;$keepcurrentdir = 1;$line_width = 80;# Process the command line#while ( $arg = shift @ARGV ) {   if ( $arg eq '-c' ) {      warn "Producing .c output files"         if $debug;      $cfile = 1;   } elsif ( $arg eq '-h' ) {      warn "Producing .h output files"         if $debug;      $hfile = 1;   } elsif ( $arg eq '-ch' || $arg eq '-hc' ) {      warn "Producing .c and .h output files"         if $debug;      $cfile = 1;      $hfile = 1;   } elsif ( $arg eq '-d' ) {      $debug = 1;   } elsif ( $arg eq '-p' ) {      warn "Will produce files in original not in current directory"         if $debug;      $keepcurrentdir = 0;   } elsif ( $arg eq '-l' ) {      if ( $line_width = shift @ARGV and $line_width > 0 ) {         warn "Line width set to $line_width"            if $debug;      } else {         die "Please specify a valid line width after -l";      }   } elsif ( $arg =~ m/\.m$/ ) {      warn "Filename: $arg"         if $debug;      push @filenames, $arg;   } else {      warn "$arg ignored"         if $debug;   }}# Validate the command line parameters#die "usage: $0 [-d] [-p] [-c|-h] srcfilewhere -c   produce only .c files      -h   produce only .h files      -p   use the path component in the source file for destination dir      -l   set line width for output files [80]      -d   switch on debugging"	unless ($cfile or $hfile)	   and $#filenames != -1;# FIXME should be able to do this more easily#$tmpdir = $ENV{'TMPDIR'};           # environment variables$tmpdir = $ENV{'TMP'}   if !$tmpdir;$tmpdir = $ENV{'TEMP'}   if !$tmpdir;$tmpdir = '/tmp'                    # look for a physical directory   if !$tmpdir and -d '/tmp';$tmpdir = '/usr/tmp'   if !$tmpdir and -d '/usr/tmp';$tmpdir = '/var/tmp'   if !$tmpdir and -d '/var/tmp';$tmpdir = '.'                       # give up and use current dir   if !$tmpdir;foreach $src ( @filenames ) {   # Names of the created files   $ctmpname = "$tmpdir/ctmp.$$";   $htmpname = "$tmpdir/htmp.$$";   ($name, $path, $suffix) = &fileparse($src, '.m');   $path = '.'      if $keepcurrentdir;   $cfilename="$path/$name.c";   $hfilename="$path/$name.h";   warn "Processing from $src to $cfile / $hfile via $ctmp / $htmp"      if $debug;   die "Could not open $src, $!"      if !open SRC, "$src";   die "Could not open $ctmpname, $!"      if $cfile and !open CFILE, ">$ctmpname";   die "Could not open $htmpname, $!"      if $hfile and !open HFILE, ">$htmpname";   if ( $cfile ) {      # Produce the header of the C file      #      print CFILE "/*\n";      print CFILE " * This file is produced automatically.\n";      print CFILE " * Do not modify anything in here by hand.\n";      print CFILE " *\n";      print CFILE " * Created from\n";      print CFILE " *   $src\n";      print CFILE " * with\n";      print CFILE " *   $0\n";      print CFILE " */\n";      print CFILE "\n";      print CFILE "#include <sys/param.h>\n";      print CFILE "#include <sys/queue.h>\n";      print CFILE "#include <sys/bus_private.h>\n";   }   if ( $hfile ) {      # Produce the header of the H file      #      print HFILE "/*\n";      print HFILE " * This file is produced automatically.\n";      print HFILE " * Do not modify anything in here by hand.\n";      print HFILE " *\n";      print HFILE " * Created from\n";      print HFILE " *   $src\n";      print HFILE " * with\n";      print HFILE " *   $0\n";      print HFILE " */\n";      print HFILE "\n";   }   %methods = ();    # clear list of methods   $lineno = 0;   $error = 0;       # to signal clean up and gerror setting   LINE: while ( $line = <SRC> ) {      $lineno++;      # take special notice of include directives.      #      if ( $line =~ m/^#\s*include\s+(["<])([^">]+)([">]).*/i ) {         warn "Included file: $1$2" . ($1 eq '<'? '>':'"')            if $debug;         print CFILE "#include $1$2" . ($1 eq '<'? '>':'"') . "\n"            if $cfile;      }      $line =~ s/#.*//;                # remove comments      $line =~ s/^\s+//;               # remove leading ...      $line =~ s/\s+$//;               # remove trailing whitespace      if ( $line =~ m/^$/ ) {          # skip empty lines         # nop      } elsif ( $line =~ m/^INTERFACE\s*([^\s;]*)(\s*;?)/i ) {         $intname = $1;         $semicolon = $2;         unless ( $intname =~ m/^[a-z_][a-z0-9_]*$/ ) {            warn $line               if $debug;            warn "$src:$lineno: Invalid interface name '$intname', use [a-z_][a-z0-9_]*";            $error = 1;            last LINE;         }         warn "$src:$lineno: semicolon missing at end of line, no problem"            if $semicolon !~ s/;$//;         warn "Interface $intname"            if $debug;         print HFILE '#ifndef _'.$intname."_if_h_\n"            if $hfile;         print HFILE '#define _'.$intname."_if_h_\n\n"            if $hfile;         print CFILE '#include "'.$intname.'_if.h"'."\n\n"            if $cfile;      } elsif ( $line =~ m/^METHOD/i ) {         # Get the return type function name and delete that from         # the line. What is left is the possibly first function argument         # if it is on the same line.         #         # FIXME For compatibilities sake METHOD and METHODE is accepted.         #         if ( !$intname ) {            warn "$src:$lineno: No interface name defined";            $error = 1;            last LINE;         }         $line =~ s/^METHODE?\s+([^{]+?)\s*{\s*//i;         @ret = split m/\s+/, $1;         $name = pop @ret;          # last element is name of method         $ret = join(" ", @ret);    # return type         warn "Method: name=$name return type=$ret"            if $debug;                  if ( !$name or !$ret ) {            warn $line               if $debug;            warn "$src:$lineno: Invalid method specification";            $error = 1;            last LINE;         }         unless ( $name =~ m/^[a-z_][a-z_0-9]*$/ ) {            warn $line               if $debug;            warn "$src:$lineno: Invalid method name '$name', use [a-z_][a-z0-9_]*";            $error = 1;            last LINE;         }         if ( defined($methods{$name}) ) {            warn "$src:$lineno: Duplicate method name";            $error = 1;            last LINE;         }         $methods{$name} = 'VIS';         while ( $line !~ m/}/ and $line .= <SRC> ) { }         if ( $line !~ s/};?(.*)// ) { # remove first '}' and trailing garbage            # The '}' was not there (the rest is optional), so complain            warn "$src:$lineno: Premature end of file";            $error = 1;            last LINE;         }         warn "$src:$lineno: Ignored '$1'"  # warn about garbage at end of line            if $debug and $1;         # Create a list of variables without the types prepended         #         $line =~ s/^\s+//;            # remove leading ...         $line =~ s/\s+$//;            # ... and trailing whitespace         $line =~ s/\s+/ /;            # remove double spaces         @arguments = split m/\s*;\s*/, $line;         @varnames = ();               # list of varnames         foreach $argument (@arguments) {            next                       # skip argument if argument is empty               if !$argument;            @ar = split m/[*\s]+/, $argument;            if ( $#ar == 0 ) {         # only 1 word in argument?               warn "$src:$lineno: no type for '$argument'";               $error = 1;               last LINE;            }            push @varnames, $ar[-1];   # last element is name of variable         };         warn 'Arguments: ' . join(', ', @arguments) . "\n"            . 'Varnames: ' . join(', ', @varnames)            if $debug;         $mname = $intname.'_'.$name;  # method name         $umname = uc($mname);         # uppercase method name         $arguments = join(", ", @arguments);         $varnames = join(", ", @varnames);         if ( $hfile ) {            # the method description             print HFILE "extern struct device_op_desc $mname\_desc;\n";            # the method typedef            print HFILE &format_line("typedef $ret $mname\_t($arguments);",                              $line_width, ', ',                              ',',' ' x length("typedef $ret $mname\_t("))                      . "\n";            # the method declaration            print HFILE "$mname\_t $umname;\n\n";         }         if ( $cfile ) {            # Print out the method desc            print CFILE "struct device_op_desc $mname\_desc = {\n";            print CFILE "\t0, \"$mname\"\n";            print CFILE "};\n\n";            # Print out the method itself            if ( 0 ) {                 # haven't chosen the format yet               print CFILE "$ret $umname($varnames)\n";               print CFILE "\t".join(";\n\t", @arguments).";\n";            } else {               print CFILE &format_line("$ret $umname($arguments)",                              $line_width, ', ',                              ',', ' ' x length("$ret $umname(")) . "\n";            }            print CFILE "{\n";            print CFILE &format_line("\t$mname\_t *m = ($mname\_t *) DEVOPMETH(dev, $mname);",                              $line_width-8, ' = ', ' =', "\t\t")                      . "\n";            print CFILE "\t".($ret eq 'void'? '':'return ') . "m($varnames);\n";            print CFILE "}\n\n";         }      } else {         warn $line            if $debug;         warn "$src:$lineno: Invalid line encountered";         $error = 1;         last LINE;      }   } # end LINE   # print the final '#endif' in the header file   #   print HFILE "#endif /* _".$intname."_if_h_ */\n"      if $hfile;   close SRC;   close CFILE      if $cfile;   close HFILE      if $hfile;   if ( !$error ) {      if ( $cfile ) {         ($rc = system("mv $ctmpname $cfilename"))            and warn "mv $ctmpname $cfilename failed, $rc";      }      if ( $hfile ) {         ($rc = system("mv $htmpname $hfilename"))            and warn "mv $htmpname $hfilename failed, $rc";      }   } else {      warn 'File' . ($hfile and $cfile? 's':'') . ' skipped';      ($rc = system("rm -f $htmpname $ctmpname"))         and warn "rm -f $htmpname $ctmpname failed, $rc";      $gerror = 1;   }}exit $gerror;sub format_line {   my ($line, $maxlength, $break, $new_end, $new_start) = @_;   my $rline = "";   while ( length($line) > $maxlength           and ($i = rindex $line, $break, $maxlength-length($new_end)) != -1 ) {      $rline .= substr($line, 0, $i) . $new_end . "\n";      $line = $new_start . substr($line, $i+length($break));   }   return $rline . $line;}# This routine is a crude replacement for one in File::Basename. We# cannot use any library code because it fouls up the Perl bootstrap# when we update a perl version. MarkMsub fileparse {   my ($filename, @suffix) = @_;   my ($dir, $name, $type, $i);   $type = '';   foreach $i (@suffix) {      if ($filename =~ m|$i$|) {         $filename =~ s|$i$||;         $type = $i;      }   }   if ($filename =~ m|/|) {      $filename =~ m|([^/]*)$|;      $name = $1;      $dir = $filename;      $dir =~ s|$name$||;   }   else {      $dir = '';      $name = $filename;   }   ($name, $dir, $type);}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?