X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=docs%2Fexdoc;h=92027663e6d6f7244b55fdcf8fa4f33a05f504c8;hb=098e88f3a87205d92516a1fe912b6f84164d0a59;hp=517956c3e6387b07137055ee91f9d5f64b62c09d;hpb=ac229973136cd80c6ff5c7fee05a63b24e1bcad3;p=mono.git diff --git a/docs/exdoc b/docs/exdoc index 517956c3e63..92027663e6d 100644 --- a/docs/exdoc +++ b/docs/exdoc @@ -1,91 +1,295 @@ #!/usr/bin/perl -if ($ARGV[0] eq "-h"){ - $sourcedir = $ARGV[1]; - $dir = $sourcedir; - $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; } -open (FILE, "$dir/api-style.css" || die "Did not find $dir/api-style.css"); -while (){ - $css = $css . $_; + +# +# 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; } -if ($ARGV[0] eq "-t"){ - $dir = $ARGV[1]; - shift @ARGV; +# +# Extract documentation from all source files. +# +sub process_source_files { + my ($docs) = @_; + for my $file_path (@ARGV) { + process_source_file($file_path, $docs); + } } -if ($html){ - opendir (D, "$sourcedir/sources/") || die "Can not open $dir"; - while ($n = readdir (D)){ - if ($n =~ /mono-api-.*\.html$/){ - open (IN, "$sourcedir/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 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; } -while (){ - if (/\/\*\* *\n/){ - &process_doc; - } else { - #print "IGNORING: $_"; - } +# +# 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"; + } + } +} + +# +# 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]); - $strikeextra = ""; - $api_shown = 0; - for ($ai = 0; $ai < $#a; $ai++){ - $line = $a[$ai]; - - ($api,$caption) = $line =~ /

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

\n\n"; - if ($deprecated{$api}){ - $strike = "mapi-strike"; - $strikeextra = "
\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
@@ -98,228 +302,201 @@ EOF
$proto

EOF - $ppars = $arguments{$api}; - if ($ppars ne "" && (!($ppars =~ /^[ \t]+$/))){ - print OUT "

Parameters
\n"; - print OUT " ".${arguments{$api}}."
"; - } - - &opt_print ("Return value", $returns{$api}, 0); - &opt_print ("Description", $bodies{$api}, 0); - print OUT "
\n
\n"; - } else { - if ($line =~ /@API_IDX@/){ - $apis_toc = &create_toc ($apis[$f]); - $line =~ s/\@API_IDX\@/$apis_toc/; - } - if ($line =~ /^

\n"; - $api_shown = 0; - } - if ($line =~ /`/){ - } - print OUT "$line\n"; - } - } - print OUT< - - -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"; - - $line = 0; - $doprint = 0; - while (){ - print HACKOUT $last if ($doprint); - $line++; - s/^\/\/\/\///; - - # Remove the junk wrapper generated by AgilityPack - if ($line==1){ - s///; - } - if (/