qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

kernel-doc (67925B)


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