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 <title>$section</title>\n <para>\n"; 557 if ($section =~ m/EXAMPLE/i) { 558 print "<example><para>\n"; 559 } 560 output_highlight($args{'sections'}{$section}); 561 if ($section =~ m/EXAMPLE/i) { 562 print "</para></example>\n"; 563 } 564 print " </para>\n</refsect1>\n"; 565 } 566} 567 568# output function in XML DocBook 569sub output_function_xml(%) { 570 my %args = %{$_[0]}; 571 my ($parameter, $section); 572 my $count; 573 my $id; 574 575 $id = "API-".$args{'function'}; 576 $id =~ s/[^A-Za-z0-9]/-/g; 577 578 print "<refentry>\n"; 579 print "<refmeta>\n"; 580 print "<refentrytitle><phrase id=\"$id\">".$args{'function'}."</phrase></refentrytitle>\n"; 581 print "</refmeta>\n"; 582 print "<refnamediv>\n"; 583 print " <refname>".$args{'function'}."</refname>\n"; 584 print " <refpurpose>\n"; 585 print " "; 586 output_highlight ($args{'purpose'}); 587 print " </refpurpose>\n"; 588 print "</refnamediv>\n"; 589 590 print "<refsynopsisdiv>\n"; 591 print " <title>Synopsis</title>\n"; 592 print " <funcsynopsis><funcprototype>\n"; 593 print " <funcdef>".$args{'functiontype'}." "; 594 print "<function>".$args{'function'}." </function></funcdef>\n"; 595 596 $count = 0; 597 if ($#{$args{'parameterlist'}} >= 0) { 598 foreach $parameter (@{$args{'parameterlist'}}) { 599 $type = $args{'parametertypes'}{$parameter}; 600 if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { 601 # pointer-to-function 602 print " <paramdef>$1<parameter>$parameter</parameter>)\n"; 603 print " <funcparams>$2</funcparams></paramdef>\n"; 604 } else { 605 print " <paramdef>".$type; 606 print " <parameter>$parameter</parameter></paramdef>\n"; 607 } 608 } 609 } else { 610 print " <void/>\n"; 611 } 612 print " </funcprototype></funcsynopsis>\n"; 613 print "</refsynopsisdiv>\n"; 614 615 # print parameters 616 print "<refsect1>\n <title>Arguments</title>\n"; 617 if ($#{$args{'parameterlist'}} >= 0) { 618 print " <variablelist>\n"; 619 foreach $parameter (@{$args{'parameterlist'}}) { 620 my $parameter_name = $parameter; 621 $parameter_name =~ s/\[.*//; 622 623 print " <varlistentry>\n <term><parameter>$parameter</parameter></term>\n"; 624 print " <listitem>\n <para>\n"; 625 $lineprefix=" "; 626 output_highlight($args{'parameterdescs'}{$parameter_name}); 627 print " </para>\n </listitem>\n </varlistentry>\n"; 628 } 629 print " </variablelist>\n"; 630 } else { 631 print " <para>\n None\n </para>\n"; 632 } 633 print "</refsect1>\n"; 634 635 output_section_xml(@_); 636 print "</refentry>\n\n"; 637} 638 639# output struct in XML DocBook 640sub output_struct_xml(%) { 641 my %args = %{$_[0]}; 642 my ($parameter, $section); 643 my $id; 644 645 $id = "API-struct-".$args{'struct'}; 646 $id =~ s/[^A-Za-z0-9]/-/g; 647 648 print "<refentry>\n"; 649 print "<refmeta>\n"; 650 print "<refentrytitle><phrase id=\"$id\">".$args{'type'}." ".$args{'struct'}."</phrase></refentrytitle>\n"; 651 print "</refmeta>\n"; 652 print "<refnamediv>\n"; 653 print " <refname>".$args{'type'}." ".$args{'struct'}."</refname>\n"; 654 print " <refpurpose>\n"; 655 print " "; 656 output_highlight ($args{'purpose'}); 657 print " </refpurpose>\n"; 658 print "</refnamediv>\n"; 659 660 print "<refsynopsisdiv>\n"; 661 print " <title>Synopsis</title>\n"; 662 print " <programlisting>\n"; 663 print $args{'type'}." ".$args{'struct'}." {\n"; 664 foreach $parameter (@{$args{'parameterlist'}}) { 665 if ($parameter =~ /^#/) { 666 print "$parameter\n"; 667 next; 668 } 669 670 my $parameter_name = $parameter; 671 $parameter_name =~ s/\[.*//; 672 673 defined($args{'parameterdescs'}{$parameter_name}) || next; 674 ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; 675 $type = $args{'parametertypes'}{$parameter}; 676 if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { 677 # pointer-to-function 678 print " $1 $parameter) ($2);\n"; 679 } elsif ($type =~ m/^(.*?)\s*(:.*)/) { 680 print " $1 $parameter$2;\n"; 681 } else { 682 print " ".$type." ".$parameter.";\n"; 683 } 684 } 685 print "};"; 686 print " </programlisting>\n"; 687 print "</refsynopsisdiv>\n"; 688 689 print " <refsect1>\n"; 690 print " <title>Members</title>\n"; 691 692 print " <variablelist>\n"; 693 foreach $parameter (@{$args{'parameterlist'}}) { 694 ($parameter =~ /^#/) && next; 695 696 my $parameter_name = $parameter; 697 $parameter_name =~ s/\[.*//; 698 699 defined($args{'parameterdescs'}{$parameter_name}) || next; 700 ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; 701 print " <varlistentry>"; 702 print " <term>$parameter</term>\n"; 703 print " <listitem><para>\n"; 704 output_highlight($args{'parameterdescs'}{$parameter_name}); 705 print " </para></listitem>\n"; 706 print " </varlistentry>\n"; 707 } 708 print " </variablelist>\n"; 709 print " </refsect1>\n"; 710 711 output_section_xml(@_); 712 713 print "</refentry>\n\n"; 714} 715 716# output enum in XML DocBook 717sub output_enum_xml(%) { 718 my %args = %{$_[0]}; 719 my ($parameter, $section); 720 my $count; 721 my $id; 722 723 $id = "API-enum-".$args{'enum'}; 724 $id =~ s/[^A-Za-z0-9]/-/g; 725 726 print "<refentry>\n"; 727 print "<refmeta>\n"; 728 print "<refentrytitle><phrase id=\"$id\">enum ".$args{'enum'}."</phrase></refentrytitle>\n"; 729 print "</refmeta>\n"; 730 print "<refnamediv>\n"; 731 print " <refname>enum ".$args{'enum'}."</refname>\n"; 732 print " <refpurpose>\n"; 733 print " "; 734 output_highlight ($args{'purpose'}); 735 print " </refpurpose>\n"; 736 print "</refnamediv>\n"; 737 738 print "<refsynopsisdiv>\n"; 739 print " <title>Synopsis</title>\n"; 740 print " <programlisting>\n"; 741 print "enum ".$args{'enum'}." {\n"; 742 $count = 0; 743 foreach $parameter (@{$args{'parameterlist'}}) { 744 print " $parameter"; 745 if ($count != $#{$args{'parameterlist'}}) { 746 $count++; 747 print ","; 748 } 749 print "\n"; 750 } 751 print "};"; 752 print " </programlisting>\n"; 753 print "</refsynopsisdiv>\n"; 754 755 print "<refsect1>\n"; 756 print " <title>Constants</title>\n"; 757 print " <variablelist>\n"; 758 foreach $parameter (@{$args{'parameterlist'}}) { 759 my $parameter_name = $parameter; 760 $parameter_name =~ s/\[.*//; 761 762 print " <varlistentry>"; 763 print " <term>$parameter</term>\n"; 764 print " <listitem><para>\n"; 765 output_highlight($args{'parameterdescs'}{$parameter_name}); 766 print " </para></listitem>\n"; 767 print " </varlistentry>\n"; 768 } 769 print " </variablelist>\n"; 770 print "</refsect1>\n"; 771 772 output_section_xml(@_); 773 774 print "</refentry>\n\n"; 775} 776 777# output typedef in XML DocBook 778sub output_typedef_xml(%) { 779 my %args = %{$_[0]}; 780 my ($parameter, $section); 781 my $id; 782 783 $id = "API-typedef-".$args{'typedef'}; 784 $id =~ s/[^A-Za-z0-9]/-/g; 785 786 print "<refentry>\n"; 787 print "<refmeta>\n"; 788 print "<refentrytitle><phrase id=\"$id\">typedef ".$args{'typedef'}."</phrase></refentrytitle>\n"; 789 print "</refmeta>\n"; 790 print "<refnamediv>\n"; 791 print " <refname>typedef ".$args{'typedef'}."</refname>\n"; 792 print " <refpurpose>\n"; 793 print " "; 794 output_highlight ($args{'purpose'}); 795 print " </refpurpose>\n"; 796 print "</refnamediv>\n"; 797 798 print "<refsynopsisdiv>\n"; 799 print " <title>Synopsis</title>\n"; 800 print " <synopsis>typedef ".$args{'typedef'}.";</synopsis>\n"; 801 print "</refsynopsisdiv>\n"; 802 803 output_section_xml(@_); 804 805 print "</refentry>\n\n"; 806} 807 808# output in XML DocBook 809sub output_intro_xml(%) { 810 my %args = %{$_[0]}; 811 my ($parameter, $section); 812 my $count; 813 814 my $id = $args{'module'}; 815 $id =~ s/[^A-Za-z0-9]/-/g; 816 817 # print out each section 818 $lineprefix=" "; 819 foreach $section (@{$args{'sectionlist'}}) { 820 print "<refsect1>\n <title>$section</title>\n <para>\n"; 821 if ($section =~ m/EXAMPLE/i) { 822 print "<example><para>\n"; 823 } 824 output_highlight($args{'sections'}{$section}); 825 if ($section =~ m/EXAMPLE/i) { 826 print "</para></example>\n"; 827 } 828 print " </para>\n</refsect1>\n"; 829 } 830 831 print "\n\n"; 832} 833 834# output in XML DocBook 835sub output_function_gnome { 836 my %args = %{$_[0]}; 837 my ($parameter, $section); 838 my $count; 839 my $id; 840 841 $id = $args{'module'}."-".$args{'function'}; 842 $id =~ s/[^A-Za-z0-9]/-/g; 843 844 print "<sect2>\n"; 845 print " <title id=\"$id\">".$args{'function'}."</title>\n"; 846 847 print " <funcsynopsis>\n"; 848 print " <funcdef>".$args{'functiontype'}." "; 849 print "<function>".$args{'function'}." "; 850 print "</function></funcdef>\n"; 851 852 $count = 0; 853 if ($#{$args{'parameterlist'}} >= 0) { 854 foreach $parameter (@{$args{'parameterlist'}}) { 855 $type = $args{'parametertypes'}{$parameter}; 856 if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { 857 # pointer-to-function 858 print " <paramdef>$1 <parameter>$parameter</parameter>)\n"; 859 print " <funcparams>$2</funcparams></paramdef>\n"; 860 } else { 861 print " <paramdef>".$type; 862 print " <parameter>$parameter</parameter></paramdef>\n"; 863 } 864 } 865 } else { 866 print " <void>\n"; 867 } 868 print " </funcsynopsis>\n"; 869 if ($#{$args{'parameterlist'}} >= 0) { 870 print " <informaltable pgwide=\"1\" frame=\"none\" role=\"params\">\n"; 871 print "<tgroup cols=\"2\">\n"; 872 print "<colspec colwidth=\"2*\">\n"; 873 print "<colspec colwidth=\"8*\">\n"; 874 print "<tbody>\n"; 875 foreach $parameter (@{$args{'parameterlist'}}) { 876 my $parameter_name = $parameter; 877 $parameter_name =~ s/\[.*//; 878 879 print " <row><entry align=\"right\"><parameter>$parameter</parameter></entry>\n"; 880 print " <entry>\n"; 881 $lineprefix=" "; 882 output_highlight($args{'parameterdescs'}{$parameter_name}); 883 print " </entry></row>\n"; 884 } 885 print " </tbody></tgroup></informaltable>\n"; 886 } else { 887 print " <para>\n None\n </para>\n"; 888 } 889 890 # print out each section 891 $lineprefix=" "; 892 foreach $section (@{$args{'sectionlist'}}) { 893 print "<simplesect>\n <title>$section</title>\n"; 894 if ($section =~ m/EXAMPLE/i) { 895 print "<example><programlisting>\n"; 896 } else { 897 } 898 print "<para>\n"; 899 output_highlight($args{'sections'}{$section}); 900 print "</para>\n"; 901 if ($section =~ m/EXAMPLE/i) { 902 print "</programlisting></example>\n"; 903 } else { 904 } 905 print " </simplesect>\n"; 906 } 907 908 print "</sect2>\n\n"; 909} 910 911## 912# output function in man 913sub output_function_man(%) { 914 my %args = %{$_[0]}; 915 my ($parameter, $section); 916 my $count; 917 918 print ".TH \"$args{'function'}\" 9 \"$args{'function'}\" \"$man_date\" \"Kernel Hacker's Manual\" LINUX\n"; 919 920 print ".SH NAME\n"; 921 print $args{'function'}." \\- ".$args{'purpose'}."\n"; 922 923 print ".SH SYNOPSIS\n"; 924 print ".B \"".$args{'functiontype'}."\" ".$args{'function'}."\n"; 925 $count = 0; 926 my $parenth = "("; 927 my $post = ","; 928 foreach my $parameter (@{$args{'parameterlist'}}) { 929 if ($count == $#{$args{'parameterlist'}}) { 930 $post = ");"; 931 } 932 $type = $args{'parametertypes'}{$parameter}; 933 if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { 934 # pointer-to-function 935 print ".BI \"".$parenth.$1."\" ".$parameter." \") (".$2.")".$post."\"\n"; 936 } else { 937 $type =~ s/([^\*])$/$1 /; 938 print ".BI \"".$parenth.$type."\" ".$parameter." \"".$post."\"\n"; 939 } 940 $count++; 941 $parenth = ""; 942 } 943 944 print ".SH ARGUMENTS\n"; 945 foreach $parameter (@{$args{'parameterlist'}}) { 946 my $parameter_name = $parameter; 947 $parameter_name =~ s/\[.*//; 948 949 print ".IP \"".$parameter."\" 12\n"; 950 output_highlight($args{'parameterdescs'}{$parameter_name}); 951 } 952 foreach $section (@{$args{'sectionlist'}}) { 953 print ".SH \"", uc $section, "\"\n"; 954 output_highlight($args{'sections'}{$section}); 955 } 956} 957 958## 959# output enum in man 960sub output_enum_man(%) { 961 my %args = %{$_[0]}; 962 my ($parameter, $section); 963 my $count; 964 965 print ".TH \"$args{'module'}\" 9 \"enum $args{'enum'}\" \"$man_date\" \"API Manual\" LINUX\n"; 966 967 print ".SH NAME\n"; 968 print "enum ".$args{'enum'}." \\- ".$args{'purpose'}."\n"; 969 970 print ".SH SYNOPSIS\n"; 971 print "enum ".$args{'enum'}." {\n"; 972 $count = 0; 973 foreach my $parameter (@{$args{'parameterlist'}}) { 974 print ".br\n.BI \" $parameter\"\n"; 975 if ($count == $#{$args{'parameterlist'}}) { 976 print "\n};\n"; 977 last; 978 } 979 else { 980 print ", \n.br\n"; 981 } 982 $count++; 983 } 984 985 print ".SH Constants\n"; 986 foreach $parameter (@{$args{'parameterlist'}}) { 987 my $parameter_name = $parameter; 988 $parameter_name =~ s/\[.*//; 989 990 print ".IP \"".$parameter."\" 12\n"; 991 output_highlight($args{'parameterdescs'}{$parameter_name}); 992 } 993 foreach $section (@{$args{'sectionlist'}}) { 994 print ".SH \"$section\"\n"; 995 output_highlight($args{'sections'}{$section}); 996 } 997} 998 999## 1000# output struct in man 1001sub output_struct_man(%) { 1002 my %args = %{$_[0]}; 1003 my ($parameter, $section); 1004 1005 print ".TH \"$args{'module'}\" 9 \"".$args{'type'}." ".$args{'struct'}."\" \"$man_date\" \"API Manual\" LINUX\n"; 1006 1007 print ".SH NAME\n"; 1008 print $args{'type'}." ".$args{'struct'}." \\- ".$args{'purpose'}."\n"; 1009 1010 print ".SH SYNOPSIS\n"; 1011 print $args{'type'}." ".$args{'struct'}." {\n.br\n"; 1012 1013 foreach my $parameter (@{$args{'parameterlist'}}) { 1014 if ($parameter =~ /^#/) { 1015 print ".BI \"$parameter\"\n.br\n"; 1016 next; 1017 } 1018 my $parameter_name = $parameter; 1019 $parameter_name =~ s/\[.*//; 1020 1021 ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; 1022 $type = $args{'parametertypes'}{$parameter}; 1023 if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { 1024 # pointer-to-function 1025 print ".BI \" ".$1."\" ".$parameter." \") (".$2.")"."\"\n;\n"; 1026 } elsif ($type =~ m/^(.*?)\s*(:.*)/) { 1027 print ".BI \" ".$1."\" ".$parameter.$2." \""."\"\n;\n"; 1028 } else { 1029 $type =~ s/([^\*])$/$1 /; 1030 print ".BI \" ".$type."\" ".$parameter." \""."\"\n;\n"; 1031 } 1032 print "\n.br\n"; 1033 } 1034 print "};\n.br\n"; 1035 1036 print ".SH Arguments\n"; 1037 foreach $parameter (@{$args{'parameterlist'}}) { 1038 ($parameter =~ /^#/) && next; 1039 1040 my $parameter_name = $parameter; 1041 $parameter_name =~ s/\[.*//; 1042 1043 ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; 1044 print ".IP \"".$parameter."\" 12\n"; 1045 output_highlight($args{'parameterdescs'}{$parameter_name}); 1046 } 1047 foreach $section (@{$args{'sectionlist'}}) { 1048 print ".SH \"$section\"\n"; 1049 output_highlight($args{'sections'}{$section}); 1050 } 1051} 1052 1053## 1054# output typedef in man 1055sub output_typedef_man(%) { 1056 my %args = %{$_[0]}; 1057 my ($parameter, $section); 1058 1059 print ".TH \"$args{'module'}\" 9 \"$args{'typedef'}\" \"$man_date\" \"API Manual\" LINUX\n"; 1060 1061 print ".SH NAME\n"; 1062 print "typedef ".$args{'typedef'}." \\- ".$args{'purpose'}."\n"; 1063 1064 foreach $section (@{$args{'sectionlist'}}) { 1065 print ".SH \"$section\"\n"; 1066 output_highlight($args{'sections'}{$section}); 1067 } 1068} 1069 1070sub output_intro_man(%) { 1071 my %args = %{$_[0]}; 1072 my ($parameter, $section); 1073 my $count; 1074 1075 print ".TH \"$args{'module'}\" 9 \"$args{'module'}\" \"$man_date\" \"API Manual\" LINUX\n"; 1076 1077 foreach $section (@{$args{'sectionlist'}}) { 1078 print ".SH \"$section\"\n"; 1079 output_highlight($args{'sections'}{$section}); 1080 } 1081} 1082 1083## 1084# output in text 1085sub output_function_text(%) { 1086 my %args = %{$_[0]}; 1087 my ($parameter, $section); 1088 1089 print "Function:\n\n"; 1090 my $start=$args{'functiontype'}." ".$args{'function'}." ("; 1091 print $start; 1092 my $count = 0; 1093 foreach my $parameter (@{$args{'parameterlist'}}) { 1094 $type = $args{'parametertypes'}{$parameter}; 1095 if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { 1096 # pointer-to-function 1097 print $1.$parameter.") (".$2; 1098 } else { 1099 print $type." ".$parameter; 1100 } 1101 if ($count != $#{$args{'parameterlist'}}) { 1102 $count++; 1103 print ",\n"; 1104 print " " x length($start); 1105 } else { 1106 print ");\n\n"; 1107 } 1108 } 1109 1110 print "Arguments:\n\n"; 1111 foreach $parameter (@{$args{'parameterlist'}}) { 1112 my $parameter_name = $parameter; 1113 $parameter_name =~ s/\[.*//; 1114 1115 print $parameter."\n\t".$args{'parameterdescs'}{$parameter_name}."\n"; 1116 } 1117 output_section_text(@_); 1118} 1119 1120#output sections in text 1121sub output_section_text(%) { 1122 my %args = %{$_[0]}; 1123 my $section; 1124 1125 print "\n"; 1126 foreach $section (@{$args{'sectionlist'}}) { 1127 print "$section:\n\n"; 1128 output_highlight($args{'sections'}{$section}); 1129 } 1130 print "\n\n"; 1131} 1132 1133# output enum in text 1134sub output_enum_text(%) { 1135 my %args = %{$_[0]}; 1136 my ($parameter); 1137 my $count; 1138 print "Enum:\n\n"; 1139 1140 print "enum ".$args{'enum'}." {\n"; 1141 $count = 0; 1142 foreach $parameter (@{$args{'parameterlist'}}) { 1143 print "\t$parameter"; 1144 if ($count != $#{$args{'parameterlist'}}) { 1145 $count++; 1146 print ","; 1147 } 1148 print "\n"; 1149 } 1150 print "};\n\n"; 1151 1152 print "Constants:\n\n"; 1153 foreach $parameter (@{$args{'parameterlist'}}) { 1154 print "$parameter\n\t"; 1155 print $args{'parameterdescs'}{$parameter}."\n"; 1156 } 1157 1158 output_section_text(@_); 1159} 1160 1161# output typedef in text 1162sub output_typedef_text(%) { 1163 my %args = %{$_[0]}; 1164 my ($parameter); 1165 my $count; 1166 print "Typedef:\n\n"; 1167 1168 print "typedef ".$args{'typedef'}."\n"; 1169 output_section_text(@_); 1170} 1171 1172# output struct as text 1173sub output_struct_text(%) { 1174 my %args = %{$_[0]}; 1175 my ($parameter); 1176 1177 print $args{'type'}." ".$args{'struct'}.":\n\n"; 1178 print $args{'type'}." ".$args{'struct'}." {\n"; 1179 foreach $parameter (@{$args{'parameterlist'}}) { 1180 if ($parameter =~ /^#/) { 1181 print "$parameter\n"; 1182 next; 1183 } 1184 1185 my $parameter_name = $parameter; 1186 $parameter_name =~ s/\[.*//; 1187 1188 ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; 1189 $type = $args{'parametertypes'}{$parameter}; 1190 if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { 1191 # pointer-to-function 1192 print "\t$1 $parameter) ($2);\n"; 1193 } elsif ($type =~ m/^(.*?)\s*(:.*)/) { 1194 print "\t$1 $parameter$2;\n"; 1195 } else { 1196 print "\t".$type." ".$parameter.";\n"; 1197 } 1198 } 1199 print "};\n\n"; 1200 1201 print "Members:\n\n"; 1202 foreach $parameter (@{$args{'parameterlist'}}) { 1203 ($parameter =~ /^#/) && next; 1204 1205 my $parameter_name = $parameter; 1206 $parameter_name =~ s/\[.*//; 1207 1208 ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; 1209 print "$parameter\n\t"; 1210 print $args{'parameterdescs'}{$parameter_name}."\n"; 1211 } 1212 print "\n"; 1213 output_section_text(@_); 1214} 1215 1216sub output_intro_text(%) { 1217 my %args = %{$_[0]}; 1218 my ($parameter, $section); 1219 1220 foreach $section (@{$args{'sectionlist'}}) { 1221 print " $section:\n"; 1222 print " -> "; 1223 output_highlight($args{'sections'}{$section}); 1224 } 1225} 1226 1227## 1228# generic output function for typedefs 1229sub output_declaration { 1230 no strict 'refs'; 1231 my $name = shift; 1232 my $functype = shift; 1233 my $func = "output_${functype}_$output_mode"; 1234 if (($function_only==0) || 1235 ( $function_only == 1 && defined($function_table{$name})) || 1236 ( $function_only == 2 && !defined($function_table{$name}))) 1237 { 1238 &$func(@_); 1239 $section_counter++; 1240 } 1241} 1242 1243## 1244# generic output function - calls the right one based 1245# on current output mode. 1246sub output_intro { 1247 no strict 'refs'; 1248 my $func = "output_intro_".$output_mode; 1249 &$func(@_); 1250 $section_counter++; 1251} 1252 1253## 1254# takes a declaration (struct, union, enum, typedef) and 1255# invokes the right handler. NOT called for functions. 1256sub dump_declaration($$) { 1257 no strict 'refs'; 1258 my ($prototype, $file) = @_; 1259 my $func = "dump_".$decl_type; 1260 &$func(@_); 1261} 1262 1263sub dump_union($$) { 1264 dump_struct(@_); 1265} 1266 1267sub dump_struct($$) { 1268 my $x = shift; 1269 my $file = shift; 1270 1271 if ($x =~/(struct|union)\s+(\w+)\s*{(.*)}/) { 1272 $declaration_name = $2; 1273 my $members = $3; 1274 1275 # ignore embedded structs or unions 1276 $members =~ s/{.*?}//g; 1277 1278 create_parameterlist($members, ';', $file); 1279 1280 output_declaration($declaration_name, 1281 'struct', 1282 {'struct' => $declaration_name, 1283 'module' => $modulename, 1284 'parameterlist' => \@parameterlist, 1285 'parameterdescs' => \%parameterdescs, 1286 'parametertypes' => \%parametertypes, 1287 'sectionlist' => \@sectionlist, 1288 'sections' => \%sections, 1289 'purpose' => $declaration_purpose, 1290 'type' => $decl_type 1291 }); 1292 } 1293 else { 1294 print STDERR "Error(${file}:$.): Cannot parse struct or union!\n"; 1295 ++$errors; 1296 } 1297} 1298 1299sub dump_enum($$) { 1300 my $x = shift; 1301 my $file = shift; 1302 1303 if ($x =~ /enum\s+(\w+)\s*{(.*)}/) { 1304 $declaration_name = $1; 1305 my $members = $2; 1306 1307 foreach my $arg (split ',', $members) { 1308 $arg =~ s/^\s*(\w+).*/$1/; 1309 push @parameterlist, $arg; 1310 if (!$parameterdescs{$arg}) { 1311 $parameterdescs{$arg} = $undescribed; 1312 print STDERR "Warning(${file}:$.): Enum value '$arg' ". 1313 "not described in enum '$declaration_name'\n"; 1314 } 1315 1316 } 1317 1318 output_declaration($declaration_name, 1319 'enum', 1320 {'enum' => $declaration_name, 1321 'module' => $modulename, 1322 'parameterlist' => \@parameterlist, 1323 'parameterdescs' => \%parameterdescs, 1324 'sectionlist' => \@sectionlist, 1325 'sections' => \%sections, 1326 'purpose' => $declaration_purpose 1327 }); 1328 } 1329 else { 1330 print STDERR "Error(${file}:$.): Cannot parse enum!\n"; 1331 ++$errors; 1332 } 1333} 1334 1335sub dump_typedef($$) { 1336 my $x = shift; 1337 my $file = shift; 1338 1339 while (($x =~ /\(*.\)\s*;$/) || ($x =~ /\[*.\]\s*;$/)) { 1340 $x =~ s/\(*.\)\s*;$/;/; 1341 $x =~ s/\[*.\]\s*;$/;/; 1342 } 1343 1344 if ($x =~ /typedef.*\s+(\w+)\s*;/) { 1345 $declaration_name = $1; 1346 1347 output_declaration($declaration_name, 1348 'typedef', 1349 {'typedef' => $declaration_name, 1350 'module' => $modulename, 1351 'sectionlist' => \@sectionlist, 1352 'sections' => \%sections, 1353 'purpose' => $declaration_purpose 1354 }); 1355 } 1356 else { 1357 print STDERR "Error(${file}:$.): Cannot parse typedef!\n"; 1358 ++$errors; 1359 } 1360} 1361 1362sub create_parameterlist($$$) { 1363 my $args = shift; 1364 my $splitter = shift; 1365 my $file = shift; 1366 my $type; 1367 my $param; 1368 1369 while ($args =~ /(\([^\),]+),/) { 1370 $args =~ s/(\([^\),]+),/$1#/g; 1371 } 1372 1373 foreach my $arg (split($splitter, $args)) { 1374 # strip comments 1375 $arg =~ s/\/\*.*\*\///; 1376 # strip leading/trailing spaces 1377 $arg =~ s/^\s*//; 1378 $arg =~ s/\s*$//; 1379 $arg =~ s/\s+/ /; 1380 1381 if ($arg =~ /^#/) { 1382 # Treat preprocessor directive as a typeless variable just to fill 1383 # corresponding data structures "correctly". Catch it later in 1384 # output_* subs. 1385 push_parameter($arg, "", $file); 1386 } elsif ($arg =~ m/\(/) { 1387 # pointer-to-function 1388 $arg =~ tr/#/,/; 1389 $arg =~ m/[^\(]+\(\*([^\)]+)\)/; 1390 $param = $1; 1391 $type = $arg; 1392 $type =~ s/([^\(]+\(\*)$param/$1/; 1393 push_parameter($param, $type, $file); 1394 } else { 1395 $arg =~ s/\s*:\s*/:/g; 1396 $arg =~ s/\s*\[/\[/g; 1397 1398 my @args = split('\s*,\s*', $arg); 1399 if ($args[0] =~ m/\*/) { 1400 $args[0] =~ s/(\*+)\s*/ $1/; 1401 } 1402 my @first_arg = split('\s+', shift @args); 1403 unshift(@args, pop @first_arg); 1404 $type = join " ", @first_arg; 1405 1406 foreach $param (@args) { 1407 if ($param =~ m/^(\*+)\s*(.*)/) { 1408 push_parameter($2, "$type $1", $file); 1409 } 1410 elsif ($param =~ m/(.*?):(\d+)/) { 1411 push_parameter($1, "$type:$2", $file) 1412 } 1413 else { 1414 push_parameter($param, $type, $file); 1415 } 1416 } 1417 } 1418 } 1419} 1420 1421sub push_parameter($$$) { 1422 my $param = shift; 1423 my $type = shift; 1424 my $file = shift; 1425 1426 my $param_name = $param; 1427 $param_name =~ s/\[.*//; 1428 1429 if ($type eq "" && $param eq "...") 1430 { 1431 $type=""; 1432 $param="..."; 1433 $parameterdescs{"..."} = "variable arguments"; 1434 } 1435 elsif ($type eq "" && ($param eq "" or $param eq "void")) 1436 { 1437 $type=""; 1438 $param="void"; 1439 $parameterdescs{void} = "no arguments"; 1440 } 1441 if (defined $type && $type && !defined $parameterdescs{$param_name}) { 1442 $parameterdescs{$param_name} = $undescribed; 1443 1444 if (($type eq 'function') || ($type eq 'enum')) { 1445 print STDERR "Warning(${file}:$.): Function parameter ". 1446 "or member '$param' not " . 1447 "described in '$declaration_name'\n"; 1448 } 1449 print STDERR "Warning(${file}:$.):". 1450 " No description found for parameter '$param'\n"; 1451 ++$warnings; 1452 } 1453 1454 push @parameterlist, $param; 1455 $parametertypes{$param} = $type; 1456} 1457 1458## 1459# takes a function prototype and the name of the current file being 1460# processed and spits out all the details stored in the global 1461# arrays/hashes. 1462sub dump_function($$) { 1463 my $prototype = shift; 1464 my $file = shift; 1465 1466 $prototype =~ s/^static +//; 1467 $prototype =~ s/^extern +//; 1468 $prototype =~ s/^fastcall +//; 1469 $prototype =~ s/^asmlinkage +//; 1470 $prototype =~ s/^inline +//; 1471 $prototype =~ s/^__inline__ +//; 1472 $prototype =~ s/^#define +//; #ak added 1473 $prototype =~ s/__attribute__ \(\([a-z,]*\)\)//; 1474 1475 # Yes, this truly is vile. We are looking for: 1476 # 1. Return type (may be nothing if we're looking at a macro) 1477 # 2. Function name 1478 # 3. Function parameters. 1479 # 1480 # All the while we have to watch out for function pointer parameters 1481 # (which IIRC is what the two sections are for), C types (these 1482 # regexps don't even start to express all the possibilities), and 1483 # so on. 1484 # 1485 # If you mess with these regexps, it's a good idea to check that 1486 # the following functions' documentation still comes out right: 1487 # - parport_register_device (function pointer parameters) 1488 # - atomic_set (macro) 1489 # - pci_match_device (long return type) 1490 1491 if ($prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || 1492 $prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || 1493 $prototype =~ m/^(\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || 1494 $prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || 1495 $prototype =~ m/^(\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || 1496 $prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || 1497 $prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\(]*)\)/ || 1498 $prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || 1499 $prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || 1500 $prototype =~ m/^(\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || 1501 $prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || 1502 $prototype =~ m/^(\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || 1503 $prototype =~ m/^(\w+\s+\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/ || 1504 $prototype =~ m/^(\w+\s+\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\{]*)\)/) { 1505 $return_type = $1; 1506 $declaration_name = $2; 1507 my $args = $3; 1508 1509 create_parameterlist($args, ',', $file); 1510 } else { 1511 print STDERR "Error(${file}:$.): cannot understand prototype: '$prototype'\n"; 1512 ++$errors; 1513 return; 1514 } 1515 1516 output_declaration($declaration_name, 1517 'function', 1518 {'function' => $declaration_name, 1519 'module' => $modulename, 1520 'functiontype' => $return_type, 1521 'parameterlist' => \@parameterlist, 1522 'parameterdescs' => \%parameterdescs, 1523 'parametertypes' => \%parametertypes, 1524 'sectionlist' => \@sectionlist, 1525 'sections' => \%sections, 1526 'purpose' => $declaration_purpose 1527 }); 1528} 1529 1530sub process_file($); 1531 1532# Read the file that maps relative names to absolute names for 1533# separate source and object directories and for shadow trees. 1534if (open(SOURCE_MAP, "<.tmp_filelist.txt")) { 1535 my ($relname, $absname); 1536 while(<SOURCE_MAP>) { 1537 chop(); 1538 ($relname, $absname) = (split())[0..1]; 1539 $relname =~ s:^/+::; 1540 $source_map{$relname} = $absname; 1541 } 1542 close(SOURCE_MAP); 1543} 1544 1545if ($filelist) { 1546 open(FLIST,"<$filelist") or die "Can't open file list $filelist"; 1547 while(<FLIST>) { 1548 chop; 1549 process_file($_); 1550 } 1551} 1552 1553foreach (@ARGV) { 1554 chomp; 1555 process_file($_); 1556} 1557if ($verbose && $errors) { 1558 print STDERR "$errors errors\n"; 1559} 1560if ($verbose && $warnings) { 1561 print STDERR "$warnings warnings\n"; 1562} 1563 1564exit($errors); 1565 1566sub reset_state { 1567 $function = ""; 1568 %constants = (); 1569 %parameterdescs = (); 1570 %parametertypes = (); 1571 @parameterlist = (); 1572 %sections = (); 1573 @sectionlist = (); 1574 $prototype = ""; 1575 1576 $state = 0; 1577} 1578 1579sub process_state3_function($$) { 1580 my $x = shift; 1581 my $file = shift; 1582 1583 if ($x =~ m#\s*/\*\s+MACDOC\s*#io || ($x =~ /^#/ && $x !~ /^#define/)) { 1584 # do nothing 1585 } 1586 elsif ($x =~ /([^\{]*)/) { 1587 $prototype .= $1; 1588 } 1589 if (($x =~ /\{/) || ($x =~ /\#define/) || ($x =~ /;/)) { 1590 $prototype =~ s@/\*.*?\*/@@gos; # strip comments. 1591 $prototype =~ s@[\r\n]+@ @gos; # strip newlines/cr's. 1592 $prototype =~ s@^\s+@@gos; # strip leading spaces 1593 dump_function($prototype,$file); 1594 reset_state(); 1595 } 1596} 1597 1598sub process_state3_type($$) { 1599 my $x = shift; 1600 my $file = shift; 1601 1602 $x =~ s@/\*.*?\*/@@gos; # strip comments. 1603 $x =~ s@[\r\n]+@ @gos; # strip newlines/cr's. 1604 $x =~ s@^\s+@@gos; # strip leading spaces 1605 $x =~ s@\s+$@@gos; # strip trailing spaces 1606 if ($x =~ /^#/) { 1607 # To distinguish preprocessor directive from regular declaration later. 1608 $x .= ";"; 1609 } 1610 1611 while (1) { 1612 if ( $x =~ /([^{};]*)([{};])(.*)/ ) { 1613 $prototype .= $1 . $2; 1614 ($2 eq '{') && $brcount++; 1615 ($2 eq '}') && $brcount--; 1616 if (($2 eq ';') && ($brcount == 0)) { 1617 dump_declaration($prototype,$file); 1618 reset_state(); 1619 last; 1620 } 1621 $x = $3; 1622 } else { 1623 $prototype .= $x; 1624 last; 1625 } 1626 } 1627} 1628 1629# replace <, >, and & 1630sub xml_escape($) { 1631 my $text = shift; 1632 $text =~ s/\&/\\\\\\amp;/g; 1633 $text =~ s/\</\\\\\\lt;/g; 1634 $text =~ s/\>/\\\\\\gt;/g; 1635 return $text; 1636} 1637 1638sub process_file($) { 1639 my ($file) = "$ENV{'SRCTREE'}@_"; 1640 my $identifier; 1641 my $func; 1642 my $initial_section_counter = $section_counter; 1643 1644 if (defined($source_map{$file})) { 1645 $file = $source_map{$file}; 1646 } 1647 1648 if (!open(IN,"<$file")) { 1649 print STDERR "Error: Cannot open file $file\n"; 1650 ++$errors; 1651 return; 1652 } 1653 1654 $section_counter = 0; 1655 while (<IN>) { 1656 if ($state == 0) { 1657 if (/$doc_start/o) { 1658 $state = 1; # next line is always the function name 1659 } 1660 } elsif ($state == 1) { # this line is the function name (always) 1661 if (/$doc_block/o) { 1662 $state = 4; 1663 $contents = ""; 1664 if ( $1 eq "" ) { 1665 $section = $section_intro; 1666 } else { 1667 $section = $1; 1668 } 1669 } 1670 elsif (/$doc_decl/o) { 1671 $identifier = $1; 1672 if (/\s*([\w\s]+?)\s*-/) { 1673 $identifier = $1; 1674 } 1675 1676 $state = 2; 1677 if (/-(.*)/) { 1678 $declaration_purpose = xml_escape($1); 1679 } else { 1680 $declaration_purpose = ""; 1681 } 1682 if ($identifier =~ m/^struct/) { 1683 $decl_type = 'struct'; 1684 } elsif ($identifier =~ m/^union/) { 1685 $decl_type = 'union'; 1686 } elsif ($identifier =~ m/^enum/) { 1687 $decl_type = 'enum'; 1688 } elsif ($identifier =~ m/^typedef/) { 1689 $decl_type = 'typedef'; 1690 } else { 1691 $decl_type = 'function'; 1692 } 1693 1694 if ($verbose) { 1695 print STDERR "Info(${file}:$.): Scanning doc for $identifier\n"; 1696 } 1697 } else { 1698 print STDERR "Warning(${file}:$.): Cannot understand $_ on line $.", 1699 " - I thought it was a doc line\n"; 1700 ++$warnings; 1701 $state = 0; 1702 } 1703 } elsif ($state == 2) { # look for head: lines, and include content 1704 if (/$doc_sect/o) { 1705 $newsection = $1; 1706 $newcontents = $2; 1707 1708 if ($contents ne "") { 1709 dump_section($section, xml_escape($contents)); 1710 $section = $section_default; 1711 } 1712 1713 $contents = $newcontents; 1714 if ($contents ne "") { 1715 $contents .= "\n"; 1716 } 1717 $section = $newsection; 1718 } elsif (/$doc_end/) { 1719 1720 if ($contents ne "") { 1721 dump_section($section, xml_escape($contents)); 1722 $section = $section_default; 1723 $contents = ""; 1724 } 1725 1726 $prototype = ""; 1727 $state = 3; 1728 $brcount = 0; 1729# print STDERR "end of doc comment, looking for prototype\n"; 1730 } elsif (/$doc_content/) { 1731 # miguel-style comment kludge, look for blank lines after 1732 # @parameter line to signify start of description 1733 if ($1 eq "" && 1734 ($section =~ m/^@/ || $section eq $section_context)) { 1735 dump_section($section, xml_escape($contents)); 1736 $section = $section_default; 1737 $contents = ""; 1738 } else { 1739 $contents .= $1."\n"; 1740 } 1741 } else { 1742 # i dont know - bad line? ignore. 1743 print STDERR "Warning(${file}:$.): bad line: $_"; 1744 ++$warnings; 1745 } 1746 } elsif ($state == 3) { # scanning for function { (end of prototype) 1747 if ($decl_type eq 'function') { 1748 process_state3_function($_, $file); 1749 } else { 1750 process_state3_type($_, $file); 1751 } 1752 } elsif ($state == 4) { 1753 # Documentation block 1754 if (/$doc_block/) { 1755 dump_section($section, $contents); 1756 output_intro({'sectionlist' => \@sectionlist, 1757 'sections' => \%sections }); 1758 $contents = ""; 1759 $function = ""; 1760 %constants = (); 1761 %parameterdescs = (); 1762 %parametertypes = (); 1763 @parameterlist = (); 1764 %sections = (); 1765 @sectionlist = (); 1766 $prototype = ""; 1767 if ( $1 eq "" ) { 1768 $section = $section_intro; 1769 } else { 1770 $section = $1; 1771 } 1772 } 1773 elsif (/$doc_end/) 1774 { 1775 dump_section($section, $contents); 1776 output_intro({'sectionlist' => \@sectionlist, 1777 'sections' => \%sections }); 1778 $contents = ""; 1779 $function = ""; 1780 %constants = (); 1781 %parameterdescs = (); 1782 %parametertypes = (); 1783 @parameterlist = (); 1784 %sections = (); 1785 @sectionlist = (); 1786 $prototype = ""; 1787 $state = 0; 1788 } 1789 elsif (/$doc_content/) 1790 { 1791 if ( $1 eq "" ) 1792 { 1793 $contents .= $blankline; 1794 } 1795 else 1796 { 1797 $contents .= $1 . "\n"; 1798 } 1799 } 1800 } 1801 } 1802 if ($initial_section_counter == $section_counter) { 1803 print STDERR "Warning(${file}): no structured comments found\n"; 1804 if ($output_mode eq "xml") { 1805 # The template wants at least one RefEntry here; make one. 1806 print "<refentry>\n"; 1807 print " <refnamediv>\n"; 1808 print " <refname>\n"; 1809 print " ${file}\n"; 1810 print " </refname>\n"; 1811 print " <refpurpose>\n"; 1812 print " Document generation inconsistency\n"; 1813 print " </refpurpose>\n"; 1814 print " </refnamediv>\n"; 1815 print " <refsect1>\n"; 1816 print " <title>\n"; 1817 print " Oops\n"; 1818 print " </title>\n"; 1819 print " <warning>\n"; 1820 print " <para>\n"; 1821 print " The template for this document tried to insert\n"; 1822 print " the structured comment from the file\n"; 1823 print " <filename>${file}</filename> at this point,\n"; 1824 print " but none was found.\n"; 1825 print " This dummy section is inserted to allow\n"; 1826 print " generation to continue.\n"; 1827 print " </para>\n"; 1828 print " </warning>\n"; 1829 print " </refsect1>\n"; 1830 print "</refentry>\n"; 1831 } 1832 } 1833} 1834