File Coverage

blib/lib/Pod/Simple.pm
Criterion Covered Total %
statement 528 633 83.4
branch 206 292 70.5
condition 168 268 62.6
subroutine 56 69 81.1
pod 30 30 100.0
total 988 1292 76.4


line stmt bran cond sub pod time code
1             package Pod::Simple;
2 70     70   860105 use strict;
  70         128  
  70         2111  
3 70     70   300 use warnings;
  70         126  
  70         2549  
4 70     70   339 use Carp ();
  70         134  
  70         3440  
5 70 50   70   1620 BEGIN { *DEBUG = sub () {0} unless defined &DEBUG }
6 70     70   29419 use integer;
  70         947  
  70         334  
7 70     70   30588 use Pod::Escapes 1.04 ();
  70         281839  
  70         3001  
8 70     70   26830 use Pod::Simple::LinkSection ();
  70         190  
  70         1538  
9 70     70   363 use Pod::Simple::BlackBox ();
  70         86  
  70         1088  
10 70     70   27244 use Pod::Simple::TiedOutFH;
  70         156  
  70         15817  
11             #use utf8;
12              
13             our @ISA = ('Pod::Simple::BlackBox');
14             our $VERSION = '3.48';
15              
16             our @Known_formatting_codes = qw(I B C L E F S U X Z);
17             our %Known_formatting_codes = map(($_=>1), @Known_formatting_codes);
18             our @Known_directives = qw(head1 head2 head3 head4 head5 head6 item over back);
19             our %Known_directives = map(($_=>'Plain'), @Known_directives);
20             our $NL = $/ unless defined $NL;
21              
22             #-----------------------------------------------------------------------------
23             # Set up some constants:
24              
25             BEGIN {
26 70 50   70   4517 if(defined &ASCII) { }
27 70         216 elsif(chr(65) eq 'A') { *ASCII = sub () {1} }
28             else { *ASCII = sub () {''} }
29              
30 70 50       267 unless(defined &MANY_LINES) { *MANY_LINES = sub () {20} }
  70         111  
31 70         103 DEBUG > 4 and print STDERR "MANY_LINES is ", MANY_LINES(), "\n";
32 70 50       247 unless(MANY_LINES() >= 1) {
33 0         0 die "MANY_LINES is too small (", MANY_LINES(), ")!\nAborting";
34             }
35 70 50       186 if(defined &UNICODE) { }
    50          
36 70     70   390 elsif( do { no integer; "$]" >= 5.008 } ) { *UNICODE = sub() {1} }
  70         93  
  70         329  
  70         500  
  70         4597  
37 0         0 else { *UNICODE = sub() {''} }
38             }
39             if(DEBUG > 2) {
40             print STDERR "# We are ", ASCII ? '' : 'not ', "in ASCII-land\n";
41             print STDERR "# We are under a Unicode-safe Perl.\n";
42             }
43              
44             # The NO BREAK SPACE and SOFT HYHPEN are used in several submodules.
45 70     70   343 if ( do { no integer; "$]" >= 5.007_003 } ) { # On sufficiently modern Perls we can handle any
  70         96  
  70         215  
46             # character set
47             $Pod::Simple::nbsp = chr utf8::unicode_to_native(0xA0);
48             $Pod::Simple::shy = chr utf8::unicode_to_native(0xAD);
49             }
50             elsif (Pod::Simple::ASCII) { # Hard code ASCII early Perl
51             $Pod::Simple::nbsp = "\xA0";
52             $Pod::Simple::shy = "\xAD";
53             }
54             else { # EBCDIC on early Perl. We know what the values are for the code
55             # pages supported then.
56             $Pod::Simple::nbsp = "\x41";
57             $Pod::Simple::shy = "\xCA";
58             }
59              
60             # Design note:
61             # This is a parser for Pod. It is not a parser for the set of Pod-like
62             # languages which happens to contain Pod -- it is just for Pod, plus possibly
63             # some extensions.
64              
65             # @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @
66             #@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @
67             #@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
68              
69             __PACKAGE__->_accessorize(
70             '_output_is_for_JustPod', # For use only by Pod::Simple::JustPod,
71             # If non-zero, don't expand Z<> E<> S<> L<>,
72             # and count how many brackets in format codes
73             'nbsp_for_S', # Whether to map S<...>'s to \xA0 characters
74             'source_filename', # Filename of the source, for use in warnings
75             'source_dead', # Whether to consider this parser's source dead
76              
77             'output_fh', # The filehandle we're writing to, if applicable.
78             # Used only in some derived classes.
79              
80             'hide_line_numbers', # For some dumping subclasses: whether to pointedly
81             # suppress the start_line attribute
82              
83             'line_count', # the current line number
84             'pod_para_count', # count of pod paragraphs seen so far
85              
86             'no_whining', # whether to suppress whining
87             'no_errata_section', # whether to suppress the errata section
88             'complain_stderr', # whether to complain to stderr
89              
90             'doc_has_started', # whether we've fired the open-Document event yet
91              
92             'bare_output', # For some subclasses: whether to prepend
93             # header-code and postpend footer-code
94              
95             'keep_encoding_directive', # whether to emit =encoding
96             'nix_X_codes', # whether to ignore X<...> codes
97             'merge_text', # whether to avoid breaking a single piece of
98             # text up into several events
99              
100             'preserve_whitespace', # whether to try to keep whitespace as-is
101             'strip_verbatim_indent', # What indent to strip from verbatim
102             'expand_verbatim_tabs', # 0: preserve tabs in verbatim blocks
103             # n: expand tabs to stops every n columns
104              
105             'parse_characters', # Whether parser should expect chars rather than octets
106              
107             'content_seen', # whether we've seen any real Pod content
108             'errors_seen', # TODO: document. whether we've seen any errors (fatal or not)
109              
110             'codes_in_verbatim', # for PseudoPod extensions
111              
112             'code_handler', # coderef to call when a code (non-pod) line is seen
113             'cut_handler', # ... when a =cut line is seen
114             'pod_handler', # ... when a =pod line is seen
115             'whiteline_handler', # ... when a line with only whitespace is seen
116             #Called like:
117             # $code_handler->($line, $self->{'line_count'}, $self) if $code_handler;
118             # $cut_handler->($line, $self->{'line_count'}, $self) if $cut_handler;
119             # $pod_handler->($line, $self->{'line_count'}, $self) if $pod_handler;
120             # $wl_handler->($line, $self->{'line_count'}, $self) if $wl_handler;
121             'parse_empty_lists', # whether to acknowledge empty =over/=back blocks
122             'raw_mode', # to report entire raw lines instead of Pod elements
123             );
124              
125             #@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
126              
127             sub any_errata_seen { # good for using as an exit() value...
128 19   100 19 1 89 return shift->{'errors_seen'} || 0;
129             }
130              
131             sub errata_seen {
132 8   50 8 1 665 return shift->{'all_errata'} || {};
133             }
134              
135             # Returns the encoding only if it was recognized as being handled and set
136             sub detected_encoding {
137 0     0 1 0 return shift->{'detected_encoding'};
138             }
139              
140             sub encoding {
141 19     19 1 66 my $this = shift;
142 19 50       55 return $this->{'encoding'} unless @_; # GET.
143              
144 0         0 $this->_handle_encoding_line("=encoding $_[0]");
145 0 0       0 if ($this->{'_processed_encoding'}) {
146 0         0 delete $this->{'_processed_encoding'};
147 0 0       0 if(! $this->{'encoding_command_statuses'} ) {
    0          
148 0         0 DEBUG > 2 and print STDERR " CRAZY ERROR: encoding wasn't really handled?!\n";
149             } elsif( $this->{'encoding_command_statuses'}[-1] ) {
150             $this->scream( "=encoding $_[0]",
151             sprintf "Couldn't do %s: %s",
152             $this->{'encoding_command_reqs' }[-1],
153 0         0 $this->{'encoding_command_statuses'}[-1],
154             );
155             } else {
156 0         0 DEBUG > 2 and print STDERR " (encoding successfully handled.)\n";
157             }
158 0         0 return $this->{'encoding'};
159             } else {
160 0         0 return undef;
161             }
162             }
163              
164             #@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
165             # Pull in some functions that, for some reason, I expect to see here too:
166             BEGIN {
167 70     70   28228 *pretty = \&Pod::Simple::BlackBox::pretty;
168 70         153 *stringify_lol = \&Pod::Simple::BlackBox::stringify_lol;
169 70         552694 *my_qr = \&Pod::Simple::BlackBox::my_qr;
170             }
171              
172             #@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
173              
174             sub version_report {
175 0   0 0 1 0 my $class = ref($_[0]) || $_[0];
176 0 0       0 if($class eq __PACKAGE__) {
177 0         0 return "$class $VERSION";
178             } else {
179 0         0 my $v = $class->VERSION;
180 0         0 return "$class $v (" . __PACKAGE__ . " $VERSION)";
181             }
182             }
183              
184             #@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
185              
186             #sub curr_open { # read-only list accessor
187             # return @{ $_[0]{'curr_open'} || return() };
188             #}
189             #sub _curr_open_listref { $_[0]{'curr_open'} ||= [] }
190              
191              
192             sub output_string {
193             # Works by faking out output_fh. Simplifies our code.
194             #
195 900     900 1 8773 my $this = shift;
196 900 100       1995 return $this->{'output_string'} unless @_; # GET.
197              
198 890 50 33     2774 my $x = (defined($_[0]) and ref($_[0])) ? $_[0] : \( $_[0] );
199 890 100       1811 $$x = '' unless defined $$x;
200 890         1039 DEBUG > 4 and print STDERR "# Output string set to $x ($$x)\n";
201 890         3466 $this->{'output_fh'} = Pod::Simple::TiedOutFH->handle_on($_[0]);
202             return
203 890         2048 $this->{'output_string'} = $_[0];
204             #${ ${ $this->{'output_fh'} } };
205             }
206              
207 10     10 1 25 sub abandon_output_string { $_[0]->abandon_output_fh; delete $_[0]{'output_string'} }
  10         17  
208 10     10 1 15 sub abandon_output_fh { $_[0]->output_fh(undef) }
209             # These don't delete the string or close the FH -- they just delete our
210             # references to it/them.
211             # TODO: document these
212              
213             #@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
214              
215             sub new {
216             # takes no parameters
217 931   33 931 1 150027 my $class = ref($_[0]) || $_[0];
218             #Carp::croak(__PACKAGE__ . " is a virtual base class -- see perldoc "
219             # . __PACKAGE__ );
220 931         15429 my $obj = bless {
221             'accept_codes' => { map( ($_=>$_), @Known_formatting_codes ) },
222             'accept_directives' => { %Known_directives },
223             'accept_targets' => {},
224             }, $class;
225              
226 931         4258 $obj->expand_verbatim_tabs(8);
227 931         1963 return $obj;
228             }
229              
230              
231              
232             # TODO: an option for whether to interpolate E<...>'s, or just resolve to codes.
233              
234             #@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
235              
236             sub _handle_element_start { # OVERRIDE IN DERIVED CLASS
237 0     0   0 my($self, $element_name, $attr_hash_r) = @_;
238 0         0 return;
239             }
240              
241             sub _handle_element_end { # OVERRIDE IN DERIVED CLASS
242 0     0   0 my($self, $element_name) = @_;
243 0         0 return;
244             }
245              
246             sub _handle_text { # OVERRIDE IN DERIVED CLASS
247 0     0   0 my($self, $text) = @_;
248 0         0 return;
249             }
250              
251             #@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
252             #
253             # And now directives (not targets)
254              
255 3     3 1 21 sub accept_directive_as_verbatim { shift->_accept_directives('Verbatim', @_) }
256 3     3 1 23 sub accept_directive_as_data { shift->_accept_directives('Data', @_) }
257 3     3 1 56 sub accept_directive_as_processed { shift->_accept_directives('Plain', @_) }
258              
259             sub _accept_directives {
260 9     9   28 my($this, $type) = splice @_,0,2;
261 9         19 foreach my $d (@_) {
262 9 50 33     40 next unless defined $d and length $d;
263 9 50       63 Carp::croak "\"$d\" isn't a valid directive name"
264             unless $d =~ m/^[a-zA-Z][a-zA-Z0-9]*$/s;
265             Carp::croak "\"$d\" is already a reserved Pod directive name"
266 9 50       22 if exists $Known_directives{$d};
267 9         23 $this->{'accept_directives'}{$d} = $type;
268 9         15 DEBUG > 2 and print STDERR "Learning to accept \"=$d\" as directive of type $type\n";
269             }
270             DEBUG > 6 and print STDERR "$this\'s accept_directives : ",
271 9         11 pretty($this->{'accept_directives'}), "\n";
272              
273 9 50       18 return sort keys %{ $this->{'accept_directives'} } if wantarray;
  0         0  
274 9         18 return;
275             }
276              
277             #--------------------------------------------------------------------------
278             # TODO: document these:
279              
280 0     0 1 0 sub unaccept_directive { shift->unaccept_directives(@_) };
281              
282             sub unaccept_directives {
283 0     0 1 0 my $this = shift;
284 0         0 foreach my $d (@_) {
285 0 0 0     0 next unless defined $d and length $d;
286 0 0       0 Carp::croak "\"$d\" isn't a valid directive name"
287             unless $d =~ m/^[a-zA-Z][a-zA-Z0-9]*$/s;
288             Carp::croak "But you must accept \"$d\" directives -- it's a builtin!"
289 0 0       0 if exists $Known_directives{$d};
290 0         0 delete $this->{'accept_directives'}{$d};
291 0         0 DEBUG > 2 and print STDERR "OK, won't accept \"=$d\" as directive.\n";
292             }
293 0 0       0 return sort keys %{ $this->{'accept_directives'} } if wantarray;
  0         0  
294             return
295 0         0 }
296              
297             #@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
298             #
299             # And now targets (not directives)
300              
301 35     35 1 183 sub accept_target { shift->accept_targets(@_) } # alias
302 49     49 1 166 sub accept_target_as_text { shift->accept_targets_as_text(@_) } # alias
303              
304              
305 281     281 1 777 sub accept_targets { shift->_accept_targets('1', @_) }
306              
307 53     53 1 175 sub accept_targets_as_text { shift->_accept_targets('force_resolve', @_) }
308             # forces them to be processed, even when there's no ":".
309              
310             sub _accept_targets {
311 334     334   913 my($this, $type) = splice @_,0,2;
312 334         581 foreach my $t (@_) {
313 615 50 33     1581 next unless defined $t and length $t;
314             # TODO: enforce some limitations on what a target name can be?
315 615         1048 $this->{'accept_targets'}{$t} = $type;
316 615         732 DEBUG > 2 and print STDERR "Learning to accept \"$t\" as target of type $type\n";
317             }
318 334 50       584 return sort keys %{ $this->{'accept_targets'} } if wantarray;
  0         0  
319 334         533 return;
320             }
321              
322             #--------------------------------------------------------------------------
323 0     0 1 0 sub unaccept_target { shift->unaccept_targets(@_) }
324              
325             sub unaccept_targets {
326 0     0 1 0 my $this = shift;
327 0         0 foreach my $t (@_) {
328 0 0 0     0 next unless defined $t and length $t;
329             # TODO: enforce some limitations on what a target name can be?
330 0         0 delete $this->{'accept_targets'}{$t};
331 0         0 DEBUG > 2 and print STDERR "OK, won't accept \"$t\" as target.\n";
332             }
333 0 0       0 return sort keys %{ $this->{'accept_targets'} } if wantarray;
  0         0  
334 0         0 return;
335             }
336              
337             #@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
338             #
339             # And now codes (not targets or directives)
340              
341             # XXX Probably it is an error that the digit '9' is excluded from these re's.
342             # Broken for early Perls on EBCDIC
343             my $xml_name_re = my_qr('[^-.0-8:A-Z_a-z[:^ascii:]]', '9');
344             $xml_name_re = qr/[\x00-\x2C\x2F\x39\x3B-\x40\x5B-\x5E\x60\x7B-\x7F]/
345             unless $xml_name_re;
346              
347 0     0 1 0 sub accept_code { shift->accept_codes(@_) } # alias
348              
349             sub accept_codes { # Add some codes
350 340     340 1 717 my $this = shift;
351              
352 340         574 foreach my $new_code (@_) {
353 1228 50 33     2750 next unless defined $new_code and length $new_code;
354             # A good-enough check that it's good as an XML Name symbol:
355 1228 50 33     5931 Carp::croak "\"$new_code\" isn't a valid element name"
      33        
356             if $new_code =~ $xml_name_re
357             # Characters under 0x80 that aren't legal in an XML Name.
358             or $new_code =~ m/^[-\.0-9]/s
359             or $new_code =~ m/:[-\.0-9]/s;
360             # The legal under-0x80 Name characters that
361             # an XML Name still can't start with.
362              
363 1228         2400 $this->{'accept_codes'}{$new_code} = $new_code;
364              
365             # Yes, map to itself -- just so that when we
366             # see "=extend W [whatever] thatelementname", we say that W maps
367             # to whatever $this->{accept_codes}{thatelementname} is,
368             # i.e., "thatelementname". Then when we go re-mapping,
369             # a "W" in the treelet turns into "thatelementname". We only
370             # remap once.
371             # If we say we accept "W", then a "W" in the treelet simply turns
372             # into "W".
373             }
374              
375 340         584 return;
376             }
377              
378             #--------------------------------------------------------------------------
379 0     0 1 0 sub unaccept_code { shift->unaccept_codes(@_) }
380              
381             sub unaccept_codes { # remove some codes
382 29     29 1 128 my $this = shift;
383              
384 29         65 foreach my $new_code (@_) {
385 29 50 33     101 next unless defined $new_code and length $new_code;
386             # A good-enough check that it's good as an XML Name symbol:
387 29 50 33     328 Carp::croak "\"$new_code\" isn't a valid element name"
      33        
388             if $new_code =~ $xml_name_re
389             # Characters under 0x80 that aren't legal in an XML Name.
390             or $new_code =~ m/^[-\.0-9]/s
391             or $new_code =~ m/:[-\.0-9]/s;
392             # The legal under-0x80 Name characters that
393             # an XML Name still can't start with.
394              
395 29 50       151 Carp::croak "But you must accept \"$new_code\" codes -- it's a builtin!"
396             if grep $new_code eq $_, @Known_formatting_codes;
397              
398 29         86 delete $this->{'accept_codes'}{$new_code};
399              
400 29         52 DEBUG > 2 and print STDERR "OK, won't accept the code $new_code<...>.\n";
401             }
402              
403 29         52 return;
404             }
405              
406              
407             #@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
408             #@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
409              
410             sub parse_string_document {
411 782     782 1 15198 my $self = shift;
412 782         1016 my @lines;
413 782         1299 foreach my $line_group (@_) {
414 782 100 66     2231 next unless defined $line_group and length $line_group;
415 764         2157 pos($line_group) = 0;
416 764         4680 while($line_group =~
417             m/([^\n\r]*)(\r?\n?)/g # supports \r, \n ,\r\n
418             #m/([^\n\r]*)((?:\r?\n)?)/g
419             ) {
420             #print(">> $1\n"),
421 8682 100 100     30252 $self->parse_lines($1)
      66        
422             if length($1) or length($2)
423             or pos($line_group) != length($line_group);
424             # I.e., unless it's a zero-length "empty line" at the very
425             # end of "foo\nbar\n" (i.e., between the \n and the EOS).
426             }
427             }
428 782         1704 $self->parse_lines(undef); # to signal EOF
429 782         2218 return $self;
430             }
431              
432             sub _init_fh_source {
433 51     51   96 my($self, $source) = @_;
434              
435             #DEBUG > 1 and print STDERR "Declaring $source as :raw for starters\n";
436             #$self->_apply_binmode($source, ':raw');
437             #binmode($source, ":raw");
438              
439 51         108 return;
440             }
441              
442             #:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.
443             #
444              
445             sub parse_file {
446 51     51 1 299 my($self, $source) = (@_);
447              
448 51 50       301 if(!defined $source) {
    50          
    50          
    50          
449 0         0 Carp::croak("Can't use empty-string as a source for parse_file");
450             } elsif(ref(\$source) eq 'GLOB') {
451 0         0 $self->{'source_filename'} = '' . ($source);
452             } elsif(ref $source) {
453 0         0 $self->{'source_filename'} = '' . ($source);
454             } elsif(!length $source) {
455 0         0 Carp::croak("Can't use empty-string as a source for parse_file");
456             } else {
457             {
458 51         83 local *PODSOURCE;
  51         116  
459 51 50       2574 open(PODSOURCE, "<$source") || Carp::croak("Can't open $source: $!");
460 51         197 $self->{'source_filename'} = $source;
461 51         148 $source = *PODSOURCE{IO};
462             }
463 51         178 $self->_init_fh_source($source);
464             }
465             # By here, $source is a FH.
466              
467 51         97 $self->{'source_fh'} = $source;
468              
469 51         91 my($i, @lines);
470 51         95 until( $self->{'source_dead'} ) {
471 490         1520 splice @lines;
472              
473 490         989 for($i = MANY_LINES; $i--;) { # read those many lines at a time
474 9326         14511 local $/ = $NL;
475 9326         17116 push @lines, scalar(<$source>); # readline
476 9326 100       19115 last unless defined $lines[-1];
477             # but pass thru the undef, which will set source_dead to true
478             }
479              
480 490         676 my $at_eof = ! $lines[-1]; # keep track of the undef
481 490 100       714 pop @lines if $at_eof; # silence warnings
482              
483             # be eol agnostic
484 490         2579 s/\r\n?/\n/g for @lines;
485              
486             # make sure there are only one line elements for parse_lines
487 490         26192 @lines = split(/(?<=\n)/, join('', @lines));
488              
489             # push the undef back after popping it to set source_dead to true
490 490 100       873 push @lines, undef if $at_eof;
491              
492 490         1330 $self->parse_lines(@lines);
493             }
494 51         104 delete($self->{'source_fh'}); # so it can be GC'd
495 51         1081 return $self;
496             }
497              
498             #:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.
499              
500             sub parse_from_file {
501             # An emulation of Pod::Parser's interface, for the sake of Perldoc.
502             # Basically just a wrapper around parse_file.
503              
504 10     10 1 18 my($self, $source, $to) = @_;
505 10 50       17 $self = $self->new unless ref($self); # so we tolerate being a class method
506              
507 10 50 33     66 if(!defined $source) { $source = *STDIN{IO}
    50 33        
    50          
    50          
508 0         0 } elsif(ref(\$source) eq 'GLOB') { # stet
509             } elsif(ref($source) ) { # stet
510             } elsif(!length $source
511             or $source eq '-' or $source =~ m/^<&(?:STDIN|0)$/i
512             ) {
513 0         0 $source = *STDIN{IO};
514             }
515              
516 10 50 33     60 if(!defined $to) { $self->output_fh( *STDOUT{IO} );
  0 50 33     0  
    50          
    50          
    50          
517 0         0 } elsif(ref(\$to) eq 'GLOB') { $self->output_fh( $to );
518 0         0 } elsif(ref($to)) { $self->output_fh( $to );
519             } elsif(!length $to
520             or $to eq '-' or $to =~ m/^>&?(?:STDOUT|1)$/i
521             ) {
522 0         0 $self->output_fh( *STDOUT{IO} );
523             } elsif($to =~ m/^>&(?:STDERR|2)$/i) {
524 0         0 $self->output_fh( *STDERR{IO} );
525             } else {
526 10         55 require Symbol;
527 10         23 my $out_fh = Symbol::gensym();
528 10         103 DEBUG and print STDERR "Write-opening to $to\n";
529 10 50       2368 open($out_fh, ">$to") or Carp::croak "Can't write-open $to: $!";
530 10 50 33     76 binmode($out_fh)
531             if $self->can('write_with_binmode') and $self->write_with_binmode;
532 10         27 $self->output_fh($out_fh);
533             }
534              
535 10         41 return $self->parse_file($source);
536             }
537              
538             #-----------------------------------------------------------------------------
539              
540             sub whine {
541             #my($self,$line,$complaint) = @_;
542 79     79 1 235 my $self = shift(@_);
543 79         134 ++$self->{'errors_seen'};
544 79 100       184 if($self->{'no_whining'}) {
545 9         8 DEBUG > 9 and print STDERR "Discarding complaint (at line $_[0]) $_[1]\n because no_whining is on.\n";
546 9         12 return;
547             }
548 70         86 push @{$self->{'all_errata'}{$_[0]}}, $_[1];
  70         291  
549 70 50       158 return $self->_complain_warn(@_) if $self->{'complain_stderr'};
550 70         239 return $self->_complain_errata(@_);
551             }
552              
553             sub scream { # like whine, but not suppressible
554             #my($self,$line,$complaint) = @_;
555 8     8 1 18 my $self = shift(@_);
556 8         31 ++$self->{'errors_seen'};
557 8         14 push @{$self->{'all_errata'}{$_[0]}}, $_[1];
  8         42  
558 8 50       31 return $self->_complain_warn(@_) if $self->{'complain_stderr'};
559 8         42 return $self->_complain_errata(@_);
560             }
561              
562             sub _complain_warn {
563 0     0   0 my($self,$line,$complaint) = @_;
564             return printf STDERR "%s around line %s: %s\n",
565 0   0     0 $self->{'source_filename'} || 'Pod input', $line, $complaint;
566             }
567              
568             sub _complain_errata {
569 78     78   165 my($self,$line,$complaint) = @_;
570 78 100       159 if( $self->{'no_errata_section'} ) {
571 10         10 DEBUG > 9 and print STDERR "Discarding erratum (at line $line) $complaint\n because no_errata_section is on.\n";
572             } else {
573 68         69 DEBUG > 9 and print STDERR "Queuing erratum (at line $line) $complaint\n";
574 68         81 push @{$self->{'errata'}{$line}}, $complaint
  68         173  
575             # for a report to be generated later!
576             }
577 78         171 return 1;
578             }
579              
580             #@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
581              
582             sub _get_initial_item_type {
583             # A hack-wrapper here for when you have like "=over\n\n=item 456\n\n"
584 192     192   363 my($self, $para) = @_;
585 192 50       415 return $para->[1]{'~type'} if $para->[1]{'~type'};
586              
587             return $para->[1]{'~type'} = 'text'
588 192 100 100     400 if join("\n", @{$para}[2 .. $#$para]) =~ m/^\s*(\d+)\.?\s*$/s and $1 ne '1';
  192         981  
589             # Else fall thru to the general case:
590 190         504 return $self->_get_item_type($para);
591             }
592              
593              
594              
595             sub _get_item_type { # mutates the item!!
596 1219     1219   1942 my($self, $para) = @_;
597 1219 100       2206 return $para->[1]{'~type'} if $para->[1]{'~type'};
598              
599              
600             # Otherwise we haven't yet been to this node. Maybe alter it...
601              
602 1027         1604 my $content = join "\n", @{$para}[2 .. $#$para];
  1027         1901  
603              
604 1027 100 100     5545 if($content =~ m/^\s*\*\s*$/s or $content =~ m/^\s*$/s) {
    100          
    100          
605             # Like: "=item *", "=item * ", "=item"
606 59         110 splice @$para, 2; # so it ends up just being ['=item', { attrhash } ]
607 59         113 $para->[1]{'~orig_content'} = $content;
608 59         175 return $para->[1]{'~type'} = 'bullet';
609              
610             } elsif($content =~ m/^\s*\*\s+(.+)/s) { # tolerance
611              
612             # Like: "=item * Foo bar baz";
613 101         173 $para->[1]{'~orig_content'} = $content;
614 101         189 $para->[1]{'~_freaky_para_hack'} = $1;
615 101         96 DEBUG > 2 and print STDERR " Tolerating $$para[2] as =item *\\n\\n$1\n";
616 101         144 splice @$para, 2; # so it ends up just being ['=item', { attrhash } ]
617 101         328 return $para->[1]{'~type'} = 'bullet';
618              
619             } elsif($content =~ m/^\s*(\d+)\.?\s*$/s) {
620             # Like: "=item 1.", "=item 123412"
621              
622 31         109 $para->[1]{'~orig_content'} = $content;
623 31         63 $para->[1]{'number'} = $1; # Yes, stores the number there!
624              
625 31         49 splice @$para, 2; # so it ends up just being ['=item', { attrhash } ]
626 31         100 return $para->[1]{'~type'} = 'number';
627              
628             } else {
629             # It's anything else.
630 836         2445 return $para->[1]{'~type'} = 'text';
631              
632             }
633             }
634              
635             #-----------------------------------------------------------------------------
636              
637             sub _make_treelet {
638 4490     4490   5054 my $self = shift; # and ($para, $start_line)
639 4490         4539 my $treelet;
640 4490 50       7094 if(!@_) {
641 0         0 return [''];
642 4490 50 33     8568 } if(ref $_[0] and ref $_[0][0] and $_[0][0][0] eq '~Top') {
      33        
643             # Hack so we can pass in fake-o pre-cooked paragraphs:
644             # just have the first line be a reference to a ['~Top', {}, ...]
645             # We use this feechure in gen_errata and stuff.
646              
647 0         0 DEBUG and print STDERR "Applying precooked treelet hack to $_[0][0]\n";
648 0         0 $treelet = $_[0][0];
649 0         0 splice @$treelet, 0, 2; # lop the top off
650 0         0 return $treelet;
651             } else {
652 4490         9023 $treelet = $self->_treelet_from_formatting_codes(@_);
653             }
654              
655 4490 100 100     11634 if( ! $self->{'_output_is_for_JustPod'} # Retain these as-is for pod output
656             && $self->_remap_sequences($treelet) )
657             {
658 1093         2499 $self->_treat_Zs($treelet); # Might as well nix these first
659 1093         2244 $self->_treat_Ls($treelet); # L has to precede E and S
660 1093         2301 $self->_treat_Es($treelet);
661 1093         2165 $self->_treat_Ss($treelet); # S has to come after E
662 1093         1868 $self->_wrap_up($treelet); # Nix X's and merge texties
663              
664             } else {
665 3397         3171 DEBUG and print STDERR "Formatless treelet gets fast-tracked.\n";
666             # Very common case!
667             }
668              
669 4490         7148 splice @$treelet, 0, 2; # lop the top off
670              
671 4490         13913 return $treelet;
672             }
673              
674             #:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.
675              
676             sub _wrap_up {
677 1093     1093   1380 my($self, @stack) = @_;
678 1093         1426 my $nixx = $self->{'nix_X_codes'};
679 1093         1255 my $merge = $self->{'merge_text' };
680 1093 100 100     2150 return unless $nixx or $merge;
681              
682 751         672 DEBUG > 2 and print STDERR "\nStarting _wrap_up traversal.\n",
683             $merge ? (" Merge mode on\n") : (),
684             $nixx ? (" Nix-X mode on\n") : (),
685             ;
686              
687              
688 751         767 my($i, $treelet);
689 751         1035 while($treelet = shift @stack) {
690 2748         2640 DEBUG > 3 and print STDERR " Considering children of this $treelet->[0] node...\n";
691 2748         3243 for($i = 2; $i < @$treelet; ++$i) { # iterate over children
692 6251         5021 DEBUG > 3 and print STDERR " Considering child at $i ", pretty($treelet->[$i]), "\n";
693 6251 100 100     20865 if($nixx and ref $treelet->[$i] and $treelet->[$i][0] eq 'X') {
    100 100        
    100 100        
      100        
      100        
694 6         6 DEBUG > 3 and print STDERR " Nixing X node at $i\n";
695 6         10 splice(@$treelet, $i, 1); # just nix this node (and its descendants)
696             # no need to back-update the counter just yet
697 6         9 redo;
698              
699             } elsif($merge and $i != 2 and # non-initial
700             !ref $treelet->[$i] and !ref $treelet->[$i - 1]
701             ) {
702 25         21 DEBUG > 3 and print STDERR " Merging ", $i-1,
703             ":[$treelet->[$i-1]] and $i\:[$treelet->[$i]]\n";
704 25         32 $treelet->[$i-1] .= ( splice(@$treelet, $i, 1) )[0];
705 25         22 DEBUG > 4 and print STDERR " Now: ", $i-1, ":[$treelet->[$i-1]]\n";
706 25         22 --$i;
707 25         33 next;
708             # since we just pulled the possibly last node out from under
709             # ourselves, we can't just redo()
710              
711             } elsif( ref $treelet->[$i] ) {
712 1754         1526 DEBUG > 4 and print STDERR " Enqueuing ", pretty($treelet->[$i]), " for traversal.\n";
713 1754         1748 push @stack, $treelet->[$i];
714              
715 1754 100       2864 if($treelet->[$i][0] eq 'L') {
716 213         193 my $thing;
717 213         248 foreach my $attrname ('section', 'to') {
718 426 100 66     922 if(defined($thing = $treelet->[$i][1]{$attrname}) and ref $thing) {
719 243         275 unshift @stack, $thing;
720             DEBUG > 4 and print STDERR " +Enqueuing ",
721 243         396 pretty( $treelet->[$i][1]{$attrname} ),
722             " as an attribute value to tweak.\n";
723             }
724             }
725             }
726             }
727             }
728             }
729 751         663 DEBUG > 2 and print STDERR "End of _wrap_up traversal.\n\n";
730              
731 751         1057 return;
732             }
733              
734             #:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.
735              
736             sub _remap_sequences {
737 3618     3618   5367 my($self,@stack) = @_;
738              
739 3618 100 66     6158 if(@stack == 1 and @{ $stack[0] } == 3 and !ref $stack[0][2]) {
  3618   100     10713  
740             # VERY common case: abort it.
741 2525         2448 DEBUG and print STDERR "Skipping _remap_sequences: formatless treelet.\n";
742 2525         6361 return 0;
743             }
744              
745 1093   50     2195 my $map = ($self->{'accept_codes'} || die "NO accept_codes in $self?!?");
746              
747 1093         1551 my $start_line = $stack[0][1]{'start_line'};
748 1093         1021 DEBUG > 2 and printf
749             "\nAbout to start _remap_sequences on treelet from line %s.\n",
750             $start_line || '[?]'
751             ;
752             DEBUG > 3 and print STDERR " Map: ",
753             join('; ', map "$_=" . (
754 1093         1056 ref($map->{$_}) ? join(",", @{$map->{$_}}) : $map->{$_}
755             ),
756             sort keys %$map ),
757             ("B~C~E~F~I~L~S~U~X~Z" eq join '~', sort keys %$map)
758             ? " (all normal)\n" : "\n"
759             ;
760              
761             # A recursive algorithm implemented iteratively! Whee!
762              
763 1093         1406 my($is, $was, $i, $treelet); # scratch
764 1093         1870 while($treelet = shift @stack) {
765 3503         3119 DEBUG > 3 and print STDERR " Considering children of this $treelet->[0] node...\n";
766 3503         4712 for($i = 2; $i < @$treelet; ++$i) { # iterate over children
767 7587 100       13184 next unless ref $treelet->[$i]; # text nodes are uninteresting
768              
769 2416         2037 DEBUG > 4 and print STDERR " Noting child $i : $treelet->[$i][0]<...>\n";
770              
771 2416         4152 $is = $treelet->[$i][0] = $map->{ $was = $treelet->[$i][0] };
772 2416         2154 if( DEBUG > 3 ) {
773             if(!defined $is) {
774             print STDERR " Code $was<> is UNKNOWN!\n";
775             } elsif($is eq $was) {
776             DEBUG > 4 and print STDERR " Code $was<> stays the same.\n";
777             } else {
778             print STDERR " Code $was<> maps to ",
779             ref($is)
780             ? ( "tags ", map("$_<", @$is), '...', map('>', @$is), "\n" )
781             : "tag $is<...>.\n";
782             }
783             }
784              
785 2416 100       2912 if(!defined $is) {
786 4         79 $self->whine($start_line, "Deleting unknown formatting code $was<>");
787 4         25 $is = $treelet->[$i][0] = '1'; # But saving the children!
788             # I could also insert a leading "$was<" and tailing ">" as
789             # children of this node, but something about that seems icky.
790             }
791 2416 100       3912 if(ref $is) {
    50          
    100          
792 2         4 my @dynasty = @$is;
793 2         2 DEBUG > 4 and print STDERR " Renaming $was node to $dynasty[-1]\n";
794 2         4 $treelet->[$i][0] = pop @dynasty;
795 2         2 my $nugget;
796 2         4 while(@dynasty) {
797 3         2 DEBUG > 4 and printf
798             " Grafting a new %s node between %s and %s\n",
799             $dynasty[-1], $treelet->[0], $treelet->[$i][0],
800             ;
801              
802             #$nugget = ;
803 3         11 splice @$treelet, $i, 1, [pop(@dynasty), {}, $treelet->[$i]];
804             # relace node with a new parent
805             }
806             } elsif($is eq '0') {
807 0         0 splice(@$treelet, $i, 1); # just nix this node (and its descendants)
808 0         0 --$i; # back-update the counter
809             } elsif($is eq '1') {
810             splice(@$treelet, $i, 1 # replace this node with its children!
811 4         5 => splice @{ $treelet->[$i] },2
  4         11  
812             # (not catching its first two (non-child) items)
813             );
814 4         11 --$i; # back up for new stuff
815             } else {
816             # otherwise it's unremarkable
817 2410         4043 unshift @stack, $treelet->[$i]; # just recurse
818             }
819             }
820             }
821              
822 1093         1100 DEBUG > 2 and print STDERR "End of _remap_sequences traversal.\n\n";
823              
824 1093 50 66     1820 if(@_ == 2 and @{ $_[1] } == 3 and !ref $_[1][2]) {
  1093   66     2598  
825 0         0 DEBUG and print STDERR "Noting that the treelet is now formatless.\n";
826 0         0 return 0;
827             }
828 1093         2597 return 1;
829             }
830              
831             # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
832              
833             sub _ponder_extend {
834              
835             # "Go to an extreme, move back to a more comfortable place"
836             # -- /Oblique Strategies/, Brian Eno and Peter Schmidt
837              
838 21     21   33 my($self, $para) = @_;
839 21         57 my $content = join ' ', splice @$para, 2;
840 21         41 $content =~ s/^\s+//s;
841 21         53 $content =~ s/\s+$//s;
842              
843 21         23 DEBUG > 2 and print STDERR "Ogling extensor: =extend $content\n";
844              
845 21 50       69 if($content =~
846             m/^
847             (\S+) # 1 : new item
848             \s+
849             (\S+) # 2 : fallback(s)
850             (?:\s+(\S+))? # 3 : element name(s)
851             \s*
852             $
853             /xs
854             ) {
855 21         33 my $new_letter = $1;
856 21         23 my $fallbacks_one = $2;
857 21         18 my $elements_one;
858 21 50       36 $elements_one = defined($3) ? $3 : $1;
859              
860 21         19 DEBUG > 2 and print STDERR "Extensor has good syntax.\n";
861              
862 21 50 33     45 unless($new_letter =~ m/^[A-Z]$/s or $new_letter) {
863 0         0 DEBUG > 2 and print STDERR " $new_letter isn't a valid thing to entend.\n";
864             $self->whine(
865 0         0 $para->[1]{'start_line'},
866             "You can extend only formatting codes A-Z, not like \"$new_letter\""
867             );
868 0         0 return;
869             }
870              
871 21 50       68 if(grep $new_letter eq $_, @Known_formatting_codes) {
872 0         0 DEBUG > 2 and print STDERR " $new_letter isn't a good thing to extend, because known.\n";
873             $self->whine(
874 0         0 $para->[1]{'start_line'},
875             "You can't extend an established code like \"$new_letter\""
876             );
877              
878             #TODO: or allow if last bit is same?
879              
880 0         0 return;
881             }
882              
883 21 0 33     80 unless($fallbacks_one =~ m/^[A-Z](,[A-Z])*$/s # like "B", "M,I", etc.
      33        
884             or $fallbacks_one eq '0' or $fallbacks_one eq '1'
885             ) {
886             $self->whine(
887 0         0 $para->[1]{'start_line'},
888             "Format for second =extend parameter must be like"
889             . " M or 1 or 0 or M,N or M,N,O but you have it like "
890             . $fallbacks_one
891             );
892 0         0 return;
893             }
894              
895 21 50       64 unless($elements_one =~ m/^[^ ,]+(,[^ ,]+)*$/s) { # like "B", "M,I", etc.
896             $self->whine(
897 0         0 $para->[1]{'start_line'},
898             "Format for third =extend parameter: like foo or bar,Baz,qu:ux but not like "
899             . $elements_one
900             );
901 0         0 return;
902             }
903              
904 21         50 my @fallbacks = split ',', $fallbacks_one, -1;
905 21         41 my @elements = split ',', $elements_one, -1;
906              
907 21         25 foreach my $f (@fallbacks) {
908 42 0 33     73 next if exists $Known_formatting_codes{$f} or $f eq '0' or $f eq '1';
      33        
909 0         0 DEBUG > 2 and print STDERR " Can't fall back on unknown code $f\n";
910             $self->whine(
911 0         0 $para->[1]{'start_line'},
912             "Can't use unknown formatting code '$f' as a fallback for '$new_letter'"
913             );
914 0         0 return;
915             }
916              
917 21         47 DEBUG > 3 and printf STDERR "Extensor: Fallbacks <%s> Elements <%s>.\n",
918             @fallbacks, @elements;
919              
920 21         23 my $canonical_form;
921 21         22 foreach my $e (@elements) {
922 42 100       54 if(exists $self->{'accept_codes'}{$e}) {
923 15         14 DEBUG > 1 and print STDERR " Mapping '$new_letter' to known extension '$e'\n";
924 15         15 $canonical_form = $e;
925 15         19 last; # first acceptable elementname wins!
926             } else {
927 27         42 DEBUG > 1 and print STDERR " Can't map '$new_letter' to unknown extension '$e'\n";
928             }
929             }
930              
931              
932 21 100       27 if( defined $canonical_form ) {
933             # We found a good N => elementname mapping
934 15         22 $self->{'accept_codes'}{$new_letter} = $canonical_form;
935 15         52 DEBUG > 2 and print
936             "Extensor maps $new_letter => known element $canonical_form.\n";
937             } else {
938             # We have to use the fallback(s), which might be '0', or '1'.
939 6 100       14 $self->{'accept_codes'}{$new_letter}
940             = (@fallbacks == 1) ? $fallbacks[0] : \@fallbacks;
941 6         13 DEBUG > 2 and print
942             "Extensor maps $new_letter => fallbacks @fallbacks.\n";
943             }
944              
945             } else {
946 0         0 DEBUG > 2 and print STDERR "Extensor has bad syntax.\n";
947             $self->whine(
948 0         0 $para->[1]{'start_line'},
949             "Unknown =extend syntax: $content"
950             )
951             }
952 21         31 return;
953             }
954              
955              
956             #:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.
957              
958             sub _treat_Zs { # Nix Z<...>'s
959 1093     1093   1472 my($self,@stack) = @_;
960              
961 1093         1208 my($i, $treelet);
962 1093         1389 my $start_line = $stack[0][1]{'start_line'};
963              
964             # A recursive algorithm implemented iteratively! Whee!
965              
966 1093         1564 while($treelet = shift @stack) {
967 3471         4527 for($i = 2; $i < @$treelet; ++$i) { # iterate over children
968 7551 100       11857 next unless ref $treelet->[$i]; # text nodes are uninteresting
969 2415 100       3332 unless($treelet->[$i][0] eq 'Z') {
970 2378         2505 unshift @stack, $treelet->[$i]; # recurse
971 2378         3148 next;
972             }
973              
974 37         33 DEBUG > 1 and print STDERR "Nixing Z node @{$treelet->[$i]}\n";
975              
976             # bitch UNLESS it's empty
977 37 50 33     48 unless( @{$treelet->[$i]} == 2
  37   33     90  
978 37         97 or (@{$treelet->[$i]} == 3 and $treelet->[$i][2] eq '')
979             ) {
980 0         0 $self->whine( $start_line, "A non-empty Z<>" );
981             } # but kill it anyway
982              
983 37         49 splice(@$treelet, $i, 1); # thereby just nix this node.
984 37         92 --$i;
985              
986             }
987             }
988              
989 1093         1553 return;
990             }
991              
992             # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
993              
994             # Quoting perlpodspec:
995              
996             # In parsing an L<...> code, Pod parsers must distinguish at least four
997             # attributes:
998              
999             ############# Not used. Expressed via the element children plus
1000             ############# the value of the "content-implicit" flag.
1001             # First:
1002             # The link-text. If there is none, this must be undef. (E.g., in "L
1003             # Functions|perlfunc>", the link-text is "Perl Functions". In
1004             # "L" and even "L<|Time::HiRes>", there is no link text. Note
1005             # that link text may contain formatting.)
1006             #
1007              
1008             ############# The element children
1009             # Second:
1010             # The possibly inferred link-text -- i.e., if there was no real link text,
1011             # then this is the text that we'll infer in its place. (E.g., for
1012             # "L", the inferred link text is "Getopt::Std".)
1013             #
1014              
1015             ############# The "to" attribute (which might be text, or a treelet)
1016             # Third:
1017             # The name or URL, or undef if none. (E.g., in "L
1018             # Functions|perlfunc>", the name -- also sometimes called the page -- is
1019             # "perlfunc". In "L", the name is undef.)
1020             #
1021              
1022             ############# The "section" attribute (which might be next, or a treelet)
1023             # Fourth:
1024             # The section (AKA "item" in older perlpods), or undef if none. E.g., in
1025             # Getopt::Std/DESCRIPTION, "DESCRIPTION" is the section. (Note that this
1026             # is not the same as a manpage section like the "5" in "man 5 crontab".
1027             # "Section Foo" in the Pod sense means the part of the text that's
1028             # introduced by the heading or item whose text is "Foo".)
1029             #
1030             # Pod parsers may also note additional attributes including:
1031             #
1032              
1033             ############# The "type" attribute.
1034             # Fifth:
1035             # A flag for whether item 3 (if present) is a URL (like
1036             # "http://lists.perl.org" is), in which case there should be no section
1037             # attribute; a Pod name (like "perldoc" and "Getopt::Std" are); or
1038             # possibly a man page name (like "crontab(5)" is).
1039             #
1040              
1041             ############# The "raw" attribute that is already there.
1042             # Sixth:
1043             # The raw original L<...> content, before text is split on "|", "/", etc,
1044             # and before E<...> codes are expanded.
1045              
1046              
1047             # For L<...> codes without a "name|" part, only E<...> and Z<> codes may
1048             # occur -- no other formatting codes. That is, authors should not use
1049             # "L>".
1050             #
1051             # Note, however, that formatting codes and Z<>'s can occur in any and all
1052             # parts of an L<...> (i.e., in name, section, text, and url).
1053              
1054             sub _treat_Ls { # Process our dear dear friends, the L<...> sequences
1055              
1056             # L
1057             # L or L
1058             # L or L or L<"sec">
1059             # L
1060             # L or L
1061             # L or L or L
1062             # L
1063             # L
1064              
1065 1093     1093   1444 my($self,@stack) = @_;
1066              
1067 1093         1200 my($i, $treelet);
1068 1093         1373 my $start_line = $stack[0][1]{'start_line'};
1069              
1070             # A recursive algorithm implemented iteratively! Whee!
1071              
1072 1093         1623 while($treelet = shift @stack) {
1073 3261         4402 for(my $i = 2; $i < @$treelet; ++$i) {
1074             # iterate over children of current tree node
1075 7484 100       11549 next unless ref $treelet->[$i]; # text nodes are uninteresting
1076 2346 100       3027 unless($treelet->[$i][0] eq 'L') {
1077 1996         2156 unshift @stack, $treelet->[$i]; # recurse
1078 1996         2539 next;
1079             }
1080              
1081              
1082             # By here, $treelet->[$i] is definitely an L node
1083 350         439 my $ell = $treelet->[$i];
1084 350         305 DEBUG > 1 and print STDERR "Ogling L node " . pretty($ell) . "\n";
1085              
1086             # bitch if it's empty or is just '/'
1087 350 100 100     332 if (@{$ell} == 3 and $ell->[2] =~ m!\A\s*/\s*\z!) {
  350         1133  
1088 1         6 $self->whine( $start_line, "L<> contains only '/'" );
1089 1         3 $treelet->[$i] = 'L'; # just make it a text node
1090 1         6 next; # and move on
1091             }
1092 349 50 66     372 if( @{$ell} == 2
  349   33     621  
1093 349         943 or (@{$ell} == 3 and $ell->[2] eq '')
1094             ) {
1095 0         0 $self->whine( $start_line, "An empty L<>" );
1096 0         0 $treelet->[$i] = 'L<>'; # just make it a text node
1097 0         0 next; # and move on
1098             }
1099              
1100 349 100 100     1942 if( (! ref $ell->[2] && $ell->[2] =~ /\A\s/)
      66        
      66        
1101             ||(! ref $ell->[-1] && $ell->[-1] =~ /\s\z/)
1102             ) {
1103 2         3 $self->whine( $start_line, "L<> starts or ends with whitespace" );
1104             }
1105              
1106             # Catch URLs:
1107              
1108             # there are a number of possible cases:
1109             # 1) text node containing url: http://foo.com
1110             # -> [ 'http://foo.com' ]
1111             # 2) text node containing url and text: foo|http://foo.com
1112             # -> [ 'foo|http://foo.com' ]
1113             # 3) text node containing url start: mailto:xEfoo.com
1114             # -> [ 'mailto:x', [ E ... ], 'foo.com' ]
1115             # 4) text node containing url start and text: foo|mailto:xEfoo.com
1116             # -> [ 'foo|mailto:x', [ E ... ], 'foo.com' ]
1117             # 5) other nodes containing text and url start: OE<39>Malley|http://foo.com
1118             # -> [ 'O', [ E ... ], 'Malley', '|http://foo.com' ]
1119             # ... etc.
1120              
1121             # anything before the url is part of the text.
1122             # anything after it is part of the url.
1123             # the url text node itself may contain parts of both.
1124              
1125 349 100       1709 if (my ($url_index, $text_part, $url_part) =
1126             # grep is no good here; we want to bail out immediately so that we can
1127             # use $1, $2, etc. without having to do the match twice.
1128             sub {
1129 349     349   975 for (2..$#$ell) {
1130 594 100       835 next if ref $ell->[$_];
1131 457 100       1145 next unless $ell->[$_] =~ m/^(?:([^|]*)\|)?(\w+:[^:\s]\S*)$/s;
1132 44         198 return ($_, $1, $2);
1133             }
1134 305         684 return;
1135             }->()
1136             ) {
1137 44         75 $ell->[1]{'type'} = 'url';
1138              
1139 44         84 my @text = @{$ell}[2..$url_index-1];
  44         72  
1140 44 100       78 push @text, $text_part if defined $text_part;
1141              
1142 44         76 my @url = @{$ell}[$url_index+1..$#$ell];
  44         51  
1143 44         99 unshift @url, $url_part;
1144              
1145 44 100       63 unless (@text) {
1146 30         44 $ell->[1]{'content-implicit'} = 'yes';
1147 30         48 @text = @url;
1148             }
1149              
1150 44 100       302 $ell->[1]{to} = Pod::Simple::LinkSection->new(
1151             @url == 1
1152             ? $url[0]
1153             : [ '', {}, @url ],
1154             );
1155              
1156 44         123 splice @$ell, 2, $#$ell, @text;
1157              
1158 44         292 next;
1159             }
1160              
1161             # Catch some very simple and/or common cases
1162 305 100 66     1116 if(@{$ell} == 3 and ! ref $ell->[2]) {
  305         756  
1163 228         295 my $it = $ell->[2];
1164 228 100       394 if($it =~ m{^[^/|]+[(][-a-zA-Z0-9]+[)]$}s) { # man sections
1165             # Hopefully neither too broad nor too restrictive a RE
1166 6         9 DEBUG > 1 and print STDERR "Catching \"$it\" as manpage link.\n";
1167 6         11 $ell->[1]{'type'} = 'man';
1168             # This's the only place where man links can get made.
1169 6         8 $ell->[1]{'content-implicit'} = 'yes';
1170 6         37 $ell->[1]{'to' } =
1171             Pod::Simple::LinkSection->new( $it ); # treelet!
1172              
1173 6         18 next;
1174             }
1175 222 100       743 if($it =~ m/^[^\/\|,\$\%\@\ \"\<\>\:\#\&\*\{\}\[\]\(\)]+(\:\:[^\/\|,\$\%\@\ \"\<\>\:\#\&\*\{\}\[\]\(\)]+)*$/s) {
1176             # Extremely forgiving idea of what constitutes a bare
1177             # modulename link like L or even L
1178 127         135 DEBUG > 1 and print STDERR "Catching \"$it\" as ho-hum L link.\n";
1179 127         222 $ell->[1]{'type'} = 'pod';
1180 127         178 $ell->[1]{'content-implicit'} = 'yes';
1181 127         507 $ell->[1]{'to' } =
1182             Pod::Simple::LinkSection->new( $it ); # treelet!
1183 127         277 next;
1184             }
1185             # else fall thru...
1186             }
1187              
1188              
1189              
1190             # ...Uhoh, here's the real L<...> parsing stuff...
1191             # "With the ill behavior, with the ill behavior, with the ill behavior..."
1192              
1193 172         190 DEBUG > 1 and print STDERR "Running a real parse on this non-trivial L\n";
1194              
1195              
1196 172         186 my $link_text; # set to an arrayref if found
1197 172         388 my @ell_content = @$ell;
1198 172         277 splice @ell_content,0,2; # Knock off the 'L' and {} bits
1199              
1200 172         172 DEBUG > 3 and print STDERR " Ell content to start: ",
1201             pretty(@ell_content), "\n";
1202              
1203              
1204             # Look for the "|" -- only in CHILDREN (not all underlings!)
1205             # Like L
1206 172         170 DEBUG > 3 and
1207             print STDERR " Peering at L content for a '|' ...\n";
1208 172         316 for(my $j = 0; $j < @ell_content; ++$j) {
1209 389 100       601 next if ref $ell_content[$j];
1210 269         236 DEBUG > 3 and
1211             print STDERR " Peering at L-content text bit \"$ell_content[$j]\" for a '|'.\n";
1212              
1213 269 100       620 if($ell_content[$j] =~ m/^([^\|]*)\|(.*)$/s) {
1214 61         142 my @link_text = ($1); # might be 0-length
1215 61         111 $ell_content[$j] = $2; # might be 0-length
1216              
1217 61         77 DEBUG > 3 and
1218             print STDERR " FOUND a '|' in it. Splitting into [$1] + [$2]\n";
1219              
1220 61 100       128 if ($link_text[0] =~ m{[|/]}) {
1221 1         4 $self->whine(
1222             $start_line,
1223             "alternative text '$link_text[0]' contains non-escaped | or /"
1224             );
1225             }
1226              
1227 61         103 unshift @link_text, splice @ell_content, 0, $j;
1228             # leaving only things at J and after
1229 61   66     250 @ell_content = grep ref($_)||length($_), @ell_content ;
1230 61   100     210 $link_text = [grep ref($_)||length($_), @link_text ];
1231 61         68 DEBUG > 3 and printf
1232             " So link text is %s\n and remaining ell content is %s\n",
1233             pretty($link_text), pretty(@ell_content);
1234 61         93 last;
1235             }
1236             }
1237              
1238              
1239             # Now look for the "/" -- only in CHILDREN (not all underlings!)
1240             # And afterward, anything left in @ell_content will be the raw name
1241             # Like L
1242 172         210 my $section_name; # set to arrayref if found
1243 172         221 DEBUG > 3 and print STDERR " Peering at L-content for a '/' ...\n";
1244 172         286 for(my $j = 0; $j < @ell_content; ++$j) {
1245 225 100       312 next if ref $ell_content[$j];
1246 190         213 DEBUG > 3 and
1247             print STDERR " Peering at L-content text bit \"$ell_content[$j]\" for a '/'.\n";
1248              
1249 190 100       508 if($ell_content[$j] =~ m/^([^\/]*)\/(.*)$/s) {
1250 107         225 my @section_name = ($2); # might be 0-length
1251 107         160 $ell_content[$j] = $1; # might be 0-length
1252              
1253 107         98 DEBUG > 3 and
1254             print STDERR " FOUND a '/' in it.",
1255             " Splitting to page [...$1] + section [$2...]\n";
1256              
1257 107         182 push @section_name, splice @ell_content, 1+$j;
1258             # leaving only things before and including J
1259              
1260 107   100     387 @ell_content = grep ref($_)||length($_), @ell_content ;
1261 107   100     404 @section_name = grep ref($_)||length($_), @section_name ;
1262              
1263             # Turn L<.../"foo"> into L<.../foo>
1264 107 100 66     789 if(@section_name
      100        
      100        
      66        
      66        
      66        
1265             and !ref($section_name[0]) and !ref($section_name[-1])
1266             and $section_name[ 0] =~ m/^\"/s
1267             and $section_name[-1] =~ m/\"$/s
1268             and !( # catch weird degenerate case of L<"> !
1269             @section_name == 1 and $section_name[0] eq '"'
1270             )
1271             ) {
1272 40         119 $section_name[ 0] =~ s/^\"//s;
1273 40         95 $section_name[-1] =~ s/\"$//s;
1274 40         43 DEBUG > 3 and
1275             print STDERR " Quotes removed: ", pretty(@section_name), "\n";
1276             } else {
1277 67         72 DEBUG > 3 and
1278             print STDERR " No need to remove quotes in ", pretty(@section_name), "\n";
1279             }
1280              
1281 107         122 $section_name = \@section_name;
1282 107         168 last;
1283             }
1284             }
1285              
1286             # Turn L<"Foo Bar"> into L
1287 172 50 66     728 if(!$section_name and @ell_content
      100        
      66        
      100        
      66        
      66        
      66        
1288             and !ref($ell_content[0]) and !ref($ell_content[-1])
1289             and $ell_content[ 0] =~ m/^\"/s
1290             and $ell_content[-1] =~ m/\"$/s
1291             and !( # catch weird degenerate case of L<"> !
1292             @ell_content == 1 and $ell_content[0] eq '"'
1293             )
1294             ) {
1295 19         39 $section_name = [splice @ell_content];
1296 19         55 $section_name->[ 0] =~ s/^\"//s;
1297 19         43 $section_name->[-1] =~ s/\"$//s;
1298 19         33 $ell->[1]{'~tolerated'} = 1;
1299             }
1300              
1301             # Turn L into L.
1302 172 100 100     529 if(!$section_name and !$link_text and @ell_content
      66        
      100        
      100        
1303             and grep !ref($_) && m/ /s, @ell_content
1304             ) {
1305 14         27 $section_name = [splice @ell_content];
1306 14         27 $ell->[1]{'~deprecated'} = 1;
1307             # That's support for the now-deprecated syntax.
1308             # Note that it deliberately won't work on L<...|Foo Bar>
1309             }
1310              
1311              
1312             # Now make up the link_text
1313             # L -> L
1314             # L -> L<"Bar"|Bar>
1315             # L -> L<"Bar" in Foo/Foo>
1316 172 100       245 unless($link_text) {
1317 111         175 $ell->[1]{'content-implicit'} = 'yes';
1318 111         166 $link_text = [];
1319 111 100       300 push @$link_text, '"', @$section_name, '"' if $section_name;
1320              
1321 111 100       184 if(@ell_content) {
1322 51 100       99 $link_text->[-1] .= ' in ' if $section_name;
1323 51         96 push @$link_text, @ell_content;
1324             }
1325             }
1326              
1327              
1328             # And the E resolver will have to deal with all our treeletty things:
1329              
1330 172 100 66     524 if(@ell_content == 1 and !ref($ell_content[0])
      100        
1331             and $ell_content[0] =~ m{^[^/]+[(][-a-zA-Z0-9]+[)]$}s
1332             ) {
1333 9         17 $ell->[1]{'type'} = 'man';
1334 9         7 DEBUG > 3 and print STDERR "Considering this ($ell_content[0]) a man link.\n";
1335             } else {
1336 163         240 $ell->[1]{'type'} = 'pod';
1337 163         148 DEBUG > 3 and print STDERR "Considering this a pod link (not man or url).\n";
1338             }
1339              
1340 172 100       253 if( defined $section_name ) {
1341 140         862 $ell->[1]{'section'} = Pod::Simple::LinkSection->new(
1342             ['', {}, @$section_name]
1343             );
1344 140         318 DEBUG > 3 and print STDERR "L-section content: ", pretty($ell->[1]{'section'}), "\n";
1345             }
1346              
1347 172 100       246 if( @ell_content ) {
1348 93         388 $ell->[1]{'to'} = Pod::Simple::LinkSection->new(
1349             ['', {}, @ell_content]
1350             );
1351 93         155 DEBUG > 3 and print STDERR "L-to content: ", pretty($ell->[1]{'to'}), "\n";
1352             }
1353              
1354             # And update children to be the link-text:
1355 172 50       644 @$ell = (@$ell[0,1], defined($link_text) ? splice(@$link_text) : '');
1356              
1357 172         179 DEBUG > 2 and print STDERR "End of L-parsing for this node " . pretty($treelet->[$i]) . "\n";
1358              
1359 172         622 unshift @stack, $treelet->[$i]; # might as well recurse
1360             }
1361             }
1362              
1363 1093         1425 return;
1364             }
1365              
1366             # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1367              
1368             sub _treat_Es {
1369 1093     1093   1396 my($self,@stack) = @_;
1370              
1371 1093         1169 my($i, $treelet, $content, $replacer, $charnum);
1372 1093         1474 my $start_line = $stack[0][1]{'start_line'};
1373              
1374             # A recursive algorithm implemented iteratively! Whee!
1375              
1376              
1377             # Has frightening side effects on L nodes' attributes.
1378              
1379             #my @ells_to_tweak;
1380              
1381 1093         1699 while($treelet = shift @stack) {
1382 3709         4907 for(my $i = 2; $i < @$treelet; ++$i) { # iterate over children
1383 8166 100       13402 next unless ref $treelet->[$i]; # text nodes are uninteresting
1384 2490 100       4200 if($treelet->[$i][0] eq 'L') {
    100          
1385             # SPECIAL STUFF for semi-processed L<>'s
1386              
1387 349         335 my $thing;
1388 349         459 foreach my $attrname ('section', 'to') {
1389 698 100 66     1577 if(defined($thing = $treelet->[$i][1]{$attrname}) and ref $thing) {
1390 410         467 unshift @stack, $thing;
1391             DEBUG > 2 and print STDERR " Enqueuing ",
1392 410         458 pretty( $treelet->[$i][1]{$attrname} ),
1393             " as an attribute value to tweak.\n";
1394             }
1395             }
1396              
1397 349         410 unshift @stack, $treelet->[$i]; # recurse
1398 349         597 next;
1399             } elsif($treelet->[$i][0] ne 'E') {
1400 1857         2051 unshift @stack, $treelet->[$i]; # recurse
1401 1857         2333 next;
1402             }
1403              
1404 284         305 DEBUG > 1 and print STDERR "Ogling E node ", pretty($treelet->[$i]), "\n";
1405              
1406             # bitch if it's empty
1407 284 50 33     275 if( @{$treelet->[$i]} == 2
  284   33     498  
1408 284         761 or (@{$treelet->[$i]} == 3 and $treelet->[$i][2] eq '')
1409             ) {
1410 0         0 $self->whine( $start_line, "An empty E<>" );
1411 0         0 $treelet->[$i] = 'E<>'; # splice in a literal
1412 0         0 next;
1413             }
1414              
1415             # bitch if content is weird
1416 284 50 33     299 unless(@{$treelet->[$i]} == 3 and !ref($content = $treelet->[$i][2])) {
  284         691  
1417 0         0 $self->whine( $start_line, "An E<...> surrounding strange content" );
1418 0         0 $replacer = $treelet->[$i]; # scratch
1419 0         0 splice(@$treelet, $i, 1, # fake out a literal
1420             'E<',
1421             splice(@$replacer,2), # promote its content
1422             '>'
1423             );
1424             # Don't need to do --$i, as the 'E<' we just added isn't interesting.
1425 0         0 next;
1426             }
1427              
1428 284         285 DEBUG > 1 and print STDERR "Ogling E<$content>\n";
1429              
1430             # XXX E<>'s contents *should* be a valid char in the scope of the current
1431             # =encoding directive. Defaults to iso-8859-1, I believe. Fix this in the
1432             # future sometime.
1433              
1434 284         555 $charnum = Pod::Escapes::e2charnum($content);
1435 284         2572 DEBUG > 1 and print STDERR " Considering E<$content> with char ",
1436             defined($charnum) ? $charnum : "undef", ".\n";
1437              
1438 284 100 100     600 if(!defined( $charnum )) {
    50          
1439 6         8 DEBUG > 1 and print STDERR "I don't know how to deal with E<$content>.\n";
1440 6         18 $self->whine( $start_line, "Unknown E content in E<$content>" );
1441 6         9 $replacer = "E<$content>"; # better than nothing
1442             } elsif($charnum >= 255 and !UNICODE) {
1443 0         0 $replacer = ASCII ? "\xA4" : "?";
1444 0         0 DEBUG > 1 and print STDERR "This Perl version can't handle ",
1445             "E<$content> (chr $charnum), so replacing with $replacer\n";
1446             } else {
1447 278         425 $replacer = Pod::Escapes::e2char($content);
1448 278         2658 DEBUG > 1 and print STDERR " Replacing E<$content> with $replacer\n";
1449             }
1450              
1451 284         835 splice(@$treelet, $i, 1, $replacer); # no need to back up $i, tho
1452             }
1453             }
1454              
1455 1093         1405 return;
1456             }
1457              
1458              
1459             # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1460              
1461             sub _treat_Ss {
1462 1093     1093   1266 my($self,$treelet) = @_;
1463              
1464 1093 100       2376 _change_S_to_nbsp($treelet,0) if $self->{'nbsp_for_S'};
1465              
1466             # TODO: or a change_nbsp_to_S
1467             # Normalizing nbsp's to S is harder: for each text node, make S content
1468             # out of anything matching m/([^ \xA0]*(?:\xA0+[^ \xA0]*)+)/
1469              
1470              
1471 1093         1205 return;
1472             }
1473              
1474             sub _change_S_to_nbsp { # a recursive function
1475             # Sanely assumes that the top node in the excursion won't be an S node.
1476 1682     1682   1818 my($treelet, $in_s) = @_;
1477              
1478 1682         1932 my $is_s = ('S' eq $treelet->[0]);
1479 1682   100     4021 $in_s ||= $is_s; # So in_s is on either by this being an S element,
1480             # or by an ancestor being an S element.
1481              
1482 1682         2244 for(my $i = 2; $i < @$treelet; ++$i) {
1483 3966 100       4091 if(ref $treelet->[$i]) {
1484 1176 100       1427 if( _change_S_to_nbsp( $treelet->[$i], $in_s ) ) {
1485 12         16 my $to_pull_up = $treelet->[$i];
1486 12         21 splice @$to_pull_up,0,2; # ...leaving just its content
1487 12         26 splice @$treelet, $i, 1, @$to_pull_up; # Pull up content
1488 12         28 $i += @$to_pull_up - 1; # Make $i skip the pulled-up stuff
1489             }
1490             } else {
1491 2790 100       4306 $treelet->[$i] =~ s/\s/$Pod::Simple::nbsp/g if $in_s;
1492              
1493             # Note that if you apply nbsp_for_S to text, and so turn
1494             # "foo S quux" into "foo bar faz quux", you
1495             # end up with something that fails to say "and don't hyphenate
1496             # any part of 'bar baz'". However, hyphenation is such a vexing
1497             # problem anyway, that most Pod renderers just don't render it
1498             # at all. But if you do want to implement hyphenation, I guess
1499             # that you'd better have nbsp_for_S off.
1500             }
1501             }
1502              
1503 1682         2826 return $is_s;
1504             }
1505              
1506             #-----------------------------------------------------------------------------
1507              
1508             sub _accessorize { # A simple-minded method-maker
1509 70     70   645 no strict 'refs';
  70         103  
  70         5824  
1510 107     107   277 foreach my $attrname (@_) {
1511 2636 100       4014 next if $attrname =~ m/::/; # a hack
1512 2529         7141 *{caller() . '::' . $attrname} = sub {
1513 70     70   367 use strict;
  70         111  
  70         40080  
1514 8621 50 66 8621   27498 $Carp::CarpLevel = 1, Carp::croak(
      33        
1515             "Accessor usage: \$obj->$attrname() or \$obj->$attrname(\$new_value)"
1516             ) unless (@_ == 1 or @_ == 2) and ref $_[0];
1517              
1518             (@_ == 1) ? $_[0]->{$attrname}
1519 8621 100       20255 : ($_[0]->{$attrname} = $_[1]);
1520 2529         5184 };
1521             }
1522             # Ya know, they say accessories make the ensemble!
1523 107         224 return;
1524             }
1525              
1526             # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1527             # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1528             #=============================================================================
1529              
1530             sub filter {
1531 0     0 1 0 my($class, $source) = @_;
1532 0         0 my $new = $class->new;
1533 0         0 $new->output_fh(*STDOUT{IO});
1534              
1535 0 0 0     0 if(ref($source || '') eq 'SCALAR') {
    0          
1536 0         0 $new->parse_string_document( $$source );
1537             } elsif(ref($source)) { # it's a file handle
1538 0         0 $new->parse_file($source);
1539             } else { # it's a filename
1540 0         0 $new->parse_file($source);
1541             }
1542              
1543 0         0 return $new;
1544             }
1545              
1546              
1547             #-----------------------------------------------------------------------------
1548              
1549             sub _out {
1550             # For use in testing: Class->_out($source)
1551             # returns the transformation of $source
1552              
1553 525     525   3118092 my $class = shift(@_);
1554              
1555 525 100 100     3207 my $mutor = shift(@_) if @_ and ref($_[0] || '') eq 'CODE';
      66        
1556              
1557 525         623 DEBUG and print STDERR "\n\n", '#' x 76,
1558             "\nAbout to parse source: {{\n$_[0]\n}}\n\n";
1559              
1560              
1561 525 100 66     2368 my $parser = ref $class && $class->isa(__PACKAGE__) ? $class : $class->new;
1562 525         1330 $parser->hide_line_numbers(1);
1563              
1564 525         696 my $out = '';
1565 525         1376 $parser->output_string( \$out );
1566 525         639 DEBUG and print STDERR " _out to ", \$out, "\n";
1567              
1568 525 100       1438 $mutor->($parser) if $mutor;
1569              
1570 525         1547 $parser->parse_string_document( $_[0] );
1571             # use Data::Dumper; print STDERR Dumper($parser), "\n";
1572 525         7053 return $out;
1573             }
1574              
1575              
1576             sub _duo {
1577             # For use in testing: Class->_duo($source1, $source2)
1578             # returns the parse trees of $source1 and $source2.
1579             # Good in things like: &ok( Class->duo(... , ...) );
1580              
1581 56     56   551468 my $class = shift(@_);
1582              
1583 56 50       158 Carp::croak "But $class->_duo is useful only in list context!"
1584             unless wantarray;
1585              
1586 56 100 100     332 my $mutor = shift(@_) if @_ and ref($_[0] || '') eq 'CODE';
      66        
1587              
1588 56 50       137 Carp::croak "But $class->_duo takes two parameters, not: @_"
1589             unless @_ == 2;
1590              
1591 56         76 my(@out);
1592              
1593 56         114 while( @_ ) {
1594 112         505 my $parser = $class->new;
1595              
1596 112         199 push @out, '';
1597 112         293 $parser->output_string( \( $out[-1] ) );
1598              
1599 112         135 DEBUG and print STDERR " _duo out to ", $parser->output_string(),
1600             " = $parser->{'output_string'}\n";
1601              
1602 112         268 $parser->hide_line_numbers(1);
1603 112 100       258 $mutor->($parser) if $mutor;
1604 112         262 $parser->parse_string_document( shift( @_ ) );
1605             # use Data::Dumper; print STDERR Dumper($parser), "\n";
1606             }
1607              
1608 56         344 return @out;
1609             }
1610              
1611              
1612              
1613             #-----------------------------------------------------------------------------
1614             1;
1615             __END__