[Docs] Use an external style sheet, prefix the css classes with mapi to isolate,...
[mono.git] / docs / exdoc
1 #!/usr/bin/perl
2
3 if ($ARGV[0] eq "-h"){
4     $sourcedir = $ARGV[1];
5     $dir = $sourcedir;
6     $html = 1;
7     shift @ARGV;
8     shift @ARGV;
9 }
10 open (FILE, "$dir/api-style.css" || die "Did not find $dir/api-style.css");
11 while (<FILE>){
12     $css = $css . $_;
13 }
14
15 if ($ARGV[0] eq "-t"){
16     $dir = $ARGV[1];
17     shift @ARGV;
18 }
19
20 if ($html){
21     opendir (D, "$sourcedir/sources/") || die "Can not open $dir";
22     while ($n = readdir (D)){
23         if ($n =~ /mono-api-.*\.html$/){
24             open (IN, "$sourcedir/sources/$n") || die "Can not open $n";
25             $files[$filecount] = $n;
26             while (<IN>){
27                 @files_content[$filecount] .= $_;
28                 if (/name="api:(.*?)"/){
29                     $_ =~ s/.*name="api:(\w+?)".*/\1/;
30                     $apis[$filecount] .= "$_";
31                 }
32             }
33             $filecount++;
34             close IN;
35         }
36     }
37 }
38
39 while (<ARGV>){
40         if (/\/\*\* *\n/){
41                 &process_doc;
42         } else {
43                 #print "IGNORING: $_";
44         }
45 }
46
47 if ($html){
48     for ($f = 0; $f < $filecount; $f++){
49         $name = $files[$f];
50         open (OUT, "> $dir/html/$name") || die "Can not create $dir/html/$name";
51         print "Merging: $name\n";
52         print OUT<<EOF;
53 <?xml version="1.0" encoding="utf-8"?>
54 <html xmlns="http://www.w3.org/1999/xhtml">
55 <head>
56     <title>$name</title>
57     <style type="text/css">
58 $css
59    </style>
60 </head>
61 <body>
62 <div class="mapi-docs">
63 EOF
64         @a = split (/\n/, $files_content[$f]);
65         $strikeextra = "";
66         for ($ai = 0; $ai < $#a; $ai++){
67             $line = $a[$ai];
68             
69             ($api,$caption) = $line =~  /<h4><a name=\"api:(\w+)\">(\w+)<\/a><\/h4>/;
70             if ($api ne ""){
71                 if ($api_shown == 1){
72                     print OUT "</div> <!-- class=mapi -->\n\n";
73                     if ($deprecated{$api}){
74                         $strike = "mapi-strike";
75                         $strikeextra = "</div><br><div class='mapi-deprecated'><b>Deprecated:</b> " . $deprecated{$api};
76                     } else {
77                         $strike = "";
78                         $strikeextra = "";
79                     }
80                 }
81                 $api_shown = 1;
82                 $proto = $prototype{$api};
83                 if ($proto eq ""){
84                     $proto = "$api";
85                 }
86
87                 print OUT<<EOF;
88 <a name="api:$api"></a>
89 <div class="mapi">
90     <div class="mapi-entry $strike"><code>$api$strikeextra</code></div>
91     <div class="mapi-height-container">
92         <div class="mapi-ptr-container"></div>
93         <div class="mapi-description">
94             <div class="mapi-ptr"></div>
95
96             <div class="mapi-declaration mapi-section">Syntax</div>
97             <div class="mapi-prototype">$proto</div>
98             <p>
99 EOF
100                 $ppars = $arguments{$api};
101                 if ($ppars ne "" && (!($ppars =~ /^[ \t]+$/))){
102                     print OUT "            <div class=\"mapi-section\">Parameters</div>\n";
103                     print OUT "            <table class=\"mapi-parameters\"><tbody>".${arguments{$api}}."</tbody></table>";
104                 }
105             
106                 &opt_print ("Return value", $returns{$api}, 0);
107                 &opt_print ("Description", $bodies{$api}, 0);
108                 print OUT "        </div><!--mapi-description-->\n    </div><!--height container-->\n";
109             } else {
110                 if ($line =~ /@API_IDX@/){
111                     $apis_toc = &create_toc ($apis[$f]);
112                     $line =~ s/\@API_IDX\@/$apis_toc/;
113                 }
114                 if ($line =~ /^<h4/){
115                     print OUT "</div>\n";
116                     $api_shown = 0;
117                 }
118                 if ($line =~ /`/){
119                 }
120                 print OUT "$line\n";
121             }
122         }
123         print OUT<<EOF;
124    </div>
125 </body>
126 </html>
127 EOF
128         close OUT;
129         system ("$ENV{runtimedir}/mono-wrapper convert.exe $dir/html/$name $dir/html/x-$name");
130
131
132         # clean up the mess that AgilityPack does, it CDATAs our CSS
133         open HACK, "$dir/html/x-$name" || die "Could not open $dir/html/x-$name";
134         open HACKOUT, ">$dir/deploy/$name" || die "Could not open output";
135
136         $line = 0;
137         while (<HACK>){
138             $line++;
139             s/^\/\/<!\[CDATA\[//;
140             s/^\/\/\]\]>\/\///;
141
142             # Remove the junk <span> wrapper generated by AgilityPack
143             if ($line==1){
144                 s/<?span>//;
145             }
146             if (/<style type/){
147                 # Replace the CSS in the XHTML output with the original CSS
148                 print HACKOUT $_;
149                 print HACKOUT $css;
150                 while (<HACK>){
151                     last if (/<\/style>/);
152                 }
153             }
154
155             print HACKOUT $_;
156         }
157         #system ("cp.exe $dir/html/$name $dir/deploy/$name");
158     }
159 }
160
161 sub process_doc {
162         $doc = "";
163         $func = <>;
164         chop $func;
165         $func =~ s/^ \* //;
166         $func =~ s/:$//;
167         print "Function: $func\n" if (!$html);
168         $args = "";
169         $inbody = 0;
170         $returns = "";
171         $body = "";
172         $functions[$fn++] = $func;
173         $deprecated = 0;
174         
175         # Process arguments
176         while (<>){
177             s/NULL/<code>NULL<\/code>/g;
178             s/TRUE/<code>TRUE<\/code>/g;
179             s/FALSE/<code>FALSE<\/code>/g;
180             if (/^ \*\*?\//){
181                     $body =~ s/@(\w+)/<i>\1<\/i>/g;
182                     $returns =~ s/@(\w+)/<i>\1<\/i>/g;
183                     $args =~ s/@(\w+)/<i>\1<\/i>/g;
184
185                     $body =~ s/#(\w+)/<code>\1<\/code>/g;
186                     $returns =~ s/#(\w+)/<code>\1<\/code>/g;
187                     $args =~ s/#(\w+)/<code>\1<\/code>/g;
188
189                     $returns =~ s/\`([:\w\*]+)\`/<code>\1<\/code>/g;
190                     $args =~ s/\`([:\w\*]+)\`/<code>\1<\/code>/g;
191                     $body =~ s/\`([:\w\*]+)\`/<code>\1<\/code>/g;
192                     
193                     $body =~ s/\n/ /;
194                     $bodies{$func} = $body;
195                     $arguments{$func} = $args;
196                     $deprecated{$func} = $deprecated;
197                     $returns{$func} = $returns;
198                     $proto = "";
199                     while (<>){
200                         $proto .= $_;
201                         last if (/\{/);
202                     }
203                     $proto =~ s/{//;
204                     # clean it up a little, remove newlines, empty space at end
205                     $proto =~ s/ +$//;
206                     # Turn "Type * xxx" into "Type* xxx"
207                     $proto =~ s/^(\w+)\W+\*/\1\*/;
208                     $prototype{$func} = $proto;
209                     return;
210                 }
211                 chop;
212                 s/^\ \*//;
213                 $_ = "\n<p>" if (/^\s+$/);
214                                 
215                 if ($inbody == 0){
216                     if (/\s*(\w+):(.*)/){
217                         if ($1 eq "deprecated"){
218                             $deprecated = $2;
219                         } else {
220                             #$args .= "<dt><i>$1:</i></dt><dd>$2</dd>";
221                             $args .= "<tr><td><i>$1</i><td>$2</td></td></tr>";
222                         }
223                     } else {
224                         
225                         $body = "\t$_\n";
226                         $inbody = 1;
227                     }
228                 } elsif ($inbody == 1) {
229                     if (/Returns?:/){
230                         s/Returns?://;
231                         $returns = "\t$_\n";
232                         $inbody = 2;
233                     } else {
234                         $body .= "\n\t$_";
235                     }
236                 } else {
237                     $returns .= "\n\t$_";
238                 }
239                    
240         }
241 }
242
243 sub create_toc {
244     my ($apis_listed) = @_;
245     my $type_size = 0;
246     my $name_size = 0;
247     my $ret, $xname, $args, $line;
248     $apis_toc = "";
249
250
251     # Try to align things, so compute type size, method size, and arguments
252     foreach $line (split /\n/, $apis_listed){
253         $p = $prototype{$line};
254         ($ret, $xname, $args) = $p =~ /(.*)\n(\w+)[ \t](.*)/;
255         $tl = length ($ret);
256         $pl = length ($xname);
257
258         $type_size = $tl if ($tl > $type_size);
259         $name_size = $pl if ($pl > $name_size);
260     }
261
262     $type_size++;
263     $name_size++;
264
265     foreach $line (split /\n/, $apis_listed){
266         chop;
267         $p = $prototype{$line};
268         ($ret, $xname, $args) = $p =~ /(.*)\n(\w+)[ \t](.*)/;
269         if ($xname eq ""){
270             $xname = $line;
271         }
272         
273         $rspace = " " x ($type_size - length ($ret));
274         $nspace = " " x ($name_size - length ($xname));
275         $args = &format ($args, length ($ret . $rspace . $xname . $nspace), 60);
276         $apis_toc .= "$ret$rspace<a href=\"\#api:$line\">$xname</a>$nspace$args\n";
277     }
278     return $apis_toc;
279 }
280
281 #
282 # Formats the rest of the arguments in a way that will fit in N columns
283 #
284 sub format {
285     my ($args, $size, $limit) = @_;
286     my $sret = "";
287
288 #    return $args if ((length (args) + size) < $limit);
289     
290     $remain = $limit - $size;
291     @sa = split /,/, $args;
292     $linelen = $size;
293     foreach $arg (@sa){
294         if ($sret eq ""){
295             $sret = $arg . ", ";
296             $linelen += length ($sret);
297         } else {
298             if ($linelen + length ($arg) < $limit){
299                 $sret .= "FITS" . $arg . ", ";
300             } else {
301                 $newline = " " x ($size) . $arg . ", ";
302                 $linelen = length ($newline);
303                 $sret .= "\n" . $newline;
304             }
305         }
306     }
307     $sret =~ s/, $/;/;
308     return $sret;
309 }
310
311 sub opt_print {
312     my ($caption, $opttext, $quote) = @_;
313
314     if ($opttext ne "" && (!($opttext =~ /^[ \t]+$/))){
315         print OUT "             <div class=\"mapi-section\">$caption</div>\n";
316         print OUT "             <div>$opttext</div>\n";
317     }
318 }