bird/tools/linuxdoc-tools/LinuxDocTools/Html2Html.pm
Ondrej Zajicek (work) 58510024be Doc: Include full LinuxDocTools code
BIRD uses hacked LinuxDocTools for building documentation, keeping some
parts locally and using remaining parts from system-installed one. This
setup breaks when LinuxDocTools makes some internal changes and is hard
to keep consistent.

Just include full LinuxDocTools code (both hacked and unmodified parts)
to avoid consistency issues. Note that we still need some binaries from
LinuxDocTools, so it still needs to be installed to build documentation.
2021-04-25 02:21:05 +02:00

584 lines
18 KiB
Perl

#
# Html2Html.pm
#
# $Id: Html2Html.pm,v 1.4 2001/08/31 23:09:10 sano Exp $
#
# Convert parsed linuxdoc-sgml to html.
# - Split files; match references, generate TOC and navigation
# aids, etc.
#
# Rules based on html2html.l
#
package LinuxDocTools::Html2Html;
use FileHandle;
use LinuxDocTools::Lang;
# Externally visible variables
$html2html = {};
# Initialize: set splitlevel, extension, images, filename,
# filenumber, label, header, footer, toclevel,
# tmpbase, debug.
# Usage:
# &{$html2html->{init}}(split,ext,img,filename,filenum,label,hdr,ftr,toc,tmpbase, debug);
# split level: 0 - super page mode
# 1 - big page mode
# 2 - small page mode
$html2html->{init} = sub {
$splitlevel = shift;
SWITCH: {
$super_page_mode = 0, $big_page_mode = 1, last SWITCH
if ($splitlevel == 1);
$super_page_mode = 0, $big_page_mode = 0, last SWITCH
if ($splitlevel == 2);
}
$fileext = shift;
$use_imgs = shift;
$firstname = shift;
$filecount = 1 + shift;
$lprec = shift;
$header = shift;
$footer = shift;
$toclevel = shift;
if ($toclevel == -1) {
if ($splitlevel == 0) {
$toclevel = 0;
} else {
$toclevel = 2;
}
}
$tmpbase = shift;
$content_file = $tmpbase . ".content";
$debug = shift;
$nextlabel = Xlat ("Next");
$prevlabel = Xlat ("Previous");
$toclabel = Xlat ("Contents");
};
# Package variables
$big_page_mode = 0; # '-2' subsection splitting
$super_page_mode = 1; # One page vs. page/section
$chapter_mode = 0; # <article> vs. <report>
$current = ""; # State of section/subsection/etc.
$filenum = 1; # Current output file number
$filecount = 1;
$firstname = "$$"; # Base name for file
$headbuf = ""; # Buffer for URL's
$fileext = "html"; # "html" vs. "htm" for 8.3
$in_appendix = 0; # n.n vs. a.n section numbers
$in_section_list = 0; # List of sections flag
$language = ""; # Default English; use '-Lname'
# $lprec{label} # Label record
$nextlabel = ""; # Link string
$outfh = STDOUT; # Output filehandle
$outname = ""; # Output file name
$prevlabel = ""; # Link string
$refname = ""; # Ref string
$sectname = ""; # Section name
$secnr = 0; # Section count
$ssectname = ""; # Subsection name
$ssecnr = 0; # Subsection count
$skipnewline = 0; # Flag to ignore new line
$toclabel = ""; # Link string
$titlename = ""; # Title of document
$use_imgs = 0; # '-img' pictorial links
$urlname = ""; # Name for url links
$header = "";
$footer = "";
$toclevel = -1;
$tmpbase = "/tmp/sgmltmp" . $$;
$debug = 0;
$content_file = $tmpbase . ".content.init";
# Ruleset
$html2html->{rules} = {}; # Individual parsing rules
$html2html->{rules}->{'^<@@appendix>.*$'} = sub {
$in_appendix = 1; $secnr = 0; $ssecnr = 0;
};
$html2html->{rules}->{'^<@@url>(.*)$'} = sub {
$skipnewline = 1; $urlname = $1; $headbuf = qq(<A HREF="$1">);
};
$html2html->{rules}->{'^<@@urlnam>(.*)$'} = sub {
$headbuf = $headbuf . "$urlname</A>";
};
$html2html->{rules}->{'^<@@endurl>.*$'} = sub {
$skipnewline = -1; $outfh->print($headbuf); $headbuf = "";
};
$html2html->{rules}->{'^<@@title>(.*)$'} = sub {
$titlename = $1; &heading(STDOUT); print(STDOUT "<H1>$1</H1>\n\n");
};
$html2html->{rules}->{'^<@@head>(.*)$'} = sub {
$skipnewline = 1; $headbuf = $1;
};
$html2html->{rules}->{'^<@@part>.*$'} = sub { $current = "PART"; };
$html2html->{rules}->{'^<@@endhead>.*$'} = sub {
SWITCH: {
$outfh->print("<H1>$headbuf</H1>\n\n"), last SWITCH
if ($current eq "PART");
$outfh->print("<H1>$headbuf</H1>\n\n"), last SWITCH
if ($current eq "CHAPTER");
$outfh->print("<H2>$headbuf</H2>\n\n"), last SWITCH
if ($current eq "SECTION");
$outfh->print("<H2>$headbuf</H2>\n\n"), last SWITCH
if ($current eq "SUBSECT");
$outfh->print("<H3>$headbuf</H3>\n\n"), last SWITCH;
}
$current = ""; $headbuf = ""; $skipnewline = 0;
};
$html2html->{rules}->{'^<@@chapt>(.*)$'} = sub {
$chapter_mode = 1; $skipnewline = 1; $sectname = $1;
&start_chapter($sectname);
};
$html2html->{rules}->{'^<@@sect>(.*)$'} = sub {
$skipnewline = 1; $ssectname = $1;
if ($chapter_mode) {
&start_section($ssectname);
} else {
$sectname = $ssectname; &start_chapter($ssectname);
}
};
$html2html->{rules}->{'^<@@ssect>(.*)$'} = sub {
$skipnewline = 1; $ssectname = $1;
if (!$chapter_mode) {
&start_section($ssectname);
} else {
$current = ""; $headbuf = $ssectname;
}
};
$html2html->{rules}->{'^<@@endchapt>.*$'} = sub {
STDOUT->print("</UL>\n") if ($in_section_list);
if ($outfh->fileno != STDOUT->fileno) {
&footing($outfh) if (!$super_page_mode);
$outfh->close; $outfh = STDOUT;
}
};
$html2html->{rules}->{'^<@@endsect>.*$'} = sub {
STDOUT->print("</UL>\n") if (!$chapter_mode && $in_section_list);
if (($outfh->fileno != STDOUT->fileno)
&& ((!$chapter_mode) || (!$big_page_mode))) {
&footing($outfh) if (!$super_page_mode);
$outfh->close; $outfh = STDOUT;
}
};
$html2html->{rules}->{'^<@@endssect>.*$'} = sub {
if (($outfh->fileno != STDOUT->fileno)
&& (!$chapter_mode) && (!$big_page_mode) && (!$super_page_mode)) {
&footing($outfh); $outfh->close; $outfh = STDOUT;
}
};
$html2html->{rules}->{'^<@@enddoc>.*$'} = sub { };
$html2html->{rules}->{'^<@@label>(.*)$'} = sub {
if (!defined($lprec->{$1})) {
STDERR->print(qq(html2html: Problem with label "$1"\n)); next;
}
if ($skipnewline) {
$headbuf = sprintf(qq(<A NAME="%s"></A> %s), $1, $headbuf);
} else {
$outfh->print(qq(<A NAME="$1"></A> ));
}
};
$html2html->{rules}->{'^<@@ref>(.*)$'} = sub {
my $tmp;
$refname = $1;
if (!defined($lprec->{$1})) {
STDERR->print(qq(html2html: Problem with ref "$1"\n));
$skipnewline++; next;
}
SWITCH: {
$tmp = qq(<A HREF="#$1">), last SWITCH
if ($lprec->{$1} == $filenum - 1);
$tmp = qq(<A HREF="$firstname.$fileext#$1">), last SWITCH
if ($lprec->{$1} == 0);
$tmp = qq(<A HREF="$firstname-$lprec->{$1}.$fileext#$1">),
last SWITCH;
}
if ($skipnewline) {
$headbuf = "$headbuf$tmp";
} else {
$headbuf = $tmp;
}
$skipnewline++;
};
$html2html->{rules}->{'^<@@refnam>.*$'} = sub {
$headbuf = "$headbuf$refname</A>\n";
};
$html2html->{rules}->{'^<@@endref>.*$'} = sub {
if ($skipnewline == 1) {
$outfh->print($headbuf); $skipnewline = -1;
} elsif ($skipnewline == 2) {
$skipnewline--;
} else {
STDERR->print("html2html: Problem with endref\n");
$skipnewline--;
}
};
# Default parsing rule
$html2html->{defaultrule} = sub {
$skipnewline++ if ($skipnewline < 0);
if ($skipnewline) {
chop; $headbuf = "$headbuf$_";
} else {
$outfh->print($_);
}
};
# Finalize parsing process
$html2html->{finish} = sub {
# Finish footers
if ($outfh->fileno != STDOUT->fileno) {
if (!$super_page_mode) {
&footing($outfh);
$outfh->close;
}
}
#
if ($super_page_mode) {
if ($toclevel > 0) { STDOUT->print("\n<HR>\n"); }
$outfh->close if ($outfh->fileno != STDOUT->fileno);
if ( -r $content_file ) {
open CONTENT, "<$content_file"
or die "Can't open content file\n";
while (<CONTENT>) {
STDOUT->print($_);
}
close CONTENT;
unlink $content_file if (! $debug);
}
}
# Finish the TOC; ensure "next" points to the first page.
&browse_links(STDOUT, 1, 0) if (!$super_page_mode);
#
# add Footer
if ( -r "$footer" ) {
open FTRFILE, "<$footer" or die "Cannot open footer file\n";
while (<FTRFILE>) {
STDOUT->print($_);
}
close FTRFILE;
} else {
STDOUT->print("</BODY>\n</HTML>\n");
}
};
###################################################################
# Secondary Functions
###################################################################
# Print standard links
sub browse_links {
my ($outfh, $myfilenum, $top) = @_;
return if ($super_page_mode);
$outfh->print("<HR>\n") unless ($top);
# NOTE: For pages where a next or prev button isn't appropriate, include
# the graphic anyway - just don't make it a link. That way, the mouse
# position of each button is unchanged from page to page.
# Use the passed myfilenum since filenum may already be incremented
# Next link (first)
my $next = $use_imgs
? qq(<IMG SRC="next.png" ALT="$nextlabel">)
: qq($nextlabel);
$next = qq(<A HREF="$firstname-$myfilenum.$fileext">$next</A>)
if ($myfilenum < $filecount);
$next = join "", $next, "\n";
$outfh->print($next);
# Previous link
my $prev = $use_imgs
? qq(<IMG SRC="prev.png" ALT="$prevlabel">)
: qq($prevlabel);
$prev = join "", qq(<A HREF="$firstname-), ($myfilenum - 2),
qq(.$fileext">$prev</A>)
if ($myfilenum >= 3);
$prev = join "", $prev, "\n";
$outfh->print($prev);
# Table of contents link
my $toc = $use_imgs
? qq(<IMG SRC="toc.png" ALT="$toclabel">)
: qq($toclabel);
$toc = join "", qq(<A HREF="$firstname.$fileext#toc),
&section_num($secnr, 0), qq(">$toc</A>)
if ($outfh->fileno != STDOUT->fileno);
$toc = join "", $toc, "\n";
$outfh->print($toc);
print($outfh "<HR>\n") if ($top);
}
# Print end-of-file markup
sub footing {
my $outfh = shift;
&browse_links($outfh, $filenum, 0);
if ( -r "$footer" ) {
open FTRFILE, "<$footer" or die "Cannot open footer file\n";
while (<FTRFILE>) {
$outfh->print($_);
}
close FTRFILE;
} else {
$outfh->print("</BODY>\n</HTML>\n");
}
}
# Print top-of-file markup
sub heading {
my $outfh = shift; my $match;
# Emit 3.2 HTML until somebody comes up with a better idea - CdG
if ( -r "$header" ) {
open HDRFILE, "<$header" or die "Cannot open header file\n";
while (<HDRFILE>) {
$outfh->print($_);
}
close HDRFILE;
} else {
$outfh->print(
qq(<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">\n));
$outfh->print("<HTML>\n<HEAD>\n");
}
open VERSFILE, "<$main::DataDir/VERSION" or die "Cannot open version file\n";
$version = <VERSFILE>;
close VERSFILE;
chop $version;
$outfh->print(
" <META NAME=\"GENERATOR\" CONTENT=\"LinuxDoc-Tools $version\">\n");
$outfh->print(" <TITLE>");
$match = $titlename;
$match =~ s/<[^>]*>//g;
$outfh->print($match);
if ($secnr > 0) {
$match = $sectname;
$match =~ s/<[^>]*>//g;
$outfh->print(": $match");
}
if ($ssecnr > 0) {
$match = $ssectname;
$match =~ s/<[^>]*>//g;
$outfh->print(": $match");
}
$outfh->print("</TITLE>\n");
if (!$super_page_mode) {
#
# <LINK> Information for next, previous, contents, etc...
#
$outfh->print(qq( <LINK HREF="$firstname-$filenum.$fileext" REL=next>),"\n")
if ($filenum < $filecount);
my $prev;
$prev = join "", qq( <LINK HREF="$firstname-), ($filenum - 2),
qq(.$fileext" REL=previous>)
if ($filenum >= 3);
$outfh->print($prev,"\n");
#
# Table of contents link
#
my $toc ;
$toc = join "", qq( <LINK HREF="$firstname.$fileext#toc),
&section_num($secnr, 0), qq(" REL=contents>)
if ($outfh->fileno != STDOUT->fileno);
$outfh->print($toc,"\n");
} # (!$super_page_mode)
$outfh->print("</HEAD>\n<BODY>\n");
&browse_links($outfh, $filenum, 1);
}
# Return the section and subsection as a dotted string
sub section_num {
my ($sec, $ssec) = @_;
my $l = "A";
if ($in_appendix) {
$sec--;
while ($sec) { $l++; $sec--; }
return("$l.$ssec") if ($ssec > 0);
return("$l");
} else {
return("$sec.$ssec") if ($ssec > 0);
return("$sec");
}
}
# Create a chapter head; start a new file, etc.
sub start_chapter {
my $sectname = shift;
if (!$super_page_mode && $outfh->fileno != STDOUT->fileno) {
&footing($outfh); $outfh->close;
}
$current = "SECTION"; $secnr++; $ssecnr = 0;
if ($super_page_mode) {
$outname = $content_file;
$outfh = new FileHandle ">>$outname"
or die qq(html2html: Fatal: Could not open file "$outname"\n);
if ($toclevel > 0) {
$headbuf = sprintf(
qq(<A NAME="s%s">%s.</A> <A HREF="#toc%s">%s</A>),
&section_num($secnr, 0), &section_num($secnr, 0),
&section_num($secnr, 0),
$sectname);
STDOUT->printf(
qq(<P>\n<H2><A NAME="toc%s">%s.</A> <A HREF="%s#s%s">%s</A></H2>\n\n),
&section_num($secnr, 0), &section_num($secnr, 0),
"$firstname.$fileext", &section_num($secnr, 0), $sectname);
} else {
$headbuf = sprintf(
qq(<A NAME="s%s">%s. %s</A>),
&section_num($secnr, 0), &section_num($secnr, 0),
$sectname);
}
} else {
$outname = "$firstname-$filenum.$fileext"; $filenum++;
$outfh = new FileHandle ">$outname"
or die qq(html2html: Fatal: Could not open file "$outname"\n);
&heading($outfh);
if ($toclevel > 0) {
$headbuf = sprintf(
qq(<A NAME="s%s">%s.</A> <A HREF="%s#toc%s">%s</A>),
&section_num($secnr, 0), &section_num($secnr, 0),
"$firstname.$fileext", &section_num($secnr, 0),
$sectname);
STDOUT->printf(
qq(<P>\n<H2><A NAME="toc%s">%s.</A> <A HREF="%s">%s</A></H2>\n\n),
&section_num($secnr, 0), &section_num($secnr, 0),
$outname, $sectname);
} else {
$headbuf = sprintf(
qq(<A NAME="s%s">%s. %s</A>),
&section_num($secnr, 0), &section_num($secnr, 0),
$sectname);
}
}
$in_section_list = 0;
}
# Create a section; start a new file, etc.
sub start_section {
my $ssectname = shift;
$current = "SUBSECT"; $ssecnr++;
if ($toclevel > 1) {
if (!$in_section_list) {
STDOUT->print("<UL>\n"); $in_section_list = 1;
}
}
if ($super_page_mode) {
if ($outfh->fileno != STDOUT->fileno && !$chapter_mode) {
$outfh->close;
}
$outname = $content_file;
$outfh = new FileHandle ">>$outname"
or die qq(html2html: Fatal: Could not open file "$outname"\n);
if ($toclevel > 1) {
$headbuf = sprintf(qq(<A NAME="ss%s">%s</A> <A HREF="#toc%s">%s</A>\n),
&section_num($secnr, $ssecnr),
&section_num($secnr, $ssecnr),
&section_num($secnr, $ssecnr),
$ssectname);
STDOUT->printf(
qq(<LI><A NAME="toc%s">%s</A> <A HREF="%s#ss%s">%s</A>\n),
&section_num($secnr, $ssecnr),
&section_num($secnr, $ssecnr),
"$firstname.$fileext",
&section_num($secnr, $ssecnr),
$ssectname);
} else {
$headbuf = sprintf(qq(<A NAME="ss%s">%s %s</A>\n),
&section_num($secnr, $ssecnr),
&section_num($secnr, $ssecnr),
$ssectname);
}
} else {
if (!$big_page_mode) {
if ($outfh->fileno != STDOUT->fileno) {
&footing($outfh); $outfh->close;
}
$outname = "$firstname-$filenum.$fileext"; $filenum++;
$outfh = new FileHandle ">$outname"
or die qq(html2html: Fatal: Could not open file "$outname"\n);
heading($outfh);
# Since only one section is on any page,
# don't use # so that when we
# jump to this page, we see the browse
# links at the top of the page.
if ($toclevel > 1) {
$headbuf = sprintf("%s <A HREF=\"%s#toc%s\">%s</A>",
&section_num($secnr, $ssecnr),
"$firstname.$fileext",
&section_num($secnr, $ssecnr),
$ssectname);
STDOUT->printf(
qq(<LI><A NAME="toc%s">%s</A> <A HREF="%s">%s</A>\n),
&section_num($secnr, $ssecnr),
&section_num($secnr, $ssecnr),
$outname, $ssectname);
} else {
$headbuf = sprintf("%s %s</A>",
&section_num($secnr, $ssecnr),
$ssectname);
}
} else {
# Since many sections are on one page, we need to use #
if ($toclevel > 1) {
$headbuf = sprintf(
qq(<A NAME="ss%s">%s</A> <A HREF="%s#toc%s">%s</A>\n),
&section_num($secnr, $ssecnr),
&section_num($secnr, $ssecnr),
"$firstname.$fileext",
&section_num($secnr, $ssecnr),
$ssectname);
STDOUT->printf(
qq(<LI><A NAME="toc%s">%s</A> <A HREF="%s#ss%s">%s</A>\n),
&section_num($secnr, $ssecnr),
&section_num($secnr, $ssecnr),
$outname,
&section_num($secnr, $ssecnr),
$ssectname);
} else {
$headbuf = sprintf(
qq(<A NAME="ss%s">%s %s</A>\n),
&section_num($secnr, $ssecnr),
&section_num($secnr, $ssecnr),
$ssectname);
}
}
}
}