File Coverage

blib/lib/Pod/Simple.pm
Criterion Covered Total %
statement 521 626 83.2
branch 206 292 70.5
condition 168 268 62.6
subroutine 54 67 80.6
pod 30 30 100.0
total 979 1283 76.3


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