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