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