#!/usr/bin/perl if ($ARGV[0] eq "-h"){ $sourcedir = $ARGV[1]; $dir = $sourcedir; $html = 1; shift @ARGV; shift @ARGV; } if ($ARGV[0] eq "-t"){ $dir = $ARGV[1]; shift @ARGV; } 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 (<IN>){ @files_content[$filecount] .= $_; if (/name="api:(.*?)"/){ $_ =~ s/.*name="api:(\w+?)".*/\1/; $apis[$filecount] .= "$_"; } } $filecount++; close IN; } } } while (<ARGV>){ if (/\/\*\* *\n/){ &process_doc; } else { #print "IGNORING: $_"; } } 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<<EOF; <?xml version="1.0" encoding="utf-8"?> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>$name</title> <style type="text/css"> h3 { font-size: 18px; padding-bottom: 4pt; border-bottom: 2px solid #dddddd; } .api { border: 1px solid; padding: 10pt; margin: 10pt; } .api-entry { border-bottom: none; font-size: 18px; } .prototype { border: 1px solid; background-color: #f2f2f2; padding: 5pt; margin-top: 5pt; margin-bottom: 5pt; } .header { border: 1px solid; padding: 0 0 5pt 5pt; margin: 10pt; white-space: pre; font-family: monospace; } .code { border: 1px solid; padding: 0 0 5pt 5pt; margin: 10pt; white-space: pre; font-family: monospace; } </style> </head> <body> EOF @a = split (/\n/, $files_content[$f]); for ($ai = 0; $ai < $#a; $ai++){ $line = $a[$ai]; ($api,$caption) = $line =~ /<h4><a name=\"api:(\w+)\">(\w+)<\/a><\/h4>/; if ($api ne ""){ if ($api_shown == 1){ print OUT "</div>"; } $api_shown = 1; $proto = $prototype{$api}; if ($proto eq ""){ $proto = "Prototype: $api"; } print OUT<<EOF; <a name="api:$api"></a> <div class="api"> <div class="api-entry">$api</div> <div class="prototype">$proto</div> <p> 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 =~ /^<h/){ print OUT "</div>"; $api_shown = 0; } print OUT "$line\n"; } } print OUT<<EOF; </body> </html> 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 (<HACK>){ s/^\/\/<!\[CDATA\[//; s/^\/\/\]\]>\/\///; print HACKOUT $_; } #system ("cp.exe $dir/html/$name $dir/deploy/$name"); } } 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+)/<i>\1<\/i>/g; $returns =~ s/[@#](\w+)/<i>\1<\/i>/g; $args =~ s/@(\w+)/<i>\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<p>" if (/^\s+$/); if ($inbody == 0){ if (/\s*(\w+):(.*)/){ $args .= "<dt><i>$1:</i></dt><dd>$2</dd>"; } 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$_"; } } } sub create_toc { my ($apis_listed) = @_; my $type_size = 0; my $name_size = 0; my $ret, $xname, $args, $line; $apis_toc = ""; # Try to align things, so compute type size, method size, and arguments foreach $line (split /\n/, $apis_listed){ $p = $prototype{$line}; ($ret, $xname, $args) = $p =~ /(.*)\n(\w+)[ \t](.*)/; $tl = length ($ret); $pl = length ($xname); $type_size = $tl if ($tl > $type_size); $name_size = $pl if ($pl > $name_size); } $type_size++; $name_size++; foreach $line (split /\n/, $apis_listed){ chop; $p = $prototype{$line}; ($ret, $xname, $args) = $p =~ /(.*)\n(\w+)[ \t](.*)/; $rspace = " " x ($type_size - length ($ret)); $nspace = " " x ($name_size - length ($xname)); $args = &format ($args, length ($ret . $rspace . $xname . $nspace), 60); $apis_toc .= "$ret$rspace<a href=\"\#api:$line\">$xname</a>$nspace$args\n"; } return $apis_toc; } # # Formats the rest of the arguments in a way that will fit in N columns # sub format { my ($args, $size, $limit) = @_; my $sret = ""; # return $args if ((length (args) + size) < $limit); $remain = $limit - $size; @sa = split /,/, $args; $linelen = $size; foreach $arg (@sa){ if ($sret eq ""){ $sret = $arg . ", "; $linelen += length ($sret); } else { if ($linelen + length ($arg) < $limit){ $sret .= "FITS" . $arg . ", "; } else { $newline = " " x ($size) . $arg . ", "; $linelen = length ($newline); $sret .= "\n" . $newline; } } } $sret =~ s/, $/;/; return $sret; } sub opt_print { my ($caption, $opttext, $quote) = @_; if ($opttext ne "" && (!($opttext =~ /^[ \t]+$/))){ print OUT "<b>$caption</b>\n"; if ($quote == 1){ print OUT "<blockquote>$opttext</blockquote>\n"; } else { print OUT "<p>$opttext\n"; } } }