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