X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=docs%2Fexdoc;h=92027663e6d6f7244b55fdcf8fa4f33a05f504c8;hb=HEAD;hp=e161a0c3d42ebbbe4362f555889af8a70b1b3ca4;hpb=4e5e61cf501ef587ec36aaf80d04d734ca0efaca;p=mono.git diff --git a/docs/exdoc b/docs/exdoc index e161a0c3d42..92027663e6d 100644 --- a/docs/exdoc +++ b/docs/exdoc @@ -1,293 +1,502 @@ #!/usr/bin/perl -if ($ARGV[0] eq "-h"){ - $dir = $ARGV[1]; - $html = 1; - shift @ARGV; - shift @ARGV; +use warnings; +use strict; + +use Getopt::Long; +use Pod::Usage; + +# Options +my $HELP = 0; +my $SOURCE_DIR = ''; +my $TARGET_DIR = ''; +my $WARNINGS = 0; + +GetOptions( + "help" => \$HELP, + "html|h=s" => \$SOURCE_DIR, + "target|t=s" => \$TARGET_DIR, + "warnings|W" => \$WARNINGS, +) or pod2usage(1); + +pod2usage(0) if $HELP; + +exdoc(); + +# +# Main entry point. +# +sub exdoc { + my %templates = (); + my %docs = (); + my $stylesheet = load_stylesheet($SOURCE_DIR); + load_templates($SOURCE_DIR, \%templates); + process_source_files(\%docs); + merge(\%docs, \%templates, \$stylesheet); +} + +# +# Load CSS stylesheet. +# +sub load_stylesheet { + my ($dir_path) = @_; + my $file_path = "$dir_path/api-style.css"; + open (my $file, '<', $file_path) or die "Could not open $file_path"; + local $/; + my $contents = <$file>; + close $file; + return $contents; +} + +# +# Load HTML templates. +# +sub load_templates { + my ($dir_path, $templates) = @_; + opendir (my $dir, "$dir_path/sources/") or die "Could not open $dir_path"; + while (my $file_name = readdir ($dir)) { + next if $file_name !~ /mono-api-.*\.html$/; + open (my $file, "$dir_path/sources/$file_name") or die "Could not open $file_name"; + my $contents = ''; + my @api = (); + while (<$file>) { + $contents .= $_; + if (/name="api:(.*?)"/) { + s/.*name="api:(\w+?)".*/$1/; + push @api, $_; + } + } + close $file; + $templates->{$file_name}->{contents} = $contents; + $templates->{$file_name}->{api} = \@api; + } + closedir $dir; +} + +# +# Extract documentation from all source files. +# +sub process_source_files { + my ($docs) = @_; + for my $file_path (@ARGV) { + process_source_file($file_path, $docs); + } +} + +# +# Extract documentation from a single source file. +# +sub process_source_file { + my ($file_path, $docs) = @_; + open (my $file, '<', $file_path) or die "Could not open $file_path"; + while (<$file>) { + next if (!/\/\*\* *\n/); + process_function($file, $file_path, $docs); + } + close $file; } -if ($html){ - opendir (D, "$dir/sources/") || die "Can not open $dir"; - while ($n = readdir (D)){ - if ($n =~ /mono-api-.*\.html$/){ - open (IN, "$dir/sources/$n") || die "Can not open $n"; - $files[$filecount] = $n; - while (){ - @files_content[$filecount] .= $_; - if (/name="api:(.*?)"/){ - $_ =~ s/.*name="api:(\w+?)".*/\1/; - $apis[$filecount] .= "$_"; - } - } - $filecount++; - close IN; - } +# +# Extract documentation from a single function. +# +sub process_function { + + my ($file, $file_path, $docs) = @_; + + my $PARAMETER_SECTION = 0; + my $BODY_SECTION = 1; + my $RETURN_SECTION = 2; + my $section = $PARAMETER_SECTION; + + my $name = do { + $_ = <$file>; + chomp; + s/^ \* //; + s/:$//; + $_ + }; + + # Ignore irrelevant functions, and those with the wrong doc format. + return if $name !~ /^mono_\w+$/; + + my $deprecated; + my @parameters = (); + my $body = ''; + my $returns = ''; + my $prototype = ''; + + while (<$file>) { + + # We've reached the last line in the documentation block. + if (/^ \*\*?\//) { + + # Grab function prototype. + while (<$file>) { + $prototype .= $_; + last if /\{/; + } + + # Clean up prototype. + $prototype = do { + $_ = $prototype; + # Strip braces and trailing whitespace. + s/{//; + s/ +$//; + # Turn "Type * xxx" into "Type* xxx" + s/^(\w+)\W+\*/$1*/; + $_; + }; + + # Process formatting within sections. + for my $parameter (@parameters) { + process_formatting(\$parameter->{description}, $file_path, $.); + } + process_formatting(\$returns, $file_path, $.); + process_formatting(\$body, $file_path, $.); + if (defined($deprecated)) { + process_formatting(\$deprecated, $file_path, $.); + } + $body =~ s/\n/ /g; + + if (exists($docs->{body}->{$name})) { + my $origin = $docs->{origin}->{$name}; + if ($WARNINGS) { + warn + "$file_path:$.: Redundant documentation for $name\n", + "$origin->{file}:$origin->{line}: Previously defined here\n"; + } + } + $docs->{origin}->{$name} = { file => $file_path, line => $. }; + $docs->{body}->{$name} = $body; + $docs->{parameters}->{$name} = \@parameters; + $docs->{deprecated}->{$name} = $deprecated if defined $deprecated; + $docs->{return}->{$name} = $returns; + $docs->{prototype}->{$name} = $prototype; + last; + + } + + # Strip newlines and asterisk prefix. + chomp; + s/^ +\*//; + + # Replace blank lines with paragraph breaks. + $_ = '

' if /^\s*$/; + + if ($section == $PARAMETER_SECTION) { + if (/\s*\\param +(\w+)(.*)/) { + # print "$file_path:$.: warning: Got parameter $1\n"; + push @parameters, { name => $1, description => $2 }; + } elsif (/\s*\\deprecated(.*)/) { + # print "$file_path:$.: warning: Got deprecated annotation\n"; + $deprecated = $1; + } elsif (/\s*(\w+):(.*)/) { + if ($1 eq 'deprecated') { + warn "$file_path:$.: Old-style monodoc notation 'deprecated:' used\n" + if $WARNINGS; + $deprecated = $2; + } else { + warn "$file_path:$.: Old-style monodoc notation 'param:' used\n" + if $WARNINGS; + push @parameters, { name => $1, description => $2 }; + } + } else { + # $body = "\t$_\n"; + $section = $BODY_SECTION; + redo; + } + } elsif ($section == $BODY_SECTION) { + if (s/(Returns?:\s*|\\returns?\s*)//) { + $returns = "\t$_\n"; + $section = $RETURN_SECTION; + } else { + $body .= "\n\t$_"; + } + } elsif ($section == $RETURN_SECTION) { + $returns .= "\n\t$_"; + } else { + die "Invalid section $section\n"; + } } } -while (){ - if (/\/\*\* *\n/){ - &process_doc; - } else { - #print "IGNORING: $_"; - } +# +# Substitute formatting within documentation text. +# +sub process_formatting { + my ($content, $file_path, $current_line) = @_; + $_ = $$content; + + # Constants + s{NULL}{NULL}g; + s{TRUE}{TRUE}g; + s{FALSE}{FALSE}g; + + # Parameters + warn "$file_path:$current_line: Old-style monodoc notation '\@param' used\n" + if s{@(\w+)}{$1}g && $WARNINGS; + s{\\p +(\w+)}{$1}g; + + # Code + warn "$file_path:$current_line: Old-style monodoc notation '#code' used\n" + if s{#(\w+)}{$1}g && $WARNINGS; + warn "$file_path:$current_line: Old-style monodoc notation '`code`' used\n" + if s{\`((?!api:)[:.\w\*]+)\`}{$1}g && $WARNINGS; + s{\\c +(\S+(?$1}g; + + $$content = $_; } -if ($html){ - for ($f = 0; $f < $filecount; $f++){ - $name = $files[$f]; - open (OUT, "> $dir/html/$name") || die "Can not create $dir/html/$name"; - print "Merging: $name\n"; - print OUT<', "$TARGET_DIR/html/$name") + or die "Could not create $TARGET_DIR/html/$name"; + print "Merging: $name\n"; + print $output_file < - $name - +

EOF - @a = split (/\n/, $files_content[$f]); - - for ($ai = 0; $ai < $#a; $ai++){ - $line = $a[$ai]; - - ($api,$caption) = $line =~ /

(\w+)<\/a><\/h4>/; - if ($api ne ""){ - if ($api_shown == 1){ - print OUT "

"; - } - $api_shown = 1; - $proto = $prototype{$api}; - if ($proto eq ""){ - $proto = "Prototype: $api"; - } - -print OUT< -
-
$api
- -
$proto
-

-EOF - &opt_print ("Parameters", $arguments{$api}, 1); - &opt_print ("Returns", $returns{$api}, 1); - &opt_print ("Remarks", $bodies{$api}, 0); - print OUT "\n"; - } else { - if ($line =~ /@API_IDX@/){ - $apis_toc = &create_toc ($apis[$f]); - $line =~ s/\@API_IDX\@/$apis_toc/; - } - if ($line =~ /^"; - $api_shown = 0; - } - - print OUT "$line\n"; - } - } - print OUT< - + my @a = split (/\n/, $templates->{$name}->{contents}); + my $strike = ''; + my $strikeextra = ''; + my $api_shown = 0; + for (my $ai = 0; $ai < $#a; $ai++) { + my $line = $a[$ai]; + if (my ($api, $caption) = ($line =~ /

(\w+)<\/a><\/h4>/)) { + if ($api_shown == 1) { + print $output_file "

\n\n"; + if ($docs->{deprecated}->{$api}) { + $strike = "mapi-strike"; + $strikeextra = "
Deprecated: " . $docs->{deprecated}->{$api}; + } else { + $strike = ""; + $strikeextra = ""; + } + } + $api_shown = 1; + my $proto = $docs->{prototype}->{$api} // $api; + + print $output_file < +
+
$api$strikeextra
+
+
+
+
+ +
Syntax
+
$proto
+

EOF - close OUT; - system ("$ENV{runtimedir}/mono-wrapper convert.exe $dir/html/$name $dir/html/x-$name"); - - # clean up the mess that AgilityPack does, it CDATAs our CSS - open HACK, "$dir/html/x-$name" || die "Could not open $dir/html/x-$name"; - open HACKOUT, ">$dir/deploy/$name" || die "Could not open output"; - - while (){ - s/^\/\/\/\///; - print HACKOUT $_; - } - #system ("cp.exe $dir/html/$name $dir/deploy/$name"); - } -} + if (exists ($docs->{parameters}->{$api})) { + my $ppars = $docs->{parameters}->{$api}; + if (@$ppars) { + print $output_file + "

Parameters
\n", + " ", + render_parameters($ppars), + "
"; + } + } -sub process_doc { - $doc = ""; - $func = <>; - chop $func; - $func =~ s/^ \* //; - $func =~ s/:$//; - print "Function: $func\n" if (!$html); - $args = ""; - $inbody = 0; - $returns = ""; - $body = ""; - $functions[$fn++] = $func; - - # Process arguments - while (<>){ - if (/^ \*\*?\//){ - $body =~ s/[@#](\w+)/\1<\/i>/g; - $returns =~ s/[@#](\w+)/\1<\/i>/g; - - $args =~ s/@(\w+)/\1<\/i>/g; - $body =~ s/\n/ /; - $bodies{$func} = $body; - $arguments{$func} = $args; - $returns{$func} = $returns; - $proto = ""; - while (<>){ - $proto .= $_; - last if (/\{/); - } - $proto =~ s/{//; - # clean it up a little, remove newlines, empty space at end - $proto =~ s/ +$//; - # Turn "Type * xxx" into "Type* xxx" - $proto =~ s/^(\w+)\W+\*/\1\*/; - $prototype{$func} = $proto; - return; - } - chop; - s/^\ \*//; - $_ = "\n

" if (/^\s+$/); - - if ($inbody == 0){ - if (/\s*(\w+):(.*)/){ - $args .= "

$1:
$2
"; - } else { - - $body = "\t$_\n"; - $inbody = 1; - } - } elsif ($inbody == 1) { - if (/Returns?:/){ - s/Returns?://; - $returns = "\t$_\n"; - $inbody = 2; - } else { - $body .= "\n\t$_"; - } - } else { - $returns .= "\n\t$_"; - } - - } + opt_print ($output_file, "Return value", $docs->{return}->{$api}); + opt_print ($output_file, "Description", $docs->{body}->{$api}); + print $output_file "
\n
\n"; + } else { + if ($line =~ /\@API_IDX\@/) { + my $apis_toc = create_toc ($docs, $templates->{$name}->{api}); + $line =~ s/\@API_IDX\@/$apis_toc/; + } + if ($line =~ /^

\n"; + $api_shown = 0; + } + if ($line =~ /`/) { + } + print $output_file "$line\n"; + } + } + print $output_file + "

", + "", + ""; + close $output_file; + system ("$ENV{runtimedir}/mono-wrapper convert.exe $TARGET_DIR/html/$name $TARGET_DIR/html/x-$name"); + + # Clean up the mess that AgilityPack makes (it CDATAs our CSS). + open (my $hack_input, '<', "$TARGET_DIR/html/x-$name") + or die "Could not open $TARGET_DIR/html/x-$name"; + open (my $hack_output, '>', "$TARGET_DIR/deploy/$name") + or die "Could not open output"; + + my $line = 0; + my $doprint = 0; + while (<$hack_input>) { + print $hack_output $last if ($doprint); + $line++; + s/^\/\/\/\///; + + # Remove the junk wrapper generated by AgilityPack. + if ($line==1) { + s///; + } + if (/