File Coverage

blib/lib/Pod/Simple.pm
Criterion Covered Total %
statement 519 624 83.1
branch 206 292 70.5
condition 168 268 62.6
subroutine 53 66 80.3
pod 30 30 100.0
total 976 1280 76.2


line stmt bran cond sub pod time code
1              
2             require 5;
3             package Pod::Simple;
4 67     67   139620 use strict;
  67         140  
  67         1871  
5 67     67   322 use Carp ();
  67         441  
  67         3039  
6 67 50   67   2064 BEGIN { *DEBUG = sub () {0} unless defined &DEBUG }
7 67     67   31953 use integer;
  67         866  
  67         309  
8 67     67   31315 use Pod::Escapes 1.04 ();
  67         278989  
  67         2638  
9 67     67   28236 use Pod::Simple::LinkSection ();
  67         213  
  67         1657  
10 67     67   356 use Pod::Simple::BlackBox ();
  67         108  
  67         1514  
11             #use utf8;
12              
13 67         19317 use vars qw(
14             $VERSION @ISA
15             @Known_formatting_codes @Known_directives
16             %Known_formatting_codes %Known_directives
17             $NL
18 67     67   291 );
  67         112  
19              
20             @ISA = ('Pod::Simple::BlackBox');
21             $VERSION = '3.42';
22              
23             @Known_formatting_codes = qw(I B C L E F S X Z);
24             %Known_formatting_codes = map(($_=>1), @Known_formatting_codes);
25             @Known_directives = qw(head1 head2 head3 head4 head5 head6 item over back);
26             %Known_directives = map(($_=>'Plain'), @Known_directives);
27             $NL = $/ unless defined $NL;
28              
29             #-----------------------------------------------------------------------------
30             # Set up some constants:
31              
32             BEGIN {
33 67 50   67   367 if(defined &ASCII) { }
34 67         181 elsif(chr(65) eq 'A') { *ASCII = sub () {1} }
35             else { *ASCII = sub () {''} }
36              
37 67 50       318 unless(defined &MANY_LINES) { *MANY_LINES = sub () {20} }
  67         131  
38 67         105 DEBUG > 4 and print STDERR "MANY_LINES is ", MANY_LINES(), "\n";
39 67 50       289 unless(MANY_LINES() >= 1) {
40 0         0 die "MANY_LINES is too small (", MANY_LINES(), ")!\nAborting";
41             }
42 67 50       277 if(defined &UNICODE) { }
    50          
43 67         25818 elsif($] >= 5.008) { *UNICODE = sub() {1} }
44 0         0 else { *UNICODE = sub() {''} }
45             }
46             if(DEBUG > 2) {
47             print STDERR "# We are ", ASCII ? '' : 'not ', "in ASCII-land\n";
48             print STDERR "# We are under a Unicode-safe Perl.\n";
49             }
50              
51             # The NO BREAK SPACE and SOFT HYHPEN are used in several submodules.
52             if ($] ge 5.007_003) { # On sufficiently modern Perls we can handle any
53             # character set
54             $Pod::Simple::nbsp = chr utf8::unicode_to_native(0xA0);
55             $Pod::Simple::shy = chr utf8::unicode_to_native(0xAD);
56             }
57             elsif (Pod::Simple::ASCII) { # Hard code ASCII early Perl
58             $Pod::Simple::nbsp = "\xA0";
59             $Pod::Simple::shy = "\xAD";
60             }
61             else { # EBCDIC on early Perl. We know what the values are for the code
62             # pages supported then.
63             $Pod::Simple::nbsp = "\x41";
64             $Pod::Simple::shy = "\xCA";
65             }
66              
67             # Design note:
68             # This is a parser for Pod. It is not a parser for the set of Pod-like
69             # languages which happens to contain Pod -- it is just for Pod, plus possibly
70             # some extensions.
71              
72             # @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @
73             #@ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @
74             #@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
75              
76             __PACKAGE__->_accessorize(
77             '_output_is_for_JustPod', # For use only by Pod::Simple::JustPod,
78             # If non-zero, don't expand Z<> E<> S<> L<>,
79             # and count how many brackets in format codes
80             'nbsp_for_S', # Whether to map S<...>'s to \xA0 characters
81             'source_filename', # Filename of the source, for use in warnings
82             'source_dead', # Whether to consider this parser's source dead
83              
84             'output_fh', # The filehandle we're writing to, if applicable.
85             # Used only in some derived classes.
86              
87             'hide_line_numbers', # For some dumping subclasses: whether to pointedly
88             # suppress the start_line attribute
89              
90             'line_count', # the current line number
91             'pod_para_count', # count of pod paragraphs seen so far
92              
93             'no_whining', # whether to suppress whining
94             'no_errata_section', # whether to suppress the errata section
95             'complain_stderr', # whether to complain to stderr
96              
97             'doc_has_started', # whether we've fired the open-Document event yet
98              
99             'bare_output', # For some subclasses: whether to prepend
100             # header-code and postpend footer-code
101              
102             'keep_encoding_directive', # whether to emit =encoding
103             'nix_X_codes', # whether to ignore X<...> codes
104             'merge_text', # whether to avoid breaking a single piece of
105             # text up into several events
106              
107             'preserve_whitespace', # whether to try to keep whitespace as-is
108             'strip_verbatim_indent', # What indent to strip from verbatim
109             'expand_verbatim_tabs', # 0: preserve tabs in verbatim blocks
110             # n: expand tabs to stops every n columns
111              
112             'parse_characters', # Whether parser should expect chars rather than octets
113              
114             'content_seen', # whether we've seen any real Pod content
115             'errors_seen', # TODO: document. whether we've seen any errors (fatal or not)
116              
117             'codes_in_verbatim', # for PseudoPod extensions
118              
119             'code_handler', # coderef to call when a code (non-pod) line is seen
120             'cut_handler', # ... when a =cut line is seen
121             'pod_handler', # ... when a =pod line is seen
122             'whiteline_handler', # ... when a line with only whitespace is seen
123             #Called like:
124             # $code_handler->($line, $self->{'line_count'}, $self) if $code_handler;
125             # $cut_handler->($line, $self->{'line_count'}, $self) if $cut_handler;
126             # $pod_handler->($line, $self->{'line_count'}, $self) if $pod_handler;
127             # $wl_handler->($line, $self->{'line_count'}, $self) if $wl_handler;
128             'parse_empty_lists', # whether to acknowledge empty =over/=back blocks
129             'raw_mode', # to report entire raw lines instead of Pod elements
130             );
131              
132             #@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
133              
134             sub any_errata_seen { # good for using as an exit() value...
135 19   100 19 1 151 return shift->{'errors_seen'} || 0;
136             }
137              
138             sub errata_seen {
139 8   50 8 1 918 return shift->{'all_errata'} || {};
140             }
141              
142             # Returns the encoding only if it was recognized as being handled and set
143             sub detected_encoding {
144 0     0 1 0 return shift->{'detected_encoding'};
145             }
146              
147             sub encoding {
148 19     19 1 133 my $this = shift;
149 19 50       120 return $this->{'encoding'} unless @_; # GET.
150              
151 0         0 $this->_handle_encoding_line("=encoding $_[0]");
152 0 0       0 if ($this->{'_processed_encoding'}) {
153 0         0 delete $this->{'_processed_encoding'};
154 0 0       0 if(! $this->{'encoding_command_statuses'} ) {
    0          
155 0         0 DEBUG > 2 and print STDERR " CRAZY ERROR: encoding wasn't really handled?!\n";
156             } elsif( $this->{'encoding_command_statuses'}[-1] ) {
157             $this->scream( "=encoding $_[0]",
158             sprintf "Couldn't do %s: %s",
159             $this->{'encoding_command_reqs' }[-1],
160 0         0 $this->{'encoding_command_statuses'}[-1],
161             );
162             } else {
163 0         0 DEBUG > 2 and print STDERR " (encoding successfully handled.)\n";
164             }
165 0         0 return $this->{'encoding'};
166             } else {
167 0         0 return undef;
168             }
169             }
170              
171             #@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
172             # Pull in some functions that, for some reason, I expect to see here too:
173             BEGIN {
174 67     67   304 *pretty = \&Pod::Simple::BlackBox::pretty;
175 67         144 *stringify_lol = \&Pod::Simple::BlackBox::stringify_lol;
176 67         454148 *my_qr = \&Pod::Simple::BlackBox::my_qr;
177             }
178              
179             #@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
180              
181             sub version_report {
182 0   0 0 1 0 my $class = ref($_[0]) || $_[0];
183 0 0       0 if($class eq __PACKAGE__) {
184 0         0 return "$class $VERSION";
185             } else {
186 0         0 my $v = $class->VERSION;
187 0         0 return "$class $v (" . __PACKAGE__ . " $VERSION)";
188             }
189             }
190              
191             #@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
192              
193             #sub curr_open { # read-only list accessor
194             # return @{ $_[0]{'curr_open'} || return() };
195             #}
196             #sub _curr_open_listref { $_[0]{'curr_open'} ||= [] }
197              
198              
199             sub output_string {
200             # Works by faking out output_fh. Simplifies our code.
201             #
202 877     877 1 10796 my $this = shift;
203 877 100       1819 return $this->{'output_string'} unless @_; # GET.
204            
205 867         27159 require Pod::Simple::TiedOutFH;
206 867 50 33     3674 my $x = (defined($_[0]) and ref($_[0])) ? $_[0] : \( $_[0] );
207 867 100       1855 $$x = '' unless defined $$x;
208 867         1040 DEBUG > 4 and print STDERR "# Output string set to $x ($$x)\n";
209 867         3066 $this->{'output_fh'} = Pod::Simple::TiedOutFH->handle_on($_[0]);
210             return
211 867         2289 $this->{'output_string'} = $_[0];
212             #${ ${ $this->{'output_fh'} } };
213             }
214              
215 10     10 1 46 sub abandon_output_string { $_[0]->abandon_output_fh; delete $_[0]{'output_string'} }
  10         28  
216 10     10 1 26 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 7744 my $class = ref($_[0]) || $_[0];
226             #Carp::croak(__PACKAGE__ . " is a virtual base class -- see perldoc "
227             # . __PACKAGE__ );
228 907         14858 my $obj = bless {
229             'accept_codes' => { map( ($_=>$_), @Known_formatting_codes ) },
230             'accept_directives' => { %Known_directives },
231             'accept_targets' => {},
232             }, $class;
233              
234 907         4099 $obj->expand_verbatim_tabs(8);
235 907         2044 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 20 sub accept_directive_as_verbatim { shift->_accept_directives('Verbatim', @_) }
264 3     3 1 18 sub accept_directive_as_data { shift->_accept_directives('Data', @_) }
265 3     3 1 21 sub accept_directive_as_processed { shift->_accept_directives('Plain', @_) }
266              
267             sub _accept_directives {
268 9     9   25 my($this, $type) = splice @_,0,2;
269 9         20 foreach my $d (@_) {
270 9 50 33     46 next unless defined $d and length $d;
271 9 50       52 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       22 if exists $Known_directives{$d};
275 9         22 $this->{'accept_directives'}{$d} = $type;
276 9         17 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         12 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 168 sub accept_target { shift->accept_targets(@_) } # alias
310 49     49 1 197 sub accept_target_as_text { shift->accept_targets_as_text(@_) } # alias
311              
312              
313 258     258 1 1064 sub accept_targets { shift->_accept_targets('1', @_) }
314              
315 53     53 1 165 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   735 my($this, $type) = splice @_,0,2;
320 311         568 foreach my $t (@_) {
321 570 50 33     1711 next unless defined $t and length $t;
322             # TODO: enforce some limitations on what a target name can be?
323 570         1105 $this->{'accept_targets'}{$t} = $type;
324 570         791 DEBUG > 2 and print STDERR "Learning to accept \"$t\" as target of type $type\n";
325             }
326 311 50       611 return sort keys %{ $this->{'accept_targets'} } if wantarray;
  0         0  
327 311         570 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 643 my $this = shift;
359            
360 337         611 foreach my $new_code (@_) {
361 1211 50 33     3222 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     6909 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         2707 $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         598 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 152 my $this = shift;
391            
392 29         69 foreach my $new_code (@_) {
393 29 50 33     101 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     275 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       114 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         56 delete $this->{'accept_codes'}{$new_code};
407              
408 29         55 DEBUG > 2 and print STDERR "OK, won't accept the code $new_code<...>.\n";
409             }
410            
411 29         47 return;
412             }
413              
414              
415             #@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
416             #@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
417              
418             sub parse_string_document {
419 761     761 1 11807 my $self = shift;
420 761         1033 my @lines;
421 761         1360 foreach my $line_group (@_) {
422 761 100 66     2954 next unless defined $line_group and length $line_group;
423 743         1957 pos($line_group) = 0;
424 743         4243 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     39078 $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         2258 $self->parse_lines(undef); # to signal EOF
437 761         2233 return $self;
438             }
439              
440             sub _init_fh_source {
441 51     51   117 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         101 return;
448             }
449              
450             #:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.
451             #
452              
453             sub parse_file {
454 51     51 1 348 my($self, $source) = (@_);
455              
456 51 50       275 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         105 local *PODSOURCE;
  51         119  
467 51 50       1943 open(PODSOURCE, "<$source") || Carp::croak("Can't open $source: $!");
468 51         297 $self->{'source_filename'} = $source;
469 51         172 $source = *PODSOURCE{IO};
470             }
471 51         275 $self->_init_fh_source($source);
472             }
473             # By here, $source is a FH.
474              
475 51         110 $self->{'source_fh'} = $source;
476              
477 51         91 my($i, @lines);
478 51         131 until( $self->{'source_dead'} ) {
479 490         1460 splice @lines;
480              
481 490         1046 for($i = MANY_LINES; $i--;) { # read those many lines at a time
482 9326         16797 local $/ = $NL;
483 9326         21075 push @lines, scalar(<$source>); # readline
484 9326 100       23413 last unless defined $lines[-1];
485             # but pass thru the undef, which will set source_dead to true
486             }
487              
488 490         767 my $at_eof = ! $lines[-1]; # keep track of the undef
489 490 100       822 pop @lines if $at_eof; # silence warnings
490              
491             # be eol agnostic
492 490         2796 s/\r\n?/\n/g for @lines;
493            
494             # make sure there are only one line elements for parse_lines
495 490         22585 @lines = split(/(?<=\n)/, join('', @lines));
496              
497             # push the undef back after popping it to set source_dead to true
498 490 100       1014 push @lines, undef if $at_eof;
499              
500 490         1368 $self->parse_lines(@lines);
501             }
502 51         117 delete($self->{'source_fh'}); # so it can be GC'd
503 51         970 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 30 my($self, $source, $to) = @_;
513 10 50       22 $self = $self->new unless ref($self); # so we tolerate being a class method
514            
515 10 50 33     112 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     93 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         69 require Symbol;
535 10         57 my $out_fh = Symbol::gensym();
536 10         140 DEBUG and print STDERR "Write-opening to $to\n";
537 10 50       692 open($out_fh, ">$to") or Carp::croak "Can't write-open $to: $!";
538 10 50 33     99 binmode($out_fh)
539             if $self->can('write_with_binmode') and $self->write_with_binmode;
540 10         32 $self->output_fh($out_fh);
541             }
542              
543 10         55 return $self->parse_file($source);
544             }
545              
546             #-----------------------------------------------------------------------------
547              
548             sub whine {
549             #my($self,$line,$complaint) = @_;
550 79     79 1 154 my $self = shift(@_);
551 79         175 ++$self->{'errors_seen'};
552 79 100       220 if($self->{'no_whining'}) {
553 9         14 DEBUG > 9 and print STDERR "Discarding complaint (at line $_[0]) $_[1]\n because no_whining is on.\n";
554 9         18 return;
555             }
556 70         106 push @{$self->{'all_errata'}{$_[0]}}, $_[1];
  70         290  
557 70 50       196 return $self->_complain_warn(@_) if $self->{'complain_stderr'};
558 70         285 return $self->_complain_errata(@_);
559             }
560              
561             sub scream { # like whine, but not suppressible
562             #my($self,$line,$complaint) = @_;
563 8     8 1 25 my $self = shift(@_);
564 8         21 ++$self->{'errors_seen'};
565 8         14 push @{$self->{'all_errata'}{$_[0]}}, $_[1];
  8         43  
566 8 50       32 return $self->_complain_warn(@_) if $self->{'complain_stderr'};
567 8         71 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   232 my($self,$line,$complaint) = @_;
578 78 100       182 if( $self->{'no_errata_section'} ) {
579 10         15 DEBUG > 9 and print STDERR "Discarding erratum (at line $line) $complaint\n because no_errata_section is on.\n";
580             } else {
581 68         86 DEBUG > 9 and print STDERR "Queuing erratum (at line $line) $complaint\n";
582 68         97 push @{$self->{'errata'}{$line}}, $complaint
  68         284  
583             # for a report to be generated later!
584             }
585 78         504 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   397 my($self, $para) = @_;
593 185 50       499 return $para->[1]{'~type'} if $para->[1]{'~type'};
594              
595             return $para->[1]{'~type'} = 'text'
596 185 100 100     524 if join("\n", @{$para}[2 .. $#$para]) =~ m/^\s*(\d+)\.?\s*$/s and $1 ne '1';
  185         1233  
597             # Else fall thru to the general case:
598 183         703 return $self->_get_item_type($para);
599             }
600              
601              
602              
603             sub _get_item_type { # mutates the item!!
604 1205     1205   2301 my($self, $para) = @_;
605 1205 100       2483 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         1744 my $content = join "\n", @{$para}[2 .. $#$para];
  1020         2076  
611              
612 1020 100 100     6222 if($content =~ m/^\s*\*\s*$/s or $content =~ m/^\s*$/s) {
    100          
    100          
613             # Like: "=item *", "=item * ", "=item"
614 59         133 splice @$para, 2; # so it ends up just being ['=item', { attrhash } ]
615 59         128 $para->[1]{'~orig_content'} = $content;
616 59         192 return $para->[1]{'~type'} = 'bullet';
617              
618             } elsif($content =~ m/^\s*\*\s+(.+)/s) { # tolerance
619            
620             # Like: "=item * Foo bar baz";
621 101         253 $para->[1]{'~orig_content'} = $content;
622 101         243 $para->[1]{'~_freaky_para_hack'} = $1;
623 101         111 DEBUG > 2 and print STDERR " Tolerating $$para[2] as =item *\\n\\n$1\n";
624 101         344 splice @$para, 2; # so it ends up just being ['=item', { attrhash } ]
625 101         362 return $para->[1]{'~type'} = 'bullet';
626              
627             } elsif($content =~ m/^\s*(\d+)\.?\s*$/s) {
628             # Like: "=item 1.", "=item 123412"
629            
630 31         73 $para->[1]{'~orig_content'} = $content;
631 31         92 $para->[1]{'number'} = $1; # Yes, stores the number there!
632              
633 31         62 splice @$para, 2; # so it ends up just being ['=item', { attrhash } ]
634 31         126 return $para->[1]{'~type'} = 'number';
635            
636             } else {
637             # It's anything else.
638 829         2669 return $para->[1]{'~type'} = 'text';
639              
640             }
641             }
642              
643             #-----------------------------------------------------------------------------
644              
645             sub _make_treelet {
646 4443     4443   6475 my $self = shift; # and ($para, $start_line)
647 4443         5130 my $treelet;
648 4443 50       7774 if(!@_) {
649 0         0 return [''];
650 4443 50 33     10248 } 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         10643 $treelet = $self->_treelet_from_formatting_codes(@_);
661             }
662            
663 4443 100 100     13242 if( ! $self->{'_output_is_for_JustPod'} # Retain these as-is for pod output
664             && $self->_remap_sequences($treelet) )
665             {
666 1080         2857 $self->_treat_Zs($treelet); # Might as well nix these first
667 1080         2452 $self->_treat_Ls($treelet); # L has to precede E and S
668 1080         2657 $self->_treat_Es($treelet);
669 1080         2532 $self->_treat_Ss($treelet); # S has to come after E
670 1080         2024 $self->_wrap_up($treelet); # Nix X's and merge texties
671            
672             } else {
673 3363         3862 DEBUG and print STDERR "Formatless treelet gets fast-tracked.\n";
674             # Very common case!
675             }
676            
677 4443         7093 splice @$treelet, 0, 2; # lop the top off
678              
679 4443         14270 return $treelet;
680             }
681              
682             #:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.
683              
684             sub _wrap_up {
685 1080     1080   1641 my($self, @stack) = @_;
686 1080         1503 my $nixx = $self->{'nix_X_codes'};
687 1080         1472 my $merge = $self->{'merge_text' };
688 1080 100 100     2434 return unless $nixx or $merge;
689              
690 739         719 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         1005 my($i, $treelet);
697 739         1148 while($treelet = shift @stack) {
698 2717         2717 DEBUG > 3 and print STDERR " Considering children of this $treelet->[0] node...\n";
699 2717         4076 for($i = 2; $i < @$treelet; ++$i) { # iterate over children
700 6192         5459 DEBUG > 3 and print STDERR " Considering child at $i ", pretty($treelet->[$i]), "\n";
701 6192 100 100     24929 if($nixx and ref $treelet->[$i] and $treelet->[$i][0] eq 'X') {
    100 100        
    100 100        
      100        
      100        
702 6         9 DEBUG > 3 and print STDERR " Nixing X node at $i\n";
703 6         9 splice(@$treelet, $i, 1); # just nix this node (and its descendants)
704             # no need to back-update the counter just yet
705 6         11 redo;
706              
707             } elsif($merge and $i != 2 and # non-initial
708             !ref $treelet->[$i] and !ref $treelet->[$i - 1]
709             ) {
710 25         29 DEBUG > 3 and print STDERR " Merging ", $i-1,
711             ":[$treelet->[$i-1]] and $i\:[$treelet->[$i]]\n";
712 25         50 $treelet->[$i-1] .= ( splice(@$treelet, $i, 1) )[0];
713 25         28 DEBUG > 4 and print STDERR " Now: ", $i-1, ":[$treelet->[$i-1]]\n";
714 25         26 --$i;
715 25         55 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         1656 DEBUG > 4 and print STDERR " Enqueuing ", pretty($treelet->[$i]), " for traversal.\n";
721 1742         1951 push @stack, $treelet->[$i];
722              
723 1742 100       3165 if($treelet->[$i][0] eq 'L') {
724 206         236 my $thing;
725 206         293 foreach my $attrname ('section', 'to') {
726 412 100 66     1159 if(defined($thing = $treelet->[$i][1]{$attrname}) and ref $thing) {
727 236         320 unshift @stack, $thing;
728             DEBUG > 4 and print STDERR " +Enqueuing ",
729 236         467 pretty( $treelet->[$i][1]{$attrname} ),
730             " as an attribute value to tweak.\n";
731             }
732             }
733             }
734             }
735             }
736             }
737 739         770 DEBUG > 2 and print STDERR "End of _wrap_up traversal.\n\n";
738              
739 739         965 return;
740             }
741              
742             #:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.
743              
744             sub _remap_sequences {
745 3581     3581   6170 my($self,@stack) = @_;
746            
747 3581 100 66     6723 if(@stack == 1 and @{ $stack[0] } == 3 and !ref $stack[0][2]) {
  3581   100     12494  
748             # VERY common case: abort it.
749 2501         2757 DEBUG and print STDERR "Skipping _remap_sequences: formatless treelet.\n";
750 2501         6843 return 0;
751             }
752            
753 1080   50     2505 my $map = ($self->{'accept_codes'} || die "NO accept_codes in $self?!?");
754              
755 1080         1587 my $start_line = $stack[0][1]{'start_line'};
756 1080         1132 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         1068 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         1525 my($is, $was, $i, $treelet); # scratch
772 1080         2016 while($treelet = shift @stack) {
773 3478         3694 DEBUG > 3 and print STDERR " Considering children of this $treelet->[0] node...\n";
774 3478         5351 for($i = 2; $i < @$treelet; ++$i) { # iterate over children
775 7551 100       14982 next unless ref $treelet->[$i]; # text nodes are uninteresting
776            
777 2404         2358 DEBUG > 4 and print STDERR " Noting child $i : $treelet->[$i][0]<...>\n";
778            
779 2404         4294 $is = $treelet->[$i][0] = $map->{ $was = $treelet->[$i][0] };
780 2404         2424 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       3519 if(!defined $is) {
794 4         23 $self->whine($start_line, "Deleting unknown formatting code $was<>");
795 4         8 $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       4673 if(ref $is) {
    50          
    100          
800 2         5 my @dynasty = @$is;
801 2         3 DEBUG > 4 and print STDERR " Renaming $was node to $dynasty[-1]\n";
802 2         3 $treelet->[$i][0] = pop @dynasty;
803 2         2 my $nugget;
804 2         6 while(@dynasty) {
805 3         3 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         12 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         5 => splice @{ $treelet->[$i] },2
  4         25  
820             # (not catching its first two (non-child) items)
821             );
822 4         13 --$i; # back up for new stuff
823             } else {
824             # otherwise it's unremarkable
825 2398         4753 unshift @stack, $treelet->[$i]; # just recurse
826             }
827             }
828             }
829            
830 1080         1195 DEBUG > 2 and print STDERR "End of _remap_sequences traversal.\n\n";
831              
832 1080 50 66     1970 if(@_ == 2 and @{ $_[1] } == 3 and !ref $_[1][2]) {
  1080   66     3103  
833 0         0 DEBUG and print STDERR "Noting that the treelet is now formatless.\n";
834 0         0 return 0;
835             }
836 1080         2934 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   34 my($self, $para) = @_;
847 21         56 my $content = join ' ', splice @$para, 2;
848 21         82 $content =~ s/^\s+//s;
849 21         55 $content =~ s/\s+$//s;
850              
851 21         23 DEBUG > 2 and print STDERR "Ogling extensor: =extend $content\n";
852              
853 21 50       75 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         42 my $new_letter = $1;
864 21         26 my $fallbacks_one = $2;
865 21         25 my $elements_one;
866 21 50       49 $elements_one = defined($3) ? $3 : $1;
867              
868 21         22 DEBUG > 2 and print STDERR "Extensor has good syntax.\n";
869              
870 21 50 33     54 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       76 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     231 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       81 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         51 my @fallbacks = split ',', $fallbacks_one, -1;
913 21         40 my @elements = split ',', $elements_one, -1;
914              
915 21         36 foreach my $f (@fallbacks) {
916 42 0 33     96 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         22 DEBUG > 3 and printf STDERR "Extensor: Fallbacks <%s> Elements <%s>.\n",
926             @fallbacks, @elements;
927              
928 21         23 my $canonical_form;
929 21         26 foreach my $e (@elements) {
930 42 100       66 if(exists $self->{'accept_codes'}{$e}) {
931 15         12 DEBUG > 1 and print STDERR " Mapping '$new_letter' to known extension '$e'\n";
932 15         112 $canonical_form = $e;
933 15         22 last; # first acceptable elementname wins!
934             } else {
935 27         34 DEBUG > 1 and print STDERR " Can't map '$new_letter' to unknown extension '$e'\n";
936             }
937             }
938              
939              
940 21 100       27 if( defined $canonical_form ) {
941             # We found a good N => elementname mapping
942 15         34 $self->{'accept_codes'}{$new_letter} = $canonical_form;
943 15         26 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       16 $self->{'accept_codes'}{$new_letter}
948             = (@fallbacks == 1) ? $fallbacks[0] : \@fallbacks;
949 6         13 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         36 return;
961             }
962              
963              
964             #:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.:.
965              
966             sub _treat_Zs { # Nix Z<...>'s
967 1080     1080   1708 my($self,@stack) = @_;
968              
969 1080         1307 my($i, $treelet);
970 1080         1640 my $start_line = $stack[0][1]{'start_line'};
971              
972             # A recursive algorithm implemented iteratively! Whee!
973              
974 1080         1835 while($treelet = shift @stack) {
975 3446         5760 for($i = 2; $i < @$treelet; ++$i) { # iterate over children
976 7515 100       14095 next unless ref $treelet->[$i]; # text nodes are uninteresting
977 2403 100       4145 unless($treelet->[$i][0] eq 'Z') {
978 2366         2858 unshift @stack, $treelet->[$i]; # recurse
979 2366         3691 next;
980             }
981            
982 37         46 DEBUG > 1 and print STDERR "Nixing Z node @{$treelet->[$i]}\n";
983            
984             # bitch UNLESS it's empty
985 37 50 33     54 unless( @{$treelet->[$i]} == 2
  37   33     90  
986 37         142 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         66 splice(@$treelet, $i, 1); # thereby just nix this node.
992 37         95 --$i;
993            
994             }
995             }
996            
997 1080         1473 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   1686 my($self,@stack) = @_;
1074              
1075 1080         1386 my($i, $treelet);
1076 1080         1649 my $start_line = $stack[0][1]{'start_line'};
1077              
1078             # A recursive algorithm implemented iteratively! Whee!
1079              
1080 1080         1845 while($treelet = shift @stack) {
1081 3236         5377 for(my $i = 2; $i < @$treelet; ++$i) {
1082             # iterate over children of current tree node
1083 7434 100       14803 next unless ref $treelet->[$i]; # text nodes are uninteresting
1084 2334 100       3748 unless($treelet->[$i][0] eq 'L') {
1085 1991         2364 unshift @stack, $treelet->[$i]; # recurse
1086 1991         2993 next;
1087             }
1088            
1089            
1090             # By here, $treelet->[$i] is definitely an L node
1091 343         542 my $ell = $treelet->[$i];
1092 343         396 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     400 if (@{$ell} == 3 and $ell->[2] =~ m!\A\s*/\s*\z!) {
  343         1380  
1096 1         5 $self->whine( $start_line, "L<> contains only '/'" );
1097 1         2 $treelet->[$i] = 'L'; # just make it a text node
1098 1         5 next; # and move on
1099             }
1100 342 50 66     467 if( @{$ell} == 2
  342   33     760  
1101 342         1094 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     2399 if( (! ref $ell->[2] && $ell->[2] =~ /\A\s/)
      66        
      66        
1109             ||(! ref $ell->[-1] && $ell->[-1] =~ /\s\z/)
1110             ) {
1111 2         13 $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       2068 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   1040 for (2..$#$ell) {
1138 584 100       1116 next if ref $ell->[$_];
1139 448 100       1386 next unless $ell->[$_] =~ m/^(?:([^|]*)\|)?(\w+:[^:\s]\S*)$/s;
1140 44         296 return ($_, $1, $2);
1141             }
1142 298         810 return;
1143             }->()
1144             ) {
1145 44         108 $ell->[1]{'type'} = 'url';
1146              
1147 44         102 my @text = @{$ell}[2..$url_index-1];
  44         115  
1148 44 100       120 push @text, $text_part if defined $text_part;
1149              
1150 44         96 my @url = @{$ell}[$url_index+1..$#$ell];
  44         83  
1151 44         113 unshift @url, $url_part;
1152              
1153 44 100       120 unless (@text) {
1154 30         58 $ell->[1]{'content-implicit'} = 'yes';
1155 30         59 @text = @url;
1156             }
1157              
1158 44 100       382 $ell->[1]{to} = Pod::Simple::LinkSection->new(
1159             @url == 1
1160             ? $url[0]
1161             : [ '', {}, @url ],
1162             );
1163              
1164 44         181 splice @$ell, 2, $#$ell, @text;
1165              
1166 44         323 next;
1167             }
1168            
1169             # Catch some very simple and/or common cases
1170 298 100 66     1183 if(@{$ell} == 3 and ! ref $ell->[2]) {
  298         992  
1171 223         334 my $it = $ell->[2];
1172 223 100       505 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         13 $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         48 $ell->[1]{'to' } =
1179             Pod::Simple::LinkSection->new( $it ); # treelet!
1180              
1181 6         22 next;
1182             }
1183 217 100       890 if($it =~ m/^[^\/\|,\$\%\@\ \"\<\>\:\#\&\*\{\}\[\]\(\)]+(\:\:[^\/\|,\$\%\@\ \"\<\>\:\#\&\*\{\}\[\]\(\)]+)*$/s) {
1184             # Extremely forgiving idea of what constitutes a bare
1185             # modulename link like L or even L
1186 127         151 DEBUG > 1 and print STDERR "Catching \"$it\" as ho-hum L link.\n";
1187 127         241 $ell->[1]{'type'} = 'pod';
1188 127         216 $ell->[1]{'content-implicit'} = 'yes';
1189 127         539 $ell->[1]{'to' } =
1190             Pod::Simple::LinkSection->new( $it ); # treelet!
1191 127         342 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         222 DEBUG > 1 and print STDERR "Running a real parse on this non-trivial L\n";
1202            
1203            
1204 165         207 my $link_text; # set to an arrayref if found
1205 165         440 my @ell_content = @$ell;
1206 165         321 splice @ell_content,0,2; # Knock off the 'L' and {} bits
1207              
1208 165         203 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         203 DEBUG > 3 and
1215             print STDERR " Peering at L content for a '|' ...\n";
1216 165         416 for(my $j = 0; $j < @ell_content; ++$j) {
1217 379 100       793 next if ref $ell_content[$j];
1218 260         297 DEBUG > 3 and
1219             print STDERR " Peering at L-content text bit \"$ell_content[$j]\" for a '|'.\n";
1220              
1221 260 100       826 if($ell_content[$j] =~ m/^([^\|]*)\|(.*)$/s) {
1222 61         180 my @link_text = ($1); # might be 0-length
1223 61         129 $ell_content[$j] = $2; # might be 0-length
1224              
1225 61         76 DEBUG > 3 and
1226             print STDERR " FOUND a '|' in it. Splitting into [$1] + [$2]\n";
1227              
1228 61 100       175 if ($link_text[0] =~ m{[|/]}) {
1229 1         5 $self->whine(
1230             $start_line,
1231             "alternative text '$link_text[0]' contains non-escaped | or /"
1232             );
1233             }
1234              
1235 61         133 unshift @link_text, splice @ell_content, 0, $j;
1236             # leaving only things at J and after
1237 61   66     345 @ell_content = grep ref($_)||length($_), @ell_content ;
1238 61   100     331 $link_text = [grep ref($_)||length($_), @link_text ];
1239 61         92 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         173 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         236 my $section_name; # set to arrayref if found
1251 165         203 DEBUG > 3 and print STDERR " Peering at L-content for a '/' ...\n";
1252 165         373 for(my $j = 0; $j < @ell_content; ++$j) {
1253 218 100       494 next if ref $ell_content[$j];
1254 183         211 DEBUG > 3 and
1255             print STDERR " Peering at L-content text bit \"$ell_content[$j]\" for a '/'.\n";
1256              
1257 183 100       651 if($ell_content[$j] =~ m/^([^\/]*)\/(.*)$/s) {
1258 100         302 my @section_name = ($2); # might be 0-length
1259 100         200 $ell_content[$j] = $1; # might be 0-length
1260              
1261 100         138 DEBUG > 3 and
1262             print STDERR " FOUND a '/' in it.",
1263             " Splitting to page [...$1] + section [$2...]\n";
1264              
1265 100         233 push @section_name, splice @ell_content, 1+$j;
1266             # leaving only things before and including J
1267            
1268 100   100     488 @ell_content = grep ref($_)||length($_), @ell_content ;
1269 100   100     508 @section_name = grep ref($_)||length($_), @section_name ;
1270              
1271             # Turn L<.../"foo"> into L<.../foo>
1272 100 100 66     1024 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         157 $section_name[ 0] =~ s/^\"//s;
1281 40         128 $section_name[-1] =~ s/\"$//s;
1282 40         59 DEBUG > 3 and
1283             print STDERR " Quotes removed: ", pretty(@section_name), "\n";
1284             } else {
1285 60         94 DEBUG > 3 and
1286             print STDERR " No need to remove quotes in ", pretty(@section_name), "\n";
1287             }
1288              
1289 100         170 $section_name = \@section_name;
1290 100         200 last;
1291             }
1292             }
1293              
1294             # Turn L<"Foo Bar"> into L
1295 165 50 66     1058 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         61 $section_name = [splice @ell_content];
1304 19         80 $section_name->[ 0] =~ s/^\"//s;
1305 19         72 $section_name->[-1] =~ s/\"$//s;
1306 19         49 $ell->[1]{'~tolerated'} = 1;
1307             }
1308              
1309             # Turn L into L.
1310 165 100 100     802 if(!$section_name and !$link_text and @ell_content
      66        
      100        
      100        
1311             and grep !ref($_) && m/ /s, @ell_content
1312             ) {
1313 14         34 $section_name = [splice @ell_content];
1314 14         35 $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       345 unless($link_text) {
1325 104         254 $ell->[1]{'content-implicit'} = 'yes';
1326 104         176 $link_text = [];
1327 104 100       374 push @$link_text, '"', @$section_name, '"' if $section_name;
1328              
1329 104 100       222 if(@ell_content) {
1330 51 100       140 $link_text->[-1] .= ' in ' if $section_name;
1331 51         97 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     687 if(@ell_content == 1 and !ref($ell_content[0])
      100        
1339             and $ell_content[0] =~ m{^[^/]+[(][-a-zA-Z0-9]+[)]$}s
1340             ) {
1341 9         25 $ell->[1]{'type'} = 'man';
1342 9         14 DEBUG > 3 and print STDERR "Considering this ($ell_content[0]) a man link.\n";
1343             } else {
1344 156         375 $ell->[1]{'type'} = 'pod';
1345 156         216 DEBUG > 3 and print STDERR "Considering this a pod link (not man or url).\n";
1346             }
1347              
1348 165 100       334 if( defined $section_name ) {
1349 133         1041 $ell->[1]{'section'} = Pod::Simple::LinkSection->new(
1350             ['', {}, @$section_name]
1351             );
1352 133         354 DEBUG > 3 and print STDERR "L-section content: ", pretty($ell->[1]{'section'}), "\n";
1353             }
1354              
1355 165 100       346 if( @ell_content ) {
1356 93         444 $ell->[1]{'to'} = Pod::Simple::LinkSection->new(
1357             ['', {}, @ell_content]
1358             );
1359 93         221 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       704 @$ell = (@$ell[0,1], defined($link_text) ? splice(@$link_text) : '');
1364            
1365 165         224 DEBUG > 2 and print STDERR "End of L-parsing for this node " . pretty($treelet->[$i]) . "\n";
1366              
1367 165         695 unshift @stack, $treelet->[$i]; # might as well recurse
1368             }
1369             }
1370              
1371 1080         1438 return;
1372             }
1373              
1374             # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1375              
1376             sub _treat_Es {
1377 1080     1080   1750 my($self,@stack) = @_;
1378              
1379 1080         1410 my($i, $treelet, $content, $replacer, $charnum);
1380 1080         1521 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         1934 while($treelet = shift @stack) {
1390 3676         6027 for(my $i = 2; $i < @$treelet; ++$i) { # iterate over children
1391 8105 100       16996 next unless ref $treelet->[$i]; # text nodes are uninteresting
1392 2477 100       4764 if($treelet->[$i][0] eq 'L') {
    100          
1393             # SPECIAL STUFF for semi-processed L<>'s
1394            
1395 342         504 my $thing;
1396 342         561 foreach my $attrname ('section', 'to') {
1397 684 100 66     2091 if(defined($thing = $treelet->[$i][1]{$attrname}) and ref $thing) {
1398 403         574 unshift @stack, $thing;
1399             DEBUG > 2 and print STDERR " Enqueuing ",
1400 403         536 pretty( $treelet->[$i][1]{$attrname} ),
1401             " as an attribute value to tweak.\n";
1402             }
1403             }
1404            
1405 342         551 unshift @stack, $treelet->[$i]; # recurse
1406 342         942 next;
1407             } elsif($treelet->[$i][0] ne 'E') {
1408 1851         2218 unshift @stack, $treelet->[$i]; # recurse
1409 1851         2839 next;
1410             }
1411            
1412 284         335 DEBUG > 1 and print STDERR "Ogling E node ", pretty($treelet->[$i]), "\n";
1413              
1414             # bitch if it's empty
1415 284 50 33     357 if( @{$treelet->[$i]} == 2
  284   33     670  
1416 284         1063 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     399 unless(@{$treelet->[$i]} == 3 and !ref($content = $treelet->[$i][2])) {
  284         1058  
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         384 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         739 $charnum = Pod::Escapes::e2charnum($content);
1443 284         3402 DEBUG > 1 and print STDERR " Considering E<$content> with char ",
1444             defined($charnum) ? $charnum : "undef", ".\n";
1445              
1446 284 100 100     883 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         21 $self->whine( $start_line, "Unknown E content in E<$content>" );
1449 6         14 $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         610 $replacer = Pod::Escapes::e2char($content);
1456 278         3698 DEBUG > 1 and print STDERR " Replacing E<$content> with $replacer\n";
1457             }
1458              
1459 284         1104 splice(@$treelet, $i, 1, $replacer); # no need to back up $i, tho
1460             }
1461             }
1462              
1463 1080         1488 return;
1464             }
1465              
1466              
1467             # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1468              
1469             sub _treat_Ss {
1470 1080     1080   1588 my($self,$treelet) = @_;
1471            
1472 1080 100       2521 _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         1400 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   2046 my($treelet, $in_s) = @_;
1485            
1486 1680         2034 my $is_s = ('S' eq $treelet->[0]);
1487 1680   100     4173 $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         2479 for(my $i = 2; $i < @$treelet; ++$i) {
1491 3964 100       4896 if(ref $treelet->[$i]) {
1492 1175 100       1534 if( _change_S_to_nbsp( $treelet->[$i], $in_s ) ) {
1493 12         22 my $to_pull_up = $treelet->[$i];
1494 12         32 splice @$to_pull_up,0,2; # ...leaving just its content
1495 12         31 splice @$treelet, $i, 1, @$to_pull_up; # Pull up content
1496 12         39 $i += @$to_pull_up - 1; # Make $i skip the pulled-up stuff
1497             }
1498             } else {
1499 2789 100       4681 $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         3287 return $is_s;
1512             }
1513              
1514             #-----------------------------------------------------------------------------
1515              
1516             sub _accessorize { # A simple-minded method-maker
1517 67     67   786 no strict 'refs';
  67         141  
  67         5907  
1518 102     102   293 foreach my $attrname (@_) {
1519 2500 100       5179 next if $attrname =~ m/::/; # a hack
1520 2398         8706 *{caller() . '::' . $attrname} = sub {
1521 67     67   495 use strict;
  67         252  
  67         40004  
1522 10508 50 66 10508   38704 $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       30614 : ($_[0]->{$attrname} = $_[1]);
1528 2398         6326 };
1529             }
1530             # Ya know, they say accessories make the ensemble!
1531 102         247 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   9656 my $class = shift(@_);
1562              
1563 524 100 100     3002 my $mutor = shift(@_) if @_ and ref($_[0] || '') eq 'CODE';
      66        
1564              
1565 524         805 DEBUG and print STDERR "\n\n", '#' x 76,
1566             "\nAbout to parse source: {{\n$_[0]\n}}\n\n";
1567            
1568            
1569 524 100 66     2208 my $parser = ref $class && $class->isa(__PACKAGE__) ? $class : $class->new;
1570 524         1543 $parser->hide_line_numbers(1);
1571              
1572 524         798 my $out = '';
1573 524         1573 $parser->output_string( \$out );
1574 524         715 DEBUG and print STDERR " _out to ", \$out, "\n";
1575            
1576 524 100       1363 $mutor->($parser) if $mutor;
1577              
1578 524         1584 $parser->parse_string_document( $_[0] );
1579             # use Data::Dumper; print STDERR Dumper($parser), "\n";
1580 524         6838 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   2454 my $class = shift(@_);
1590            
1591 56 50       175 Carp::croak "But $class->_duo is useful only in list context!"
1592             unless wantarray;
1593              
1594 56 100 100     346 my $mutor = shift(@_) if @_ and ref($_[0] || '') eq 'CODE';
      66        
1595              
1596 56 50       155 Carp::croak "But $class->_duo takes two parameters, not: @_"
1597             unless @_ == 2;
1598              
1599 56         90 my(@out);
1600            
1601 56         127 while( @_ ) {
1602 112         481 my $parser = $class->new;
1603              
1604 112         226 push @out, '';
1605 112         347 $parser->output_string( \( $out[-1] ) );
1606              
1607 112         143 DEBUG and print STDERR " _duo out to ", $parser->output_string(),
1608             " = $parser->{'output_string'}\n";
1609              
1610 112         307 $parser->hide_line_numbers(1);
1611 112 100       292 $mutor->($parser) if $mutor;
1612 112         305 $parser->parse_string_document( shift( @_ ) );
1613             # use Data::Dumper; print STDERR Dumper($parser), "\n";
1614             }
1615              
1616 56         342 return @out;
1617             }
1618              
1619              
1620              
1621             #-----------------------------------------------------------------------------
1622             1;
1623             __END__