kernel-doc
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:46k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

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