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             package Pod::Simple;
2 68     68   431136 use strict;
  68         155  
  68         1977  
3 68     68   326 use warnings;
  68         124  
  68         2984  
4 68     68   381 use Carp ();
  68         146  
  68         3316  
5 68 50   68   1905 BEGIN { *DEBUG = sub () {0} unless defined &DEBUG }
6 68     68   35394 use integer;
  68         941  
  68         337  
7 68     68   35084 use Pod::Escapes 1.04 ();
  68         232362  
  68         2411  
8 68     68   29032 use Pod::Simple::LinkSection ();
  68         246  
  68         1793  
9 68     68   458 use Pod::Simple::BlackBox ();
  68         142  
  68         1221  
10 68     68   28605 use Pod::Simple::TiedOutFH;
  68         160  
  68         20363  
11             #use utf8;
12              
13             our @ISA = ('Pod::Simple::BlackBox');
14             our $VERSION = '3.45';
15              
16             our @Known_formatting_codes = qw(I B C L E F S 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 68 50   68   367 if(defined &ASCII) { }
27 68         203 elsif(chr(65) eq 'A') { *ASCII = sub () {1} }
28             else { *ASCII = sub () {''} }
29              
30 68 50       465 unless(defined &MANY_LINES) { *MANY_LINES = sub () {20} }
  68         280  
31 68         110 DEBUG > 4 and print STDERR "MANY_LINES is ", MANY_LINES(), "\n";
32 68 50       475 unless(MANY_LINES() >= 1) {
33 0         0 die "MANY_LINES is too small (", MANY_LINES(), ")!\nAborting";
34             }
35 68 50       318 if(defined &UNICODE) { }
    50          
36 68         28401 elsif($] >= 5.008) { *UNICODE = sub() {1} }
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             if ($] ge 5.007_003) { # On sufficiently modern Perls we can handle any
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 117 return shift->{'errors_seen'} || 0;
129             }
130              
131             sub errata_seen {
132 8   50 8 1 809 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 105 my $this = shift;
142 19 50       65 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 68     68   339 *pretty = \&Pod::Simple::BlackBox::pretty;
168 68         706 *stringify_lol = \&Pod::Simple::BlackBox::stringify_lol;
169 68         519765 *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 879     879 1 10142 my $this = shift;
196 879 100       3345 return $this->{'output_string'} unless @_; # GET.
197              
198 869 50 33     3443 my $x = (defined($_[0]) and ref($_[0])) ? $_[0] : \( $_[0] );
199 869 100       1946 $$x = '' unless defined $$x;
200 869         1118 DEBUG > 4 and print STDERR "# Output string set to $x ($$x)\n";
201 869         3120 $this->{'output_fh'} = Pod::Simple::TiedOutFH->handle_on($_[0]);
202             return
203 869         2408 $this->{'output_string'} = $_[0];
204             #${ ${ $this->{'output_fh'} } };
205             }
206              
207 10     10 1 36 sub abandon_output_string { $_[0]->abandon_output_fh; delete $_[0]{'output_string'} }
  10         30  
208 10     10 1 53 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 909   33 909 1 8873 my $class = ref($_[0]) || $_[0];
218             #Carp::croak(__PACKAGE__ . " is a virtual base class -- see perldoc "
219             # . __PACKAGE__ );
220 909         14500 my $obj = bless {
221             'accept_codes' => { map( ($_=>$_), @Known_formatting_codes ) },
222             'accept_directives' => { %Known_directives },
223             'accept_targets' => {},
224             }, $class;
225              
226 909         4223 $obj->expand_verbatim_tabs(8);
227 909         2272 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 26 sub accept_directive_as_verbatim { shift->_accept_directives('Verbatim', @_) }
256 3     3 1 22 sub accept_directive_as_data { shift->_accept_directives('Data', @_) }
257 3     3 1 24 sub accept_directive_as_processed { shift->_accept_directives('Plain', @_) }
258              
259             sub _accept_directives {
260 9     9   27 my($this, $type) = splice @_,0,2;
261 9         17 foreach my $d (@_) {
262 9 50 33     33 next unless defined $d and length $d;
263 9 50       56 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       25 if exists $Known_directives{$d};
267 9         20 $this->{'accept_directives'}{$d} = $type;
268 9         17 DEBUG > 2 and print STDERR "Learning to accept \"=$d\" as directive of type $type\n";
269             }
270             DEBUG > 6 and print STDERR "$this\'s accept_directives : ",
271 9         11 pretty($this->{'accept_directives'}), "\n";
272              
273 9 50       19 return sort keys %{ $this->{'accept_directives'} } if wantarray;
  0         0  
274 9         15 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 184 sub accept_target { shift->accept_targets(@_) } # alias
302 49     49 1 205 sub accept_target_as_text { shift->accept_targets_as_text(@_) } # alias
303              
304              
305 259     259 1 792 sub accept_targets { shift->_accept_targets('1', @_) }
306              
307 53     53 1 174 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 312     312   775 my($this, $type) = splice @_,0,2;
312 312         604 foreach my $t (@_) {
313 572 50 33     1793 next unless defined $t and length $t;
314             # TODO: enforce some limitations on what a target name can be?
315 572         1226 $this->{'accept_targets'}{$t} = $type;
316 572         864 DEBUG > 2 and print STDERR "Learning to accept \"$t\" as target of type $type\n";
317             }
318 312 50       633 return sort keys %{ $this->{'accept_targets'} } if wantarray;
  0         0  
319 312         656 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 338     338 1 748 my $this = shift;
351              
352 338         621 foreach my $new_code (@_) {
353 1212 50 33     3321 next unless defined $new_code and length $new_code;
354             # A good-enough check that it's good as an XML Name symbol:
355 1212 50 33     7120 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 1212         2789 $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 338         655 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 113 my $this = shift;
383              
384 29         53 foreach my $new_code (@_) {
385 29 50 33     96 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     275 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       114 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         55 delete $this->{'accept_codes'}{$new_code};
399              
400 29         45 DEBUG > 2 and print STDERR "OK, won't accept the code $new_code<...>.\n";
401             }
402              
403 29         47 return;
404             }
405              
406              
407             #@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
408             #@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
409              
410             sub parse_string_document {
411 762     762 1 14565 my $self = shift;
412 762         1100 my @lines;
413 762         1439 foreach my $line_group (@_) {
414 762 100 66     2812 next unless defined $line_group and length $line_group;
415 744         2093 pos($line_group) = 0;
416 744         4603 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 8513 100 100     40664 $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 762         2426 $self->parse_lines(undef); # to signal EOF
429 762         2497 return $self;
430             }
431              
432             sub _init_fh_source {
433 51     51   162 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         109 return;
440             }
441              
442             #:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.
443             #
444              
445             sub parse_file {
446 51     51 1 289 my($self, $source) = (@_);
447              
448 51 50       281 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         77 local *PODSOURCE;
  51         121  
459 51 50       2412 open(PODSOURCE, "<$source") || Carp::croak("Can't open $source: $!");
460 51         305 $self->{'source_filename'} = $source;
461 51         227 $source = *PODSOURCE{IO};
462             }
463 51         226 $self->_init_fh_source($source);
464             }
465             # By here, $source is a FH.
466              
467 51         114 $self->{'source_fh'} = $source;
468              
469 51         82 my($i, @lines);
470 51         117 until( $self->{'source_dead'} ) {
471 490         1574 splice @lines;
472              
473 490         1611 for($i = MANY_LINES; $i--;) { # read those many lines at a time
474 9326         20391 local $/ = $NL;
475 9326         24254 push @lines, scalar(<$source>); # readline
476 9326 100       28103 last unless defined $lines[-1];
477             # but pass thru the undef, which will set source_dead to true
478             }
479              
480 490         884 my $at_eof = ! $lines[-1]; # keep track of the undef
481 490 100       915 pop @lines if $at_eof; # silence warnings
482              
483             # be eol agnostic
484 490         3239 s/\r\n?/\n/g for @lines;
485              
486             # make sure there are only one line elements for parse_lines
487 490         27706 @lines = split(/(?<=\n)/, join('', @lines));
488              
489             # push the undef back after popping it to set source_dead to true
490 490 100       1150 push @lines, undef if $at_eof;
491              
492 490         1583 $self->parse_lines(@lines);
493             }
494 51         136 delete($self->{'source_fh'}); # so it can be GC'd
495 51         978 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 21 my($self, $source, $to) = @_;
505 10 50       28 $self = $self->new unless ref($self); # so we tolerate being a class method
506              
507 10 50 33     94 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     102 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         66 require Symbol;
527 10         31 my $out_fh = Symbol::gensym();
528 10         130 DEBUG and print STDERR "Write-opening to $to\n";
529 10 50       806 open($out_fh, ">$to") or Carp::croak "Can't write-open $to: $!";
530 10 50 33     93 binmode($out_fh)
531             if $self->can('write_with_binmode') and $self->write_with_binmode;
532 10         26 $self->output_fh($out_fh);
533             }
534              
535 10         56 return $self->parse_file($source);
536             }
537              
538             #-----------------------------------------------------------------------------
539              
540             sub whine {
541             #my($self,$line,$complaint) = @_;
542 79     79 1 180 my $self = shift(@_);
543 79         197 ++$self->{'errors_seen'};
544 79 100       251 if($self->{'no_whining'}) {
545 9         39 DEBUG > 9 and print STDERR "Discarding complaint (at line $_[0]) $_[1]\n because no_whining is on.\n";
546 9         32 return;
547             }
548 70         126 push @{$self->{'all_errata'}{$_[0]}}, $_[1];
  70         310  
549 70 50       253 return $self->_complain_warn(@_) if $self->{'complain_stderr'};
550 70         277 return $self->_complain_errata(@_);
551             }
552              
553             sub scream { # like whine, but not suppressible
554             #my($self,$line,$complaint) = @_;
555 8     8 1 34 my $self = shift(@_);
556 8         25 ++$self->{'errors_seen'};
557 8         20 push @{$self->{'all_errata'}{$_[0]}}, $_[1];
  8         41  
558 8 50       33 return $self->_complain_warn(@_) if $self->{'complain_stderr'};
559 8         48 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   221 my($self,$line,$complaint) = @_;
570 78 100       189 if( $self->{'no_errata_section'} ) {
571 10         13 DEBUG > 9 and print STDERR "Discarding erratum (at line $line) $complaint\n because no_errata_section is on.\n";
572             } else {
573 68         107 DEBUG > 9 and print STDERR "Queuing erratum (at line $line) $complaint\n";
574 68         102 push @{$self->{'errata'}{$line}}, $complaint
  68         342  
575             # for a report to be generated later!
576             }
577 78         209 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 185     185   392 my($self, $para) = @_;
585 185 50       484 return $para->[1]{'~type'} if $para->[1]{'~type'};
586              
587             return $para->[1]{'~type'} = 'text'
588 185 100 100     470 if join("\n", @{$para}[2 .. $#$para]) =~ m/^\s*(\d+)\.?\s*$/s and $1 ne '1';
  185         1251  
589             # Else fall thru to the general case:
590 183         665 return $self->_get_item_type($para);
591             }
592              
593              
594              
595             sub _get_item_type { # mutates the item!!
596 1205     1205   2377 my($self, $para) = @_;
597 1205 100       2907 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 1020         1976 my $content = join "\n", @{$para}[2 .. $#$para];
  1020         2337  
603              
604 1020 100 100     6944 if($content =~ m/^\s*\*\s*$/s or $content =~ m/^\s*$/s) {
    100          
    100          
605             # Like: "=item *", "=item * ", "=item"
606 59         152 splice @$para, 2; # so it ends up just being ['=item', { attrhash } ]
607 59         171 $para->[1]{'~orig_content'} = $content;
608 59         242 return $para->[1]{'~type'} = 'bullet';
609              
610             } elsif($content =~ m/^\s*\*\s+(.+)/s) { # tolerance
611              
612             # Like: "=item * Foo bar baz";
613 101         260 $para->[1]{'~orig_content'} = $content;
614 101         275 $para->[1]{'~_freaky_para_hack'} = $1;
615 101         120 DEBUG > 2 and print STDERR " Tolerating $$para[2] as =item *\\n\\n$1\n";
616 101         188 splice @$para, 2; # so it ends up just being ['=item', { attrhash } ]
617 101         341 return $para->[1]{'~type'} = 'bullet';
618              
619             } elsif($content =~ m/^\s*(\d+)\.?\s*$/s) {
620             # Like: "=item 1.", "=item 123412"
621              
622 31         110 $para->[1]{'~orig_content'} = $content;
623 31         117 $para->[1]{'number'} = $1; # Yes, stores the number there!
624              
625 31         69 splice @$para, 2; # so it ends up just being ['=item', { attrhash } ]
626 31         131 return $para->[1]{'~type'} = 'number';
627              
628             } else {
629             # It's anything else.
630 829         2963 return $para->[1]{'~type'} = 'text';
631              
632             }
633             }
634              
635             #-----------------------------------------------------------------------------
636              
637             sub _make_treelet {
638 4444     4444   7429 my $self = shift; # and ($para, $start_line)
639 4444         6218 my $treelet;
640 4444 50       9000 if(!@_) {
641 0         0 return [''];
642 4444 50 33     11761 } 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 4444         11105 $treelet = $self->_treelet_from_formatting_codes(@_);
653             }
654              
655 4444 100 100     15034 if( ! $self->{'_output_is_for_JustPod'} # Retain these as-is for pod output
656             && $self->_remap_sequences($treelet) )
657             {
658 1080         3031 $self->_treat_Zs($treelet); # Might as well nix these first
659 1080         2844 $self->_treat_Ls($treelet); # L has to precede E and S
660 1080         2801 $self->_treat_Es($treelet);
661 1080         2827 $self->_treat_Ss($treelet); # S has to come after E
662 1080         2337 $self->_wrap_up($treelet); # Nix X's and merge texties
663              
664             } else {
665 3364         4364 DEBUG and print STDERR "Formatless treelet gets fast-tracked.\n";
666             # Very common case!
667             }
668              
669 4444         8050 splice @$treelet, 0, 2; # lop the top off
670              
671 4444         15992 return $treelet;
672             }
673              
674             #:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.
675              
676             sub _wrap_up {
677 1080     1080   1902 my($self, @stack) = @_;
678 1080         1751 my $nixx = $self->{'nix_X_codes'};
679 1080         1646 my $merge = $self->{'merge_text' };
680 1080 100 100     2835 return unless $nixx or $merge;
681              
682 739         978 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 739         1074 my($i, $treelet);
689 739         1379 while($treelet = shift @stack) {
690 2717         3373 DEBUG > 3 and print STDERR " Considering children of this $treelet->[0] node...\n";
691 2717         4620 for($i = 2; $i < @$treelet; ++$i) { # iterate over children
692 6192         6821 DEBUG > 3 and print STDERR " Considering child at $i ", pretty($treelet->[$i]), "\n";
693 6192 100 100     29813 if($nixx and ref $treelet->[$i] and $treelet->[$i][0] eq 'X') {
    100 100        
    100 100        
      100        
      100        
694 6         10 DEBUG > 3 and print STDERR " Nixing X node at $i\n";
695 6         14 splice(@$treelet, $i, 1); # just nix this node (and its descendants)
696             # no need to back-update the counter just yet
697 6         13 redo;
698              
699             } elsif($merge and $i != 2 and # non-initial
700             !ref $treelet->[$i] and !ref $treelet->[$i - 1]
701             ) {
702 25         31 DEBUG > 3 and print STDERR " Merging ", $i-1,
703             ":[$treelet->[$i-1]] and $i\:[$treelet->[$i]]\n";
704 25         48 $treelet->[$i-1] .= ( splice(@$treelet, $i, 1) )[0];
705 25         47 DEBUG > 4 and print STDERR " Now: ", $i-1, ":[$treelet->[$i-1]]\n";
706 25         30 --$i;
707 25         52 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 1742         2043 DEBUG > 4 and print STDERR " Enqueuing ", pretty($treelet->[$i]), " for traversal.\n";
713 1742         2449 push @stack, $treelet->[$i];
714              
715 1742 100       3938 if($treelet->[$i][0] eq 'L') {
716 206         649 my $thing;
717 206         326 foreach my $attrname ('section', 'to') {
718 412 100 66     1294 if(defined($thing = $treelet->[$i][1]{$attrname}) and ref $thing) {
719 236         412 unshift @stack, $thing;
720             DEBUG > 4 and print STDERR " +Enqueuing ",
721 236         577 pretty( $treelet->[$i][1]{$attrname} ),
722             " as an attribute value to tweak.\n";
723             }
724             }
725             }
726             }
727             }
728             }
729 739         885 DEBUG > 2 and print STDERR "End of _wrap_up traversal.\n\n";
730              
731 739         1191 return;
732             }
733              
734             #:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.
735              
736             sub _remap_sequences {
737 3582     3582   7071 my($self,@stack) = @_;
738              
739 3582 100 66     7921 if(@stack == 1 and @{ $stack[0] } == 3 and !ref $stack[0][2]) {
  3582   100     14112  
740             # VERY common case: abort it.
741 2502         3227 DEBUG and print STDERR "Skipping _remap_sequences: formatless treelet.\n";
742 2502         7749 return 0;
743             }
744              
745 1080   50     2819 my $map = ($self->{'accept_codes'} || die "NO accept_codes in $self?!?");
746              
747 1080         1817 my $start_line = $stack[0][1]{'start_line'};
748 1080         1348 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 1080         1291 ref($map->{$_}) ? join(",", @{$map->{$_}}) : $map->{$_}
755             ),
756             sort keys %$map ),
757             ("B~C~E~F~I~L~S~X~Z" eq join '~', sort keys %$map)
758             ? " (all normal)\n" : "\n"
759             ;
760              
761             # A recursive algorithm implemented iteratively! Whee!
762              
763 1080         1889 my($is, $was, $i, $treelet); # scratch
764 1080         2259 while($treelet = shift @stack) {
765 3478         4301 DEBUG > 3 and print STDERR " Considering children of this $treelet->[0] node...\n";
766 3478         6280 for($i = 2; $i < @$treelet; ++$i) { # iterate over children
767 7551 100       17626 next unless ref $treelet->[$i]; # text nodes are uninteresting
768              
769 2404         2701 DEBUG > 4 and print STDERR " Noting child $i : $treelet->[$i][0]<...>\n";
770              
771 2404         5158 $is = $treelet->[$i][0] = $map->{ $was = $treelet->[$i][0] };
772 2404         2777 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 2404 100       4042 if(!defined $is) {
786 4         34 $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 2404 100       5504 if(ref $is) {
    50          
    100          
792 2         9 my @dynasty = @$is;
793 2         3 DEBUG > 4 and print STDERR " Renaming $was node to $dynasty[-1]\n";
794 2         5 $treelet->[$i][0] = pop @dynasty;
795 2         3 my $nugget;
796 2         6 while(@dynasty) {
797 3         4 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         16 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         10 => splice @{ $treelet->[$i] },2
  4         24  
812             # (not catching its first two (non-child) items)
813             );
814 4         16 --$i; # back up for new stuff
815             } else {
816             # otherwise it's unremarkable
817 2398         5301 unshift @stack, $treelet->[$i]; # just recurse
818             }
819             }
820             }
821              
822 1080         1379 DEBUG > 2 and print STDERR "End of _remap_sequences traversal.\n\n";
823              
824 1080 50 66     2203 if(@_ == 2 and @{ $_[1] } == 3 and !ref $_[1][2]) {
  1080   66     3546  
825 0         0 DEBUG and print STDERR "Noting that the treelet is now formatless.\n";
826 0         0 return 0;
827             }
828 1080         3127 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   44 my($self, $para) = @_;
839 21         65 my $content = join ' ', splice @$para, 2;
840 21         52 $content =~ s/^\s+//s;
841 21         62 $content =~ s/\s+$//s;
842              
843 21         27 DEBUG > 2 and print STDERR "Ogling extensor: =extend $content\n";
844              
845 21 50       110 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         50 my $new_letter = $1;
856 21         33 my $fallbacks_one = $2;
857 21         27 my $elements_one;
858 21 50       61 $elements_one = defined($3) ? $3 : $1;
859              
860 21         26 DEBUG > 2 and print STDERR "Extensor has good syntax.\n";
861              
862 21 50 33     66 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       80 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     90 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       85 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         63 my @fallbacks = split ',', $fallbacks_one, -1;
905 21         45 my @elements = split ',', $elements_one, -1;
906              
907 21         43 foreach my $f (@fallbacks) {
908 42 0 33     104 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         28 DEBUG > 3 and printf STDERR "Extensor: Fallbacks <%s> Elements <%s>.\n",
918             @fallbacks, @elements;
919              
920 21         28 my $canonical_form;
921 21         27 foreach my $e (@elements) {
922 42 100       76 if(exists $self->{'accept_codes'}{$e}) {
923 15         18 DEBUG > 1 and print STDERR " Mapping '$new_letter' to known extension '$e'\n";
924 15         27 $canonical_form = $e;
925 15         19 last; # first acceptable elementname wins!
926             } else {
927 27         38 DEBUG > 1 and print STDERR " Can't map '$new_letter' to unknown extension '$e'\n";
928             }
929             }
930              
931              
932 21 100       41 if( defined $canonical_form ) {
933             # We found a good N => elementname mapping
934 15         30 $self->{'accept_codes'}{$new_letter} = $canonical_form;
935 15         33 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       22 $self->{'accept_codes'}{$new_letter}
940             = (@fallbacks == 1) ? $fallbacks[0] : \@fallbacks;
941 6         13 DEBUG > 2 and print
942             "Extensor maps $new_letter => fallbacks @fallbacks.\n";
943             }
944              
945             } else {
946 0         0 DEBUG > 2 and print STDERR "Extensor has bad syntax.\n";
947             $self->whine(
948 0         0 $para->[1]{'start_line'},
949             "Unknown =extend syntax: $content"
950             )
951             }
952 21         42 return;
953             }
954              
955              
956             #:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.
957              
958             sub _treat_Zs { # Nix Z<...>'s
959 1080     1080   1958 my($self,@stack) = @_;
960              
961 1080         1605 my($i, $treelet);
962 1080         1810 my $start_line = $stack[0][1]{'start_line'};
963              
964             # A recursive algorithm implemented iteratively! Whee!
965              
966 1080         2277 while($treelet = shift @stack) {
967 3446         6252 for($i = 2; $i < @$treelet; ++$i) { # iterate over children
968 7515 100       16356 next unless ref $treelet->[$i]; # text nodes are uninteresting
969 2403 100       4457 unless($treelet->[$i][0] eq 'Z') {
970 2366         3482 unshift @stack, $treelet->[$i]; # recurse
971 2366         4279 next;
972             }
973              
974 37         45 DEBUG > 1 and print STDERR "Nixing Z node @{$treelet->[$i]}\n";
975              
976             # bitch UNLESS it's empty
977 37 50 33     53 unless( @{$treelet->[$i]} == 2
  37   33     94  
978 37         135 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         62 splice(@$treelet, $i, 1); # thereby just nix this node.
984 37         101 --$i;
985              
986             }
987             }
988              
989 1080         1738 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 1080     1080   1900 my($self,@stack) = @_;
1066              
1067 1080         1530 my($i, $treelet);
1068 1080         1853 my $start_line = $stack[0][1]{'start_line'};
1069              
1070             # A recursive algorithm implemented iteratively! Whee!
1071              
1072 1080         2086 while($treelet = shift @stack) {
1073 3236         6000 for(my $i = 2; $i < @$treelet; ++$i) {
1074             # iterate over children of current tree node
1075 7434 100       16535 next unless ref $treelet->[$i]; # text nodes are uninteresting
1076 2334 100       4286 unless($treelet->[$i][0] eq 'L') {
1077 1991         2857 unshift @stack, $treelet->[$i]; # recurse
1078 1991         3587 next;
1079             }
1080              
1081              
1082             # By here, $treelet->[$i] is definitely an L node
1083 343         542 my $ell = $treelet->[$i];
1084 343         455 DEBUG > 1 and print STDERR "Ogling L node " . pretty($ell) . "\n";
1085              
1086             # bitch if it's empty or is just '/'
1087 343 100 100     440 if (@{$ell} == 3 and $ell->[2] =~ m!\A\s*/\s*\z!) {
  343         1517  
1088 1         4 $self->whine( $start_line, "L<> contains only '/'" );
1089 1         3 $treelet->[$i] = 'L'; # just make it a text node
1090 1         4 next; # and move on
1091             }
1092 342 50 66     490 if( @{$ell} == 2
  342   33     768  
1093 342         1075 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 342 100 100     2434 if( (! ref $ell->[2] && $ell->[2] =~ /\A\s/)
      66        
      66        
1101             ||(! ref $ell->[-1] && $ell->[-1] =~ /\s\z/)
1102             ) {
1103 2         7 $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 342 100       1879 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 342     342   991 for (2..$#$ell) {
1130 584 100       1195 next if ref $ell->[$_];
1131 448 100       1427 next unless $ell->[$_] =~ m/^(?:([^|]*)\|)?(\w+:[^:\s]\S*)$/s;
1132 44         239 return ($_, $1, $2);
1133             }
1134 298         872 return;
1135             }->()
1136             ) {
1137 44         107 $ell->[1]{'type'} = 'url';
1138              
1139 44         117 my @text = @{$ell}[2..$url_index-1];
  44         99  
1140 44 100       111 push @text, $text_part if defined $text_part;
1141              
1142 44         105 my @url = @{$ell}[$url_index+1..$#$ell];
  44         72  
1143 44         138 unshift @url, $url_part;
1144              
1145 44 100       108 unless (@text) {
1146 30         59 $ell->[1]{'content-implicit'} = 'yes';
1147 30         67 @text = @url;
1148             }
1149              
1150 44 100       329 $ell->[1]{to} = Pod::Simple::LinkSection->new(
1151             @url == 1
1152             ? $url[0]
1153             : [ '', {}, @url ],
1154             );
1155              
1156 44         147 splice @$ell, 2, $#$ell, @text;
1157              
1158 44         341 next;
1159             }
1160              
1161             # Catch some very simple and/or common cases
1162 298 100 66     1173 if(@{$ell} == 3 and ! ref $ell->[2]) {
  298         980  
1163 223         371 my $it = $ell->[2];
1164 223 100       564 if($it =~ m{^[^/|]+[(][-a-zA-Z0-9]+[)]$}s) { # man sections
1165             # Hopefully neither too broad nor too restrictive a RE
1166 6         10 DEBUG > 1 and print STDERR "Catching \"$it\" as manpage link.\n";
1167 6         17 $ell->[1]{'type'} = 'man';
1168             # This's the only place where man links can get made.
1169 6         16 $ell->[1]{'content-implicit'} = 'yes';
1170 6         36 $ell->[1]{'to' } =
1171             Pod::Simple::LinkSection->new( $it ); # treelet!
1172              
1173 6         24 next;
1174             }
1175 217 100       974 if($it =~ m/^[^\/\|,\$\%\@\ \"\<\>\:\#\&\*\{\}\[\]\(\)]+(\:\:[^\/\|,\$\%\@\ \"\<\>\:\#\&\*\{\}\[\]\(\)]+)*$/s) {
1176             # Extremely forgiving idea of what constitutes a bare
1177             # modulename link like L or even L
1178 127         187 DEBUG > 1 and print STDERR "Catching \"$it\" as ho-hum L link.\n";
1179 127         277 $ell->[1]{'type'} = 'pod';
1180 127         248 $ell->[1]{'content-implicit'} = 'yes';
1181 127         512 $ell->[1]{'to' } =
1182             Pod::Simple::LinkSection->new( $it ); # treelet!
1183 127         376 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 165         230 DEBUG > 1 and print STDERR "Running a real parse on this non-trivial L\n";
1194              
1195              
1196 165         231 my $link_text; # set to an arrayref if found
1197 165         462 my @ell_content = @$ell;
1198 165         351 splice @ell_content,0,2; # Knock off the 'L' and {} bits
1199              
1200 165         218 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 165         205 DEBUG > 3 and
1207             print STDERR " Peering at L content for a '|' ...\n";
1208 165         440 for(my $j = 0; $j < @ell_content; ++$j) {
1209 379 100       786 next if ref $ell_content[$j];
1210 260         305 DEBUG > 3 and
1211             print STDERR " Peering at L-content text bit \"$ell_content[$j]\" for a '|'.\n";
1212              
1213 260 100       864 if($ell_content[$j] =~ m/^([^\|]*)\|(.*)$/s) {
1214 61         184 my @link_text = ($1); # might be 0-length
1215 61         137 $ell_content[$j] = $2; # might be 0-length
1216              
1217 61         81 DEBUG > 3 and
1218             print STDERR " FOUND a '|' in it. Splitting into [$1] + [$2]\n";
1219              
1220 61 100       156 if ($link_text[0] =~ m{[|/]}) {
1221 1         33 $self->whine(
1222             $start_line,
1223             "alternative text '$link_text[0]' contains non-escaped | or /"
1224             );
1225             }
1226              
1227 61         139 unshift @link_text, splice @ell_content, 0, $j;
1228             # leaving only things at J and after
1229 61   66     332 @ell_content = grep ref($_)||length($_), @ell_content ;
1230 61   100     303 $link_text = [grep ref($_)||length($_), @link_text ];
1231 61         140 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         111 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 165         241 my $section_name; # set to arrayref if found
1243 165         214 DEBUG > 3 and print STDERR " Peering at L-content for a '/' ...\n";
1244 165         365 for(my $j = 0; $j < @ell_content; ++$j) {
1245 218 100       433 next if ref $ell_content[$j];
1246 183         221 DEBUG > 3 and
1247             print STDERR " Peering at L-content text bit \"$ell_content[$j]\" for a '/'.\n";
1248              
1249 183 100       623 if($ell_content[$j] =~ m/^([^\/]*)\/(.*)$/s) {
1250 100         308 my @section_name = ($2); # might be 0-length
1251 100         210 $ell_content[$j] = $1; # might be 0-length
1252              
1253 100         137 DEBUG > 3 and
1254             print STDERR " FOUND a '/' in it.",
1255             " Splitting to page [...$1] + section [$2...]\n";
1256              
1257 100         264 push @section_name, splice @ell_content, 1+$j;
1258             # leaving only things before and including J
1259              
1260 100   100     496 @ell_content = grep ref($_)||length($_), @ell_content ;
1261 100   100     512 @section_name = grep ref($_)||length($_), @section_name ;
1262              
1263             # Turn L<.../"foo"> into L<.../foo>
1264 100 100 66     1049 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         165 $section_name[ 0] =~ s/^\"//s;
1273 40         144 $section_name[-1] =~ s/\"$//s;
1274 40         65 DEBUG > 3 and
1275             print STDERR " Quotes removed: ", pretty(@section_name), "\n";
1276             } else {
1277 60         96 DEBUG > 3 and
1278             print STDERR " No need to remove quotes in ", pretty(@section_name), "\n";
1279             }
1280              
1281 100         196 $section_name = \@section_name;
1282 100         211 last;
1283             }
1284             }
1285              
1286             # Turn L<"Foo Bar"> into L
1287 165 50 66     1022 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         58 $section_name = [splice @ell_content];
1296 19         71 $section_name->[ 0] =~ s/^\"//s;
1297 19         67 $section_name->[-1] =~ s/\"$//s;
1298 19         43 $ell->[1]{'~tolerated'} = 1;
1299             }
1300              
1301             # Turn L into L.
1302 165 100 100     745 if(!$section_name and !$link_text and @ell_content
      66        
      100        
      100        
1303             and grep !ref($_) && m/ /s, @ell_content
1304             ) {
1305 14         40 $section_name = [splice @ell_content];
1306 14         36 $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 165 100       334 unless($link_text) {
1317 104         252 $ell->[1]{'content-implicit'} = 'yes';
1318 104         184 $link_text = [];
1319 104 100       357 push @$link_text, '"', @$section_name, '"' if $section_name;
1320              
1321 104 100       223 if(@ell_content) {
1322 51 100       135 $link_text->[-1] .= ' in ' if $section_name;
1323 51         110 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 165 100 66     653 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         16 DEBUG > 3 and print STDERR "Considering this ($ell_content[0]) a man link.\n";
1335             } else {
1336 156         318 $ell->[1]{'type'} = 'pod';
1337 156         203 DEBUG > 3 and print STDERR "Considering this a pod link (not man or url).\n";
1338             }
1339              
1340 165 100       357 if( defined $section_name ) {
1341 133         958 $ell->[1]{'section'} = Pod::Simple::LinkSection->new(
1342             ['', {}, @$section_name]
1343             );
1344 133         371 DEBUG > 3 and print STDERR "L-section content: ", pretty($ell->[1]{'section'}), "\n";
1345             }
1346              
1347 165 100       343 if( @ell_content ) {
1348 93         434 $ell->[1]{'to'} = Pod::Simple::LinkSection->new(
1349             ['', {}, @ell_content]
1350             );
1351 93         248 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 165 50       739 @$ell = (@$ell[0,1], defined($link_text) ? splice(@$link_text) : '');
1356              
1357 165         262 DEBUG > 2 and print STDERR "End of L-parsing for this node " . pretty($treelet->[$i]) . "\n";
1358              
1359 165         755 unshift @stack, $treelet->[$i]; # might as well recurse
1360             }
1361             }
1362              
1363 1080         1679 return;
1364             }
1365              
1366             # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1367              
1368             sub _treat_Es {
1369 1080     1080   1933 my($self,@stack) = @_;
1370              
1371 1080         1669 my($i, $treelet, $content, $replacer, $charnum);
1372 1080         1833 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 1080         2074 while($treelet = shift @stack) {
1382 3676         6928 for(my $i = 2; $i < @$treelet; ++$i) { # iterate over children
1383 8105 100       19738 next unless ref $treelet->[$i]; # text nodes are uninteresting
1384 2477 100       5806 if($treelet->[$i][0] eq 'L') {
    100          
1385             # SPECIAL STUFF for semi-processed L<>'s
1386              
1387 342         474 my $thing;
1388 342         584 foreach my $attrname ('section', 'to') {
1389 684 100 66     2500 if(defined($thing = $treelet->[$i][1]{$attrname}) and ref $thing) {
1390 403         622 unshift @stack, $thing;
1391             DEBUG > 2 and print STDERR " Enqueuing ",
1392 403         583 pretty( $treelet->[$i][1]{$attrname} ),
1393             " as an attribute value to tweak.\n";
1394             }
1395             }
1396              
1397 342         552 unshift @stack, $treelet->[$i]; # recurse
1398 342         834 next;
1399             } elsif($treelet->[$i][0] ne 'E') {
1400 1851         2655 unshift @stack, $treelet->[$i]; # recurse
1401 1851         3365 next;
1402             }
1403              
1404 284         350 DEBUG > 1 and print STDERR "Ogling E node ", pretty($treelet->[$i]), "\n";
1405              
1406             # bitch if it's empty
1407 284 50 33     382 if( @{$treelet->[$i]} == 2
  284   33     735  
1408 284         1041 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     393 unless(@{$treelet->[$i]} == 3 and !ref($content = $treelet->[$i][2])) {
  284         1009  
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         398 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         743 $charnum = Pod::Escapes::e2charnum($content);
1435 284         3532 DEBUG > 1 and print STDERR " Considering E<$content> with char ",
1436             defined($charnum) ? $charnum : "undef", ".\n";
1437              
1438 284 100 100     894 if(!defined( $charnum )) {
    50          
1439 6         8 DEBUG > 1 and print STDERR "I don't know how to deal with E<$content>.\n";
1440 6         30 $self->whine( $start_line, "Unknown E content in E<$content>" );
1441 6         20 $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         605 $replacer = Pod::Escapes::e2char($content);
1448 278         3706 DEBUG > 1 and print STDERR " Replacing E<$content> with $replacer\n";
1449             }
1450              
1451 284         1122 splice(@$treelet, $i, 1, $replacer); # no need to back up $i, tho
1452             }
1453             }
1454              
1455 1080         1724 return;
1456             }
1457              
1458              
1459             # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1460              
1461             sub _treat_Ss {
1462 1080     1080   1818 my($self,$treelet) = @_;
1463              
1464 1080 100       2761 _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 1080         1556 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 1680     1680   2511 my($treelet, $in_s) = @_;
1477              
1478 1680         2481 my $is_s = ('S' eq $treelet->[0]);
1479 1680   100     5241 $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 1680         3087 for(my $i = 2; $i < @$treelet; ++$i) {
1483 3964 100       6049 if(ref $treelet->[$i]) {
1484 1175 100       2007 if( _change_S_to_nbsp( $treelet->[$i], $in_s ) ) {
1485 12         32 my $to_pull_up = $treelet->[$i];
1486 12         29 splice @$to_pull_up,0,2; # ...leaving just its content
1487 12         33 splice @$treelet, $i, 1, @$to_pull_up; # Pull up content
1488 12         45 $i += @$to_pull_up - 1; # Make $i skip the pulled-up stuff
1489             }
1490             } else {
1491 2789 100       5992 $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 1680         4379 return $is_s;
1504             }
1505              
1506             #-----------------------------------------------------------------------------
1507              
1508             sub _accessorize { # A simple-minded method-maker
1509 68     68   631 no strict 'refs';
  68         151  
  68         6065  
1510 103     103   294 foreach my $attrname (@_) {
1511 2530 100       5772 next if $attrname =~ m/::/; # a hack
1512 2427         9445 *{caller() . '::' . $attrname} = sub {
1513 68     68   473 use strict;
  68         135  
  68         44530  
1514 7961 50 66 7961   33249 $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 7961 100       24098 : ($_[0]->{$attrname} = $_[1]);
1520 2427         6905 };
1521             }
1522             # Ya know, they say accessories make the ensemble!
1523 103         248 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 524     524   15173 my $class = shift(@_);
1554              
1555 524 100 100     3215 my $mutor = shift(@_) if @_ and ref($_[0] || '') eq 'CODE';
      66        
1556              
1557 524         855 DEBUG and print STDERR "\n\n", '#' x 76,
1558             "\nAbout to parse source: {{\n$_[0]\n}}\n\n";
1559              
1560              
1561 524 100 66     2249 my $parser = ref $class && $class->isa(__PACKAGE__) ? $class : $class->new;
1562 524         1494 $parser->hide_line_numbers(1);
1563              
1564 524         845 my $out = '';
1565 524         1488 $parser->output_string( \$out );
1566 524         732 DEBUG and print STDERR " _out to ", \$out, "\n";
1567              
1568 524 100       1479 $mutor->($parser) if $mutor;
1569              
1570 524         1640 $parser->parse_string_document( $_[0] );
1571             # use Data::Dumper; print STDERR Dumper($parser), "\n";
1572 524         7968 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   4371 my $class = shift(@_);
1582              
1583 56 50       158 Carp::croak "But $class->_duo is useful only in list context!"
1584             unless wantarray;
1585              
1586 56 100 100     418 my $mutor = shift(@_) if @_ and ref($_[0] || '') eq 'CODE';
      66        
1587              
1588 56 50       153 Carp::croak "But $class->_duo takes two parameters, not: @_"
1589             unless @_ == 2;
1590              
1591 56         103 my(@out);
1592              
1593 56         124 while( @_ ) {
1594 112         495 my $parser = $class->new;
1595              
1596 112         241 push @out, '';
1597 112         357 $parser->output_string( \( $out[-1] ) );
1598              
1599 112         154 DEBUG and print STDERR " _duo out to ", $parser->output_string(),
1600             " = $parser->{'output_string'}\n";
1601              
1602 112         346 $parser->hide_line_numbers(1);
1603 112 100       327 $mutor->($parser) if $mutor;
1604 112         303 $parser->parse_string_document( shift( @_ ) );
1605             # use Data::Dumper; print STDERR Dumper($parser), "\n";
1606             }
1607              
1608 56         440 return @out;
1609             }
1610              
1611              
1612              
1613             #-----------------------------------------------------------------------------
1614             1;
1615             __END__