]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - scripts/kernel-doc
.gitignore: drop include/asm from ignored file list
[karo-tx-uboot.git] / scripts / kernel-doc
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 ## Copyright (C) 2005-2012  Randy Dunlap                         ##
9 ## Copyright (C) 2012  Dan Luedtke                               ##
10 ##                                                               ##
11 ## #define enhancements by Armin Kuster <akuster@mvista.com>     ##
12 ## Copyright (c) 2000 MontaVista Software, Inc.                  ##
13 ##                                                               ##
14 ## This software falls under the GNU General Public License.     ##
15 ## Please read the COPYING file for more information             ##
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 # 25/07/2012 - Added support for HTML5
40 # -- Dan Luedtke <mail@danrl.de>
41
42 #
43 # This will read a 'c' file and scan for embedded comments in the
44 # style of gnome comments (+minor extensions - see below).
45 #
46
47 # Note: This only supports 'c'.
48
49 # usage:
50 # kernel-doc [ -docbook | -html | -html5 | -text | -man | -list ]
51 #            [ -no-doc-sections ]
52 #            [ -function funcname [ -function funcname ...] ]
53 #            c file(s)s > outputfile
54 # or
55 #            [ -nofunction funcname [ -function funcname ...] ]
56 #            c file(s)s > outputfile
57 #
58 #  Set output format using one of -docbook -html -html5 -text or -man.
59 #  Default is man.
60 #  The -list format is for internal use by docproc.
61 #
62 #  -no-doc-sections
63 #       Do not output DOC: sections
64 #
65 #  -function funcname
66 #       If set, then only generate documentation for the given function(s) or
67 #       DOC: section titles.  All other functions and DOC: sections are ignored.
68 #
69 #  -nofunction funcname
70 #       If set, then only generate documentation for the other function(s)/DOC:
71 #       sections. Cannot be used together with -function (yes, that's a bug --
72 #       perl hackers can fix it 8))
73 #
74 #  c files - list of 'c' files to process
75 #
76 #  All output goes to stdout, with errors to stderr.
77
78 #
79 # format of comments.
80 # In the following table, (...)? signifies optional structure.
81 #                         (...)* signifies 0 or more structure elements
82 # /**
83 #  * function_name(:)? (- short description)?
84 # (* @parameterx: (description of parameter x)?)*
85 # (* a blank line)?
86 #  * (Description:)? (Description of function)?
87 #  * (section header: (section description)? )*
88 #  (*)?*/
89 #
90 # So .. the trivial example would be:
91 #
92 # /**
93 #  * my_function
94 #  */
95 #
96 # If the Description: header tag is omitted, then there must be a blank line
97 # after the last parameter specification.
98 # e.g.
99 # /**
100 #  * my_function - does my stuff
101 #  * @my_arg: its mine damnit
102 #  *
103 #  * Does my stuff explained.
104 #  */
105 #
106 #  or, could also use:
107 # /**
108 #  * my_function - does my stuff
109 #  * @my_arg: its mine damnit
110 #  * Description: Does my stuff explained.
111 #  */
112 # etc.
113 #
114 # Besides functions you can also write documentation for structs, unions,
115 # enums and typedefs. Instead of the function name you must write the name
116 # of the declaration;  the struct/union/enum/typedef must always precede
117 # the name. Nesting of declarations is not supported.
118 # Use the argument mechanism to document members or constants.
119 # e.g.
120 # /**
121 #  * struct my_struct - short description
122 #  * @a: first member
123 #  * @b: second member
124 #  *
125 #  * Longer description
126 #  */
127 # struct my_struct {
128 #     int a;
129 #     int b;
130 # /* private: */
131 #     int c;
132 # };
133 #
134 # All descriptions can be multiline, except the short function description.
135 #
136 # You can also add additional sections. When documenting kernel functions you
137 # should document the "Context:" of the function, e.g. whether the functions
138 # can be called form interrupts. Unlike other sections you can end it with an
139 # empty line.
140 # Example-sections should contain the string EXAMPLE so that they are marked
141 # appropriately in DocBook.
142 #
143 # Example:
144 # /**
145 #  * user_function - function that can only be called in user context
146 #  * @a: some argument
147 #  * Context: !in_interrupt()
148 #  *
149 #  * Some description
150 #  * Example:
151 #  *    user_function(22);
152 #  */
153 # ...
154 #
155 #
156 # All descriptive text is further processed, scanning for the following special
157 # patterns, which are highlighted appropriately.
158 #
159 # 'funcname()' - function
160 # '$ENVVAR' - environmental variable
161 # '&struct_name' - name of a structure (up to two words including 'struct')
162 # '@parameter' - name of a parameter
163 # '%CONST' - name of a constant.
164
165 ## init lots of data
166
167 my $errors = 0;
168 my $warnings = 0;
169 my $anon_struct_union = 0;
170
171 # match expressions used to find embedded type information
172 my $type_constant = '\%([-_\w]+)';
173 my $type_func = '(\w+)\(\)';
174 my $type_param = '\@(\w+)';
175 my $type_struct = '\&((struct\s*)*[_\w]+)';
176 my $type_struct_xml = '\\&amp;((struct\s*)*[_\w]+)';
177 my $type_env = '(\$\w+)';
178
179 # Output conversion substitutions.
180 #  One for each output format
181
182 # these work fairly well
183 my %highlights_html = ( $type_constant, "<i>\$1</i>",
184                         $type_func, "<b>\$1</b>",
185                         $type_struct_xml, "<i>\$1</i>",
186                         $type_env, "<b><i>\$1</i></b>",
187                         $type_param, "<tt><b>\$1</b></tt>" );
188 my $local_lt = "\\\\\\\\lt:";
189 my $local_gt = "\\\\\\\\gt:";
190 my $blankline_html = $local_lt . "p" . $local_gt;       # was "<p>"
191
192 # html version 5
193 my %highlights_html5 = ( $type_constant, "<span class=\"const\">\$1</span>",
194                         $type_func, "<span class=\"func\">\$1</span>",
195                         $type_struct_xml, "<span class=\"struct\">\$1</span>",
196                         $type_env, "<span class=\"env\">\$1</span>",
197                         $type_param, "<span class=\"param\">\$1</span>" );
198 my $blankline_html5 = $local_lt . "br /" . $local_gt;
199
200 # XML, docbook format
201 my %highlights_xml = ( "([^=])\\\"([^\\\"<]+)\\\"", "\$1<quote>\$2</quote>",
202                         $type_constant, "<constant>\$1</constant>",
203                         $type_func, "<function>\$1</function>",
204                         $type_struct_xml, "<structname>\$1</structname>",
205                         $type_env, "<envar>\$1</envar>",
206                         $type_param, "<parameter>\$1</parameter>" );
207 my $blankline_xml = $local_lt . "/para" . $local_gt . $local_lt . "para" . $local_gt . "\n";
208
209 # gnome, docbook format
210 my %highlights_gnome = ( $type_constant, "<replaceable class=\"option\">\$1</replaceable>",
211                          $type_func, "<function>\$1</function>",
212                          $type_struct, "<structname>\$1</structname>",
213                          $type_env, "<envar>\$1</envar>",
214                          $type_param, "<parameter>\$1</parameter>" );
215 my $blankline_gnome = "</para><para>\n";
216
217 # these are pretty rough
218 my %highlights_man = ( $type_constant, "\$1",
219                        $type_func, "\\\\fB\$1\\\\fP",
220                        $type_struct, "\\\\fI\$1\\\\fP",
221                        $type_param, "\\\\fI\$1\\\\fP" );
222 my $blankline_man = "";
223
224 # text-mode
225 my %highlights_text = ( $type_constant, "\$1",
226                         $type_func, "\$1",
227                         $type_struct, "\$1",
228                         $type_param, "\$1" );
229 my $blankline_text = "";
230
231 # list mode
232 my %highlights_list = ( $type_constant, "\$1",
233                         $type_func, "\$1",
234                         $type_struct, "\$1",
235                         $type_param, "\$1" );
236 my $blankline_list = "";
237
238 # read arguments
239 if ($#ARGV == -1) {
240     usage();
241 }
242
243 my $kernelversion;
244 my $dohighlight = "";
245
246 my $verbose = 0;
247 my $output_mode = "man";
248 my $no_doc_sections = 0;
249 my %highlights = %highlights_man;
250 my $blankline = $blankline_man;
251 my $modulename = "Bootloader API";
252 my $function_only = 0;
253 my $man_date = ('January', 'February', 'March', 'April', 'May', 'June',
254                 'July', 'August', 'September', 'October',
255                 'November', 'December')[(localtime)[4]] .
256   " " . ((localtime)[5]+1900);
257
258 # Essentially these are globals.
259 # They probably want to be tidied up, made more localised or something.
260 # CAVEAT EMPTOR!  Some of the others I localised may not want to be, which
261 # could cause "use of undefined value" or other bugs.
262 my ($function, %function_table, %parametertypes, $declaration_purpose);
263 my ($type, $declaration_name, $return_type);
264 my ($newsection, $newcontents, $prototype, $brcount, %source_map);
265
266 if (defined($ENV{'KBUILD_VERBOSE'})) {
267         $verbose = "$ENV{'KBUILD_VERBOSE'}";
268 }
269
270 # Generated docbook code is inserted in a template at a point where
271 # docbook v3.1 requires a non-zero sequence of RefEntry's; see:
272 # http://www.oasis-open.org/docbook/documentation/reference/html/refentry.html
273 # We keep track of number of generated entries and generate a dummy
274 # if needs be to ensure the expanded template can be postprocessed
275 # into html.
276 my $section_counter = 0;
277
278 my $lineprefix="";
279
280 # states
281 # 0 - normal code
282 # 1 - looking for function name
283 # 2 - scanning field start.
284 # 3 - scanning prototype.
285 # 4 - documentation block
286 my $state;
287 my $in_doc_sect;
288
289 #declaration types: can be
290 # 'function', 'struct', 'union', 'enum', 'typedef'
291 my $decl_type;
292
293 my $doc_special = "\@\%\$\&";
294
295 my $doc_start = '^/\*\*\s*$'; # Allow whitespace at end of comment start.
296 my $doc_end = '\*/';
297 my $doc_com = '\s*\*\s*';
298 my $doc_decl = $doc_com . '(\w+)';
299 my $doc_sect = $doc_com . '([' . $doc_special . ']?[\w\s]+):(.*)';
300 my $doc_content = $doc_com . '(.*)';
301 my $doc_block = $doc_com . 'DOC:\s*(.*)?';
302
303 my %constants;
304 my %parameterdescs;
305 my @parameterlist;
306 my %sections;
307 my @sectionlist;
308 my $sectcheck;
309 my $struct_actual;
310
311 my $contents = "";
312 my $section_default = "Description";    # default section
313 my $section_intro = "Introduction";
314 my $section = $section_default;
315 my $section_context = "Context";
316
317 my $undescribed = "-- undescribed --";
318
319 reset_state();
320
321 while ($ARGV[0] =~ m/^-(.*)/) {
322     my $cmd = shift @ARGV;
323     if ($cmd eq "-html") {
324         $output_mode = "html";
325         %highlights = %highlights_html;
326         $blankline = $blankline_html;
327     } elsif ($cmd eq "-html5") {
328         $output_mode = "html5";
329         %highlights = %highlights_html5;
330         $blankline = $blankline_html5;
331     } elsif ($cmd eq "-man") {
332         $output_mode = "man";
333         %highlights = %highlights_man;
334         $blankline = $blankline_man;
335     } elsif ($cmd eq "-text") {
336         $output_mode = "text";
337         %highlights = %highlights_text;
338         $blankline = $blankline_text;
339     } elsif ($cmd eq "-docbook") {
340         $output_mode = "xml";
341         %highlights = %highlights_xml;
342         $blankline = $blankline_xml;
343     } elsif ($cmd eq "-list") {
344         $output_mode = "list";
345         %highlights = %highlights_list;
346         $blankline = $blankline_list;
347     } elsif ($cmd eq "-gnome") {
348         $output_mode = "gnome";
349         %highlights = %highlights_gnome;
350         $blankline = $blankline_gnome;
351     } elsif ($cmd eq "-module") { # not needed for XML, inherits from calling document
352         $modulename = shift @ARGV;
353     } elsif ($cmd eq "-function") { # to only output specific functions
354         $function_only = 1;
355         $function = shift @ARGV;
356         $function_table{$function} = 1;
357     } elsif ($cmd eq "-nofunction") { # to only output specific functions
358         $function_only = 2;
359         $function = shift @ARGV;
360         $function_table{$function} = 1;
361     } elsif ($cmd eq "-v") {
362         $verbose = 1;
363     } elsif (($cmd eq "-h") || ($cmd eq "--help")) {
364         usage();
365     } elsif ($cmd eq '-no-doc-sections') {
366             $no_doc_sections = 1;
367     }
368 }
369
370 # continue execution near EOF;
371
372 sub usage {
373     print "Usage: $0 [ -docbook | -html | -html5 | -text | -man | -list ]\n";
374     print "         [ -no-doc-sections ]\n";
375     print "         [ -function funcname [ -function funcname ...] ]\n";
376     print "         [ -nofunction funcname [ -nofunction funcname ...] ]\n";
377     print "         [ -v ]\n";
378     print "         c source file(s) > outputfile\n";
379     print "         -v : verbose output, more warnings & other info listed\n";
380     exit 1;
381 }
382
383 # get kernel version from env
384 sub get_kernel_version() {
385     my $version = 'unknown kernel version';
386
387     if (defined($ENV{'U_BOOT_VERSION'})) {
388         $version = $ENV{'U_BOOT_VERSION'};
389     }
390     return $version;
391 }
392
393 ##
394 # dumps section contents to arrays/hashes intended for that purpose.
395 #
396 sub dump_section {
397     my $file = shift;
398     my $name = shift;
399     my $contents = join "\n", @_;
400
401     if ($name =~ m/$type_constant/) {
402         $name = $1;
403 #       print STDERR "constant section '$1' = '$contents'\n";
404         $constants{$name} = $contents;
405     } elsif ($name =~ m/$type_param/) {
406 #       print STDERR "parameter def '$1' = '$contents'\n";
407         $name = $1;
408         $parameterdescs{$name} = $contents;
409         $sectcheck = $sectcheck . $name . " ";
410     } elsif ($name eq "@\.\.\.") {
411 #       print STDERR "parameter def '...' = '$contents'\n";
412         $name = "...";
413         $parameterdescs{$name} = $contents;
414         $sectcheck = $sectcheck . $name . " ";
415     } else {
416 #       print STDERR "other section '$name' = '$contents'\n";
417         if (defined($sections{$name}) && ($sections{$name} ne "")) {
418                 print STDERR "Error(${file}:$.): duplicate section name '$name'\n";
419                 ++$errors;
420         }
421         $sections{$name} = $contents;
422         push @sectionlist, $name;
423     }
424 }
425
426 ##
427 # dump DOC: section after checking that it should go out
428 #
429 sub dump_doc_section {
430     my $file = shift;
431     my $name = shift;
432     my $contents = join "\n", @_;
433
434     if ($no_doc_sections) {
435         return;
436     }
437
438     if (($function_only == 0) ||
439         ( $function_only == 1 && defined($function_table{$name})) ||
440         ( $function_only == 2 && !defined($function_table{$name})))
441     {
442         dump_section($file, $name, $contents);
443         output_blockhead({'sectionlist' => \@sectionlist,
444                           'sections' => \%sections,
445                           'module' => $modulename,
446                           'content-only' => ($function_only != 0), });
447     }
448 }
449
450 ##
451 # output function
452 #
453 # parameterdescs, a hash.
454 #  function => "function name"
455 #  parameterlist => @list of parameters
456 #  parameterdescs => %parameter descriptions
457 #  sectionlist => @list of sections
458 #  sections => %section descriptions
459 #
460
461 sub output_highlight {
462     my $contents = join "\n",@_;
463     my $line;
464
465 #   DEBUG
466 #   if (!defined $contents) {
467 #       use Carp;
468 #       confess "output_highlight got called with no args?\n";
469 #   }
470
471     if ($output_mode eq "html" || $output_mode eq "html5" ||
472         $output_mode eq "xml") {
473         $contents = local_unescape($contents);
474         # convert data read & converted thru xml_escape() into &xyz; format:
475         $contents =~ s/\\\\\\/\&/g;
476     }
477 #   print STDERR "contents b4:$contents\n";
478     eval $dohighlight;
479     die $@ if $@;
480 #   print STDERR "contents af:$contents\n";
481
482 #   strip whitespaces when generating html5
483     if ($output_mode eq "html5") {
484         $contents =~ s/^\s+//;
485         $contents =~ s/\s+$//;
486     }
487     foreach $line (split "\n", $contents) {
488         if ($line eq ""){
489             print $lineprefix, local_unescape($blankline);
490         } else {
491             $line =~ s/\\\\\\/\&/g;
492             if ($output_mode eq "man" && substr($line, 0, 1) eq ".") {
493                 print "\\&$line";
494             } else {
495                 print $lineprefix, $line;
496             }
497         }
498         print "\n";
499     }
500 }
501
502 # output sections in html
503 sub output_section_html(%) {
504     my %args = %{$_[0]};
505     my $section;
506
507     foreach $section (@{$args{'sectionlist'}}) {
508         print "<h3>$section</h3>\n";
509         print "<blockquote>\n";
510         output_highlight($args{'sections'}{$section});
511         print "</blockquote>\n";
512     }
513 }
514
515 # output enum in html
516 sub output_enum_html(%) {
517     my %args = %{$_[0]};
518     my ($parameter);
519     my $count;
520     print "<h2>enum " . $args{'enum'} . "</h2>\n";
521
522     print "<b>enum " . $args{'enum'} . "</b> {<br>\n";
523     $count = 0;
524     foreach $parameter (@{$args{'parameterlist'}}) {
525         print " <b>" . $parameter . "</b>";
526         if ($count != $#{$args{'parameterlist'}}) {
527             $count++;
528             print ",\n";
529         }
530         print "<br>";
531     }
532     print "};<br>\n";
533
534     print "<h3>Constants</h3>\n";
535     print "<dl>\n";
536     foreach $parameter (@{$args{'parameterlist'}}) {
537         print "<dt><b>" . $parameter . "</b>\n";
538         print "<dd>";
539         output_highlight($args{'parameterdescs'}{$parameter});
540     }
541     print "</dl>\n";
542     output_section_html(@_);
543     print "<hr>\n";
544 }
545
546 # output typedef in html
547 sub output_typedef_html(%) {
548     my %args = %{$_[0]};
549     my ($parameter);
550     my $count;
551     print "<h2>typedef " . $args{'typedef'} . "</h2>\n";
552
553     print "<b>typedef " . $args{'typedef'} . "</b>\n";
554     output_section_html(@_);
555     print "<hr>\n";
556 }
557
558 # output struct in html
559 sub output_struct_html(%) {
560     my %args = %{$_[0]};
561     my ($parameter);
562
563     print "<h2>" . $args{'type'} . " " . $args{'struct'} . " - " . $args{'purpose'} . "</h2>\n";
564     print "<b>" . $args{'type'} . " " . $args{'struct'} . "</b> {<br>\n";
565     foreach $parameter (@{$args{'parameterlist'}}) {
566         if ($parameter =~ /^#/) {
567                 print "$parameter<br>\n";
568                 next;
569         }
570         my $parameter_name = $parameter;
571         $parameter_name =~ s/\[.*//;
572
573         ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
574         $type = $args{'parametertypes'}{$parameter};
575         if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
576             # pointer-to-function
577             print "&nbsp; &nbsp; <i>$1</i><b>$parameter</b>) <i>($2)</i>;<br>\n";
578         } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
579             # bitfield
580             print "&nbsp; &nbsp; <i>$1</i> <b>$parameter</b>$2;<br>\n";
581         } else {
582             print "&nbsp; &nbsp; <i>$type</i> <b>$parameter</b>;<br>\n";
583         }
584     }
585     print "};<br>\n";
586
587     print "<h3>Members</h3>\n";
588     print "<dl>\n";
589     foreach $parameter (@{$args{'parameterlist'}}) {
590         ($parameter =~ /^#/) && next;
591
592         my $parameter_name = $parameter;
593         $parameter_name =~ s/\[.*//;
594
595         ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
596         print "<dt><b>" . $parameter . "</b>\n";
597         print "<dd>";
598         output_highlight($args{'parameterdescs'}{$parameter_name});
599     }
600     print "</dl>\n";
601     output_section_html(@_);
602     print "<hr>\n";
603 }
604
605 # output function in html
606 sub output_function_html(%) {
607     my %args = %{$_[0]};
608     my ($parameter, $section);
609     my $count;
610
611     print "<h2>" . $args{'function'} . " - " . $args{'purpose'} . "</h2>\n";
612     print "<i>" . $args{'functiontype'} . "</i>\n";
613     print "<b>" . $args{'function'} . "</b>\n";
614     print "(";
615     $count = 0;
616     foreach $parameter (@{$args{'parameterlist'}}) {
617         $type = $args{'parametertypes'}{$parameter};
618         if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
619             # pointer-to-function
620             print "<i>$1</i><b>$parameter</b>) <i>($2)</i>";
621         } else {
622             print "<i>" . $type . "</i> <b>" . $parameter . "</b>";
623         }
624         if ($count != $#{$args{'parameterlist'}}) {
625             $count++;
626             print ",\n";
627         }
628     }
629     print ")\n";
630
631     print "<h3>Arguments</h3>\n";
632     print "<dl>\n";
633     foreach $parameter (@{$args{'parameterlist'}}) {
634         my $parameter_name = $parameter;
635         $parameter_name =~ s/\[.*//;
636
637         ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
638         print "<dt><b>" . $parameter . "</b>\n";
639         print "<dd>";
640         output_highlight($args{'parameterdescs'}{$parameter_name});
641     }
642     print "</dl>\n";
643     output_section_html(@_);
644     print "<hr>\n";
645 }
646
647 # output DOC: block header in html
648 sub output_blockhead_html(%) {
649     my %args = %{$_[0]};
650     my ($parameter, $section);
651     my $count;
652
653     foreach $section (@{$args{'sectionlist'}}) {
654         print "<h3>$section</h3>\n";
655         print "<ul>\n";
656         output_highlight($args{'sections'}{$section});
657         print "</ul>\n";
658     }
659     print "<hr>\n";
660 }
661
662 # output sections in html5
663 sub output_section_html5(%) {
664     my %args = %{$_[0]};
665     my $section;
666
667     foreach $section (@{$args{'sectionlist'}}) {
668         print "<section>\n";
669         print "<h1>$section</h1>\n";
670         print "<p>\n";
671         output_highlight($args{'sections'}{$section});
672         print "</p>\n";
673         print "</section>\n";
674     }
675 }
676
677 # output enum in html5
678 sub output_enum_html5(%) {
679     my %args = %{$_[0]};
680     my ($parameter);
681     my $count;
682     my $html5id;
683
684     $html5id = $args{'enum'};
685     $html5id =~ s/[^a-zA-Z0-9\-]+/_/g;
686     print "<article class=\"enum\" id=\"enum:". $html5id . "\">";
687     print "<h1>enum " . $args{'enum'} . "</h1>\n";
688     print "<ol class=\"code\">\n";
689     print "<li>";
690     print "<span class=\"keyword\">enum</span> ";
691     print "<span class=\"identifier\">" . $args{'enum'} . "</span> {";
692     print "</li>\n";
693     $count = 0;
694     foreach $parameter (@{$args{'parameterlist'}}) {
695         print "<li class=\"indent\">";
696         print "<span class=\"param\">" . $parameter . "</span>";
697         if ($count != $#{$args{'parameterlist'}}) {
698             $count++;
699             print ",";
700         }
701         print "</li>\n";
702     }
703     print "<li>};</li>\n";
704     print "</ol>\n";
705
706     print "<section>\n";
707     print "<h1>Constants</h1>\n";
708     print "<dl>\n";
709     foreach $parameter (@{$args{'parameterlist'}}) {
710         print "<dt>" . $parameter . "</dt>\n";
711         print "<dd>";
712         output_highlight($args{'parameterdescs'}{$parameter});
713         print "</dd>\n";
714     }
715     print "</dl>\n";
716     print "</section>\n";
717     output_section_html5(@_);
718     print "</article>\n";
719 }
720
721 # output typedef in html5
722 sub output_typedef_html5(%) {
723     my %args = %{$_[0]};
724     my ($parameter);
725     my $count;
726     my $html5id;
727
728     $html5id = $args{'typedef'};
729     $html5id =~ s/[^a-zA-Z0-9\-]+/_/g;
730     print "<article class=\"typedef\" id=\"typedef:" . $html5id . "\">\n";
731     print "<h1>typedef " . $args{'typedef'} . "</h1>\n";
732
733     print "<ol class=\"code\">\n";
734     print "<li>";
735     print "<span class=\"keyword\">typedef</span> ";
736     print "<span class=\"identifier\">" . $args{'typedef'} . "</span>";
737     print "</li>\n";
738     print "</ol>\n";
739     output_section_html5(@_);
740     print "</article>\n";
741 }
742
743 # output struct in html5
744 sub output_struct_html5(%) {
745     my %args = %{$_[0]};
746     my ($parameter);
747     my $html5id;
748
749     $html5id = $args{'struct'};
750     $html5id =~ s/[^a-zA-Z0-9\-]+/_/g;
751     print "<article class=\"struct\" id=\"struct:" . $html5id . "\">\n";
752     print "<hgroup>\n";
753     print "<h1>" . $args{'type'} . " " . $args{'struct'} . "</h1>";
754     print "<h2>". $args{'purpose'} . "</h2>\n";
755     print "</hgroup>\n";
756     print "<ol class=\"code\">\n";
757     print "<li>";
758     print "<span class=\"type\">" . $args{'type'} . "</span> ";
759     print "<span class=\"identifier\">" . $args{'struct'} . "</span> {";
760     print "</li>\n";
761     foreach $parameter (@{$args{'parameterlist'}}) {
762         print "<li class=\"indent\">";
763         if ($parameter =~ /^#/) {
764                 print "<span class=\"param\">" . $parameter ."</span>\n";
765                 print "</li>\n";
766                 next;
767         }
768         my $parameter_name = $parameter;
769         $parameter_name =~ s/\[.*//;
770
771         ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
772         $type = $args{'parametertypes'}{$parameter};
773         if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
774             # pointer-to-function
775             print "<span class=\"type\">$1</span> ";
776             print "<span class=\"param\">$parameter</span>";
777             print "<span class=\"type\">)</span> ";
778             print "(<span class=\"args\">$2</span>);";
779         } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
780             # bitfield
781             print "<span class=\"type\">$1</span> ";
782             print "<span class=\"param\">$parameter</span>";
783             print "<span class=\"bits\">$2</span>;";
784         } else {
785             print "<span class=\"type\">$type</span> ";
786             print "<span class=\"param\">$parameter</span>;";
787         }
788         print "</li>\n";
789     }
790     print "<li>};</li>\n";
791     print "</ol>\n";
792
793     print "<section>\n";
794     print "<h1>Members</h1>\n";
795     print "<dl>\n";
796     foreach $parameter (@{$args{'parameterlist'}}) {
797         ($parameter =~ /^#/) && next;
798
799         my $parameter_name = $parameter;
800         $parameter_name =~ s/\[.*//;
801
802         ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
803         print "<dt>" . $parameter . "</dt>\n";
804         print "<dd>";
805         output_highlight($args{'parameterdescs'}{$parameter_name});
806         print "</dd>\n";
807     }
808     print "</dl>\n";
809     print "</section>\n";
810     output_section_html5(@_);
811     print "</article>\n";
812 }
813
814 # output function in html5
815 sub output_function_html5(%) {
816     my %args = %{$_[0]};
817     my ($parameter, $section);
818     my $count;
819     my $html5id;
820
821     $html5id = $args{'function'};
822     $html5id =~ s/[^a-zA-Z0-9\-]+/_/g;
823     print "<article class=\"function\" id=\"func:". $html5id . "\">\n";
824     print "<hgroup>\n";
825     print "<h1>" . $args{'function'} . "</h1>";
826     print "<h2>" . $args{'purpose'} . "</h2>\n";
827     print "</hgroup>\n";
828     print "<ol class=\"code\">\n";
829     print "<li>";
830     print "<span class=\"type\">" . $args{'functiontype'} . "</span> ";
831     print "<span class=\"identifier\">" . $args{'function'} . "</span> (";
832     print "</li>";
833     $count = 0;
834     foreach $parameter (@{$args{'parameterlist'}}) {
835         print "<li class=\"indent\">";
836         $type = $args{'parametertypes'}{$parameter};
837         if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
838             # pointer-to-function
839             print "<span class=\"type\">$1</span> ";
840             print "<span class=\"param\">$parameter</span>";
841             print "<span class=\"type\">)</span> ";
842             print "(<span class=\"args\">$2</span>)";
843         } else {
844             print "<span class=\"type\">$type</span> ";
845             print "<span class=\"param\">$parameter</span>";
846         }
847         if ($count != $#{$args{'parameterlist'}}) {
848             $count++;
849             print ",";
850         }
851         print "</li>\n";
852     }
853     print "<li>)</li>\n";
854     print "</ol>\n";
855
856     print "<section>\n";
857     print "<h1>Arguments</h1>\n";
858     print "<p>\n";
859     print "<dl>\n";
860     foreach $parameter (@{$args{'parameterlist'}}) {
861         my $parameter_name = $parameter;
862         $parameter_name =~ s/\[.*//;
863
864         ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
865         print "<dt>" . $parameter . "</dt>\n";
866         print "<dd>";
867         output_highlight($args{'parameterdescs'}{$parameter_name});
868         print "</dd>\n";
869     }
870     print "</dl>\n";
871     print "</section>\n";
872     output_section_html5(@_);
873     print "</article>\n";
874 }
875
876 # output DOC: block header in html5
877 sub output_blockhead_html5(%) {
878     my %args = %{$_[0]};
879     my ($parameter, $section);
880     my $count;
881     my $html5id;
882
883     foreach $section (@{$args{'sectionlist'}}) {
884         $html5id = $section;
885         $html5id =~ s/[^a-zA-Z0-9\-]+/_/g;
886         print "<article class=\"doc\" id=\"doc:". $html5id . "\">\n";
887         print "<h1>$section</h1>\n";
888         print "<p>\n";
889         output_highlight($args{'sections'}{$section});
890         print "</p>\n";
891     }
892     print "</article>\n";
893 }
894
895 sub output_section_xml(%) {
896     my %args = %{$_[0]};
897     my $section;
898     # print out each section
899     $lineprefix="   ";
900     foreach $section (@{$args{'sectionlist'}}) {
901         print "<refsect1>\n";
902         print "<title>$section</title>\n";
903         if ($section =~ m/EXAMPLE/i) {
904             print "<informalexample><programlisting>\n";
905         } else {
906             print "<para>\n";
907         }
908         output_highlight($args{'sections'}{$section});
909         if ($section =~ m/EXAMPLE/i) {
910             print "</programlisting></informalexample>\n";
911         } else {
912             print "</para>\n";
913         }
914         print "</refsect1>\n";
915     }
916 }
917
918 # output function in XML DocBook
919 sub output_function_xml(%) {
920     my %args = %{$_[0]};
921     my ($parameter, $section);
922     my $count;
923     my $id;
924
925     $id = "API-" . $args{'function'};
926     $id =~ s/[^A-Za-z0-9]/-/g;
927
928     print "<refentry id=\"$id\">\n";
929     print "<refentryinfo>\n";
930     print " <title>U-BOOT</title>\n";
931     print " <productname>Bootloader Hackers Manual</productname>\n";
932     print " <date>$man_date</date>\n";
933     print "</refentryinfo>\n";
934     print "<refmeta>\n";
935     print " <refentrytitle><phrase>" . $args{'function'} . "</phrase></refentrytitle>\n";
936     print " <manvolnum>9</manvolnum>\n";
937     print " <refmiscinfo class=\"version\">" . $kernelversion . "</refmiscinfo>\n";
938     print "</refmeta>\n";
939     print "<refnamediv>\n";
940     print " <refname>" . $args{'function'} . "</refname>\n";
941     print " <refpurpose>\n";
942     print "  ";
943     output_highlight ($args{'purpose'});
944     print " </refpurpose>\n";
945     print "</refnamediv>\n";
946
947     print "<refsynopsisdiv>\n";
948     print " <title>Synopsis</title>\n";
949     print "  <funcsynopsis><funcprototype>\n";
950     print "   <funcdef>" . $args{'functiontype'} . " ";
951     print "<function>" . $args{'function'} . " </function></funcdef>\n";
952
953     $count = 0;
954     if ($#{$args{'parameterlist'}} >= 0) {
955         foreach $parameter (@{$args{'parameterlist'}}) {
956             $type = $args{'parametertypes'}{$parameter};
957             if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
958                 # pointer-to-function
959                 print "   <paramdef>$1<parameter>$parameter</parameter>)\n";
960                 print "     <funcparams>$2</funcparams></paramdef>\n";
961             } else {
962                 print "   <paramdef>" . $type;
963                 print " <parameter>$parameter</parameter></paramdef>\n";
964             }
965         }
966     } else {
967         print "  <void/>\n";
968     }
969     print "  </funcprototype></funcsynopsis>\n";
970     print "</refsynopsisdiv>\n";
971
972     # print parameters
973     print "<refsect1>\n <title>Arguments</title>\n";
974     if ($#{$args{'parameterlist'}} >= 0) {
975         print " <variablelist>\n";
976         foreach $parameter (@{$args{'parameterlist'}}) {
977             my $parameter_name = $parameter;
978             $parameter_name =~ s/\[.*//;
979
980             print "  <varlistentry>\n   <term><parameter>$parameter</parameter></term>\n";
981             print "   <listitem>\n    <para>\n";
982             $lineprefix="     ";
983             output_highlight($args{'parameterdescs'}{$parameter_name});
984             print "    </para>\n   </listitem>\n  </varlistentry>\n";
985         }
986         print " </variablelist>\n";
987     } else {
988         print " <para>\n  None\n </para>\n";
989     }
990     print "</refsect1>\n";
991
992     output_section_xml(@_);
993     print "</refentry>\n\n";
994 }
995
996 # output struct in XML DocBook
997 sub output_struct_xml(%) {
998     my %args = %{$_[0]};
999     my ($parameter, $section);
1000     my $id;
1001
1002     $id = "API-struct-" . $args{'struct'};
1003     $id =~ s/[^A-Za-z0-9]/-/g;
1004
1005     print "<refentry id=\"$id\">\n";
1006     print "<refentryinfo>\n";
1007     print " <title>U-BOOT</title>\n";
1008     print " <productname>Bootloader Hackers Manual</productname>\n";
1009     print " <date>$man_date</date>\n";
1010     print "</refentryinfo>\n";
1011     print "<refmeta>\n";
1012     print " <refentrytitle><phrase>" . $args{'type'} . " " . $args{'struct'} . "</phrase></refentrytitle>\n";
1013     print " <manvolnum>9</manvolnum>\n";
1014     print " <refmiscinfo class=\"version\">" . $kernelversion . "</refmiscinfo>\n";
1015     print "</refmeta>\n";
1016     print "<refnamediv>\n";
1017     print " <refname>" . $args{'type'} . " " . $args{'struct'} . "</refname>\n";
1018     print " <refpurpose>\n";
1019     print "  ";
1020     output_highlight ($args{'purpose'});
1021     print " </refpurpose>\n";
1022     print "</refnamediv>\n";
1023
1024     print "<refsynopsisdiv>\n";
1025     print " <title>Synopsis</title>\n";
1026     print "  <programlisting>\n";
1027     print $args{'type'} . " " . $args{'struct'} . " {\n";
1028     foreach $parameter (@{$args{'parameterlist'}}) {
1029         if ($parameter =~ /^#/) {
1030             my $prm = $parameter;
1031             # convert data read & converted thru xml_escape() into &xyz; format:
1032             # This allows us to have #define macros interspersed in a struct.
1033             $prm =~ s/\\\\\\/\&/g;
1034             print "$prm\n";
1035             next;
1036         }
1037
1038         my $parameter_name = $parameter;
1039         $parameter_name =~ s/\[.*//;
1040
1041         defined($args{'parameterdescs'}{$parameter_name}) || next;
1042         ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
1043         $type = $args{'parametertypes'}{$parameter};
1044         if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
1045             # pointer-to-function
1046             print "  $1 $parameter) ($2);\n";
1047         } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
1048             # bitfield
1049             print "  $1 $parameter$2;\n";
1050         } else {
1051             print "  " . $type . " " . $parameter . ";\n";
1052         }
1053     }
1054     print "};";
1055     print "  </programlisting>\n";
1056     print "</refsynopsisdiv>\n";
1057
1058     print " <refsect1>\n";
1059     print "  <title>Members</title>\n";
1060
1061     if ($#{$args{'parameterlist'}} >= 0) {
1062     print "  <variablelist>\n";
1063     foreach $parameter (@{$args{'parameterlist'}}) {
1064       ($parameter =~ /^#/) && next;
1065
1066       my $parameter_name = $parameter;
1067       $parameter_name =~ s/\[.*//;
1068
1069       defined($args{'parameterdescs'}{$parameter_name}) || next;
1070       ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
1071       print "    <varlistentry>";
1072       print "      <term>$parameter</term>\n";
1073       print "      <listitem><para>\n";
1074       output_highlight($args{'parameterdescs'}{$parameter_name});
1075       print "      </para></listitem>\n";
1076       print "    </varlistentry>\n";
1077     }
1078     print "  </variablelist>\n";
1079     } else {
1080         print " <para>\n  None\n </para>\n";
1081     }
1082     print " </refsect1>\n";
1083
1084     output_section_xml(@_);
1085
1086     print "</refentry>\n\n";
1087 }
1088
1089 # output enum in XML DocBook
1090 sub output_enum_xml(%) {
1091     my %args = %{$_[0]};
1092     my ($parameter, $section);
1093     my $count;
1094     my $id;
1095
1096     $id = "API-enum-" . $args{'enum'};
1097     $id =~ s/[^A-Za-z0-9]/-/g;
1098
1099     print "<refentry id=\"$id\">\n";
1100     print "<refentryinfo>\n";
1101     print " <title>U-BOOT</title>\n";
1102     print " <productname>Bootloader Hackers Manual</productname>\n";
1103     print " <date>$man_date</date>\n";
1104     print "</refentryinfo>\n";
1105     print "<refmeta>\n";
1106     print " <refentrytitle><phrase>enum " . $args{'enum'} . "</phrase></refentrytitle>\n";
1107     print " <manvolnum>9</manvolnum>\n";
1108     print " <refmiscinfo class=\"version\">" . $kernelversion . "</refmiscinfo>\n";
1109     print "</refmeta>\n";
1110     print "<refnamediv>\n";
1111     print " <refname>enum " . $args{'enum'} . "</refname>\n";
1112     print " <refpurpose>\n";
1113     print "  ";
1114     output_highlight ($args{'purpose'});
1115     print " </refpurpose>\n";
1116     print "</refnamediv>\n";
1117
1118     print "<refsynopsisdiv>\n";
1119     print " <title>Synopsis</title>\n";
1120     print "  <programlisting>\n";
1121     print "enum " . $args{'enum'} . " {\n";
1122     $count = 0;
1123     foreach $parameter (@{$args{'parameterlist'}}) {
1124         print "  $parameter";
1125         if ($count != $#{$args{'parameterlist'}}) {
1126             $count++;
1127             print ",";
1128         }
1129         print "\n";
1130     }
1131     print "};";
1132     print "  </programlisting>\n";
1133     print "</refsynopsisdiv>\n";
1134
1135     print "<refsect1>\n";
1136     print " <title>Constants</title>\n";
1137     print "  <variablelist>\n";
1138     foreach $parameter (@{$args{'parameterlist'}}) {
1139       my $parameter_name = $parameter;
1140       $parameter_name =~ s/\[.*//;
1141
1142       print "    <varlistentry>";
1143       print "      <term>$parameter</term>\n";
1144       print "      <listitem><para>\n";
1145       output_highlight($args{'parameterdescs'}{$parameter_name});
1146       print "      </para></listitem>\n";
1147       print "    </varlistentry>\n";
1148     }
1149     print "  </variablelist>\n";
1150     print "</refsect1>\n";
1151
1152     output_section_xml(@_);
1153
1154     print "</refentry>\n\n";
1155 }
1156
1157 # output typedef in XML DocBook
1158 sub output_typedef_xml(%) {
1159     my %args = %{$_[0]};
1160     my ($parameter, $section);
1161     my $id;
1162
1163     $id = "API-typedef-" . $args{'typedef'};
1164     $id =~ s/[^A-Za-z0-9]/-/g;
1165
1166     print "<refentry id=\"$id\">\n";
1167     print "<refentryinfo>\n";
1168     print " <title>U-BOOT</title>\n";
1169     print " <productname>Bootloader Hackers Manual</productname>\n";
1170     print " <date>$man_date</date>\n";
1171     print "</refentryinfo>\n";
1172     print "<refmeta>\n";
1173     print " <refentrytitle><phrase>typedef " . $args{'typedef'} . "</phrase></refentrytitle>\n";
1174     print " <manvolnum>9</manvolnum>\n";
1175     print "</refmeta>\n";
1176     print "<refnamediv>\n";
1177     print " <refname>typedef " . $args{'typedef'} . "</refname>\n";
1178     print " <refpurpose>\n";
1179     print "  ";
1180     output_highlight ($args{'purpose'});
1181     print " </refpurpose>\n";
1182     print "</refnamediv>\n";
1183
1184     print "<refsynopsisdiv>\n";
1185     print " <title>Synopsis</title>\n";
1186     print "  <synopsis>typedef " . $args{'typedef'} . ";</synopsis>\n";
1187     print "</refsynopsisdiv>\n";
1188
1189     output_section_xml(@_);
1190
1191     print "</refentry>\n\n";
1192 }
1193
1194 # output in XML DocBook
1195 sub output_blockhead_xml(%) {
1196     my %args = %{$_[0]};
1197     my ($parameter, $section);
1198     my $count;
1199
1200     my $id = $args{'module'};
1201     $id =~ s/[^A-Za-z0-9]/-/g;
1202
1203     # print out each section
1204     $lineprefix="   ";
1205     foreach $section (@{$args{'sectionlist'}}) {
1206         if (!$args{'content-only'}) {
1207                 print "<refsect1>\n <title>$section</title>\n";
1208         }
1209         if ($section =~ m/EXAMPLE/i) {
1210             print "<example><para>\n";
1211         } else {
1212             print "<para>\n";
1213         }
1214         output_highlight($args{'sections'}{$section});
1215         if ($section =~ m/EXAMPLE/i) {
1216             print "</para></example>\n";
1217         } else {
1218             print "</para>";
1219         }
1220         if (!$args{'content-only'}) {
1221                 print "\n</refsect1>\n";
1222         }
1223     }
1224
1225     print "\n\n";
1226 }
1227
1228 # output in XML DocBook
1229 sub output_function_gnome {
1230     my %args = %{$_[0]};
1231     my ($parameter, $section);
1232     my $count;
1233     my $id;
1234
1235     $id = $args{'module'} . "-" . $args{'function'};
1236     $id =~ s/[^A-Za-z0-9]/-/g;
1237
1238     print "<sect2>\n";
1239     print " <title id=\"$id\">" . $args{'function'} . "</title>\n";
1240
1241     print "  <funcsynopsis>\n";
1242     print "   <funcdef>" . $args{'functiontype'} . " ";
1243     print "<function>" . $args{'function'} . " ";
1244     print "</function></funcdef>\n";
1245
1246     $count = 0;
1247     if ($#{$args{'parameterlist'}} >= 0) {
1248         foreach $parameter (@{$args{'parameterlist'}}) {
1249             $type = $args{'parametertypes'}{$parameter};
1250             if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
1251                 # pointer-to-function
1252                 print "   <paramdef>$1 <parameter>$parameter</parameter>)\n";
1253                 print "     <funcparams>$2</funcparams></paramdef>\n";
1254             } else {
1255                 print "   <paramdef>" . $type;
1256                 print " <parameter>$parameter</parameter></paramdef>\n";
1257             }
1258         }
1259     } else {
1260         print "  <void>\n";
1261     }
1262     print "  </funcsynopsis>\n";
1263     if ($#{$args{'parameterlist'}} >= 0) {
1264         print " <informaltable pgwide=\"1\" frame=\"none\" role=\"params\">\n";
1265         print "<tgroup cols=\"2\">\n";
1266         print "<colspec colwidth=\"2*\">\n";
1267         print "<colspec colwidth=\"8*\">\n";
1268         print "<tbody>\n";
1269         foreach $parameter (@{$args{'parameterlist'}}) {
1270             my $parameter_name = $parameter;
1271             $parameter_name =~ s/\[.*//;
1272
1273             print "  <row><entry align=\"right\"><parameter>$parameter</parameter></entry>\n";
1274             print "   <entry>\n";
1275             $lineprefix="     ";
1276             output_highlight($args{'parameterdescs'}{$parameter_name});
1277             print "    </entry></row>\n";
1278         }
1279         print " </tbody></tgroup></informaltable>\n";
1280     } else {
1281         print " <para>\n  None\n </para>\n";
1282     }
1283
1284     # print out each section
1285     $lineprefix="   ";
1286     foreach $section (@{$args{'sectionlist'}}) {
1287         print "<simplesect>\n <title>$section</title>\n";
1288         if ($section =~ m/EXAMPLE/i) {
1289             print "<example><programlisting>\n";
1290         } else {
1291         }
1292         print "<para>\n";
1293         output_highlight($args{'sections'}{$section});
1294         print "</para>\n";
1295         if ($section =~ m/EXAMPLE/i) {
1296             print "</programlisting></example>\n";
1297         } else {
1298         }
1299         print " </simplesect>\n";
1300     }
1301
1302     print "</sect2>\n\n";
1303 }
1304
1305 ##
1306 # output function in man
1307 sub output_function_man(%) {
1308     my %args = %{$_[0]};
1309     my ($parameter, $section);
1310     my $count;
1311
1312     print ".TH \"$args{'function'}\" 9 \"$args{'function'}\" \"$man_date\" \"Bootloader Hacker's Manual\" U-BOOT\n";
1313
1314     print ".SH NAME\n";
1315     print $args{'function'} . " \\- " . $args{'purpose'} . "\n";
1316
1317     print ".SH SYNOPSIS\n";
1318     if ($args{'functiontype'} ne "") {
1319         print ".B \"" . $args{'functiontype'} . "\" " . $args{'function'} . "\n";
1320     } else {
1321         print ".B \"" . $args{'function'} . "\n";
1322     }
1323     $count = 0;
1324     my $parenth = "(";
1325     my $post = ",";
1326     foreach my $parameter (@{$args{'parameterlist'}}) {
1327         if ($count == $#{$args{'parameterlist'}}) {
1328             $post = ");";
1329         }
1330         $type = $args{'parametertypes'}{$parameter};
1331         if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
1332             # pointer-to-function
1333             print ".BI \"" . $parenth . $1 . "\" " . $parameter . " \") (" . $2 . ")" . $post . "\"\n";
1334         } else {
1335             $type =~ s/([^\*])$/$1 /;
1336             print ".BI \"" . $parenth . $type . "\" " . $parameter . " \"" . $post . "\"\n";
1337         }
1338         $count++;
1339         $parenth = "";
1340     }
1341
1342     print ".SH ARGUMENTS\n";
1343     foreach $parameter (@{$args{'parameterlist'}}) {
1344         my $parameter_name = $parameter;
1345         $parameter_name =~ s/\[.*//;
1346
1347         print ".IP \"" . $parameter . "\" 12\n";
1348         output_highlight($args{'parameterdescs'}{$parameter_name});
1349     }
1350     foreach $section (@{$args{'sectionlist'}}) {
1351         print ".SH \"", uc $section, "\"\n";
1352         output_highlight($args{'sections'}{$section});
1353     }
1354 }
1355
1356 ##
1357 # output enum in man
1358 sub output_enum_man(%) {
1359     my %args = %{$_[0]};
1360     my ($parameter, $section);
1361     my $count;
1362
1363     print ".TH \"$args{'module'}\" 9 \"enum $args{'enum'}\" \"$man_date\" \"API Manual\" U-BOOT\n";
1364
1365     print ".SH NAME\n";
1366     print "enum " . $args{'enum'} . " \\- " . $args{'purpose'} . "\n";
1367
1368     print ".SH SYNOPSIS\n";
1369     print "enum " . $args{'enum'} . " {\n";
1370     $count = 0;
1371     foreach my $parameter (@{$args{'parameterlist'}}) {
1372         print ".br\n.BI \"    $parameter\"\n";
1373         if ($count == $#{$args{'parameterlist'}}) {
1374             print "\n};\n";
1375             last;
1376         }
1377         else {
1378             print ", \n.br\n";
1379         }
1380         $count++;
1381     }
1382
1383     print ".SH Constants\n";
1384     foreach $parameter (@{$args{'parameterlist'}}) {
1385         my $parameter_name = $parameter;
1386         $parameter_name =~ s/\[.*//;
1387
1388         print ".IP \"" . $parameter . "\" 12\n";
1389         output_highlight($args{'parameterdescs'}{$parameter_name});
1390     }
1391     foreach $section (@{$args{'sectionlist'}}) {
1392         print ".SH \"$section\"\n";
1393         output_highlight($args{'sections'}{$section});
1394     }
1395 }
1396
1397 ##
1398 # output struct in man
1399 sub output_struct_man(%) {
1400     my %args = %{$_[0]};
1401     my ($parameter, $section);
1402
1403     print ".TH \"$args{'module'}\" 9 \"" . $args{'type'} . " " . $args{'struct'} . "\" \"$man_date\" \"API Manual\" U-BOOT\n";
1404
1405     print ".SH NAME\n";
1406     print $args{'type'} . " " . $args{'struct'} . " \\- " . $args{'purpose'} . "\n";
1407
1408     print ".SH SYNOPSIS\n";
1409     print $args{'type'} . " " . $args{'struct'} . " {\n.br\n";
1410
1411     foreach my $parameter (@{$args{'parameterlist'}}) {
1412         if ($parameter =~ /^#/) {
1413             print ".BI \"$parameter\"\n.br\n";
1414             next;
1415         }
1416         my $parameter_name = $parameter;
1417         $parameter_name =~ s/\[.*//;
1418
1419         ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
1420         $type = $args{'parametertypes'}{$parameter};
1421         if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
1422             # pointer-to-function
1423             print ".BI \"    " . $1 . "\" " . $parameter . " \") (" . $2 . ")" . "\"\n;\n";
1424         } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
1425             # bitfield
1426             print ".BI \"    " . $1 . "\ \" " . $parameter . $2 . " \"" . "\"\n;\n";
1427         } else {
1428             $type =~ s/([^\*])$/$1 /;
1429             print ".BI \"    " . $type . "\" " . $parameter . " \"" . "\"\n;\n";
1430         }
1431         print "\n.br\n";
1432     }
1433     print "};\n.br\n";
1434
1435     print ".SH Members\n";
1436     foreach $parameter (@{$args{'parameterlist'}}) {
1437         ($parameter =~ /^#/) && next;
1438
1439         my $parameter_name = $parameter;
1440         $parameter_name =~ s/\[.*//;
1441
1442         ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
1443         print ".IP \"" . $parameter . "\" 12\n";
1444         output_highlight($args{'parameterdescs'}{$parameter_name});
1445     }
1446     foreach $section (@{$args{'sectionlist'}}) {
1447         print ".SH \"$section\"\n";
1448         output_highlight($args{'sections'}{$section});
1449     }
1450 }
1451
1452 ##
1453 # output typedef in man
1454 sub output_typedef_man(%) {
1455     my %args = %{$_[0]};
1456     my ($parameter, $section);
1457
1458     print ".TH \"$args{'module'}\" 9 \"$args{'typedef'}\" \"$man_date\" \"API Manual\" U-BOOT\n";
1459
1460     print ".SH NAME\n";
1461     print "typedef " . $args{'typedef'} . " \\- " . $args{'purpose'} . "\n";
1462
1463     foreach $section (@{$args{'sectionlist'}}) {
1464         print ".SH \"$section\"\n";
1465         output_highlight($args{'sections'}{$section});
1466     }
1467 }
1468
1469 sub output_blockhead_man(%) {
1470     my %args = %{$_[0]};
1471     my ($parameter, $section);
1472     my $count;
1473
1474     print ".TH \"$args{'module'}\" 9 \"$args{'module'}\" \"$man_date\" \"API Manual\" U-BOOT\n";
1475
1476     foreach $section (@{$args{'sectionlist'}}) {
1477         print ".SH \"$section\"\n";
1478         output_highlight($args{'sections'}{$section});
1479     }
1480 }
1481
1482 ##
1483 # output in text
1484 sub output_function_text(%) {
1485     my %args = %{$_[0]};
1486     my ($parameter, $section);
1487     my $start;
1488
1489     print "Name:\n\n";
1490     print $args{'function'} . " - " . $args{'purpose'} . "\n";
1491
1492     print "\nSynopsis:\n\n";
1493     if ($args{'functiontype'} ne "") {
1494         $start = $args{'functiontype'} . " " . $args{'function'} . " (";
1495     } else {
1496         $start = $args{'function'} . " (";
1497     }
1498     print $start;
1499
1500     my $count = 0;
1501     foreach my $parameter (@{$args{'parameterlist'}}) {
1502         $type = $args{'parametertypes'}{$parameter};
1503         if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
1504             # pointer-to-function
1505             print $1 . $parameter . ") (" . $2;
1506         } else {
1507             print $type . " " . $parameter;
1508         }
1509         if ($count != $#{$args{'parameterlist'}}) {
1510             $count++;
1511             print ",\n";
1512             print " " x length($start);
1513         } else {
1514             print ");\n\n";
1515         }
1516     }
1517
1518     print "Arguments:\n\n";
1519     foreach $parameter (@{$args{'parameterlist'}}) {
1520         my $parameter_name = $parameter;
1521         $parameter_name =~ s/\[.*//;
1522
1523         print $parameter . "\n\t" . $args{'parameterdescs'}{$parameter_name} . "\n";
1524     }
1525     output_section_text(@_);
1526 }
1527
1528 #output sections in text
1529 sub output_section_text(%) {
1530     my %args = %{$_[0]};
1531     my $section;
1532
1533     print "\n";
1534     foreach $section (@{$args{'sectionlist'}}) {
1535         print "$section:\n\n";
1536         output_highlight($args{'sections'}{$section});
1537     }
1538     print "\n\n";
1539 }
1540
1541 # output enum in text
1542 sub output_enum_text(%) {
1543     my %args = %{$_[0]};
1544     my ($parameter);
1545     my $count;
1546     print "Enum:\n\n";
1547
1548     print "enum " . $args{'enum'} . " - " . $args{'purpose'} . "\n\n";
1549     print "enum " . $args{'enum'} . " {\n";
1550     $count = 0;
1551     foreach $parameter (@{$args{'parameterlist'}}) {
1552         print "\t$parameter";
1553         if ($count != $#{$args{'parameterlist'}}) {
1554             $count++;
1555             print ",";
1556         }
1557         print "\n";
1558     }
1559     print "};\n\n";
1560
1561     print "Constants:\n\n";
1562     foreach $parameter (@{$args{'parameterlist'}}) {
1563         print "$parameter\n\t";
1564         print $args{'parameterdescs'}{$parameter} . "\n";
1565     }
1566
1567     output_section_text(@_);
1568 }
1569
1570 # output typedef in text
1571 sub output_typedef_text(%) {
1572     my %args = %{$_[0]};
1573     my ($parameter);
1574     my $count;
1575     print "Typedef:\n\n";
1576
1577     print "typedef " . $args{'typedef'} . " - " . $args{'purpose'} . "\n";
1578     output_section_text(@_);
1579 }
1580
1581 # output struct as text
1582 sub output_struct_text(%) {
1583     my %args = %{$_[0]};
1584     my ($parameter);
1585
1586     print $args{'type'} . " " . $args{'struct'} . " - " . $args{'purpose'} . "\n\n";
1587     print $args{'type'} . " " . $args{'struct'} . " {\n";
1588     foreach $parameter (@{$args{'parameterlist'}}) {
1589         if ($parameter =~ /^#/) {
1590             print "$parameter\n";
1591             next;
1592         }
1593
1594         my $parameter_name = $parameter;
1595         $parameter_name =~ s/\[.*//;
1596
1597         ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
1598         $type = $args{'parametertypes'}{$parameter};
1599         if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
1600             # pointer-to-function
1601             print "\t$1 $parameter) ($2);\n";
1602         } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
1603             # bitfield
1604             print "\t$1 $parameter$2;\n";
1605         } else {
1606             print "\t" . $type . " " . $parameter . ";\n";
1607         }
1608     }
1609     print "};\n\n";
1610
1611     print "Members:\n\n";
1612     foreach $parameter (@{$args{'parameterlist'}}) {
1613         ($parameter =~ /^#/) && next;
1614
1615         my $parameter_name = $parameter;
1616         $parameter_name =~ s/\[.*//;
1617
1618         ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
1619         print "$parameter\n\t";
1620         print $args{'parameterdescs'}{$parameter_name} . "\n";
1621     }
1622     print "\n";
1623     output_section_text(@_);
1624 }
1625
1626 sub output_blockhead_text(%) {
1627     my %args = %{$_[0]};
1628     my ($parameter, $section);
1629
1630     foreach $section (@{$args{'sectionlist'}}) {
1631         print " $section:\n";
1632         print "    -> ";
1633         output_highlight($args{'sections'}{$section});
1634     }
1635 }
1636
1637 ## list mode output functions
1638
1639 sub output_function_list(%) {
1640     my %args = %{$_[0]};
1641
1642     print $args{'function'} . "\n";
1643 }
1644
1645 # output enum in list
1646 sub output_enum_list(%) {
1647     my %args = %{$_[0]};
1648     print $args{'enum'} . "\n";
1649 }
1650
1651 # output typedef in list
1652 sub output_typedef_list(%) {
1653     my %args = %{$_[0]};
1654     print $args{'typedef'} . "\n";
1655 }
1656
1657 # output struct as list
1658 sub output_struct_list(%) {
1659     my %args = %{$_[0]};
1660
1661     print $args{'struct'} . "\n";
1662 }
1663
1664 sub output_blockhead_list(%) {
1665     my %args = %{$_[0]};
1666     my ($parameter, $section);
1667
1668     foreach $section (@{$args{'sectionlist'}}) {
1669         print "DOC: $section\n";
1670     }
1671 }
1672
1673 ##
1674 # generic output function for all types (function, struct/union, typedef, enum);
1675 # calls the generated, variable output_ function name based on
1676 # functype and output_mode
1677 sub output_declaration {
1678     no strict 'refs';
1679     my $name = shift;
1680     my $functype = shift;
1681     my $func = "output_${functype}_$output_mode";
1682     if (($function_only==0) ||
1683         ( $function_only == 1 && defined($function_table{$name})) ||
1684         ( $function_only == 2 && !defined($function_table{$name})))
1685     {
1686         &$func(@_);
1687         $section_counter++;
1688     }
1689 }
1690
1691 ##
1692 # generic output function - calls the right one based on current output mode.
1693 sub output_blockhead {
1694     no strict 'refs';
1695     my $func = "output_blockhead_" . $output_mode;
1696     &$func(@_);
1697     $section_counter++;
1698 }
1699
1700 ##
1701 # takes a declaration (struct, union, enum, typedef) and
1702 # invokes the right handler. NOT called for functions.
1703 sub dump_declaration($$) {
1704     no strict 'refs';
1705     my ($prototype, $file) = @_;
1706     my $func = "dump_" . $decl_type;
1707     &$func(@_);
1708 }
1709
1710 sub dump_union($$) {
1711     dump_struct(@_);
1712 }
1713
1714 sub dump_struct($$) {
1715     my $x = shift;
1716     my $file = shift;
1717     my $nested;
1718
1719     if ($x =~ /(struct|union)\s+(\w+)\s*{(.*)}/) {
1720         #my $decl_type = $1;
1721         $declaration_name = $2;
1722         my $members = $3;
1723
1724         # ignore embedded structs or unions
1725         $members =~ s/({.*})//g;
1726         $nested = $1;
1727
1728         # ignore members marked private:
1729         $members =~ s/\/\*\s*private:.*?\/\*\s*public:.*?\*\///gos;
1730         $members =~ s/\/\*\s*private:.*//gos;
1731         # strip comments:
1732         $members =~ s/\/\*.*?\*\///gos;
1733         $nested =~ s/\/\*.*?\*\///gos;
1734         # strip kmemcheck_bitfield_{begin,end}.*;
1735         $members =~ s/kmemcheck_bitfield_.*?;//gos;
1736         # strip attributes
1737         $members =~ s/__aligned\s*\(\d+\)//gos;
1738
1739         create_parameterlist($members, ';', $file);
1740         check_sections($file, $declaration_name, "struct", $sectcheck, $struct_actual, $nested);
1741
1742         output_declaration($declaration_name,
1743                            'struct',
1744                            {'struct' => $declaration_name,
1745                             'module' => $modulename,
1746                             'parameterlist' => \@parameterlist,
1747                             'parameterdescs' => \%parameterdescs,
1748                             'parametertypes' => \%parametertypes,
1749                             'sectionlist' => \@sectionlist,
1750                             'sections' => \%sections,
1751                             'purpose' => $declaration_purpose,
1752                             'type' => $decl_type
1753                            });
1754     }
1755     else {
1756         print STDERR "Error(${file}:$.): Cannot parse struct or union!\n";
1757         ++$errors;
1758     }
1759 }
1760
1761 sub dump_enum($$) {
1762     my $x = shift;
1763     my $file = shift;
1764
1765     $x =~ s@/\*.*?\*/@@gos;     # strip comments.
1766     $x =~ s/^#\s*define\s+.*$//; # strip #define macros inside enums
1767
1768     if ($x =~ /enum\s+(\w+)\s*{(.*)}/) {
1769         $declaration_name = $1;
1770         my $members = $2;
1771
1772         foreach my $arg (split ',', $members) {
1773             $arg =~ s/^\s*(\w+).*/$1/;
1774             push @parameterlist, $arg;
1775             if (!$parameterdescs{$arg}) {
1776                 $parameterdescs{$arg} = $undescribed;
1777                 print STDERR "Warning(${file}:$.): Enum value '$arg' ".
1778                     "not described in enum '$declaration_name'\n";
1779             }
1780
1781         }
1782
1783         output_declaration($declaration_name,
1784                            'enum',
1785                            {'enum' => $declaration_name,
1786                             'module' => $modulename,
1787                             'parameterlist' => \@parameterlist,
1788                             'parameterdescs' => \%parameterdescs,
1789                             'sectionlist' => \@sectionlist,
1790                             'sections' => \%sections,
1791                             'purpose' => $declaration_purpose
1792                            });
1793     }
1794     else {
1795         print STDERR "Error(${file}:$.): Cannot parse enum!\n";
1796         ++$errors;
1797     }
1798 }
1799
1800 sub dump_typedef($$) {
1801     my $x = shift;
1802     my $file = shift;
1803
1804     $x =~ s@/\*.*?\*/@@gos;     # strip comments.
1805     while (($x =~ /\(*.\)\s*;$/) || ($x =~ /\[*.\]\s*;$/)) {
1806         $x =~ s/\(*.\)\s*;$/;/;
1807         $x =~ s/\[*.\]\s*;$/;/;
1808     }
1809
1810     if ($x =~ /typedef.*\s+(\w+)\s*;/) {
1811         $declaration_name = $1;
1812
1813         output_declaration($declaration_name,
1814                            'typedef',
1815                            {'typedef' => $declaration_name,
1816                             'module' => $modulename,
1817                             'sectionlist' => \@sectionlist,
1818                             'sections' => \%sections,
1819                             'purpose' => $declaration_purpose
1820                            });
1821     }
1822     else {
1823         print STDERR "Error(${file}:$.): Cannot parse typedef!\n";
1824         ++$errors;
1825     }
1826 }
1827
1828 sub save_struct_actual($) {
1829     my $actual = shift;
1830
1831     # strip all spaces from the actual param so that it looks like one string item
1832     $actual =~ s/\s*//g;
1833     $struct_actual = $struct_actual . $actual . " ";
1834 }
1835
1836 sub create_parameterlist($$$) {
1837     my $args = shift;
1838     my $splitter = shift;
1839     my $file = shift;
1840     my $type;
1841     my $param;
1842
1843     # temporarily replace commas inside function pointer definition
1844     while ($args =~ /(\([^\),]+),/) {
1845         $args =~ s/(\([^\),]+),/$1#/g;
1846     }
1847
1848     foreach my $arg (split($splitter, $args)) {
1849         # strip comments
1850         $arg =~ s/\/\*.*\*\///;
1851         # strip leading/trailing spaces
1852         $arg =~ s/^\s*//;
1853         $arg =~ s/\s*$//;
1854         $arg =~ s/\s+/ /;
1855
1856         if ($arg =~ /^#/) {
1857             # Treat preprocessor directive as a typeless variable just to fill
1858             # corresponding data structures "correctly". Catch it later in
1859             # output_* subs.
1860             push_parameter($arg, "", $file);
1861         } elsif ($arg =~ m/\(.+\)\s*\(/) {
1862             # pointer-to-function
1863             $arg =~ tr/#/,/;
1864             $arg =~ m/[^\(]+\(\*?\s*(\w*)\s*\)/;
1865             $param = $1;
1866             $type = $arg;
1867             $type =~ s/([^\(]+\(\*?)\s*$param/$1/;
1868             save_struct_actual($param);
1869             push_parameter($param, $type, $file);
1870         } elsif ($arg) {
1871             $arg =~ s/\s*:\s*/:/g;
1872             $arg =~ s/\s*\[/\[/g;
1873
1874             my @args = split('\s*,\s*', $arg);
1875             if ($args[0] =~ m/\*/) {
1876                 $args[0] =~ s/(\*+)\s*/ $1/;
1877             }
1878
1879             my @first_arg;
1880             if ($args[0] =~ /^(.*\s+)(.*?\[.*\].*)$/) {
1881                     shift @args;
1882                     push(@first_arg, split('\s+', $1));
1883                     push(@first_arg, $2);
1884             } else {
1885                     @first_arg = split('\s+', shift @args);
1886             }
1887
1888             unshift(@args, pop @first_arg);
1889             $type = join " ", @first_arg;
1890
1891             foreach $param (@args) {
1892                 if ($param =~ m/^(\*+)\s*(.*)/) {
1893                     save_struct_actual($2);
1894                     push_parameter($2, "$type $1", $file);
1895                 }
1896                 elsif ($param =~ m/(.*?):(\d+)/) {
1897                     if ($type ne "") { # skip unnamed bit-fields
1898                         save_struct_actual($1);
1899                         push_parameter($1, "$type:$2", $file)
1900                     }
1901                 }
1902                 else {
1903                     save_struct_actual($param);
1904                     push_parameter($param, $type, $file);
1905                 }
1906             }
1907         }
1908     }
1909 }
1910
1911 sub push_parameter($$$) {
1912         my $param = shift;
1913         my $type = shift;
1914         my $file = shift;
1915
1916         if (($anon_struct_union == 1) && ($type eq "") &&
1917             ($param eq "}")) {
1918                 return;         # ignore the ending }; from anon. struct/union
1919         }
1920
1921         $anon_struct_union = 0;
1922         my $param_name = $param;
1923         $param_name =~ s/\[.*//;
1924
1925         if ($type eq "" && $param =~ /\.\.\.$/)
1926         {
1927             if (!defined $parameterdescs{$param} || $parameterdescs{$param} eq "") {
1928                 $parameterdescs{$param} = "variable arguments";
1929             }
1930         }
1931         elsif ($type eq "" && ($param eq "" or $param eq "void"))
1932         {
1933             $param="void";
1934             $parameterdescs{void} = "no arguments";
1935         }
1936         elsif ($type eq "" && ($param eq "struct" or $param eq "union"))
1937         # handle unnamed (anonymous) union or struct:
1938         {
1939                 $type = $param;
1940                 $param = "{unnamed_" . $param . "}";
1941                 $parameterdescs{$param} = "anonymous\n";
1942                 $anon_struct_union = 1;
1943         }
1944
1945         # warn if parameter has no description
1946         # (but ignore ones starting with # as these are not parameters
1947         # but inline preprocessor statements);
1948         # also ignore unnamed structs/unions;
1949         if (!$anon_struct_union) {
1950         if (!defined $parameterdescs{$param_name} && $param_name !~ /^#/) {
1951
1952             $parameterdescs{$param_name} = $undescribed;
1953
1954             if (($type eq 'function') || ($type eq 'enum')) {
1955                 print STDERR "Warning(${file}:$.): Function parameter ".
1956                     "or member '$param' not " .
1957                     "described in '$declaration_name'\n";
1958             }
1959             print STDERR "Warning(${file}:$.):" .
1960                          " No description found for parameter '$param'\n";
1961             ++$warnings;
1962         }
1963         }
1964
1965         $param = xml_escape($param);
1966
1967         # strip spaces from $param so that it is one continuous string
1968         # on @parameterlist;
1969         # this fixes a problem where check_sections() cannot find
1970         # a parameter like "addr[6 + 2]" because it actually appears
1971         # as "addr[6", "+", "2]" on the parameter list;
1972         # but it's better to maintain the param string unchanged for output,
1973         # so just weaken the string compare in check_sections() to ignore
1974         # "[blah" in a parameter string;
1975         ###$param =~ s/\s*//g;
1976         push @parameterlist, $param;
1977         $parametertypes{$param} = $type;
1978 }
1979
1980 sub check_sections($$$$$$) {
1981         my ($file, $decl_name, $decl_type, $sectcheck, $prmscheck, $nested) = @_;
1982         my @sects = split ' ', $sectcheck;
1983         my @prms = split ' ', $prmscheck;
1984         my $err;
1985         my ($px, $sx);
1986         my $prm_clean;          # strip trailing "[array size]" and/or beginning "*"
1987
1988         foreach $sx (0 .. $#sects) {
1989                 $err = 1;
1990                 foreach $px (0 .. $#prms) {
1991                         $prm_clean = $prms[$px];
1992                         $prm_clean =~ s/\[.*\]//;
1993                         $prm_clean =~ s/__attribute__\s*\(\([a-z,_\*\s\(\)]*\)\)//i;
1994                         # ignore array size in a parameter string;
1995                         # however, the original param string may contain
1996                         # spaces, e.g.:  addr[6 + 2]
1997                         # and this appears in @prms as "addr[6" since the
1998                         # parameter list is split at spaces;
1999                         # hence just ignore "[..." for the sections check;
2000                         $prm_clean =~ s/\[.*//;
2001
2002                         ##$prm_clean =~ s/^\**//;
2003                         if ($prm_clean eq $sects[$sx]) {
2004                                 $err = 0;
2005                                 last;
2006                         }
2007                 }
2008                 if ($err) {
2009                         if ($decl_type eq "function") {
2010                                 print STDERR "Warning(${file}:$.): " .
2011                                         "Excess function parameter " .
2012                                         "'$sects[$sx]' " .
2013                                         "description in '$decl_name'\n";
2014                                 ++$warnings;
2015                         } else {
2016                                 if ($nested !~ m/\Q$sects[$sx]\E/) {
2017                                     print STDERR "Warning(${file}:$.): " .
2018                                         "Excess struct/union/enum/typedef member " .
2019                                         "'$sects[$sx]' " .
2020                                         "description in '$decl_name'\n";
2021                                     ++$warnings;
2022                                 }
2023                         }
2024                 }
2025         }
2026 }
2027
2028 ##
2029 # takes a function prototype and the name of the current file being
2030 # processed and spits out all the details stored in the global
2031 # arrays/hashes.
2032 sub dump_function($$) {
2033     my $prototype = shift;
2034     my $file = shift;
2035
2036     $prototype =~ s/^static +//;
2037     $prototype =~ s/^extern +//;
2038     $prototype =~ s/^asmlinkage +//;
2039     $prototype =~ s/^inline +//;
2040     $prototype =~ s/^__inline__ +//;
2041     $prototype =~ s/^__inline +//;
2042     $prototype =~ s/^__always_inline +//;
2043     $prototype =~ s/^noinline +//;
2044     $prototype =~ s/__devinit +//;
2045     $prototype =~ s/__init +//;
2046     $prototype =~ s/__init_or_module +//;
2047     $prototype =~ s/__must_check +//;
2048     $prototype =~ s/__weak +//;
2049     $prototype =~ s/^#\s*define\s+//; #ak added
2050     $prototype =~ s/__attribute__\s*\(\([a-z,]*\)\)//;
2051
2052     # Yes, this truly is vile.  We are looking for:
2053     # 1. Return type (may be nothing if we're looking at a macro)
2054     # 2. Function name
2055     # 3. Function parameters.
2056     #
2057     # All the while we have to watch out for function pointer parameters
2058     # (which IIRC is what the two sections are for), C types (these
2059     # regexps don't even start to express all the possibilities), and
2060     # so on.
2061     #
2062     # If you mess with these regexps, it's a good idea to check that
2063     # the following functions' documentation still comes out right:
2064     # - parport_register_device (function pointer parameters)
2065     # - atomic_set (macro)
2066     # - pci_match_device, __copy_to_user (long return type)
2067
2068     if ($prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
2069         $prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
2070         $prototype =~ m/^(\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
2071         $prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
2072         $prototype =~ m/^(\w+\s+\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
2073         $prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
2074         $prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
2075         $prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
2076         $prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
2077         $prototype =~ m/^(\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
2078         $prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
2079         $prototype =~ m/^(\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
2080         $prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
2081         $prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
2082         $prototype =~ m/^(\w+\s+\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
2083         $prototype =~ m/^(\w+\s+\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
2084         $prototype =~ m/^(\w+\s+\w+\s*\*\s*\w+\s*\*\s*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/)  {
2085         $return_type = $1;
2086         $declaration_name = $2;
2087         my $args = $3;
2088
2089         create_parameterlist($args, ',', $file);
2090     } else {
2091         print STDERR "Error(${file}:$.): cannot understand prototype: '$prototype'\n";
2092         ++$errors;
2093         return;
2094     }
2095
2096         my $prms = join " ", @parameterlist;
2097         check_sections($file, $declaration_name, "function", $sectcheck, $prms, "");
2098
2099     output_declaration($declaration_name,
2100                        'function',
2101                        {'function' => $declaration_name,
2102                         'module' => $modulename,
2103                         'functiontype' => $return_type,
2104                         'parameterlist' => \@parameterlist,
2105                         'parameterdescs' => \%parameterdescs,
2106                         'parametertypes' => \%parametertypes,
2107                         'sectionlist' => \@sectionlist,
2108                         'sections' => \%sections,
2109                         'purpose' => $declaration_purpose
2110                        });
2111 }
2112
2113 sub reset_state {
2114     $function = "";
2115     %constants = ();
2116     %parameterdescs = ();
2117     %parametertypes = ();
2118     @parameterlist = ();
2119     %sections = ();
2120     @sectionlist = ();
2121     $sectcheck = "";
2122     $struct_actual = "";
2123     $prototype = "";
2124
2125     $state = 0;
2126 }
2127
2128 sub tracepoint_munge($) {
2129         my $file = shift;
2130         my $tracepointname = 0;
2131         my $tracepointargs = 0;
2132
2133         if ($prototype =~ m/TRACE_EVENT\((.*?),/) {
2134                 $tracepointname = $1;
2135         }
2136         if ($prototype =~ m/DEFINE_SINGLE_EVENT\((.*?),/) {
2137                 $tracepointname = $1;
2138         }
2139         if ($prototype =~ m/DEFINE_EVENT\((.*?),(.*?),/) {
2140                 $tracepointname = $2;
2141         }
2142         $tracepointname =~ s/^\s+//; #strip leading whitespace
2143         if ($prototype =~ m/TP_PROTO\((.*?)\)/) {
2144                 $tracepointargs = $1;
2145         }
2146         if (($tracepointname eq 0) || ($tracepointargs eq 0)) {
2147                 print STDERR "Warning(${file}:$.): Unrecognized tracepoint format: \n".
2148                              "$prototype\n";
2149         } else {
2150                 $prototype = "static inline void trace_$tracepointname($tracepointargs)";
2151         }
2152 }
2153
2154 sub syscall_munge() {
2155         my $void = 0;
2156
2157         $prototype =~ s@[\r\n\t]+@ @gos; # strip newlines/CR's/tabs
2158 ##      if ($prototype =~ m/SYSCALL_DEFINE0\s*\(\s*(a-zA-Z0-9_)*\s*\)/) {
2159         if ($prototype =~ m/SYSCALL_DEFINE0/) {
2160                 $void = 1;
2161 ##              $prototype = "long sys_$1(void)";
2162         }
2163
2164         $prototype =~ s/SYSCALL_DEFINE.*\(/long sys_/; # fix return type & func name
2165         if ($prototype =~ m/long (sys_.*?),/) {
2166                 $prototype =~ s/,/\(/;
2167         } elsif ($void) {
2168                 $prototype =~ s/\)/\(void\)/;
2169         }
2170
2171         # now delete all of the odd-number commas in $prototype
2172         # so that arg types & arg names don't have a comma between them
2173         my $count = 0;
2174         my $len = length($prototype);
2175         if ($void) {
2176                 $len = 0;       # skip the for-loop
2177         }
2178         for (my $ix = 0; $ix < $len; $ix++) {
2179                 if (substr($prototype, $ix, 1) eq ',') {
2180                         $count++;
2181                         if ($count % 2 == 1) {
2182                                 substr($prototype, $ix, 1) = ' ';
2183                         }
2184                 }
2185         }
2186 }
2187
2188 sub process_state3_function($$) {
2189     my $x = shift;
2190     my $file = shift;
2191
2192     $x =~ s@\/\/.*$@@gos; # strip C99-style comments to end of line
2193
2194     if ($x =~ m#\s*/\*\s+MACDOC\s*#io || ($x =~ /^#/ && $x !~ /^#\s*define/)) {
2195         # do nothing
2196     }
2197     elsif ($x =~ /([^\{]*)/) {
2198         $prototype .= $1;
2199     }
2200
2201     if (($x =~ /\{/) || ($x =~ /\#\s*define/) || ($x =~ /;/)) {
2202         $prototype =~ s@/\*.*?\*/@@gos; # strip comments.
2203         $prototype =~ s@[\r\n]+@ @gos; # strip newlines/cr's.
2204         $prototype =~ s@^\s+@@gos; # strip leading spaces
2205         if ($prototype =~ /SYSCALL_DEFINE/) {
2206                 syscall_munge();
2207         }
2208         if ($prototype =~ /TRACE_EVENT/ || $prototype =~ /DEFINE_EVENT/ ||
2209             $prototype =~ /DEFINE_SINGLE_EVENT/)
2210         {
2211                 tracepoint_munge($file);
2212         }
2213         dump_function($prototype, $file);
2214         reset_state();
2215     }
2216 }
2217
2218 sub process_state3_type($$) {
2219     my $x = shift;
2220     my $file = shift;
2221
2222     $x =~ s@[\r\n]+@ @gos; # strip newlines/cr's.
2223     $x =~ s@^\s+@@gos; # strip leading spaces
2224     $x =~ s@\s+$@@gos; # strip trailing spaces
2225     $x =~ s@\/\/.*$@@gos; # strip C99-style comments to end of line
2226
2227     if ($x =~ /^#/) {
2228         # To distinguish preprocessor directive from regular declaration later.
2229         $x .= ";";
2230     }
2231
2232     while (1) {
2233         if ( $x =~ /([^{};]*)([{};])(.*)/ ) {
2234             $prototype .= $1 . $2;
2235             ($2 eq '{') && $brcount++;
2236             ($2 eq '}') && $brcount--;
2237             if (($2 eq ';') && ($brcount == 0)) {
2238                 dump_declaration($prototype, $file);
2239                 reset_state();
2240                 last;
2241             }
2242             $x = $3;
2243         } else {
2244             $prototype .= $x;
2245             last;
2246         }
2247     }
2248 }
2249
2250 # xml_escape: replace <, >, and & in the text stream;
2251 #
2252 # however, formatting controls that are generated internally/locally in the
2253 # kernel-doc script are not escaped here; instead, they begin life like
2254 # $blankline_html (4 of '\' followed by a mnemonic + ':'), then these strings
2255 # are converted to their mnemonic-expected output, without the 4 * '\' & ':',
2256 # just before actual output; (this is done by local_unescape())
2257 sub xml_escape($) {
2258         my $text = shift;
2259         if (($output_mode eq "text") || ($output_mode eq "man")) {
2260                 return $text;
2261         }
2262         $text =~ s/\&/\\\\\\amp;/g;
2263         $text =~ s/\</\\\\\\lt;/g;
2264         $text =~ s/\>/\\\\\\gt;/g;
2265         return $text;
2266 }
2267
2268 # convert local escape strings to html
2269 # local escape strings look like:  '\\\\menmonic:' (that's 4 backslashes)
2270 sub local_unescape($) {
2271         my $text = shift;
2272         if (($output_mode eq "text") || ($output_mode eq "man")) {
2273                 return $text;
2274         }
2275         $text =~ s/\\\\\\\\lt:/</g;
2276         $text =~ s/\\\\\\\\gt:/>/g;
2277         return $text;
2278 }
2279
2280 sub process_file($) {
2281     my $file;
2282     my $identifier;
2283     my $func;
2284     my $descr;
2285     my $in_purpose = 0;
2286     my $initial_section_counter = $section_counter;
2287
2288     if (defined($ENV{'SRCTREE'})) {
2289         $file = "$ENV{'SRCTREE'}" . "/" . "@_";
2290     }
2291     else {
2292         $file = "@_";
2293     }
2294     if (defined($source_map{$file})) {
2295         $file = $source_map{$file};
2296     }
2297
2298     if (!open(IN,"<$file")) {
2299         print STDERR "Error: Cannot open file $file\n";
2300         ++$errors;
2301         return;
2302     }
2303
2304     $. = 1;
2305
2306     $section_counter = 0;
2307     while (<IN>) {
2308         if ($state == 0) {
2309             if (/$doc_start/o) {
2310                 $state = 1;             # next line is always the function name
2311                 $in_doc_sect = 0;
2312             }
2313         } elsif ($state == 1) { # this line is the function name (always)
2314             if (/$doc_block/o) {
2315                 $state = 4;
2316                 $contents = "";
2317                 if ( $1 eq "" ) {
2318                         $section = $section_intro;
2319                 } else {
2320                         $section = $1;
2321                 }
2322             }
2323             elsif (/$doc_decl/o) {
2324                 $identifier = $1;
2325                 if (/\s*([\w\s]+?)\s*-/) {
2326                     $identifier = $1;
2327                 }
2328
2329                 $state = 2;
2330                 if (/-(.*)/) {
2331                     # strip leading/trailing/multiple spaces
2332                     $descr= $1;
2333                     $descr =~ s/^\s*//;
2334                     $descr =~ s/\s*$//;
2335                     $descr =~ s/\s+/ /;
2336                     $declaration_purpose = xml_escape($descr);
2337                     $in_purpose = 1;
2338                 } else {
2339                     $declaration_purpose = "";
2340                 }
2341
2342                 if (($declaration_purpose eq "") && $verbose) {
2343                         print STDERR "Warning(${file}:$.): missing initial short description on line:\n";
2344                         print STDERR $_;
2345                         ++$warnings;
2346                 }
2347
2348                 if ($identifier =~ m/^struct/) {
2349                     $decl_type = 'struct';
2350                 } elsif ($identifier =~ m/^union/) {
2351                     $decl_type = 'union';
2352                 } elsif ($identifier =~ m/^enum/) {
2353                     $decl_type = 'enum';
2354                 } elsif ($identifier =~ m/^typedef/) {
2355                     $decl_type = 'typedef';
2356                 } else {
2357                     $decl_type = 'function';
2358                 }
2359
2360                 if ($verbose) {
2361                     print STDERR "Info(${file}:$.): Scanning doc for $identifier\n";
2362                 }
2363             } else {
2364                 print STDERR "Warning(${file}:$.): Cannot understand $_ on line $.",
2365                 " - I thought it was a doc line\n";
2366                 ++$warnings;
2367                 $state = 0;
2368             }
2369         } elsif ($state == 2) { # look for head: lines, and include content
2370             if (/$doc_sect/o) {
2371                 $newsection = $1;
2372                 $newcontents = $2;
2373
2374                 if (($contents ne "") && ($contents ne "\n")) {
2375                     if (!$in_doc_sect && $verbose) {
2376                         print STDERR "Warning(${file}:$.): contents before sections\n";
2377                         ++$warnings;
2378                     }
2379                     dump_section($file, $section, xml_escape($contents));
2380                     $section = $section_default;
2381                 }
2382
2383                 $in_doc_sect = 1;
2384                 $in_purpose = 0;
2385                 $contents = $newcontents;
2386                 if ($contents ne "") {
2387                     while ((substr($contents, 0, 1) eq " ") ||
2388                         substr($contents, 0, 1) eq "\t") {
2389                             $contents = substr($contents, 1);
2390                     }
2391                     $contents .= "\n";
2392                 }
2393                 $section = $newsection;
2394             } elsif (/$doc_end/) {
2395
2396                 if (($contents ne "") && ($contents ne "\n")) {
2397                     dump_section($file, $section, xml_escape($contents));
2398                     $section = $section_default;
2399                     $contents = "";
2400                 }
2401                 # look for doc_com + <text> + doc_end:
2402                 if ($_ =~ m'\s*\*\s*[a-zA-Z_0-9:\.]+\*/') {
2403                     print STDERR "Warning(${file}:$.): suspicious ending line: $_";
2404                     ++$warnings;
2405                 }
2406
2407                 $prototype = "";
2408                 $state = 3;
2409                 $brcount = 0;
2410 #               print STDERR "end of doc comment, looking for prototype\n";
2411             } elsif (/$doc_content/) {
2412                 # miguel-style comment kludge, look for blank lines after
2413                 # @parameter line to signify start of description
2414                 if ($1 eq "") {
2415                     if ($section =~ m/^@/ || $section eq $section_context) {
2416                         dump_section($file, $section, xml_escape($contents));
2417                         $section = $section_default;
2418                         $contents = "";
2419                     } else {
2420                         $contents .= "\n";
2421                     }
2422                     $in_purpose = 0;
2423                 } elsif ($in_purpose == 1) {
2424                     # Continued declaration purpose
2425                     chomp($declaration_purpose);
2426                     $declaration_purpose .= " " . xml_escape($1);
2427                 } elsif ($section =~ m/^Example/) {
2428                     $_ =~ s/^\s*\*//;
2429                     $contents .= $_;
2430                 } else {
2431                     $contents .= $1 . "\n";
2432                 }
2433             } else {
2434                 # i dont know - bad line?  ignore.
2435                 print STDERR "Warning(${file}:$.): bad line: $_";
2436                 ++$warnings;
2437             }
2438         } elsif ($state == 3) { # scanning for function '{' (end of prototype)
2439             if ($decl_type eq 'function') {
2440                 process_state3_function($_, $file);
2441             } else {
2442                 process_state3_type($_, $file);
2443             }
2444         } elsif ($state == 4) {
2445                 # Documentation block
2446                 if (/$doc_block/) {
2447                         dump_doc_section($file, $section, xml_escape($contents));
2448                         $contents = "";
2449                         $function = "";
2450                         %constants = ();
2451                         %parameterdescs = ();
2452                         %parametertypes = ();
2453                         @parameterlist = ();
2454                         %sections = ();
2455                         @sectionlist = ();
2456                         $prototype = "";
2457                         if ( $1 eq "" ) {
2458                                 $section = $section_intro;
2459                         } else {
2460                                 $section = $1;
2461                         }
2462                 }
2463                 elsif (/$doc_end/)
2464                 {
2465                         dump_doc_section($file, $section, xml_escape($contents));
2466                         $contents = "";
2467                         $function = "";
2468                         %constants = ();
2469                         %parameterdescs = ();
2470                         %parametertypes = ();
2471                         @parameterlist = ();
2472                         %sections = ();
2473                         @sectionlist = ();
2474                         $prototype = "";
2475                         $state = 0;
2476                 }
2477                 elsif (/$doc_content/)
2478                 {
2479                         if ( $1 eq "" )
2480                         {
2481                                 $contents .= $blankline;
2482                         }
2483                         else
2484                         {
2485                                 $contents .= $1 . "\n";
2486                         }
2487                 }
2488         }
2489     }
2490     if ($initial_section_counter == $section_counter) {
2491         print STDERR "Warning(${file}): no structured comments found\n";
2492         if ($output_mode eq "xml") {
2493             # The template wants at least one RefEntry here; make one.
2494             print "<refentry>\n";
2495             print " <refnamediv>\n";
2496             print "  <refname>\n";
2497             print "   ${file}\n";
2498             print "  </refname>\n";
2499             print "  <refpurpose>\n";
2500             print "   Document generation inconsistency\n";
2501             print "  </refpurpose>\n";
2502             print " </refnamediv>\n";
2503             print " <refsect1>\n";
2504             print "  <title>\n";
2505             print "   Oops\n";
2506             print "  </title>\n";
2507             print "  <warning>\n";
2508             print "   <para>\n";
2509             print "    The template for this document tried to insert\n";
2510             print "    the structured comment from the file\n";
2511             print "    <filename>${file}</filename> at this point,\n";
2512             print "    but none was found.\n";
2513             print "    This dummy section is inserted to allow\n";
2514             print "    generation to continue.\n";
2515             print "   </para>\n";
2516             print "  </warning>\n";
2517             print " </refsect1>\n";
2518             print "</refentry>\n";
2519         }
2520     }
2521 }
2522
2523
2524 $kernelversion = get_kernel_version();
2525
2526 # generate a sequence of code that will splice in highlighting information
2527 # using the s// operator.
2528 foreach my $pattern (keys %highlights) {
2529 #   print STDERR "scanning pattern:$pattern, highlight:($highlights{$pattern})\n";
2530     $dohighlight .=  "\$contents =~ s:$pattern:$highlights{$pattern}:gs;\n";
2531 }
2532
2533 # Read the file that maps relative names to absolute names for
2534 # separate source and object directories and for shadow trees.
2535 if (open(SOURCE_MAP, "<.tmp_filelist.txt")) {
2536         my ($relname, $absname);
2537         while(<SOURCE_MAP>) {
2538                 chop();
2539                 ($relname, $absname) = (split())[0..1];
2540                 $relname =~ s:^/+::;
2541                 $source_map{$relname} = $absname;
2542         }
2543         close(SOURCE_MAP);
2544 }
2545
2546 foreach (@ARGV) {
2547     chomp;
2548     process_file($_);
2549 }
2550 if ($verbose && $errors) {
2551   print STDERR "$errors errors\n";
2552 }
2553 if ($verbose && $warnings) {
2554   print STDERR "$warnings warnings\n";
2555 }
2556
2557 exit($errors);