1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
|
#!/usr/bin/env perl
# Copyright (c) 2010-2015, Daniel S. Standage and CONTRIBUTORS
#
# The AEGeAn Toolkit is distributed under the ISC License. See
# the 'LICENSE' file in the AEGeAn source code distribution or
# online at https://github.com/standage/AEGeAn/blob/master/LICENSE.
#
# Usage: perl build-docs.pl inc/core inc/ParsEval > docs/api.rst
use strict;
use warnings;
use Getopt::Long;
print "AEGeAn C API\n============\n\nThe AEGeAn Toolkit relies heavily on data
types implemented by the GenomeTools library. For data types beginning with
``Gt``, see the GenomeTools API documentation at
http://genometools.org/libgenometools.html.\n\n";
# Main procedure
my $dir;
foreach my $dirname(@ARGV)
{
$dir = $dirname;
opendir(my $dh, $dir) or die("open dir fail");
while(my $entry = readdir($dh))
{
make_docs_from_file("$dir/$entry") if($entry =~ m/\.h$/);
}
closedir($dh);
}
# Generate class or module documentation from a header file
sub make_docs_from_file
{
my $file = shift(@_);
my $contents = do
{
local $/;
open(my $fh, "<", $file) or die("open file fail: $file");
<$fh>;
};
my @docblocks = $contents =~ m/(\/\*\*.+?\*\/.+?;)/sg;
return if(@docblocks == 0);
process_doc_blocks(@docblocks);
}
# Process a set of doc blocks from a class/module header file
sub process_doc_blocks
{
my $summary = shift(@_);
do {} while($summary =~ s/\s+\*\s+/ /g);
if($summary =~ m/\@class/)
{
my($class, $description) = $summary =~ m/\/\*\* \@class (\S+) (.+)/;
my $title = "Class $class";
my $url = "https://github.com/standage/AEGeAn/blob/master/$dir/$class.h";
printf("%s\n%s\n\n", $title, "-" x length($title));
printf(".. c:type:: %s\n\n %s See the `%s class header <%s>`_.\n\n",
$class, $description, $class, $url);
foreach my $block(@_)
{
process_doc_block($block);
}
}
elsif($summary =~ m/\@module/)
{
my($module, $description) = $summary =~ m/\/\*\* \@module (\S+) (.+)/;
my $title = "Module $module";
my $url = "https://github.com/standage/AEGeAn/blob/master/$dir/$module.h";
printf("%s\n%s\n\n", $title, "-" x length($title));
printf("%s See the `%s module header <%s>`_.\n\n", $description, $module,
$url);
foreach my $block(@_)
{
process_doc_block($block);
}
}
else
{
die("class/module fail");
}
}
# Process the doc block corresponding to an individual function or type def
sub process_doc_block
{
my $block = shift(@_);
$block =~ s/\/\*\*\W+//s;
my($type) = $block =~ m/(function|functype|type)/;
die("block type fail") unless($type);
$block =~ s/(function|functype|type) *//;
my($synopsis) = $block =~ m/^(.+?)(\@param|\@member|\*\/)/s;
$synopsis =~ s/\*//g;
$synopsis =~ s/\s+/ /sg;
$synopsis =~ s/\s+$//;
if($type eq "function")
{
my($prototype) = $block =~ m/\*\/\s*(\w[^;]+);/;
$prototype =~ s/\s+/ /sg;
print(".. c:function:: $prototype\n\n $synopsis\n\n");
}
elsif($type eq "type")
{
my($typetype, $typename) = $block =~ m/(struct|enum) (Agn\S+)/;
print(".. c:type:: $typename\n\n $synopsis\n\n");
my @members = $block =~ m/\@member (.+)/g;
foreach my $member(@members)
{
my($mtype, $mname, $mdesc) = $member =~ m/\[(.+)\] (\S+) (.+)/;
print(" * **$mtype $mname**: $mdesc\n");
}
print("\n\n");
}
elsif($type eq "functype")
{
my($signature) = $block =~ m/\*\/\s*(\w[^;]+);/;
$signature =~ s/\s+/ /sg;
print(".. c:type:: $signature\n\n $synopsis\n\n");
}
else
{
die("block type fail");
}
}
|