linux/scripts/kernel-doc
<<
>>
Prefs
   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-2012  Randy Dunlap                         ##
   9## Copyright (C) 2012  Dan Luedtke                               ##
  10##                                                               ##
  11## #define enhancements by Armin Kuster <akuster@mvista.com>     ##
  12## Copyright (c) 2000 MontaVista Software, Inc.                  ##
  13##                                                               ##
  14## This software falls under the GNU General Public License.     ##
  15## Please read the COPYING file for more information             ##
  16
  17# 18/01/2001 -  Cleanups
  18#               Functions prototyped as foo(void) same as foo()
  19#               Stop eval'ing where we don't need to.
  20# -- huggie@earth.li
  21
  22# 27/06/2001 -  Allowed whitespace after initial "/**" and
  23#               allowed comments before function declarations.
  24# -- Christian Kreibich <ck@whoop.org>
  25
  26# Still to do:
  27#       - add perldoc documentation
  28#       - Look more closely at some of the scarier bits :)
  29
  30# 26/05/2001 -  Support for separate source and object trees.
  31#               Return error code.
  32#               Keith Owens <kaos@ocs.com.au>
  33
  34# 23/09/2001 - Added support for typedefs, structs, enums and unions
  35#              Support for Context section; can be terminated using empty line
  36#              Small fixes (like spaces vs. \s in regex)
  37# -- Tim Jansen <tim@tjansen.de>
  38
  39# 25/07/2012 - Added support for HTML5
  40# -- Dan Luedtke <mail@danrl.de>
  41
  42sub usage {
  43    my $message = <<"EOF";
  44Usage: $0 [OPTION ...] FILE ...
  45
  46Read C language source or header FILEs, extract embedded documentation comments,
  47and print formatted documentation to standard output.
  48
  49The documentation comments are identified by "/**" opening comment mark. See
  50Documentation/kernel-doc-nano-HOWTO.txt for the documentation comment syntax.
  51
  52Output format selection (mutually exclusive):
  53  -docbook              Output DocBook format.
  54  -html                 Output HTML format.
  55  -html5                Output HTML5 format.
  56  -list                 Output symbol list format. This is for use by docproc.
  57  -man                  Output troff manual page format. This is the default.
  58  -rst                  Output reStructuredText format.
  59  -text                 Output plain text format.
  60
  61Output selection (mutually exclusive):
  62  -export               Only output documentation for symbols that have been
  63                        exported using EXPORT_SYMBOL() or EXPORT_SYMBOL_GPL()
  64                        in any input FILE or -export-file FILE.
  65  -internal             Only output documentation for symbols that have NOT been
  66                        exported using EXPORT_SYMBOL() or EXPORT_SYMBOL_GPL()
  67                        in any input FILE or -export-file FILE.
  68  -function NAME        Only output documentation for the given function(s)
  69                        or DOC: section title(s). All other functions and DOC:
  70                        sections are ignored. May be specified multiple times.
  71  -nofunction NAME      Do NOT output documentation for the given function(s);
  72                        only output documentation for the other functions and
  73                        DOC: sections. May be specified multiple times.
  74
  75Output selection modifiers:
  76  -no-doc-sections      Do not output DOC: sections.
  77  -enable-lineno        Enable output of #define LINENO lines. Only works with
  78                        reStructuredText format.
  79  -export-file FILE     Specify an additional FILE in which to look for
  80                        EXPORT_SYMBOL() and EXPORT_SYMBOL_GPL(). To be used with
  81                        -export or -internal. May be specified multiple times.
  82
  83Other parameters:
  84  -v                    Verbose output, more warnings and other information.
  85  -h                    Print this help.
  86
  87EOF
  88    print $message;
  89    exit 1;
  90}
  91
  92#
  93# format of comments.
  94# In the following table, (...)? signifies optional structure.
  95#                         (...)* signifies 0 or more structure elements
  96# /**
  97#  * function_name(:)? (- short description)?
  98# (* @parameterx: (description of parameter x)?)*
  99# (* a blank line)?
 100#  * (Description:)? (Description of function)?
 101#  * (section header: (section description)? )*
 102#  (*)?*/
 103#
 104# So .. the trivial example would be:
 105#
 106# /**
 107#  * my_function
 108#  */
 109#
 110# If the Description: header tag is omitted, then there must be a blank line
 111# after the last parameter specification.
 112# e.g.
 113# /**
 114#  * my_function - does my stuff
 115#  * @my_arg: its mine damnit
 116#  *
 117#  * Does my stuff explained.
 118#  */
 119#
 120#  or, could also use:
 121# /**
 122#  * my_function - does my stuff
 123#  * @my_arg: its mine damnit
 124#  * Description: Does my stuff explained.
 125#  */
 126# etc.
 127#
 128# Besides functions you can also write documentation for structs, unions,
 129# enums and typedefs. Instead of the function name you must write the name
 130# of the declaration;  the struct/union/enum/typedef must always precede
 131# the name. Nesting of declarations is not supported.
 132# Use the argument mechanism to document members or constants.
 133# e.g.
 134# /**
 135#  * struct my_struct - short description
 136#  * @a: first member
 137#  * @b: second member
 138#  *
 139#  * Longer description
 140#  */
 141# struct my_struct {
 142#     int a;
 143#     int b;
 144# /* private: */
 145#     int c;
 146# };
 147#
 148# All descriptions can be multiline, except the short function description.
 149#
 150# For really longs structs, you can also describe arguments inside the
 151# body of the struct.
 152# eg.
 153# /**
 154#  * struct my_struct - short description
 155#  * @a: first member
 156#  * @b: second member
 157#  *
 158#  * Longer description
 159#  */
 160# struct my_struct {
 161#     int a;
 162#     int b;
 163#     /**
 164#      * @c: This is longer description of C
 165#      *
 166#      * You can use paragraphs to describe arguments
 167#      * using this method.
 168#      */
 169#     int c;
 170# };
 171#
 172# This should be use only for struct/enum members.
 173#
 174# You can also add additional sections. When documenting kernel functions you
 175# should document the "Context:" of the function, e.g. whether the functions
 176# can be called form interrupts. Unlike other sections you can end it with an
 177# empty line.
 178# A non-void function should have a "Return:" section describing the return
 179# value(s).
 180# Example-sections should contain the string EXAMPLE so that they are marked
 181# appropriately in DocBook.
 182#
 183# Example:
 184# /**
 185#  * user_function - function that can only be called in user context
 186#  * @a: some argument
 187#  * Context: !in_interrupt()
 188#  *
 189#  * Some description
 190#  * Example:
 191#  *    user_function(22);
 192#  */
 193# ...
 194#
 195#
 196# All descriptive text is further processed, scanning for the following special
 197# patterns, which are highlighted appropriately.
 198#
 199# 'funcname()' - function
 200# '$ENVVAR' - environmental variable
 201# '&struct_name' - name of a structure (up to two words including 'struct')
 202# '&struct_name.member' - name of a structure member
 203# '@parameter' - name of a parameter
 204# '%CONST' - name of a constant.
 205# '``LITERAL``' - literal string without any spaces on it.
 206
 207## init lots of data
 208
 209my $errors = 0;
 210my $warnings = 0;
 211my $anon_struct_union = 0;
 212
 213# match expressions used to find embedded type information
 214my $type_constant = '\b``([^\`]+)``\b';
 215my $type_constant2 = '\%([-_\w]+)';
 216my $type_func = '(\w+)\(\)';
 217my $type_param = '\@(\w+(\.\.\.)?)';
 218my $type_fp_param = '\@(\w+)\(\)';  # Special RST handling for func ptr params
 219my $type_env = '(\$\w+)';
 220my $type_enum = '\&(enum\s*([_\w]+))';
 221my $type_struct = '\&(struct\s*([_\w]+))';
 222my $type_typedef = '\&(typedef\s*([_\w]+))';
 223my $type_union = '\&(union\s*([_\w]+))';
 224my $type_member = '\&([_\w]+)(\.|->)([_\w]+)';
 225my $type_fallback = '\&([_\w]+)';
 226my $type_enum_xml = '\&amp;(enum\s*([_\w]+))';
 227my $type_struct_xml = '\&amp;(struct\s*([_\w]+))';
 228my $type_typedef_xml = '\&amp;(typedef\s*([_\w]+))';
 229my $type_union_xml = '\&amp;(union\s*([_\w]+))';
 230my $type_member_xml = '\&amp;([_\w]+)(\.|-\&gt;)([_\w]+)';
 231my $type_fallback_xml = '\&amp([_\w]+)';
 232my $type_member_func = $type_member . '\(\)';
 233
 234# Output conversion substitutions.
 235#  One for each output format
 236
 237# these work fairly well
 238my @highlights_html = (
 239                       [$type_constant, "<i>\$1</i>"],
 240                       [$type_constant2, "<i>\$1</i>"],
 241                       [$type_func, "<b>\$1</b>"],
 242                       [$type_enum_xml, "<i>\$1</i>"],
 243                       [$type_struct_xml, "<i>\$1</i>"],
 244                       [$type_typedef_xml, "<i>\$1</i>"],
 245                       [$type_union_xml, "<i>\$1</i>"],
 246                       [$type_env, "<b><i>\$1</i></b>"],
 247                       [$type_param, "<tt><b>\$1</b></tt>"],
 248                       [$type_member_xml, "<tt><i>\$1</i>\$2\$3</tt>"],
 249                       [$type_fallback_xml, "<i>\$1</i>"]
 250                      );
 251my $local_lt = "\\\\\\\\lt:";
 252my $local_gt = "\\\\\\\\gt:";
 253my $blankline_html = $local_lt . "p" . $local_gt;       # was "<p>"
 254
 255# html version 5
 256my @highlights_html5 = (
 257                        [$type_constant, "<span class=\"const\">\$1</span>"],
 258                        [$type_constant2, "<span class=\"const\">\$1</span>"],
 259                        [$type_func, "<span class=\"func\">\$1</span>"],
 260                        [$type_enum_xml, "<span class=\"enum\">\$1</span>"],
 261                        [$type_struct_xml, "<span class=\"struct\">\$1</span>"],
 262                        [$type_typedef_xml, "<span class=\"typedef\">\$1</span>"],
 263                        [$type_union_xml, "<span class=\"union\">\$1</span>"],
 264                        [$type_env, "<span class=\"env\">\$1</span>"],
 265                        [$type_param, "<span class=\"param\">\$1</span>]"],
 266                        [$type_member_xml, "<span class=\"literal\"><span class=\"struct\">\$1</span>\$2<span class=\"member\">\$3</span></span>"],
 267                        [$type_fallback_xml, "<span class=\"struct\">\$1</span>"]
 268                       );
 269my $blankline_html5 = $local_lt . "br /" . $local_gt;
 270
 271# XML, docbook format
 272my @highlights_xml = (
 273                      ["([^=])\\\"([^\\\"<]+)\\\"", "\$1<quote>\$2</quote>"],
 274                      [$type_constant, "<constant>\$1</constant>"],
 275                      [$type_constant2, "<constant>\$1</constant>"],
 276                      [$type_enum_xml, "<type>\$1</type>"],
 277                      [$type_struct_xml, "<structname>\$1</structname>"],
 278                      [$type_typedef_xml, "<type>\$1</type>"],
 279                      [$type_union_xml, "<structname>\$1</structname>"],
 280                      [$type_param, "<parameter>\$1</parameter>"],
 281                      [$type_func, "<function>\$1</function>"],
 282                      [$type_env, "<envar>\$1</envar>"],
 283                      [$type_member_xml, "<literal><structname>\$1</structname>\$2<structfield>\$3</structfield></literal>"],
 284                      [$type_fallback_xml, "<structname>\$1</structname>"]
 285                     );
 286my $blankline_xml = $local_lt . "/para" . $local_gt . $local_lt . "para" . $local_gt . "\n";
 287
 288# gnome, docbook format
 289my @highlights_gnome = (
 290                        [$type_constant, "<replaceable class=\"option\">\$1</replaceable>"],
 291                        [$type_constant2, "<replaceable class=\"option\">\$1</replaceable>"],
 292                        [$type_func, "<function>\$1</function>"],
 293                        [$type_enum, "<type>\$1</type>"],
 294                        [$type_struct, "<structname>\$1</structname>"],
 295                        [$type_typedef, "<type>\$1</type>"],
 296                        [$type_union, "<structname>\$1</structname>"],
 297                        [$type_env, "<envar>\$1</envar>"],
 298                        [$type_param, "<parameter>\$1</parameter>" ],
 299                        [$type_member, "<literal><structname>\$1</structname>\$2<structfield>\$3</structfield></literal>"],
 300                        [$type_fallback, "<structname>\$1</structname>"]
 301                       );
 302my $blankline_gnome = "</para><para>\n";
 303
 304# these are pretty rough
 305my @highlights_man = (
 306                      [$type_constant, "\$1"],
 307                      [$type_constant2, "\$1"],
 308                      [$type_func, "\\\\fB\$1\\\\fP"],
 309                      [$type_enum, "\\\\fI\$1\\\\fP"],
 310                      [$type_struct, "\\\\fI\$1\\\\fP"],
 311                      [$type_typedef, "\\\\fI\$1\\\\fP"],
 312                      [$type_union, "\\\\fI\$1\\\\fP"],
 313                      [$type_param, "\\\\fI\$1\\\\fP"],
 314                      [$type_member, "\\\\fI\$1\$2\$3\\\\fP"],
 315                      [$type_fallback, "\\\\fI\$1\\\\fP"]
 316                     );
 317my $blankline_man = "";
 318
 319# text-mode
 320my @highlights_text = (
 321                       [$type_constant, "\$1"],
 322                       [$type_constant2, "\$1"],
 323                       [$type_func, "\$1"],
 324                       [$type_enum, "\$1"],
 325                       [$type_struct, "\$1"],
 326                       [$type_typedef, "\$1"],
 327                       [$type_union, "\$1"],
 328                       [$type_param, "\$1"],
 329                       [$type_member, "\$1\$2\$3"],
 330                       [$type_fallback, "\$1"]
 331                      );
 332my $blankline_text = "";
 333
 334# rst-mode
 335my @highlights_rst = (
 336                       [$type_constant, "``\$1``"],
 337                       [$type_constant2, "``\$1``"],
 338                       # Note: need to escape () to avoid func matching later
 339                       [$type_member_func, "\\:c\\:type\\:`\$1\$2\$3\\\\(\\\\) <\$1>`"],
 340                       [$type_member, "\\:c\\:type\\:`\$1\$2\$3 <\$1>`"],
 341                       [$type_fp_param, "**\$1\\\\(\\\\)**"],
 342                       [$type_func, "\\:c\\:func\\:`\$1()`"],
 343                       [$type_enum, "\\:c\\:type\\:`\$1 <\$2>`"],
 344                       [$type_struct, "\\:c\\:type\\:`\$1 <\$2>`"],
 345                       [$type_typedef, "\\:c\\:type\\:`\$1 <\$2>`"],
 346                       [$type_union, "\\:c\\:type\\:`\$1 <\$2>`"],
 347                       # in rst this can refer to any type
 348                       [$type_fallback, "\\:c\\:type\\:`\$1`"],
 349                       [$type_param, "**\$1**"]
 350                      );
 351my $blankline_rst = "\n";
 352
 353# list mode
 354my @highlights_list = (
 355                       [$type_constant, "\$1"],
 356                       [$type_constant2, "\$1"],
 357                       [$type_func, "\$1"],
 358                       [$type_enum, "\$1"],
 359                       [$type_struct, "\$1"],
 360                       [$type_typedef, "\$1"],
 361                       [$type_union, "\$1"],
 362                       [$type_param, "\$1"],
 363                       [$type_member, "\$1"],
 364                       [$type_fallback, "\$1"]
 365                      );
 366my $blankline_list = "";
 367
 368# read arguments
 369if ($#ARGV == -1) {
 370    usage();
 371}
 372
 373my $kernelversion;
 374my $dohighlight = "";
 375
 376my $verbose = 0;
 377my $output_mode = "man";
 378my $output_preformatted = 0;
 379my $no_doc_sections = 0;
 380my $enable_lineno = 0;
 381my @highlights = @highlights_man;
 382my $blankline = $blankline_man;
 383my $modulename = "Kernel API";
 384
 385use constant {
 386    OUTPUT_ALL          => 0, # output all symbols and doc sections
 387    OUTPUT_INCLUDE      => 1, # output only specified symbols
 388    OUTPUT_EXCLUDE      => 2, # output everything except specified symbols
 389    OUTPUT_EXPORTED     => 3, # output exported symbols
 390    OUTPUT_INTERNAL     => 4, # output non-exported symbols
 391};
 392my $output_selection = OUTPUT_ALL;
 393my $show_not_found = 0;
 394
 395my @export_file_list;
 396
 397my @build_time;
 398if (defined($ENV{'KBUILD_BUILD_TIMESTAMP'}) &&
 399    (my $seconds = `date -d"${ENV{'KBUILD_BUILD_TIMESTAMP'}}" +%s`) ne '') {
 400    @build_time = gmtime($seconds);
 401} else {
 402    @build_time = localtime;
 403}
 404
 405my $man_date = ('January', 'February', 'March', 'April', 'May', 'June',
 406                'July', 'August', 'September', 'October',
 407                'November', 'December')[$build_time[4]] .
 408  " " . ($build_time[5]+1900);
 409
 410# Essentially these are globals.
 411# They probably want to be tidied up, made more localised or something.
 412# CAVEAT EMPTOR!  Some of the others I localised may not want to be, which
 413# could cause "use of undefined value" or other bugs.
 414my ($function, %function_table, %parametertypes, $declaration_purpose);
 415my $declaration_start_line;
 416my ($type, $declaration_name, $return_type);
 417my ($newsection, $newcontents, $prototype, $brcount, %source_map);
 418
 419if (defined($ENV{'KBUILD_VERBOSE'})) {
 420        $verbose = "$ENV{'KBUILD_VERBOSE'}";
 421}
 422
 423# Generated docbook code is inserted in a template at a point where
 424# docbook v3.1 requires a non-zero sequence of RefEntry's; see:
 425# http://www.oasis-open.org/docbook/documentation/reference/html/refentry.html
 426# We keep track of number of generated entries and generate a dummy
 427# if needs be to ensure the expanded template can be postprocessed
 428# into html.
 429my $section_counter = 0;
 430
 431my $lineprefix="";
 432
 433# Parser states
 434use constant {
 435    STATE_NORMAL        => 0, # normal code
 436    STATE_NAME          => 1, # looking for function name
 437    STATE_FIELD         => 2, # scanning field start
 438    STATE_PROTO         => 3, # scanning prototype
 439    STATE_DOCBLOCK      => 4, # documentation block
 440    STATE_INLINE        => 5, # gathering documentation outside main block
 441};
 442my $state;
 443my $in_doc_sect;
 444
 445# Inline documentation state
 446use constant {
 447    STATE_INLINE_NA     => 0, # not applicable ($state != STATE_INLINE)
 448    STATE_INLINE_NAME   => 1, # looking for member name (@foo:)
 449    STATE_INLINE_TEXT   => 2, # looking for member documentation
 450    STATE_INLINE_END    => 3, # done
 451    STATE_INLINE_ERROR  => 4, # error - Comment without header was found.
 452                              # Spit a warning as it's not
 453                              # proper kernel-doc and ignore the rest.
 454};
 455my $inline_doc_state;
 456
 457#declaration types: can be
 458# 'function', 'struct', 'union', 'enum', 'typedef'
 459my $decl_type;
 460
 461my $doc_start = '^/\*\*\s*$'; # Allow whitespace at end of comment start.
 462my $doc_end = '\*/';
 463my $doc_com = '\s*\*\s*';
 464my $doc_com_body = '\s*\* ?';
 465my $doc_decl = $doc_com . '(\w+)';
 466# @params and a strictly limited set of supported section names
 467my $doc_sect = $doc_com . 
 468    '\s*(\@[.\w]+|\@\.\.\.|description|context|returns?|notes?|examples?)\s*:(.*)';
 469my $doc_content = $doc_com_body . '(.*)';
 470my $doc_block = $doc_com . 'DOC:\s*(.*)?';
 471my $doc_inline_start = '^\s*/\*\*\s*$';
 472my $doc_inline_sect = '\s*\*\s*(@[\w\s]+):(.*)';
 473my $doc_inline_end = '^\s*\*/\s*$';
 474my $doc_inline_oneline = '^\s*/\*\*\s*(@[\w\s]+):\s*(.*)\s*\*/\s*$';
 475my $export_symbol = '^\s*EXPORT_SYMBOL(_GPL)?\s*\(\s*(\w+)\s*\)\s*;';
 476
 477my %parameterdescs;
 478my %parameterdesc_start_lines;
 479my @parameterlist;
 480my %sections;
 481my @sectionlist;
 482my %section_start_lines;
 483my $sectcheck;
 484my $struct_actual;
 485
 486my $contents = "";
 487my $new_start_line = 0;
 488
 489# the canonical section names. see also $doc_sect above.
 490my $section_default = "Description";    # default section
 491my $section_intro = "Introduction";
 492my $section = $section_default;
 493my $section_context = "Context";
 494my $section_return = "Return";
 495
 496my $undescribed = "-- undescribed --";
 497
 498reset_state();
 499
 500while ($ARGV[0] =~ m/^-(.*)/) {
 501    my $cmd = shift @ARGV;
 502    if ($cmd eq "-html") {
 503        $output_mode = "html";
 504        @highlights = @highlights_html;
 505        $blankline = $blankline_html;
 506    } elsif ($cmd eq "-html5") {
 507        $output_mode = "html5";
 508        @highlights = @highlights_html5;
 509        $blankline = $blankline_html5;
 510    } elsif ($cmd eq "-man") {
 511        $output_mode = "man";
 512        @highlights = @highlights_man;
 513        $blankline = $blankline_man;
 514    } elsif ($cmd eq "-text") {
 515        $output_mode = "text";
 516        @highlights = @highlights_text;
 517        $blankline = $blankline_text;
 518    } elsif ($cmd eq "-rst") {
 519        $output_mode = "rst";
 520        @highlights = @highlights_rst;
 521        $blankline = $blankline_rst;
 522    } elsif ($cmd eq "-docbook") {
 523        $output_mode = "xml";
 524        @highlights = @highlights_xml;
 525        $blankline = $blankline_xml;
 526    } elsif ($cmd eq "-list") {
 527        $output_mode = "list";
 528        @highlights = @highlights_list;
 529        $blankline = $blankline_list;
 530    } elsif ($cmd eq "-gnome") {
 531        $output_mode = "gnome";
 532        @highlights = @highlights_gnome;
 533        $blankline = $blankline_gnome;
 534    } elsif ($cmd eq "-module") { # not needed for XML, inherits from calling document
 535        $modulename = shift @ARGV;
 536    } elsif ($cmd eq "-function") { # to only output specific functions
 537        $output_selection = OUTPUT_INCLUDE;
 538        $function = shift @ARGV;
 539        $function_table{$function} = 1;
 540    } elsif ($cmd eq "-nofunction") { # output all except specific functions
 541        $output_selection = OUTPUT_EXCLUDE;
 542        $function = shift @ARGV;
 543        $function_table{$function} = 1;
 544    } elsif ($cmd eq "-export") { # only exported symbols
 545        $output_selection = OUTPUT_EXPORTED;
 546        %function_table = ();
 547    } elsif ($cmd eq "-internal") { # only non-exported symbols
 548        $output_selection = OUTPUT_INTERNAL;
 549        %function_table = ();
 550    } elsif ($cmd eq "-export-file") {
 551        my $file = shift @ARGV;
 552        push(@export_file_list, $file);
 553    } elsif ($cmd eq "-v") {
 554        $verbose = 1;
 555    } elsif (($cmd eq "-h") || ($cmd eq "--help")) {
 556        usage();
 557    } elsif ($cmd eq '-no-doc-sections') {
 558            $no_doc_sections = 1;
 559    } elsif ($cmd eq '-enable-lineno') {
 560            $enable_lineno = 1;
 561    } elsif ($cmd eq '-show-not-found') {
 562        $show_not_found = 1;
 563    }
 564}
 565
 566# continue execution near EOF;
 567
 568# get kernel version from env
 569sub get_kernel_version() {
 570    my $version = 'unknown kernel version';
 571
 572    if (defined($ENV{'KERNELVERSION'})) {
 573        $version = $ENV{'KERNELVERSION'};
 574    }
 575    return $version;
 576}
 577
 578#
 579sub print_lineno {
 580    my $lineno = shift;
 581    if ($enable_lineno && defined($lineno)) {
 582        print "#define LINENO " . $lineno . "\n";
 583    }
 584}
 585##
 586# dumps section contents to arrays/hashes intended for that purpose.
 587#
 588sub dump_section {
 589    my $file = shift;
 590    my $name = shift;
 591    my $contents = join "\n", @_;
 592
 593    if ($name =~ m/$type_param/) {
 594        $name = $1;
 595        $parameterdescs{$name} = $contents;
 596        $sectcheck = $sectcheck . $name . " ";
 597        $parameterdesc_start_lines{$name} = $new_start_line;
 598        $new_start_line = 0;
 599    } elsif ($name eq "@\.\.\.") {
 600        $name = "...";
 601        $parameterdescs{$name} = $contents;
 602        $sectcheck = $sectcheck . $name . " ";
 603        $parameterdesc_start_lines{$name} = $new_start_line;
 604        $new_start_line = 0;
 605    } else {
 606        if (defined($sections{$name}) && ($sections{$name} ne "")) {
 607            # Only warn on user specified duplicate section names.
 608            if ($name ne $section_default) {
 609                print STDERR "${file}:$.: warning: duplicate section name '$name'\n";
 610                ++$warnings;
 611            }
 612            $sections{$name} .= $contents;
 613        } else {
 614            $sections{$name} = $contents;
 615            push @sectionlist, $name;
 616            $section_start_lines{$name} = $new_start_line;
 617            $new_start_line = 0;
 618        }
 619    }
 620}
 621
 622##
 623# dump DOC: section after checking that it should go out
 624#
 625sub dump_doc_section {
 626    my $file = shift;
 627    my $name = shift;
 628    my $contents = join "\n", @_;
 629
 630    if ($no_doc_sections) {
 631        return;
 632    }
 633
 634    if (($output_selection == OUTPUT_ALL) ||
 635        ($output_selection == OUTPUT_INCLUDE &&
 636         defined($function_table{$name})) ||
 637        ($output_selection == OUTPUT_EXCLUDE &&
 638         !defined($function_table{$name})))
 639    {
 640        dump_section($file, $name, $contents);
 641        output_blockhead({'sectionlist' => \@sectionlist,
 642                          'sections' => \%sections,
 643                          'module' => $modulename,
 644                          'content-only' => ($output_selection != OUTPUT_ALL), });
 645    }
 646}
 647
 648##
 649# output function
 650#
 651# parameterdescs, a hash.
 652#  function => "function name"
 653#  parameterlist => @list of parameters
 654#  parameterdescs => %parameter descriptions
 655#  sectionlist => @list of sections
 656#  sections => %section descriptions
 657#
 658
 659sub output_highlight {
 660    my $contents = join "\n",@_;
 661    my $line;
 662
 663#   DEBUG
 664#   if (!defined $contents) {
 665#       use Carp;
 666#       confess "output_highlight got called with no args?\n";
 667#   }
 668
 669    if ($output_mode eq "html" || $output_mode eq "html5" ||
 670        $output_mode eq "xml") {
 671        $contents = local_unescape($contents);
 672        # convert data read & converted thru xml_escape() into &xyz; format:
 673        $contents =~ s/\\\\\\/\&/g;
 674    }
 675#   print STDERR "contents b4:$contents\n";
 676    eval $dohighlight;
 677    die $@ if $@;
 678#   print STDERR "contents af:$contents\n";
 679
 680#   strip whitespaces when generating html5
 681    if ($output_mode eq "html5") {
 682        $contents =~ s/^\s+//;
 683        $contents =~ s/\s+$//;
 684    }
 685    foreach $line (split "\n", $contents) {
 686        if (! $output_preformatted) {
 687            $line =~ s/^\s*//;
 688        }
 689        if ($line eq ""){
 690            if (! $output_preformatted) {
 691                print $lineprefix, local_unescape($blankline);
 692            }
 693        } else {
 694            $line =~ s/\\\\\\/\&/g;
 695            if ($output_mode eq "man" && substr($line, 0, 1) eq ".") {
 696                print "\\&$line";
 697            } else {
 698                print $lineprefix, $line;
 699            }
 700        }
 701        print "\n";
 702    }
 703}
 704
 705# output sections in html
 706sub output_section_html(%) {
 707    my %args = %{$_[0]};
 708    my $section;
 709
 710    foreach $section (@{$args{'sectionlist'}}) {
 711        print "<h3>$section</h3>\n";
 712        print "<blockquote>\n";
 713        output_highlight($args{'sections'}{$section});
 714        print "</blockquote>\n";
 715    }
 716}
 717
 718# output enum in html
 719sub output_enum_html(%) {
 720    my %args = %{$_[0]};
 721    my ($parameter);
 722    my $count;
 723    print "<h2>enum " . $args{'enum'} . "</h2>\n";
 724
 725    print "<b>enum " . $args{'enum'} . "</b> {<br>\n";
 726    $count = 0;
 727    foreach $parameter (@{$args{'parameterlist'}}) {
 728        print " <b>" . $parameter . "</b>";
 729        if ($count != $#{$args{'parameterlist'}}) {
 730            $count++;
 731            print ",\n";
 732        }
 733        print "<br>";
 734    }
 735    print "};<br>\n";
 736
 737    print "<h3>Constants</h3>\n";
 738    print "<dl>\n";
 739    foreach $parameter (@{$args{'parameterlist'}}) {
 740        print "<dt><b>" . $parameter . "</b>\n";
 741        print "<dd>";
 742        output_highlight($args{'parameterdescs'}{$parameter});
 743    }
 744    print "</dl>\n";
 745    output_section_html(@_);
 746    print "<hr>\n";
 747}
 748
 749# output typedef in html
 750sub output_typedef_html(%) {
 751    my %args = %{$_[0]};
 752    my ($parameter);
 753    my $count;
 754    print "<h2>typedef " . $args{'typedef'} . "</h2>\n";
 755
 756    print "<b>typedef " . $args{'typedef'} . "</b>\n";
 757    output_section_html(@_);
 758    print "<hr>\n";
 759}
 760
 761# output struct in html
 762sub output_struct_html(%) {
 763    my %args = %{$_[0]};
 764    my ($parameter);
 765
 766    print "<h2>" . $args{'type'} . " " . $args{'struct'} . " - " . $args{'purpose'} . "</h2>\n";
 767    print "<b>" . $args{'type'} . " " . $args{'struct'} . "</b> {<br>\n";
 768    foreach $parameter (@{$args{'parameterlist'}}) {
 769        if ($parameter =~ /^#/) {
 770                print "$parameter<br>\n";
 771                next;
 772        }
 773        my $parameter_name = $parameter;
 774        $parameter_name =~ s/\[.*//;
 775
 776        ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
 777        $type = $args{'parametertypes'}{$parameter};
 778        if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
 779            # pointer-to-function
 780            print "&nbsp; &nbsp; <i>$1</i><b>$parameter</b>) <i>($2)</i>;<br>\n";
 781        } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
 782            # bitfield
 783            print "&nbsp; &nbsp; <i>$1</i> <b>$parameter</b>$2;<br>\n";
 784        } else {
 785            print "&nbsp; &nbsp; <i>$type</i> <b>$parameter</b>;<br>\n";
 786        }
 787    }
 788    print "};<br>\n";
 789
 790    print "<h3>Members</h3>\n";
 791    print "<dl>\n";
 792    foreach $parameter (@{$args{'parameterlist'}}) {
 793        ($parameter =~ /^#/) && next;
 794
 795        my $parameter_name = $parameter;
 796        $parameter_name =~ s/\[.*//;
 797
 798        ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
 799        print "<dt><b>" . $parameter . "</b>\n";
 800        print "<dd>";
 801        output_highlight($args{'parameterdescs'}{$parameter_name});
 802    }
 803    print "</dl>\n";
 804    output_section_html(@_);
 805    print "<hr>\n";
 806}
 807
 808# output function in html
 809sub output_function_html(%) {
 810    my %args = %{$_[0]};
 811    my ($parameter, $section);
 812    my $count;
 813
 814    print "<h2>" . $args{'function'} . " - " . $args{'purpose'} . "</h2>\n";
 815    print "<i>" . $args{'functiontype'} . "</i>\n";
 816    print "<b>" . $args{'function'} . "</b>\n";
 817    print "(";
 818    $count = 0;
 819    foreach $parameter (@{$args{'parameterlist'}}) {
 820        $type = $args{'parametertypes'}{$parameter};
 821        if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
 822            # pointer-to-function
 823            print "<i>$1</i><b>$parameter</b>) <i>($2)</i>";
 824        } else {
 825            print "<i>" . $type . "</i> <b>" . $parameter . "</b>";
 826        }
 827        if ($count != $#{$args{'parameterlist'}}) {
 828            $count++;
 829            print ",\n";
 830        }
 831    }
 832    print ")\n";
 833
 834    print "<h3>Arguments</h3>\n";
 835    print "<dl>\n";
 836    foreach $parameter (@{$args{'parameterlist'}}) {
 837        my $parameter_name = $parameter;
 838        $parameter_name =~ s/\[.*//;
 839
 840        ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
 841        print "<dt><b>" . $parameter . "</b>\n";
 842        print "<dd>";
 843        output_highlight($args{'parameterdescs'}{$parameter_name});
 844    }
 845    print "</dl>\n";
 846    output_section_html(@_);
 847    print "<hr>\n";
 848}
 849
 850# output DOC: block header in html
 851sub output_blockhead_html(%) {
 852    my %args = %{$_[0]};
 853    my ($parameter, $section);
 854    my $count;
 855
 856    foreach $section (@{$args{'sectionlist'}}) {
 857        print "<h3>$section</h3>\n";
 858        print "<ul>\n";
 859        output_highlight($args{'sections'}{$section});
 860        print "</ul>\n";
 861    }
 862    print "<hr>\n";
 863}
 864
 865# output sections in html5
 866sub output_section_html5(%) {
 867    my %args = %{$_[0]};
 868    my $section;
 869
 870    foreach $section (@{$args{'sectionlist'}}) {
 871        print "<section>\n";
 872        print "<h1>$section</h1>\n";
 873        print "<p>\n";
 874        output_highlight($args{'sections'}{$section});
 875        print "</p>\n";
 876        print "</section>\n";
 877    }
 878}
 879
 880# output enum in html5
 881sub output_enum_html5(%) {
 882    my %args = %{$_[0]};
 883    my ($parameter);
 884    my $count;
 885    my $html5id;
 886
 887    $html5id = $args{'enum'};
 888    $html5id =~ s/[^a-zA-Z0-9\-]+/_/g;
 889    print "<article class=\"enum\" id=\"enum:". $html5id . "\">";
 890    print "<h1>enum " . $args{'enum'} . "</h1>\n";
 891    print "<ol class=\"code\">\n";
 892    print "<li>";
 893    print "<span class=\"keyword\">enum</span> ";
 894    print "<span class=\"identifier\">" . $args{'enum'} . "</span> {";
 895    print "</li>\n";
 896    $count = 0;
 897    foreach $parameter (@{$args{'parameterlist'}}) {
 898        print "<li class=\"indent\">";
 899        print "<span class=\"param\">" . $parameter . "</span>";
 900        if ($count != $#{$args{'parameterlist'}}) {
 901            $count++;
 902            print ",";
 903        }
 904        print "</li>\n";
 905    }
 906    print "<li>};</li>\n";
 907    print "</ol>\n";
 908
 909    print "<section>\n";
 910    print "<h1>Constants</h1>\n";
 911    print "<dl>\n";
 912    foreach $parameter (@{$args{'parameterlist'}}) {
 913        print "<dt>" . $parameter . "</dt>\n";
 914        print "<dd>";
 915        output_highlight($args{'parameterdescs'}{$parameter});
 916        print "</dd>\n";
 917    }
 918    print "</dl>\n";
 919    print "</section>\n";
 920    output_section_html5(@_);
 921    print "</article>\n";
 922}
 923
 924# output typedef in html5
 925sub output_typedef_html5(%) {
 926    my %args = %{$_[0]};
 927    my ($parameter);
 928    my $count;
 929    my $html5id;
 930
 931    $html5id = $args{'typedef'};
 932    $html5id =~ s/[^a-zA-Z0-9\-]+/_/g;
 933    print "<article class=\"typedef\" id=\"typedef:" . $html5id . "\">\n";
 934    print "<h1>typedef " . $args{'typedef'} . "</h1>\n";
 935
 936    print "<ol class=\"code\">\n";
 937    print "<li>";
 938    print "<span class=\"keyword\">typedef</span> ";
 939    print "<span class=\"identifier\">" . $args{'typedef'} . "</span>";
 940    print "</li>\n";
 941    print "</ol>\n";
 942    output_section_html5(@_);
 943    print "</article>\n";
 944}
 945
 946# output struct in html5
 947sub output_struct_html5(%) {
 948    my %args = %{$_[0]};
 949    my ($parameter);
 950    my $html5id;
 951
 952    $html5id = $args{'struct'};
 953    $html5id =~ s/[^a-zA-Z0-9\-]+/_/g;
 954    print "<article class=\"struct\" id=\"struct:" . $html5id . "\">\n";
 955    print "<hgroup>\n";
 956    print "<h1>" . $args{'type'} . " " . $args{'struct'} . "</h1>";
 957    print "<h2>". $args{'purpose'} . "</h2>\n";
 958    print "</hgroup>\n";
 959    print "<ol class=\"code\">\n";
 960    print "<li>";
 961    print "<span class=\"type\">" . $args{'type'} . "</span> ";
 962    print "<span class=\"identifier\">" . $args{'struct'} . "</span> {";
 963    print "</li>\n";
 964    foreach $parameter (@{$args{'parameterlist'}}) {
 965        print "<li class=\"indent\">";
 966        if ($parameter =~ /^#/) {
 967                print "<span class=\"param\">" . $parameter ."</span>\n";
 968                print "</li>\n";
 969                next;
 970        }
 971        my $parameter_name = $parameter;
 972        $parameter_name =~ s/\[.*//;
 973
 974        ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
 975        $type = $args{'parametertypes'}{$parameter};
 976        if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
 977            # pointer-to-function
 978            print "<span class=\"type\">$1</span> ";
 979            print "<span class=\"param\">$parameter</span>";
 980            print "<span class=\"type\">)</span> ";
 981            print "(<span class=\"args\">$2</span>);";
 982        } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
 983            # bitfield
 984            print "<span class=\"type\">$1</span> ";
 985            print "<span class=\"param\">$parameter</span>";
 986            print "<span class=\"bits\">$2</span>;";
 987        } else {
 988            print "<span class=\"type\">$type</span> ";
 989            print "<span class=\"param\">$parameter</span>;";
 990        }
 991        print "</li>\n";
 992    }
 993    print "<li>};</li>\n";
 994    print "</ol>\n";
 995
 996    print "<section>\n";
 997    print "<h1>Members</h1>\n";
 998    print "<dl>\n";
 999    foreach $parameter (@{$args{'parameterlist'}}) {
1000        ($parameter =~ /^#/) && next;
1001
1002        my $parameter_name = $parameter;
1003        $parameter_name =~ s/\[.*//;
1004
1005        ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
1006        print "<dt>" . $parameter . "</dt>\n";
1007        print "<dd>";
1008        output_highlight($args{'parameterdescs'}{$parameter_name});
1009        print "</dd>\n";
1010    }
1011    print "</dl>\n";
1012    print "</section>\n";
1013    output_section_html5(@_);
1014    print "</article>\n";
1015}
1016
1017# output function in html5
1018sub output_function_html5(%) {
1019    my %args = %{$_[0]};
1020    my ($parameter, $section);
1021    my $count;
1022    my $html5id;
1023
1024    $html5id = $args{'function'};
1025    $html5id =~ s/[^a-zA-Z0-9\-]+/_/g;
1026    print "<article class=\"function\" id=\"func:". $html5id . "\">\n";
1027    print "<hgroup>\n";
1028    print "<h1>" . $args{'function'} . "</h1>";
1029    print "<h2>" . $args{'purpose'} . "</h2>\n";
1030    print "</hgroup>\n";
1031    print "<ol class=\"code\">\n";
1032    print "<li>";
1033    print "<span class=\"type\">" . $args{'functiontype'} . "</span> ";
1034    print "<span class=\"identifier\">" . $args{'function'} . "</span> (";
1035    print "</li>";
1036    $count = 0;
1037    foreach $parameter (@{$args{'parameterlist'}}) {
1038        print "<li class=\"indent\">";
1039        $type = $args{'parametertypes'}{$parameter};
1040        if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
1041            # pointer-to-function
1042            print "<span class=\"type\">$1</span> ";
1043            print "<span class=\"param\">$parameter</span>";
1044            print "<span class=\"type\">)</span> ";
1045            print "(<span class=\"args\">$2</span>)";
1046        } else {
1047            print "<span class=\"type\">$type</span> ";
1048            print "<span class=\"param\">$parameter</span>";
1049        }
1050        if ($count != $#{$args{'parameterlist'}}) {
1051            $count++;
1052            print ",";
1053        }
1054        print "</li>\n";
1055    }
1056    print "<li>)</li>\n";
1057    print "</ol>\n";
1058
1059    print "<section>\n";
1060    print "<h1>Arguments</h1>\n";
1061    print "<p>\n";
1062    print "<dl>\n";
1063    foreach $parameter (@{$args{'parameterlist'}}) {
1064        my $parameter_name = $parameter;
1065        $parameter_name =~ s/\[.*//;
1066
1067        ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
1068        print "<dt>" . $parameter . "</dt>\n";
1069        print "<dd>";
1070        output_highlight($args{'parameterdescs'}{$parameter_name});
1071        print "</dd>\n";
1072    }
1073    print "</dl>\n";
1074    print "</section>\n";
1075    output_section_html5(@_);
1076    print "</article>\n";
1077}
1078
1079# output DOC: block header in html5
1080sub output_blockhead_html5(%) {
1081    my %args = %{$_[0]};
1082    my ($parameter, $section);
1083    my $count;
1084    my $html5id;
1085
1086    foreach $section (@{$args{'sectionlist'}}) {
1087        $html5id = $section;
1088        $html5id =~ s/[^a-zA-Z0-9\-]+/_/g;
1089        print "<article class=\"doc\" id=\"doc:". $html5id . "\">\n";
1090        print "<h1>$section</h1>\n";
1091        print "<p>\n";
1092        output_highlight($args{'sections'}{$section});
1093        print "</p>\n";
1094    }
1095    print "</article>\n";
1096}
1097
1098sub output_section_xml(%) {
1099    my %args = %{$_[0]};
1100    my $section;
1101    # print out each section
1102    $lineprefix="   ";
1103    foreach $section (@{$args{'sectionlist'}}) {
1104        print "<refsect1>\n";
1105        print "<title>$section</title>\n";
1106        if ($section =~ m/EXAMPLE/i) {
1107            print "<informalexample><programlisting>\n";
1108            $output_preformatted = 1;
1109        } else {
1110            print "<para>\n";
1111        }
1112        output_highlight($args{'sections'}{$section});
1113        $output_preformatted = 0;
1114        if ($section =~ m/EXAMPLE/i) {
1115            print "</programlisting></informalexample>\n";
1116        } else {
1117            print "</para>\n";
1118        }
1119        print "</refsect1>\n";
1120    }
1121}
1122
1123# output function in XML DocBook
1124sub output_function_xml(%) {
1125    my %args = %{$_[0]};
1126    my ($parameter, $section);
1127    my $count;
1128    my $id;
1129
1130    $id = "API-" . $args{'function'};
1131    $id =~ s/[^A-Za-z0-9]/-/g;
1132
1133    print "<refentry id=\"$id\">\n";
1134    print "<refentryinfo>\n";
1135    print " <title>LINUX</title>\n";
1136    print " <productname>Kernel Hackers Manual</productname>\n";
1137    print " <date>$man_date</date>\n";
1138    print "</refentryinfo>\n";
1139    print "<refmeta>\n";
1140    print " <refentrytitle><phrase>" . $args{'function'} . "</phrase></refentrytitle>\n";
1141    print " <manvolnum>9</manvolnum>\n";
1142    print " <refmiscinfo class=\"version\">" . $kernelversion . "</refmiscinfo>\n";
1143    print "</refmeta>\n";
1144    print "<refnamediv>\n";
1145    print " <refname>" . $args{'function'} . "</refname>\n";
1146    print " <refpurpose>\n";
1147    print "  ";
1148    output_highlight ($args{'purpose'});
1149    print " </refpurpose>\n";
1150    print "</refnamediv>\n";
1151
1152    print "<refsynopsisdiv>\n";
1153    print " <title>Synopsis</title>\n";
1154    print "  <funcsynopsis><funcprototype>\n";
1155    print "   <funcdef>" . $args{'functiontype'} . " ";
1156    print "<function>" . $args{'function'} . " </function></funcdef>\n";
1157
1158    $count = 0;
1159    if ($#{$args{'parameterlist'}} >= 0) {
1160        foreach $parameter (@{$args{'parameterlist'}}) {
1161            $type = $args{'parametertypes'}{$parameter};
1162            if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
1163                # pointer-to-function
1164                print "   <paramdef>$1<parameter>$parameter</parameter>)\n";
1165                print "     <funcparams>$2</funcparams></paramdef>\n";
1166            } else {
1167                print "   <paramdef>" . $type;
1168                print " <parameter>$parameter</parameter></paramdef>\n";
1169            }
1170        }
1171    } else {
1172        print "  <void/>\n";
1173    }
1174    print "  </funcprototype></funcsynopsis>\n";
1175    print "</refsynopsisdiv>\n";
1176
1177    # print parameters
1178    print "<refsect1>\n <title>Arguments</title>\n";
1179    if ($#{$args{'parameterlist'}} >= 0) {
1180        print " <variablelist>\n";
1181        foreach $parameter (@{$args{'parameterlist'}}) {
1182            my $parameter_name = $parameter;
1183            $parameter_name =~ s/\[.*//;
1184            $type = $args{'parametertypes'}{$parameter};
1185
1186            print "  <varlistentry>\n   <term><parameter>$type $parameter</parameter></term>\n";
1187            print "   <listitem>\n    <para>\n";
1188            $lineprefix="     ";
1189            output_highlight($args{'parameterdescs'}{$parameter_name});
1190            print "    </para>\n   </listitem>\n  </varlistentry>\n";
1191        }
1192        print " </variablelist>\n";
1193    } else {
1194        print " <para>\n  None\n </para>\n";
1195    }
1196    print "</refsect1>\n";
1197
1198    output_section_xml(@_);
1199    print "</refentry>\n\n";
1200}
1201
1202# output struct in XML DocBook
1203sub output_struct_xml(%) {
1204    my %args = %{$_[0]};
1205    my ($parameter, $section);
1206    my $id;
1207
1208    $id = "API-struct-" . $args{'struct'};
1209    $id =~ s/[^A-Za-z0-9]/-/g;
1210
1211    print "<refentry id=\"$id\">\n";
1212    print "<refentryinfo>\n";
1213    print " <title>LINUX</title>\n";
1214    print " <productname>Kernel Hackers Manual</productname>\n";
1215    print " <date>$man_date</date>\n";
1216    print "</refentryinfo>\n";
1217    print "<refmeta>\n";
1218    print " <refentrytitle><phrase>" . $args{'type'} . " " . $args{'struct'} . "</phrase></refentrytitle>\n";
1219    print " <manvolnum>9</manvolnum>\n";
1220    print " <refmiscinfo class=\"version\">" . $kernelversion . "</refmiscinfo>\n";
1221    print "</refmeta>\n";
1222    print "<refnamediv>\n";
1223    print " <refname>" . $args{'type'} . " " . $args{'struct'} . "</refname>\n";
1224    print " <refpurpose>\n";
1225    print "  ";
1226    output_highlight ($args{'purpose'});
1227    print " </refpurpose>\n";
1228    print "</refnamediv>\n";
1229
1230    print "<refsynopsisdiv>\n";
1231    print " <title>Synopsis</title>\n";
1232    print "  <programlisting>\n";
1233    print $args{'type'} . " " . $args{'struct'} . " {\n";
1234    foreach $parameter (@{$args{'parameterlist'}}) {
1235        if ($parameter =~ /^#/) {
1236            my $prm = $parameter;
1237            # convert data read & converted thru xml_escape() into &xyz; format:
1238            # This allows us to have #define macros interspersed in a struct.
1239            $prm =~ s/\\\\\\/\&/g;
1240            print "$prm\n";
1241            next;
1242        }
1243
1244        my $parameter_name = $parameter;
1245        $parameter_name =~ s/\[.*//;
1246
1247        defined($args{'parameterdescs'}{$parameter_name}) || next;
1248        ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
1249        $type = $args{'parametertypes'}{$parameter};
1250        if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
1251            # pointer-to-function
1252            print "  $1 $parameter) ($2);\n";
1253        } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
1254            # bitfield
1255            print "  $1 $parameter$2;\n";
1256        } else {
1257            print "  " . $type . " " . $parameter . ";\n";
1258        }
1259    }
1260    print "};";
1261    print "  </programlisting>\n";
1262    print "</refsynopsisdiv>\n";
1263
1264    print " <refsect1>\n";
1265    print "  <title>Members</title>\n";
1266
1267    if ($#{$args{'parameterlist'}} >= 0) {
1268    print "  <variablelist>\n";
1269    foreach $parameter (@{$args{'parameterlist'}}) {
1270      ($parameter =~ /^#/) && next;
1271
1272      my $parameter_name = $parameter;
1273      $parameter_name =~ s/\[.*//;
1274
1275      defined($args{'parameterdescs'}{$parameter_name}) || next;
1276      ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
1277      $type = $args{'parametertypes'}{$parameter};
1278      print "    <varlistentry>";
1279      print "      <term><literal>$type $parameter</literal></term>\n";
1280      print "      <listitem><para>\n";
1281      output_highlight($args{'parameterdescs'}{$parameter_name});
1282      print "      </para></listitem>\n";
1283      print "    </varlistentry>\n";
1284    }
1285    print "  </variablelist>\n";
1286    } else {
1287        print " <para>\n  None\n </para>\n";
1288    }
1289    print " </refsect1>\n";
1290
1291    output_section_xml(@_);
1292
1293    print "</refentry>\n\n";
1294}
1295
1296# output enum in XML DocBook
1297sub output_enum_xml(%) {
1298    my %args = %{$_[0]};
1299    my ($parameter, $section);
1300    my $count;
1301    my $id;
1302
1303    $id = "API-enum-" . $args{'enum'};
1304    $id =~ s/[^A-Za-z0-9]/-/g;
1305
1306    print "<refentry id=\"$id\">\n";
1307    print "<refentryinfo>\n";
1308    print " <title>LINUX</title>\n";
1309    print " <productname>Kernel Hackers Manual</productname>\n";
1310    print " <date>$man_date</date>\n";
1311    print "</refentryinfo>\n";
1312    print "<refmeta>\n";
1313    print " <refentrytitle><phrase>enum " . $args{'enum'} . "</phrase></refentrytitle>\n";
1314    print " <manvolnum>9</manvolnum>\n";
1315    print " <refmiscinfo class=\"version\">" . $kernelversion . "</refmiscinfo>\n";
1316    print "</refmeta>\n";
1317    print "<refnamediv>\n";
1318    print " <refname>enum " . $args{'enum'} . "</refname>\n";
1319    print " <refpurpose>\n";
1320    print "  ";
1321    output_highlight ($args{'purpose'});
1322    print " </refpurpose>\n";
1323    print "</refnamediv>\n";
1324
1325    print "<refsynopsisdiv>\n";
1326    print " <title>Synopsis</title>\n";
1327    print "  <programlisting>\n";
1328    print "enum " . $args{'enum'} . " {\n";
1329    $count = 0;
1330    foreach $parameter (@{$args{'parameterlist'}}) {
1331        print "  $parameter";
1332        if ($count != $#{$args{'parameterlist'}}) {
1333            $count++;
1334            print ",";
1335        }
1336        print "\n";
1337    }
1338    print "};";
1339    print "  </programlisting>\n";
1340    print "</refsynopsisdiv>\n";
1341
1342    print "<refsect1>\n";
1343    print " <title>Constants</title>\n";
1344    print "  <variablelist>\n";
1345    foreach $parameter (@{$args{'parameterlist'}}) {
1346      my $parameter_name = $parameter;
1347      $parameter_name =~ s/\[.*//;
1348
1349      print "    <varlistentry>";
1350      print "      <term>$parameter</term>\n";
1351      print "      <listitem><para>\n";
1352      output_highlight($args{'parameterdescs'}{$parameter_name});
1353      print "      </para></listitem>\n";
1354      print "    </varlistentry>\n";
1355    }
1356    print "  </variablelist>\n";
1357    print "</refsect1>\n";
1358
1359    output_section_xml(@_);
1360
1361    print "</refentry>\n\n";
1362}
1363
1364# output typedef in XML DocBook
1365sub output_typedef_xml(%) {
1366    my %args = %{$_[0]};
1367    my ($parameter, $section);
1368    my $id;
1369
1370    $id = "API-typedef-" . $args{'typedef'};
1371    $id =~ s/[^A-Za-z0-9]/-/g;
1372
1373    print "<refentry id=\"$id\">\n";
1374    print "<refentryinfo>\n";
1375    print " <title>LINUX</title>\n";
1376    print " <productname>Kernel Hackers Manual</productname>\n";
1377    print " <date>$man_date</date>\n";
1378    print "</refentryinfo>\n";
1379    print "<refmeta>\n";
1380    print " <refentrytitle><phrase>typedef " . $args{'typedef'} . "</phrase></refentrytitle>\n";
1381    print " <manvolnum>9</manvolnum>\n";
1382    print "</refmeta>\n";
1383    print "<refnamediv>\n";
1384    print " <refname>typedef " . $args{'typedef'} . "</refname>\n";
1385    print " <refpurpose>\n";
1386    print "  ";
1387    output_highlight ($args{'purpose'});
1388    print " </refpurpose>\n";
1389    print "</refnamediv>\n";
1390
1391    print "<refsynopsisdiv>\n";
1392    print " <title>Synopsis</title>\n";
1393    print "  <synopsis>typedef " . $args{'typedef'} . ";</synopsis>\n";
1394    print "</refsynopsisdiv>\n";
1395
1396    output_section_xml(@_);
1397
1398    print "</refentry>\n\n";
1399}
1400
1401# output in XML DocBook
1402sub output_blockhead_xml(%) {
1403    my %args = %{$_[0]};
1404    my ($parameter, $section);
1405    my $count;
1406
1407    my $id = $args{'module'};
1408    $id =~ s/[^A-Za-z0-9]/-/g;
1409
1410    # print out each section
1411    $lineprefix="   ";
1412    foreach $section (@{$args{'sectionlist'}}) {
1413        if (!$args{'content-only'}) {
1414                print "<refsect1>\n <title>$section</title>\n";
1415        }
1416        if ($section =~ m/EXAMPLE/i) {
1417            print "<example><para>\n";
1418            $output_preformatted = 1;
1419        } else {
1420            print "<para>\n";
1421        }
1422        output_highlight($args{'sections'}{$section});
1423        $output_preformatted = 0;
1424        if ($section =~ m/EXAMPLE/i) {
1425            print "</para></example>\n";
1426        } else {
1427            print "</para>";
1428        }
1429        if (!$args{'content-only'}) {
1430                print "\n</refsect1>\n";
1431        }
1432    }
1433
1434    print "\n\n";
1435}
1436
1437# output in XML DocBook
1438sub output_function_gnome {
1439    my %args = %{$_[0]};
1440    my ($parameter, $section);
1441    my $count;
1442    my $id;
1443
1444    $id = $args{'module'} . "-" . $args{'function'};
1445    $id =~ s/[^A-Za-z0-9]/-/g;
1446
1447    print "<sect2>\n";
1448    print " <title id=\"$id\">" . $args{'function'} . "</title>\n";
1449
1450    print "  <funcsynopsis>\n";
1451    print "   <funcdef>" . $args{'functiontype'} . " ";
1452    print "<function>" . $args{'function'} . " ";
1453    print "</function></funcdef>\n";
1454
1455    $count = 0;
1456    if ($#{$args{'parameterlist'}} >= 0) {
1457        foreach $parameter (@{$args{'parameterlist'}}) {
1458            $type = $args{'parametertypes'}{$parameter};
1459            if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
1460                # pointer-to-function
1461                print "   <paramdef>$1 <parameter>$parameter</parameter>)\n";
1462                print "     <funcparams>$2</funcparams></paramdef>\n";
1463            } else {
1464                print "   <paramdef>" . $type;
1465                print " <parameter>$parameter</parameter></paramdef>\n";
1466            }
1467        }
1468    } else {
1469        print "  <void>\n";
1470    }
1471    print "  </funcsynopsis>\n";
1472    if ($#{$args{'parameterlist'}} >= 0) {
1473        print " <informaltable pgwide=\"1\" frame=\"none\" role=\"params\">\n";
1474        print "<tgroup cols=\"2\">\n";
1475        print "<colspec colwidth=\"2*\">\n";
1476        print "<colspec colwidth=\"8*\">\n";
1477        print "<tbody>\n";
1478        foreach $parameter (@{$args{'parameterlist'}}) {
1479            my $parameter_name = $parameter;
1480            $parameter_name =~ s/\[.*//;
1481
1482            print "  <row><entry align=\"right\"><parameter>$parameter</parameter></entry>\n";
1483            print "   <entry>\n";
1484            $lineprefix="     ";
1485            output_highlight($args{'parameterdescs'}{$parameter_name});
1486            print "    </entry></row>\n";
1487        }
1488        print " </tbody></tgroup></informaltable>\n";
1489    } else {
1490        print " <para>\n  None\n </para>\n";
1491    }
1492
1493    # print out each section
1494    $lineprefix="   ";
1495    foreach $section (@{$args{'sectionlist'}}) {
1496        print "<simplesect>\n <title>$section</title>\n";
1497        if ($section =~ m/EXAMPLE/i) {
1498            print "<example><programlisting>\n";
1499            $output_preformatted = 1;
1500        } else {
1501        }
1502        print "<para>\n";
1503        output_highlight($args{'sections'}{$section});
1504        $output_preformatted = 0;
1505        print "</para>\n";
1506        if ($section =~ m/EXAMPLE/i) {
1507            print "</programlisting></example>\n";
1508        } else {
1509        }
1510        print " </simplesect>\n";
1511    }
1512
1513    print "</sect2>\n\n";
1514}
1515
1516##
1517# output function in man
1518sub output_function_man(%) {
1519    my %args = %{$_[0]};
1520    my ($parameter, $section);
1521    my $count;
1522
1523    print ".TH \"$args{'function'}\" 9 \"$args{'function'}\" \"$man_date\" \"Kernel Hacker's Manual\" LINUX\n";
1524
1525    print ".SH NAME\n";
1526    print $args{'function'} . " \\- " . $args{'purpose'} . "\n";
1527
1528    print ".SH SYNOPSIS\n";
1529    if ($args{'functiontype'} ne "") {
1530        print ".B \"" . $args{'functiontype'} . "\" " . $args{'function'} . "\n";
1531    } else {
1532        print ".B \"" . $args{'function'} . "\n";
1533    }
1534    $count = 0;
1535    my $parenth = "(";
1536    my $post = ",";
1537    foreach my $parameter (@{$args{'parameterlist'}}) {
1538        if ($count == $#{$args{'parameterlist'}}) {
1539            $post = ");";
1540        }
1541        $type = $args{'parametertypes'}{$parameter};
1542        if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
1543            # pointer-to-function
1544            print ".BI \"" . $parenth . $1 . "\" " . $parameter . " \") (" . $2 . ")" . $post . "\"\n";
1545        } else {
1546            $type =~ s/([^\*])$/$1 /;
1547            print ".BI \"" . $parenth . $type . "\" " . $parameter . " \"" . $post . "\"\n";
1548        }
1549        $count++;
1550        $parenth = "";
1551    }
1552
1553    print ".SH ARGUMENTS\n";
1554    foreach $parameter (@{$args{'parameterlist'}}) {
1555        my $parameter_name = $parameter;
1556        $parameter_name =~ s/\[.*//;
1557
1558        print ".IP \"" . $parameter . "\" 12\n";
1559        output_highlight($args{'parameterdescs'}{$parameter_name});
1560    }
1561    foreach $section (@{$args{'sectionlist'}}) {
1562        print ".SH \"", uc $section, "\"\n";
1563        output_highlight($args{'sections'}{$section});
1564    }
1565}
1566
1567##
1568# output enum in man
1569sub output_enum_man(%) {
1570    my %args = %{$_[0]};
1571    my ($parameter, $section);
1572    my $count;
1573
1574    print ".TH \"$args{'module'}\" 9 \"enum $args{'enum'}\" \"$man_date\" \"API Manual\" LINUX\n";
1575
1576    print ".SH NAME\n";
1577    print "enum " . $args{'enum'} . " \\- " . $args{'purpose'} . "\n";
1578
1579    print ".SH SYNOPSIS\n";
1580    print "enum " . $args{'enum'} . " {\n";
1581    $count = 0;
1582    foreach my $parameter (@{$args{'parameterlist'}}) {
1583        print ".br\n.BI \"    $parameter\"\n";
1584        if ($count == $#{$args{'parameterlist'}}) {
1585            print "\n};\n";
1586            last;
1587        }
1588        else {
1589            print ", \n.br\n";
1590        }
1591        $count++;
1592    }
1593
1594    print ".SH Constants\n";
1595    foreach $parameter (@{$args{'parameterlist'}}) {
1596        my $parameter_name = $parameter;
1597        $parameter_name =~ s/\[.*//;
1598
1599        print ".IP \"" . $parameter . "\" 12\n";
1600        output_highlight($args{'parameterdescs'}{$parameter_name});
1601    }
1602    foreach $section (@{$args{'sectionlist'}}) {
1603        print ".SH \"$section\"\n";
1604        output_highlight($args{'sections'}{$section});
1605    }
1606}
1607
1608##
1609# output struct in man
1610sub output_struct_man(%) {
1611    my %args = %{$_[0]};
1612    my ($parameter, $section);
1613
1614    print ".TH \"$args{'module'}\" 9 \"" . $args{'type'} . " " . $args{'struct'} . "\" \"$man_date\" \"API Manual\" LINUX\n";
1615
1616    print ".SH NAME\n";
1617    print $args{'type'} . " " . $args{'struct'} . " \\- " . $args{'purpose'} . "\n";
1618
1619    print ".SH SYNOPSIS\n";
1620    print $args{'type'} . " " . $args{'struct'} . " {\n.br\n";
1621
1622    foreach my $parameter (@{$args{'parameterlist'}}) {
1623        if ($parameter =~ /^#/) {
1624            print ".BI \"$parameter\"\n.br\n";
1625            next;
1626        }
1627        my $parameter_name = $parameter;
1628        $parameter_name =~ s/\[.*//;
1629
1630        ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
1631        $type = $args{'parametertypes'}{$parameter};
1632        if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
1633            # pointer-to-function
1634            print ".BI \"    " . $1 . "\" " . $parameter . " \") (" . $2 . ")" . "\"\n;\n";
1635        } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
1636            # bitfield
1637            print ".BI \"    " . $1 . "\ \" " . $parameter . $2 . " \"" . "\"\n;\n";
1638        } else {
1639            $type =~ s/([^\*])$/$1 /;
1640            print ".BI \"    " . $type . "\" " . $parameter . " \"" . "\"\n;\n";
1641        }
1642        print "\n.br\n";
1643    }
1644    print "};\n.br\n";
1645
1646    print ".SH Members\n";
1647    foreach $parameter (@{$args{'parameterlist'}}) {
1648        ($parameter =~ /^#/) && next;
1649
1650        my $parameter_name = $parameter;
1651        $parameter_name =~ s/\[.*//;
1652
1653        ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
1654        print ".IP \"" . $parameter . "\" 12\n";
1655        output_highlight($args{'parameterdescs'}{$parameter_name});
1656    }
1657    foreach $section (@{$args{'sectionlist'}}) {
1658        print ".SH \"$section\"\n";
1659        output_highlight($args{'sections'}{$section});
1660    }
1661}
1662
1663##
1664# output typedef in man
1665sub output_typedef_man(%) {
1666    my %args = %{$_[0]};
1667    my ($parameter, $section);
1668
1669    print ".TH \"$args{'module'}\" 9 \"$args{'typedef'}\" \"$man_date\" \"API Manual\" LINUX\n";
1670
1671    print ".SH NAME\n";
1672    print "typedef " . $args{'typedef'} . " \\- " . $args{'purpose'} . "\n";
1673
1674    foreach $section (@{$args{'sectionlist'}}) {
1675        print ".SH \"$section\"\n";
1676        output_highlight($args{'sections'}{$section});
1677    }
1678}
1679
1680sub output_blockhead_man(%) {
1681    my %args = %{$_[0]};
1682    my ($parameter, $section);
1683    my $count;
1684
1685    print ".TH \"$args{'module'}\" 9 \"$args{'module'}\" \"$man_date\" \"API Manual\" LINUX\n";
1686
1687    foreach $section (@{$args{'sectionlist'}}) {
1688        print ".SH \"$section\"\n";
1689        output_highlight($args{'sections'}{$section});
1690    }
1691}
1692
1693##
1694# output in text
1695sub output_function_text(%) {
1696    my %args = %{$_[0]};
1697    my ($parameter, $section);
1698    my $start;
1699
1700    print "Name:\n\n";
1701    print $args{'function'} . " - " . $args{'purpose'} . "\n";
1702
1703    print "\nSynopsis:\n\n";
1704    if ($args{'functiontype'} ne "") {
1705        $start = $args{'functiontype'} . " " . $args{'function'} . " (";
1706    } else {
1707        $start = $args{'function'} . " (";
1708    }
1709    print $start;
1710
1711    my $count = 0;
1712    foreach my $parameter (@{$args{'parameterlist'}}) {
1713        $type = $args{'parametertypes'}{$parameter};
1714        if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
1715            # pointer-to-function
1716            print $1 . $parameter . ") (" . $2;
1717        } else {
1718            print $type . " " . $parameter;
1719        }
1720        if ($count != $#{$args{'parameterlist'}}) {
1721            $count++;
1722            print ",\n";
1723            print " " x length($start);
1724        } else {
1725            print ");\n\n";
1726        }
1727    }
1728
1729    print "Arguments:\n\n";
1730    foreach $parameter (@{$args{'parameterlist'}}) {
1731        my $parameter_name = $parameter;
1732        $parameter_name =~ s/\[.*//;
1733
1734        print $parameter . "\n\t" . $args{'parameterdescs'}{$parameter_name} . "\n";
1735    }
1736    output_section_text(@_);
1737}
1738
1739#output sections in text
1740sub output_section_text(%) {
1741    my %args = %{$_[0]};
1742    my $section;
1743
1744    print "\n";
1745    foreach $section (@{$args{'sectionlist'}}) {
1746        print "$section:\n\n";
1747        output_highlight($args{'sections'}{$section});
1748    }
1749    print "\n\n";
1750}
1751
1752# output enum in text
1753sub output_enum_text(%) {
1754    my %args = %{$_[0]};
1755    my ($parameter);
1756    my $count;
1757    print "Enum:\n\n";
1758
1759    print "enum " . $args{'enum'} . " - " . $args{'purpose'} . "\n\n";
1760    print "enum " . $args{'enum'} . " {\n";
1761    $count = 0;
1762    foreach $parameter (@{$args{'parameterlist'}}) {
1763        print "\t$parameter";
1764        if ($count != $#{$args{'parameterlist'}}) {
1765            $count++;
1766            print ",";
1767        }
1768        print "\n";
1769    }
1770    print "};\n\n";
1771
1772    print "Constants:\n\n";
1773    foreach $parameter (@{$args{'parameterlist'}}) {
1774        print "$parameter\n\t";
1775        print $args{'parameterdescs'}{$parameter} . "\n";
1776    }
1777
1778    output_section_text(@_);
1779}
1780
1781# output typedef in text
1782sub output_typedef_text(%) {
1783    my %args = %{$_[0]};
1784    my ($parameter);
1785    my $count;
1786    print "Typedef:\n\n";
1787
1788    print "typedef " . $args{'typedef'} . " - " . $args{'purpose'} . "\n";
1789    output_section_text(@_);
1790}
1791
1792# output struct as text
1793sub output_struct_text(%) {
1794    my %args = %{$_[0]};
1795    my ($parameter);
1796
1797    print $args{'type'} . " " . $args{'struct'} . " - " . $args{'purpose'} . "\n\n";
1798    print $args{'type'} . " " . $args{'struct'} . " {\n";
1799    foreach $parameter (@{$args{'parameterlist'}}) {
1800        if ($parameter =~ /^#/) {
1801            print "$parameter\n";
1802            next;
1803        }
1804
1805        my $parameter_name = $parameter;
1806        $parameter_name =~ s/\[.*//;
1807
1808        ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
1809        $type = $args{'parametertypes'}{$parameter};
1810        if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
1811            # pointer-to-function
1812            print "\t$1 $parameter) ($2);\n";
1813        } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
1814            # bitfield
1815            print "\t$1 $parameter$2;\n";
1816        } else {
1817            print "\t" . $type . " " . $parameter . ";\n";
1818        }
1819    }
1820    print "};\n\n";
1821
1822    print "Members:\n\n";
1823    foreach $parameter (@{$args{'parameterlist'}}) {
1824        ($parameter =~ /^#/) && next;
1825
1826        my $parameter_name = $parameter;
1827        $parameter_name =~ s/\[.*//;
1828
1829        ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
1830        print "$parameter\n\t";
1831        print $args{'parameterdescs'}{$parameter_name} . "\n";
1832    }
1833    print "\n";
1834    output_section_text(@_);
1835}
1836
1837sub output_blockhead_text(%) {
1838    my %args = %{$_[0]};
1839    my ($parameter, $section);
1840
1841    foreach $section (@{$args{'sectionlist'}}) {
1842        print " $section:\n";
1843        print "    -> ";
1844        output_highlight($args{'sections'}{$section});
1845    }
1846}
1847
1848##
1849# output in restructured text
1850#
1851
1852#
1853# This could use some work; it's used to output the DOC: sections, and
1854# starts by putting out the name of the doc section itself, but that tends
1855# to duplicate a header already in the template file.
1856#
1857sub output_blockhead_rst(%) {
1858    my %args = %{$_[0]};
1859    my ($parameter, $section);
1860
1861    foreach $section (@{$args{'sectionlist'}}) {
1862        if ($output_selection != OUTPUT_INCLUDE) {
1863            print "**$section**\n\n";
1864        }
1865        print_lineno($section_start_lines{$section});
1866        output_highlight_rst($args{'sections'}{$section});
1867        print "\n";
1868    }
1869}
1870
1871sub output_highlight_rst {
1872    my $contents = join "\n",@_;
1873    my $line;
1874
1875    # undo the evil effects of xml_escape() earlier
1876    $contents = xml_unescape($contents);
1877
1878    eval $dohighlight;
1879    die $@ if $@;
1880
1881    foreach $line (split "\n", $contents) {
1882        print $lineprefix . $line . "\n";
1883    }
1884}
1885
1886sub output_function_rst(%) {
1887    my %args = %{$_[0]};
1888    my ($parameter, $section);
1889    my $oldprefix = $lineprefix;
1890    my $start = "";
1891
1892    if ($args{'typedef'}) {
1893        print ".. c:type:: ". $args{'function'} . "\n\n";
1894        print_lineno($declaration_start_line);
1895        print "   **Typedef**: ";
1896        $lineprefix = "";
1897        output_highlight_rst($args{'purpose'});
1898        $start = "\n\n**Syntax**\n\n  ``";
1899    } else {
1900        print ".. c:function:: ";
1901    }
1902    if ($args{'functiontype'} ne "") {
1903        $start .= $args{'functiontype'} . " " . $args{'function'} . " (";
1904    } else {
1905        $start .= $args{'function'} . " (";
1906    }
1907    print $start;
1908
1909    my $count = 0;
1910    foreach my $parameter (@{$args{'parameterlist'}}) {
1911        if ($count ne 0) {
1912            print ", ";
1913        }
1914        $count++;
1915        $type = $args{'parametertypes'}{$parameter};
1916
1917        if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
1918            # pointer-to-function
1919            print $1 . $parameter . ") (" . $2;
1920        } else {
1921            print $type . " " . $parameter;
1922        }
1923    }
1924    if ($args{'typedef'}) {
1925        print ");``\n\n";
1926    } else {
1927        print ")\n\n";
1928        print_lineno($declaration_start_line);
1929        $lineprefix = "   ";
1930        output_highlight_rst($args{'purpose'});
1931        print "\n";
1932    }
1933
1934    print "**Parameters**\n\n";
1935    $lineprefix = "  ";
1936    foreach $parameter (@{$args{'parameterlist'}}) {
1937        my $parameter_name = $parameter;
1938        $parameter_name =~ s/\[.*//;
1939        $type = $args{'parametertypes'}{$parameter};
1940
1941        if ($type ne "") {
1942            print "``$type $parameter``\n";
1943        } else {
1944            print "``$parameter``\n";
1945        }
1946
1947        print_lineno($parameterdesc_start_lines{$parameter_name});
1948
1949        if (defined($args{'parameterdescs'}{$parameter_name}) &&
1950            $args{'parameterdescs'}{$parameter_name} ne $undescribed) {
1951            output_highlight_rst($args{'parameterdescs'}{$parameter_name});
1952        } else {
1953            print "  *undescribed*\n";
1954        }
1955        print "\n";
1956    }
1957
1958    $lineprefix = $oldprefix;
1959    output_section_rst(@_);
1960}
1961
1962sub output_section_rst(%) {
1963    my %args = %{$_[0]};
1964    my $section;
1965    my $oldprefix = $lineprefix;
1966    $lineprefix = "";
1967
1968    foreach $section (@{$args{'sectionlist'}}) {
1969        print "**$section**\n\n";
1970        print_lineno($section_start_lines{$section});
1971        output_highlight_rst($args{'sections'}{$section});
1972        print "\n";
1973    }
1974    print "\n";
1975    $lineprefix = $oldprefix;
1976}
1977
1978sub output_enum_rst(%) {
1979    my %args = %{$_[0]};
1980    my ($parameter);
1981    my $oldprefix = $lineprefix;
1982    my $count;
1983    my $name = "enum " . $args{'enum'};
1984
1985    print "\n\n.. c:type:: " . $name . "\n\n";
1986    print_lineno($declaration_start_line);
1987    $lineprefix = "   ";
1988    output_highlight_rst($args{'purpose'});
1989    print "\n";
1990
1991    print "**Constants**\n\n";
1992    $lineprefix = "  ";
1993    foreach $parameter (@{$args{'parameterlist'}}) {
1994        print "``$parameter``\n";
1995        if ($args{'parameterdescs'}{$parameter} ne $undescribed) {
1996            output_highlight_rst($args{'parameterdescs'}{$parameter});
1997        } else {
1998            print "  *undescribed*\n";
1999        }
2000        print "\n";
2001    }
2002
2003    $lineprefix = $oldprefix;
2004    output_section_rst(@_);
2005}
2006
2007sub output_typedef_rst(%) {
2008    my %args = %{$_[0]};
2009    my ($parameter);
2010    my $oldprefix = $lineprefix;
2011    my $name = "typedef " . $args{'typedef'};
2012
2013    print "\n\n.. c:type:: " . $name . "\n\n";
2014    print_lineno($declaration_start_line);
2015    $lineprefix = "   ";
2016    output_highlight_rst($args{'purpose'});
2017    print "\n";
2018
2019    $lineprefix = $oldprefix;
2020    output_section_rst(@_);
2021}
2022
2023sub output_struct_rst(%) {
2024    my %args = %{$_[0]};
2025    my ($parameter);
2026    my $oldprefix = $lineprefix;
2027    my $name = $args{'type'} . " " . $args{'struct'};
2028
2029    print "\n\n.. c:type:: " . $name . "\n\n";
2030    print_lineno($declaration_start_line);
2031    $lineprefix = "   ";
2032    output_highlight_rst($args{'purpose'});
2033    print "\n";
2034
2035    print "**Definition**\n\n";
2036    print "::\n\n";
2037    print "  " . $args{'type'} . " " . $args{'struct'} . " {\n";
2038    foreach $parameter (@{$args{'parameterlist'}}) {
2039        if ($parameter =~ /^#/) {
2040            print "  " . "$parameter\n";
2041            next;
2042        }
2043
2044        my $parameter_name = $parameter;
2045        $parameter_name =~ s/\[.*//;
2046
2047        ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
2048        $type = $args{'parametertypes'}{$parameter};
2049        if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
2050            # pointer-to-function
2051            print "    $1 $parameter) ($2);\n";
2052        } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
2053            # bitfield
2054            print "    $1 $parameter$2;\n";
2055        } else {
2056            print "    " . $type . " " . $parameter . ";\n";
2057        }
2058    }
2059    print "  };\n\n";
2060
2061    print "**Members**\n\n";
2062    $lineprefix = "  ";
2063    foreach $parameter (@{$args{'parameterlist'}}) {
2064        ($parameter =~ /^#/) && next;
2065
2066        my $parameter_name = $parameter;
2067        $parameter_name =~ s/\[.*//;
2068
2069        ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
2070        $type = $args{'parametertypes'}{$parameter};
2071        print_lineno($parameterdesc_start_lines{$parameter_name});
2072        print "``" . $parameter . "``\n";
2073        output_highlight_rst($args{'parameterdescs'}{$parameter_name});
2074        print "\n";
2075    }
2076    print "\n";
2077
2078    $lineprefix = $oldprefix;
2079    output_section_rst(@_);
2080}
2081
2082
2083## list mode output functions
2084
2085sub output_function_list(%) {
2086    my %args = %{$_[0]};
2087
2088    print $args{'function'} . "\n";
2089}
2090
2091# output enum in list
2092sub output_enum_list(%) {
2093    my %args = %{$_[0]};
2094    print $args{'enum'} . "\n";
2095}
2096
2097# output typedef in list
2098sub output_typedef_list(%) {
2099    my %args = %{$_[0]};
2100    print $args{'typedef'} . "\n";
2101}
2102
2103# output struct as list
2104sub output_struct_list(%) {
2105    my %args = %{$_[0]};
2106
2107    print $args{'struct'} . "\n";
2108}
2109
2110sub output_blockhead_list(%) {
2111    my %args = %{$_[0]};
2112    my ($parameter, $section);
2113
2114    foreach $section (@{$args{'sectionlist'}}) {
2115        print "DOC: $section\n";
2116    }
2117}
2118
2119##
2120# generic output function for all types (function, struct/union, typedef, enum);
2121# calls the generated, variable output_ function name based on
2122# functype and output_mode
2123sub output_declaration {
2124    no strict 'refs';
2125    my $name = shift;
2126    my $functype = shift;
2127    my $func = "output_${functype}_$output_mode";
2128    if (($output_selection == OUTPUT_ALL) ||
2129        (($output_selection == OUTPUT_INCLUDE ||
2130          $output_selection == OUTPUT_EXPORTED) &&
2131         defined($function_table{$name})) ||
2132        (($output_selection == OUTPUT_EXCLUDE ||
2133          $output_selection == OUTPUT_INTERNAL) &&
2134         !($functype eq "function" && defined($function_table{$name}))))
2135    {
2136        &$func(@_);
2137        $section_counter++;
2138    }
2139}
2140
2141##
2142# generic output function - calls the right one based on current output mode.
2143sub output_blockhead {
2144    no strict 'refs';
2145    my $func = "output_blockhead_" . $output_mode;
2146    &$func(@_);
2147    $section_counter++;
2148}
2149
2150##
2151# takes a declaration (struct, union, enum, typedef) and
2152# invokes the right handler. NOT called for functions.
2153sub dump_declaration($$) {
2154    no strict 'refs';
2155    my ($prototype, $file) = @_;
2156    my $func = "dump_" . $decl_type;
2157    &$func(@_);
2158}
2159
2160sub dump_union($$) {
2161    dump_struct(@_);
2162}
2163
2164sub dump_struct($$) {
2165    my $x = shift;
2166    my $file = shift;
2167    my $nested;
2168
2169    if ($x =~ /(struct|union)\s+(\w+)\s*{(.*)}/) {
2170        #my $decl_type = $1;
2171        $declaration_name = $2;
2172        my $members = $3;
2173
2174        # ignore embedded structs or unions
2175        $members =~ s/({.*})//g;
2176        $nested = $1;
2177
2178        # ignore members marked private:
2179        $members =~ s/\/\*\s*private:.*?\/\*\s*public:.*?\*\///gosi;
2180        $members =~ s/\/\*\s*private:.*//gosi;
2181        # strip comments:
2182        $members =~ s/\/\*.*?\*\///gos;
2183        $nested =~ s/\/\*.*?\*\///gos;
2184        # strip kmemcheck_bitfield_{begin,end}.*;
2185        $members =~ s/kmemcheck_bitfield_.*?;//gos;
2186        # strip attributes
2187        $members =~ s/__attribute__\s*\(\([a-z,_\*\s\(\)]*\)\)//i;
2188        $members =~ s/__aligned\s*\([^;]*\)//gos;
2189        $members =~ s/\s*CRYPTO_MINALIGN_ATTR//gos;
2190        # replace DECLARE_BITMAP
2191        $members =~ s/DECLARE_BITMAP\s*\(([^,)]+), ([^,)]+)\)/unsigned long $1\[BITS_TO_LONGS($2)\]/gos;
2192
2193        create_parameterlist($members, ';', $file);
2194        check_sections($file, $declaration_name, "struct", $sectcheck, $struct_actual, $nested);
2195
2196        output_declaration($declaration_name,
2197                           'struct',
2198                           {'struct' => $declaration_name,
2199                            'module' => $modulename,
2200                            'parameterlist' => \@parameterlist,
2201                            'parameterdescs' => \%parameterdescs,
2202                            'parametertypes' => \%parametertypes,
2203                            'sectionlist' => \@sectionlist,
2204                            'sections' => \%sections,
2205                            'purpose' => $declaration_purpose,
2206                            'type' => $decl_type
2207                           });
2208    }
2209    else {
2210        print STDERR "${file}:$.: error: Cannot parse struct or union!\n";
2211        ++$errors;
2212    }
2213}
2214
2215sub dump_enum($$) {
2216    my $x = shift;
2217    my $file = shift;
2218
2219    $x =~ s@/\*.*?\*/@@gos;     # strip comments.
2220    # strip #define macros inside enums
2221    $x =~ s@#\s*((define|ifdef)\s+|endif)[^;]*;@@gos;
2222
2223    if ($x =~ /enum\s+(\w+)\s*{(.*)}/) {
2224        $declaration_name = $1;
2225        my $members = $2;
2226
2227        foreach my $arg (split ',', $members) {
2228            $arg =~ s/^\s*(\w+).*/$1/;
2229            push @parameterlist, $arg;
2230            if (!$parameterdescs{$arg}) {
2231                $parameterdescs{$arg} = $undescribed;
2232                print STDERR "${file}:$.: warning: Enum value '$arg' ".
2233                    "not described in enum '$declaration_name'\n";
2234            }
2235
2236        }
2237
2238        output_declaration($declaration_name,
2239                           'enum',
2240                           {'enum' => $declaration_name,
2241                            'module' => $modulename,
2242                            'parameterlist' => \@parameterlist,
2243                            'parameterdescs' => \%parameterdescs,
2244                            'sectionlist' => \@sectionlist,
2245                            'sections' => \%sections,
2246                            'purpose' => $declaration_purpose
2247                           });
2248    }
2249    else {
2250        print STDERR "${file}:$.: error: Cannot parse enum!\n";
2251        ++$errors;
2252    }
2253}
2254
2255sub dump_typedef($$) {
2256    my $x = shift;
2257    my $file = shift;
2258
2259    $x =~ s@/\*.*?\*/@@gos;     # strip comments.
2260
2261    # Parse function prototypes
2262    if ($x =~ /typedef\s+(\w+)\s*\(\*\s*(\w\S+)\s*\)\s*\((.*)\);/ ||
2263        $x =~ /typedef\s+(\w+)\s*(\w\S+)\s*\s*\((.*)\);/) {
2264
2265        # Function typedefs
2266        $return_type = $1;
2267        $declaration_name = $2;
2268        my $args = $3;
2269
2270        create_parameterlist($args, ',', $file);
2271
2272        output_declaration($declaration_name,
2273                           'function',
2274                           {'function' => $declaration_name,
2275                            'typedef' => 1,
2276                            'module' => $modulename,
2277                            'functiontype' => $return_type,
2278                            'parameterlist' => \@parameterlist,
2279                            'parameterdescs' => \%parameterdescs,
2280                            'parametertypes' => \%parametertypes,
2281                            'sectionlist' => \@sectionlist,
2282                            'sections' => \%sections,
2283                            'purpose' => $declaration_purpose
2284                           });
2285        return;
2286    }
2287
2288    while (($x =~ /\(*.\)\s*;$/) || ($x =~ /\[*.\]\s*;$/)) {
2289        $x =~ s/\(*.\)\s*;$/;/;
2290        $x =~ s/\[*.\]\s*;$/;/;
2291    }
2292
2293    if ($x =~ /typedef.*\s+(\w+)\s*;/) {
2294        $declaration_name = $1;
2295
2296        output_declaration($declaration_name,
2297                           'typedef',
2298                           {'typedef' => $declaration_name,
2299                            'module' => $modulename,
2300                            'sectionlist' => \@sectionlist,
2301                            'sections' => \%sections,
2302                            'purpose' => $declaration_purpose
2303                           });
2304    }
2305    else {
2306        print STDERR "${file}:$.: error: Cannot parse typedef!\n";
2307        ++$errors;
2308    }
2309}
2310
2311sub save_struct_actual($) {
2312    my $actual = shift;
2313
2314    # strip all spaces from the actual param so that it looks like one string item
2315    $actual =~ s/\s*//g;
2316    $struct_actual = $struct_actual . $actual . " ";
2317}
2318
2319sub create_parameterlist($$$) {
2320    my $args = shift;
2321    my $splitter = shift;
2322    my $file = shift;
2323    my $type;
2324    my $param;
2325
2326    # temporarily replace commas inside function pointer definition
2327    while ($args =~ /(\([^\),]+),/) {
2328        $args =~ s/(\([^\),]+),/$1#/g;
2329    }
2330
2331    foreach my $arg (split($splitter, $args)) {
2332        # strip comments
2333        $arg =~ s/\/\*.*\*\///;
2334        # strip leading/trailing spaces
2335        $arg =~ s/^\s*//;
2336        $arg =~ s/\s*$//;
2337        $arg =~ s/\s+/ /;
2338
2339        if ($arg =~ /^#/) {
2340            # Treat preprocessor directive as a typeless variable just to fill
2341            # corresponding data structures "correctly". Catch it later in
2342            # output_* subs.
2343            push_parameter($arg, "", $file);
2344        } elsif ($arg =~ m/\(.+\)\s*\(/) {
2345            # pointer-to-function
2346            $arg =~ tr/#/,/;
2347            $arg =~ m/[^\(]+\(\*?\s*(\w*)\s*\)/;
2348            $param = $1;
2349            $type = $arg;
2350            $type =~ s/([^\(]+\(\*?)\s*$param/$1/;
2351            save_struct_actual($param);
2352            push_parameter($param, $type, $file);
2353        } elsif ($arg) {
2354            $arg =~ s/\s*:\s*/:/g;
2355            $arg =~ s/\s*\[/\[/g;
2356
2357            my @args = split('\s*,\s*', $arg);
2358            if ($args[0] =~ m/\*/) {
2359                $args[0] =~ s/(\*+)\s*/ $1/;
2360            }
2361
2362            my @first_arg;
2363            if ($args[0] =~ /^(.*\s+)(.*?\[.*\].*)$/) {
2364                    shift @args;
2365                    push(@first_arg, split('\s+', $1));
2366                    push(@first_arg, $2);
2367            } else {
2368                    @first_arg = split('\s+', shift @args);
2369            }
2370
2371            unshift(@args, pop @first_arg);
2372            $type = join " ", @first_arg;
2373
2374            foreach $param (@args) {
2375                if ($param =~ m/^(\*+)\s*(.*)/) {
2376                    save_struct_actual($2);
2377                    push_parameter($2, "$type $1", $file);
2378                }
2379                elsif ($param =~ m/(.*?):(\d+)/) {
2380                    if ($type ne "") { # skip unnamed bit-fields
2381                        save_struct_actual($1);
2382                        push_parameter($1, "$type:$2", $file)
2383                    }
2384                }
2385                else {
2386                    save_struct_actual($param);
2387                    push_parameter($param, $type, $file);
2388                }
2389            }
2390        }
2391    }
2392}
2393
2394sub push_parameter($$$) {
2395        my $param = shift;
2396        my $type = shift;
2397        my $file = shift;
2398
2399        if (($anon_struct_union == 1) && ($type eq "") &&
2400            ($param eq "}")) {
2401                return;         # ignore the ending }; from anon. struct/union
2402        }
2403
2404        $anon_struct_union = 0;
2405        $param =~ s/[\[\)].*//;
2406
2407        if ($type eq "" && $param =~ /\.\.\.$/)
2408        {
2409            if (!$param =~ /\w\.\.\.$/) {
2410              # handles unnamed variable parameters
2411              $param = "...";
2412            }
2413            if (!defined $parameterdescs{$param} || $parameterdescs{$param} eq "") {
2414                $parameterdescs{$param} = "variable arguments";
2415            }
2416        }
2417        elsif ($type eq "" && ($param eq "" or $param eq "void"))
2418        {
2419            $param="void";
2420            $parameterdescs{void} = "no arguments";
2421        }
2422        elsif ($type eq "" && ($param eq "struct" or $param eq "union"))
2423        # handle unnamed (anonymous) union or struct:
2424        {
2425                $type = $param;
2426                $param = "{unnamed_" . $param . "}";
2427                $parameterdescs{$param} = "anonymous\n";
2428                $anon_struct_union = 1;
2429        }
2430
2431        # warn if parameter has no description
2432        # (but ignore ones starting with # as these are not parameters
2433        # but inline preprocessor statements);
2434        # also ignore unnamed structs/unions;
2435        if (!$anon_struct_union) {
2436        if (!defined $parameterdescs{$param} && $param !~ /^#/) {
2437
2438            $parameterdescs{$param} = $undescribed;
2439
2440            if (($type eq 'function') || ($type eq 'enum')) {
2441                print STDERR "${file}:$.: warning: Function parameter ".
2442                    "or member '$param' not " .
2443                    "described in '$declaration_name'\n";
2444            }
2445            print STDERR "${file}:$.: warning:" .
2446                         " No description found for parameter '$param'\n";
2447            ++$warnings;
2448        }
2449        }
2450
2451        $param = xml_escape($param);
2452
2453        # strip spaces from $param so that it is one continuous string
2454        # on @parameterlist;
2455        # this fixes a problem where check_sections() cannot find
2456        # a parameter like "addr[6 + 2]" because it actually appears
2457        # as "addr[6", "+", "2]" on the parameter list;
2458        # but it's better to maintain the param string unchanged for output,
2459        # so just weaken the string compare in check_sections() to ignore
2460        # "[blah" in a parameter string;
2461        ###$param =~ s/\s*//g;
2462        push @parameterlist, $param;
2463        $type =~ s/\s\s+/ /g;
2464        $parametertypes{$param} = $type;
2465}
2466
2467sub check_sections($$$$$$) {
2468        my ($file, $decl_name, $decl_type, $sectcheck, $prmscheck, $nested) = @_;
2469        my @sects = split ' ', $sectcheck;
2470        my @prms = split ' ', $prmscheck;
2471        my $err;
2472        my ($px, $sx);
2473        my $prm_clean;          # strip trailing "[array size]" and/or beginning "*"
2474
2475        foreach $sx (0 .. $#sects) {
2476                $err = 1;
2477                foreach $px (0 .. $#prms) {
2478                        $prm_clean = $prms[$px];
2479                        $prm_clean =~ s/\[.*\]//;
2480                        $prm_clean =~ s/__attribute__\s*\(\([a-z,_\*\s\(\)]*\)\)//i;
2481                        # ignore array size in a parameter string;
2482                        # however, the original param string may contain
2483                        # spaces, e.g.:  addr[6 + 2]
2484                        # and this appears in @prms as "addr[6" since the
2485                        # parameter list is split at spaces;
2486                        # hence just ignore "[..." for the sections check;
2487                        $prm_clean =~ s/\[.*//;
2488
2489                        ##$prm_clean =~ s/^\**//;
2490                        if ($prm_clean eq $sects[$sx]) {
2491                                $err = 0;
2492                                last;
2493                        }
2494                }
2495                if ($err) {
2496                        if ($decl_type eq "function") {
2497                                print STDERR "${file}:$.: warning: " .
2498                                        "Excess function parameter " .
2499                                        "'$sects[$sx]' " .
2500                                        "description in '$decl_name'\n";
2501                                ++$warnings;
2502                        } else {
2503                                if ($nested !~ m/\Q$sects[$sx]\E/) {
2504                                    print STDERR "${file}:$.: warning: " .
2505                                        "Excess struct/union/enum/typedef member " .
2506                                        "'$sects[$sx]' " .
2507                                        "description in '$decl_name'\n";
2508                                    ++$warnings;
2509                                }
2510                        }
2511                }
2512        }
2513}
2514
2515##
2516# Checks the section describing the return value of a function.
2517sub check_return_section {
2518        my $file = shift;
2519        my $declaration_name = shift;
2520        my $return_type = shift;
2521
2522        # Ignore an empty return type (It's a macro)
2523        # Ignore functions with a "void" return type. (But don't ignore "void *")
2524        if (($return_type eq "") || ($return_type =~ /void\s*\w*\s*$/)) {
2525                return;
2526        }
2527
2528        if (!defined($sections{$section_return}) ||
2529            $sections{$section_return} eq "") {
2530                print STDERR "${file}:$.: warning: " .
2531                        "No description found for return value of " .
2532                        "'$declaration_name'\n";
2533                ++$warnings;
2534        }
2535}
2536
2537##
2538# takes a function prototype and the name of the current file being
2539# processed and spits out all the details stored in the global
2540# arrays/hashes.
2541sub dump_function($$) {
2542    my $prototype = shift;
2543    my $file = shift;
2544    my $noret = 0;
2545
2546    $prototype =~ s/^static +//;
2547    $prototype =~ s/^extern +//;
2548    $prototype =~ s/^asmlinkage +//;
2549    $prototype =~ s/^inline +//;
2550    $prototype =~ s/^__inline__ +//;
2551    $prototype =~ s/^__inline +//;
2552    $prototype =~ s/^__always_inline +//;
2553    $prototype =~ s/^noinline +//;
2554    $prototype =~ s/__init +//;
2555    $prototype =~ s/__init_or_module +//;
2556    $prototype =~ s/__meminit +//;
2557    $prototype =~ s/__must_check +//;
2558    $prototype =~ s/__weak +//;
2559    my $define = $prototype =~ s/^#\s*define\s+//; #ak added
2560    $prototype =~ s/__attribute__\s*\(\(
2561            (?:
2562                 [\w\s]++          # attribute name
2563                 (?:\([^)]*+\))?   # attribute arguments
2564                 \s*+,?            # optional comma at the end
2565            )+
2566          \)\)\s+//x;
2567
2568    # Yes, this truly is vile.  We are looking for:
2569    # 1. Return type (may be nothing if we're looking at a macro)
2570    # 2. Function name
2571    # 3. Function parameters.
2572    #
2573    # All the while we have to watch out for function pointer parameters
2574    # (which IIRC is what the two sections are for), C types (these
2575    # regexps don't even start to express all the possibilities), and
2576    # so on.
2577    #
2578    # If you mess with these regexps, it's a good idea to check that
2579    # the following functions' documentation still comes out right:
2580    # - parport_register_device (function pointer parameters)
2581    # - atomic_set (macro)
2582    # - pci_match_device, __copy_to_user (long return type)
2583
2584    if ($define && $prototype =~ m/^()([a-zA-Z0-9_~:]+)\s+/) {
2585        # This is an object-like macro, it has no return type and no parameter
2586        # list.
2587        # Function-like macros are not allowed to have spaces between
2588        # declaration_name and opening parenthesis (notice the \s+).
2589        $return_type = $1;
2590        $declaration_name = $2;
2591        $noret = 1;
2592    } elsif ($prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
2593        $prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
2594        $prototype =~ m/^(\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
2595        $prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
2596        $prototype =~ m/^(\w+\s+\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
2597        $prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
2598        $prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ ||
2599        $prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
2600        $prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
2601        $prototype =~ m/^(\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
2602        $prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
2603        $prototype =~ m/^(\w+\s+\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
2604        $prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
2605        $prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
2606        $prototype =~ m/^(\w+\s+\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
2607        $prototype =~ m/^(\w+\s+\w+\s+\w+\s+\w+\s*\*+)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ ||
2608        $prototype =~ m/^(\w+\s+\w+\s*\*+\s*\w+\s*\*+\s*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/)  {
2609        $return_type = $1;
2610        $declaration_name = $2;
2611        my $args = $3;
2612
2613        create_parameterlist($args, ',', $file);
2614    } else {
2615        print STDERR "${file}:$.: warning: cannot understand function prototype: '$prototype'\n";
2616        return;
2617    }
2618
2619        my $prms = join " ", @parameterlist;
2620        check_sections($file, $declaration_name, "function", $sectcheck, $prms, "");
2621
2622        # This check emits a lot of warnings at the moment, because many
2623        # functions don't have a 'Return' doc section. So until the number
2624        # of warnings goes sufficiently down, the check is only performed in
2625        # verbose mode.
2626        # TODO: always perform the check.
2627        if ($verbose && !$noret) {
2628                check_return_section($file, $declaration_name, $return_type);
2629        }
2630
2631    output_declaration($declaration_name,
2632                       'function',
2633                       {'function' => $declaration_name,
2634                        'module' => $modulename,
2635                        'functiontype' => $return_type,
2636                        'parameterlist' => \@parameterlist,
2637                        'parameterdescs' => \%parameterdescs,
2638                        'parametertypes' => \%parametertypes,
2639                        'sectionlist' => \@sectionlist,
2640                        'sections' => \%sections,
2641                        'purpose' => $declaration_purpose
2642                       });
2643}
2644
2645sub reset_state {
2646    $function = "";
2647    %parameterdescs = ();
2648    %parametertypes = ();
2649    @parameterlist = ();
2650    %sections = ();
2651    @sectionlist = ();
2652    $sectcheck = "";
2653    $struct_actual = "";
2654    $prototype = "";
2655
2656    $state = STATE_NORMAL;
2657    $inline_doc_state = STATE_INLINE_NA;
2658}
2659
2660sub tracepoint_munge($) {
2661        my $file = shift;
2662        my $tracepointname = 0;
2663        my $tracepointargs = 0;
2664
2665        if ($prototype =~ m/TRACE_EVENT\((.*?),/) {
2666                $tracepointname = $1;
2667        }
2668        if ($prototype =~ m/DEFINE_SINGLE_EVENT\((.*?),/) {
2669                $tracepointname = $1;
2670        }
2671        if ($prototype =~ m/DEFINE_EVENT\((.*?),(.*?),/) {
2672                $tracepointname = $2;
2673        }
2674        $tracepointname =~ s/^\s+//; #strip leading whitespace
2675        if ($prototype =~ m/TP_PROTO\((.*?)\)/) {
2676                $tracepointargs = $1;
2677        }
2678        if (($tracepointname eq 0) || ($tracepointargs eq 0)) {
2679                print STDERR "${file}:$.: warning: Unrecognized tracepoint format: \n".
2680                             "$prototype\n";
2681        } else {
2682                $prototype = "static inline void trace_$tracepointname($tracepointargs)";
2683        }
2684}
2685
2686sub syscall_munge() {
2687        my $void = 0;
2688
2689        $prototype =~ s@[\r\n\t]+@ @gos; # strip newlines/CR's/tabs
2690##      if ($prototype =~ m/SYSCALL_DEFINE0\s*\(\s*(a-zA-Z0-9_)*\s*\)/) {
2691        if ($prototype =~ m/SYSCALL_DEFINE0/) {
2692                $void = 1;
2693##              $prototype = "long sys_$1(void)";
2694        }
2695
2696        $prototype =~ s/SYSCALL_DEFINE.*\(/long sys_/; # fix return type & func name
2697        if ($prototype =~ m/long (sys_.*?),/) {
2698                $prototype =~ s/,/\(/;
2699        } elsif ($void) {
2700                $prototype =~ s/\)/\(void\)/;
2701        }
2702
2703        # now delete all of the odd-number commas in $prototype
2704        # so that arg types & arg names don't have a comma between them
2705        my $count = 0;
2706        my $len = length($prototype);
2707        if ($void) {
2708                $len = 0;       # skip the for-loop
2709        }
2710        for (my $ix = 0; $ix < $len; $ix++) {
2711                if (substr($prototype, $ix, 1) eq ',') {
2712                        $count++;
2713                        if ($count % 2 == 1) {
2714                                substr($prototype, $ix, 1) = ' ';
2715                        }
2716                }
2717        }
2718}
2719
2720sub process_proto_function($$) {
2721    my $x = shift;
2722    my $file = shift;
2723
2724    $x =~ s@\/\/.*$@@gos; # strip C99-style comments to end of line
2725
2726    if ($x =~ m#\s*/\*\s+MACDOC\s*#io || ($x =~ /^#/ && $x !~ /^#\s*define/)) {
2727        # do nothing
2728    }
2729    elsif ($x =~ /([^\{]*)/) {
2730        $prototype .= $1;
2731    }
2732
2733    if (($x =~ /\{/) || ($x =~ /\#\s*define/) || ($x =~ /;/)) {
2734        $prototype =~ s@/\*.*?\*/@@gos; # strip comments.
2735        $prototype =~ s@[\r\n]+@ @gos; # strip newlines/cr's.
2736        $prototype =~ s@^\s+@@gos; # strip leading spaces
2737        if ($prototype =~ /SYSCALL_DEFINE/) {
2738                syscall_munge();
2739        }
2740        if ($prototype =~ /TRACE_EVENT/ || $prototype =~ /DEFINE_EVENT/ ||
2741            $prototype =~ /DEFINE_SINGLE_EVENT/)
2742        {
2743                tracepoint_munge($file);
2744        }
2745        dump_function($prototype, $file);
2746        reset_state();
2747    }
2748}
2749
2750sub process_proto_type($$) {
2751    my $x = shift;
2752    my $file = shift;
2753
2754    $x =~ s@[\r\n]+@ @gos; # strip newlines/cr's.
2755    $x =~ s@^\s+@@gos; # strip leading spaces
2756    $x =~ s@\s+$@@gos; # strip trailing spaces
2757    $x =~ s@\/\/.*$@@gos; # strip C99-style comments to end of line
2758
2759    if ($x =~ /^#/) {
2760        # To distinguish preprocessor directive from regular declaration later.
2761        $x .= ";";
2762    }
2763
2764    while (1) {
2765        if ( $x =~ /([^{};]*)([{};])(.*)/ ) {
2766            $prototype .= $1 . $2;
2767            ($2 eq '{') && $brcount++;
2768            ($2 eq '}') && $brcount--;
2769            if (($2 eq ';') && ($brcount == 0)) {
2770                dump_declaration($prototype, $file);
2771                reset_state();
2772                last;
2773            }
2774            $x = $3;
2775        } else {
2776            $prototype .= $x;
2777            last;
2778        }
2779    }
2780}
2781
2782# xml_escape: replace <, >, and & in the text stream;
2783#
2784# however, formatting controls that are generated internally/locally in the
2785# kernel-doc script are not escaped here; instead, they begin life like
2786# $blankline_html (4 of '\' followed by a mnemonic + ':'), then these strings
2787# are converted to their mnemonic-expected output, without the 4 * '\' & ':',
2788# just before actual output; (this is done by local_unescape())
2789sub xml_escape($) {
2790        my $text = shift;
2791        if (($output_mode eq "text") || ($output_mode eq "man")) {
2792                return $text;
2793        }
2794        $text =~ s/\&/\\\\\\amp;/g;
2795        $text =~ s/\</\\\\\\lt;/g;
2796        $text =~ s/\>/\\\\\\gt;/g;
2797        return $text;
2798}
2799
2800# xml_unescape: reverse the effects of xml_escape
2801sub xml_unescape($) {
2802        my $text = shift;
2803        if (($output_mode eq "text") || ($output_mode eq "man")) {
2804                return $text;
2805        }
2806        $text =~ s/\\\\\\amp;/\&/g;
2807        $text =~ s/\\\\\\lt;/</g;
2808        $text =~ s/\\\\\\gt;/>/g;
2809        return $text;
2810}
2811
2812# convert local escape strings to html
2813# local escape strings look like:  '\\\\menmonic:' (that's 4 backslashes)
2814sub local_unescape($) {
2815        my $text = shift;
2816        if (($output_mode eq "text") || ($output_mode eq "man")) {
2817                return $text;
2818        }
2819        $text =~ s/\\\\\\\\lt:/</g;
2820        $text =~ s/\\\\\\\\gt:/>/g;
2821        return $text;
2822}
2823
2824sub map_filename($) {
2825    my $file;
2826    my ($orig_file) = @_;
2827
2828    if (defined($ENV{'SRCTREE'})) {
2829        $file = "$ENV{'SRCTREE'}" . "/" . $orig_file;
2830    } else {
2831        $file = $orig_file;
2832    }
2833
2834    if (defined($source_map{$file})) {
2835        $file = $source_map{$file};
2836    }
2837
2838    return $file;
2839}
2840
2841sub process_export_file($) {
2842    my ($orig_file) = @_;
2843    my $file = map_filename($orig_file);
2844
2845    if (!open(IN,"<$file")) {
2846        print STDERR "Error: Cannot open file $file\n";
2847        ++$errors;
2848        return;
2849    }
2850
2851    while (<IN>) {
2852        if (/$export_symbol/) {
2853            $function_table{$2} = 1;
2854        }
2855    }
2856
2857    close(IN);
2858}
2859
2860sub process_file($) {
2861    my $file;
2862    my $identifier;
2863    my $func;
2864    my $descr;
2865    my $in_purpose = 0;
2866    my $initial_section_counter = $section_counter;
2867    my ($orig_file) = @_;
2868    my $leading_space;
2869
2870    $file = map_filename($orig_file);
2871
2872    if (!open(IN,"<$file")) {
2873        print STDERR "Error: Cannot open file $file\n";
2874        ++$errors;
2875        return;
2876    }
2877
2878    $. = 1;
2879
2880    $section_counter = 0;
2881    while (<IN>) {
2882        while (s/\\\s*$//) {
2883            $_ .= <IN>;
2884        }
2885        if ($state == STATE_NORMAL) {
2886            if (/$doc_start/o) {
2887                $state = STATE_NAME;    # next line is always the function name
2888                $in_doc_sect = 0;
2889                $declaration_start_line = $. + 1;
2890            }
2891        } elsif ($state == STATE_NAME) {# this line is the function name (always)
2892            if (/$doc_block/o) {
2893                $state = STATE_DOCBLOCK;
2894                $contents = "";
2895                $new_start_line = $. + 1;
2896
2897                if ( $1 eq "" ) {
2898                        $section = $section_intro;
2899                } else {
2900                        $section = $1;
2901                }
2902            }
2903            elsif (/$doc_decl/o) {
2904                $identifier = $1;
2905                if (/\s*([\w\s]+?)\s*-/) {
2906                    $identifier = $1;
2907                }
2908
2909                $state = STATE_FIELD;
2910                # if there's no @param blocks need to set up default section
2911                # here
2912                $contents = "";
2913                $section = $section_default;
2914                $new_start_line = $. + 1;
2915                if (/-(.*)/) {
2916                    # strip leading/trailing/multiple spaces
2917                    $descr= $1;
2918                    $descr =~ s/^\s*//;
2919                    $descr =~ s/\s*$//;
2920                    $descr =~ s/\s+/ /g;
2921                    $declaration_purpose = xml_escape($descr);
2922                    $in_purpose = 1;
2923                } else {
2924                    $declaration_purpose = "";
2925                }
2926
2927                if (($declaration_purpose eq "") && $verbose) {
2928                        print STDERR "${file}:$.: warning: missing initial short description on line:\n";
2929                        print STDERR $_;
2930                        ++$warnings;
2931                }
2932
2933                if ($identifier =~ m/^struct/) {
2934                    $decl_type = 'struct';
2935                } elsif ($identifier =~ m/^union/) {
2936                    $decl_type = 'union';
2937                } elsif ($identifier =~ m/^enum/) {
2938                    $decl_type = 'enum';
2939                } elsif ($identifier =~ m/^typedef/) {
2940                    $decl_type = 'typedef';
2941                } else {
2942                    $decl_type = 'function';
2943                }
2944
2945                if ($verbose) {
2946                    print STDERR "${file}:$.: info: Scanning doc for $identifier\n";
2947                }
2948            } else {
2949                print STDERR "${file}:$.: warning: Cannot understand $_ on line $.",
2950                " - I thought it was a doc line\n";
2951                ++$warnings;
2952                $state = STATE_NORMAL;
2953            }
2954        } elsif ($state == STATE_FIELD) {       # look for head: lines, and include content
2955            if (/$doc_sect/i) { # case insensitive for supported section names
2956                $newsection = $1;
2957                $newcontents = $2;
2958
2959                # map the supported section names to the canonical names
2960                if ($newsection =~ m/^description$/i) {
2961                    $newsection = $section_default;
2962                } elsif ($newsection =~ m/^context$/i) {
2963                    $newsection = $section_context;
2964                } elsif ($newsection =~ m/^returns?$/i) {
2965                    $newsection = $section_return;
2966                } elsif ($newsection =~ m/^\@return$/) {
2967                    # special: @return is a section, not a param description
2968                    $newsection = $section_return;
2969                }
2970
2971                if (($contents ne "") && ($contents ne "\n")) {
2972                    if (!$in_doc_sect && $verbose) {
2973                        print STDERR "${file}:$.: warning: contents before sections\n";
2974                        ++$warnings;
2975                    }
2976                    dump_section($file, $section, xml_escape($contents));
2977                    $section = $section_default;
2978                }
2979
2980                $in_doc_sect = 1;
2981                $in_purpose = 0;
2982                $contents = $newcontents;
2983                $new_start_line = $.;
2984                while ((substr($contents, 0, 1) eq " ") ||
2985                       substr($contents, 0, 1) eq "\t") {
2986                    $contents = substr($contents, 1);
2987                }
2988                if ($contents ne "") {
2989                    $contents .= "\n";
2990                }
2991                $section = $newsection;
2992                $leading_space = undef;
2993            } elsif (/$doc_end/) {
2994                if (($contents ne "") && ($contents ne "\n")) {
2995                    dump_section($file, $section, xml_escape($contents));
2996                    $section = $section_default;
2997                    $contents = "";
2998                }
2999                # look for doc_com + <text> + doc_end:
3000                if ($_ =~ m'\s*\*\s*[a-zA-Z_0-9:\.]+\*/') {
3001                    print STDERR "${file}:$.: warning: suspicious ending line: $_";
3002                    ++$warnings;
3003                }
3004
3005                $prototype = "";
3006                $state = STATE_PROTO;
3007                $brcount = 0;
3008#               print STDERR "end of doc comment, looking for prototype\n";
3009            } elsif (/$doc_content/) {
3010                # miguel-style comment kludge, look for blank lines after
3011                # @parameter line to signify start of description
3012                if ($1 eq "") {
3013                    if ($section =~ m/^@/ || $section eq $section_context) {
3014                        dump_section($file, $section, xml_escape($contents));
3015                        $section = $section_default;
3016                        $contents = "";
3017                        $new_start_line = $.;
3018                    } else {
3019                        $contents .= "\n";
3020                    }
3021                    $in_purpose = 0;
3022                } elsif ($in_purpose == 1) {
3023                    # Continued declaration purpose
3024                    chomp($declaration_purpose);
3025                    $declaration_purpose .= " " . xml_escape($1);
3026                    $declaration_purpose =~ s/\s+/ /g;
3027                } else {
3028                    my $cont = $1;
3029                    if ($section =~ m/^@/ || $section eq $section_context) {
3030                        if (!defined $leading_space) {
3031                            if ($cont =~ m/^(\s+)/) {
3032                                $leading_space = $1;
3033                            } else {
3034                                $leading_space = "";
3035                            }
3036                        }
3037
3038                        $cont =~ s/^$leading_space//;
3039                    }
3040                    $contents .= $cont . "\n";
3041                }
3042            } else {
3043                # i dont know - bad line?  ignore.
3044                print STDERR "${file}:$.: warning: bad line: $_";
3045                ++$warnings;
3046            }
3047        } elsif ($state == STATE_INLINE) { # scanning for inline parameters
3048            # First line (state 1) needs to be a @parameter
3049            if ($inline_doc_state == STATE_INLINE_NAME && /$doc_inline_sect/o) {
3050                $section = $1;
3051                $contents = $2;
3052                $new_start_line = $.;
3053                if ($contents ne "") {
3054                    while ((substr($contents, 0, 1) eq " ") ||
3055                           substr($contents, 0, 1) eq "\t") {
3056                        $contents = substr($contents, 1);
3057                    }
3058                    $contents .= "\n";
3059                }
3060                $inline_doc_state = STATE_INLINE_TEXT;
3061            # Documentation block end */
3062            } elsif (/$doc_inline_end/) {
3063                if (($contents ne "") && ($contents ne "\n")) {
3064                    dump_section($file, $section, xml_escape($contents));
3065                    $section = $section_default;
3066                    $contents = "";
3067                }
3068                $state = STATE_PROTO;
3069                $inline_doc_state = STATE_INLINE_NA;
3070            # Regular text
3071            } elsif (/$doc_content/) {
3072                if ($inline_doc_state == STATE_INLINE_TEXT) {
3073                    $contents .= $1 . "\n";
3074                    # nuke leading blank lines
3075                    if ($contents =~ /^\s*$/) {
3076                        $contents = "";
3077                    }
3078                } elsif ($inline_doc_state == STATE_INLINE_NAME) {
3079                    $inline_doc_state = STATE_INLINE_ERROR;
3080                    print STDERR "${file}:$.: warning: ";
3081                    print STDERR "Incorrect use of kernel-doc format: $_";
3082                    ++$warnings;
3083                }
3084            }
3085        } elsif ($state == STATE_PROTO) {       # scanning for function '{' (end of prototype)
3086            if (/$doc_inline_oneline/) {
3087                $section = $1;
3088                $contents = $2;
3089                if ($contents ne "") {
3090                    $contents .= "\n";
3091                    dump_section($file, $section, xml_escape($contents));
3092                    $section = $section_default;
3093                    $contents = "";
3094                }
3095            } elsif (/$doc_inline_start/) {
3096                $state = STATE_INLINE;
3097                $inline_doc_state = STATE_INLINE_NAME;
3098            } elsif ($decl_type eq 'function') {
3099                process_proto_function($_, $file);
3100            } else {
3101                process_proto_type($_, $file);
3102            }
3103        } elsif ($state == STATE_DOCBLOCK) {
3104                if (/$doc_end/)
3105                {
3106                        dump_doc_section($file, $section, xml_escape($contents));
3107                        $section = $section_default;
3108                        $contents = "";
3109                        $function = "";
3110                        %parameterdescs = ();
3111                        %parametertypes = ();
3112                        @parameterlist = ();
3113                        %sections = ();
3114                        @sectionlist = ();
3115                        $prototype = "";
3116                        $state = STATE_NORMAL;
3117                }
3118                elsif (/$doc_content/)
3119                {
3120                        if ( $1 eq "" )
3121                        {
3122                                $contents .= $blankline;
3123                        }
3124                        else
3125                        {
3126                                $contents .= $1 . "\n";
3127                        }
3128                }
3129        }
3130    }
3131    if ($initial_section_counter == $section_counter) {
3132        print STDERR "${file}:1: warning: no structured comments found\n";
3133        if (($output_selection == OUTPUT_INCLUDE) && ($show_not_found == 1)) {
3134            print STDERR "    Was looking for '$_'.\n" for keys %function_table;
3135        }
3136        if ($output_mode eq "xml") {
3137            # The template wants at least one RefEntry here; make one.
3138            print "<refentry>\n";
3139            print " <refnamediv>\n";
3140            print "  <refname>\n";
3141            print "   ${orig_file}\n";
3142            print "  </refname>\n";
3143            print "  <refpurpose>\n";
3144            print "   Document generation inconsistency\n";
3145            print "  </refpurpose>\n";
3146            print " </refnamediv>\n";
3147            print " <refsect1>\n";
3148            print "  <title>\n";
3149            print "   Oops\n";
3150            print "  </title>\n";
3151            print "  <warning>\n";
3152            print "   <para>\n";
3153            print "    The template for this document tried to insert\n";
3154            print "    the structured comment from the file\n";
3155            print "    <filename>${orig_file}</filename> at this point,\n";
3156            print "    but none was found.\n";
3157            print "    This dummy section is inserted to allow\n";
3158            print "    generation to continue.\n";
3159            print "   </para>\n";
3160            print "  </warning>\n";
3161            print " </refsect1>\n";
3162            print "</refentry>\n";
3163        }
3164    }
3165}
3166
3167
3168$kernelversion = get_kernel_version();
3169
3170# generate a sequence of code that will splice in highlighting information
3171# using the s// operator.
3172for (my $k = 0; $k < @highlights; $k++) {
3173    my $pattern = $highlights[$k][0];
3174    my $result = $highlights[$k][1];
3175#   print STDERR "scanning pattern:$pattern, highlight:($result)\n";
3176    $dohighlight .=  "\$contents =~ s:$pattern:$result:gs;\n";
3177}
3178
3179# Read the file that maps relative names to absolute names for
3180# separate source and object directories and for shadow trees.
3181if (open(SOURCE_MAP, "<.tmp_filelist.txt")) {
3182        my ($relname, $absname);
3183        while(<SOURCE_MAP>) {
3184                chop();
3185                ($relname, $absname) = (split())[0..1];
3186                $relname =~ s:^/+::;
3187                $source_map{$relname} = $absname;
3188        }
3189        close(SOURCE_MAP);
3190}
3191
3192if ($output_selection == OUTPUT_EXPORTED ||
3193    $output_selection == OUTPUT_INTERNAL) {
3194
3195    push(@export_file_list, @ARGV);
3196
3197    foreach (@export_file_list) {
3198        chomp;
3199        process_export_file($_);
3200    }
3201}
3202
3203foreach (@ARGV) {
3204    chomp;
3205    process_file($_);
3206}
3207if ($verbose && $errors) {
3208  print STDERR "$errors errors\n";
3209}
3210if ($verbose && $warnings) {
3211  print STDERR "$warnings warnings\n";
3212}
3213
3214exit($errors);
3215