Annotation of embedaddon/bird/doc/kernel-doc, revision 1.1.1.1

1.1       misho       1: #!/usr/bin/perl
                      2: 
                      3: ## Copyright (c) 1998 Michael Zucchi, All Rights Reserved        ##
                      4: ##                                                               ##
                      5: ## This software falls under the GNU Public License. Please read ##
                      6: ##              the COPYING file for more information            ##
                      7: 
                      8: #
                      9: # This will read a 'c' file and scan for embedded comments in the
                     10: # style of gnome comments (+minor extensions - see below).
                     11: #
                     12: 
                     13: # Note: This only supports 'c'.
                     14: 
                     15: # usage:
                     16: # kerneldoc [ -docbook | -html | -text | -man | -gnome | -bird ]
                     17: #           [ -function funcname [ -function funcname ...] ] c file(s)s > outputfile
                     18: # or
                     19: #           [ -nofunction funcname [ -function funcname ...] ] c file(s)s > outputfile
                     20: #
                     21: #  Set output format using one of -docbook -html -text -man -gnome or -bird.  Default is man.
                     22: #
                     23: #  -function funcname
                     24: #      If set, then only generate documentation for the given function(s).  All
                     25: #      other functions are ignored.
                     26: #
                     27: #  -nofunction funcname
                     28: #      If set, then only generate documentation for the other function(s).  All
                     29: #      other functions are ignored. Cannot be used with -function together
                     30: #      (yes thats a bug - perl hackers can fix it 8))
                     31: #
                     32: #  c files - list of 'c' files to process
                     33: #
                     34: #  All output goes to stdout, with errors to stderr.
                     35: 
                     36: #
                     37: # format of comments.
                     38: # In the following table, (...)? signifies optional structure.
                     39: #                         (...)* signifies 0 or more structure elements
                     40: # /**
                     41: #  * function_name(:)? (- short description)?
                     42: # (* @parameterx: (description of parameter x)?)*
                     43: # (* a blank line)?
                     44: #  * (Description:)? (Description of function)?
                     45: #  * (section header: (section description)? )*
                     46: #  (*)?*/
                     47: #
                     48: # So .. the trivial example would be:
                     49: #
                     50: # /**
                     51: #  * my_function
                     52: #  **/
                     53: #
                     54: # If the Description: header tag is ommitted, then there must be a blank line
                     55: # after the last parameter specification.
                     56: # e.g.
                     57: # /**
                     58: #  * my_function - does my stuff
                     59: #  * @my_arg: its mine damnit
                     60: #  *
                     61: #  * Does my stuff explained. 
                     62: #  */
                     63: #
                     64: #  or, could also use:
                     65: # /**
                     66: #  * my_function - does my stuff
                     67: #  * @my_arg: its mine damnit
                     68: #  * Description: Does my stuff explained. 
                     69: #  */
                     70: # etc.
                     71: #
                     72: # All descriptions can be multiline, apart from the short function description.
                     73: #
                     74: # All descriptive text is further processed, scanning for the following special
                     75: # patterns, which are highlighted appropriately.
                     76: #
                     77: # 'funcname()' - function
                     78: # '$ENVVAR' - environmental variable
                     79: # '&struct_name' - name of a structure or a type
                     80: # '@parameter' - name of a parameter
                     81: # '%CONST' - name of a constant.
                     82: # '|code|' - literal string
                     83: 
                     84: # match expressions used to find embedded type information
                     85: $type_constant = "\\\%(\\w+)";
                     86: $type_func = "(\\w+\\(\\))";
                     87: $type_param = "\\\@(\\w+)";
                     88: $type_struct = "\\\&(\\w+)";
                     89: $type_env = "(\\\$\\w+)";
                     90: $type_code = "\\|([^|]*)\\|";
                     91: 
                     92: 
                     93: # Output conversion substitutions.
                     94: #  One for each output format
                     95: 
                     96: # these work fairly well
                     97: %highlights_html = ( $type_constant, "<i>\$1</i>",
                     98:                     $type_func, "<b>\$1</b>",
                     99:                     $type_struct, "<i>\$1</i>",
                    100:                     $type_param, "<tt><b>\$1</b></tt>" );
                    101: $blankline_html = "<p>";
                    102: 
                    103: # sgml, docbook format
                    104: %highlights_sgml = ( $type_constant, "<replaceable class=\"option\">\$1</replaceable>",
                    105:                     $type_func, "<function>\$1</function>",
                    106:                     $type_struct, "<structname>\$1</structname>",
                    107:                     $type_env, "<envar>\$1</envar>",
                    108:                     $type_param, "<parameter>\$1</parameter>" );
                    109: $blankline_sgml = "</para><para>\n";
                    110: 
                    111: # gnome, docbook format
                    112: %highlights_gnome = ( $type_constant, "<replaceable class=\"option\">\$1</replaceable>",
                    113:                     $type_func, "<function>\$1</function>",
                    114:                     $type_struct, "<structname>\$1</structname>",
                    115:                     $type_env, "<envar>\$1</envar>",
                    116:                     $type_param, "<parameter>\$1</parameter>" );
                    117: $blankline_gnome = "</para><para>\n";
                    118: 
                    119: # bird documentation
                    120: %highlights_bird = ( $type_constant, "<const/\$1/",
                    121:                     $type_func, "<func/\$1/",
                    122:                     $type_struct, "<struct/\$1/",
                    123:                     $type_param, "<param/\$1/",
                    124:                     $type_code, "<tt>\$1</tt>");
                    125: $blankline_bird = "<p>";
                    126: 
                    127: # these are pretty rough
                    128: %highlights_man = ( $type_constant, "\\n.I \\\"\$1\\\"\\n",
                    129:                    $type_func, "\\n.B \\\"\$1\\\"\\n",
                    130:                    $type_struct, "\\n.I \\\"\$1\\\"\\n",
                    131:                    $type_param."([\.\, ]*)\n?", "\\n.I \\\"\$1\$2\\\"\\n" );
                    132: $blankline_man = "";
                    133: 
                    134: # text-mode
                    135: %highlights_text = ( $type_constant, "\$1",
                    136:                     $type_func, "\$1",
                    137:                     $type_struct, "\$1",
                    138:                     $type_param, "\$1" );
                    139: $blankline_text = "";
                    140: 
                    141: 
                    142: sub usage {
                    143:     print "Usage: $0 [ -v ] [ -docbook | -html | -text | -man ]\n";
                    144:     print "         [ -function funcname [ -function funcname ...] ]\n";
                    145:     print "         [ -nofunction funcname [ -nofunction funcname ...] ]\n";
                    146:     print "         c source file(s) > outputfile\n";
                    147:     exit 1;
                    148: }
                    149: 
                    150: # read arguments
                    151: if ($#ARGV==-1) {
                    152:     usage();
                    153: }
                    154: 
                    155: $verbose = 0;
                    156: $output_mode = "man";
                    157: %highlights = %highlights_man;
                    158: $blankline = $blankline_man;
                    159: $modulename = "API Documentation";
                    160: $function_only = 0;
                    161: while ($ARGV[0] =~ m/^-(.*)/) {
                    162:     $cmd = shift @ARGV;
                    163:     if ($cmd eq "-html") {
                    164:        $output_mode = "html";
                    165:        %highlights = %highlights_html;
                    166:        $blankline = $blankline_html;
                    167:     } elsif ($cmd eq "-man") {
                    168:        $output_mode = "man";
                    169:        %highlights = %highlights_man;
                    170:        $blankline = $blankline_man;
                    171:     } elsif ($cmd eq "-text") {
                    172:        $output_mode = "text";
                    173:        %highlights = %highlights_text;
                    174:        $blankline = $blankline_text;
                    175:     } elsif ($cmd eq "-docbook") {
                    176:        $output_mode = "sgml";
                    177:        %highlights = %highlights_sgml;
                    178:        $blankline = $blankline_sgml;
                    179:     } elsif ($cmd eq "-gnome") {
                    180:        $output_mode = "gnome";
                    181:        %highlights = %highlights_gnome;
                    182:        $blankline = $blankline_gnome;
                    183:     } elsif ($cmd eq "-bird") {
                    184:        $output_mode = "bird";
                    185:        %highlights = %highlights_bird;
                    186:        $blankline = $blankline_bird;
                    187:     } elsif ($cmd eq "-module") { # not needed for sgml, inherits from calling document
                    188:        $modulename = shift @ARGV;
                    189:     } elsif ($cmd eq "-function") { # to only output specific functions
                    190:        $function_only = 1;
                    191:        $function = shift @ARGV;
                    192:        $function_table{$function} = 1;
                    193:     } elsif ($cmd eq "-nofunction") { # to only output specific functions
                    194:        $function_only = 2;
                    195:        $function = shift @ARGV;
                    196:        $function_table{$function} = 1;
                    197:     } elsif ($cmd eq "-v") {
                    198:        $verbose = 1;
                    199:     } elsif (($cmd eq "-h") || ($cmd eq "--help")) {
                    200:        usage();
                    201:     }
                    202: }
                    203: 
                    204: 
                    205: # generate a sequence of code that will splice in highlighting information
                    206: # using the s// operator.
                    207: $dohighlight = "";
                    208: foreach $pattern (keys %highlights) {
                    209: #    print "scanning pattern $pattern ($highlights{$pattern})\n";
                    210:     $dohighlight .=  "\$contents =~ s:$pattern:$highlights{$pattern}:gs;\n";
                    211: }
                    212: 
                    213: ##
                    214: # dumps section contents to arrays/hashes intended for that purpose.
                    215: #
                    216: sub dump_section {
                    217:     my $name = shift @_;
                    218:     my $contents = join "\n", @_;
                    219: 
                    220:     if ($name =~ m/$type_constant/) {
                    221:        $name = $1;
                    222: #      print STDERR "constant section '$1' = '$contents'\n";
                    223:        $constants{$name} = $contents;
                    224:     } elsif ($name =~ m/$type_param/) {
                    225: #      print STDERR "parameter def '$1' = '$contents'\n";
                    226:        $name = $1;
                    227:        $parameters{$name} = $contents;
                    228:     } else {
                    229: #      print STDERR "other section '$name' = '$contents'\n";
                    230:        $sections{$name} = $contents;
                    231:        push @sectionlist, $name;
                    232:     }
                    233: }
                    234: 
                    235: ##
                    236: # output function
                    237: #
                    238: # parameters, a hash.
                    239: #  function => "function name"
                    240: #  parameterlist => @list of parameters
                    241: #  parameters => %parameter descriptions
                    242: #  sectionlist => @list of sections
                    243: #  sections => %descriont descriptions
                    244: #  
                    245: 
                    246: sub output_highlight {
                    247:     my $contents = join "\n", @_;
                    248:     my $line;
                    249: 
                    250:     eval $dohighlight;
                    251:     foreach $line (split "\n", $contents) {
                    252:        if ($line eq ""){
                    253:            print $lineprefix, $blankline;
                    254:        } else {
                    255:             $line =~ s/\\\\\\/\&/g;
                    256:            print $lineprefix, $line;
                    257:        }
                    258:        print "\n";
                    259:     }
                    260: }
                    261: 
                    262: 
                    263: # output in html
                    264: sub output_html {
                    265:     my %args = %{$_[0]};
                    266:     my ($parameter, $section);
                    267:     my $count;
                    268:     print "<h2>Function</h2>\n";
                    269: 
                    270:     print "<i>".$args{'functiontype'}."</i>\n";
                    271:     print "<b>".$args{'function'}."</b>\n";
                    272:     print "(";
                    273:     $count = 0;
                    274:     foreach $parameter (@{$args{'parameterlist'}}) {
                    275:        print "<i>".$args{'parametertypes'}{$parameter}."</i> <b>".$parameter."</b>\n";
                    276:        if ($count != $#{$args{'parameterlist'}}) {
                    277:            $count++;
                    278:            print ", ";
                    279:        }
                    280:     }
                    281:     print ")\n";
                    282: 
                    283:     print "<h3>Arguments</h3>\n";
                    284:     print "<dl>\n";
                    285:     foreach $parameter (@{$args{'parameterlist'}}) {
                    286:        print "<dt><i>".$args{'parametertypes'}{$parameter}."</i> <b>".$parameter."</b>\n";
                    287:        print "<dd>";
                    288:        output_highlight($args{'parameters'}{$parameter});
                    289:     }
                    290:     print "</dl>\n";
                    291:     foreach $section (@{$args{'sectionlist'}}) {
                    292:        print "<h1>$section</h1>\n";
                    293:        print "<ul>\n";
                    294:        output_highlight($args{'sections'}{$section});
                    295:        print "</ul>\n";
                    296:     }
                    297:     print "<hr>\n";
                    298: }
                    299: 
                    300: 
                    301: # output in html
                    302: sub output_intro_html {
                    303:     my %args = %{$_[0]};
                    304:     my ($parameter, $section);
                    305:     my $count;
                    306: 
                    307:     foreach $section (@{$args{'sectionlist'}}) {
                    308:        print "<h1>$section</h1>\n";
                    309:        print "<ul>\n";
                    310:        output_highlight($args{'sections'}{$section});
                    311:        print "</ul>\n";
                    312:     }
                    313:     print "<hr>\n";
                    314: }
                    315: 
                    316: 
                    317: 
                    318: # output in sgml DocBook
                    319: sub output_sgml {
                    320:     my %args = %{$_[0]};
                    321:     my ($parameter, $section);
                    322:     my $count;
                    323:     my $id;
                    324: 
                    325:     $id = $args{'module'}."-".$args{'function'};
                    326:     $id =~ s/[^A-Za-z0-9]/-/g;
                    327: 
                    328:     print "<refentry>\n";
                    329:     print "<refmeta>\n";
                    330:     print "<refentrytitle><phrase id=\"$id\">".$args{'function'}."</phrase></refentrytitle>\n";
                    331:     print "</refmeta>\n";
                    332:     print "<refnamediv>\n";
                    333:     print " <refname>".$args{'function'}."</refname>\n";
                    334:     print " <refpurpose>\n";
                    335:     print "  ".$args{'purpose'}."\n";
                    336:     print " </refpurpose>\n";
                    337:     print "</refnamediv>\n";
                    338: 
                    339:     print "<refsynopsisdiv>\n";
                    340:     print " <title>Synopsis</title>\n";
                    341:     print "  <funcsynopsis>\n";
                    342:     print "   <funcdef>".$args{'functiontype'}." ";
                    343:     print "<function>".$args{'function'}." ";
                    344:     print "</function></funcdef>\n";
                    345: 
                    346: #    print "<refsect1>\n";
                    347: #    print " <title>Synopsis</title>\n";
                    348: #    print "  <funcsynopsis>\n";
                    349: #    print "   <funcdef>".$args{'functiontype'}." ";
                    350: #    print "<function>".$args{'function'}." ";
                    351: #    print "</function></funcdef>\n";
                    352: 
                    353:     $count = 0;
                    354:     if ($#{$args{'parameterlist'}} >= 0) {
                    355:        foreach $parameter (@{$args{'parameterlist'}}) {
                    356:            print "   <paramdef>".$args{'parametertypes'}{$parameter};
                    357:            print " <parameter>$parameter</parameter></paramdef>\n";
                    358:        }
                    359:     } else {
                    360:        print "  <void>\n";
                    361:     }
                    362:     print "  </funcsynopsis>\n";
                    363:     print "</refsynopsisdiv>\n";
                    364: #    print "</refsect1>\n";
                    365: 
                    366:     # print parameters
                    367:     print "<refsect1>\n <title>Arguments</title>\n";
                    368: #    print "<para>\nArguments\n";
                    369:     if ($#{$args{'parameterlist'}} >= 0) {
                    370:        print " <variablelist>\n";
                    371:        foreach $parameter (@{$args{'parameterlist'}}) {
                    372:            print "  <varlistentry>\n   <term><parameter>$parameter</parameter></term>\n";
                    373:            print "   <listitem>\n    <para>\n";
                    374:            $lineprefix="     ";
                    375:            output_highlight($args{'parameters'}{$parameter});
                    376:            print "    </para>\n   </listitem>\n  </varlistentry>\n";
                    377:        }
                    378:        print " </variablelist>\n";
                    379:     } else {
                    380:        print " <para>\n  None\n </para>\n";
                    381:     }
                    382:     print "</refsect1>\n";
                    383: 
                    384:     # print out each section
                    385:     $lineprefix="   ";
                    386:     foreach $section (@{$args{'sectionlist'}}) {
                    387:        print "<refsect1>\n <title>$section</title>\n <para>\n";
                    388: #      print "<para>\n$section\n";
                    389:        if ($section =~ m/EXAMPLE/i) {
                    390:            print "<example><para>\n";
                    391:        }
                    392:        output_highlight($args{'sections'}{$section});
                    393: #      print "</para>";
                    394:        if ($section =~ m/EXAMPLE/i) {
                    395:            print "</para></example>\n";
                    396:        }
                    397:        print " </para>\n</refsect1>\n";
                    398:     }
                    399: 
                    400:     print "</refentry>\n\n";
                    401: }
                    402: 
                    403: # output in sgml DocBook
                    404: sub output_intro_sgml {
                    405:     my %args = %{$_[0]};
                    406:     my ($parameter, $section);
                    407:     my $count;
                    408:     my $id;
                    409: 
                    410:     $id = $args{'module'};
                    411:     $id =~ s/[^A-Za-z0-9]/-/g;
                    412: 
                    413:     # print out each section
                    414:     $lineprefix="   ";
                    415:     foreach $section (@{$args{'sectionlist'}}) {
                    416:        print "<refsect1>\n <title>$section</title>\n <para>\n";
                    417: #      print "<para>\n$section\n";
                    418:        if ($section =~ m/EXAMPLE/i) {
                    419:            print "<example><para>\n";
                    420:        }
                    421:        output_highlight($args{'sections'}{$section});
                    422: #      print "</para>";
                    423:        if ($section =~ m/EXAMPLE/i) {
                    424:            print "</para></example>\n";
                    425:        }
                    426:        print " </para>\n</refsect1>\n";
                    427:     }
                    428: 
                    429:     print "\n\n";
                    430: }
                    431: 
                    432: # output in sgml DocBook
                    433: sub output_gnome {
                    434:     my %args = %{$_[0]};
                    435:     my ($parameter, $section);
                    436:     my $count;
                    437:     my $id;
                    438: 
                    439:     $id = $args{'module'}."-".$args{'function'};
                    440:     $id =~ s/[^A-Za-z0-9]/-/g;
                    441: 
                    442:     print "<sect2>\n";
                    443:     print " <title id=\"$id\">".$args{'function'}."</title>\n";
                    444: 
                    445: #    print "<simplesect>\n";
                    446: #    print " <title>Synopsis</title>\n";
                    447:     print "  <funcsynopsis>\n";
                    448:     print "   <funcdef>".$args{'functiontype'}." ";
                    449:     print "<function>".$args{'function'}." ";
                    450:     print "</function></funcdef>\n";
                    451: 
                    452:     $count = 0;
                    453:     if ($#{$args{'parameterlist'}} >= 0) {
                    454:        foreach $parameter (@{$args{'parameterlist'}}) {
                    455:            print "   <paramdef>".$args{'parametertypes'}{$parameter};
                    456:            print " <parameter>$parameter</parameter></paramdef>\n";
                    457:        }
                    458:     } else {
                    459:        print "  <void>\n";
                    460:     }
                    461:     print "  </funcsynopsis>\n";
                    462: #    print "</simplesect>\n";
                    463: #    print "</refsect1>\n";
                    464: 
                    465:     # print parameters
                    466: #    print "<simplesect>\n <title>Arguments</title>\n";
                    467: #    if ($#{$args{'parameterlist'}} >= 0) {
                    468: #      print " <variablelist>\n";
                    469: #      foreach $parameter (@{$args{'parameterlist'}}) {
                    470: #          print "  <varlistentry>\n   <term><parameter>$parameter</parameter></term>\n";
                    471: #          print "   <listitem>\n    <para>\n";
                    472: #          $lineprefix="     ";
                    473: #          output_highlight($args{'parameters'}{$parameter});
                    474: #          print "    </para>\n   </listitem>\n  </varlistentry>\n";
                    475: #      }
                    476: #      print " </variablelist>\n";
                    477: #    } else {
                    478: #      print " <para>\n  None\n </para>\n";
                    479: #    }
                    480: #    print "</simplesect>\n";
                    481: 
                    482: #    print "<simplesect>\n <title>Arguments</title>\n";
                    483:     if ($#{$args{'parameterlist'}} >= 0) {
                    484:        print " <informaltable pgwide=\"1\" frame=\"none\" role=\"params\">\n";
                    485:        print "<tgroup cols=\"2\">\n";
                    486:        print "<colspec colwidth=\"2*\">\n";
                    487:        print "<colspec colwidth=\"8*\">\n";
                    488:        print "<tbody>\n";
                    489:        foreach $parameter (@{$args{'parameterlist'}}) {
                    490:            print "  <row><entry align=\"right\"><parameter>$parameter</parameter></entry>\n";
                    491:            print "   <entry>\n";
                    492:            $lineprefix="     ";
                    493:            output_highlight($args{'parameters'}{$parameter});
                    494:            print "    </entry></row>\n";
                    495:        }
                    496:        print " </tbody></tgroup></informaltable>\n";
                    497:     } else {
                    498:        print " <para>\n  None\n </para>\n";
                    499:     }
                    500: #    print "</simplesect>\n";
                    501: 
                    502:     # print out each section
                    503:     $lineprefix="   ";
                    504:     foreach $section (@{$args{'sectionlist'}}) {
                    505:        print "<simplesect>\n <title>$section</title>\n";
                    506: #      print "<para>\n$section\n";
                    507:        if ($section =~ m/EXAMPLE/i) {
                    508:            print "<example><programlisting>\n";
                    509:        } else {
                    510:        }
                    511:        print "<para>\n";
                    512:        output_highlight($args{'sections'}{$section});
                    513: #      print "</para>";
                    514:        print "</para>\n";
                    515:        if ($section =~ m/EXAMPLE/i) {
                    516:            print "</programlisting></example>\n";
                    517:        } else {
                    518:        }
                    519:        print " </simplesect>\n";
                    520:     }
                    521: 
                    522:     print "</sect2>\n\n";
                    523: }
                    524: 
                    525: # output in birddoc
                    526: sub output_bird {
                    527:     my %args = %{$_[0]};
                    528:     my ($parameter, $section);
                    529:     my $count;
                    530:     print "<function><p><type>".$args{'functiontype'}."</type>\n";
                    531:     print "<funcdef>".$args{'function'}."</funcdef>\n";
                    532:     print "(";
                    533:     $count = 0;
                    534:     my $ntyped = 0;
                    535:     foreach $parameter (@{$args{'parameterlist'}}) {
                    536:        if ($args{'parametertypes'}{$parameter} ne "") {
                    537:            print "<type>".$args{'parametertypes'}{$parameter}."</type> ";
                    538:            $ntyped++;
                    539:        }
                    540:        print "<param>".$parameter."</param>";
                    541:        if ($count != $#{$args{'parameterlist'}}) {
                    542:            $count++;
                    543:            print ", ";
                    544:        }
                    545:     }
                    546:     print ")";
                    547:     if ($args{'purpose'} ne "") {
                    548:        print " -- ";
                    549:        output_highlight($args{'purpose'});
                    550:     }
                    551:     print "\n";
                    552: 
                    553:     if ($ntyped) {
                    554:        print "<funcsect>Arguments\n";
                    555:        print "<p><descrip>\n";
                    556:        foreach $parameter (@{$args{'parameterlist'}}) {
                    557:            print "<tagp><type>".$args{'parametertypes'}{$parameter}."</type> <param>".$parameter."</param></tagp>\n";
                    558:            output_highlight($args{'parameters'}{$parameter});
                    559:        }
                    560:        print "</descrip>\n";
                    561:     }
                    562:     foreach $section (@{$args{'sectionlist'}}) {
                    563:        print "<funcsect>$section\n";
                    564:        print "<p>\n";
                    565:        output_highlight($args{'sections'}{$section});
                    566:     }
                    567:     print "</function>\n";
                    568: }
                    569: 
                    570: # output in birddoc
                    571: sub output_intro_bird {
                    572:     my %args = %{$_[0]};
                    573:     my ($parameter, $section);
                    574:     my $count;
                    575:     my $id;
                    576: 
                    577:     $id = $args{'module'};
                    578:     $id =~ s/[^A-Za-z0-9]/-/g;
                    579: 
                    580:     # print out each section
                    581:     $lineprefix="   ";
                    582:     foreach $section (@{$args{'sectionlist'}}) {
                    583:        print "<sect>$section\n<p>\n";
                    584:        output_highlight($args{'sections'}{$section});
                    585:     }
                    586: 
                    587:     print "\n\n";
                    588: }
                    589: 
                    590: ##
                    591: # output in man
                    592: sub output_man {
                    593:     my %args = %{$_[0]};
                    594:     my ($parameter, $section);
                    595:     my $count;
                    596: 
                    597:     print ".TH \"$args{'module'}\" \"$args{'function'}\" \"25 May 1998\" \"API Manual\" LINUX\n";
                    598: 
                    599:     print ".SH Function\n";
                    600: 
                    601:     print ".I \"".$args{'functiontype'}."\"\n";
                    602:     print ".B \"".$args{'function'}."\"\n";
                    603:     print "(\n";
                    604:     $count = 0;
                    605:     foreach $parameter (@{$args{'parameterlist'}}) {
                    606:        print ".I \"".$args{'parametertypes'}{$parameter}."\"\n.B \"".$parameter."\"\n";
                    607:        if ($count != $#{$args{'parameterlist'}}) {
                    608:            $count++;
                    609:            print ",\n";
                    610:        }
                    611:     }
                    612:     print ")\n";
                    613: 
                    614:     print ".SH Arguments\n";
                    615:     foreach $parameter (@{$args{'parameterlist'}}) {
                    616:        print ".IP \"".$args{'parametertypes'}{$parameter}." ".$parameter."\" 12\n";
                    617:        output_highlight($args{'parameters'}{$parameter});
                    618:     }
                    619:     foreach $section (@{$args{'sectionlist'}}) {
                    620:        print ".SH \"$section\"\n";
                    621:        output_highlight($args{'sections'}{$section});
                    622:     }
                    623: }
                    624: 
                    625: sub output_intro_man {
                    626:     my %args = %{$_[0]};
                    627:     my ($parameter, $section);
                    628:     my $count;
                    629: 
                    630:     print ".TH \"$args{'module'}\" \"$args{'module'}\" \"25 May 1998\" \"API Manual\" LINUX\n";
                    631: 
                    632:     foreach $section (@{$args{'sectionlist'}}) {
                    633:        print ".SH \"$section\"\n";
                    634:        output_highlight($args{'sections'}{$section});
                    635:     }
                    636: }
                    637: 
                    638: ##
                    639: # output in text
                    640: sub output_text {
                    641:     my %args = %{$_[0]};
                    642:     my ($parameter, $section);
                    643: 
                    644:     print "Function = ".$args{'function'}."\n";
                    645:     print "  return type: ".$args{'functiontype'}."\n\n";
                    646:     foreach $parameter (@{$args{'parameterlist'}}) {
                    647:        print " ".$args{'parametertypes'}{$parameter}." ".$parameter."\n";
                    648:        print "    -> ".$args{'parameters'}{$parameter}."\n";
                    649:     }
                    650:     foreach $section (@{$args{'sectionlist'}}) {
                    651:        print " $section:\n";
                    652:        print "    -> ";
                    653:        output_highlight($args{'sections'}{$section});
                    654:     }
                    655: }
                    656: 
                    657: sub output_intro_text {
                    658:     my %args = %{$_[0]};
                    659:     my ($parameter, $section);
                    660: 
                    661:     foreach $section (@{$args{'sectionlist'}}) {
                    662:        print " $section:\n";
                    663:        print "    -> ";
                    664:        output_highlight($args{'sections'}{$section});
                    665:     }
                    666: }
                    667: 
                    668: ##
                    669: # generic output function - calls the right one based
                    670: # on current output mode.
                    671: sub output_function {
                    672: #    output_html(@_);
                    673:     eval "output_".$output_mode."(\@_);";
                    674: }
                    675: 
                    676: ##
                    677: # generic output function - calls the right one based
                    678: # on current output mode.
                    679: sub output_intro {
                    680: #    output_html(@_);
                    681:     eval "output_intro_".$output_mode."(\@_);";
                    682: }
                    683: 
                    684: 
                    685: ##
                    686: # takes a function prototype and spits out all the details
                    687: # stored in the global arrays/hsahes.
                    688: sub dump_function {
                    689:     my $prototype = shift @_;
                    690: 
                    691:     $prototype =~ s/^static+ //;
                    692:     $prototype =~ s/^extern+ //;
                    693:     $prototype =~ s/^inline+ //;
                    694:     $prototype =~ s/^__inline__+ //;
                    695: 
                    696:     if ($prototype =~ m/^()([a-zA-Z0-9_~:]+)\s*\(([^\)]*)\)/ ||
                    697:        $prototype =~ m/^(\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\)]*)\)/ ||
                    698:        $prototype =~ m/^(\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\)]*)\)/ ||
                    699:        $prototype =~ m/^(\w+\s+\w+)\s+([a-zA-Z0-9_~:]+)\s*\(([^\)]*)\)/ ||
                    700:        $prototype =~ m/^(\w+\s+\w+\s*\*)\s*([a-zA-Z0-9_~:]+)\s*\(([^\)]*)\)/)  {
                    701:        $return_type = $1;
                    702:        $function_name = $2;
                    703:        $args = $3;
                    704: 
                    705: #      print STDERR "ARGS = '$args'\n";
                    706: 
                    707:        foreach $arg (split ',', $args) {
                    708:            # strip leading/trailing spaces
                    709:            $arg =~ s/^\s*//;
                    710:            $arg =~ s/\s*$//;
                    711: #          print STDERR "SCAN ARG: '$arg'\n";
                    712:            @args = split('\s', $arg);
                    713: 
                    714: #          print STDERR " -> @args\n";
                    715:            $param = pop @args;
                    716: #          print STDERR " -> @args\n";
                    717:            if ($param =~ m/^(\*+)(.*)/) {
                    718:                $param = $2;
                    719:                push @args, $1;
                    720:            }
                    721:            $type = join " ", @args;
                    722: 
                    723:            if ($type eq "" && $param eq "...")
                    724:            {
                    725:                $type="...";
                    726:                $param="...";
                    727:                $parameters{"..."} = "variable arguments";
                    728:            }
                    729:            if ($type eq "")
                    730:            {
                    731:                $type="";
                    732:                $param="void";
                    733:                $parameters{void} = "no arguments";
                    734:            }
                    735:             if ($parameters{$param} eq "") {
                    736:                $parameters{$param} = "-- undescribed --";
                    737:                print STDERR "Warning($lineno): Function parameter '$param' not described in '$function_name'\n";
                    738:            }
                    739: 
                    740:            push @parameterlist, $param;
                    741:            $parametertypes{$param} = $type;
                    742: #          print STDERR "param = '$param', type = '$type'\n";
                    743:        }
                    744:     } else {
                    745:        print STDERR "Error($lineno): cannot understand prototype: '$prototype'\n";
                    746:        return;
                    747:     }
                    748: 
                    749:     if ($function_only==0 || 
                    750:      ( $function_only == 1 && defined($function_table{$function_name})) || 
                    751:      ( $function_only == 2 && !defined($function_table{$function_name})))
                    752:     {
                    753:        output_function({'function' => $function_name,
                    754:                         'module' => $modulename,
                    755:                         'functiontype' => $return_type,
                    756:                         'parameterlist' => \@parameterlist,
                    757:                         'parameters' => \%parameters,
                    758:                         'parametertypes' => \%parametertypes,
                    759:                         'sectionlist' => \@sectionlist,
                    760:                         'sections' => \%sections,
                    761:                         'purpose' => $function_purpose
                    762:                         });
                    763:     }
                    764: }
                    765: 
                    766: ######################################################################
                    767: # main
                    768: # states
                    769: # 0 - normal code
                    770: # 1 - looking for function name
                    771: # 2 - scanning field start.
                    772: # 3 - scanning prototype.
                    773: $state = 0;
                    774: $section = "";
                    775: 
                    776: $doc_special = "\@\%\$\&";
                    777: 
                    778: $doc_start = "^/\\*\\*\$";
                    779: $doc_end = "\\*/";
                    780: $doc_com = "\\s*\\*\\s*";
                    781: $doc_func = $doc_com."(\\w+):?";
                    782: $doc_sect = $doc_com."([".$doc_special."]?[\\w ]+):(.*)";
                    783: $doc_content = $doc_com."(.*)";
                    784: $doc_block = $doc_com."DOC:\\s*(.*)?";
                    785: 
                    786: %constants = ();
                    787: %parameters = ();
                    788: @parameterlist = ();
                    789: %sections = ();
                    790: @sectionlist = ();
                    791: 
                    792: $contents = "";
                    793: $section_default = "Description";      # default section
                    794: $section_intro = "Introduction";
                    795: $section = $section_default;
                    796: 
                    797: $lineno = 0;
                    798: foreach $file (@ARGV) {
                    799:     if (!open(IN,"<$file")) {
                    800:        print STDERR "Error: Cannot open file $file\n";
                    801:        next;
                    802:     }
                    803:     while (<IN>) {
                    804:        $lineno++;
                    805: 
                    806:        if ($state == 0) {
                    807:            if (/$doc_start/o) {
                    808:                $state = 1;             # next line is always the function name
                    809:            }
                    810:        } elsif ($state == 1) { # this line is the function name (always)
                    811:            if (/$doc_block/o) {
                    812:                $state = 4;
                    813:                $contents = "";
                    814:                if ( $1 eq "" ) {
                    815:                        $section = $section_intro;
                    816:                } else {
                    817:                        $section = $1;
                    818:                }
                    819:             }
                    820:            elsif (/$doc_func/o) {
                    821:                $function = $1;
                    822:                $state = 2;
                    823:                if (/-(.*)/) {
                    824:                    $function_purpose = $1;
                    825:                } else {
                    826:                    $function_purpose = "";
                    827:                }
                    828:                if ($verbose) {
                    829:                    print STDERR "Info($lineno): Scanning doc for $function\n";
                    830:                }
                    831:            } else {
                    832:                print STDERR "WARN($lineno): Cannot understand $_ on line $lineno",
                    833:                " - I thought it was a doc line\n";
                    834:                $state = 0;
                    835:            }
                    836:        } elsif ($state == 2) { # look for head: lines, and include content
                    837:            if (/$doc_sect/o) {
                    838:                $newsection = $1;
                    839:                $newcontents = $2;
                    840: 
                    841:                if ($contents ne "") {
                    842: #                  $contents =~ s/\&/\\\\\\amp;/g;
                    843:                    $contents =~ s/\</\\\\\\lt;/g;
                    844:                    $contents =~ s/\>/\\\\\\gt;/g;
                    845:                    dump_section($section, $contents);
                    846:                    $section = $section_default;
                    847:                }
                    848: 
                    849:                $contents = $newcontents;
                    850:                if ($contents ne "") {
                    851:                    $contents .= "\n";
                    852:                }
                    853:                $section = $newsection;
                    854:            } elsif (/$doc_end/) {
                    855: 
                    856:                if ($contents ne "") {
                    857: #                  $contents =~ s/\&/\\\\\\amp;/g;
                    858:                    $contents =~ s/\</\\\\\\lt;/g;
                    859:                    $contents =~ s/\>/\\\\\\gt;/g;
                    860:                    dump_section($section, $contents);
                    861:                    $section = $section_default;
                    862:                    $contents = "";
                    863:                }
                    864: 
                    865: #          print STDERR "end of doc comment, looking for prototype\n";
                    866:                $prototype = "";
                    867:                $state = 3;
                    868:            } elsif (/$doc_content/) {
                    869:                # miguel-style comment kludge, look for blank lines after
                    870:                # @parameter line to signify start of description
                    871:                if ($1 eq "" && $section =~ m/^@/) {
                    872: #                  $contents =~ s/\&/\\\\\\amp;/g;
                    873:                    $contents =~ s/\</\\\\\\lt;/g;
                    874:                    $contents =~ s/\>/\\\\\\gt;/g;
                    875:                    dump_section($section, $contents);
                    876:                    $section = $section_default;
                    877:                    $contents = "";
                    878:                } else {
                    879:                    $contents .= $1."\n";
                    880:                }
                    881:            } else {
                    882:                # i dont know - bad line?  ignore.
                    883:                print STDERR "WARNING($lineno): bad line: $_"; 
                    884:            }
                    885:        } elsif ($state == 3) { # scanning for function { (end of prototype)
                    886:            if (m#\s*/\*\s+MACDOC\s*#io) {
                    887:              # do nothing
                    888:            }
                    889:            elsif (/([^\{]*)/) {
                    890:                $prototype .= $1;
                    891:            }
                    892:            if (/\{/) {
                    893:                $prototype =~ s@/\*.*?\*/@@gos; # strip comments.
                    894:                $prototype =~ s@[\r\n]+@ @gos; # strip newlines/cr's.
                    895:                $prototype =~ s@^ +@@gos; # strip leading spaces
                    896:                dump_function($prototype);
                    897: 
                    898:                $function = "";
                    899:                %constants = ();
                    900:                %parameters = ();
                    901:                %parametertypes = ();
                    902:                @parameterlist = ();
                    903:                %sections = ();
                    904:                @sectionlist = ();
                    905:                $prototype = "";
                    906: 
                    907:                $state = 0;
                    908:            }
                    909:        } elsif ($state == 4) {
                    910:                # Documentation block
                    911:                if (/$doc_block/) {
                    912: #                      $contents =~ s/\&/\\\\\\amp;/g;
                    913:                        $contents =~ s/\</\\\\\\lt;/g;
                    914:                        $contents =~ s/\>/\\\\\\gt;/g;
                    915:                        dump_section($section, $contents);
                    916:                        output_intro({'sectionlist' => \@sectionlist,
                    917:                                      'sections' => \%sections });
                    918:                        $contents = "";
                    919:                        $function = "";
                    920:                        %constants = ();
                    921:                        %parameters = ();
                    922:                        %parametertypes = ();
                    923:                        @parameterlist = ();
                    924:                        %sections = ();
                    925:                        @sectionlist = ();
                    926:                        $prototype = "";
                    927:                        if ( $1 eq "" ) {
                    928:                                $section = $section_intro;
                    929:                        } else {
                    930:                                $section = $1;
                    931:                        }
                    932:                 }
                    933:                elsif (/$doc_end/)
                    934:                {
                    935: #                      $contents =~ s/\&/\\\\\\amp;/g;
                    936:                        $contents =~ s/\</\\\\\\lt;/g;
                    937:                        $contents =~ s/\>/\\\\\\gt;/g;
                    938:                        dump_section($section, $contents);
                    939:                        output_intro({'sectionlist' => \@sectionlist,
                    940:                                      'sections' => \%sections });
                    941:                        $contents = "";
                    942:                        $function = "";
                    943:                        %constants = ();
                    944:                        %parameters = ();
                    945:                        %parametertypes = ();
                    946:                        @parameterlist = ();
                    947:                        %sections = ();
                    948:                        @sectionlist = ();
                    949:                        $prototype = "";
                    950:                        $state = 0;
                    951:                }
                    952:                elsif (/$doc_content/)
                    953:                {
                    954:                        if ( $1 eq "" )
                    955:                        {
                    956:                                $contents .= "\n";
                    957:                        }
                    958:                        else
                    959:                        {
                    960:                                $contents .= $1 . "\n";
                    961:                        }       
                    962:                }
                    963:           }
                    964:     }
                    965: }
                    966: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>