patch by: David Nečas <yeti@physics.muni.cz>
[gtk-doc.git] / gtkdoc-fixxref.in
blob4839dead52e650b33174913da58855c730502fde
1 #!@PERL@ -w
2 # -*- cperl -*-
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 #############################################################################
23 # Script      : gtkdoc-fixxref
24 # Description : This fixes cross-references in the HTML documentation.
25 #############################################################################
27 use strict;
28 use bytes;
29 use Getopt::Long;
31 # Options
33 # name of documentation module
34 my $MODULE;
35 my $MODULE_DIR;
36 my $HTML_DIR = "";
37 my @EXTRA_DIRS;
38 my $PRINT_VERSION;
39 my $PRINT_HELP;
40 my $ONLINE = 0;
42 my %optctl = (module => \$MODULE,
43               'module-dir' => \$MODULE_DIR,
44               'html-dir' => \$HTML_DIR,
45               'extra-dir' => \@EXTRA_DIRS,
46               'online' => \$ONLINE,
47               'version' => \$PRINT_VERSION,
48               'help' => \$PRINT_HELP);
49 GetOptions(\%optctl, "module=s", "module-dir=s", "html-dir=s", "extra-dir=s@",
50                      "online", "version", "help");
52 if ($PRINT_VERSION) {
53     print "@VERSION@\n";
54     exit 0;
57 if ($PRINT_HELP) {
58     print "gtkdoc-fixxref version @VERSION@\n";
59     print "\n--module=MODULE_NAME    Name of the doc module being parsed";
60     print "\n--module-dir=MODULE_DIR The directory which contains the generated HTML";
61     print "\n--html-dir=HTML_DIR     The directory where gtk-doc generated documentation is installed";
62     print "\n--extra-dir=EXTRA_DIR   Directories to recursively scan for indices (index.sgml) in addition to HTML_DIR";
63     print "\n                        May be used more than once for multiple directories";
64     print "\n--online                Prefer cross-references to online documents";
65     print "\n--version               Print the version of this program";
66     print "\n--help                  Print this help\n";
67     exit 0;
70 # This contains all the entities and their relative URLs.
71 my %Links;
72 # This hold the path entries we already scanned
73 my @VisitedPaths;
76 my $path_prefix="";
77 if ($HTML_DIR =~ m%(.*?)/share/gtk-doc/html%) {
78     $path_prefix=$1;
79 #    print "Path prefix: $path_prefix\n";
82 my $dir;
84 # We scan the directory containing GLib and any directories in GNOME2_PATH
85 # first, but these will be overriden by any later scans.
86 $dir = `pkg-config --variable=prefix glib-2.0`;
87 $dir =~ s/\s+$//;
88 $dir = $dir . "/share/gtk-doc/html";
89 if (-d $dir && $dir ne $HTML_DIR) {
90 #    print "Scanning GLib directory: $dir\n";
91     if ($dir !~ m%^\Q$path_prefix\E/%) {
92         &ScanIndices ($dir, 1, $ONLINE);
93     } else {
94         &ScanIndices ($dir, 0, $ONLINE);
95     }
96     push (@VisitedPaths, $dir);
99 if (defined ($ENV{"GNOME2_PATH"})) {
100     foreach $dir (split (/:/, $ENV{"GNOME2_PATH"})) {
101         $dir = $dir . "/share/gtk-doc/html";
102         if (-d $dir && $dir ne $HTML_DIR) {
103 #           print "Scanning GNOME2_PATH directory: $dir\n";
104             if ($dir !~ m%^\Q$path_prefix\E/%) {
105                 &ScanIndices ($dir, 1, $ONLINE);
106             } else {
107                 &ScanIndices ($dir, 0, $ONLINE);
108             }
109             push (@VisitedPaths, $dir);
110         }
111         # ubuntu started to compress this as index.sgml.gz :/
112         # https://bugs.launchpad.net/ubuntu/+source/gtk-doc/+bug/77138
113     }
116 #print "Scanning HTML_DIR directory: $HTML_DIR\n";
117 &ScanIndices ($HTML_DIR, 0, $ONLINE);
118 push (@VisitedPaths, $HTML_DIR);
120 # check all extra dirs, but skip already scanned dirs ord subdirs of those
121 foreach my $dir (@EXTRA_DIRS) {
122     my $vdir;
123     my $skip = 0;
125     foreach $vdir (@VisitedPaths) {
126         if ($dir eq $vdir || $dir =~ m%^\Q$vdir\E/%) {
127 #            print "Skipping EXTRA_DIR directory: $dir\n";
128             $skip=1;
129         }
130     }
131     next if $skip;
132 #    print "Scanning EXTRA_DIR directory: $dir\n";
133     push (@VisitedPaths, $dir);
135     # If the --extra-dir option is not relative and is not sharing the same
136     # prefix as the target directory of the docs, we need to use absolute
137     # directories for the links
138     if ($dir !~m/^\.\./ &&  $dir !~ m%\Q$path_prefix\E/%) {
139         &ScanIndices ($dir, 1, $ONLINE);
140     } else {
141         &ScanIndices ($dir, 0, $ONLINE);
142     }
145 &FixCrossReferences (defined $MODULE_DIR ? $MODULE_DIR : "$HTML_DIR/$MODULE");
147 sub ScanIndices {
148     my ($scan_dir, $use_absolute_links, $use_online_location) = @_;
150 #    print "Scanning source directory: $scan_dir absolute: $use_absolute_links\n";
152     # This array holds any subdirectories found.
153     my (@subdirs) = ();
155     opendir (HTMLDIR, $scan_dir) || return;
156     my $file;
157     foreach $file (readdir (HTMLDIR)) {
158         if ($file eq '.' || $file eq '..') {
159             next;
160         } elsif (-d "$scan_dir/$file") {
161             push (@subdirs, $file);
162         } elsif ($file eq "index.sgml") {
163             &ScanIndex ("$scan_dir/$file", $use_absolute_links, $use_online_location);
164         }
165         # ubuntu started to compress this as index.sgml.gz :/
166         # https://bugs.launchpad.net/ubuntu/+source/gtk-doc/+bug/77138
167     }
168     closedir (HTMLDIR);
170     # Now recursively scan the subdirectories.
171     my $dir;
172     foreach $dir (@subdirs) {
173         &ScanIndices ("$scan_dir/$dir", $use_absolute_links, $use_online_location);
174     }
177 sub ScanIndex {
178     my ($file, $use_absolute_links, $use_online_location) = @_;
179 #    print "Scanning index file: $file absolute: $use_absolute_links\n";
181     # Determine the absolute directory, to be added to links in index.sgml
182     # if we need to use an absolute link.
183     # $file will be something like /opt/gnome/share/gtk-doc/html/gtk/index.sgml
184     # We want the part up to 'html' since the links in index.sgml include
185     # the rest.
186     my $dir = "../";
187     my $onlinedir = '';
188     my $seen_anchor = 0;
189     if ($use_absolute_links) {
190         $file =~ /(.*\/)(.*?)\/index\.sgml/;
191         $dir = "$1";
192     }
193     else {
194         # FIXME: This needs some clarification of what we are actually
195         # attempting to achieve.  But relative links are links to self and
196         # probably should remain so, on-line or not.
197         $use_online_location = 0;
198     }
200     open (INDEXFILE, $file)
201         || die "Can't open $file: $!";
202     while (<INDEXFILE>) {
203         if (m/^<ANCHOR\s+id\s*=\s*"([^"]*)"\s+href\s*=\s*"([^"]*)\/([^"]*)"\s*>/) {
204 #           print "Found id: $1 href: $2$3\n";
205             $use_online_location = 0 if !$onlinedir;
206             $Links{$1} = $use_online_location? "$onlinedir$3" : "$dir$2/$3";
207             $seen_anchor = 'yes';
208         }
209         elsif (m/^<ONLINE\s+href\s*=\s*"([^"]+)"\s*>/) {
210             if ($seen_anchor) {
211                 die "<ONLINE> must come before any <ANCHOR> in $file"
212             }
213             $onlinedir = $1;
214             # Remove trailing non-directory component.
215             $onlinedir =~ s#(.*/).*#$1#;
216         }
217     }
218     close (INDEXFILE);
221 sub FixCrossReferences {
222     my ($scan_dir) = @_;
224     opendir (HTMLDIR, $scan_dir)
225         || die "Can't open HTML directory $scan_dir: $!";
226     my $file;
227     foreach $file (readdir (HTMLDIR)) {
228         if ($file eq '.' || $file eq '..') {
229             next;
230         } elsif ($file =~ m/.html?$/) {
231             &FixHTMLFile ("$scan_dir/$file");
232         }
233     }
234     closedir (HTMLDIR);
238 sub FixHTMLFile {
239     my ($file) = @_;
240 #    print "Fixing file: $file\n";
242     open (HTMLFILE, $file)
243         || die "Can't open $file: $!";
244     undef $/;
245     my $entire_file = <HTMLFILE>;
246     close (HTMLFILE);
248     $entire_file =~ s%<GTKDOCLINK\s+HREF="([^"]*)"\s*>(.*?)</GTKDOCLINK\s*>% &MakeXRef($1, $2); %gse;
250     open (NEWFILE, ">$file.new")
251         || die "Can't open $file: $!";
252     print NEWFILE $entire_file;
253     close (NEWFILE);
255     unlink ($file)
256         || die "Can't delete $file: $!";
257     rename ("$file.new", $file)
258         || die "Can't rename $file.new: $!";
262 sub MakeXRef {
263     my ($id, $text) = @_;
265     my $href = $Links{$id};
267     if ($href) {
268 #        print "  Fixing link: $id, $href, $text\n";
269         return "<a\nhref=\"$href\"\n>$text</a>";
270     } else {
271         return $text;
272     }