EOP
}
### Subroutines
# Process and print the body of a section
sub printsectionbody {
local(*man, *sectionlines, *sline, *name) = @_; # Number of section
local($sfirst, $slast, @paralines, @paratypes, $comment, $dl, $pline,
$comment, $pfirst, $plast, @para, @tag, $changeindent);
# Define section boundaries
$sfirst = $sectionlines[$sline] + 1;
if ($sline == $#sectionlines) {
$slast = $#man;
} else {
$slast = $sectionlines[$sline + 1] - 1;
}
# Find paragraph markers, ignoring those between '.ig' and '..'
if ($man[$sfirst] =~ /^\.[PIT]P/) {
@paralines = ();
@paratypes = ();
} else {
@paralines = ($sfirst - 1); # .P follows .S[HS] by default
@paratypes = ('P');
}
$comment = 0;
foreach ($sfirst .. $slast) {
if ($man[$_] =~ /^\.ig/) { # Start ignoring
$comment = 1;
} elsif ($man[$_] =~ /^\.\./) { # Stop ignoring
$comment = 0;
} elsif (! $comment && $man[$_] =~ /^\.([PIT])P/) {
push(@paralines, $_);
push(@paratypes, $1);
}
}
# Process paragraphs
$changeindent = 0;
$dl = 0;
foreach $pline (0 .. $#paralines) {
@para = ();
$comment = 0;
# Define para boundaries
$pfirst = $paralines[$pline] + 1;
if ($pline == $#paralines) {
$plast = $slast;
} else {
$plast = $paralines[$pline + 1] - 1;
}
foreach (@man[$pfirst .. $plast]) {
if (/^\.ig/) { # nroff begin ignore
if ($comment == 0) {
$comment = 2;
push(@para, "\n");
} elsif ($comment == 2) {
s/--/-/g; # Remove double-dashes in comments
}
unless ($comment) {
if (/^\.TH/) { # Title; got this already
next;
} elsif (/^\.PD/) { # Para spacing; unimplemented
next;
} elsif (/^\.RS/) { # Indent (one width only)
$changeindent = 1;
next;
} elsif (/^\.RE/) { # Outdent
$changeindent = -1;
next;
}
# Line break
s/^\.br.*/
/;
# nroff special characters
s/\\(e|\\)/\\/g; # \e, \\
s/^\\(\s)/$1/; # leading space escape
s/^\\&\;//; # leading dot escape
&make_hrefs(*name, *_);
}
push(@para, $_);
}
}
push(@para, "-->\n") if $comment; # Close open comment
# Print paragraph
if ($paratypes[$pline] eq 'P') {
&font(*para);
print @para;
} elsif ($paratypes[$pline] eq 'I') {
&font(*para);
print "\n";
} else { # T
@tag = shift(@para);
&font(*tag);
&font(*para);
print "\n" unless $dl;
print "- \n",
@tag,
"
- \n",
@para;
if ($paratypes[$pline + 1] ne 'T') { # Next para not defn list
$dl = 0; # Close open defn list
print "
\n";
} else {
$dl = 1; # Leave defn list open
}
}
print "\n";
# Indent/outdent the *next* para
if ($changeindent == 1) {
print "
\n";
$changeindent = 0;
}
}
1;
}
# Make one name anchor in a line; cue on fonts (.B or .I) but leave them alone
sub make_name {
local(*name, *font, *file, *line) = @_;
local($text);
if (($text) = ($line =~ /^\.[BI]\s+([^\s\\]+)/)) { # Found pattern
if (
$text !~ /^-/ # Avoid lists of options
&& (length($text) > 1 # and history escapes
|| $text =~ /^[%:@]$/) # Special pleading for %, :, @
&& ! $name{"$text $font"} # Skip if there's one already
) {
# Record link
$name{"$text $font"} = "$file#$text";
# Put in the name anchor
$line =~ s/^(\.[BI]\s+)([^\s\\]+)/$1$2<\/A>/;
}
}
$line;
}
# Make all the href anchors in a line; cue on fonts (\fB ... \fR or
# \fI ... \fR) but leave them alone
sub make_hrefs {
local(*name, *line) = @_;
local(@pieces, $piece);
@pieces = split(/(\\f[BI][^\\]*\\fR)/, $line);
$piece = 0;
foreach (@pieces) {
if (/\\f([BI])([^\\]*)\\fR/ # Found a possibility
# It's not followed by (, i.e. it's not a manpage reference
&& substr($pieces[$piece + 1], 0, 1) ne '(') {
$key = "$2 $1";
if ($name{$key}) { # If there's a matching name
s/(\\f[BI])([^\\]*)(\\fR)/$1$2<\/A>$3/;
}
}
$piece++;
}
$line = join('', @pieces);
}
# Convert nroff font escapes to HTML
# Expects comments and breaks to be in HTML form already
sub font {
local(*para) = @_;
local($i, $j, @begin, @end, $part, @pieces, $bold, $italic);
# Find beginning and end of each part between HTML comments
$i = 0;
@begin = ();
@end = ();
foreach (@para) {
push(@begin, $i + 1) if /^-->/ || /^
/;
push(@end, $i - 1) if /^/ || $para[$#para] =~ /^
/) {
pop(@begin);
} else {
push(@end, $#para); # End at the end
}
# Fontify each part
$bold = $italic = 0;
foreach $i (0 .. $#begin) {
$* = 1;
$part = join('', @para[$begin[$i] .. $end[$i]]);
$part =~ s/^\.([BI])\s+(.*)$/\\f$1$2\\fR/g; # .B, .I
@pieces = split(/(\\f[BIR])/, $part);
$part = '';
foreach $j (@pieces) {
if ($j eq '\fB') {
if ($italic) {
$italic = 0;
$part .= '';
}
unless ($bold) {
$bold = 1;
$part .= '';
}
} elsif ($j eq '\fI') {
if ($bold) {
$bold = 0;
$part .= '';
}
unless ($italic) {
$italic = 1;
$part .= '';
}
} elsif ($j eq '\fR') {
if ($bold) {
$bold = 0;
$part .= '';
} elsif ($italic) {
$italic = 0;
$part .= '';
}
} else {
$part .= $j;
}
}
$* = 0;
# Close bold/italic before break
if ($para[$end[$i] + 1] =~ /^
/) {
if ($bold) {
$bold = 0;
$part =~ s/(\n)?$/<\/B>$1\n/;
} elsif ($italic) {
$italic = 0;
$part =~ s/(\n)?$/<\/I>$1\n/;
}
}
# Rebuild this section of @para
foreach $j ($begin[$i] .. $end[$i]) {
$part =~ s/^([^\n]*(\n|$))//;
$para[$j] = $1;
}
}
# Close bold/italic on last non-comment line
# Do this only here because fonts pass through comments
$para[$end[$#end]] =~ s/(\n)?$/<\/B>$1/ if $bold;
$para[$end[$#end]] =~ s/(\n)?$/<\/I>$1/ if $italic;
}