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