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