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