4 # gtk-doc - GTK DocBook documentation generator.
5 # Copyright (C) 1998 Damon Chaplin
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 2 of the License, or
10 # (at your option) any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with this program; if not, write to the Free Software
19 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 #############################################################################
23 # Script : gtkdoc-fixxref
24 # Description : This fixes cross-references in the HTML documentation.
25 #############################################################################
31 push @INC, '@PACKAGE_DATA_DIR@';
32 require "gtkdoc-common.pl";
36 # name of documentation module
44 my %optctl = ('module' => \$MODULE,
45 'module-dir' => \$MODULE_DIR,
46 'html-dir' => \$HTML_DIR,
47 'extra-dir' => \@EXTRA_DIRS,
48 'version' => \$PRINT_VERSION,
49 'help' => \$PRINT_HELP);
50 GetOptions(\%optctl, "module=s", "module-dir=s", "html-dir:s", "extra-dir=s@",
60 gtkdoc-fixxref version @VERSION@ - fix cross references in html files
62 --module=MODULE_NAME Name of the doc module being parsed
63 --module-dir=MODULE_DIR The directory which contains the generated HTML
64 --html-dir=HTML_DIR The directory where gtk-doc generated documentation is
66 --extra-dir=EXTRA_DIR Directories to recursively scan for indices (index.sgml)
67 in addition to HTML_DIR
68 May be used more than once for multiple directories
69 --version Print the version of this program
70 --help Print this help
75 # This contains all the entities and their relative URLs.
77 # This hold the path entries we already scanned
80 # failing link targets we don't warn about even once
99 if ($HTML_DIR =~ m%(.*?)/share/gtk-doc/html%) {
101 #print "Path prefix: $path_prefix\n";
104 if (!defined $MODULE_DIR) {
105 $MODULE_DIR="$HTML_DIR/$MODULE";
110 # We scan the directory containing GLib and any directories in GNOME2_PATH
111 # first, but these will be overriden by any later scans.
112 $dir = `pkg-config --variable=prefix glib-2.0`;
114 $dir = $dir . "/share/gtk-doc/html";
115 if (-d $dir && $dir ne $HTML_DIR) {
116 #print "Scanning GLib directory: $dir\n";
117 if ($dir !~ m%^\Q$path_prefix\E/%) {
118 &ScanIndices ($dir, 1);
120 &ScanIndices ($dir, 0);
122 push (@VisitedPaths, $dir);
125 if (defined ($ENV{"GNOME2_PATH"})) {
126 foreach $dir (split (/:/, $ENV{"GNOME2_PATH"})) {
127 $dir = $dir . "/share/gtk-doc/html";
128 if (-d $dir && $dir ne $HTML_DIR) {
129 #print "Scanning GNOME2_PATH directory: $dir\n";
130 if ($dir !~ m%^\Q$path_prefix\E/%) {
131 &ScanIndices ($dir, 1);
133 &ScanIndices ($dir, 0);
135 push (@VisitedPaths, $dir);
137 # ubuntu started to compress this as index.sgml.gz :/
138 # https://bugs.launchpad.net/ubuntu/+source/gtk-doc/+bug/77138
142 #print "Scanning HTML_DIR directory: $HTML_DIR\n";
143 &ScanIndices ($HTML_DIR, 0);
144 push (@VisitedPaths, $HTML_DIR);
145 #print "Scanning HTML_DIR directory: $MODULE_DIR\n";
146 &ScanIndices ($MODULE_DIR, 0);
147 push (@VisitedPaths, $MODULE_DIR);
149 # check all extra dirs, but skip already scanned dirs or subdirs of those
150 foreach my $dir (@EXTRA_DIRS) {
154 foreach $vdir (@VisitedPaths) {
155 if ($dir eq $vdir || $dir =~ m%^\Q$vdir\E/%) {
156 #print "Skipping EXTRA_DIR directory: $dir\n";
161 #print "Scanning EXTRA_DIR directory: $dir\n";
162 push (@VisitedPaths, $dir);
164 # If the --extra-dir option is not relative and is not sharing the same
165 # prefix as the target directory of the docs, we need to use absolute
166 # directories for the links
167 if ($dir !~m/^\.\./ && $dir !~ m%\Q$path_prefix\E/%) {
168 &ScanIndices ($dir, 1);
170 &ScanIndices ($dir, 0);
174 if (defined($MODULE)) {
175 open (INPUT, "$MODULE-sections.txt")
176 || die "Can't open $MODULE-sections.txt: $!";
182 } elsif (m/^<SECTION>/) {
184 } elsif (m/^<SUBSECTION\s*(.*)>/i) {
186 } elsif (m/^<SUBSECTION>/) {
188 } elsif (m/^<TITLE>(.*)<\/TITLE>/) {
190 } elsif (m/^<FILE>(.*)<\/FILE>/) {
192 } elsif (m/^<INCLUDE>(.*)<\/INCLUDE>/) {
194 } elsif (m/^<\/SECTION>/) {
196 } elsif (m/^(\S+)/) {
197 my $symbol=CreateValidSGMLID($1);
199 if ($subsection eq "Standard" || $subsection eq "Private") {
200 $NoLinks{$symbol} = 1;
207 &FixCrossReferences ($MODULE_DIR);
210 my ($scan_dir, $use_absolute_links) = @_;
212 #print "Scanning source directory: $scan_dir absolute: $use_absolute_links\n";
214 # This array holds any subdirectories found.
217 opendir (HTMLDIR, $scan_dir) || return;
219 foreach $file (readdir (HTMLDIR)) {
220 if ($file eq '.' || $file eq '..') {
222 } elsif (-d "$scan_dir/$file") {
223 push (@subdirs, $file);
224 } elsif ($file eq "index.sgml") {
225 &ScanIndex ("$scan_dir/$file", $use_absolute_links);
227 # ubuntu started to compress this as index.sgml.gz :/
228 # https://bugs.launchpad.net/ubuntu/+source/gtk-doc/+bug/77138
232 # Now recursively scan the subdirectories.
234 foreach $dir (@subdirs) {
235 &ScanIndices ("$scan_dir/$dir", $use_absolute_links);
240 my ($file, $use_absolute_links) = @_;
241 #print "Scanning index file: $file absolute: $use_absolute_links\n";
243 # Determine the absolute directory, to be added to links in index.sgml
244 # if we need to use an absolute link.
245 # $file will be something like /opt/gnome/share/gtk-doc/html/gtk/index.sgml
246 # We want the part up to 'html' since the links in index.sgml include
249 if ($use_absolute_links) {
250 $file =~ /(.*\/)(.*?)\/index\.sgml/;
254 open (INDEXFILE, $file)
255 || die "Can't open $file: $!";
256 while (<INDEXFILE>) {
257 if (m/^<ANCHOR\s+id\s*=\s*"([^"]*)"\s+href\s*=\s*"([^"]*)"\s*>/) {
258 #print "Found id: $1 href: $2\n";
259 $Links{$1} = "$dir$2";
266 sub FixCrossReferences {
269 opendir (HTMLDIR, $scan_dir)
270 || die "Can't open HTML directory $scan_dir: $!";
272 foreach $file (readdir (HTMLDIR)) {
273 if ($file eq '.' || $file eq '..') {
275 } elsif ($file =~ m/.html?$/) {
276 &FixHTMLFile ("$scan_dir/$file");
285 #print "Fixing file: $file\n";
287 open (HTMLFILE, $file)
288 || die "Can't open $file: $!";
290 my $entire_file = <HTMLFILE>;
293 if ("@HIGHLIGHT@" ne "") {
294 # FIXME: ideally we'd pass a clue about the example language to the highligher
295 # unfortunately the "language" attribute is not appearing in the html output
296 # we could patch the customization to have <code class="xxx"> inside of <pre>
297 if ("@HIGHLIGHT@" =~ m%/vim$%) {
298 $entire_file =~ s%<div class=\"(example-contents|informalexample)\"><pre class=\"programlisting\">(.*?)</pre></div>%&HighlightSourceVim($1,$2);%gse;
301 $entire_file =~ s%<div class=\"(example-contents|informalexample)\"><pre class=\"programlisting\">(.*?)</pre></div>%&HighlightSource($1,$2);%gse;
303 # this just broke existing GTKDOCLINK tags
304 # <GTKDOCLINK HREF="GST-PAD-SINK:CAPS">GST_PAD_SINK</GTKDOCLINK>
305 $entire_file =~ s%\<GTKDOCLINK\s+HREF=\"(.*?)\"\>(.*?)\</GTKDOCLINK\>%\<GTKDOCLINK\ HREF=\"$1\"\>$2\</GTKDOCLINK\>%gs;
307 # from the highlighter we get all the functions marked up
308 # now we could turn them into GTKDOCLINK items
309 $entire_file =~ s%(<span class=\"function\">)(.*?)(</span>)%&MakeGtkDocLink($1,$2,$3);%gse;
310 # we could also try the first item in stuff marked up as 'normal'
311 $entire_file =~ s%(<span class=\"normal\">\s*)(.+?)((\s+.+?)?\s*</span>)%&MakeGtkDocLink($1,$2,$3);%gse;
314 my @lines = split(/\n/, $entire_file);
315 for (my $i=0; $i<$#lines; $i++) {
316 $lines[$i] =~ s%<GTKDOCLINK\s+HREF="([^"]*)"\s*>(.*?)</GTKDOCLINK\s*>% &MakeXRef($file,$i+1,$1,$2); %ge;
317 #if ($lines[$i] =~ m/GTKDOCLINK/) {
318 # print "make xref failed for line: ",$lines[$i], "\n";
321 $entire_file = join("\n",@lines);
323 open (NEWFILE, ">$file.new")
324 || die "Can't open $file: $!";
325 print NEWFILE $entire_file;
329 || die "Can't delete $file: $!";
330 rename ("$file.new", $file)
331 || die "Can't rename $file.new: $!";
335 my ($file, $line, $id, $text) = @_;
337 my $href = $Links{$id};
339 # this is a workaround for some inconsitency we have with CreateValidSGMLID
340 if (!$href && $id =~ m/:/) {
343 $href = $Links{$tid};
345 # poor mans plural support
346 if (!$href && $id =~ m/s$/) {
349 $href = $Links{$tid};
353 # if it is a link to same module, remove path to make it work
355 if (defined($MODULE) && $href =~ m%^\.\./$MODULE/(.*)$%) {
358 #print " Fixing link: $id, $href, $text\n";
359 return "<a href=\"$href\">$text</a>";
362 #print " no link for: $id, $text\n";
364 # don't warn multiple times and also skip blacklisted (ctypes)
365 $warn = 0 if exists $NoLinks{$id};
366 # if it's a function, don't warn if it does not contain a "_"
367 # (transformed to "-")
368 # - gnome coding style would use '_'
369 # - will avoid wrong warnings for ansi c functions
370 $warn = 0 if ($text =~ m/ class=\"function\"/ && $id !~ m/-/);
371 # if it's a 'return value', don't warn (implicitly created link)
372 $warn = 0 if ($text =~ m/ class=\"returnvalue\"/);
373 # if it's a 'type', don't warn if it starts with lowercase
374 # - gnome coding style would use CamelCase
375 $warn = 0 if ($text =~ m/ class=\"type\"/ && ($id =~ m/^[a-z]/));
378 &LogWarning ($file, $line, "no link for: '$id' -> ($text).");
387 my ($pre,$symbol,$post) = @_;
389 my $id=CreateValidSGMLID($symbol);
391 # these are implicitely created links in highlighed sources
392 # we don't want warnings for those if the links cannot be resolved.
395 #return "<span class=\"$type\"><GTKDOCLINK HREF=\"$id\">$symbol</GTKDOCLINK></span>";
396 return "$pre<GTKDOCLINK HREF=\"$id\">$symbol</GTKDOCLINK>$post";
400 sub HighlightSource {
401 my ($type, $source) = @_;
403 # chop of leading and trailing empty lines
404 $source =~ s/^\s*\n+//gs;
405 $source =~ s/[\s\n]+$//gs;
407 $source =~ m/^(\s*)/;
408 $source =~ s/^$1//gms;
409 # avoid double entity replacement
410 $source =~ s/</</g;
411 $source =~ s/>/>/g;
412 $source =~ s/&/&/g;
414 # write source to a temp file
415 # FIXME: use .c for now to hint the language to the highlighter
416 my $temp_source_file="$MODULE_DIR/_temp_src.$$.c";
417 open (NEWFILE, ">$temp_source_file") || die "Can't open $temp_source_file: $!";
418 print NEWFILE $source;
421 #print" running @HIGHLIGHT@ @HIGHLIGHT_OPTIONS@$temp_source_file \n";
424 my $highlighted_source=`@HIGHLIGHT@ @HIGHLIGHT_OPTIONS@$temp_source_file`;
425 if ("@HIGHLIGHT@" =~ m%/source-highlight$%) {
426 $highlighted_source =~ s%^<\!-- .*? -->%%gs;
427 $highlighted_source =~ s%<pre><tt>(.*?)</tt></pre>%$1%gs;
429 elsif ("@HIGHLIGHT@" =~ m%/highlight$%) {
430 # need to rewrite the stylesheet classes
431 $highlighted_source =~ s%<span class="gtkdoc com">%<span class="comment">%gs;
432 $highlighted_source =~ s%<span class="gtkdoc dir">%<span class="preproc">%gs;
433 $highlighted_source =~ s%<span class="gtkdoc kwd">%<span class="function">%gs;
434 $highlighted_source =~ s%<span class="gtkdoc kwa">%<span class="keyword">%gs;
435 $highlighted_source =~ s%<span class="gtkdoc line">%<span class="linenum">%gs;
436 $highlighted_source =~ s%<span class="gtkdoc num">%<span class="number">%gs;
437 $highlighted_source =~ s%<span class="gtkdoc str">%<span class="string">%gs;
438 $highlighted_source =~ s%<span class="gtkdoc sym">%<span class="symbol">%gs;
440 # $highlighted_source =~ s%</span>(.+)<span%</span><span class="normal">$1</span><span%gs;
443 unlink ($temp_source_file)
444 || die "Can't delete $temp_source_file: $!";
446 return &HighlightSourcePostprocess($type, $highlighted_source);
449 sub HighlightSourceVim {
450 my ($type, $source) = @_;
452 # chop of leading and trailing empty lines
453 $source =~ s/^[\s\n]+//gs;
454 $source =~ s/[\s\n]+$//gs;
455 # avoid double entity replacement
456 $source =~ s/</</g;
457 $source =~ s/>/>/g;
458 $source =~ s/&/&/g;
460 # write source to a temp file
461 my $temp_source_file="$MODULE_DIR/_temp_src.$$.h";
462 open (NEWFILE, ">$temp_source_file") || die "Can't open $temp_source_file: $!";
463 print NEWFILE $source;
467 system "echo 'let html_number_lines=0|let html_use_css=1|let use_xhtml=1|syn on|e $temp_source_file|run! syntax/2html.vim|w! $temp_source_file.html|qa!' | @HIGHLIGHT@ -n -e -u NONE -T xterm >/dev/null";
469 my $highlighted_source;
472 open (NEWFILE, "<$temp_source_file.html");
473 $highlighted_source = <NEWFILE>;
476 $highlighted_source =~ s#.*<pre>\n##s;
477 $highlighted_source =~ s#</pre>.*##s;
479 # need to rewrite the stylesheet classes
480 # FIXME: Vim has somewhat different syntax groups
481 $highlighted_source =~ s%<span class="Comment">%<span class="comment">%gs;
482 $highlighted_source =~ s%<span class="PreProc">%<span class="preproc">%gs;
483 $highlighted_source =~ s%<span class="Statement">%<span class="keyword">%gs;
484 $highlighted_source =~ s%<span class="Identifier">%<span class="function">%gs;
485 $highlighted_source =~ s%<span class="Constant">%<span class="number">%gs;
486 $highlighted_source =~ s%<span class="Special">%<span class="symbol">%gs;
487 $highlighted_source =~ s%<span class="Type">%<span class="type">%gs;
490 unlink ($temp_source_file)
491 || die "Can't delete $temp_source_file: $!";
492 unlink ("$temp_source_file.html")
493 || die "Can't delete $temp_source_file.html: $!";
495 return &HighlightSourcePostprocess($type, $highlighted_source);
498 sub HighlightSourcePostprocess {
499 my ($type, $highlighted_source) = @_;
501 # chop of leading and trailing empty lines
502 $highlighted_source =~ s/^[\s\n]+//gs;
503 $highlighted_source =~ s/[\s\n]+$//gs;
505 # turn common urls in comments into links
506 $highlighted_source =~ s%<span class="url">(.*?)</span>%<span class="url"><a href="$1">$1</a></span>%gs;
508 # we do own line-numbering
510 my $line_count = () = $highlighted_source =~ /\n/gs;
511 for (my $i=1; $i < ($line_count+2); $i++) {
512 $source_lines.="$i\n";
514 $source_lines =~ s/\n\Z//;
518 <table class="listing_frame" border="0" cellpadding="0" cellspacing="0">
521 <td class="listing_lines" align="right"><pre>$source_lines</pre></td>
522 <td class="listing_code"><pre class="programlisting">$highlighted_source</pre></td>