\Z/){push@pre,$html;}else{if(@pre){if(@pre>1){$pre[0]=~s/<\/pre>\Z//;
$pre[$#pre]=~s/\A]+>//;
for my $i(1..($#pre-1)){$pre[$i]=~s/\A]+>|\n?<\/pre>\Z//g;}push@out,join("\n",@pre);}else{push@out,@pre;}@pre=();}push@out,$html;}}print HTML join"\n",@out;
close(HTML);
warn"Finished\n" if$self->{verbose};}{no strict 'refs';
*pod2xhtml=\*pod2html;}sub usage{my$self=shift->class_obj;
$self->{podfile}=shift;
warn ref($self)." $self->{podfile}: @_\n" if@_;
confess$self->{usage};}sub parse_command_line{my$self=shift->class_obj;
my($opt_backlink,$opt_css,$opt_flush,$opt_header,$opt_help,$opt_htmldir,$opt_htmlroot,$opt_index,$opt_infile,$opt_libpods,$opt_netscape,$opt_outfile,$opt_podpath,$opt_podroot,$opt_quiet,$opt_recurse,$opt_title,$opt_verbose);
unshift@ARGV,split ' ',$Config{pod2html}if$Config{pod2html};
my$result=GetOptions('backlink=s'=>\$opt_backlink,'css=s'=>\$opt_css,'flush'=>\$opt_flush,'header!'=>\$opt_header,'help'=>\$opt_help,'htmldir=s'=>\$opt_htmldir,'htmlroot=s'=>\$opt_htmlroot,'index!'=>\$opt_index,'infile=s'=>\$opt_infile,'libpods=s'=>\$opt_libpods,'netscape!'=>\$opt_netscape,'outfile=s'=>\$opt_outfile,'podpath=s'=>\$opt_podpath,'podroot=s'=>\$opt_podroot,'quiet!'=>\$opt_quiet,'recurse!'=>\$opt_recurse,'title=s'=>\$opt_title,'verbose!'=>\$opt_verbose,);
$self->usage("-","invalid parameters")if not$result;
$self->usage("-")if defined$opt_help;
$opt_help="";
@{$self->{podpath}}=split(":",$opt_podpath)if defined$opt_podpath;
@{$self->{libpods}}=split(":",$opt_libpods)if defined$opt_libpods;
$self->{backlink}=$opt_backlink if defined$opt_backlink;
$self->{css}=$opt_css if defined$opt_css;
$self->{header}=$opt_header if defined$opt_header;
$self->{htmldir}=$opt_htmldir if defined$opt_htmldir;
$self->{htmlroot}=$opt_htmlroot if defined$opt_htmlroot;
$self->{doindex}=$opt_index if defined$opt_index;
$self->{podfile}=$opt_infile if defined$opt_infile;
$self->{netscape}=$opt_netscape if defined$opt_netscape;
$self->{htmlfile}=$opt_outfile if defined$opt_outfile;
$self->{podroot}=$opt_podroot if defined$opt_podroot;
$self->{quiet}=$opt_quiet if defined$opt_quiet;
$self->{recurse}=$opt_recurse if defined$opt_recurse;
$self->{title}=$opt_title if defined$opt_title;
$self->{verbose}=$opt_verbose if defined$opt_verbose;
warn"Flushing item and directory caches\n" if$opt_verbose&&defined$opt_flush;
unlink($self->{dircache},$self->{itemcache})if defined$opt_flush;}sub get_cache{my$self=shift->class_obj;
my$podpath;
($self->{dircache},$self->{itemcache},$podpath,$self->{podroot},$self->{recurse})=@_;
my@cache_key_args=@_;
my$this_cache_key=$self->cache_key(@cache_key_args);
return if$self->{saved_cache_key}and$this_cache_key eq$self->{saved_cache_key};
my$tests=0;
if(-f$self->{dircache}&&-f$self->{itemcache}){warn"scanning for item cache\n" if$self->{verbose};
$tests=$self->load_cache($self->{dircache},$self->{itemcache},$podpath,$self->{podroot});}if(!$tests){warn"scanning directories in pod-path\n" if$self->{verbose};
$self->scan_podpath($self->{podroot},$self->{recurse},0);}$self->{saved_cache_key}=$self->cache_key(@cache_key_args);}sub cache_key{my$self=shift->class_obj;
my$podpath;
($self->{dircache},$self->{itemcache},$podpath,$self->{podroot},$self->{recurse})=@_;
return join('!',$self->{dircache},$self->{itemcache},$self->{recurse},@$podpath,$self->{podroot},stat($self->{dircache}),stat($self->{itemcache}));}sub load_cache{my$self=shift->class_obj;
my$podpath;
($self->{dircache},$self->{itemcache},$podpath,$self->{podroot})=@_;
my($tests);
local$_;
$tests=0;
open(CACHE,"<$self->{itemcache}")||die ref($self)." error opening $self->{itemcache} for reading: $!\n";
$/="\n";
$_=;
chomp($_);
$tests++ if(join(":",@$podpath)eq$_);
$_=;
chomp($_);
$tests++ if($self->{podroot}eq$_);
if($tests!=2){close(CACHE);
return 0;}warn"loading item cache\n" if$self->{verbose};
while(){/(.*?) (.*)$/;
$self->{items}->{$1}=$2;}close(CACHE);
warn"scanning for directory cache\n" if$self->{verbose};
open(CACHE,"<$self->{dircache}")||die ref($self)." error opening $self->{dircache} for reading: $!\n";
$/="\n";
$tests=0;
$_=;
chomp($_);
$tests++ if(join(":",@$podpath)eq$_);
$_=;
chomp($_);
$tests++ if($self->{podroot}eq$_);
if($tests!=2){close(CACHE);
return 0;}warn"loading directory cache\n" if$self->{verbose};
while(){/(.*?) (.*)$/;
$self->{pages}->{$1}=$2;}close(CACHE);
return 1;}sub scan_podpath{my$self=shift->class_obj;
my$append;
($self->{podroot},$self->{recurse},$append)=@_;
my($pwd,$dir);
my($libpod,$dirname,$pod,@files,@poddata);
unless($append){%{$self->{items}}=();
%{$self->{pages}}=();}$pwd=getcwd();
chdir($self->{podroot})||die ref($self)." error changing to directory $self->{podroot}: $!\n";
foreach$dir(@{$self->{podpath}}){$self->scan_dir($dir,$self->{recurse});}foreach$libpod(@{$self->{libpods}}){next unless defined$self->{pages}->{$libpod}&&$self->{pages}->{$libpod};
if($self->{pages}->{$libpod}=~/([^:]*(?;
close(POD);
$self->clean_data(\@poddata);
$self->scan_items(\%{$self->{items}},"$dirname/$pod",@poddata);}}elsif($self->{pages}->{$libpod}=~/([^:]*\.pod):/||$self->{pages}->{$libpod}=~/([^:]*\.pm):/){$pod=$1;
open(POD,"<$pod")||die ref($self)." error opening $pod for input: $!\n";
@poddata=;
close(POD);
$self->clean_data(\@poddata);
$self->scan_items(\%{$self->{items}},"$pod",@poddata);}else{warn ref($self)." shouldn't be here (line ".__LINE__."\n" unless$self->{quiet};}}@poddata=();
chdir($pwd)||die ref($self)." error changing to directory $pwd: $!\n";
warn"caching items for later use\n" if$self->{verbose};
open(CACHE,">$self->{itemcache}")||die ref($self)." error open $self->{itemcache} for writing: $!\n";
print CACHE join(":",@{$self->{podpath}})."\n$self->{podroot}\n";
foreach my $key(keys%{$self->{items}}){print CACHE"$key $self->{items}->{$key}\n";}close(CACHE);
warn"caching directories for later use\n" if$self->{verbose};
open(CACHE,">$self->{dircache}")||die ref($self)." error open $self->{dircache} for writing: $!\n";
print CACHE join(":",@{$self->{podpath}})."\n$self->{podroot}\n";
foreach my $key(keys%{$self->{pages}}){print CACHE"$key $self->{pages}->{$key}\n";}close(CACHE);}sub scan_dir{my$self=shift->class_obj;
my$dir;
($dir,$self->{recurse})=@_;
my($t,@subdirs,@pods,$pod,$dirname,@dirs);
local$_;
@subdirs=();
@pods=();
opendir(DIR,$dir)||die ref($self)." error opening directory $dir: $!\n";
while(defined($_=readdir(DIR))){if(-d"$dir/$_"&&$_ ne"."&&$_ ne".."){$self->{pages}->{$_}="" unless defined$self->{pages}->{$_};
$self->{pages}->{$_}.="$dir/$_:";
push(@subdirs,$_);}elsif(/\.pod\z/){s/\.pod\z//;
$self->{pages}->{$_}="" unless defined$self->{pages}->{$_};
$self->{pages}->{$_}.="$dir/$_.pod:";
push(@pods,"$dir/$_.pod");}elsif(/\.html\z/){s/\.html\z//;
$self->{pages}->{$_}="" unless defined$self->{pages}->{$_};
$self->{pages}->{$_}.="$dir/$_.pod:";}elsif(/\.pm\z/){s/\.pm\z//;
$self->{pages}->{$_}="" unless defined$self->{pages}->{$_};
$self->{pages}->{$_}.="$dir/$_.pm:";
push(@pods,"$dir/$_.pm");}}closedir(DIR);
if($self->{recurse}){foreach my $subdir(@subdirs){$self->scan_dir("$dir/$subdir",$self->{recurse});}}}sub scan_headings{my$self=shift->class_obj;
my($sections,@data)=@_;
my($tag,$which_head,$otitle,$listdepth,$index);
$self->{ignore}=0;
$listdepth=0;
$index="";
foreach my $line(@data){if($line=~/^=(head)([1-6])\s+(.*)/){($tag,$which_head,$otitle)=($1,$2,$3);
my$title=$self->depod($otitle);
my$name=$self->htmlify($title);
$sections->{$name}=1;
$title=$self->process_text(\$otitle);
while($which_head!=$listdepth){if($which_head>$listdepth){$index.="\n".("\t" x$listdepth).qq'\n';
$listdepth++;}elsif($which_head<$listdepth){$listdepth--;
$index.="\n".("\t" x$listdepth)."
\n";}}$index.="\n".("\t" x$listdepth).qq''.qq''."$title";}}while($listdepth--){$index.="\n".("\t" x$listdepth)."\n";}$index=~s!\t*!!g;
$self->{ignore}=1;
return$index;}sub scan_items{my$self=shift->class_obj;
my($itemref,$pod,@poddata)=@_;
my($i,$item);
local$_;
$pod=~s/\.pod\z//;
$pod.=".html" if$pod;
foreach$i(0..$#poddata){my$txt=$self->depod($poddata[$i]);
if($txt=~/\A=item\s+[*+-]\s*(.*)\Z/s){next unless$1;
$item=$1;}elsif($txt=~/\A=item\s+(?>\d+\.?)\s*(.*)\Z/s){$item=$1;}elsif($txt=~/\A=item\s+(.*)\Z/s){$item=$1;}else{next;}my$fid=$self->fragment_id($item);
$itemref->{$fid}="$pod" if$fid;}}sub process_head{my$self=shift->class_obj;
my($tag,$heading,$hasindex)=@_;
$tag=~/head([1-6])/;
my$level=$1;
push@{$self->{HTML}},"\n\n";
if($self->{listlevel}){warn ref($self)." $self->{podfile}: unterminated list at =head in paragraph $self->{paragraph}. ignoring.\n" unless$self->{quiet};
while($self->{listlevel}){$self->process_back();}}push@{$self->{HTML}},qq'\n';
if($level==1&&!$self->{top}){push@{$self->{HTML}},q'$self->{backlink}\n' if$hasindex and$self->{backlink};
push@{$self->{HTML}},qq'
\n';}my$name=$self->htmlify($self->depod($heading));
my$convert=$self->process_text(\$heading);
push@{$self->{HTML}},qq'$convert\n';}sub emit_item_tag{my$self=shift->class_obj;
my($otext,$text,$index)=@_;
my$item=$self->fragment_id($text);
$self->{EmittedItem}=$item;
if($self->{items_named}->{$item}++){push@{$self->{HTML}},$self->process_text(\$otext);}else{my$name='item_'.$item;
my$ptxt=$self->process_text(\$otext);
push@{$self->{HTML}},qq'\n$ptxt\n';
if($index){my$index=$self->_fragment_id($text,1);
my($str,$str_type)=@$index;
if($str_type ne"Sections"){($str)=$str=~m/\A\s*(\S+<.*>\S+|\S+)/;}$self->process_text(\$str);
$self->{printed_items}->{$str_type}{$str}="\#$name" unless$self->{printed_items}->{$str_type}{$str};
$self->{printed_items}->{$str_type}{$str}="\#$name" if$str eq$text;}}push@{$self->{HTML}},"
\n";
undef($self->{EmittedItem});}sub emit_li{my$self=shift->class_obj;
my$tag=lc(shift@_);
if($self->{items_seen}->[$self->{listlevel}]++ ==0){push(@{$self->{listend}},($tag eq 'dl'?'':'')."$tag>");
push@{$self->{HTML}},qq'<$tag class="item">\n';}else{push@{$self->{HTML}},$tag eq 'dl'?'':'';}push@{$self->{HTML}},$tag eq 'dl'?'':'';}sub process_item{my$self=shift->class_obj;
my($otext)=@_;
if($self->{listlevel}==0){warn ref($self)." $self->{podfile}: unexpected =item directive in paragraph $self->{paragraph}. ignoring.\n" unless$self->{quiet};
$self->process_over();}if($self->{after_lpar}){push@{$self->{HTML}},"\n";
$self->{after_lpar}=0;}my$text=$self->depod($otext);
if($text=~/\A\*/){$self->emit_li('ul');
if($text=~/\A\s*[+*-]\s+(.+)\Z/s){my$tag=$1;
$otext=~s/\A\s*[+*-]\s+//;
$self->emit_item_tag($otext,$tag,0);}}elsif($text=~/\A\s*\d+/){$self->emit_li('ol');
if($text=~/\A\s*(?>\d+\.?)\s*(.+)\Z/s){my$tag=$1;
$otext=~s/\A\s*\d+\.?\s*//;
$self->emit_item_tag($otext,$tag,0);}}else{$self->emit_li('dl');
if($text=~/\A\s*(.+)\s*\Z/s){$self->emit_item_tag($otext,$1,1);}push@{$self->{HTML}},'';}push@{$self->{HTML}},"\n";}sub process_over{my$self=shift->class_obj;
push@{$self->{HTML}},"\n\n";
$self->{listlevel}++;
push(@{$self->{items_seen}},0);
$self->{after_lpar}=0;}sub process_back{my$self=shift->class_obj;
if($self->{listlevel}==0){warn ref($self)." $self->{podfile}: unexpected =back directive in paragraph $self->{paragraph}. ignoring.\n" unless$self->{quiet};
return;}push@{$self->{HTML}},"\n\n";
$self->{listlevel}--;
if(defined$self->{listend}->[$self->{listlevel}]){push@{$self->{HTML}},qq'\n' if$self->{after_lpar};
push@{$self->{HTML}},$self->{listend}->[$self->{listlevel}];
push@{$self->{HTML}},"\n";
pop(@{$self->{listend}});}$self->{after_lpar}=0;
pop(@{$self->{items_seen}});}sub process_cut{my$self=shift->class_obj;
$self->{ignore}=1;}sub process_pod{my$self=shift->class_obj;}sub process_for{my$self=shift->class_obj;
my($whom,$text)=@_;
if($whom=~/^(pod2)?xhtml$/i){push@{$self->{HTML}},$text;}elsif($whom=~/^illustration$/i){1 while chomp$text;
for my $ext(qw[.png .gif .jpeg .jpg .tga .pcl .bmp]){$text.=$ext,last if-r"$text$ext";}push@{$self->{HTML}},qq{
};}}sub process_begin{my$self=shift->class_obj;
my($whom,$text)=@_;
$whom=lc($whom);
push(@{$self->{begin_stack}},$whom);
if($whom=~/^(pod2)?xhtml$/){push@{$self->{HTML}},$text if$text;}}sub process_end{my$self=shift->class_obj;
my($whom,$text)=@_;
$whom=lc($whom);
if($self->{begin_stack}->[-1]ne$whom){die"Unmatched begin/end at chunk $self->{paragraph}\n";}pop(@{$self->{begin_stack}});}sub process_pre{my$self=shift->class_obj;
my($text)=@_;
my($rest);
return if$self->{ignore};
$rest=$$text;
$rest=~s#.*#
my $line = $&;
1 while $line =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e;
$line;
#eg;
$rest=~s/&/&/g;
$rest=~s/</g;
$rest=~s/>/>/g;
$rest=~s/"/"/g;
$rest=~s{
(\s*)(perl\w+)
}{
if ( defined $self->{pages}->{$2} ){ # is a link
qq($1$2);
} elsif (defined $self->{pages}->{$self->dosify($2)}) { # is a link
qq($1$2);
} else {
"$1$2";
}
}xeg;
$rest=~s{
({htmldir}$old_url" if $old_url =~ m{^\/};
$url =$self->relativize_url( "$old_url.html", $self->{htmlfileurl} );
} else {
$url = "$3.html" ;
}
"$1$url" ;
}xeg;
my$urls='('.join('|',
qw{
http
telnet
mailto
news
gopher
file
wais
ftp
}
).')';
my$ltrs='\w';
my$gunk='/#~:.?+=&%@!\-';
my$punc='.:?\-';
my$any="${ltrs}${gunk}${punc}";
$rest=~s{
\b # start at word boundary
( # begin $1 {
$urls : # need resource and a colon
(?!:) # Ignore File::, among others.
[$any]+? # followed by one or more
# of any valid character, but
# be conservative and take only
# what you need to....
) # end $1 }
(?= # look-ahead non-consumptive assertion
[$punc]* # either 0 or more punctuation
[^$any] # followed by a non-url char
| # or else
$ # the end of the string
)
}{$1}igox;
$$text=$rest;}sub pure_text{my$self=shift->class_obj;
my$text=shift();
$self->process_puretext($text,\$self->{ptQuote},1);}sub inIS_text{my$self=shift->class_obj;
my$text=shift();
$self->process_puretext($text,\$self->{ptQuote},0);}sub process_puretext{my$self=shift->class_obj;
my($text,$quote,$notinIS)=@_;
my(@words,$lead,$trail);
if($$quote&&$text=~s/"/$self->{rdq}/s){$$quote=0;}while($text=~s/"([^"]*)"/$self->{ldq}$1$self->{rdq}/sg){}$$quote=1 if$text=~s/"/$self->{ldq}/s;
$lead=($text=~s/\A(\s+)//s?$1:"");
$trail=($text=~s/(\s+)\Z//s?$1:"");
@words=split(/(?<=\s)(?=\S)|(?<=\S)(?=\s)/,$text);
foreach my $word(@words){next if$word=~/^\s*$/;
if($notinIS&&$word=~/^(\w+)\((.*)\)$/){my($func,$args)=($1,$2);
if($args=~/^\d+$/){my$url=$self->page_sect($word,'');
if(defined$url){$word=qq'the $word manpage';
next;}}$word=$self->emit_C($func,'',"($args)");}elsif($word=~m,^\w+://\w,){$word=qq'$word';}elsif($word=~/[\w.-]+\@[\w-]+\.\w/){my($w1,$w2,$w3)=("",$word,"");
($w1,$w2,$w3)=("(",$1,")$2")if$word=~/^\((.*?)\)(,?)/;
($w1,$w2,$w3)=("<",$1,">$2")if$word=~/^<(.*?)>(,?)/;
$word=qq'$w1$w2$w3';}else{$word=$self->html_escape($word)if$word=~/["&<>]/;}}return$lead.join('',@words).$trail;}sub pattern{my$self=shift->class_obj;
$_[0]?'[^\S\n]+'.('>' x($_[0]+1)):'>';}sub closing{my$self=shift->class_obj;
local($_)=shift;
(defined&&s/\s+$//)?length:0;}sub process_text{my$self=shift->class_obj;
return if$self->{ignore};
my($tref)=@_;
my$res=$self->process_text1(0,$tref);
$$tref=$res;}sub process_text1{my$self=shift->class_obj;
my($lev,$rstr,$func,$closing)=@_;
my$res='';
unless(defined$func){$func='';
$lev++;}if($func eq 'B'){$res=''.$self->process_text1($lev,$rstr).'';}elsif($func eq 'C'){my$par=$self->go_ahead($rstr,'C',$closing);
my$text=$self->depod($par);
$res=$self->emit_C($text,$lev>1||($par=~/[BI]));}elsif($func eq 'E'){$$rstr=~s/^([^>]*)>//;
my$escape=$1;
$escape=~s/^(\d+|X[\dA-F]+)$/#$1/i;
$res="&$escape;";}elsif($func eq 'F'){$res=''.$self->process_text1($lev,$rstr).'';}elsif($func eq 'I'){$res=''.$self->process_text1($lev,$rstr).'';}elsif($func eq 'L'){my$par=$self->go_ahead($rstr,'L',$closing);
if($par=~m{^\w+://}s){return$self->make_URL_href($par);}if($par=~/^C<(.*)>$/){my$text=$self->depod($1);
return$self->emit_C($text,$lev>1||($par=~/[BI]));}$par=~s/\n/ /g;
my$opar=$par;
my$linktext;
if($par=~s{^([^|]+)\|}{}){$linktext=$1;}$par=~s{^"}{/"};
my($page,$section,$ident);
if($par=~m{^([^/]+?)/(?!")(.*?)$}){($page,$ident)=($1,$2);}elsif($par=~m{^(.*?)/"?(.*?)"?$}){($page,$ident)=($1,$2);}elsif($par=~/\s/){($page,$section)=('',$par);}else{($page,$section)=($par,'');}defined and s/\(\s*\d+\s*\)//g foreach$page,$section,$ident;
my($url,$ltext,$fid);
RESOLVE:{if(defined$ident){($url,$fid)=$self->coderef($page,$ident);
if($url){if(!defined($linktext)){$linktext=$ident;
$linktext.=" in " if$ident&&$page;
$linktext.="the $page manpage" if$page;}last RESOLVE;}$section=$ident;}my$htmlsection=$self->htmlify($section);
$url=$self->page_sect($page,$htmlsection);
if($url){if(!defined($linktext)){$linktext=$section;
$linktext.=" in " if$section&&$page;
$linktext.="the $page manpage" if$page;}last RESOLVE;}if($section){$ident=$section;}else{$ident=$page;
$page=undef();}($url,$fid)=$self->coderef($page,$ident);
if($url){if(!defined($linktext)){$linktext=$ident;
$linktext.=" in " if$ident&&$page;
$linktext.="the $page manpage" if$page;}last RESOLVE;}$linktext=$opar unless defined$linktext;
warn ref($self).": $self->{podfile}: cannot resolve L<$opar> $page $section $ident in paragraph $self->{paragraph}." unless$self->{quiet};}$$rstr=$linktext.'>'.$$rstr;
if(defined($url)){$res=qq''.$self->process_text1($lev,$rstr).'';}else{$res=''.$self->process_text1($lev,$rstr).'';}}elsif($func eq 'S'){$res=$self->process_text1($lev,$rstr);
$res=~s/ / /g;}elsif($func eq 'X'){$$rstr=~s/^[^>]*>//;}elsif($func eq 'Z'){warn ref($self)." $self->{podfile}: invalid X<> in paragraph $self->{paragraph}." unless$$rstr=~s/^>// or$self->{quiet};}else{my$term=$self->pattern($closing);
while($$rstr=~s/\A(.*?)(([BCEFILSXZ])<(<+[^\S\n]+)?|$term)//s){my$pt=$1;
$pt.=$2 if!$3&&$lev==1;
$res.=$lev==1?$self->pure_text($pt):$self->inIS_text($pt);
return$res if!$3&&$lev>1;
if($3){$res.=$self->process_text1($lev,$rstr,$3,$self->closing($4));}}if($lev==1){$res.=$self->pure_text($$rstr);}else{warn ref($self)." $self->{podfile}: undelimited $func<> in paragraph $self->{paragraph}." unless$self->{quiet};}}return$res;}sub go_ahead{my$self=shift->class_obj;
my($rstr,$func,$closing)=@_;
my$res='';
my@closing=($closing);
while($$rstr=~s/\A(.*?)(([BCEFILSXZ])<(<+[^\S\n]+)?|@{[$self->pattern($closing[0])]})//s){$res.=$1;
unless($3){shift@closing;
return$res unless@closing;}else{unshift@closing,$self->closing($4);}$res.=$2;}warn ref($self)." $self->{podfile}: undelimited $func<> in paragraph $self->{paragraph}." unless$self->{quiet};
return$res;}sub emit_C{my$self=shift->class_obj;
my($text,$nocode,$args)=@_;
$args='' unless defined$args;
my$res;
my($url,$fid)=$self->coderef(undef(),$text);
my$linktext=$self->html_escape("$text$args");
if(defined($url)&&(!defined($self->{EmittedItem})||$self->{EmittedItem}ne$fid)){$res=qq'$linktext';}elsif(0&&$nocode){$res=$linktext;}else{$res="$linktext";}return$res;}sub html_escape{my$self=shift->class_obj;
my$rest=$_[0];
$rest=~s/&/&/g;
$rest=~s/</g;
$rest=~s/>/>/g;
$rest=~s/"/"/g;
return$rest;}sub dosify{my$self=shift->class_obj;
my($str)=@_;
return lc($str)if$^O eq 'VMS';
if($self->{Is83}){$str=lc$str;
$str=~s/(\.\w+)/substr ($1,0,4)/ge;
$str=~s/(\w+)/substr ($1,0,8)/ge;}return$str;}sub page_sect{my$self=shift->class_obj;
my($page,$section)=@_;
my($linktext,$page83,$link);
if(!defined$self->{pages}->{$page}&&defined$self->{sections}->{$page}){$section=$page;
$page="";}$page83=$self->dosify($page);
$page=$page83 if(defined$self->{pages}->{$page83});
if($page eq""){$link="#".$self->htmlify($section);}elsif($page=~/::/){$page=~s,::,/,g;
my$page_name=$page;
$page_name=~s,^.*/,,s;
if(defined($self->{pages}->{$page_name})&&$self->{pages}->{$page_name}=~/([^:]*$page)\.(?:pod|pm):/){$page=$1;}else{}$link="$self->{htmlroot}/$page.html";
$link.="#".$self->htmlify($section)if($section);}elsif(!defined$self->{pages}->{$page}){$link="";}else{$section=$self->htmlify($section)if$section ne"";
if($section ne""&&$self->{pages}->{$page}=~/([^:]*(?{htmlroot}/$1/$section.html";}else{$section="#$section" if$section;
if($self->{pages}->{$page}=~/([^:]*)\.pod:/){$link="$self->{htmlroot}/$1.html$section";}elsif($self->{pages}->{$page}=~/([^:]*)\.pm:/){$link="$self->{htmlroot}/$1.html$section";}else{$link="";}}}if($link){my$url;
if($self->{htmlfileurl}ne ''){$link="$self->{htmldir}$link" if$link=~m{^/}s;
$url=$self->relativize_url($link,$self->{htmlfileurl});}else{$url=$link;}return$url;}else{return undef();}}sub relativize_url{my$self=shift->class_obj;
my($dest,$source)=@_;
my($dest_volume,$dest_directory,$dest_file)=File::Spec::Unix->splitpath($dest);
$dest=File::Spec::Unix->catpath($dest_volume,$dest_directory,'');
my($source_volume,$source_directory,$source_file)=File::Spec::Unix->splitpath($source);
$source=File::Spec::Unix->catpath($source_volume,$source_directory,'');
my$rel_path='';
if($dest ne ''){$rel_path=File::Spec::Unix->abs2rel($dest,$source);}if($rel_path ne ''&&substr($rel_path,-1)ne '/'&&substr($dest_file,0,1)ne '#'){$rel_path.="/$dest_file";}else{$rel_path.="$dest_file";}return$rel_path;}sub coderef{my$self=shift->class_obj;
my($page,$item)=@_;
my($url);
my$fid=$self->fragment_id($item);
if(defined($page)){$page=~s{::}{/}g;
my$base=$self->{items}->{$fid}||"";
$base=~s{[^/]*/}{};
if($base ne"$page.html"){$page=undef();}}else{if(defined($fid)){if(exists$self->{local_items}->{$fid}){$page=$self->{local_items}->{$fid};}else{$page=$self->{items}->{$fid};}}}if(defined$page){if($page){if(exists$self->{pages}->{$page}and$self->{pages}->{$page}=~/([^:.]*)\.[^:]*:/){$page=$1.'.html';}my$link="$self->{htmlroot}/$page#item_$fid";
if($self->{htmlfileurl}ne ''){$link="$self->{htmldir}$link";
$url=$self->relativize_url($link,$self->{htmlfileurl});}else{$url=$link;}}else{$url="#item_".$fid;}confess"url has space: $url" if$url=~/"[^"]*\s[^"]*"/;}return($url,$fid);}sub relative_url{my$self=shift->class_obj;
my$source_file=shift;
my$destination_file=shift;
my$source=URI::file->new_abs($source_file);
my$uo=URI::file->new($destination_file,$source)->abs;
return$uo->rel->as_string;}sub finish_list{my$self=shift->class_obj;
while($self->{listlevel}>0){push@{$self->{HTML}},"\n";
$self->{listlevel}--;}}sub htmlify{my$self=shift->class_obj;
my($heading)=@_;
$heading=~s/(\s+)/ /g;
$heading=~s/\s+\Z//;
$heading=~s/\A\s+//;
$heading=~s/[-"?]//g;
$heading=lc($heading);
return$heading;}sub depod{my$self=shift->class_obj;
my$string;
if(ref($_[0])){$string=${$_[0]};
${$_[0]}=$self->depod1(\$string);}else{$string=$_[0];
$self->depod1(\$string);}}sub depod1{my$self=shift->class_obj;
my($rstr,$func,$closing)=@_;
my$res='';
return$res unless defined$$rstr;
if(!defined($func)){while($$rstr=~s/\A(.*?)([BCEFILSXZ])<(<+[^\S\n]+)?//){$res.=$1.$self->depod1($rstr,$2,$self->closing($3));}$res.=$$rstr;}elsif($func eq 'E'){$$rstr=~s/^([^>]*)>//;
$res.=$self->{E2c}->{$1}||"";}elsif($func eq 'X'){$$rstr=~s/^[^>]*>//;}elsif($func eq 'Z'){$$rstr=~s/^>//;}else{my$term=$self->pattern($closing);
while($$rstr=~s/\A(.*?)(([BCEFILSXZ])<(<+[^\S\n]+)?|$term)//){$res.=$1;
last unless$3;
$res.=$self->depod1($rstr,$3,$self->closing($4));}}return$res;}sub fragment_id{my$self=shift->class_obj;
my$text=$self->_fragment_id(shift);
return$text unless defined($text);
$text=~s/\s+/_/sg;
$text=~s{(\W)}{
defined( $self->{hc}->[ord($1)] ) ? $self->{hc}->[ord($1)]
: ( $self->{hc}->[ord($1)] = sprintf( "%%%02X", ord($1) ) ) }gxe;
$text=substr($text,0,50);
$text;}sub _fragment_id{my$self=shift->class_obj;
my$text=shift@_;
$text=~s/\s+\Z//s;
$text=~s/\A\s+//s;
local$_=$text;
my$ret;
if($text){if(m{^
(\s*-[rwxoRWXOezsfdlpSbctugkTBMAC]|[a-z\d]+)
(\s+[:A-Z\d,\(\)/& ]+)?
$
}x
){$ret=[$1,"Functions"];}elsif(m{^([a-z\d]+)\s+Module(\s+[A-Z\d,/& ]+)?$}){$ret=[$1,"Functions"];}elsif(/(\w+)\s*\(/){$ret=[$1,"Functions"];}elsif(/->\s*(\w+)\s*\(?/){$ret=[$1,"Functions"];}elsif(/^\s*([\$\@\%\*]\S+)/){$ret=[$1,"Variables"];}elsif(m|^(\w+/).*/\w*$|){my$rop=$1."/";
$rop.="/" if$rop=~/^([sy]|tr)/;
$ret=[$rop,"Functions"];}elsif(m|^(\w+)\s*{.*}$|){$ret=[$1,"Functions"];}else{$ret=[$text,"Sections"];}return@_?$ret:$ret->[0];}else{return;}}sub make_URL_href{my$self=shift->class_obj;
my($url)=@_;
if($url!~s{^(http:[-\w/#~:.+=&%@!]+)(\?.*)$}{$1}i){$url=qq'$url';}return$url;}1;