4 # gtk-doc - GTK DocBook documentation generator.
5 # Copyright (C) 1998 Damon Chaplin
6 # Copyright (C) 2007 David Necas (Yeti)
8 # This program is free software; you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation; either version 2 of the License, or
11 # (at your option) any later version.
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
18 # You should have received a copy of the GNU General Public License
19 # along with this program; if not, write to the Free Software
20 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 #############################################################################
24 # Script : gtkdoc-rebase
25 # Description : Rebases URI references in installed HTML documentation.
26 #############################################################################
30 use Getopt::Long qw(:config gnu_getopt);
45 my %optctl = ('html-dir' => \$HTML_DIR,
46 'other-dir' => \@OTHER_DIRS,
47 'dest-dir' => \$DEST_DIR,
49 'relative' => \$RELATIVE,
50 'aggressive' => \$AGGRESSIVE,
51 'verbose' => \$VERBOSE,
52 'version' => \$PRINT_VERSION,
53 'help' => \$PRINT_HELP);
54 GetOptions(\%optctl, 'html-dir=s', 'other-dir=s@', 'dest-dir:s',
55 'online', 'relative', 'aggressive', 'verbose',
65 gtkdoc-rebase version @VERSION@ - rewrite the base url of html files
67 --html-dir=HTML_DIR The directory which contains the installed HTML
68 --other-dir=OTHER_DIR Directories to recursively scan for indices (index.sgml)
69 May be used more than once for multiple directories
70 --online Prefer cross-references to online documents
71 --relative Prefer relative cross-references
72 --aggressive Rebase links to all files that are under a directory
73 matching a package name.
74 --dest-dir=ROOT_DIR Staging area virtual root, this prefix will be removed
75 from HTML_DIR fore relative link calculation.
77 --version Print the version of this program
78 --help Print this help
84 die "No HTML directory (--html-dir) given.\n";
88 # These two point to the last seen URI of given type for a package:
89 # OnlineMap: package => on-line URI
90 # LocalMap: package => local URI
91 # This maps all seen URIs of a package to fix broken links in the process:
92 # RevMap: URI => package
93 my (%OnlineMap, %LocalMap, %RevMap);
94 # Remember what mangling we did.
99 # We scan the directory containing GLib and any directories in GNOME2_PATH
100 # first, but these will be overriden by any later scans.
101 if (defined ($ENV{"GNOME2_PATH"})) {
102 foreach $dir (split(/:/, $ENV{"GNOME2_PATH"})) {
103 $dir = $dir . "/share/gtk-doc/html";
104 if ($dir && -d $dir) {
105 print "Prepending GNOME2_PATH directory: $dir\n" if $VERBOSE;
106 unshift @OTHER_DIRS, $dir;
111 $dir = `pkg-config --variable=prefix glib-2.0`;
112 $dir =~ s/^\s*(\S*)\s*$/$1/;
113 $dir = $dir . "/share/gtk-doc/html";
114 print "Prepending GLib directory $dir\n" if $VERBOSE;
115 unshift @OTHER_DIRS, $dir;
117 # Check all other dirs, but skip already scanned dirs ord subdirs of those
119 $DEST_DIR =~ s#/?$#/#;
121 $HTML_DIR =~ s#/?$#/#;
123 foreach $dir (@OTHER_DIRS) {
124 &ScanDirectory($dir, $HTML_DIR);
128 &RelativizeLocalMap($HTML_DIR);
131 &RebaseReferences($HTML_DIR);
132 &PrintWhatWeHaveDone();
136 my ($dir, $self) = @_;
137 # This array holds any subdirectories found.
140 print "Scanning documentation directory $dir\n" if $VERBOSE;
142 if ("$dir/" eq $self) {
143 print "Excluding self\n" if $VERBOSE;
146 if (not opendir(HTMLDIR, $dir)) {
147 print "Cannot open $dir: $!\n";
152 foreach $file (readdir(HTMLDIR)) {
153 if ($file eq '.' or $file eq '..') {
156 elsif (-d "$dir/$file") {
157 push @subdirs, $file;
159 elsif ($file eq "index.sgml") {
162 elsif ($file eq "index.sgml.gz") {
163 print "Please fix https://bugs.launchpad.net/ubuntu/+source/gtk-doc/+bug/77138\n";
168 # Now recursively scan the subdirectories.
170 foreach my $subdir (@subdirs) {
171 &ScanDirectory("$dir/$subdir", $self);
178 my $file = "$dir/index.sgml";
179 my ($onlinedir, $package);
181 open(INDEXFILE, $file) || die "Can't open $file: $!";
182 while (<INDEXFILE>) {
183 # ONLINE must come before any ANCHORs
185 if (m/^<ONLINE\s+href\s*=\s*"([^"]+)"\s*>/) {
187 # Remove trailing non-directory component.
188 $onlinedir =~ s#(.*/).*#$1#;
194 ($package = $dir) =~ s#.*/([^/]+)/#$1#;
195 if ($DEST_DIR and substr($dir, 0, length $DEST_DIR) eq $DEST_DIR) {
196 $dir = substr($dir, -1 + length $DEST_DIR);
199 print "On-line location of $package: $onlinedir\n" if $VERBOSE;
200 $OnlineMap{ $package } = $onlinedir;
201 $RevMap{ $onlinedir } = $package;
203 print "Local location of $package: $dir\n" if $VERBOSE;
204 $LocalMap{ $package } = $dir;
205 $RevMap{ $dir } = $package;
209 sub RelativizeLocalMap {
213 $self = realpath $self;
215 ($prefix = $self) =~ s#[^/]+/$##;
216 foreach my $package (keys %LocalMap) {
217 $dir = $LocalMap{ $package };
218 if (substr($dir, 0, length $prefix) eq $prefix) {
219 $dir = "../" . substr($dir, length $prefix);
220 $LocalMap{ $package } = $dir;
221 print "Relativizing local location of $package to $dir\n" if $VERBOSE;
227 sub RebaseReferences {
230 opendir(HTMLDIR, $dir) || die "Can't open HTML directory $dir: $!";
231 foreach my $file (readdir(HTMLDIR)) {
232 if ($file =~ m/\.html?$/) {
233 &RebaseFile("$dir$file");
242 print "Fixing file: $file\n" if $VERBOSE;
244 open(HTMLFILE, $file) || die "Can't open $file: $!";
247 my $text = <HTMLFILE>;
250 $text =~ s#(<a(?:\s+\w+=(?:"[^"]*"|'[^']*'))*\s+href=")([^"]*)(")#$1 . &RebaseLink($2) .$3#gse;
252 open(NEWFILE, ">$file.new") || die "Can't open $file: $!";
256 unlink($file) || die "Can't delete $file: $!";
257 rename("$file.new", $file) || die "Can't rename $file.new: $!";
263 my ($dir, $origdir, $file, $package);
265 if ($href =~ m#^(.*/)([^/]*)$#) {
266 $dir = $origdir = $1;
268 if ($RevMap{ $dir }) {
269 $package = $RevMap{ $dir };
271 elsif ($dir =~ m#^\.\./([^/]+)/#) {
274 elsif ($AGGRESSIVE) {
275 $dir =~ m#([^/]+)/$#;
280 if ($ONLINE && $OnlineMap{ $package }) {
281 $dir = $OnlineMap{ $package };
283 elsif ($LocalMap{ $package }) {
284 $dir = $LocalMap{ $package };
286 $href = $dir . $file;
288 if ($dir ne $origdir) {
289 if ($Mapped{ $origdir }) {
290 $Mapped{ $origdir }->[1]++;
293 $Mapped{ $origdir } = [ $dir, 1 ];
301 sub PrintWhatWeHaveDone {
302 my ($origdir, $info);
303 foreach $origdir (sort keys %Mapped) {
304 $info = $Mapped{$origdir};
305 print "$origdir -> ", $info->[0], " (", $info->[1], ")\n";