#!/usr/bin/perl
# follow javadoc
# @see http://java.sun.com/j2se/javadoc/writingdoccomments/
use strict;
=cut
這個程式可以從 C 的程式碼中,列出所有 statis/non-static 的 functions。
每個 function 前面可以有 javadoc-style 的註解。範例如下:
/**
* Function of the function func.
* @param x variable, if there are more than one @-style description, it
* will end with the next @-style description.
* @return void
*/
void func(int x)
{
...
}
如果有註解之後沒有接 function 的話,會原封不動丟出來。
=cut
my $content;
foreach my $f (@ARGV) {
makedoc($f);
}
sub grep_desc
{
my @buffer = ();
my $name = '\b\w+\b';
my $type = '\b (?: (?:struct|unsigned) \s+)? \w+\b (?: \s*\*\s* | \s+)';
my $sentence = '.*';
my $one_desc = "$name\\s+$sentence";
my $desc_head = "\\/ \\* \\* \n";
my $desc_tail = "\\s* \\* \\/ \n";
my $desc_line = "\\s* \\* .* \n";
my $paramdesc = "\@param\\s+ $one_desc (?:\n$desc_line)*";
my $returndesc = "\@return\\s+ $sentence (?:\n$desc_line)*";
my $seedesc = "\@see\\s+ $sentence (?:\n$desc_line)*";
my $desc = "$desc_head(?:$desc_line)*$desc_tail";
my $modifier = '(?: static | inline)\s+';
my $one_param = "$type \\s* $name";
my $more_param = ",\\s* $one_param";
my $param = "(?: $one_param(?:$more_param)* | void )?";
my $func_proto = "(?:$modifier)* $type \\s* $name\\($param\\)";
my $pattern = "(?: ($desc)|($func_proto)[\n\\s]*{ )";
my $out;
if ($content =~ s/^([.\n]*)$pattern//mox) {
$1 and push @buffer, {type => 'garbage', data => undef};
if ($2) {
$out = $2;
$out =~ s#^/\*\*##;
$out =~ s#\s*\*/$##;
$out =~ s/^\s*\* ?/ /mg;
push @buffer, { type => 'comment', data => $out };
}
elsif ($3) {
$out = $3;
$out =~ s/\n/ /g;
$out =~ s/\s+/ /g;
$out .= ";\n";
push @buffer, { type => 'function', data => $out };
}
else {
die;
}
}
return @buffer;
}
sub makedoc
{
my $file = shift @_;
open SRC, "<$file";
$content = join "",<SRC>;
close SRC;
# just to break them up to avoid vim's misunderstanding
print "// vim".":ft=c\n\n";
$content =~ s#/\*[^*].*?\*/##sg;
my @buffer = ();
while (my @b = grep_desc()) {
push @buffer, @b;
shift @buffer while ($buffer[0]->{type} eq 'garbage');
last unless @buffer;
if (@buffer == 3) {
if ($buffer[1]->{type} eq 'garbage') {
$_ = shift @buffer;
shift @buffer;
unshift @buffer, $_;
}
}
if (@buffer == 2) {
if ($buffer[0]->{type} eq 'function') {
$_ = shift @buffer;
print $/, $_->{data};
}
elsif ($buffer[0]->{type} eq 'comment') {
if ($buffer[1]->{type} eq 'comment') {
$_ = shift @buffer;
print $_->{data}, $/;
}
else {
print $/, $buffer[1]->{data}, $buffer[0]->{data}, $/;
undef @buffer;
}
}
}
if (@buffer == 1) {
if ($buffer[0]->{type} eq 'function') {
$_ = shift @buffer;
print $/, $_->{data};
}
}
}
}