The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kern/makedevops.pl

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 #!/usr/bin/perl
    2 #
    3 # Copyright (c) 1992, 1993
    4 #        The Regents of the University of California.  All rights reserved.
    5 #
    6 # Redistribution and use in source and binary forms, with or without
    7 # modification, are permitted provided that the following conditions
    8 # are met:
    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.
   21 #
   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
   32 # SUCH DAMAGE.
   33 #
   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 #
   38 # $FreeBSD$
   39 
   40 #
   41 # Script to produce device front-end sugar.
   42 #
   43 
   44 $debug = 0;
   45 $cfile = 0;          # by default do not produce any file type
   46 $hfile = 0;
   47 
   48 $keepcurrentdir = 1;
   49 
   50 $line_width = 80;
   51 
   52 # Process the command line
   53 #
   54 while ( $arg = shift @ARGV ) {
   55    if ( $arg eq '-c' ) {
   56       warn "Producing .c output files"
   57          if $debug;
   58       $cfile = 1;
   59    } elsif ( $arg eq '-h' ) {
   60       warn "Producing .h output files"
   61          if $debug;
   62       $hfile = 1;
   63    } elsif ( $arg eq '-ch' || $arg eq '-hc' ) {
   64       warn "Producing .c and .h output files"
   65          if $debug;
   66       $cfile = 1;
   67       $hfile = 1;
   68    } elsif ( $arg eq '-d' ) {
   69       $debug = 1;
   70    } elsif ( $arg eq '-p' ) {
   71       warn "Will produce files in original not in current directory"
   72          if $debug;
   73       $keepcurrentdir = 0;
   74    } elsif ( $arg eq '-l' ) {
   75       if ( $line_width = shift @ARGV and $line_width > 0 ) {
   76          warn "Line width set to $line_width"
   77             if $debug;
   78       } else {
   79          die "Please specify a valid line width after -l";
   80       }
   81    } elsif ( $arg =~ m/\.m$/ ) {
   82       warn "Filename: $arg"
   83          if $debug;
   84       push @filenames, $arg;
   85    } else {
   86       warn "$arg ignored"
   87          if $debug;
   88    }
   89 }
   90 
   91 
   92 # Validate the command line parameters
   93 #
   94 die "usage: $0 [-d] [-p] [-l <nr>] [-c|-h] srcfile
   95 where -c   produce only .c files
   96       -h   produce only .h files
   97       -p   use the path component in the source file for destination dir
   98       -l   set line width for output files [80]
   99       -d   switch on debugging
  100 "
  101         unless ($cfile or $hfile)
  102            and $#filenames != -1;
  103 
  104 # FIXME should be able to do this more easily
  105 #
  106 $tmpdir = $ENV{'TMPDIR'};           # environment variables
  107 $tmpdir = $ENV{'TMP'}
  108    if !$tmpdir;
  109 $tmpdir = $ENV{'TEMP'}
  110    if !$tmpdir;
  111 $tmpdir = '/tmp'                    # look for a physical directory
  112    if !$tmpdir and -d '/tmp';
  113 $tmpdir = '/usr/tmp'
  114    if !$tmpdir and -d '/usr/tmp';
  115 $tmpdir = '/var/tmp'
  116    if !$tmpdir and -d '/var/tmp';
  117 $tmpdir = '.'                       # give up and use current dir
  118    if !$tmpdir;
  119 
  120 foreach $src ( @filenames ) {
  121    # Names of the created files
  122    $ctmpname = "$tmpdir/ctmp.$$";
  123    $htmpname = "$tmpdir/htmp.$$";
  124 
  125    ($name, $path, $suffix) = &fileparse($src, '.m');
  126    $path = '.'
  127       if $keepcurrentdir;
  128    $cfilename="$path/$name.c";
  129    $hfilename="$path/$name.h";
  130 
  131    warn "Processing from $src to $cfilename / $hfilename via $ctmpname / $htmpname"
  132       if $debug;
  133 
  134    die "Could not open $src, $!"
  135       if !open SRC, "$src";
  136    die "Could not open $ctmpname, $!"
  137       if $cfile and !open CFILE, ">$ctmpname";
  138    die "Could not open $htmpname, $!"
  139       if $hfile and !open HFILE, ">$htmpname";
  140 
  141    if ( $cfile ) {
  142       # Produce the header of the C file
  143       #
  144       print CFILE "/*\n";
  145       print CFILE " * This file is produced automatically.\n";
  146       print CFILE " * Do not modify anything in here by hand.\n";
  147       print CFILE " *\n";
  148       print CFILE " * Created from source file\n";
  149       print CFILE " *   $src\n";
  150       print CFILE " * with\n";
  151       print CFILE " *   $0\n";
  152       print CFILE " *\n";
  153       print CFILE " * See the source file for legal information\n";
  154       print CFILE " */\n";
  155       print CFILE "\n";
  156       print CFILE "#include <sys/param.h>\n";
  157       print CFILE "#include <sys/queue.h>\n";
  158       print CFILE "#include <sys/sysctl.h>\n";
  159       print CFILE "#include <sys/bus_private.h>\n";
  160    }
  161 
  162    if ( $hfile ) {
  163       # Produce the header of the H file
  164       #
  165       print HFILE "/*\n";
  166       print HFILE " * This file is produced automatically.\n";
  167       print HFILE " * Do not modify anything in here by hand.\n";
  168       print HFILE " *\n";
  169       print HFILE " * Created from source file\n";
  170       print HFILE " *   $src\n";
  171       print HFILE " * with\n";
  172       print HFILE " *   $0\n";
  173       print HFILE " *\n";
  174       print HFILE " * See the source file for legal information\n";
  175       print HFILE " */\n";
  176       print HFILE "\n";
  177    }
  178 
  179    %methods = ();    # clear list of methods
  180    $lineno = 0;
  181    $error = 0;       # to signal clean up and gerror setting
  182 
  183    LINE: while ( $line = <SRC> ) {
  184       $lineno++;
  185 
  186       # take special notice of include directives.
  187       #
  188       if ( $line =~ m/^#\s*include\s+(["<])([^">]+)([">]).*/i ) {
  189          warn "Included file: $1$2" . ($1 eq '<'? '>':'"')
  190             if $debug;
  191          print CFILE "#include $1$2" . ($1 eq '<'? '>':'"') . "\n"
  192             if $cfile;
  193       }
  194 
  195       $line =~ s/#.*//;                # remove comments
  196       $line =~ s/^\s+//;               # remove leading ...
  197       $line =~ s/\s+$//;               # remove trailing whitespace
  198 
  199       if ( $line =~ m/^$/ ) {          # skip empty lines
  200          # nop
  201       } elsif ( $line =~ m/^INTERFACE\s*([^\s;]*)(\s*;?)/i ) {
  202          $intname = $1;
  203          $semicolon = $2;
  204          unless ( $intname =~ m/^[a-z_][a-z0-9_]*$/ ) {
  205             warn $line
  206                if $debug;
  207             warn "$src:$lineno: Invalid interface name '$intname', use [a-z_][a-z0-9_]*";
  208             $error = 1;
  209             last LINE;
  210          }
  211 
  212          warn "$src:$lineno: semicolon missing at end of line, no problem"
  213             if $semicolon !~ s/;$//;
  214 
  215          warn "Interface $intname"
  216             if $debug;
  217 
  218          print HFILE '#ifndef _'.$intname."_if_h_\n"
  219             if $hfile;
  220          print HFILE '#define _'.$intname."_if_h_\n\n"
  221             if $hfile;
  222          print CFILE '#include "'.$intname.'_if.h"'."\n\n"
  223             if $cfile;
  224       } elsif ( $line =~ m/^CODE\s*{$/i ) {
  225          $code = "";
  226          $line = <SRC>;
  227          $line =~ m/^(\s*)/;
  228          $indent = $1;           # find the indent used
  229          while ( $line !~ m/^}/ ) {
  230             $line =~ s/^$indent//g; # remove the indent
  231             $code .= $line;
  232             $line = <SRC>;
  233             $lineno++
  234          }
  235          if ( $cfile ) {
  236              print CFILE "\n".$code."\n";
  237          }
  238       } elsif ( $line =~ m/^HEADER\s*{$/i ) {
  239          $header = "";
  240          $line = <SRC>;
  241          $line =~ m/^(\s*)/;
  242          $indent = $1;              # find the indent used
  243          while ( $line !~ m/^}/ ) {
  244             $line =~ s/^$indent//g; # remove the indent
  245             $header .= $line;
  246             $line = <SRC>;
  247             $lineno++
  248          }
  249          if ( $hfile ) {
  250              print HFILE $header;
  251          }
  252       } elsif ( $line =~ m/^(STATIC|)METHOD/i ) {
  253          # Get the return type function name and delete that from
  254          # the line. What is left is the possibly first function argument
  255          # if it is on the same line.
  256          #
  257          if ( !$intname ) {
  258             warn "$src:$lineno: No interface name defined";
  259             $error = 1;
  260             last LINE;
  261          }
  262          $line =~ s/^(STATIC|)METHOD\s+([^{]+?)\s*{\s*//i;
  263          $static = $1;                                                    
  264          @ret = split m/\s+/, $2;
  265          $name = pop @ret;          # last element is name of method
  266          $ret = join(" ", @ret);    # return type
  267 
  268          warn "Method: name=$name return type=$ret"
  269             if $debug;
  270          
  271          if ( !$name or !$ret ) {
  272             warn $line
  273                if $debug;
  274             warn "$src:$lineno: Invalid method specification";
  275             $error = 1;
  276             last LINE;
  277          }
  278 
  279          unless ( $name =~ m/^[a-z_][a-z_0-9]*$/ ) {
  280             warn $line
  281                if $debug;
  282             warn "$src:$lineno: Invalid method name '$name', use [a-z_][a-z0-9_]*";
  283             $error = 1;
  284             last LINE;
  285          }
  286 
  287          if ( defined($methods{$name}) ) {
  288             warn "$src:$lineno: Duplicate method name";
  289             $error = 1;
  290             last LINE;
  291          }
  292 
  293          $methods{$name} = 'VIS';
  294 
  295          while ( $line !~ m/}/ and $line .= <SRC> ) {
  296             $lineno++
  297          }
  298 
  299          $default = "";
  300          if ( $line !~ s/};?(.*)// ) { # remove first '}' and trailing garbage
  301             # The '}' was not there (the rest is optional), so complain
  302             warn "$src:$lineno: Premature end of file";
  303             $error = 1;
  304             last LINE;
  305          }
  306          $extra = $1;
  307          if ( $extra =~ /\s*DEFAULT\s*([a-zA-Z_][a-zA-Z_0-9]*)\s*;/ ) {
  308             $default = $1;
  309          } else {
  310             warn "$src:$lineno: Ignored '$1'"  # warn about garbage at end of line
  311                if $debug and $1;
  312          }
  313 
  314          # Create a list of variables without the types prepended
  315          #
  316          $line =~ s/^\s+//;            # remove leading ...
  317          $line =~ s/\s+$//;            # ... and trailing whitespace
  318          $line =~ s/\s+/ /g;           # remove double spaces
  319 
  320          @arguments = split m/\s*;\s*/, $line;
  321          @varnames = ();               # list of varnames
  322          foreach $argument (@arguments) {
  323             next                       # skip argument if argument is empty
  324                if !$argument;
  325 
  326             @ar = split m/[*\s]+/, $argument;
  327             if ( $#ar == 0 ) {         # only 1 word in argument?
  328                warn "$src:$lineno: no type for '$argument'";
  329                $error = 1;
  330                last LINE;
  331             }
  332 
  333             push @varnames, $ar[-1];   # last element is name of variable
  334          };
  335 
  336          warn 'Arguments: ' . join(', ', @arguments) . "\n"
  337             . 'Varnames: ' . join(', ', @varnames)
  338             if $debug;
  339 
  340          $mname = $intname.'_'.$name;  # method name
  341          $umname = uc($mname);         # uppercase method name
  342 
  343          $arguments = join(", ", @arguments);
  344          $varnames = join(", ", @varnames);
  345 
  346          $default = "0" if $default eq "";
  347 
  348          if ( $hfile ) {
  349             # the method description 
  350             print HFILE "extern struct device_op_desc $mname\_desc;\n";
  351             # the method typedef
  352             my $prototype = "typedef $ret $mname\_t(";
  353             print HFILE &format_line("$prototype$arguments);",
  354                               $line_width, ', ', ',',' ' x length($prototype))
  355                       . "\n";
  356             # the method declaration
  357             print HFILE "$mname\_t $umname;\n\n";
  358          }
  359 
  360          if ( $cfile ) {
  361             # Print out the method desc
  362             print CFILE "struct device_op_desc $mname\_desc = {\n";
  363             print CFILE "\t0, 0, (devop_t) $default, \"$mname\"\n";
  364             print CFILE "};\n\n";
  365 
  366             # Print out the method itself
  367             if ( 0 ) {                 # haven't chosen the format yet
  368                print CFILE "$ret $umname($varnames)\n";
  369                print CFILE "\t".join(";\n\t", @arguments).";\n";
  370             } else {
  371                my $prototype = "$ret $umname(";
  372                print CFILE &format_line("$prototype$arguments)",
  373                               $line_width, ', ', ',', ' ' x length($prototype))
  374                          . "\n";
  375             }
  376             print CFILE "{\n";
  377             if ($static) {
  378               print CFILE &format_line("\t$mname\_t *m = ($mname\_t *) DRVOPMETH(driver, $mname);",
  379                                        $line_width-8, ' = ', ' =', "\t\t")
  380                 . "\n";
  381             } else {
  382               print CFILE &format_line("\t$mname\_t *m = ($mname\_t *) DEVOPMETH(dev, $mname);",
  383                                        $line_width-8, ' = ', ' =', "\t\t")
  384                 . "\n";
  385             }
  386             print CFILE "\t".($ret eq 'void'? '':'return ') . "m($varnames);\n";
  387             print CFILE "}\n\n";
  388          }
  389       } else {
  390          warn $line
  391             if $debug;
  392          warn "$src:$lineno: Invalid line encountered";
  393          $error = 1;
  394          last LINE;
  395       }
  396    } # end LINE
  397 
  398    # print the final '#endif' in the header file
  399    #
  400    print HFILE "#endif /* _".$intname."_if_h_ */\n"
  401       if $hfile;
  402 
  403    close SRC;
  404    close CFILE
  405       if $cfile;
  406    close HFILE
  407       if $hfile;
  408 
  409    if ( !$error ) {
  410       if ( $cfile ) {
  411          ($rc = system("mv $ctmpname $cfilename"))
  412             and warn "mv $ctmpname $cfilename failed, $rc";
  413       }
  414 
  415       if ( $hfile ) {
  416          ($rc = system("mv $htmpname $hfilename"))
  417             and warn "mv $htmpname $hfilename failed, $rc";
  418       }
  419    } else {
  420       warn 'Output skipped';
  421       ($rc = system("rm -f $htmpname $ctmpname"))
  422          and warn "rm -f $htmpname $ctmpname failed, $rc";
  423       $gerror = 1;
  424    }
  425 }
  426 
  427 exit $gerror;
  428 
  429 
  430 sub format_line {
  431    my ($line, $maxlength, $break, $new_end, $new_start) = @_;
  432    my $rline = "";
  433 
  434    while ( length($line) > $maxlength
  435            and ($i = rindex $line, $break, $maxlength-length($new_end)) != -1 ) {
  436       $rline .= substr($line, 0, $i) . $new_end . "\n";
  437       $line = $new_start . substr($line, $i+length($break));
  438    }
  439 
  440    return $rline . $line;
  441 }
  442 
  443 # This routine is a crude replacement for one in File::Basename. We
  444 # cannot use any library code because it fouls up the Perl bootstrap
  445 # when we update a perl version. MarkM
  446 
  447 sub fileparse {
  448    my ($filename, @suffix) = @_;
  449    my ($dir, $name, $type, $i);
  450 
  451    $type = '';
  452    foreach $i (@suffix) {
  453       if ($filename =~ m|$i$|) {
  454          $filename =~ s|$i$||;
  455          $type = $i;
  456       }
  457    }
  458    if ($filename =~ m|/|) {
  459       $filename =~ m|([^/]*)$|;
  460       $name = $1;
  461       $dir = $filename;
  462       $dir =~ s|$name$||;
  463    }
  464    else {
  465       $dir = '';
  466       $name = $filename;
  467    }
  468    ($name, $dir, $type);
  469 }

Cache object: 2c9df81b0d8d26c3d52e12ad900cbe12


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.