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   1108283 use strict;
  70         197  
  70         2660  
3 70     70   399 use warnings;
  70         132  
  70         3403  
4 70     70   489 use Carp ();
  70         145  
  70         3979  
5 70 50   70   2216 BEGIN { *DEBUG = sub () {0} unless defined &DEBUG }
6 70     70   37880 use integer;
  70         1126  
  70         411  
7 70     70   39317 use Pod::Escapes 1.04 ();
  70         383640  
  70         3951  
8 70     70   36960 use Pod::Simple::LinkSection ();
  70         291  
  70         2118  
9 70     70   577 use Pod::Simple::BlackBox ();
  70         138  
  70         1630  
10 70     70   40371 use Pod::Simple::TiedOutFH;
  70         226  
  70         22743  
11             #use utf8;
12              
13             our @ISA = ('Pod::Simple::BlackBox');
14             our $VERSION = '3.47';
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   6540 if(defined &ASCII) { }
27 70         242 elsif(chr(65) eq 'A') { *ASCII = sub () {1} }
28             else { *ASCII = sub () {''} }
29              
30 70 50       327 unless(defined &MANY_LINES) { *MANY_LINES = sub () {20} }
  70         168  
31 70         125 DEBUG > 4 and print STDERR "MANY_LINES is ", MANY_LINES(), "\n";
32 70 50       403 unless(MANY_LINES() >= 1) {
33 0         0 die "MANY_LINES is too small (", MANY_LINES(), ")!\nAborting";
34             }
35 70 50       221 if(defined &UNICODE) { }
    50          
36 70     70   594 elsif( do { no integer; "$]" >= 5.008 } ) { *UNICODE = sub() {1} }
  70         138  
  70         487  
  70         601  
  70         6484  
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   534 if ( do { no integer; "$]" >= 5.007_003 } ) { # On sufficiently modern Perls we can handle any
  70         168  
  70         377  
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 141 return shift->{'errors_seen'} || 0;
129             }
130              
131             sub errata_seen {
132 8   50 8 1 1940 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 103 my $this = shift;
142 19 50       90 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   44195 *pretty = \&Pod::Simple::BlackBox::pretty;
168 70         209 *stringify_lol = \&Pod::Simple::BlackBox::stringify_lol;
169 70         821689 *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 892     892 1 13400 my $this = shift;
196 892 100       3348 return $this->{'output_string'} unless @_; # GET.
197              
198 882 50 33     3854 my $x = (defined($_[0]) and ref($_[0])) ? $_[0] : \( $_[0] );
199 882 100       2292 $$x = '' unless defined $$x;
200 882         1232 DEBUG > 4 and print STDERR "# Output string set to $x ($$x)\n";
201 882         4577 $this->{'output_fh'} = Pod::Simple::TiedOutFH->handle_on($_[0]);
202             return
203 882         2870 $this->{'output_string'} = $_[0];
204             #${ ${ $this->{'output_fh'} } };
205             }
206              
207 10     10 1 43 sub abandon_output_string { $_[0]->abandon_output_fh; delete $_[0]{'output_string'} }
  10         31  
208 10     10 1 31 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 923   33 923 1 186064 my $class = ref($_[0]) || $_[0];
218             #Carp::croak(__PACKAGE__ . " is a virtual base class -- see perldoc "
219             # . __PACKAGE__ );
220 923         23280 my $obj = bless {
221             'accept_codes' => { map( ($_=>$_), @Known_formatting_codes ) },
222             'accept_directives' => { %Known_directives },
223             'accept_targets' => {},
224             }, $class;
225              
226 923         5628 $obj->expand_verbatim_tabs(8);
227 923         2642 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 45 sub accept_directive_as_verbatim { shift->_accept_directives('Verbatim', @_) }
256 3     3 1 26 sub accept_directive_as_data { shift->_accept_directives('Data', @_) }
257 3     3 1 26 sub accept_directive_as_processed { shift->_accept_directives('Plain', @_) }
258              
259             sub _accept_directives {
260 9     9   32 my($this, $type) = splice @_,0,2;
261 9         24 foreach my $d (@_) {
262 9 50 33     43 next unless defined $d and length $d;
263 9 50       61 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       28 if exists $Known_directives{$d};
267 9         28 $this->{'accept_directives'}{$d} = $type;
268 9         19 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         12 pretty($this->{'accept_directives'}), "\n";
272              
273 9 50       21 return sort keys %{ $this->{'accept_directives'} } if wantarray;
  0         0  
274 9         20 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 241 sub accept_target { shift->accept_targets(@_) } # alias
302 49     49 1 248 sub accept_target_as_text { shift->accept_targets_as_text(@_) } # alias
303              
304              
305 273     273 1 1015 sub accept_targets { shift->_accept_targets('1', @_) }
306              
307 53     53 1 206 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 326     326   1532 my($this, $type) = splice @_,0,2;
312 326         982 foreach my $t (@_) {
313 599 50 33     2146 next unless defined $t and length $t;
314             # TODO: enforce some limitations on what a target name can be?
315 599         1551 $this->{'accept_targets'}{$t} = $type;
316 599         1083 DEBUG > 2 and print STDERR "Learning to accept \"$t\" as target of type $type\n";
317             }
318 326 50       780 return sort keys %{ $this->{'accept_targets'} } if wantarray;
  0         0  
319 326         761 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 706 my $this = shift;
351              
352 340         828 foreach my $new_code (@_) {
353 1228 50 33     3393 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     8038 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         3069 $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         699 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 139 my $this = shift;
383              
384 29         73 foreach my $new_code (@_) {
385 29 50 33     120 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     441 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       155 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         78 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         66 return;
404             }
405              
406              
407             #@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
408             #@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
409              
410             sub parse_string_document {
411 774     774 1 26645 my $self = shift;
412 774         1267 my @lines;
413 774         1703 foreach my $line_group (@_) {
414 774 100 66     3312 next unless defined $line_group and length $line_group;
415 756         2851 pos($line_group) = 0;
416 756         5783 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 8616 100 100     49402 $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 774         2939 $self->parse_lines(undef); # to signal EOF
429 774         3365 return $self;
430             }
431              
432             sub _init_fh_source {
433 51     51   120 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         105 return;
440             }
441              
442             #:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.
443             #
444              
445             sub parse_file {
446 51     51 1 358 my($self, $source) = (@_);
447              
448 51 50       385 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         79 local *PODSOURCE;
  51         173  
459 51 50       2931 open(PODSOURCE, "<$source") || Carp::croak("Can't open $source: $!");
460 51         226 $self->{'source_filename'} = $source;
461 51         182 $source = *PODSOURCE{IO};
462             }
463 51         224 $self->_init_fh_source($source);
464             }
465             # By here, $source is a FH.
466              
467 51         186 $self->{'source_fh'} = $source;
468              
469 51         97 my($i, @lines);
470 51         150 until( $self->{'source_dead'} ) {
471 490         2175 splice @lines;
472              
473 490         1320 for($i = MANY_LINES; $i--;) { # read those many lines at a time
474 9326         20534 local $/ = $NL;
475 9326         23834 push @lines, scalar(<$source>); # readline
476 9326 100       27622 last unless defined $lines[-1];
477             # but pass thru the undef, which will set source_dead to true
478             }
479              
480 490         920 my $at_eof = ! $lines[-1]; # keep track of the undef
481 490 100       964 pop @lines if $at_eof; # silence warnings
482              
483             # be eol agnostic
484 490         3831 s/\r\n?/\n/g for @lines;
485              
486             # make sure there are only one line elements for parse_lines
487 490         49515 @lines = split(/(?<=\n)/, join('', @lines));
488              
489             # push the undef back after popping it to set source_dead to true
490 490 100       4614 push @lines, undef if $at_eof;
491              
492 490         2208 $self->parse_lines(@lines);
493             }
494 51         134 delete($self->{'source_fh'}); # so it can be GC'd
495 51         1210 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 27 my($self, $source, $to) = @_;
505 10 50       27 $self = $self->new unless ref($self); # so we tolerate being a class method
506              
507 10 50 33     136 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     150 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         84 require Symbol;
527 10         40 my $out_fh = Symbol::gensym();
528 10         174 DEBUG and print STDERR "Write-opening to $to\n";
529 10 50       1923 open($out_fh, ">$to") or Carp::croak "Can't write-open $to: $!";
530 10 50 33     121 binmode($out_fh)
531             if $self->can('write_with_binmode') and $self->write_with_binmode;
532 10         44 $self->output_fh($out_fh);
533             }
534              
535 10         69 return $self->parse_file($source);
536             }
537              
538             #-----------------------------------------------------------------------------
539              
540             sub whine {
541             #my($self,$line,$complaint) = @_;
542 79     79 1 184 my $self = shift(@_);
543 79         208 ++$self->{'errors_seen'};
544 79 100       228 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         14 return;
547             }
548 70         211 push @{$self->{'all_errata'}{$_[0]}}, $_[1];
  70         373  
549 70 50       199 return $self->_complain_warn(@_) if $self->{'complain_stderr'};
550 70         280 return $self->_complain_errata(@_);
551             }
552              
553             sub scream { # like whine, but not suppressible
554             #my($self,$line,$complaint) = @_;
555 8     8 1 22 my $self = shift(@_);
556 8         27 ++$self->{'errors_seen'};
557 8         14 push @{$self->{'all_errata'}{$_[0]}}, $_[1];
  8         47  
558 8 50       51 return $self->_complain_warn(@_) if $self->{'complain_stderr'};
559 8         58 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   248 my($self,$line,$complaint) = @_;
570 78 100       246 if( $self->{'no_errata_section'} ) {
571 10         40 DEBUG > 9 and print STDERR "Discarding erratum (at line $line) $complaint\n because no_errata_section is on.\n";
572             } else {
573 68         127 DEBUG > 9 and print STDERR "Queuing erratum (at line $line) $complaint\n";
574 68         131 push @{$self->{'errata'}{$line}}, $complaint
  68         264  
575             # for a report to be generated later!
576             }
577 78         252 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 189     189   486 my($self, $para) = @_;
585 189 50       620 return $para->[1]{'~type'} if $para->[1]{'~type'};
586              
587             return $para->[1]{'~type'} = 'text'
588 189 100 100     558 if join("\n", @{$para}[2 .. $#$para]) =~ m/^\s*(\d+)\.?\s*$/s and $1 ne '1';
  189         1544  
589             # Else fall thru to the general case:
590 187         956 return $self->_get_item_type($para);
591             }
592              
593              
594              
595             sub _get_item_type { # mutates the item!!
596 1213     1213   2712 my($self, $para) = @_;
597 1213 100       3543 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 1024         2279 my $content = join "\n", @{$para}[2 .. $#$para];
  1024         3028  
603              
604 1024 100 100     8783 if($content =~ m/^\s*\*\s*$/s or $content =~ m/^\s*$/s) {
    100          
    100          
605             # Like: "=item *", "=item * ", "=item"
606 59         150 splice @$para, 2; # so it ends up just being ['=item', { attrhash } ]
607 59         190 $para->[1]{'~orig_content'} = $content;
608 59         291 return $para->[1]{'~type'} = 'bullet';
609              
610             } elsif($content =~ m/^\s*\*\s+(.+)/s) { # tolerance
611              
612             # Like: "=item * Foo bar baz";
613 101         280 $para->[1]{'~orig_content'} = $content;
614 101         301 $para->[1]{'~_freaky_para_hack'} = $1;
615 101         115 DEBUG > 2 and print STDERR " Tolerating $$para[2] as =item *\\n\\n$1\n";
616 101         217 splice @$para, 2; # so it ends up just being ['=item', { attrhash } ]
617 101         492 return $para->[1]{'~type'} = 'bullet';
618              
619             } elsif($content =~ m/^\s*(\d+)\.?\s*$/s) {
620             # Like: "=item 1.", "=item 123412"
621              
622 31         179 $para->[1]{'~orig_content'} = $content;
623 31         97 $para->[1]{'number'} = $1; # Yes, stores the number there!
624              
625 31         63 splice @$para, 2; # so it ends up just being ['=item', { attrhash } ]
626 31         142 return $para->[1]{'~type'} = 'number';
627              
628             } else {
629             # It's anything else.
630 833         3844 return $para->[1]{'~type'} = 'text';
631              
632             }
633             }
634              
635             #-----------------------------------------------------------------------------
636              
637             sub _make_treelet {
638 4479     4479   7156 my $self = shift; # and ($para, $start_line)
639 4479         6435 my $treelet;
640 4479 50       9380 if(!@_) {
641 0         0 return [''];
642 4479 50 33     12063 } 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 4479         14173 $treelet = $self->_treelet_from_formatting_codes(@_);
653             }
654              
655 4479 100 100     17256 if( ! $self->{'_output_is_for_JustPod'} # Retain these as-is for pod output
656             && $self->_remap_sequences($treelet) )
657             {
658 1090         3771 $self->_treat_Zs($treelet); # Might as well nix these first
659 1090         3496 $self->_treat_Ls($treelet); # L has to precede E and S
660 1090         4030 $self->_treat_Es($treelet);
661 1090         3280 $self->_treat_Ss($treelet); # S has to come after E
662 1090         2843 $self->_wrap_up($treelet); # Nix X's and merge texties
663              
664             } else {
665 3389         4723 DEBUG and print STDERR "Formatless treelet gets fast-tracked.\n";
666             # Very common case!
667             }
668              
669 4479         9908 splice @$treelet, 0, 2; # lop the top off
670              
671 4479         21573 return $treelet;
672             }
673              
674             #:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.
675              
676             sub _wrap_up {
677 1090     1090   1976 my($self, @stack) = @_;
678 1090         2110 my $nixx = $self->{'nix_X_codes'};
679 1090         1951 my $merge = $self->{'merge_text' };
680 1090 100 100     3487 return unless $nixx or $merge;
681              
682 748         925 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 748         1200 my($i, $treelet);
689 748         1527 while($treelet = shift @stack) {
690 2739         3458 DEBUG > 3 and print STDERR " Considering children of this $treelet->[0] node...\n";
691 2739         4851 for($i = 2; $i < @$treelet; ++$i) { # iterate over children
692 6236         7077 DEBUG > 3 and print STDERR " Considering child at $i ", pretty($treelet->[$i]), "\n";
693 6236 100 100     31286 if($nixx and ref $treelet->[$i] and $treelet->[$i][0] eq 'X') {
    100 100        
    100 100        
      100        
      100        
694 6         9 DEBUG > 3 and print STDERR " Nixing X node at $i\n";
695 6         12 splice(@$treelet, $i, 1); # just nix this node (and its descendants)
696             # no need to back-update the counter just yet
697 6         12 redo;
698              
699             } elsif($merge and $i != 2 and # non-initial
700             !ref $treelet->[$i] and !ref $treelet->[$i - 1]
701             ) {
702 25         23 DEBUG > 3 and print STDERR " Merging ", $i-1,
703             ":[$treelet->[$i-1]] and $i\:[$treelet->[$i]]\n";
704 25         47 $treelet->[$i-1] .= ( splice(@$treelet, $i, 1) )[0];
705 25         41 DEBUG > 4 and print STDERR " Now: ", $i-1, ":[$treelet->[$i-1]]\n";
706 25         46 --$i;
707 25         42 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 1751         2080 DEBUG > 4 and print STDERR " Enqueuing ", pretty($treelet->[$i]), " for traversal.\n";
713 1751         2526 push @stack, $treelet->[$i];
714              
715 1751 100       4093 if($treelet->[$i][0] eq 'L') {
716 210         266 my $thing;
717 210         415 foreach my $attrname ('section', 'to') {
718 420 100 66     1340 if(defined($thing = $treelet->[$i][1]{$attrname}) and ref $thing) {
719 240         397 unshift @stack, $thing;
720             DEBUG > 4 and print STDERR " +Enqueuing ",
721 240         530 pretty( $treelet->[$i][1]{$attrname} ),
722             " as an attribute value to tweak.\n";
723             }
724             }
725             }
726             }
727             }
728             }
729 748         995 DEBUG > 2 and print STDERR "End of _wrap_up traversal.\n\n";
730              
731 748         1461 return;
732             }
733              
734             #:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.
735              
736             sub _remap_sequences {
737 3607     3607   8334 my($self,@stack) = @_;
738              
739 3607 100 66     8215 if(@stack == 1 and @{ $stack[0] } == 3 and !ref $stack[0][2]) {
  3607   100     15177  
740             # VERY common case: abort it.
741 2517         3341 DEBUG and print STDERR "Skipping _remap_sequences: formatless treelet.\n";
742 2517         8775 return 0;
743             }
744              
745 1090   50     3061 my $map = ($self->{'accept_codes'} || die "NO accept_codes in $self?!?");
746              
747 1090         2386 my $start_line = $stack[0][1]{'start_line'};
748 1090         1465 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 1090         1468 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 1090         1846 my($is, $was, $i, $treelet); # scratch
764 1090         2601 while($treelet = shift @stack) {
765 3497         4328 DEBUG > 3 and print STDERR " Considering children of this $treelet->[0] node...\n";
766 3497         6535 for($i = 2; $i < @$treelet; ++$i) { # iterate over children
767 7581 100       18840 next unless ref $treelet->[$i]; # text nodes are uninteresting
768              
769 2413         2866 DEBUG > 4 and print STDERR " Noting child $i : $treelet->[$i][0]<...>\n";
770              
771 2413         5829 $is = $treelet->[$i][0] = $map->{ $was = $treelet->[$i][0] };
772 2413         3033 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 2413 100       4097 if(!defined $is) {
786 4         139 $self->whine($start_line, "Deleting unknown formatting code $was<>");
787 4         9 $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 2413 100       5931 if(ref $is) {
    50          
    100          
792 2         8 my @dynasty = @$is;
793 2         5 DEBUG > 4 and print STDERR " Renaming $was node to $dynasty[-1]\n";
794 2         4 $treelet->[$i][0] = pop @dynasty;
795 2         4 my $nugget;
796 2         6 while(@dynasty) {
797 3         5 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         17 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         8 => splice @{ $treelet->[$i] },2
  4         16  
812             # (not catching its first two (non-child) items)
813             );
814 4         18 --$i; # back up for new stuff
815             } else {
816             # otherwise it's unremarkable
817 2407         5622 unshift @stack, $treelet->[$i]; # just recurse
818             }
819             }
820             }
821              
822 1090         1540 DEBUG > 2 and print STDERR "End of _remap_sequences traversal.\n\n";
823              
824 1090 50 66     2630 if(@_ == 2 and @{ $_[1] } == 3 and !ref $_[1][2]) {
  1090   66     3667  
825 0         0 DEBUG and print STDERR "Noting that the treelet is now formatless.\n";
826 0         0 return 0;
827             }
828 1090         3770 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   53 my($self, $para) = @_;
839 21         89 my $content = join ' ', splice @$para, 2;
840 21         78 $content =~ s/^\s+//s;
841 21         82 $content =~ s/\s+$//s;
842              
843 21         35 DEBUG > 2 and print STDERR "Ogling extensor: =extend $content\n";
844              
845 21 50       155 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         63 my $new_letter = $1;
856 21         42 my $fallbacks_one = $2;
857 21         31 my $elements_one;
858 21 50       73 $elements_one = defined($3) ? $3 : $1;
859              
860 21         28 DEBUG > 2 and print STDERR "Extensor has good syntax.\n";
861              
862 21 50 33     118 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       120 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     106 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       118 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         74 my @fallbacks = split ',', $fallbacks_one, -1;
905 21         66 my @elements = split ',', $elements_one, -1;
906              
907 21         43 foreach my $f (@fallbacks) {
908 42 0 33     144 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         39 DEBUG > 3 and printf STDERR "Extensor: Fallbacks <%s> Elements <%s>.\n",
918             @fallbacks, @elements;
919              
920 21         33 my $canonical_form;
921 21         38 foreach my $e (@elements) {
922 42 100       102 if(exists $self->{'accept_codes'}{$e}) {
923 15         20 DEBUG > 1 and print STDERR " Mapping '$new_letter' to known extension '$e'\n";
924 15         27 $canonical_form = $e;
925 15         28 last; # first acceptable elementname wins!
926             } else {
927 27         45 DEBUG > 1 and print STDERR " Can't map '$new_letter' to unknown extension '$e'\n";
928             }
929             }
930              
931              
932 21 100       42 if( defined $canonical_form ) {
933             # We found a good N => elementname mapping
934 15         44 $self->{'accept_codes'}{$new_letter} = $canonical_form;
935 15         46 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       23 $self->{'accept_codes'}{$new_letter}
940             = (@fallbacks == 1) ? $fallbacks[0] : \@fallbacks;
941 6         18 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         69 return;
953             }
954              
955              
956             #:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.
957              
958             sub _treat_Zs { # Nix Z<...>'s
959 1090     1090   2308 my($self,@stack) = @_;
960              
961 1090         1624 my($i, $treelet);
962 1090         2054 my $start_line = $stack[0][1]{'start_line'};
963              
964             # A recursive algorithm implemented iteratively! Whee!
965              
966 1090         2565 while($treelet = shift @stack) {
967 3465         6595 for($i = 2; $i < @$treelet; ++$i) { # iterate over children
968 7545 100       17250 next unless ref $treelet->[$i]; # text nodes are uninteresting
969 2412 100       4829 unless($treelet->[$i][0] eq 'Z') {
970 2375         3656 unshift @stack, $treelet->[$i]; # recurse
971 2375         4761 next;
972             }
973              
974 37         40 DEBUG > 1 and print STDERR "Nixing Z node @{$treelet->[$i]}\n";
975              
976             # bitch UNLESS it's empty
977 37 50 33     73 unless( @{$treelet->[$i]} == 2
  37   33     95  
978 37         145 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         66 splice(@$treelet, $i, 1); # thereby just nix this node.
984 37         100 --$i;
985              
986             }
987             }
988              
989 1090         2267 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 1090     1090   2105 my($self,@stack) = @_;
1066              
1067 1090         1617 my($i, $treelet);
1068 1090         2041 my $start_line = $stack[0][1]{'start_line'};
1069              
1070             # A recursive algorithm implemented iteratively! Whee!
1071              
1072 1090         2308 while($treelet = shift @stack) {
1073 3255         6524 for(my $i = 2; $i < @$treelet; ++$i) {
1074             # iterate over children of current tree node
1075 7472 100       17045 next unless ref $treelet->[$i]; # text nodes are uninteresting
1076 2343 100       4908 unless($treelet->[$i][0] eq 'L') {
1077 1996         3009 unshift @stack, $treelet->[$i]; # recurse
1078 1996         3664 next;
1079             }
1080              
1081              
1082             # By here, $treelet->[$i] is definitely an L node
1083 347         583 my $ell = $treelet->[$i];
1084 347         434 DEBUG > 1 and print STDERR "Ogling L node " . pretty($ell) . "\n";
1085              
1086             # bitch if it's empty or is just '/'
1087 347 100 100     459 if (@{$ell} == 3 and $ell->[2] =~ m!\A\s*/\s*\z!) {
  347         1722  
1088 1         5 $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 346 50 66     503 if( @{$ell} == 2
  346   33     924  
1093 346         1322 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 346 100 100     2990 if( (! ref $ell->[2] && $ell->[2] =~ /\A\s/)
      66        
      66        
1101             ||(! ref $ell->[-1] && $ell->[-1] =~ /\s\z/)
1102             ) {
1103 2         6 $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 346 100       2518 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 346     346   1261 for (2..$#$ell) {
1130 591 100       1337 next if ref $ell->[$_];
1131 454 100       1686 next unless $ell->[$_] =~ m/^(?:([^|]*)\|)?(\w+:[^:\s]\S*)$/s;
1132 44         264 return ($_, $1, $2);
1133             }
1134 302         967 return;
1135             }->()
1136             ) {
1137 44         123 $ell->[1]{'type'} = 'url';
1138              
1139 44         103 my @text = @{$ell}[2..$url_index-1];
  44         95  
1140 44 100       102 push @text, $text_part if defined $text_part;
1141              
1142 44         91 my @url = @{$ell}[$url_index+1..$#$ell];
  44         92  
1143 44         98 unshift @url, $url_part;
1144              
1145 44 100       89 unless (@text) {
1146 30         60 $ell->[1]{'content-implicit'} = 'yes';
1147 30         56 @text = @url;
1148             }
1149              
1150 44 100       434 $ell->[1]{to} = Pod::Simple::LinkSection->new(
1151             @url == 1
1152             ? $url[0]
1153             : [ '', {}, @url ],
1154             );
1155              
1156 44         156 splice @$ell, 2, $#$ell, @text;
1157              
1158 44         355 next;
1159             }
1160              
1161             # Catch some very simple and/or common cases
1162 302 100 66     1561 if(@{$ell} == 3 and ! ref $ell->[2]) {
  302         1094  
1163 225         494 my $it = $ell->[2];
1164 225 100       573 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         16 $ell->[1]{'type'} = 'man';
1168             # This's the only place where man links can get made.
1169 6         12 $ell->[1]{'content-implicit'} = 'yes';
1170 6         38 $ell->[1]{'to' } =
1171             Pod::Simple::LinkSection->new( $it ); # treelet!
1172              
1173 6         23 next;
1174             }
1175 219 100       1169 if($it =~ m/^[^\/\|,\$\%\@\ \"\<\>\:\#\&\*\{\}\[\]\(\)]+(\:\:[^\/\|,\$\%\@\ \"\<\>\:\#\&\*\{\}\[\]\(\)]+)*$/s) {
1176             # Extremely forgiving idea of what constitutes a bare
1177             # modulename link like L or even L
1178 127         178 DEBUG > 1 and print STDERR "Catching \"$it\" as ho-hum L link.\n";
1179 127         321 $ell->[1]{'type'} = 'pod';
1180 127         272 $ell->[1]{'content-implicit'} = 'yes';
1181 127         729 $ell->[1]{'to' } =
1182             Pod::Simple::LinkSection->new( $it ); # treelet!
1183 127         472 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 169         331 DEBUG > 1 and print STDERR "Running a real parse on this non-trivial L\n";
1194              
1195              
1196 169         260 my $link_text; # set to an arrayref if found
1197 169         560 my @ell_content = @$ell;
1198 169         379 splice @ell_content,0,2; # Knock off the 'L' and {} bits
1199              
1200 169         255 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 169         238 DEBUG > 3 and
1207             print STDERR " Peering at L content for a '|' ...\n";
1208 169         499 for(my $j = 0; $j < @ell_content; ++$j) {
1209 386 100       999 next if ref $ell_content[$j];
1210 266         388 DEBUG > 3 and
1211             print STDERR " Peering at L-content text bit \"$ell_content[$j]\" for a '|'.\n";
1212              
1213 266 100       1006 if($ell_content[$j] =~ m/^([^\|]*)\|(.*)$/s) {
1214 61         197 my @link_text = ($1); # might be 0-length
1215 61         149 $ell_content[$j] = $2; # might be 0-length
1216              
1217 61         94 DEBUG > 3 and
1218             print STDERR " FOUND a '|' in it. Splitting into [$1] + [$2]\n";
1219              
1220 61 100       196 if ($link_text[0] =~ m{[|/]}) {
1221 1         7 $self->whine(
1222             $start_line,
1223             "alternative text '$link_text[0]' contains non-escaped | or /"
1224             );
1225             }
1226              
1227 61         180 unshift @link_text, splice @ell_content, 0, $j;
1228             # leaving only things at J and after
1229 61   66     348 @ell_content = grep ref($_)||length($_), @ell_content ;
1230 61   100     392 $link_text = [grep ref($_)||length($_), @link_text ];
1231 61         84 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         132 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 169         269 my $section_name; # set to arrayref if found
1243 169         282 DEBUG > 3 and print STDERR " Peering at L-content for a '/' ...\n";
1244 169         479 for(my $j = 0; $j < @ell_content; ++$j) {
1245 222 100       523 next if ref $ell_content[$j];
1246 187         253 DEBUG > 3 and
1247             print STDERR " Peering at L-content text bit \"$ell_content[$j]\" for a '/'.\n";
1248              
1249 187 100       814 if($ell_content[$j] =~ m/^([^\/]*)\/(.*)$/s) {
1250 104         389 my @section_name = ($2); # might be 0-length
1251 104         244 $ell_content[$j] = $1; # might be 0-length
1252              
1253 104         147 DEBUG > 3 and
1254             print STDERR " FOUND a '/' in it.",
1255             " Splitting to page [...$1] + section [$2...]\n";
1256              
1257 104         278 push @section_name, splice @ell_content, 1+$j;
1258             # leaving only things before and including J
1259              
1260 104   100     628 @ell_content = grep ref($_)||length($_), @ell_content ;
1261 104   100     620 @section_name = grep ref($_)||length($_), @section_name ;
1262              
1263             # Turn L<.../"foo"> into L<.../foo>
1264 104 100 66     1274 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         193 $section_name[ 0] =~ s/^\"//s;
1273 40         157 $section_name[-1] =~ s/\"$//s;
1274 40         86 DEBUG > 3 and
1275             print STDERR " Quotes removed: ", pretty(@section_name), "\n";
1276             } else {
1277 64         123 DEBUG > 3 and
1278             print STDERR " No need to remove quotes in ", pretty(@section_name), "\n";
1279             }
1280              
1281 104         276 $section_name = \@section_name;
1282 104         234 last;
1283             }
1284             }
1285              
1286             # Turn L<"Foo Bar"> into L
1287 169 50 66     1130 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         92 $section_name = [splice @ell_content];
1296 19         81 $section_name->[ 0] =~ s/^\"//s;
1297 19         66 $section_name->[-1] =~ s/\"$//s;
1298 19         59 $ell->[1]{'~tolerated'} = 1;
1299             }
1300              
1301             # Turn L into L.
1302 169 100 100     751 if(!$section_name and !$link_text and @ell_content
      66        
      100        
      100        
1303             and grep !ref($_) && m/ /s, @ell_content
1304             ) {
1305 14         57 $section_name = [splice @ell_content];
1306 14         42 $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 169 100       369 unless($link_text) {
1317 108         292 $ell->[1]{'content-implicit'} = 'yes';
1318 108         193 $link_text = [];
1319 108 100       493 push @$link_text, '"', @$section_name, '"' if $section_name;
1320              
1321 108 100       242 if(@ell_content) {
1322 51 100       165 $link_text->[-1] .= ' in ' if $section_name;
1323 51         123 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 169 100 66     839 if(@ell_content == 1 and !ref($ell_content[0])
      100        
1331             and $ell_content[0] =~ m{^[^/]+[(][-a-zA-Z0-9]+[)]$}s
1332             ) {
1333 9         24 $ell->[1]{'type'} = 'man';
1334 9         15 DEBUG > 3 and print STDERR "Considering this ($ell_content[0]) a man link.\n";
1335             } else {
1336 160         369 $ell->[1]{'type'} = 'pod';
1337 160         227 DEBUG > 3 and print STDERR "Considering this a pod link (not man or url).\n";
1338             }
1339              
1340 169 100       354 if( defined $section_name ) {
1341 137         1527 $ell->[1]{'section'} = Pod::Simple::LinkSection->new(
1342             ['', {}, @$section_name]
1343             );
1344 137         466 DEBUG > 3 and print STDERR "L-section content: ", pretty($ell->[1]{'section'}), "\n";
1345             }
1346              
1347 169 100       361 if( @ell_content ) {
1348 93         592 $ell->[1]{'to'} = Pod::Simple::LinkSection->new(
1349             ['', {}, @ell_content]
1350             );
1351 93         245 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 169 50       979 @$ell = (@$ell[0,1], defined($link_text) ? splice(@$link_text) : '');
1356              
1357 169         288 DEBUG > 2 and print STDERR "End of L-parsing for this node " . pretty($treelet->[$i]) . "\n";
1358              
1359 169         920 unshift @stack, $treelet->[$i]; # might as well recurse
1360             }
1361             }
1362              
1363 1090         1985 return;
1364             }
1365              
1366             # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1367              
1368             sub _treat_Es {
1369 1090     1090   2091 my($self,@stack) = @_;
1370              
1371 1090         1736 my($i, $treelet, $content, $replacer, $charnum);
1372 1090         2036 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 1090         2299 while($treelet = shift @stack) {
1382 3700         8154 for(my $i = 2; $i < @$treelet; ++$i) { # iterate over children
1383 8151 100       21165 next unless ref $treelet->[$i]; # text nodes are uninteresting
1384 2487 100       6223 if($treelet->[$i][0] eq 'L') {
    100          
1385             # SPECIAL STUFF for semi-processed L<>'s
1386              
1387 346         534 my $thing;
1388 346         629 foreach my $attrname ('section', 'to') {
1389 692 100 66     2414 if(defined($thing = $treelet->[$i][1]{$attrname}) and ref $thing) {
1390 407         653 unshift @stack, $thing;
1391             DEBUG > 2 and print STDERR " Enqueuing ",
1392 407         689 pretty( $treelet->[$i][1]{$attrname} ),
1393             " as an attribute value to tweak.\n";
1394             }
1395             }
1396              
1397 346         607 unshift @stack, $treelet->[$i]; # recurse
1398 346         897 next;
1399             } elsif($treelet->[$i][0] ne 'E') {
1400 1857         2935 unshift @stack, $treelet->[$i]; # recurse
1401 1857         3462 next;
1402             }
1403              
1404 284         402 DEBUG > 1 and print STDERR "Ogling E node ", pretty($treelet->[$i]), "\n";
1405              
1406             # bitch if it's empty
1407 284 50 33     389 if( @{$treelet->[$i]} == 2
  284   33     813  
1408 284         1261 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     466 unless(@{$treelet->[$i]} == 3 and !ref($content = $treelet->[$i][2])) {
  284         1186  
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         410 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         898 $charnum = Pod::Escapes::e2charnum($content);
1435 284         4327 DEBUG > 1 and print STDERR " Considering E<$content> with char ",
1436             defined($charnum) ? $charnum : "undef", ".\n";
1437              
1438 284 100 100     973 if(!defined( $charnum )) {
    50          
1439 6         12 DEBUG > 1 and print STDERR "I don't know how to deal with E<$content>.\n";
1440 6         30 $self->whine( $start_line, "Unknown E content in E<$content>" );
1441 6         15 $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         698 $replacer = Pod::Escapes::e2char($content);
1448 278         4655 DEBUG > 1 and print STDERR " Replacing E<$content> with $replacer\n";
1449             }
1450              
1451 284         1437 splice(@$treelet, $i, 1, $replacer); # no need to back up $i, tho
1452             }
1453             }
1454              
1455 1090         2102 return;
1456             }
1457              
1458              
1459             # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1460              
1461             sub _treat_Ss {
1462 1090     1090   2116 my($self,$treelet) = @_;
1463              
1464 1090 100       3136 _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 1090         1787 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   2515 my($treelet, $in_s) = @_;
1477              
1478 1682         2475 my $is_s = ('S' eq $treelet->[0]);
1479 1682   100     5486 $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         2996 for(my $i = 2; $i < @$treelet; ++$i) {
1483 3966 100       5609 if(ref $treelet->[$i]) {
1484 1176 100       2084 if( _change_S_to_nbsp( $treelet->[$i], $in_s ) ) {
1485 12         17 my $to_pull_up = $treelet->[$i];
1486 12         22 splice @$to_pull_up,0,2; # ...leaving just its content
1487 12         29 splice @$treelet, $i, 1, @$to_pull_up; # Pull up content
1488 12         30 $i += @$to_pull_up - 1; # Make $i skip the pulled-up stuff
1489             }
1490             } else {
1491 2790 100       5881 $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         3930 return $is_s;
1504             }
1505              
1506             #-----------------------------------------------------------------------------
1507              
1508             sub _accessorize { # A simple-minded method-maker
1509 70     70   853 no strict 'refs';
  70         145  
  70         8289  
1510 107     107   369 foreach my $attrname (@_) {
1511 2636 100       5918 next if $attrname =~ m/::/; # a hack
1512 2529         10729 *{caller() . '::' . $attrname} = sub {
1513 70     70   595 use strict;
  70         155  
  70         57756  
1514 8402 50 66 8402   38000 $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 8402 100       28947 : ($_[0]->{$attrname} = $_[1]);
1520 2529         7695 };
1521             }
1522             # Ya know, they say accessories make the ensemble!
1523 107         306 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   4648637 my $class = shift(@_);
1554              
1555 525 100 100     4173 my $mutor = shift(@_) if @_ and ref($_[0] || '') eq 'CODE';
      66        
1556              
1557 525         847 DEBUG and print STDERR "\n\n", '#' x 76,
1558             "\nAbout to parse source: {{\n$_[0]\n}}\n\n";
1559              
1560              
1561 525 100 66     3082 my $parser = ref $class && $class->isa(__PACKAGE__) ? $class : $class->new;
1562 525         1670 $parser->hide_line_numbers(1);
1563              
1564 525         969 my $out = '';
1565 525         1954 $parser->output_string( \$out );
1566 525         803 DEBUG and print STDERR " _out to ", \$out, "\n";
1567              
1568 525 100       1698 $mutor->($parser) if $mutor;
1569              
1570 525         2139 $parser->parse_string_document( $_[0] );
1571             # use Data::Dumper; print STDERR Dumper($parser), "\n";
1572 525         10189 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   803304 my $class = shift(@_);
1582              
1583 56 50       206 Carp::croak "But $class->_duo is useful only in list context!"
1584             unless wantarray;
1585              
1586 56 100 100     410 my $mutor = shift(@_) if @_ and ref($_[0] || '') eq 'CODE';
      66        
1587              
1588 56 50       183 Carp::croak "But $class->_duo takes two parameters, not: @_"
1589             unless @_ == 2;
1590              
1591 56         96 my(@out);
1592              
1593 56         135 while( @_ ) {
1594 112         698 my $parser = $class->new;
1595              
1596 112         236 push @out, '';
1597 112         368 $parser->output_string( \( $out[-1] ) );
1598              
1599 112         225 DEBUG and print STDERR " _duo out to ", $parser->output_string(),
1600             " = $parser->{'output_string'}\n";
1601              
1602 112         372 $parser->hide_line_numbers(1);
1603 112 100       369 $mutor->($parser) if $mutor;
1604 112         385 $parser->parse_string_document( shift( @_ ) );
1605             # use Data::Dumper; print STDERR Dumper($parser), "\n";
1606             }
1607              
1608 56         507 return @out;
1609             }
1610              
1611              
1612              
1613             #-----------------------------------------------------------------------------
1614             1;
1615             __END__