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/scripts/kernel-doc

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 -w
    2 
    3 use strict;
    4 
    5 ## Copyright (c) 1998 Michael Zucchi, All Rights Reserved        ##
    6 ## Copyright (C) 2000, 1  Tim Waugh <twaugh@redhat.com>          ##
    7 ## Copyright (C) 2001  Simon Huggins                             ##
    8 ##                                                               ##
    9 ## #define enhancements by Armin Kuster <akuster@mvista.com>     ##
   10 ## Copyright (c) 2000 MontaVista Software, Inc.                  ##
   11 ##                                                               ##
   12 ## This software falls under the GNU General Public License.     ##
   13 ## Please read the COPYING file for more information             ##
   14 
   15 # w.o. 03-11-2000: added the '-filelist' option.
   16 
   17 # 18/01/2001 -  Cleanups
   18 #               Functions prototyped as foo(void) same as foo()
   19 #               Stop eval'ing where we don't need to.
   20 # -- huggie@earth.li
   21 
   22 # 27/06/2001 -  Allowed whitespace after initial "/**" and
   23 #               allowed comments before function declarations.
   24 # -- Christian Kreibich <ck@whoop.org>
   25 
   26 # Still to do:
   27 #       - add perldoc documentation
   28 #       - Look more closely at some of the scarier bits :)
   29 
   30 # 26/05/2001 -  Support for separate source and object trees.
   31 #               Return error code.
   32 #               Keith Owens <kaos@ocs.com.au>
   33 
   34 # 23/09/2001 - Added support for typedefs, structs, enums and unions
   35 #              Support for Context section; can be terminated using empty line
   36 #              Small fixes (like spaces vs. \s in regex)
   37 # -- Tim Jansen <tim@tjansen.de>
   38 
   39 
   40 #
   41 # This will read a 'c' file and scan for embedded comments in the
   42 # style of gnome comments (+minor extensions - see below).
   43 #
   44 
   45 # Note: This only supports 'c'.
   46 
   47 # usage:
   48 # kerneldoc [ -docbook | -html | -text | -man ]
   49 #           [ -function funcname [ -function funcname ...] ] c file(s)s > outputfile
   50 # or
   51 #           [ -nofunction funcname [ -function funcname ...] ] c file(s)s > outputfile
   52 #
   53 #  Set output format using one of -docbook -html -text or -man.  Default is man.
   54 #
   55 #  -function funcname
   56 #       If set, then only generate documentation for the given function(s).  All
   57 #       other functions are ignored.
   58 #
   59 #  -nofunction funcname
   60 #       If set, then only generate documentation for the other function(s).  All
   61 #       other functions are ignored. Cannot be used with -function together
   62 #       (yes thats a bug - perl hackers can fix it 8))
   63 #
   64 #  c files - list of 'c' files to process
   65 #
   66 #  All output goes to stdout, with errors to stderr.
   67 
   68 #
   69 # format of comments.
   70 # In the following table, (...)? signifies optional structure.
   71 #                         (...)* signifies 0 or more structure elements
   72 # /**
   73 #  * function_name(:)? (- short description)?
   74 # (* @parameterx: (description of parameter x)?)*
   75 # (* a blank line)?
   76 #  * (Description:)? (Description of function)?
   77 #  * (section header: (section description)? )*
   78 #  (*)?*/
   79 #
   80 # So .. the trivial example would be:
   81 #
   82 # /**
   83 #  * my_function
   84 #  **/
   85 #
   86 # If the Description: header tag is ommitted, then there must be a blank line
   87 # after the last parameter specification.
   88 # e.g.
   89 # /**
   90 #  * my_function - does my stuff
   91 #  * @my_arg: its mine damnit
   92 #  *
   93 #  * Does my stuff explained. 
   94 #  */
   95 #
   96 #  or, could also use:
   97 # /**
   98 #  * my_function - does my stuff
   99 #  * @my_arg: its mine damnit
  100 #  * Description: Does my stuff explained. 
  101 #  */
  102 # etc.
  103 #
  104 # Beside functions you can also write documentation for structs, unions, 
  105 # enums and typedefs. Instead of the function name you must write the name 
  106 # of the declaration;  the struct/union/enum/typedef must always precede 
  107 # the name. Nesting of declarations is not supported. 
  108 # Use the argument mechanism to document members or constants. In 
  109 # structs and unions you must declare one member per declaration 
  110 # (comma-separated members are not allowed -  the parser does not support 
  111 # this).
  112 # e.g.
  113 # /**
  114 #  * struct my_struct - short description
  115 #  * @a: first member
  116 #  * @b: second member
  117 #  * 
  118 #  * Longer description
  119 #  */
  120 # struct my_struct {
  121 #     int a;
  122 #     int b;
  123 # };
  124 #
  125 # All descriptions can be multiline, except the short function description.
  126 # 
  127 # You can also add additional sections. When documenting kernel functions you 
  128 # should document the "Context:" of the function, e.g. whether the functions 
  129 # can be called form interrupts. Unlike other sections you can end it with an
  130 # empty line. 
  131 # Example-sections should contain the string EXAMPLE so that they are marked 
  132 # appropriately in DocBook.
  133 #
  134 # Example:
  135 # /**
  136 #  * user_function - function that can only be called in user context
  137 #  * @a: some argument
  138 #  * Context: !in_interrupt()
  139 #  * 
  140 #  * Some description
  141 #  * Example:
  142 #  *    user_function(22);
  143 #  */
  144 # ...
  145 #
  146 #
  147 # All descriptive text is further processed, scanning for the following special
  148 # patterns, which are highlighted appropriately.
  149 #
  150 # 'funcname()' - function
  151 # '$ENVVAR' - environmental variable
  152 # '&struct_name' - name of a structure (up to two words including 'struct')
  153 # '@parameter' - name of a parameter
  154 # '%CONST' - name of a constant.
  155 
  156 my $errors = 0;
  157 
  158 # match expressions used to find embedded type information
  159 my $type_constant = '\%([-_\w]+)';
  160 my $type_func = '(\w+)\(\)';
  161 my $type_param = '\@(\w+)';
  162 my $type_struct = '\&((struct\s*)?[_\w]+)';
  163 my $type_env = '(\$\w+)';
  164 
  165 # Output conversion substitutions.
  166 #  One for each output format
  167 
  168 # these work fairly well
  169 my %highlights_html = ( $type_constant, "<i>\$1</i>",
  170                         $type_func, "<b>\$1</b>",
  171                         $type_struct, "<i>\$1</i>",
  172                         $type_param, "<tt><b>\$1</b></tt>" );
  173 my $blankline_html = "<p>";
  174 
  175 # sgml, docbook format
  176 my %highlights_sgml = ( "([^=])\\\"([^\\\"<]+)\\\"", "\$1<quote>\$2</quote>",
  177                         $type_constant, "<constant>\$1</constant>",
  178                         $type_func, "<function>\$1</function>",
  179                         $type_struct, "<structname>\$1</structname>",
  180                         $type_env, "<envar>\$1</envar>",
  181                         $type_param, "<parameter>\$1</parameter>" );
  182 my $blankline_sgml = "</para><para>\n";
  183 
  184 # gnome, docbook format
  185 my %highlights_gnome = ( $type_constant, "<replaceable class=\"option\">\$1</replaceable>",
  186                          $type_func, "<function>\$1</function>",
  187                          $type_struct, "<structname>\$1</structname>",
  188                          $type_env, "<envar>\$1</envar>",
  189                          $type_param, "<parameter>\$1</parameter>" );
  190 my $blankline_gnome = "</para><para>\n";
  191 
  192 # these are pretty rough
  193 my %highlights_man = ( $type_constant, "\$1",
  194                        $type_func, "\\\\fB\$1\\\\fP",
  195                        $type_struct, "\\\\fI\$1\\\\fP",
  196                        $type_param, "\\\\fI\$1\\\\fP" );
  197 my $blankline_man = "";
  198 
  199 # text-mode
  200 my %highlights_text = ( $type_constant, "\$1",
  201                         $type_func, "\$1",
  202                         $type_struct, "\$1",
  203                         $type_param, "\$1" );
  204 my $blankline_text = "";
  205 
  206 
  207 sub usage {
  208     print "Usage: $0 [ -v ] [ -docbook | -html | -text | -man ]\n";
  209     print "         [ -function funcname [ -function funcname ...] ]\n";
  210     print "         [ -nofunction funcname [ -nofunction funcname ...] ]\n";
  211     print "         c source file(s) > outputfile\n";
  212     exit 1;
  213 }
  214 
  215 # read arguments
  216 if ($#ARGV==-1) {
  217     usage();
  218 }
  219 
  220 my $verbose = 0;
  221 my $output_mode = "man";
  222 my %highlights = %highlights_man;
  223 my $blankline = $blankline_man;
  224 my $modulename = "Kernel API";
  225 my $function_only = 0;
  226 my $man_date = ('January', 'February', 'March', 'April', 'May', 'June', 
  227                 'July', 'August', 'September', 'October', 
  228                 'November', 'December')[(localtime)[4]] . 
  229   " " . ((localtime)[5]+1900);
  230 
  231 # Essentially these are globals
  232 # They probably want to be tidied up made more localised or summat.
  233 # CAVEAT EMPTOR!  Some of the others I localised may not want to be which
  234 # could cause "use of undefined value" or other bugs.
  235 my ($function, %function_table,%parametertypes,$declaration_purpose);
  236 my ($type,$declaration_name,$return_type);
  237 my ($newsection,$newcontents,$prototype,$filelist, $brcount, %source_map);
  238 
  239 # Generated docbook code is inserted in a template at a point where 
  240 # docbook v3.1 requires a non-zero sequence of RefEntry's; see:
  241 # http://www.oasis-open.org/docbook/documentation/reference/html/refentry.html
  242 # We keep track of number of generated entries and generate a dummy
  243 # if needs be to ensure the expanded template can be postprocessed
  244 # into html.
  245 my $section_counter = 0;
  246 
  247 my $lineprefix="";
  248 
  249 # states
  250 # 0 - normal code
  251 # 1 - looking for function name
  252 # 2 - scanning field start.
  253 # 3 - scanning prototype.
  254 # 4 - documentation block
  255 my $state;
  256 
  257 #declaration types: can be
  258 # 'function', 'struct', 'union', 'enum', 'typedef'
  259 my $decl_type;
  260 
  261 my $doc_special = "\@\%\$\&";
  262 
  263 my $doc_start = '^/\*\*\s*$'; # Allow whitespace at end of comment start.
  264 my $doc_end = '\*/';
  265 my $doc_com = '\s*\*\s*';
  266 my $doc_decl = $doc_com.'(\w+)';
  267 my $doc_sect = $doc_com.'(['.$doc_special.']?[\w ]+):(.*)';
  268 my $doc_content = $doc_com.'(.*)';
  269 my $doc_block = $doc_com.'DOC:\s*(.*)?';
  270 
  271 my %constants;
  272 my %parameterdescs;
  273 my @parameterlist;
  274 my %sections;
  275 my @sectionlist;
  276 
  277 my $contents = "";
  278 my $section_default = "Description";    # default section
  279 my $section_intro = "Introduction";
  280 my $section = $section_default;
  281 my $section_context = "Context";
  282 
  283 my $undescribed = "-- undescribed --";
  284 
  285 reset_state();
  286 
  287 while ($ARGV[0] =~ m/^-(.*)/) {
  288     my $cmd = shift @ARGV;
  289     if ($cmd eq "-html") {
  290         $output_mode = "html";
  291         %highlights = %highlights_html;
  292         $blankline = $blankline_html;
  293     } elsif ($cmd eq "-man") {
  294         $output_mode = "man";
  295         %highlights = %highlights_man;
  296         $blankline = $blankline_man;
  297     } elsif ($cmd eq "-text") {
  298         $output_mode = "text";
  299         %highlights = %highlights_text;
  300         $blankline = $blankline_text;
  301     } elsif ($cmd eq "-docbook") {
  302         $output_mode = "sgml";
  303         %highlights = %highlights_sgml;
  304         $blankline = $blankline_sgml;
  305     } elsif ($cmd eq "-gnome") {
  306         $output_mode = "gnome";
  307         %highlights = %highlights_gnome;
  308         $blankline = $blankline_gnome;
  309     } elsif ($cmd eq "-module") { # not needed for sgml, inherits from calling document
  310         $modulename = shift @ARGV;
  311     } elsif ($cmd eq "-function") { # to only output specific functions
  312         $function_only = 1;
  313         $function = shift @ARGV;
  314         $function_table{$function} = 1;
  315     } elsif ($cmd eq "-nofunction") { # to only output specific functions
  316         $function_only = 2;
  317         $function = shift @ARGV;
  318         $function_table{$function} = 1;
  319     } elsif ($cmd eq "-v") {
  320         $verbose = 1;
  321     } elsif (($cmd eq "-h") || ($cmd eq "--help")) {
  322         usage();
  323     } elsif ($cmd eq '-filelist') {
  324             $filelist = shift @ARGV;
  325     }
  326 }
  327 
  328 
  329 # generate a sequence of code that will splice in highlighting information
  330 # using the s// operator.
  331 my $dohighlight = "";
  332 foreach my $pattern (keys %highlights) {
  333 #    print "scanning pattern $pattern ($highlights{$pattern})\n";
  334     $dohighlight .=  "\$contents =~ s:$pattern:$highlights{$pattern}:gs;\n";
  335 }
  336 
  337 ##
  338 # dumps section contents to arrays/hashes intended for that purpose.
  339 #
  340 sub dump_section {
  341     my $name = shift;
  342     my $contents = join "\n", @_;
  343 
  344     if ($name =~ m/$type_constant/) {
  345         $name = $1;
  346 #       print STDERR "constant section '$1' = '$contents'\n";
  347         $constants{$name} = $contents;
  348     } elsif ($name =~ m/$type_param/) {
  349 #       print STDERR "parameter def '$1' = '$contents'\n";
  350         $name = $1;
  351         $parameterdescs{$name} = $contents;
  352     } else {
  353 #       print STDERR "other section '$name' = '$contents'\n";
  354         $sections{$name} = $contents;
  355         push @sectionlist, $name;
  356     }
  357 }
  358 
  359 ##
  360 # output function
  361 #
  362 # parameterdescs, a hash.
  363 #  function => "function name"
  364 #  parameterlist => @list of parameters
  365 #  parameterdescs => %parameter descriptions
  366 #  sectionlist => @list of sections
  367 #  sections => %descriont descriptions
  368 #  
  369 
  370 sub output_highlight {
  371     my $contents = join "\n",@_;
  372     my $line;
  373 
  374 #   DEBUG
  375 #   if (!defined $contents) {
  376 #       use Carp;
  377 #       confess "output_highlight got called with no args?\n";
  378 #   }
  379 
  380     eval $dohighlight;
  381     die $@ if $@;
  382     foreach $line (split "\n", $contents) {
  383       if ($line eq ""){
  384             print $lineprefix, $blankline;
  385         } else {
  386             $line =~ s/\\\\\\/\&/g;
  387             print $lineprefix, $line;
  388         }
  389         print "\n";
  390     }
  391 }
  392 
  393 #output sections in html
  394 sub output_section_html(%) {
  395     my %args = %{$_[0]};
  396     my $section;
  397 
  398     foreach $section (@{$args{'sectionlist'}}) {
  399         print "<h3>$section</h3>\n";
  400         print "<blockquote>\n";
  401         output_highlight($args{'sections'}{$section});
  402         print "</blockquote>\n";
  403     }  
  404 }
  405 
  406 # output enum in html
  407 sub output_enum_html(%) {
  408     my %args = %{$_[0]};
  409     my ($parameter);
  410     my $count;
  411     print "<h2>enum ".$args{'enum'}."</h2>\n";
  412 
  413     print "<b>enum ".$args{'enum'}."</b> {<br>\n";
  414     $count = 0;
  415     foreach $parameter (@{$args{'parameterlist'}}) {
  416         print " <b>".$parameter."</b>";
  417         if ($count != $#{$args{'parameterlist'}}) {
  418             $count++;
  419             print ",\n";
  420         }
  421         print "<br>";
  422     }
  423     print "};<br>\n";
  424 
  425     print "<h3>Constants</h3>\n";
  426     print "<dl>\n";
  427     foreach $parameter (@{$args{'parameterlist'}}) {
  428         print "<dt><b>".$parameter."</b>\n";
  429         print "<dd>";
  430         output_highlight($args{'parameterdescs'}{$parameter});
  431     }
  432     print "</dl>\n";
  433     output_section_html(@_);
  434     print "<hr>\n";
  435 }
  436 
  437 # output tyepdef in html
  438 sub output_typedef_html(%) {
  439     my %args = %{$_[0]};
  440     my ($parameter);
  441     my $count;
  442     print "<h2>typedef ".$args{'typedef'}."</h2>\n";
  443 
  444     print "<b>typedef ".$args{'typedef'}."</b>\n";
  445     output_section_html(@_);
  446     print "<hr>\n";
  447 }
  448 
  449 # output struct in html
  450 sub output_struct_html(%) {
  451     my %args = %{$_[0]};
  452     my ($parameter);
  453 
  454     print "<h2>".$args{'type'}." ".$args{'struct'}."</h2>\n";
  455     print "<b>".$args{'type'}." ".$args{'struct'}."</b> {<br>\n";
  456     foreach $parameter (@{$args{'parameterlist'}}) {
  457         ($args{'parameterdescs'}{$parameter} ne $undescribed) || next;
  458         $type = $args{'parametertypes'}{$parameter};
  459         if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
  460             # pointer-to-function
  461             print " <i>$1</i><b>$parameter</b>) <i>($2)</i>;<br>\n";
  462         } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
  463             print " <i>$1</i> <b>$parameter</b>$2;<br>\n";
  464         } else {
  465             print " <i>$type</i> <b>$parameter</b>;<br>\n";
  466         }
  467     }
  468     print "};<br>\n";
  469 
  470     print "<h3>Members</h3>\n";
  471     print "<dl>\n";
  472     foreach $parameter (@{$args{'parameterlist'}}) {
  473         ($args{'parameterdescs'}{$parameter} ne $undescribed) || next;
  474         print "<dt><b>".$parameter."</b>\n";
  475         print "<dd>";
  476         output_highlight($args{'parameterdescs'}{$parameter});
  477     }
  478     print "</dl>\n";
  479     output_section_html(@_);
  480     print "<hr>\n";
  481 }
  482 
  483 # output function in html
  484 sub output_function_html(%) {
  485     my %args = %{$_[0]};
  486     my ($parameter, $section);
  487     my $count;
  488     print "<h2>Function</h2>\n";
  489 
  490     print "<i>".$args{'functiontype'}."</i>\n";
  491     print "<b>".$args{'function'}."</b>\n";
  492     print "(";
  493     $count = 0;
  494     foreach $parameter (@{$args{'parameterlist'}}) {
  495         $type = $args{'parametertypes'}{$parameter};
  496         if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
  497             # pointer-to-function
  498             print "<i>$1</i><b>$parameter</b>) <i>($2)</i>";
  499         } else {
  500             print "<i>".$type."</i> <b>".$parameter."</b>";
  501         }
  502         if ($count != $#{$args{'parameterlist'}}) {
  503             $count++;
  504             print ",\n";
  505         }
  506     }
  507     print ")\n";
  508 
  509     print "<h3>Arguments</h3>\n";
  510     print "<dl>\n";
  511     foreach $parameter (@{$args{'parameterlist'}}) {
  512         ($args{'parameterdescs'}{$parameter} ne $undescribed) || next;
  513         print "<dt><b>".$parameter."</b>\n";
  514         print "<dd>";
  515         output_highlight($args{'parameterdescs'}{$parameter});
  516     }
  517     print "</dl>\n";
  518     output_section_html(@_);
  519     print "<hr>\n";
  520 }
  521 
  522 # output intro in html
  523 sub output_intro_html(%) {
  524     my %args = %{$_[0]};
  525     my ($parameter, $section);
  526     my $count;
  527 
  528     foreach $section (@{$args{'sectionlist'}}) {
  529         print "<h3>$section</h3>\n";
  530         print "<ul>\n";
  531         output_highlight($args{'sections'}{$section});
  532         print "</ul>\n";
  533     }
  534     print "<hr>\n";
  535 }
  536 
  537 sub output_section_sgml(%) {
  538     my %args = %{$_[0]};
  539     my $section;    
  540     # print out each section
  541     $lineprefix="   ";
  542     foreach $section (@{$args{'sectionlist'}}) {
  543         print "<refsect1>\n <title>$section</title>\n <para>\n";
  544         if ($section =~ m/EXAMPLE/i) {
  545             print "<example><para>\n";
  546         }
  547         output_highlight($args{'sections'}{$section});
  548         if ($section =~ m/EXAMPLE/i) {
  549             print "</para></example>\n";
  550         }
  551         print " </para>\n</refsect1>\n";
  552     }
  553 }
  554 
  555 # output function in sgml DocBook
  556 sub output_function_sgml(%) {
  557     my %args = %{$_[0]};
  558     my ($parameter, $section);
  559     my $count;
  560     my $id;
  561 
  562     $id = "API-".$args{'function'};
  563     $id =~ s/[^A-Za-z0-9]/-/g;
  564 
  565     print "<refentry>\n";
  566     print "<refmeta>\n";
  567     print "<refentrytitle><phrase id=\"$id\">".$args{'function'}."</phrase></refentrytitle>\n";
  568     print "</refmeta>\n";
  569     print "<refnamediv>\n";
  570     print " <refname>".$args{'function'}."</refname>\n";
  571     print " <refpurpose>\n";
  572     print "  ";
  573     output_highlight ($args{'purpose'});
  574     print " </refpurpose>\n";
  575     print "</refnamediv>\n";
  576 
  577     print "<refsynopsisdiv>\n";
  578     print " <title>Synopsis</title>\n";
  579     print "  <funcsynopsis><funcprototype>\n";
  580     print "   <funcdef>".$args{'functiontype'}." ";
  581     print "<function>".$args{'function'}." </function></funcdef>\n";
  582 
  583     $count = 0;
  584     if ($#{$args{'parameterlist'}} >= 0) {
  585         foreach $parameter (@{$args{'parameterlist'}}) {
  586             $type = $args{'parametertypes'}{$parameter};
  587             if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
  588                 # pointer-to-function
  589                 print "   <paramdef>$1<parameter>$parameter</parameter>)\n";
  590                 print "     <funcparams>$2</funcparams></paramdef>\n";
  591             } else {
  592                 print "   <paramdef>".$type;
  593                 print " <parameter>$parameter</parameter></paramdef>\n";
  594             }
  595         }
  596     } else {
  597         print "  <void>\n";
  598     }
  599     print "  </funcprototype></funcsynopsis>\n";
  600     print "</refsynopsisdiv>\n";
  601 
  602     # print parameters
  603     print "<refsect1>\n <title>Arguments</title>\n";
  604     if ($#{$args{'parameterlist'}} >= 0) {
  605         print " <variablelist>\n";
  606         foreach $parameter (@{$args{'parameterlist'}}) {
  607             print "  <varlistentry>\n   <term><parameter>$parameter</parameter></term>\n";
  608             print "   <listitem>\n    <para>\n";
  609             $lineprefix="     ";
  610             output_highlight($args{'parameterdescs'}{$parameter});
  611             print "    </para>\n   </listitem>\n  </varlistentry>\n";
  612         }
  613         print " </variablelist>\n";
  614     } else {
  615         print " <para>\n  None\n </para>\n";
  616     }
  617     print "</refsect1>\n";
  618 
  619     output_section_sgml(@_);
  620     print "</refentry>\n\n";
  621 }
  622 
  623 # output struct in sgml DocBook
  624 sub output_struct_sgml(%) {
  625     my %args = %{$_[0]};
  626     my ($parameter, $section);
  627     my $id;
  628 
  629     $id = "API-struct-".$args{'struct'};
  630     $id =~ s/[^A-Za-z0-9]/-/g;
  631 
  632     print "<refentry>\n";
  633     print "<refmeta>\n";
  634     print "<refentrytitle><phrase id=\"$id\">".$args{'type'}." ".$args{'struct'}."</phrase></refentrytitle>\n";
  635     print "</refmeta>\n";
  636     print "<refnamediv>\n";
  637     print " <refname>".$args{'type'}." ".$args{'struct'}."</refname>\n";
  638     print " <refpurpose>\n";
  639     print "  ";
  640     output_highlight ($args{'purpose'});
  641     print " </refpurpose>\n";
  642     print "</refnamediv>\n";
  643 
  644     print "<refsynopsisdiv>\n";
  645     print " <title>Synopsis</title>\n";
  646     print "  <programlisting>\n";
  647     print $args{'type'}." ".$args{'struct'}." {\n";
  648     foreach $parameter (@{$args{'parameterlist'}}) {
  649         ($args{'parameterdescs'}{$parameter} ne $undescribed) || next;
  650         $type = $args{'parametertypes'}{$parameter};
  651         if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
  652             # pointer-to-function
  653             print "  $1 $parameter ($2);\n";
  654         } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
  655             print "  $1 $parameter$2;\n";
  656         } else {
  657             print "  ".$type." ".$parameter.";\n";
  658         }
  659     }
  660     print "};";
  661     print "  </programlisting>\n";
  662     print "</refsynopsisdiv>\n";
  663 
  664     print " <refsect1>\n";
  665     print "  <title>Members</title>\n";
  666 
  667     print "  <variablelist>\n";
  668     foreach $parameter (@{$args{'parameterlist'}}) {
  669       ($args{'parameterdescs'}{$parameter} ne $undescribed) || next;
  670       print "    <varlistentry>";
  671       print "      <term>$parameter</term>\n";
  672       print "      <listitem><para>\n";
  673       output_highlight($args{'parameterdescs'}{$parameter});
  674       print "      </para></listitem>\n";
  675       print "    </varlistentry>\n";
  676     }
  677     print "  </variablelist>\n";
  678     print " </refsect1>\n";
  679 
  680     output_section_sgml(@_);
  681 
  682     print "</refentry>\n\n";
  683 }
  684 
  685 # output enum in sgml DocBook
  686 sub output_enum_sgml(%) {
  687     my %args = %{$_[0]};
  688     my ($parameter, $section);
  689     my $count;
  690     my $id;
  691 
  692     $id = "API-enum-".$args{'enum'};
  693     $id =~ s/[^A-Za-z0-9]/-/g;
  694 
  695     print "<refentry>\n";
  696     print "<refmeta>\n";
  697     print "<refentrytitle><phrase id=\"$id\">enum ".$args{'enum'}."</phrase></refentrytitle>\n";
  698     print "</refmeta>\n";
  699     print "<refnamediv>\n";
  700     print " <refname>enum ".$args{'enum'}."</refname>\n";
  701     print " <refpurpose>\n";
  702     print "  ";
  703     output_highlight ($args{'purpose'});
  704     print " </refpurpose>\n";
  705     print "</refnamediv>\n";
  706 
  707     print "<refsynopsisdiv>\n";
  708     print " <title>Synopsis</title>\n";
  709     print "  <programlisting>\n";
  710     print "enum ".$args{'enum'}." {\n";
  711     $count = 0;
  712     foreach $parameter (@{$args{'parameterlist'}}) {
  713         print "  $parameter";
  714         if ($count != $#{$args{'parameterlist'}}) {
  715             $count++;
  716             print ",";
  717         }
  718         print "\n";
  719     }
  720     print "};";
  721     print "  </programlisting>\n";
  722     print "</refsynopsisdiv>\n";
  723 
  724     print "<refsect1>\n";
  725     print " <title>Constants</title>\n";    
  726     print "  <variablelist>\n";
  727     foreach $parameter (@{$args{'parameterlist'}}) {
  728       print "    <varlistentry>";
  729       print "      <term>$parameter</term>\n";
  730       print "      <listitem><para>\n";
  731       output_highlight($args{'parameterdescs'}{$parameter});
  732       print "      </para></listitem>\n";
  733       print "    </varlistentry>\n";
  734     }
  735     print "  </variablelist>\n";
  736     print "</refsect1>\n";
  737 
  738     output_section_sgml(@_);
  739 
  740     print "</refentry>\n\n";
  741 }
  742 
  743 # output typedef in sgml DocBook
  744 sub output_typedef_sgml(%) {
  745     my %args = %{$_[0]};
  746     my ($parameter, $section);
  747     my $id;
  748 
  749     $id = "API-typedef-".$args{'typedef'};
  750     $id =~ s/[^A-Za-z0-9]/-/g;
  751 
  752     print "<refentry>\n";
  753     print "<refmeta>\n";
  754     print "<refentrytitle><phrase id=\"$id\">typedef ".$args{'typedef'}."</phrase></refentrytitle>\n";
  755     print "</refmeta>\n";
  756     print "<refnamediv>\n";
  757     print " <refname>typedef ".$args{'typedef'}."</refname>\n";
  758     print " <refpurpose>\n";
  759     print "  ";
  760     output_highlight ($args{'purpose'});
  761     print " </refpurpose>\n";
  762     print "</refnamediv>\n";
  763 
  764     print "<refsynopsisdiv>\n";
  765     print " <title>Synopsis</title>\n";
  766     print "  <synopsis>typedef ".$args{'typedef'}.";</synopsis>\n";
  767     print "</refsynopsisdiv>\n";
  768 
  769     output_section_sgml(@_);
  770 
  771     print "</refentry>\n\n";
  772 }
  773 
  774 # output in sgml DocBook
  775 sub output_intro_sgml(%) {
  776     my %args = %{$_[0]};
  777     my ($parameter, $section);
  778     my $count;
  779 
  780     my $id = $args{'module'};
  781     $id =~ s/[^A-Za-z0-9]/-/g;
  782 
  783     # print out each section
  784     $lineprefix="   ";
  785     foreach $section (@{$args{'sectionlist'}}) {
  786         print "<refsect1>\n <title>$section</title>\n <para>\n";
  787         if ($section =~ m/EXAMPLE/i) {
  788             print "<example><para>\n";
  789         }
  790         output_highlight($args{'sections'}{$section});
  791         if ($section =~ m/EXAMPLE/i) {
  792             print "</para></example>\n";
  793         }
  794         print " </para>\n</refsect1>\n";
  795     }
  796 
  797     print "\n\n";
  798 }
  799 
  800 # output in sgml DocBook
  801 sub output_function_gnome {
  802     my %args = %{$_[0]};
  803     my ($parameter, $section);
  804     my $count;
  805     my $id;
  806 
  807     $id = $args{'module'}."-".$args{'function'};
  808     $id =~ s/[^A-Za-z0-9]/-/g;
  809 
  810     print "<sect2>\n";
  811     print " <title id=\"$id\">".$args{'function'}."</title>\n";
  812 
  813     print "  <funcsynopsis>\n";
  814     print "   <funcdef>".$args{'functiontype'}." ";
  815     print "<function>".$args{'function'}." ";
  816     print "</function></funcdef>\n";
  817 
  818     $count = 0;
  819     if ($#{$args{'parameterlist'}} >= 0) {
  820         foreach $parameter (@{$args{'parameterlist'}}) {
  821             $type = $args{'parametertypes'}{$parameter};
  822             if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
  823                 # pointer-to-function
  824                 print "   <paramdef>$1 <parameter>$parameter</parameter>)\n";
  825                 print "     <funcparams>$2</funcparams></paramdef>\n";
  826             } else {
  827                 print "   <paramdef>".$type;
  828                 print " <parameter>$parameter</parameter></paramdef>\n";
  829             }
  830         }
  831     } else {
  832         print "  <void>\n";
  833     }
  834     print "  </funcsynopsis>\n";
  835     if ($#{$args{'parameterlist'}} >= 0) {
  836         print " <informaltable pgwide=\"1\" frame=\"none\" role=\"params\">\n";
  837         print "<tgroup cols=\"2\">\n";
  838         print "<colspec colwidth=\"2*\">\n";
  839         print "<colspec colwidth=\"8*\">\n";
  840         print "<tbody>\n";
  841         foreach $parameter (@{$args{'parameterlist'}}) {
  842             print "  <row><entry align=\"right\"><parameter>$parameter</parameter></entry>\n";
  843             print "   <entry>\n";
  844             $lineprefix="     ";
  845             output_highlight($args{'parameterdescs'}{$parameter});
  846             print "    </entry></row>\n";
  847         }
  848         print " </tbody></tgroup></informaltable>\n";
  849     } else {
  850         print " <para>\n  None\n </para>\n";
  851     }
  852 
  853     # print out each section
  854     $lineprefix="   ";
  855     foreach $section (@{$args{'sectionlist'}}) {
  856         print "<simplesect>\n <title>$section</title>\n";
  857         if ($section =~ m/EXAMPLE/i) {
  858             print "<example><programlisting>\n";
  859         } else {
  860         }
  861         print "<para>\n";
  862         output_highlight($args{'sections'}{$section});
  863         print "</para>\n";
  864         if ($section =~ m/EXAMPLE/i) {
  865             print "</programlisting></example>\n";
  866         } else {
  867         }
  868         print " </simplesect>\n";
  869     }
  870 
  871     print "</sect2>\n\n";
  872 }
  873 
  874 ##
  875 # output function in man
  876 sub output_function_man(%) {
  877     my %args = %{$_[0]};
  878     my ($parameter, $section);
  879     my $count;
  880 
  881     print ".TH \"$args{'function'}\" 9 \"$args{'function'}\" \"25 May 1998\" \"Kernel Hacker's Manual\" LINUX\n";
  882 
  883     print ".SH NAME\n";
  884     print $args{'function'}." \\- ".$args{'purpose'}."\n";
  885 
  886     print ".SH SYNOPSIS\n";
  887     print ".B \"".$args{'functiontype'}."\" ".$args{'function'}."\n";
  888     $count = 0;
  889     my $parenth = "(";
  890     my $post = ",";
  891     foreach my $parameter (@{$args{'parameterlist'}}) {
  892         if ($count == $#{$args{'parameterlist'}}) {
  893             $post = ");";
  894         }
  895         $type = $args{'parametertypes'}{$parameter};
  896         if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
  897             # pointer-to-function
  898             print ".BI \"".$parenth.$1."\" ".$parameter." \") (".$2.")".$post."\"\n";
  899         } else {
  900             $type =~ s/([^\*])$/$1 /;
  901             print ".BI \"".$parenth.$type."\" ".$parameter." \"".$post."\"\n";
  902         }
  903         $count++;
  904         $parenth = "";
  905     }
  906 
  907     print ".SH ARGUMENTS\n";
  908     foreach $parameter (@{$args{'parameterlist'}}) {
  909         print ".IP \"".$parameter."\" 12\n";
  910         output_highlight($args{'parameterdescs'}{$parameter});
  911     }
  912     foreach $section (@{$args{'sectionlist'}}) {
  913         print ".SH \"", uc $section, "\"\n";
  914         output_highlight($args{'sections'}{$section});
  915     }
  916 }
  917 
  918 ##
  919 # output enum in man
  920 sub output_enum_man(%) {
  921     my %args = %{$_[0]};
  922     my ($parameter, $section);
  923     my $count;
  924 
  925     print ".TH \"$args{'module'}\" 9 \"enum $args{'enum'}\" \"$man_date\" \"API Manual\" LINUX\n";
  926 
  927     print ".SH NAME\n";
  928     print "enum ".$args{'enum'}." \\- ".$args{'purpose'}."\n";
  929 
  930     print ".SH SYNOPSIS\n";
  931     print "enum ".$args{'enum'}." {\n";
  932     $count = 0;
  933     foreach my $parameter (@{$args{'parameterlist'}}) {
  934         print ".br\n.BI \"    $parameter\"\n";
  935         if ($count == $#{$args{'parameterlist'}}) {
  936             print "\n};\n";
  937             last;
  938         }
  939         else {
  940             print ", \n.br\n";
  941         }
  942         $count++;
  943     }
  944 
  945     print ".SH Constants\n";
  946     foreach $parameter (@{$args{'parameterlist'}}) {
  947         print ".IP \"".$parameter."\" 12\n";
  948         output_highlight($args{'parameterdescs'}{$parameter});
  949     }
  950     foreach $section (@{$args{'sectionlist'}}) {
  951         print ".SH \"$section\"\n";
  952         output_highlight($args{'sections'}{$section});
  953     }
  954 }
  955 
  956 ##
  957 # output struct in man
  958 sub output_struct_man(%) {
  959     my %args = %{$_[0]};
  960     my ($parameter, $section);
  961 
  962     print ".TH \"$args{'module'}\" 9 \"".$args{'type'}." ".$args{'struct'}."\" \"$man_date\" \"API Manual\" LINUX\n";
  963 
  964     print ".SH NAME\n";
  965     print $args{'type'}." ".$args{'struct'}." \\- ".$args{'purpose'}."\n";
  966 
  967     print ".SH SYNOPSIS\n";
  968     print $args{'type'}." ".$args{'struct'}." {\n";
  969 
  970     foreach my $parameter (@{$args{'parameterlist'}}) {
  971         ($args{'parameterdescs'}{$parameter} ne $undescribed) || next;
  972         print "\n.br\n";
  973         $type = $args{'parametertypes'}{$parameter};
  974         if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
  975             # pointer-to-function
  976             print ".BI \"    ".$1."\" ".$parameter." \") (".$2.")"."\"\n;\n";
  977         } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
  978             print ".BI \"    ".$1."\" ".$parameter.$2." \""."\"\n;\n";
  979         } else {
  980             $type =~ s/([^\*])$/$1 /;
  981             print ".BI \"    ".$type."\" ".$parameter." \""."\"\n;\n";
  982         }
  983         print "\n.br\n";
  984     }
  985     print "};\n.br\n";
  986 
  987     print ".SH Arguments\n";
  988     foreach $parameter (@{$args{'parameterlist'}}) {
  989         ($args{'parameterdescs'}{$parameter} ne $undescribed) || next;
  990         print ".IP \"".$parameter."\" 12\n";
  991         output_highlight($args{'parameterdescs'}{$parameter});
  992     }
  993     foreach $section (@{$args{'sectionlist'}}) {
  994         print ".SH \"$section\"\n";
  995         output_highlight($args{'sections'}{$section});
  996     }
  997 }
  998 
  999 ##
 1000 # output typedef in man
 1001 sub output_typedef_man(%) {
 1002     my %args = %{$_[0]};
 1003     my ($parameter, $section);
 1004 
 1005     print ".TH \"$args{'module'}\" 9 \"$args{'typedef'}\" \"$man_date\" \"API Manual\" LINUX\n";
 1006 
 1007     print ".SH NAME\n";
 1008     print "typedef ".$args{'typedef'}." \\- ".$args{'purpose'}."\n";
 1009 
 1010     foreach $section (@{$args{'sectionlist'}}) {
 1011         print ".SH \"$section\"\n";
 1012         output_highlight($args{'sections'}{$section});
 1013     }
 1014 }
 1015 
 1016 sub output_intro_man(%) {
 1017     my %args = %{$_[0]};
 1018     my ($parameter, $section);
 1019     my $count;
 1020 
 1021     print ".TH \"$args{'module'}\" 9 \"$args{'module'}\" \"$man_date\" \"API Manual\" LINUX\n";
 1022 
 1023     foreach $section (@{$args{'sectionlist'}}) {
 1024         print ".SH \"$section\"\n";
 1025         output_highlight($args{'sections'}{$section});
 1026     }
 1027 }
 1028 
 1029 ##
 1030 # output in text
 1031 sub output_function_text(%) {
 1032     my %args = %{$_[0]};
 1033     my ($parameter, $section);
 1034 
 1035     print "Function:\n\n";
 1036     my $start=$args{'functiontype'}." ".$args{'function'}." (";
 1037     print $start;
 1038     my $count = 0;
 1039     foreach my $parameter (@{$args{'parameterlist'}}) {
 1040         $type = $args{'parametertypes'}{$parameter};
 1041         if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
 1042             # pointer-to-function
 1043             print $1.$parameter.") (".$2;
 1044         } else {
 1045             print $type." ".$parameter;
 1046         }
 1047         if ($count != $#{$args{'parameterlist'}}) {
 1048             $count++;
 1049             print ",\n";
 1050             print " " x length($start);
 1051         } else {
 1052             print ");\n\n";
 1053         }
 1054     }
 1055 
 1056     print "Arguments:\n\n";
 1057     foreach $parameter (@{$args{'parameterlist'}}) {
 1058         print $parameter."\n\t".$args{'parameterdescs'}{$parameter}."\n";
 1059     }
 1060     output_section_text(@_);
 1061 }
 1062 
 1063 #output sections in text
 1064 sub output_section_text(%) {
 1065     my %args = %{$_[0]};
 1066     my $section;
 1067 
 1068     print "\n";
 1069     foreach $section (@{$args{'sectionlist'}}) {
 1070         print "$section:\n\n";
 1071         output_highlight($args{'sections'}{$section});
 1072     }  
 1073     print "\n\n";
 1074 }
 1075 
 1076 # output enum in text
 1077 sub output_enum_text(%) {
 1078     my %args = %{$_[0]};
 1079     my ($parameter);
 1080     my $count;
 1081     print "Enum:\n\n";
 1082 
 1083     print "enum ".$args{'enum'}." {\n";
 1084     $count = 0;
 1085     foreach $parameter (@{$args{'parameterlist'}}) {
 1086         print "\t$parameter";
 1087         if ($count != $#{$args{'parameterlist'}}) {
 1088             $count++;
 1089             print ",";
 1090         }
 1091         print "\n";
 1092     }
 1093     print "};\n\n";
 1094 
 1095     print "Constants:\n\n";
 1096     foreach $parameter (@{$args{'parameterlist'}}) {
 1097         print "$parameter\n\t";
 1098         print $args{'parameterdescs'}{$parameter}."\n";
 1099     }
 1100 
 1101     output_section_text(@_);
 1102 }
 1103 
 1104 # output typedef in text
 1105 sub output_typedef_text(%) {
 1106     my %args = %{$_[0]};
 1107     my ($parameter);
 1108     my $count;
 1109     print "Typedef:\n\n";
 1110 
 1111     print "typedef ".$args{'typedef'}."\n";
 1112     output_section_text(@_);
 1113 }
 1114 
 1115 # output struct as text
 1116 sub output_struct_text(%) {
 1117     my %args = %{$_[0]};
 1118     my ($parameter);
 1119 
 1120     print $args{'type'}." ".$args{'struct'}.":\n\n";
 1121     print $args{'type'}." ".$args{'struct'}." {\n";
 1122     foreach $parameter (@{$args{'parameterlist'}}) {
 1123         ($args{'parameterdescs'}{$parameter} ne $undescribed) || next;
 1124         $type = $args{'parametertypes'}{$parameter};
 1125         if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
 1126             # pointer-to-function
 1127             print "\t$1 $parameter) ($2);\n";
 1128         } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
 1129             print "\t$1 $parameter$2;\n";
 1130         } else {
 1131             print "\t".$type." ".$parameter.";\n";
 1132         }
 1133     }
 1134     print "};\n\n";
 1135 
 1136     print "Members:\n\n";
 1137     foreach $parameter (@{$args{'parameterlist'}}) {
 1138         ($args{'parameterdescs'}{$parameter} ne $undescribed) || next;
 1139         print "$parameter\n\t";
 1140         print $args{'parameterdescs'}{$parameter}."\n";
 1141     }
 1142     print "\n";
 1143     output_section_text(@_);
 1144 }
 1145 
 1146 sub output_intro_text(%) {
 1147     my %args = %{$_[0]};
 1148     my ($parameter, $section);
 1149 
 1150     foreach $section (@{$args{'sectionlist'}}) {
 1151         print " $section:\n";
 1152         print "    -> ";
 1153         output_highlight($args{'sections'}{$section});
 1154     }
 1155 }
 1156 
 1157 ##
 1158 # generic output function for typedefs
 1159 sub output_declaration {
 1160     no strict 'refs';
 1161     my $name = shift;
 1162     my $functype = shift;
 1163     my $func = "output_${functype}_$output_mode";
 1164     if (($function_only==0) || 
 1165         ( $function_only == 1 && defined($function_table{$name})) || 
 1166         ( $function_only == 2 && !defined($function_table{$name})))
 1167     {
 1168         &$func(@_);
 1169         $section_counter++;
 1170     }
 1171 }
 1172 
 1173 ##
 1174 # generic output function - calls the right one based
 1175 # on current output mode.
 1176 sub output_intro {
 1177     no strict 'refs';
 1178     my $func = "output_intro_".$output_mode;
 1179     &$func(@_);
 1180     $section_counter++;
 1181 }
 1182 
 1183 ##
 1184 # takes a declaration (struct, union, enum, typedef) and 
 1185 # invokes the right handler. NOT called for functions.
 1186 sub dump_declaration($$) {
 1187     no strict 'refs';
 1188     my ($prototype, $file) = @_;
 1189     my $func = "dump_".$decl_type;
 1190     &$func(@_);
 1191 }
 1192 
 1193 sub dump_union($$) {
 1194     dump_struct(@_);
 1195 }
 1196 
 1197 sub dump_struct($$) {
 1198     my $x = shift;
 1199     my $file = shift;
 1200 
 1201     if ($x =~/(struct|union)\s+(\w+)\s*{(.*)}/) {
 1202         $declaration_name = $2;
 1203         my $members = $3;
 1204 
 1205         # ignore embedded structs or unions
 1206         $members =~ s/{.*}//g;
 1207 
 1208         create_parameterlist($members, ';', $file);
 1209 
 1210         output_declaration($declaration_name,
 1211                            'struct',
 1212                            {'struct' => $declaration_name,
 1213                             'module' => $modulename,
 1214                             'parameterlist' => \@parameterlist,
 1215                             'parameterdescs' => \%parameterdescs,
 1216                             'parametertypes' => \%parametertypes,
 1217                             'sectionlist' => \@sectionlist,
 1218                             'sections' => \%sections,
 1219                             'purpose' => $declaration_purpose,
 1220                             'type' => $decl_type
 1221                            });
 1222     }
 1223     else {
 1224         print STDERR "Error(${file}:$.): Cannot parse struct or union!\n";
 1225         ++$errors;
 1226     }
 1227 }
 1228 
 1229 sub dump_enum($$) {
 1230     my $x = shift;
 1231     my $file = shift;
 1232 
 1233     if ($x =~ /enum\s+(\w+)\s*{(.*)}/) {
 1234         $declaration_name = $1;
 1235         my $members = $2;
 1236 
 1237         foreach my $arg (split ',', $members) {
 1238             $arg =~ s/^\s*(\w+).*/$1/;
 1239             push @parameterlist, $arg;
 1240             if (!$parameterdescs{$arg}) {
 1241                 $parameterdescs{$arg} = $undescribed;
 1242                 print STDERR "Warning(${file}:$.): Enum value '$arg' ".
 1243                     "not described in enum '$declaration_name'\n";
 1244             }
 1245 
 1246         }
 1247         
 1248         output_declaration($declaration_name,
 1249                            'enum',
 1250                            {'enum' => $declaration_name,
 1251                             'module' => $modulename,
 1252                             'parameterlist' => \@parameterlist,
 1253                             'parameterdescs' => \%parameterdescs,
 1254                             'sectionlist' => \@sectionlist,
 1255                             'sections' => \%sections,
 1256                             'purpose' => $declaration_purpose
 1257                            });
 1258     }
 1259     else {
 1260         print STDERR "Error(${file}:$.): Cannot parse enum!\n";
 1261         ++$errors;
 1262     }
 1263 }
 1264 
 1265 sub dump_typedef($$) {
 1266     my $x = shift;
 1267     my $file = shift;
 1268 
 1269     while (($x =~ /\(*.\)\s*;$/) || ($x =~ /\[*.\]\s*;$/)) {
 1270         $x =~ s/\(*.\)\s*;$/;/;
 1271         $x =~ s/\[*.\]\s*;$/;/;
 1272     }
 1273 
 1274     if ($x =~ /typedef.*\s+(\w+)\s*;/) {
 1275         $declaration_name = $1;
 1276 
 1277         output_declaration($declaration_name,
 1278                            'typedef',
 1279                            {'typedef' => $declaration_name,
 1280                             'module' => $modulename,
 1281                             'sectionlist' => \@sectionlist,
 1282                             'sections' => \%sections,
 1283                             'purpose' => $declaration_purpose
 1284                            });
 1285     }
 1286     else {
 1287         print STDERR "Error(${file}:$.): Cannot parse typedef!\n";
 1288         ++$errors;
 1289     }
 1290 }
 1291 
 1292 sub create_parameterlist($$$) {
 1293     my $args = shift;
 1294     my $splitter = shift;
 1295     my $file = shift;
 1296     my $type;
 1297     my $param;
 1298 
 1299     while ($args =~ /(\([^\),]+),/) {
 1300         $args =~ s/(\([^\),]+),/$1#/g;
 1301     }
 1302     
 1303     foreach my $arg (split($splitter, $args)) {
 1304         # strip leading/trailing spaces
 1305         $arg =~ s/^\s*//;
 1306         $arg =~ s/\s*$//;
 1307         $arg =~ s/\s+/ /;
 1308 
 1309         if ($arg =~ m/\(/) {
 1310             # pointer-to-function
 1311             $arg =~ tr/#/,/;
 1312             $arg =~ m/[^\(]+\(\*([^\)]+)\)/;
 1313             $param = $1;
 1314             $type = $arg;
 1315             $type =~ s/([^\(]+\(\*)$param/$1/;
 1316         } else {
 1317             # evil magic to get fixed array parameters to work
 1318             $arg =~ s/(.+\s+)(.+)\[.*/$1* $2/;
 1319             my @args = split('\s', $arg);
 1320         
 1321             $param = pop @args;
 1322             if ($param =~ m/^(\*+)(.*)/) {
 1323                 $param = $2;
 1324                 push @args, $1;
 1325             } 
 1326             elsif ($param =~ m/(.*?)\s*:\s*(\d+)/) {
 1327                 $param = $1;
 1328                 push @args, ":$2";
 1329             }
 1330             $type = join " ", @args;
 1331         }
 1332 
 1333         if ($type eq "" && $param eq "...")
 1334         {
 1335             $type="...";
 1336             $param="...";
 1337             $parameterdescs{"..."} = "variable arguments";
 1338         }
 1339         elsif ($type eq "" && ($param eq "" or $param eq "void"))
 1340         {
 1341             $type="";
 1342             $param="void";
 1343             $parameterdescs{void} = "no arguments";
 1344         }
 1345         if (defined $type && $type && !defined $parameterdescs{$param}) {
 1346             $parameterdescs{$param} = $undescribed;
 1347 
 1348             if (($type eq 'function') || ($type eq 'enum')) {
 1349                 print STDERR "Warning(${file}:$.): Function parameter ".
 1350                     "or member '$param' not " .
 1351                     "described in '$declaration_name'\n";
 1352             }
 1353             ++$errors;
 1354         }
 1355 
 1356         push @parameterlist, $param;
 1357         $parametertypes{$param} = $type;
 1358     }
 1359 }
 1360 
 1361 ##
 1362 # takes a function prototype and the name of the current file being
 1363 # processed and spits out all the details stored in the global
 1364 # arrays/hashes.
 1365 sub dump_function($$) {
 1366     my $prototype = shift;
 1367     my $file = shift;
 1368 
 1369     $prototype =~ s/^static +//;
 1370     $prototype =~ s/^extern +//;
 1371     $prototype =~ s/^inline +//;
 1372     $prototype =~ s/^__inline__ +//;
 1373     $prototype =~ s/^#define +//; #ak added
 1374 
 1375     # Yes, this truly is vile.  We are looking for:
 1376     # 1. Return type (may be nothing if we're looking at a macro)
 1377     # 2. Function name
 1378     # 3. Function parameters.
 1379     #
 1380     # All the while we have to watch out for function pointer parameters
 1381     # (which IIRC is what the two sections are for), C types (these
 1382     # regexps don't even start to express all the possibilities), and
 1383     # so on.
 1384     #
 1385     # If you mess with these regexps, it's a good idea to check that
 1386     # the following functions' documentation still comes out right:
 1387     # - parport_register_device (function pointer parameters)
 1388     # - atomic_set (macro)
 1389     # - pci_match_device (long return type)
 1390 
 1391     if ($prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
 1392         $prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
 1393         $prototype =~ m/^(\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
 1394         $prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
 1395         $prototype =~ m/^(\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
 1396         $prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
 1397         $prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
 1398         $prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
 1399         $prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
 1400         $prototype =~ m/^(\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
 1401         $prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
 1402         $prototype =~ m/^(\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
 1403         $prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
 1404         $prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/)  {
 1405         $return_type = $1;
 1406         $declaration_name = $2;
 1407         my $args = $3;
 1408 
 1409         create_parameterlist($args, ',', $file);
 1410     } else {
 1411         print STDERR "Error(${file}:$.): cannot understand prototype: '$prototype'\n";
 1412         ++$errors;
 1413         return;
 1414     }
 1415 
 1416     output_declaration($declaration_name, 
 1417                        'function',
 1418                        {'function' => $declaration_name,
 1419                         'module' => $modulename,
 1420                         'functiontype' => $return_type,
 1421                         'parameterlist' => \@parameterlist,
 1422                         'parameterdescs' => \%parameterdescs,
 1423                         'parametertypes' => \%parametertypes,
 1424                         'sectionlist' => \@sectionlist,
 1425                         'sections' => \%sections,
 1426                         'purpose' => $declaration_purpose
 1427                        });
 1428 }
 1429 
 1430 sub process_file($);
 1431 
 1432 # Read the file that maps relative names to absolute names for
 1433 # separate source and object directories and for shadow trees.
 1434 if (open(SOURCE_MAP, "<.tmp_filelist.txt")) {
 1435         my ($relname, $absname);
 1436         while(<SOURCE_MAP>) {
 1437                 chop();
 1438                 ($relname, $absname) = (split())[0..1];
 1439                 $relname =~ s:^/+::;
 1440                 $source_map{$relname} = $absname;
 1441         }
 1442         close(SOURCE_MAP);
 1443 }
 1444 
 1445 if ($filelist) {
 1446         open(FLIST,"<$filelist") or die "Can't open file list $filelist";
 1447         while(<FLIST>) {
 1448                 chop;
 1449                 process_file($_);
 1450         }
 1451 }
 1452 
 1453 foreach (@ARGV) {
 1454     chomp;
 1455     process_file($_);
 1456 }
 1457 
 1458 exit($errors);
 1459 
 1460 sub reset_state {
 1461     $function = "";
 1462     %constants = ();
 1463     %parameterdescs = ();
 1464     %parametertypes = ();
 1465     @parameterlist = ();
 1466     %sections = ();
 1467     @sectionlist = ();
 1468     $prototype = "";
 1469     
 1470     $state = 0;
 1471 }
 1472 
 1473 sub process_state3_function($$) { 
 1474     my $x = shift;
 1475     my $file = shift;
 1476 
 1477     if ($x =~ m#\s*/\*\s+MACDOC\s*#io) {
 1478         # do nothing
 1479     }
 1480     elsif ($x =~ /([^\{]*)/) {
 1481         $prototype .= $1;
 1482     }
 1483     if (($x =~ /\{/) || ($x =~ /\#/) || ($x =~ /;/)) {
 1484         $prototype =~ s@/\*.*?\*/@@gos; # strip comments.
 1485         $prototype =~ s@[\r\n]+@ @gos; # strip newlines/cr's.
 1486         $prototype =~ s@^\s+@@gos; # strip leading spaces
 1487         dump_function($prototype,$file);
 1488         reset_state();
 1489     }
 1490 }
 1491 
 1492 sub process_state3_type($$) { 
 1493     my $x = shift;
 1494     my $file = shift;
 1495 
 1496     $x =~ s@/\*.*?\*/@@gos;     # strip comments.
 1497     $x =~ s@[\r\n]+@ @gos; # strip newlines/cr's.
 1498     $x =~ s@^\s+@@gos; # strip leading spaces
 1499     $x =~ s@\s+$@@gos; # strip trailing spaces
 1500 
 1501     while (1) {
 1502         if ( $x =~ /([^{};]*)([{};])(.*)/ ) {
 1503             $prototype .= $1 . $2;
 1504             ($2 eq '{') && $brcount++;
 1505             ($2 eq '}') && $brcount--;
 1506             if (($2 eq ';') && ($brcount == 0)) {
 1507                 dump_declaration($prototype,$file);
 1508                 reset_state();
 1509                 last;
 1510             }
 1511             $x = $3;
 1512         } else {
 1513             $prototype .= $x;
 1514             last;
 1515         }
 1516     }
 1517 }
 1518 
 1519 sub process_file($) {
 1520     my ($file) = @_;
 1521     my $identifier;
 1522     my $func;
 1523     my $initial_section_counter = $section_counter;
 1524 
 1525     if (defined($source_map{$file})) {
 1526         $file = $source_map{$file};
 1527     }
 1528 
 1529     if (!open(IN,"<$file")) {
 1530         print STDERR "Error: Cannot open file $file\n";
 1531         ++$errors;
 1532         return;
 1533     }
 1534 
 1535     $section_counter = 0;
 1536     while (<IN>) {
 1537         if ($state == 0) {
 1538             if (/$doc_start/o) {
 1539                 $state = 1;             # next line is always the function name
 1540             }
 1541         } elsif ($state == 1) { # this line is the function name (always)
 1542             if (/$doc_block/o) {
 1543                 $state = 4;
 1544                 $contents = "";
 1545                 if ( $1 eq "" ) {
 1546                         $section = $section_intro;
 1547                 } else {
 1548                         $section = $1;
 1549                 }
 1550             }
 1551             elsif (/$doc_decl/o) {
 1552                 $identifier = $1;
 1553                 if (/\s*([\w\s]+?)\s*-/) {
 1554                     $identifier = $1;
 1555                 }
 1556 
 1557                 $state = 2;
 1558                 if (/-(.*)/) {
 1559                     $declaration_purpose = $1;
 1560                 } else {
 1561                     $declaration_purpose = "";
 1562                 }
 1563                 if ($identifier =~ m/^struct/) {
 1564                     $decl_type = 'struct';
 1565                 } elsif ($identifier =~ m/^union/) {
 1566                     $decl_type = 'union';
 1567                 } elsif ($identifier =~ m/^enum/) {
 1568                     $decl_type = 'enum';
 1569                 } elsif ($identifier =~ m/^typedef/) {
 1570                     $decl_type = 'typedef';
 1571                 } else {
 1572                     $decl_type = 'function';
 1573                 }
 1574 
 1575                 if ($verbose) {
 1576                     print STDERR "Info(${file}:$.): Scanning doc for $identifier\n";
 1577                 }
 1578             } else {
 1579                 print STDERR "Warning(${file}:$.): Cannot understand $_ on line $.",
 1580                 " - I thought it was a doc line\n";
 1581                 ++$errors;
 1582                 $state = 0;
 1583             }
 1584         } elsif ($state == 2) { # look for head: lines, and include content
 1585             if (/$doc_sect/o) {
 1586                 $newsection = $1;
 1587                 $newcontents = $2;
 1588 
 1589                 if ($contents ne "") {
 1590                     $contents =~ s/\&/\\\\\\amp;/g;
 1591                     $contents =~ s/\</\\\\\\lt;/g;
 1592                     $contents =~ s/\>/\\\\\\gt;/g;
 1593                     dump_section($section, $contents);
 1594                     $section = $section_default;
 1595                 }
 1596 
 1597                 $contents = $newcontents;
 1598                 if ($contents ne "") {
 1599                     $contents .= "\n";
 1600                 }
 1601                 $section = $newsection;
 1602             } elsif (/$doc_end/) {
 1603 
 1604                 if ($contents ne "") {
 1605                     $contents =~ s/\&/\\\\\\amp;/g;
 1606                     $contents =~ s/\</\\\\\\lt;/g;
 1607                     $contents =~ s/\>/\\\\\\gt;/g;
 1608                     dump_section($section, $contents);
 1609                     $section = $section_default;
 1610                     $contents = "";
 1611                 }
 1612 
 1613                 $prototype = "";
 1614                 $state = 3;
 1615                 $brcount = 0;
 1616 #           print STDERR "end of doc comment, looking for prototype\n";
 1617             } elsif (/$doc_content/) {
 1618                 # miguel-style comment kludge, look for blank lines after
 1619                 # @parameter line to signify start of description
 1620                 if ($1 eq "" && 
 1621                         ($section =~ m/^@/ || $section eq $section_context)) {
 1622                     $contents =~ s/\&/\\\\\\amp;/g;
 1623                     $contents =~ s/\</\\\\\\lt;/g;
 1624                     $contents =~ s/\>/\\\\\\gt;/g;
 1625                     dump_section($section, $contents);
 1626                     $section = $section_default;
 1627                     $contents = "";
 1628                 } else {
 1629                     $contents .= $1."\n";
 1630                 }
 1631             } else {
 1632                 # i dont know - bad line?  ignore.
 1633                 print STDERR "Warning(${file}:$.): bad line: $_"; 
 1634                 ++$errors;
 1635             }
 1636         } elsif ($state == 3) { # scanning for function { (end of prototype)
 1637             if ($decl_type eq 'function') {
 1638                 process_state3_function($_, $file);
 1639             } else {
 1640                 process_state3_type($_, $file);
 1641             }
 1642         } elsif ($state == 4) {
 1643                 # Documentation block
 1644                 if (/$doc_block/) {
 1645                         dump_section($section, $contents);
 1646                         output_intro({'sectionlist' => \@sectionlist,
 1647                                       'sections' => \%sections });
 1648                         $contents = "";
 1649                         $function = "";
 1650                         %constants = ();
 1651                         %parameterdescs = ();
 1652                         %parametertypes = ();
 1653                         @parameterlist = ();
 1654                         %sections = ();
 1655                         @sectionlist = ();
 1656                         $prototype = "";
 1657                         if ( $1 eq "" ) {
 1658                                 $section = $section_intro;
 1659                         } else {
 1660                                 $section = $1;
 1661                         }
 1662                 }
 1663                 elsif (/$doc_end/)
 1664                 {
 1665                         dump_section($section, $contents);
 1666                         output_intro({'sectionlist' => \@sectionlist,
 1667                                       'sections' => \%sections });
 1668                         $contents = "";
 1669                         $function = "";
 1670                         %constants = ();
 1671                         %parameterdescs = ();
 1672                         %parametertypes = ();
 1673                         @parameterlist = ();
 1674                         %sections = ();
 1675                         @sectionlist = ();
 1676                         $prototype = "";
 1677                         $state = 0;
 1678                 }
 1679                 elsif (/$doc_content/)
 1680                 {
 1681                         if ( $1 eq "" )
 1682                         {
 1683                                 $contents .= $blankline;
 1684                         }
 1685                         else
 1686                         {
 1687                                 $contents .= $1 . "\n";
 1688                         }       
 1689                 }
 1690           }
 1691     }
 1692     if ($initial_section_counter == $section_counter) {
 1693         print STDERR "Warning(${file}): no structured comments found\n";
 1694         if ($output_mode eq "sgml") {
 1695             # The template wants at least one RefEntry here; make one.
 1696             print "<refentry>\n";
 1697             print " <refnamediv>\n";
 1698             print "  <refname>\n";
 1699             print "   ${file}\n";
 1700             print "  </refname>\n";
 1701             print "  <refpurpose>\n";
 1702             print "   Document generation inconsistency\n";
 1703             print "  </refpurpose>\n";
 1704             print " </refnamediv>\n";
 1705             print " <refsect1>\n";
 1706             print "  <title>\n";
 1707             print "   Oops\n";
 1708             print "  </title>\n";
 1709             print "  <warning>\n";
 1710             print "   <para>\n";
 1711             print "    The template for this document tried to insert\n";
 1712             print "    the structured comment from the file\n";
 1713             print "    <filename>${file}</filename> at this point,\n";
 1714             print "    but none was found.\n";
 1715             print "    This dummy section is inserted to allow\n";
 1716             print "    generation to continue.\n";
 1717             print "   </para>\n";
 1718             print "  </warning>\n";
 1719             print " </refsect1>\n";
 1720             print "</refentry>\n";
 1721         }
 1722     }
 1723 }

Cache object: 62ab40fdb6520f5dec4958a76a73d646


[ 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.