[Documentation] Fix the nesting of docs
[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
11 if ($ARGV[0] eq "-t"){
12     $dir = $ARGV[1];
13     shift @ARGV;
14 }
15
16 if ($html){
17     opendir (D, "$sourcedir/sources/") || die "Can not open $dir";
18     while ($n = readdir (D)){
19         if ($n =~ /mono-api-.*\.html$/){
20             open (IN, "$sourcedir/sources/$n") || die "Can not open $n";
21             $files[$filecount] = $n;
22             while (<IN>){
23                 @files_content[$filecount] .= $_;
24                 if (/name="api:(.*?)"/){
25                     $_ =~ s/.*name="api:(\w+?)".*/\1/;
26                     $apis[$filecount] .= "$_";
27                 }
28             }
29             $filecount++;
30             close IN;
31         }
32     }
33 }
34
35 while (<ARGV>){
36         if (/\/\*\* *\n/){
37                 &process_doc;
38         } else {
39                 #print "IGNORING: $_";
40         }
41 }
42
43 if ($html){
44     for ($f = 0; $f < $filecount; $f++){
45         $name = $files[$f];
46         open (OUT, "> $dir/html/$name") || die "Can not create $dir/html/$name";
47         print "Merging: $name\n";
48         print OUT<<EOF;
49 <?xml version="1.0" encoding="utf-8"?>
50 <html xmlns="http://www.w3.org/1999/xhtml">
51 <head>
52     <title>$name</title>
53     <style type="text/css">
54     body {
55         line-height: 1.5;
56         padding-left: 2em;
57         padding-right: 2em;
58     }
59     body code {
60         font-family: "Consolas", "Courier", monospace;
61         border: 1px solid rgba(214,214,214,1);
62         background-color: rgba(249,249,249,1);
63         padding-left: 3px;
64         padding-right: 3px;
65     }
66
67     .api-entry code {
68         border: none;
69         background-color: transparent;
70     }
71     h3 { 
72     }
73     
74     .api-parameters {
75         border-collapse: collapse;
76         border-spacing: 0;
77         empty-cells: hide;
78         border: 0;
79         margin: 5px 0 26px;         
80     }
81
82     .api-parameters td {
83         border: 1px solid rgba(214,214,214,1);
84           border-left-style: none;
85         padding: 5px 25px 5px 10px;
86     }
87
88     .api-parameters tr>td:last-child  {
89         border-right: 0;
90     }
91         
92     .api-parameters td:first-of-type {
93         text-align: right;
94         padding: 7px;
95         vertical-align: top;
96         word-break: normal;
97         width: 40px;
98     }
99
100     .api-parameters tr:last-child>td {
101         border-bottom: 0;
102     }
103
104     .api-parameters tr:first-child>td {
105         border-top: 0;
106     }
107
108     .api-parameters tr td:first-of-type {
109         text-align: right;
110         padding: 7px;
111         vertical-align: top;
112         word-break: normal;
113         width: 40px;
114     }
115
116    .api {
117         left: -25px;
118         margin: 0;
119         padding: 13px 25px 0;
120         position: relative;
121         width: 100%;
122     } 
123
124     .api-description {
125         background: rgba(249,249,249,1);
126         border-bottom: 1px solid rgba(233,233,233,1);
127         left: -25px;
128         margin: 0;
129         padding: 13px 25px 0;
130         position: relative;
131         width: 100%;     
132     }
133
134      .api-entry {
135          background: transparent;
136      }
137
138      .api-docs {
139      }
140         
141      .prototype {
142          border-left: 5px solid rgba(205,233,244,1);
143          padding: .5em;
144          margin-top: 5pt;
145          margin-bottom: 5pt;
146          font-family: "Consolas", "Courier", monospace;
147          display: block;
148          overflow: auto;
149          background-color: #f9f9f9;
150     } 
151
152     .header {
153         padding: 0 0 5pt 5pt;
154         margin: 10pt;
155         white-space: pre;
156         font-family: monospace;
157         border: 1px solid rgba(233,233,233,1);
158     }
159     
160     .code {
161         border: 1px solid;
162         padding: 0 0 5pt 5pt;
163         margin: 10pt;
164         white-space: pre;
165         font-family: monospace;
166     }
167
168     .declaration {
169         margin-top: 21px;
170     }
171
172     .api-section {
173         font-size: smaller;
174         font-weight: bold;
175         margin-top: 21px;
176         line-height: 1.5;
177     }
178         
179     .strike {
180         text-decoration: line-through;
181     }
182
183     .deprecated {
184         color: red;
185     }
186
187     .api-ptr-container {
188         background: white;
189         border-bottom: 1px solid rgba(233,233,233,1);
190         left: -25px;
191         padding-left: 25px;
192         padding-right: 25px;
193         padding-bottom: 13px;
194         position: relative;
195         width: 100%;
196     }
197
198     .api-ptr {
199         background: rgba(249,249,249,1);
200         border-left: 1px solid rgba(233,233,233,1);
201         border-top: 1px solid rgba(233,233,233,1);
202         height: 12px;
203         left: 37px;
204         top: -7px;
205         -webkit-transform: rotate(45deg);
206         -moz-transform: rotate(45deg);
207         -o-transform: rotate(45deg);
208         transform: rotate(45deg);
209         position: absolute;
210         width: 12px;
211     }
212
213     .api-height-container {
214         left: -25px;
215         padding: 0 25px;
216         position: relative;
217         width: 100%;
218     }
219         
220    </style>
221 </head>
222 <body>
223 <div class="api-docs">
224 EOF
225         @a = split (/\n/, $files_content[$f]);
226         $strikeextra = "";
227         for ($ai = 0; $ai < $#a; $ai++){
228             $line = $a[$ai];
229             
230             ($api,$caption) = $line =~  /<h4><a name=\"api:(\w+)\">(\w+)<\/a><\/h4>/;
231             if ($api ne ""){
232                 if ($api_shown == 1){
233                     print OUT "</div> <!-- class=api -->\n\n";
234                     if ($deprecated{$api}){
235                         $strike = "strike";
236                         $strikeextra = "</div><br><div class='deprecated'><b>Deprecated:</b> " . $deprecated{$api};
237                     } else {
238                         $strike = "";
239                         $strikeextra = "";
240                     }
241                 }
242                 $api_shown = 1;
243                 $proto = $prototype{$api};
244                 if ($proto eq ""){
245                     $proto = "Prototype: $api";
246                 }
247
248                 print OUT<<EOF;
249 <a name="api:$api"></a>
250 <div class="api">
251     <div class="api-entry $strike"><code>$api$strikeextra</code></div>
252     <div class="api-height-container">
253         <div class="api-ptr-container"></div>
254         <div class="api-description">
255             <div class="api-ptr"></div>
256
257             <div class="declaration api-section">Syntax</div>
258             <div class="prototype">$proto</div>
259             <p>
260 EOF
261
262 #               if ($arguments{$api} ne "" && (!($arguments{$api}) =~ /^[ \t]+$/)){
263                     print OUT "            <div class=\"api-section\">Parameters</div>\n";
264                     print OUT "            <table class=\"api-parameters\"><tbody>".${arguments{$api}}."</tbody></table>";
265 #               }
266 #               &opt_print ("Parameters", $arguments{$api}, 1);
267             
268                 &opt_print ("Returns", $returns{$api}, 1);
269                 &opt_print ("Description", $bodies{$api}, 0);
270                 print OUT "        </div><!--api-description-->\n    </div><!--height container-->\n";
271             } else {
272                 if ($line =~ /@API_IDX@/){
273                     $apis_toc = &create_toc ($apis[$f]);
274                     $line =~ s/\@API_IDX\@/$apis_toc/;
275                 }
276                 if ($line =~ /^<h4/){
277                     print OUT "</div>\n";
278                     $api_shown = 0;
279                 }
280                 if ($line =~ /`/){
281                 }
282                 print OUT "$line\n";
283             }
284         }
285         print OUT<<EOF;
286    </div>
287 </body>
288 </html>
289 EOF
290         close OUT;
291         system ("$ENV{runtimedir}/mono-wrapper convert.exe $dir/html/$name $dir/html/x-$name");
292
293         # clean up the mess that AgilityPack does, it CDATAs our CSS
294         open HACK, "$dir/html/x-$name" || die "Could not open $dir/html/x-$name";
295         open HACKOUT, ">$dir/deploy/$name" || die "Could not open output";
296
297         while (<HACK>){
298             s/^\/\/<!\[CDATA\[//;
299             s/^\/\/\]\]>\/\///;
300             print HACKOUT $_;
301         }
302         #system ("cp.exe $dir/html/$name $dir/deploy/$name");
303     }
304 }
305
306 sub process_doc {
307         $doc = "";
308         $func = <>;
309         chop $func;
310         $func =~ s/^ \* //;
311         $func =~ s/:$//;
312         print "Function: $func\n" if (!$html);
313         $args = "";
314         $inbody = 0;
315         $returns = "";
316         $body = "";
317         $functions[$fn++] = $func;
318         $deprecated = 0;
319         
320         # Process arguments
321         while (<>){
322             s/NULL/<code>NULL<\/code>/g;
323             s/TRUE/<code>TRUE<\/code>/g;
324             s/FALSE/<code>FALSE<\/code>/g;
325             if (/^ \*\*?\//){
326                     $body =~ s/@(\w+)/<i>\1<\/i>/g;
327                     $returns =~ s/@(\w+)/<i>\1<\/i>/g;
328                     $args =~ s/@(\w+)/<i>\1<\/i>/g;
329
330                     $body =~ s/#(\w+)/<code>\1<\/code>/g;
331                     $returns =~ s/#(\w+)/<code>\1<\/code>/g;
332                     $args =~ s/#(\w+)/<code>\1<\/code>/g;
333
334                     $returns =~ s/\`([:\w\*]+)\`/<code>\1<\/code>/g;
335                     $args =~ s/\`([:\w\*]+)\`/<code>\1<\/code>/g;
336                     $body =~ s/\`([:\w\*]+)\`/<code>\1<\/code>/g;
337                     
338                     $body =~ s/\n/ /;
339                     $bodies{$func} = $body;
340                     $arguments{$func} = $args;
341                     $deprecated{$func} = $deprecated;
342                     $returns{$func} = $returns;
343                     $proto = "";
344                     while (<>){
345                         $proto .= $_;
346                         last if (/\{/);
347                     }
348                     $proto =~ s/{//;
349                     # clean it up a little, remove newlines, empty space at end
350                     $proto =~ s/ +$//;
351                     # Turn "Type * xxx" into "Type* xxx"
352                     $proto =~ s/^(\w+)\W+\*/\1\*/;
353                     $prototype{$func} = $proto;
354                     return;
355                 }
356                 chop;
357                 s/^\ \*//;
358                 $_ = "\n<p>" if (/^\s+$/);
359                                 
360                 if ($inbody == 0){
361                     if (/\s*(\w+):(.*)/){
362                         if ($1 eq "deprecated"){
363                             $deprecated = $2;
364                         } else {
365                             #$args .= "<dt><i>$1:</i></dt><dd>$2</dd>";
366                             $args .= "<tr><td><i>$1</i><td>$2</td></td></tr>";
367                         }
368                     } else {
369                         
370                         $body = "\t$_\n";
371                         $inbody = 1;
372                     }
373                 } elsif ($inbody == 1) {
374                     if (/Returns?:/){
375                         s/Returns?://;
376                         $returns = "\t$_\n";
377                         $inbody = 2;
378                     } else {
379                         $body .= "\n\t$_";
380                     }
381                 } else {
382                     $returns .= "\n\t$_";
383                 }
384                    
385         }
386 }
387
388 sub create_toc {
389     my ($apis_listed) = @_;
390     my $type_size = 0;
391     my $name_size = 0;
392     my $ret, $xname, $args, $line;
393     $apis_toc = "";
394
395
396     # Try to align things, so compute type size, method size, and arguments
397     foreach $line (split /\n/, $apis_listed){
398         $p = $prototype{$line};
399         ($ret, $xname, $args) = $p =~ /(.*)\n(\w+)[ \t](.*)/;
400         $tl = length ($ret);
401         $pl = length ($xname);
402
403         $type_size = $tl if ($tl > $type_size);
404         $name_size = $pl if ($pl > $name_size);
405     }
406
407     $type_size++;
408     $name_size++;
409
410     foreach $line (split /\n/, $apis_listed){
411         chop;
412         $p = $prototype{$line};
413         ($ret, $xname, $args) = $p =~ /(.*)\n(\w+)[ \t](.*)/;
414         
415         $rspace = " " x ($type_size - length ($ret));
416         $nspace = " " x ($name_size - length ($xname));
417         $args = &format ($args, length ($ret . $rspace . $xname . $nspace), 60);
418         $apis_toc .= "$ret$rspace<a href=\"\#api:$line\">$xname</a>$nspace$args\n";
419     }
420     return $apis_toc;
421 }
422
423 #
424 # Formats the rest of the arguments in a way that will fit in N columns
425 #
426 sub format {
427     my ($args, $size, $limit) = @_;
428     my $sret = "";
429
430 #    return $args if ((length (args) + size) < $limit);
431     
432     $remain = $limit - $size;
433     @sa = split /,/, $args;
434     $linelen = $size;
435     foreach $arg (@sa){
436         if ($sret eq ""){
437             $sret = $arg . ", ";
438             $linelen += length ($sret);
439         } else {
440             if ($linelen + length ($arg) < $limit){
441                 $sret .= "FITS" . $arg . ", ";
442             } else {
443                 $newline = " " x ($size) . $arg . ", ";
444                 $linelen = length ($newline);
445                 $sret .= "\n" . $newline;
446             }
447         }
448     }
449     $sret =~ s/, $/;/;
450     return $sret;
451 }
452
453 sub opt_print {
454     my ($caption, $opttext, $quote) = @_;
455
456     if ($opttext ne "" && (!($opttext =~ /^[ \t]+$/))){
457         print OUT "             <div class=\"api-section\">$caption</div>\n";
458         if ($quote == 1){
459             print OUT "             <blockquote>$opttext</blockquote>\n";
460         } else {
461             print OUT "             <p>$opttext\n";
462         }
463     }
464 }