File Coverage

blib/lib/Pod/WinHtml.pm
Criterion Covered Total %
statement 24 628 3.8
branch 0 384 0.0
condition 0 75 0.0
subroutine 8 42 19.0
pod 0 34 0.0
total 32 1163 2.7


line stmt bran cond sub pod time code
1             # $File: //member/autrijus/Pod-HtmlHelp/WinHtml.pm $ $Author: autrijus $
2             # $Revision: #1 $ $Change: 1 $ $DateTime: 2002/06/11 08:35:12 $
3              
4             package Pod::WinHtml;
5              
6 1     1   1685 use Pod::Functions;
  1         3903  
  1         179  
7 1     1   1254 use Getopt::Long; # package for handling command-line parameters
  1         13539  
  1         6  
8             require Exporter;
9 1     1   246 use vars qw($VERSION);
  1         2  
  1         70  
10              
11             $VERSION = 1.01;
12             @ISA = Exporter;
13             @EXPORT = qw(pod2html htmlify);
14              
15 1     1   5 use Cwd;
  1         2  
  1         65  
16 1     1   6 use Carp;
  1         1  
  1         63  
17 1     1   7 use strict;
  1         2  
  1         32  
18 1     1   1488 use locale; # make \w work right in non-ASCII lands
  1         228  
  1         5  
19 1     1   27 use Config;
  1         2  
  1         12653  
20              
21             my $dircache = "pod2html-dircache";
22             my $itemcache = "pod2html-itemcache";
23              
24             my @begin_stack = (); # begin/end stack
25              
26             my @libpods = (); # files to search for links from C<> directives
27             my $htmlroot = "/"; # http-server base directory from which all
28             # relative paths in $podpath stem.
29             my $htmlfile = ""; # write to stdout by default
30             my $podfile = ""; # read from stdin by default
31             my @podpath = (); # list of directories containing library pods.
32             my $podroot = "."; # filesystem base directory from which all
33             # relative paths in $podpath stem.
34             my $css = '';
35              
36             my $csslink = "";
37             $csslink =~ s{\\}{/}g;
38             $csslink =~ s{(/.):}{$1|};
39             my $recurse = 1; # recurse on subdirectories in $podpath.
40             my $verbose = 0; # not verbose by default
41             my $doindex = 1; # non-zero if we should generate an index
42             my $listlevel = 0; # current list depth
43             my @listitem = (); # stack of HTML commands to use when a =item is
44             # encountered. the top of the stack is the
45             # current list.
46             my @listdata = (); # similar to @listitem, but for the text after
47             # an =item
48             my @listend = (); # similar to @listitem, but the text to use to
49             # end the list.
50             my $ignore = 1; # whether or not to format text. we don't
51             # format text until we hit our first pod
52             # directive.
53              
54             my %items_named = (); # for the multiples of the same item in perlfunc
55             my @items_seen = ();
56             my $netscape = 0; # whether or not to use netscape directives.
57             my $title; # title to give the pod(s)
58             my $top = 1; # true if we are at the top of the doc. used
59             # to prevent the first
directive.
60             my $paragraph; # which paragraph we're processing (used
61             # for error messages)
62             my %pages = (); # associative array used to find the location
63             # of pages referenced by L<> links.
64             my %sections = (); # sections within this page
65             my %items = (); # associative array used to find the location
66             # of =item directives referenced by C<> links
67             my $Is83; # is dos with short filenames (8.3)
68              
69             sub init_globals {
70 0     0 0   $dircache = "pod2html.dir";
71 0           $itemcache = "pod2html.itm";
72              
73 0           @begin_stack = (); # begin/end stack
74              
75 0           @libpods = (); # files to search for links from C<> directives
76 0           $htmlroot = "/"; # http-server base directory from which all
77             # relative paths in $podpath stem.
78 0           $htmlfile = ""; # write to stdout by default
79 0           $podfile = ""; # read from stdin by default
80 0           @podpath = (); # list of directories containing library pods.
81 0           $podroot = "."; # filesystem base directory from which all
82             # relative paths in $podpath stem.
83 0           $recurse = 1; # recurse on subdirectories in $podpath.
84 0           $verbose = 0; # not verbose by default
85 0           $doindex = 1; # non-zero if we should generate an index
86 0           $listlevel = 0; # current list depth
87 0           @listitem = (); # stack of HTML commands to use when a =item is
88             # encountered. the top of the stack is the
89             # current list.
90 0           @listdata = (); # similar to @listitem, but for the text after
91             # an =item
92 0           @listend = (); # similar to @listitem, but the text to use to
93             # end the list.
94 0           $ignore = 1; # whether or not to format text. we don't
95             # format text until we hit our first pod
96             # directive.
97              
98 0           @items_seen = ();
99 0           %items_named = ();
100 0           $netscape = 0; # whether or not to use netscape directives.
101 0           $title = ''; # title to give the pod(s)
102 0           $top = 1; # true if we are at the top of the doc. used
103             # to prevent the first
directive.
104 0           $paragraph = ''; # which paragraph we're processing (used
105             # for error messages)
106 0           %sections = (); # sections within this page
107              
108             # These are not reinitialised here but are kept as a cache.
109             # See get_cache and related cache management code.
110             #%pages = (); # associative array used to find the location
111             # of pages referenced by L<> links.
112             #%items = (); # associative array used to find the location
113             # of =item directives referenced by C<> links
114 0           $Is83=$^O eq 'dos';
115             }
116              
117             my $hashead;
118              
119             sub pod2html {
120 0     0 0   local(@ARGV) = @_;
121 0           local($/);
122 0           local $_;
123              
124 0           init_globals();
125              
126 0 0 0       $Is83 = 0 if (defined (&Dos::UseLFN) && Dos::UseLFN());
127              
128             # cache of %pages and %items from last time we ran pod2html
129              
130             #undef $opt_help if defined $opt_help;
131              
132             # parse the command-line parameters
133 0           parse_command_line();
134              
135             # Setup the stylsheet link if one was provided
136 0 0         $csslink = qq()
137             if $css;
138              
139             # set some variables to their default values if necessary
140 0           local *POD;
141 0 0 0       unless (@ARGV && $ARGV[0]) {
142 0 0         $podfile = "-" unless $podfile; # stdin
143 0 0         open(POD, "<$podfile")
144             || die "$0: cannot open $podfile file for input: $!\n";
145             } else {
146 0           $podfile = $ARGV[0]; # XXX: might be more filenames
147 0           *POD = *ARGV;
148             }
149 0 0         $htmlfile = "-" unless $htmlfile; # stdout
150 0 0         $htmlroot = "" if $htmlroot eq "/"; # so we don't get a //
151              
152             # read the pod a paragraph at a time
153 0 0         warn "Scanning for sections in input file(s)\n" if $verbose;
154 0           $/ = "";
155 0           my @poddata = ;
156 0           close(POD);
157              
158             # scan the pod for =head[1-6] directives and build an index
159 0           my $index = scan_headings(\%sections, @poddata);
160              
161 0 0         unless($index) {
162 0 0         warn "No pod in $podfile\n" if $verbose;
163 0           return;
164             }
165              
166             # open the output file
167 0 0         open(HTML, ">$htmlfile")
168             || die "$0: cannot open $htmlfile file for output: $!\n";
169              
170             # put a title in the HTML file if one wasn't specified
171 0 0         if ($title eq '') {
172             TITLE_SEARCH: {
173 0           for (my $i = 0; $i < @poddata; $i++) {
  0            
174 0 0         if ($poddata[$i] =~ /^=head1\s*(NAME|\Q¦WºÙ\E)/m) {
175 0           for my $para ( @poddata[$i, $i+1] ) {
176             last TITLE_SEARCH
177 0 0         if ($title) = $para =~ /(\S+\s+-+.*\S)/s;
178             }
179             }
180              
181             }
182             }
183             }
184 0 0 0       if (!$title and $podfile =~ /\.pod$/) {
185 0           $doindex = 0; # XXX autrijus
186             # probably a split pod so take first =head[12] as title
187             # for (my $i = 0; $i < @poddata; $i++) {
188             # last if ($title) = $poddata[$i] =~ /^=head[12]\s*(.*)/;
189             # }
190             # warn "adopted '$title' as title for $podfile\n"
191             # if $verbose and $title;
192             }
193 0 0         if ($title) {
194 0           $title =~ s/\s*\(.*\)//;
195             } else {
196 0           $hashead = grep { /^=head1\s/ } @poddata;
  0            
197             # warn "$0: no title for $podfile";
198             # $podfile =~ /^(.*)(\.[^.\/]+)?$/;
199             # $title = ($podfile eq "-" ? 'No Title' : $1);
200             # warn "using $title" if $verbose;
201             }
202 0 0         my $charset = qq(
203            
204             ) if $htmlfile =~ /zh[-_]tw/;
205              
206 0 0         my $h1 = $title ? "

$title

" : '';
207 0           print HTML <
208            
209            
210             $title
211            
212             $charset
213             $csslink
214            
215            
216              
217             $h1
218            
219             END_OF_HEAD
220              
221             # load/reload/validate/cache %pages and %items
222 0           get_cache($dircache, $itemcache, \@podpath, $podroot, $recurse);
223              
224             # scan the pod for =item directives
225 0           scan_items("", \%items, @poddata);
226              
227             # put an index at the top of the file. note, if $doindex is 0 we
228             # still generate an index, but surround it with an html comment.
229             # that way some other program can extract it if desired.
230 0           $index =~ s/--+/-/g;
231 0           print HTML "\n";
232 0 0         print HTML "\n" unless $doindex;
235 0           print HTML "\n\n";
236 0 0         print HTML "
\n" if $doindex;
237              
238             # now convert this file
239 0 0         warn "Converting input file\n" if $verbose;
240 0           foreach my $i (0..$#poddata) {
241 0           $_ = $poddata[$i];
242 0           $paragraph = $i+1;
243 0 0         if (/^(=.*)/s) { # is it a pod directive?
244 0           $ignore = 0;
245 0           $_ = $1;
246 0 0         if (/^=begin\s+(\S+)\s*(.*)/si) {# =begin
    0          
    0          
    0          
247 0           process_begin($1, $2);
248             } elsif (/^=end\s+(\S+)\s*(.*)/si) {# =end
249 0           process_end($1, $2);
250             } elsif (/^=cut/) { # =cut
251 0           process_cut();
252             } elsif (/^=pod/) { # =pod
253 0           process_pod();
254             } else {
255 0 0 0       next if @begin_stack && $begin_stack[-1] ne 'html';
256              
257 0 0         if (/^=(head[1-6])\s+(.*\S)/s) { # =head[1-6] heading
    0          
    0          
    0          
    0          
258 0           process_head($1, $2);
259             } elsif (/^=item\s*(.*\S)/sm) { # =item text
260 0           process_item($1);
261             } elsif (/^=over\s*(.*)/) { # =over N
262 0           process_over();
263             } elsif (/^=back/) { # =back
264 0           process_back();
265             } elsif (/^=for\s+(\S+)\s+(.*)/si) {# =for
266 0           process_for($1,$2);
267             } else {
268 0           /^=(\S*)\s*/;
269 0           warn "$0: $podfile: unknown pod directive '$1' in "
270             . "paragraph $paragraph. ignoring.\n";
271             }
272             }
273 0           $top = 0;
274             }
275             else {
276 0 0         next if $ignore;
277 0 0 0       next if @begin_stack && $begin_stack[-1] ne 'html';
278 0           my $text = $_;
279 0           process_text(\$text, 1);
280 0           print HTML "

\n$text

\n";
281             }
282             }
283              
284             # finish off any pending directives
285 0           finish_list();
286 0           print HTML <<"END_OF_TAIL";
287            
288            
289            
290             END_OF_TAIL
291              
292             # close the html file
293 0           close(HTML);
294              
295 0 0         warn "Finished\n" if $verbose;
296             }
297              
298             ##############################################################################
299              
300             my $usage; # see below
301             sub usage {
302 0     0 0   my $podfile = shift;
303 0 0         warn "$0: $podfile: @_\n" if @_;
304 0           die $usage;
305             }
306              
307             $usage =<
308             Usage: $0 --help --htmlroot= --infile= --outfile=
309             --podpath=:...: --podroot=
310             --libpods=:...: --recurse --verbose --index
311             --netscape --norecurse --noindex
312              
313             --flush - flushes the item and directory caches.
314             --help - prints this message.
315             --htmlroot - http-server base directory from which all relative paths
316             in podpath stem (default is /).
317             --index - generate an index at the top of the resulting html
318             (default).
319             --infile - filename for the pod to convert (input taken from stdin
320             by default).
321             --libpods - colon-separated list of pages to search for =item pod
322             directives in as targets of C<> and implicit links (empty
323             by default). note, these are not filenames, but rather
324             page names like those that appear in L<> links.
325             --netscape - will use netscape html directives when applicable.
326             --nonetscape - will not use netscape directives (default).
327             --outfile - filename for the resulting html file (output sent to
328             stdout by default).
329             --podpath - colon-separated list of directories containing library
330             pods. empty by default.
331             --podroot - filesystem base directory from which all relative paths
332             in podpath stem (default is .).
333             --noindex - don't generate an index at the top of the resulting html.
334             --norecurse - don't recurse on those subdirectories listed in podpath.
335             --recurse - recurse on those subdirectories listed in podpath
336             (default behavior).
337             --title - title that will appear in resulting html file.
338             --verbose - self-explanatory
339              
340             END_OF_USAGE
341              
342             sub parse_command_line {
343 0     0 0   my ($opt_flush,$opt_help,$opt_htmlroot,$opt_index,$opt_infile,$opt_libpods,$opt_netscape,$opt_outfile,$opt_podpath,$opt_podroot,$opt_norecurse,$opt_recurse,$opt_title,$opt_verbose,$opt_css,$opt_embedcss);
344 0           my $result = GetOptions(
345             'flush' => \$opt_flush,
346             'help' => \$opt_help,
347             'htmlroot=s' => \$opt_htmlroot,
348             'index!' => \$opt_index,
349             'infile=s' => \$opt_infile,
350             'libpods=s' => \$opt_libpods,
351             'netscape!' => \$opt_netscape,
352             'outfile=s' => \$opt_outfile,
353             'podpath=s' => \$opt_podpath,
354             'podroot=s' => \$opt_podroot,
355             'norecurse' => \$opt_norecurse,
356             'recurse!' => \$opt_recurse,
357             'title=s' => \$opt_title,
358             'verbose' => \$opt_verbose,
359             'css=s' => \$opt_css
360             );
361 0 0         usage("-", "invalid parameters") if not $result;
362              
363 0 0         usage("-") if defined $opt_help; # see if the user asked for help
364 0           $opt_help = ""; # just to make -w shut-up.
365              
366 0 0         $podfile = $opt_infile if defined $opt_infile;
367 0 0         $htmlfile = $opt_outfile if defined $opt_outfile;
368              
369 0 0         @podpath = split(":", $opt_podpath) if defined $opt_podpath;
370 0 0         @libpods = split(":", $opt_libpods) if defined $opt_libpods;
371              
372 0 0 0       warn "Flushing item and directory caches\n"
373             if $opt_verbose && defined $opt_flush;
374 0 0         unlink($dircache, $itemcache) if defined $opt_flush;
375              
376 0 0         $htmlroot = $opt_htmlroot if defined $opt_htmlroot;
377 0 0         $podroot = $opt_podroot if defined $opt_podroot;
378              
379 0 0         $doindex = $opt_index if defined $opt_index;
380 0 0         $recurse = $opt_recurse if defined $opt_recurse;
381 0 0         $title = $opt_title if defined $opt_title;
382 0 0         $verbose = defined $opt_verbose ? 1 : 0;
383 0 0         $netscape = $opt_netscape if defined $opt_netscape;
384              
385 0 0         $css = $opt_css if defined $opt_css;
386             }
387              
388              
389             my $saved_cache_key;
390              
391             sub get_cache {
392 0     0 0   my($dircache, $itemcache, $podpath, $podroot, $recurse) = @_;
393 0           my @cache_key_args = @_;
394              
395             # A first-level cache:
396             # Don't bother reading the cache files if they still apply
397             # and haven't changed since we last read them.
398              
399 0           my $this_cache_key = cache_key(@cache_key_args);
400              
401 0 0 0       return if $saved_cache_key and $this_cache_key eq $saved_cache_key;
402              
403             # load the cache of %pages and %items if possible. $tests will be
404             # non-zero if successful.
405 0           my $tests = 0;
406 0 0 0       if (-f $dircache && -f $itemcache) {
407 0 0         warn "scanning for item cache\n" if $verbose;
408 0           $tests = load_cache($dircache, $itemcache, $podpath, $podroot);
409             }
410              
411             # if we didn't succeed in loading the cache then we must (re)build
412             # %pages and %items.
413 0 0         if (!$tests) {
414 0 0         warn "scanning directories in pod-path\n" if $verbose;
415 0           scan_podpath($podroot, $recurse, 0);
416             }
417 0           $saved_cache_key = cache_key(@cache_key_args);
418             }
419              
420             sub cache_key {
421 0     0 0   my($dircache, $itemcache, $podpath, $podroot, $recurse) = @_;
422 0           return join('!', $dircache, $itemcache, $recurse,
423             @$podpath, $podroot, stat($dircache), stat($itemcache));
424             }
425              
426             #
427             # load_cache - tries to find if the caches stored in $dircache and $itemcache
428             # are valid caches of %pages and %items. if they are valid then it loads
429             # them and returns a non-zero value.
430             #
431              
432             sub load_cache {
433 0     0 0   my($dircache, $itemcache, $podpath, $podroot) = @_;
434 0           my($tests);
435 0           local $_;
436              
437 0           $tests = 0;
438              
439 0 0         open(CACHE, "<$itemcache") ||
440             die "$0: error opening $itemcache for reading: $!\n";
441 0           $/ = "\n";
442              
443             # is it the same podpath?
444 0           $_ = ;
445 0           chomp($_);
446 0 0         $tests++ if (join(":", @$podpath) eq $_);
447              
448             # is it the same podroot?
449 0           $_ = ;
450 0           chomp($_);
451 0 0         $tests++ if ($podroot eq $_);
452              
453             # load the cache if its good
454 0 0         if ($tests != 2) {
455 0           close(CACHE);
456 0           return 0;
457             }
458              
459 0 0         warn "loading item cache\n" if $verbose;
460 0           while () {
461 0           /(.*?) (.*)$/;
462 0           $items{$1} = $2;
463             }
464 0           close(CACHE);
465              
466 0 0         warn "scanning for directory cache\n" if $verbose;
467 0 0         open(CACHE, "<$dircache") ||
468             die "$0: error opening $dircache for reading: $!\n";
469 0           $/ = "\n";
470 0           $tests = 0;
471              
472             # is it the same podpath?
473 0           $_ = ;
474 0           chomp($_);
475 0 0         $tests++ if (join(":", @$podpath) eq $_);
476              
477             # is it the same podroot?
478 0           $_ = ;
479 0           chomp($_);
480 0 0         $tests++ if ($podroot eq $_);
481              
482             # load the cache if its good
483 0 0         if ($tests != 2) {
484 0           close(CACHE);
485 0           return 0;
486             }
487              
488 0 0         warn "loading directory cache\n" if $verbose;
489 0           while () {
490 0           /(.*?) (.*)$/;
491 0           $pages{$1} = $2;
492             }
493              
494 0           close(CACHE);
495              
496 0           return 1;
497             }
498              
499             #
500             # scan_podpath - scans the directories specified in @podpath for directories,
501             # .pod files, and .pm files. it also scans the pod files specified in
502             # @libpods for =item directives.
503             #
504             sub scan_podpath {
505 0     0 0   my($podroot, $recurse, $append) = @_;
506 0           my($pwd, $dir);
507 0           my($libpod, $dirname, $pod, @files, @poddata);
508              
509 0 0         unless($append) {
510 0           %items = ();
511 0           %pages = ();
512             }
513              
514             # scan each directory listed in @podpath
515 0           $pwd = getcwd();
516 0 0         chdir($podroot)
517             || die "$0: error changing to directory $podroot: $!\n";
518 0           foreach $dir (@podpath) {
519 0           scan_dir($dir, $recurse);
520             }
521              
522             # scan the pods listed in @libpods for =item directives
523 0           foreach $libpod (@libpods) {
524             # if the page isn't defined then we won't know where to find it
525             # on the system.
526 0 0 0       next unless defined $pages{$libpod} && $pages{$libpod};
527              
528             # if there is a directory then use the .pod and .pm files within it.
529 0 0 0       if ($pages{$libpod} =~ /([^:]*[^(\.pod|\.pm)]):/) {
    0          
530             # find all the .pod and .pm files within the directory
531 0           $dirname = $1;
532 0 0         opendir(DIR, $dirname) ||
533             die "$0: error opening directory $dirname: $!\n";
534 0   0       @files = grep(/(\.pod|\.pm)$/ && ! -d $_, readdir(DIR));
535 0           closedir(DIR);
536              
537             # scan each .pod and .pm file for =item directives
538 0           foreach $pod (@files) {
539 0 0         open(POD, "<$dirname/$pod") ||
540             die "$0: error opening $dirname/$pod for input: $!\n";
541 0           @poddata = ;
542 0           close(POD);
543              
544 0           scan_items("$dirname/$pod", @poddata);
545             }
546              
547             # use the names of files as =item directives too.
548 0           foreach $pod (@files) {
549 0           $pod =~ /^(.*)(\.pod|\.pm)$/;
550 0 0         $items{$1} = "$dirname/$1.html" if $1;
551             }
552             } elsif ($pages{$libpod} =~ /([^:]*\.pod):/ ||
553             $pages{$libpod} =~ /([^:]*\.pm):/) {
554             # scan the .pod or .pm file for =item directives
555 0           $pod = $1;
556 0 0         open(POD, "<$pod") ||
557             die "$0: error opening $pod for input: $!\n";
558 0           @poddata = ;
559 0           close(POD);
560              
561 0           scan_items("$pod", @poddata);
562             } else {
563 0           warn "$0: shouldn't be here (line ".__LINE__."\n";
564             }
565             }
566 0           @poddata = (); # clean-up a bit
567              
568 0 0         chdir($pwd)
569             || die "$0: error changing to directory $pwd: $!\n";
570              
571             # cache the item list for later use
572 0 0         warn "caching items for later use\n" if $verbose;
573 0 0         open(CACHE, ">$itemcache") ||
574             die "$0: error open $itemcache for writing: $!\n";
575              
576 0           print CACHE join(":", @podpath) . "\n$podroot\n";
577 0           foreach my $key (keys %items) {
578 0           print CACHE "$key $items{$key}\n";
579             }
580              
581 0           close(CACHE);
582              
583             # cache the directory list for later use
584 0 0         warn "caching directories for later use\n" if $verbose;
585 0 0         open(CACHE, ">$dircache") ||
586             die "$0: error open $dircache for writing: $!\n";
587              
588 0           print CACHE join(":", @podpath) . "\n$podroot\n";
589 0           foreach my $key (keys %pages) {
590 0           print CACHE "$key $pages{$key}\n";
591             }
592              
593 0           close(CACHE);
594             }
595              
596             #
597             # scan_dir - scans the directory specified in $dir for subdirectories, .pod
598             # files, and .pm files. notes those that it finds. this information will
599             # be used later in order to figure out where the pages specified in L<>
600             # links are on the filesystem.
601             #
602             sub scan_dir {
603 0     0 0   my($dir, $recurse) = @_;
604 0           my($t, @subdirs, @pods, $pod, $dirname, @dirs);
605 0           local $_;
606              
607 0           @subdirs = ();
608 0           @pods = ();
609              
610 0 0         opendir(DIR, $dir) ||
611             die "$0: error opening directory $dir: $!\n";
612 0           while (defined($_ = readdir(DIR))) {
613 0 0 0       if (-d "$dir/$_" && $_ ne "." && $_ ne "..") { # directory
    0 0        
    0          
614 0 0         $pages{$_} = "" unless defined $pages{$_};
615 0           $pages{$_} .= "$dir/$_:";
616 0           push(@subdirs, $_);
617             } elsif (/\.pod$/) { # .pod
618 0           s/\.pod$//;
619 0 0         $pages{$_} = "" unless defined $pages{$_};
620 0           $pages{$_} .= "$dir/$_.pod:";
621 0           push(@pods, "$dir/$_.pod");
622             } elsif (/\.pm$/) { # .pm
623 0           s/\.pm$//;
624 0 0         $pages{$_} = "" unless defined $pages{$_};
625 0           $pages{$_} .= "$dir/$_.pm:";
626 0           push(@pods, "$dir/$_.pm");
627             }
628             }
629 0           closedir(DIR);
630              
631             # recurse on the subdirectories if necessary
632 0 0         if ($recurse) {
633 0           foreach my $subdir (@subdirs) {
634 0           scan_dir("$dir/$subdir", $recurse);
635             }
636             }
637             }
638              
639             #
640             # scan_headings - scan a pod file for head[1-6] tags, note the tags, and
641             # build an index.
642             #
643             sub scan_headings {
644 0     0 0   my($sections, @data) = @_;
645 0           my($tag, $which_head, $title, $listdepth, $index);
646              
647             # here we need local $ignore = 0;
648             # unfortunately, we can't have it, because $ignore is lexical
649 0           $ignore = 0;
650              
651 0           $listdepth = 0;
652 0           $index = "";
653              
654             # scan for =head directives, note their name, and build an index
655             # pointing to each of them.
656 0           foreach my $line (@data) {
657 0 0         if ($line =~ /^=(head)([1-6])\s+(.*)/) {
658 0           ($tag,$which_head, $title) = ($1,$2,$3);
659 0           chomp($title);
660 0           $$sections{htmlify(0,$title)} = 1;
661              
662 0           while ($which_head != $listdepth) {
663 0 0         if ($which_head > $listdepth) {
    0          
664 0           $index .= "\n" . ("\t" x $listdepth) . "
    \n";
665 0           $listdepth++;
666             } elsif ($which_head < $listdepth) {
667 0           $listdepth--;
668 0           $index .= "\n" . ("\t" x $listdepth) . "\n";
669             }
670             }
671              
672             # DTG *** Added after the to close the list item
673 0           $index .= "\n" . ("\t" x $listdepth) . "
  • " .
  • 674             "" .
    675             html_escape(process_text(\$title, 0)) . "";
    676             }
    677             }
    678              
    679             # finish off the lists
    680 0           while ($listdepth--) {
    681 0           $index .= "\n" . ("\t" x $listdepth) . "\n";
    682             }
    683              
    684             # get rid of bogus lists
    685 0           $index =~ s,\t*
      \s*
    \n,,g;
    686              
    687 0           $ignore = 1; # restore old value;
    688              
    689 0           return $index;
    690             }
    691              
    692             #
    693             # scan_items - scans the pod specified by $pod for =item directives. we
    694             # will use this information later on in resolving C<> links.
    695             #
    696             sub scan_items {
    697 0     0 0   my($pod, @poddata) = @_;
    698 0           my($i, $item);
    699 0           local $_;
    700              
    701 0           $pod =~ s/\.pod$//;
    702 0 0         $pod .= ".html" if $pod;
    703              
    704 0           foreach $i (0..$#poddata) {
    705 0           $_ = $poddata[$i];
    706              
    707             # remove any formatting instructions
    708 0           s,[A-Z]<([^<>]*)>,$1,g;
    709              
    710             # figure out what kind of item it is and get the first word of
    711             # it's name.
    712 0 0         if (/^=item\s+(\w*)\s*.*$/s) {
    713 0 0         if ($1 eq "*") { # bullet list
        0          
    714 0           /\A=item\s+\*\s*(.*?)\s*\Z/s;
    715 0           $item = $1;
    716             } elsif ($1 =~ /^\d+/) { # numbered list
    717 0           /\A=item\s+\d+\.?(.*?)\s*\Z/s;
    718 0           $item = $1;
    719             } else {
    720             # /\A=item\s+(.*?)\s*\Z/s;
    721 0           /\A=item\s+(\w*)/s;
    722 0           $item = $1;
    723             }
    724              
    725 0 0         $items{$item} = "$pod" if $item;
    726             }
    727             }
    728             }
    729              
    730             #
    731             # process_head - convert a pod head[1-6] tag and convert it to HTML format.
    732             #
    733             sub process_head {
    734 0     0 0   my($tag, $heading) = @_;
    735 0           my $firstword;
    736              
    737             # figure out the level of the =head
    738 0           $tag =~ /head([1-6])/;
    739 0           my $level = $1 + 1;
    740              
    741             # can't have a heading full of spaces and speechmarks and so on
    742 0           $firstword = $heading; $firstword =~ s/\s*(\w+)\s.*/$1/;
      0            
    743              
    744             #print HTML "

    \n" unless $listlevel;

    745 0 0 0       print HTML "
    \n" unless $listlevel || $top;
    746 0           print HTML ""; # unless $listlevel;
    747             #print HTML "" unless $listlevel;
    748 0           my $convert = $heading; process_text(\$convert, 0);
      0            
    749 0           $convert = html_escape($convert);
    750 0           print HTML '$convert";
    751 0           print HTML ""; # unless $listlevel;
    752 0           print HTML "\n";
    753             }
    754              
    755             #
    756             # process_item - convert a pod item tag and convert it to HTML format.
    757             #
    758             sub process_item {
    759 0     0 0   my $text = $_[0];
    760 0           my($i, $quote, $name);
    761              
    762 0           my $need_preamble = 0;
    763 0           my $this_entry;
    764              
    765              
    766             # lots of documents start a list without doing an =over. this is
    767             # bad! but, the proper thing to do seems to be to just assume
    768             # they did do an =over. so warn them once and then continue.
    769 0 0         warn "$0: $podfile: unexpected =item directive in paragraph $paragraph. ignoring.\n"
    770             unless $listlevel;
    771 0 0         process_over() unless $listlevel;
    772              
    773 0 0         return unless $listlevel;
    774              
    775             # remove formatting instructions from the text
    776 0           1 while $text =~ s/[A-Z]<([^<>]*)>/$1/g;
    777 0           pre_escape(\$text);
    778              
    779 0           $need_preamble = $items_seen[$listlevel]++ == 0;
    780              
    781             # check if this is the first =item after an =over
    782 0           $i = $listlevel - 1;
    783 0           my $need_new = $listlevel >= @listitem;
    784              
    785 0 0         if ($text =~ /\A\*/) { # bullet
        0          
    786              
    787 0 0         if ($need_preamble) {
    788 0           push(@listend, "");
    789 0           print HTML "
      \n";
    790             }
    791              
    792 0           print HTML '
  • ';
  • 793 0 0         if ($text =~ /\A\*\s*(.+)\Z/s) {
    794 0           print HTML '';
    795 0 0         if ($items_named{$1}++) {
    796 0           print HTML html_escape($1);
    797             } else {
    798 0           my $name = 'item_' . htmlify(1,$1);
    799 0           print HTML qq(), html_escape($1), '';
    800             }
    801 0           print HTML '';
    802             }
    803              
    804             } elsif ($text =~ /\A[\d#]+/) { # numbered list
    805              
    806 0 0         if ($need_preamble) {
    807 0           push(@listend, "");
    808 0           print HTML "
      \n";
    809             }
    810              
    811 0           print HTML '
  • ';
  • 812 0 0         if ($text =~ /\A\d+\.?\s*(.+)\Z/s) {
    813 0           print HTML '';
    814 0 0         if ($items_named{$1}++) {
    815 0           print HTML html_escape($1);
    816             } else {
    817 0           my $name = 'item_' . htmlify(0,$1);
    818 0           print HTML qq(), html_escape($1), '';
    819             }
    820 0           print HTML '';
    821             }
    822              
    823             } else { # all others
    824              
    825 0 0         if ($need_preamble) {
    826 0           push(@listend, '');
    827 0           print HTML "
    \n";
    828             }
    829              
    830 0           print HTML '
    ';
    831 0 0         if ($text =~ /(\S+)/) {
    832 0           print HTML '';
    833 0 0         if ($items_named{$1}++) {
    834 0           print HTML html_escape($text);
    835             } else {
    836 0           my $name = 'item_' . htmlify(1,$text);
    837 0           print HTML qq(), html_escape($text), '';
    838             }
    839 0           print HTML '';
    840             }
    841 0           print HTML '
    ';
    842             }
    843              
    844 0           print HTML "\n";
    845             }
    846              
    847             #
    848             # process_over - process a pod over tag and start a corresponding HTML
    849             # list.
    850             #
    851             sub process_over {
    852             # start a new list
    853 0     0 0   $listlevel++;
    854             }
    855              
    856             #
    857             # process_back - process a pod back tag and convert it to HTML format.
    858             #
    859             sub process_back {
    860 0 0   0 0   warn "$0: $podfile: unexpected =back directive in paragraph $paragraph. ignoring.\n"
    861             unless $listlevel;
    862 0 0         return unless $listlevel;
    863              
    864             # close off the list. note, I check to see if $listend[$listlevel] is
    865             # defined because an =item directive may have never appeared and thus
    866             # $listend[$listlevel] may have never been initialized.
    867 0           $listlevel--;
    868 0 0         print HTML $listend[$listlevel] if defined $listend[$listlevel];
    869 0           print HTML "\n";
    870              
    871             # don't need the corresponding perl code anymore
    872 0           pop(@listitem);
    873 0           pop(@listdata);
    874 0           pop(@listend);
    875              
    876 0           pop(@items_seen);
    877             }
    878              
    879             #
    880             # process_cut - process a pod cut tag, thus stop ignoring pod directives.
    881             #
    882             sub process_cut {
    883 0     0 0   $ignore = 1;
    884             }
    885              
    886             #
    887             # process_pod - process a pod pod tag, thus ignore pod directives until we see a
    888             # corresponding cut.
    889             #
    890 0     0 0   sub process_pod {
    891             # no need to set $ignore to 0 cause the main loop did it
    892             }
    893              
    894             #
    895             # process_for - process a =for pod tag. if it's for html, split
    896             # it out verbatim, if illustration, center it, otherwise ignore it.
    897             #
    898             sub process_for {
    899 0     0 0   my($whom, $text) = @_;
    900 0 0         if ( $whom =~ /^(pod2)?html$/i) {
        0          
    901 0           print HTML $text;
    902             } elsif ($whom =~ /^illustration$/i) {
    903 0           1 while chomp $text;
    904 0           for my $ext (qw[.png .gif .jpeg .jpg .tga .pcl .bmp]) {
    905 0 0         $text .= $ext, last if -r "$text$ext";
    906             }
    907 0           print HTML qq{

    $text illustration

    };
    908             }
    909             }
    910              
    911             #
    912             # process_begin - process a =begin pod tag. this pushes
    913             # whom we're beginning on the begin stack. if there's a
    914             # begin stack, we only print if it us.
    915             #
    916             sub process_begin {
    917 0     0 0   my($whom, $text) = @_;
    918 0           $whom = lc($whom);
    919 0           push (@begin_stack, $whom);
    920 0 0         if ( $whom =~ /^(pod2)?html$/) {
    921 0 0         print HTML $text if $text;
    922             }
    923             }
    924              
    925             #
    926             # process_end - process a =end pod tag. pop the
    927             # begin stack. die if we're mismatched.
    928             #
    929             sub process_end {
    930 0     0 0   my($whom, $text) = @_;
    931 0           $whom = lc($whom);
    932 0 0         if ($begin_stack[-1] ne $whom ) {
    933 0           die "$0: $podfile: Unmatched begin/end at chunk $paragraph\n"
    934             }
    935 0           pop @begin_stack;
    936             }
    937              
    938             #
    939             # process_text - handles plaintext that appears in the input pod file.
    940             # there may be pod commands embedded within the text so those must be
    941             # converted to html commands.
    942             #
    943             sub process_text {
    944 0     0 0   my($text, $escapeQuotes) = @_;
    945 0           my($result, $rest, $s1, $s2, $s3, $s4, $match, $bf);
    946 0           my($podcommand, $params, $tag, $quote);
    947 0           $htmlroot =~ s|/$||;
    948              
    949 0 0         return if $ignore;
    950              
    951 0           $quote = 0; # status of double-quote conversion
    952 0           $result = "";
    953 0           $rest = $$text;
    954              
    955 0 0         if ($rest =~ /^\s+/) { # preformatted text, no pod directives
    956 0           $rest =~ s/\n+\Z//;
    957 0           $rest =~ s#.*#
    958 0           my $line = $&;
    959 0           1 while $line =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e;
      0            
    960 0           $line;
    961             #eg;
    962              
    963 0           $rest =~ s/&/&/g;
    964 0           $rest =~ s/
    965 0           $rest =~ s/>/>/g;
    966 0           $rest =~ s/"/"/g;
    967              
    968             # try and create links for all occurrences of perl.* within
    969             # the preformatted text.
    970 0           $rest =~ s{
    971             (\s*)(perl\w+)
    972             }{
    973 0 0         if (defined $pages{$2}) { # is a link
        0          
    974 0           qq($1$2);
    975             } elsif (defined $pages{dosify($2)}) { # is a link
    976 0           qq($1$2);
    977             } else {
    978 0           "$1$2";
    979             }
    980             }xeg;
    981 0           $rest =~ s/(:]*:)?([^>:]*)\.pod:([^>:]*:)?/$1$3.html/g;
    982              
    983 0           my $urls = '(' . join ('|', qw{
    984             http
    985             telnet
    986             mailto
    987             news
    988             gopher
    989             file
    990             wais
    991             ftp
    992             } )
    993             . ')';
    994            
    995 0           my $ltrs = '\w';
    996 0           my $gunk = '/#~:.?+=&%@!\-';
    997 0           my $punc = '.:?\-';
    998 0           my $any = "${ltrs}${gunk}${punc}";
    999              
    1000 0           $rest =~ s{
    1001             \b # start at word boundary
    1002             ( # begin $1 {
    1003             $urls : # need resource and a colon
    1004             [$any] +? # followed by on or more
    1005             # of any valid character, but
    1006             # be conservative and take only
    1007             # what you need to....
    1008             ) # end $1 }
    1009             (?= # look-ahead non-consumptive assertion
    1010             [$punc]* # either 0 or more puntuation
    1011             [^$any] # followed by a non-url char
    1012             | # or else
    1013             $ # then end of the string
    1014             )
    1015             }{$1}igox;
    1016              
    1017 0           $result = "
    "	# text should be as it is (verbatim) 
    1018             . "$rest\n"
    1019             . "\n";
    1020             } else { # formatted text
    1021             # parse through the string, stopping each time we find a
    1022             # pod-escape. once the string has been throughly processed
    1023             # we can output it.
    1024              
    1025 0           while (length $rest) {
    1026             # check to see if there are any possible pod directives in
    1027             # the remaining part of the text.
    1028              
    1029 0 0         if ($rest =~ m/[BCEIFLSZ]
    1030 0 0         warn "\$rest\t= $rest\n" unless
    1031             $rest =~ /\A
    1032             ([^<]*?)
    1033             ([BCEIFLSZ]?)
    1034             <
    1035             (.*)\Z/xs;
    1036              
    1037 0           $s1 = $1; # pure text
    1038 0           $s2 = $2; # the type of pod-escape that follows
    1039 0           $s3 = '<'; # '<'
    1040 0           $s4 = $3; # the rest of the string
    1041             } else {
    1042 0           $s1 = $rest;
    1043 0           $s2 = "";
    1044 0           $s3 = "";
    1045 0           $s4 = "";
    1046             }
    1047              
    1048 0 0 0       if ($s3 eq '<' && $s2) { # a pod-escape
    1049 0 0         $result .= ($escapeQuotes ? process_puretext($s1, \$quote) : $s1);
    1050 0           $podcommand = "$s2<";
    1051 0           $rest = $s4;
    1052              
    1053             # find the matching '>'
    1054 0           $match = 1;
    1055 0           $bf = 0;
    1056 0   0       while ($match && !$bf) {
    1057 0           $bf = 1;
    1058 0 0         if ($rest =~ /\A([^<>]*[BCEIFLSZ]<)(.*)\Z/s) {
        0          
    1059 0           $bf = 0;
    1060 0           $match++;
    1061 0           $podcommand .= $1;
    1062 0           $rest = $2;
    1063             } elsif ($rest =~ /\A([^>]*>)(.*)\Z/s) {
    1064 0           $bf = 0;
    1065 0           $match--;
    1066 0           $podcommand .= $1;
    1067 0           $rest = $2;
    1068             }
    1069             }
    1070              
    1071 0 0         if ($match != 0) {
    1072 0           warn <
    1073             $0: $podfile: cannot find matching > for $s2 in paragraph $paragraph.
    1074             WARN
    1075 0           $result .= substr $podcommand, 0, 2;
    1076 0           $rest = substr($podcommand, 2) . $rest;
    1077 0           next;
    1078             }
    1079              
    1080             # pull out the parameters to the pod-escape
    1081 0           $podcommand =~ /^([BCFEILSZ]?)<(.*)>$/s;
    1082 0           $tag = $1;
    1083 0           $params = $2;
    1084              
    1085             # process the text within the pod-escape so that any escapes
    1086             # which must occur do.
    1087 0 0         process_text(\$params, 0) unless $tag eq 'L';
    1088              
    1089 0           $s1 = $params;
    1090 0 0 0       if (!$tag || $tag eq " ") { # <> : no tag
        0 0        
        0 0        
        0          
        0          
        0          
        0          
        0          
    1091 0           $s1 = "<$params>";
    1092             } elsif ($tag eq "L") { # L<> : link
    1093 0           $s1 = process_L($params);
    1094             } elsif ($tag eq "I" || # I<> : italicize text
    1095             $tag eq "B" || # B<> : bold text
    1096             $tag eq "F") { # F<> : file specification
    1097 0           $s1 = process_BFI($tag, $params);
    1098             } elsif ($tag eq "C") { # C<> : literal code
    1099 0           $s1 = process_C($params, 1);
    1100             } elsif ($tag eq "E") { # E<> : escape
    1101 0           $s1 = process_E($params);
    1102             } elsif ($tag eq "Z") { # Z<> : zero-width character
    1103 0           $s1 = process_Z($params);
    1104             } elsif ($tag eq "S") { # S<> : non-breaking space
    1105 0           $s1 = process_S($params);
    1106             } elsif ($tag eq "X") { # S<> : non-breaking space
    1107 0           $s1 = process_X($params);
    1108             } else {
    1109 0           warn "$0: $podfile: unhandled tag '$tag' in paragraph $paragraph\n";
    1110             }
    1111              
    1112 0           $result .= "$s1";
    1113             } else {
    1114             # for pure text we must deal with implicit links and
    1115             # double-quotes among other things.
    1116 0 0         $result .= (
    1117             $escapeQuotes ? process_puretext("$s1$s2$s3", \$quote) : "$s1$s2$s3"
    1118             );
    1119 0           $rest = $s4;
    1120             }
    1121             }
    1122             }
    1123 0           $$text = $result;
    1124             }
    1125              
    1126             sub html_escape {
    1127 0     0 0   my $rest = $_[0];
    1128 0           $rest =~ s/&/&/g;
    1129 0           $rest =~ s/
    1130 0           $rest =~ s/>/>/g;
    1131 0           $rest =~ s/"/"/g;
    1132 0           return $rest;
    1133             }
    1134              
    1135             #
    1136             # process_puretext - process pure text (without pod-escapes) converting
    1137             # double-quotes and handling implicit C<> links.
    1138             #
    1139             sub process_puretext {
    1140 0     0 0   my($text, $quote) = @_;
    1141 0           my(@words, $result, $rest, $lead, $trail);
    1142              
    1143             # convert double-quotes to single-quotes
    1144 0 0         $text =~ s/\A([^"]*)"/$1''/s if $$quote;
    1145 0           while ($text =~ s/\A([^"]*)["]([^"]*)["]/$1``$2''/sg) {}
    1146              
    1147 0 0         $$quote = ($text =~ m/"/ ? 1 : 0);
    1148 0 0         $text =~ s/\A([^"]*)"/$1``/s if $$quote;
    1149              
    1150             # keep track of leading and trailing white-space
    1151 0 0         $lead = ($text =~ /\A(\s*)/s ? $1 : "");
    1152 0 0         $trail = ($text =~ /(\s*)\Z/s ? $1 : "");
    1153              
    1154             # collapse all white space into a single space
    1155 0           $text =~ s/\s+/ /g;
    1156 0           @words = split(" ", $text);
    1157              
    1158             # process each word individually
    1159 0           foreach my $word (@words) {
    1160             # see if we can infer a link
    1161              
    1162 0 0 0       if ($word =~ /^\w+\(/) {
        0          
        0          
        0          
        0          
    1163             # has parenthesis so should have been a C<> ref
    1164              
    1165 0           $word = process_C($word);
    1166              
    1167             # $word =~ /^[^()]*]\(/;
    1168             # if (defined $items{$1} && $items{$1}) {
    1169             # $word = "\n
    1170             # . htmlify(0,$word)
    1171             # . "\">$word";
    1172             # } elsif (defined $items{$word} && $items{$word}) {
    1173             # $word = "\n
    1174             # . htmlify(0,$word)
    1175             # . "\">$word";
    1176             # } else {
    1177             # $word = "\n
    1178             # . htmlify(0,$word)
    1179             # . "\">$word";
    1180             # }
    1181             } elsif ($word =~ /^[\$\@%&*]+\w+$/) {
    1182             # perl variables, should be a C<> ref
    1183 0           $word = process_C($word, 1);
    1184             } elsif ($word =~ m,^\w+://\w,) {
    1185             # looks like a URL
    1186 0           $word = qq($word);
    1187             } elsif ($word =~ /[\w.-]+\@[\w-]+\.\w/) {
    1188             # looks like an e-mail address
    1189              
    1190 0           my ($w1, $w2, $w3) = ("", $word, "");
    1191 0 0         ($w1, $w2, $w3) = ("(", $1, ")$2") if $word =~ /^\((.*?)\)(,?)/;
    1192 0 0         ($w1, $w2, $w3) = ("<", $1, ">$2") if $word =~ /^<(.*?)>(,?)/;
    1193 0           $word = qq($w1$w2$w3);
    1194             } elsif ($word !~ /[a-z]/ && $word =~ /[A-Z]/) { # all uppercase?
    1195 0 0         $word = html_escape($word) if $word =~ /["&<>]/;
    1196 0 0         $word = "\n$word" if $netscape;
    1197             } else {
    1198 0 0         $word = html_escape($word) if $word =~ /["&<>]/;
    1199             }
    1200             }
    1201              
    1202             # build a new string based upon our conversion
    1203 0           $result = "";
    1204 0           $rest = join(" ", @words);
    1205 0           while (length($rest) > 75) {
    1206 0 0 0       if ( $rest =~ m/^(.{0,75})\s(.*?)$/o ||
    1207             $rest =~ m/^(\S*)\s(.*?)$/o) {
    1208              
    1209 0           $result .= "$1\n";
    1210 0           $rest = $2;
    1211             } else {
    1212 0           $result .= "$rest\n";
    1213 0           $rest = "";
    1214             }
    1215             }
    1216 0 0         $result .= $rest if $rest;
    1217              
    1218             # restore the leading and trailing white-space
    1219 0           $result = "$lead$result$trail";
    1220              
    1221 0           return $result;
    1222             }
    1223              
    1224             #
    1225             # pre_escape - convert & in text to $amp;
    1226             #
    1227             sub pre_escape {
    1228 0     0 0   my($str) = @_;
    1229              
    1230 0           $$str =~ s,&,&,g;
    1231             }
    1232              
    1233             #
    1234             # dosify - convert filenames to 8.3
    1235             #
    1236             sub dosify {
    1237 0     0 0   my($str) = @_;
    1238 0 0         if ($Is83) {
    1239 0           $str = lc $str;
    1240 0           $str =~ s/(\.\w+)/substr ($1,0,4)/ge;
      0            
    1241 0           $str =~ s/(\w+)/substr ($1,0,8)/ge;
      0            
    1242             }
    1243 0           return $str;
    1244             }
    1245              
    1246             #
    1247             # process_L - convert a pod L<> directive to a corresponding HTML link.
    1248             # most of the links made are inferred rather than known about directly
    1249             # (i.e it's not known whether the =head\d section exists in the target file,
    1250             # or whether a .pod file exists in the case of split files). however, the
    1251             # guessing usually works.
    1252             #
    1253             # Unlike the other directives, this should be called with an unprocessed
    1254             # string, else tags in the link won't be matched.
    1255             #
    1256             sub process_L {
    1257 0     0 0   my($str) = @_;
    1258 0           my($s1, $s2, $linktext, $page, $page83, $section, $link); # work strings
    1259 0           my $alternate;
    1260 0           my $hyperlink = 0;
    1261              
    1262 0           $str =~ s/\n/ /g; # undo word-wrapped tags
    1263 0           $s1 = $str;
    1264 0           for ($s1) {
    1265             # LREF: a la HREF L
    1266 0 0         $linktext = $1 if s:^([^|]+[^\xa0-\xff])\|::;
    1267 0           $alternate = ($1 eq $linktext);
    1268              
    1269             # make sure sections start with a /
    1270 0           s,^",/",g;
    1271 0 0 0       s,^,/,g if (!m,/, && / /);
    1272              
    1273             # check if there's a section specified
    1274 0 0         if (m,^(.*?)/"?(.*?)"?$,) { # yes
    1275 0           ($page, $section) = ($1, $2);
    1276             } else { # no
    1277 0           $str =~ s:^[^|]+[^\xa0-\xff]\|::;
    1278 0           ($page, $section) = ($str, "");
    1279             }
    1280              
    1281             # check if we know that this is a section in this page
    1282             #if (!defined $pages{$page} && defined $sections{$page}) {
    1283             # $section = $page;
    1284             # $page = "";
    1285             #}
    1286             }
    1287              
    1288 0           $page83=dosify($page);
    1289 0 0         $page=$page83 if (defined $pages{$page83});
    1290 0 0 0       if ($page eq "") {
        0          
        0          
        0          
    1291 0           $link = "#" . htmlify(0,$section);
    1292 0 0         $linktext = $section unless defined($linktext);
    1293             } elsif ( $page =~ /::/ or $page =~ /^\w+$/) {
    1294 0 0         $linktext = ($section ? "$section" : "$page") unless $alternate;
        0          
    1295 0           $page =~ s,::,/,g;
    1296 0           $link = "$htmlroot/$page.html";
    1297 0 0         if ($section) {
    1298             # XXX: autrijus
    1299 0 0         if ($doindex) {
        0          
    1300 0           $link .= "#" . htmlify(0,$section);
    1301             }
    1302             elsif ($hashead) {
    1303 0           $link = "$page/".htmlify(0, $section).".html";
    1304             }
    1305             else {
    1306 0           $link = "../../../$page/".htmlify(0, $section).".html";
    1307             }
    1308             }
    1309             } elsif ($str =~ m{(?:http|ftp|news|telnet|mailto)://}) {
    1310 0           $linktext = $link = $str;
    1311 0 0         $hyperlink = 1 if $str =~ m{(?:http|ftp)://};
    1312             } elsif (!defined $pages{$page}) {
    1313 0           warn "$0: $podfile: cannot resolve L<$str> in paragraph $paragraph: no such page '$page'\n";
    1314 0           $link = "";
    1315 0 0         $linktext = $page unless defined($linktext);
    1316             } else {
    1317 0 0         $linktext = ($section ? "$section" : "the $page manpage") unless defined($linktext);
        0          
    1318 0 0         $section = htmlify(0,$section) if $section ne "";
    1319              
    1320             # if there is a directory by the name of the page, then assume that an
    1321             # appropriate section will exist in the subdirectory
    1322 0 0 0       if ($section ne "" && $pages{$page} =~ /([^:]*[^(\.pod|\.pm)]):/) {
    1323 0           $link = "$htmlroot/$1/$section.html";
    1324              
    1325             # since there is no directory by the name of the page, the section will
    1326             # have to exist within a .html of the same name. thus, make sure there
    1327             # is a .pod or .pm that might become that .html
    1328             } else {
    1329 0           $section = "#$section";
    1330             # check if there is a .pod with the page name
    1331 0 0         if ($pages{$page} =~ /([^:]*)\.pod:/) {
        0          
    1332 0           $link = "$htmlroot/$1.html$section";
    1333             } elsif ($pages{$page} =~ /([^:]*)\.pm:/) {
    1334 0           $link = "$htmlroot/$1.html$section";
    1335             } else {
    1336 0           warn "$0: $podfile: cannot resolve L$str in paragraph $paragraph: ".
    1337             "no .pod or .pm found\n";
    1338 0           $link = "";
    1339 0 0         $linktext = $section unless defined($linktext);
    1340             }
    1341             }
    1342             }
    1343              
    1344 0           $link =~ s|^(?:\./)?(?:\.\./)?\.\./||; # XXX: autrijus
    1345 0 0         $link = "../$link" if $link =~ m|pod/|;
    1346              
    1347 0           process_text(\$linktext, 0);
    1348 0 0         if ($link) {
    1349 0 0         if ($hyperlink) {
    1350 0           $s1 = "$linktext";
    1351             }
    1352             else {
    1353 0           $s1 = "$linktext";
    1354             }
    1355             } else {
    1356 0           $s1 = "$linktext";
    1357             }
    1358 0           return $s1;
    1359             }
    1360              
    1361             #
    1362             # process_BFI - process any of the B<>, F<>, or I<> pod-escapes and
    1363             # convert them to corresponding HTML directives.
    1364             #
    1365             sub process_BFI {
    1366 0     0 0   my($tag, $str) = @_;
    1367 0           my($s1); # work string
    1368 0           my(%repltext) = ( 'B' => 'STRONG',
    1369             'F' => 'EM',
    1370             'I' => 'EM');
    1371              
    1372             # extract the modified text and convert to HTML
    1373 0           $s1 = "<$repltext{$tag}>$str";
    1374 0           return $s1;
    1375             }
    1376              
    1377             #
    1378             # process_C - process the C<> pod-escape.
    1379             #
    1380             sub process_C {
    1381 0     0 0   my($str, $doref) = @_;
    1382 0           my($s1, $s2);
    1383              
    1384 0           $s1 = $str;
    1385 0           $s1 =~ s/\([^()]*\)//g; # delete parentheses
    1386 0           $s2 = $s1;
    1387 0           $s1 =~ s/\W//g; # delete bogus characters
    1388 0           $str = html_escape($str);
    1389              
    1390             # if there was a pod file that we found earlier with an appropriate
    1391             # =item directive, then create a link to that page.
    1392 0 0 0       if ($doref && defined $items{$s1}) {
    1393 0 0         $s1 = ($items{$s1} ?
    1394             "$str" :
    1395             "$str");
    1396 0           $s1 =~ s,(perl\w+/(\S+)\.html)#item_\2\b,$1,;
    1397 0 0         confess "s1 has space: $s1" if $s1 =~ /HREF="[^"]*\s[^"]*"/;
    1398             } else {
    1399 0           $s1 = "$str";
    1400             # warn "$0: $podfile: cannot resolve C<$str> in paragraph $paragraph\n" if $verbose
    1401             }
    1402              
    1403              
    1404 0           return $s1;
    1405             }
    1406              
    1407             #
    1408             # process_E - process the E<> pod directive which seems to escape a character.
    1409             #
    1410             sub process_E {
    1411 0     0 0   my($str) = @_;
    1412              
    1413 0           for ($str) {
    1414 0           s,([^/].*),\&$1\;,g;
    1415             }
    1416              
    1417 0           return $str;
    1418             }
    1419              
    1420             #
    1421             # process_Z - process the Z<> pod directive which really just amounts to
    1422             # ignoring it. this allows someone to start a paragraph with an =
    1423             #
    1424             sub process_Z {
    1425 0     0 0   my($str) = @_;
    1426              
    1427             # there is no equivalent in HTML for this so just ignore it.
    1428 0           $str = "";
    1429 0           return $str;
    1430             }
    1431              
    1432             #
    1433             # process_S - process the S<> pod directive which means to convert all
    1434             # spaces in the string to non-breaking spaces (in HTML-eze).
    1435             #
    1436             sub process_S {
    1437 0     0 0   my($str) = @_;
    1438              
    1439             # convert all spaces in the text to non-breaking spaces in HTML.
    1440 0           return "$str";
    1441             }
    1442              
    1443             #
    1444             # process_X - this is supposed to make an index entry. we'll just
    1445             # ignore it.
    1446             #
    1447             sub process_X {
    1448 0     0 0   return '';
    1449             }
    1450              
    1451              
    1452             #
    1453             # finish_list - finish off any pending HTML lists. this should be called
    1454             # after the entire pod file has been read and converted.
    1455             #
    1456             sub finish_list {
    1457 0     0 0   while ($listlevel > 0) {
    1458 0           print HTML "\n";
    1459 0           $listlevel--;
    1460             }
    1461             }
    1462              
    1463             #
    1464             # htmlify - converts a pod section specification to a suitable section
    1465             # specification for HTML. if first arg is 1, only takes 1st word.
    1466             #
    1467             sub htmlify {
    1468 0     0 0   my($compact, $heading) = @_;
    1469              
    1470 0 0         if ($compact) {
    1471 0           $heading =~ /^(\w+)/;
    1472 0           $heading = $1;
    1473             }
    1474              
    1475             # $heading = lc($heading);
    1476             # $heading =~ s/[^\w\s]/_/g;
    1477 0           $heading =~ s/(\s+)/ /g;
    1478 0           $heading =~ s/^\s*(.*?)\s*$/$1/s;
    1479 0           $heading =~ s/ /_/g;
    1480 0           $heading =~ s/\s+\Z//;
    1481 0           $heading =~ s/_{2,}/_/g;
    1482              
    1483 0           return $heading;
    1484             }
    1485              
    1486             1;