]> git.donarmstrong.com Git - perltidy.git/blob - lib/Perl/Tidy/Formatter.pm
New upstream version 20200110
[perltidy.git] / lib / Perl / Tidy / Formatter.pm
1 #####################################################################
2 #
3 # The Perl::Tidy::Formatter package adds indentation, whitespace, and
4 # line breaks to the token stream
5 #
6 # WARNING: This is not a real class for speed reasons.  Only one
7 # Formatter may be used.
8 #
9 #####################################################################
10
11 package Perl::Tidy::Formatter;
12 use strict;
13 use warnings;
14 use Carp;
15 our $VERSION = '20200110';
16
17 # The Tokenizer will be loaded with the Formatter
18 ##use Perl::Tidy::Tokenizer;    # for is_keyword()
19
20 sub Die {
21     my ($msg) = @_;
22     Perl::Tidy::Die($msg);
23     croak "unexpected return from Perl::Tidy::Die";
24 }
25
26 sub Warn {
27     my ($msg) = @_;
28     Perl::Tidy::Warn($msg);
29     return;
30 }
31
32 sub Exit {
33     my ($msg) = @_;
34     Perl::Tidy::Exit($msg);
35     croak "unexpected return from Perl::Tidy::Exit";
36 }
37
38 BEGIN {
39
40     # Codes for insertion and deletion of blanks
41     use constant DELETE => 0;
42     use constant STABLE => 1;
43     use constant INSERT => 2;
44
45     # Caution: these debug flags produce a lot of output
46     # They should all be 0 except when debugging small scripts
47     use constant FORMATTER_DEBUG_FLAG_RECOMBINE   => 0;
48     use constant FORMATTER_DEBUG_FLAG_BOND_TABLES => 0;
49     use constant FORMATTER_DEBUG_FLAG_BOND        => 0;
50     use constant FORMATTER_DEBUG_FLAG_BREAK       => 0;
51     use constant FORMATTER_DEBUG_FLAG_CI          => 0;
52     use constant FORMATTER_DEBUG_FLAG_FLUSH       => 0;
53     use constant FORMATTER_DEBUG_FLAG_FORCE       => 0;
54     use constant FORMATTER_DEBUG_FLAG_LIST        => 0;
55     use constant FORMATTER_DEBUG_FLAG_NOBREAK     => 0;
56     use constant FORMATTER_DEBUG_FLAG_OUTPUT      => 0;
57     use constant FORMATTER_DEBUG_FLAG_SPARSE      => 0;
58     use constant FORMATTER_DEBUG_FLAG_STORE       => 0;
59     use constant FORMATTER_DEBUG_FLAG_UNDOBP      => 0;
60     use constant FORMATTER_DEBUG_FLAG_WHITE       => 0;
61
62     my $debug_warning = sub {
63         print STDOUT "FORMATTER_DEBUGGING with key $_[0]\n";
64     };
65
66     FORMATTER_DEBUG_FLAG_RECOMBINE   && $debug_warning->('RECOMBINE');
67     FORMATTER_DEBUG_FLAG_BOND_TABLES && $debug_warning->('BOND_TABLES');
68     FORMATTER_DEBUG_FLAG_BOND        && $debug_warning->('BOND');
69     FORMATTER_DEBUG_FLAG_BREAK       && $debug_warning->('BREAK');
70     FORMATTER_DEBUG_FLAG_CI          && $debug_warning->('CI');
71     FORMATTER_DEBUG_FLAG_FLUSH       && $debug_warning->('FLUSH');
72     FORMATTER_DEBUG_FLAG_FORCE       && $debug_warning->('FORCE');
73     FORMATTER_DEBUG_FLAG_LIST        && $debug_warning->('LIST');
74     FORMATTER_DEBUG_FLAG_NOBREAK     && $debug_warning->('NOBREAK');
75     FORMATTER_DEBUG_FLAG_OUTPUT      && $debug_warning->('OUTPUT');
76     FORMATTER_DEBUG_FLAG_SPARSE      && $debug_warning->('SPARSE');
77     FORMATTER_DEBUG_FLAG_STORE       && $debug_warning->('STORE');
78     FORMATTER_DEBUG_FLAG_UNDOBP      && $debug_warning->('UNDOBP');
79     FORMATTER_DEBUG_FLAG_WHITE       && $debug_warning->('WHITE');
80 }
81
82 use vars qw{
83
84   @gnu_stack
85   $max_gnu_stack_index
86   $gnu_position_predictor
87   $line_start_index_to_go
88   $last_indentation_written
89   $last_unadjusted_indentation
90   $last_leading_token
91   $last_output_short_opening_token
92   $peak_batch_size
93
94   $saw_VERSION_in_this_file
95   $saw_END_or_DATA_
96
97   @gnu_item_list
98   $max_gnu_item_index
99   $gnu_sequence_number
100   $last_output_indentation
101   %last_gnu_equals
102   %gnu_comma_count
103   %gnu_arrow_count
104
105   @block_type_to_go
106   @type_sequence_to_go
107   @container_environment_to_go
108   @bond_strength_to_go
109   @forced_breakpoint_to_go
110   @token_lengths_to_go
111   @summed_lengths_to_go
112   @levels_to_go
113   @leading_spaces_to_go
114   @reduced_spaces_to_go
115   @mate_index_to_go
116   @ci_levels_to_go
117   @nesting_depth_to_go
118   @nobreak_to_go
119   @old_breakpoint_to_go
120   @tokens_to_go
121   @K_to_go
122   @types_to_go
123   @inext_to_go
124   @iprev_to_go
125
126   %saved_opening_indentation
127
128   $max_index_to_go
129   $comma_count_in_batch
130   $last_nonblank_index_to_go
131   $last_nonblank_type_to_go
132   $last_nonblank_token_to_go
133   $last_last_nonblank_index_to_go
134   $last_last_nonblank_type_to_go
135   $last_last_nonblank_token_to_go
136   @nonblank_lines_at_depth
137   $starting_in_quote
138   $ending_in_quote
139   @whitespace_level_stack
140   $whitespace_last_level
141
142   $format_skipping_pattern_begin
143   $format_skipping_pattern_end
144
145   $forced_breakpoint_count
146   $forced_breakpoint_undo_count
147   @forced_breakpoint_undo_stack
148   %postponed_breakpoint
149
150   $tabbing
151   $embedded_tab_count
152   $first_embedded_tab_at
153   $last_embedded_tab_at
154   $deleted_semicolon_count
155   $first_deleted_semicolon_at
156   $last_deleted_semicolon_at
157   $added_semicolon_count
158   $first_added_semicolon_at
159   $last_added_semicolon_at
160   $first_tabbing_disagreement
161   $last_tabbing_disagreement
162   $in_tabbing_disagreement
163   $tabbing_disagreement_count
164   $input_line_tabbing
165
166   $last_line_leading_type
167   $last_line_leading_level
168   $last_last_line_leading_level
169
170   %block_leading_text
171   %block_opening_line_number
172   $csc_new_statement_ok
173   $csc_last_label
174   %csc_block_label
175   $accumulating_text_for_block
176   $leading_block_text
177   $rleading_block_if_elsif_text
178   $leading_block_text_level
179   $leading_block_text_length_exceeded
180   $leading_block_text_line_length
181   $leading_block_text_line_number
182   $closing_side_comment_prefix_pattern
183   $closing_side_comment_list_pattern
184
185   $blank_lines_after_opening_block_pattern
186   $blank_lines_before_closing_block_pattern
187
188   $last_nonblank_token
189   $last_nonblank_type
190   $last_last_nonblank_token
191   $last_last_nonblank_type
192   $last_nonblank_block_type
193   $last_output_level
194   %is_do_follower
195   %is_if_brace_follower
196   %space_after_keyword
197   $rbrace_follower
198   $looking_for_else
199   %is_last_next_redo_return
200   %is_other_brace_follower
201   %is_else_brace_follower
202   %is_anon_sub_brace_follower
203   %is_anon_sub_1_brace_follower
204   %is_sort_map_grep
205   %is_sort_map_grep_eval
206   %want_one_line_block
207   %is_sort_map_grep_eval_do
208   %is_block_without_semicolon
209   %is_if_unless
210   %is_and_or
211   %is_assignment
212   %is_chain_operator
213   %is_if_unless_and_or_last_next_redo_return
214   %ok_to_add_semicolon_for_block_type
215
216   @has_broken_sublist
217   @dont_align
218   @want_comma_break
219
220   $is_static_block_comment
221   $index_start_one_line_block
222   $semicolons_before_block_self_destruct
223   $index_max_forced_break
224   $input_line_number
225   $diagnostics_object
226   $vertical_aligner_object
227   $logger_object
228   $file_writer_object
229   $formatter_self
230   @ci_stack
231   %want_break_before
232   %outdent_keyword
233   $static_block_comment_pattern
234   $static_side_comment_pattern
235   %opening_vertical_tightness
236   %closing_vertical_tightness
237   %closing_token_indentation
238   $some_closing_token_indentation
239
240   %opening_token_right
241   %stack_opening_token
242   %stack_closing_token
243
244   $block_brace_vertical_tightness_pattern
245   $keyword_group_list_pattern
246   $keyword_group_list_comment_pattern
247
248   $rOpts_add_newlines
249   $rOpts_add_whitespace
250   $rOpts_block_brace_tightness
251   $rOpts_block_brace_vertical_tightness
252   $rOpts_brace_left_and_indent
253   $rOpts_comma_arrow_breakpoints
254   $rOpts_break_at_old_keyword_breakpoints
255   $rOpts_break_at_old_comma_breakpoints
256   $rOpts_break_at_old_logical_breakpoints
257   $rOpts_break_at_old_method_breakpoints
258   $rOpts_break_at_old_ternary_breakpoints
259   $rOpts_break_at_old_attribute_breakpoints
260   $rOpts_closing_side_comment_else_flag
261   $rOpts_closing_side_comment_maximum_text
262   $rOpts_continuation_indentation
263   $rOpts_delete_old_whitespace
264   $rOpts_fuzzy_line_length
265   $rOpts_indent_columns
266   $rOpts_line_up_parentheses
267   $rOpts_maximum_fields_per_table
268   $rOpts_maximum_line_length
269   $rOpts_variable_maximum_line_length
270   $rOpts_short_concatenation_item_length
271   $rOpts_keep_old_blank_lines
272   $rOpts_ignore_old_breakpoints
273   $rOpts_format_skipping
274   $rOpts_space_function_paren
275   $rOpts_space_keyword_paren
276   $rOpts_keep_interior_semicolons
277   $rOpts_ignore_side_comment_lengths
278   $rOpts_stack_closing_block_brace
279   $rOpts_space_backslash_quote
280   $rOpts_whitespace_cycle
281   $rOpts_one_line_block_semicolons
282
283   %is_opening_type
284   %is_closing_type
285   %is_keyword_returning_list
286   %tightness
287   %matching_token
288   $rOpts
289   %right_bond_strength
290   %left_bond_strength
291   %binary_ws_rules
292   %want_left_space
293   %want_right_space
294   %is_digraph
295   %is_trigraph
296   $bli_pattern
297   $bli_list_string
298   %is_closing_type
299   %is_opening_type
300   %is_closing_token
301   %is_opening_token
302
303   %weld_len_left_closing
304   %weld_len_right_closing
305   %weld_len_left_opening
306   %weld_len_right_opening
307
308   $rcuddled_block_types
309
310   $SUB_PATTERN
311   $ASUB_PATTERN
312
313   $NVARS
314
315 };
316
317 BEGIN {
318
319     # Array index names for token variables
320     my $i = 0;
321     use constant {
322         _BLOCK_TYPE_            => $i++,
323         _CI_LEVEL_              => $i++,
324         _CONTAINER_ENVIRONMENT_ => $i++,
325         _CONTAINER_TYPE_        => $i++,
326         _CUMULATIVE_LENGTH_     => $i++,
327         _LINE_INDEX_            => $i++,
328         _KNEXT_SEQ_ITEM_        => $i++,
329         _LEVEL_                 => $i++,
330         _LEVEL_TRUE_            => $i++,
331         _SLEVEL_                => $i++,
332         _TOKEN_                 => $i++,
333         _TYPE_                  => $i++,
334         _TYPE_SEQUENCE_         => $i++,
335     };
336     $NVARS = 1 + _TYPE_SEQUENCE_;
337
338     # default list of block types for which -bli would apply
339     $bli_list_string = 'if else elsif unless while for foreach do : sub';
340
341     my @q;
342
343     @q = qw(
344       .. :: << >> ** && .. || // -> => += -= .= %= &= |= ^= *= <>
345       <= >= == =~ !~ != ++ -- /= x=
346     );
347     @is_digraph{@q} = (1) x scalar(@q);
348
349     @q = qw( ... **= <<= >>= &&= ||= //= <=> <<~ );
350     @is_trigraph{@q} = (1) x scalar(@q);
351
352     @q = qw(
353       = **= += *= &= <<= &&=
354       -= /= |= >>= ||= //=
355       .= %= ^=
356       x=
357     );
358     @is_assignment{@q} = (1) x scalar(@q);
359
360     @q = qw(
361       grep
362       keys
363       map
364       reverse
365       sort
366       split
367     );
368     @is_keyword_returning_list{@q} = (1) x scalar(@q);
369
370     @q = qw(is if unless and or err last next redo return);
371     @is_if_unless_and_or_last_next_redo_return{@q} = (1) x scalar(@q);
372
373     @q = qw(last next redo return);
374     @is_last_next_redo_return{@q} = (1) x scalar(@q);
375
376     @q = qw(sort map grep);
377     @is_sort_map_grep{@q} = (1) x scalar(@q);
378
379     @q = qw(sort map grep eval);
380     @is_sort_map_grep_eval{@q} = (1) x scalar(@q);
381
382     @q = qw(sort map grep eval do);
383     @is_sort_map_grep_eval_do{@q} = (1) x scalar(@q);
384
385     @q = qw(if unless);
386     @is_if_unless{@q} = (1) x scalar(@q);
387
388     @q = qw(and or err);
389     @is_and_or{@q} = (1) x scalar(@q);
390
391     # Identify certain operators which often occur in chains.
392     # Note: the minus (-) causes a side effect of padding of the first line in
393     # something like this (by sub set_logical_padding):
394     #    Checkbutton => 'Transmission checked',
395     #   -variable    => \$TRANS
396     # This usually improves appearance so it seems ok.
397     @q = qw(&& || and or : ? . + - * /);
398     @is_chain_operator{@q} = (1) x scalar(@q);
399
400     # We can remove semicolons after blocks preceded by these keywords
401     @q =
402       qw(BEGIN END CHECK INIT AUTOLOAD DESTROY UNITCHECK continue if elsif else
403       unless while until for foreach given when default);
404     @is_block_without_semicolon{@q} = (1) x scalar(@q);
405
406     # We will allow semicolons to be added within these block types
407     # as well as sub and package blocks.
408     # NOTES:
409     # 1. Note that these keywords are omitted:
410     #     switch case given when default sort map grep
411     # 2. It is also ok to add for sub and package blocks and a labeled block
412     # 3. But not okay for other perltidy types including:
413     #     { } ; G t
414     # 4. Test files: blktype.t, blktype1.t, semicolon.t
415     @q =
416       qw( BEGIN END CHECK INIT AUTOLOAD DESTROY UNITCHECK continue if elsif else
417       unless do while until eval for foreach );
418     @ok_to_add_semicolon_for_block_type{@q} = (1) x scalar(@q);
419
420     # 'L' is token for opening { at hash key
421     @q = qw< L { ( [ >;
422     @is_opening_type{@q} = (1) x scalar(@q);
423
424     # 'R' is token for closing } at hash key
425     @q = qw< R } ) ] >;
426     @is_closing_type{@q} = (1) x scalar(@q);
427
428     @q = qw< { ( [ >;
429     @is_opening_token{@q} = (1) x scalar(@q);
430
431     @q = qw< } ) ] >;
432     @is_closing_token{@q} = (1) x scalar(@q);
433
434     # Patterns for standardizing matches to block types for regular subs and
435     # anonymous subs. Examples
436     #  'sub process' is a named sub
437     #  'sub ::m' is a named sub
438     #  'sub' is an anonymous sub
439     #  'sub:' is a label, not a sub
440     #  'substr' is a keyword
441     $SUB_PATTERN  = '^sub\s+(::|\w)';
442     $ASUB_PATTERN = '^sub$';
443 }
444
445 # whitespace codes
446 use constant WS_YES      => 1;
447 use constant WS_OPTIONAL => 0;
448 use constant WS_NO       => -1;
449
450 # Token bond strengths.
451 use constant NO_BREAK    => 10000;
452 use constant VERY_STRONG => 100;
453 use constant STRONG      => 2.1;
454 use constant NOMINAL     => 1.1;
455 use constant WEAK        => 0.8;
456 use constant VERY_WEAK   => 0.55;
457
458 # values for testing indexes in output array
459 use constant UNDEFINED_INDEX => -1;
460
461 # Maximum number of little messages; probably need not be changed.
462 use constant MAX_NAG_MESSAGES => 6;
463
464 # increment between sequence numbers for each type
465 # For example, ?: pairs might have numbers 7,11,15,...
466 use constant TYPE_SEQUENCE_INCREMENT => 4;
467
468 {
469
470     # methods to count instances
471     my $_count = 0;
472     sub get_count        { return $_count; }
473     sub _increment_count { return ++$_count }
474     sub _decrement_count { return --$_count }
475 }
476
477 sub trim {
478
479     # trim leading and trailing whitespace from a string
480     my $str = shift;
481     $str =~ s/\s+$//;
482     $str =~ s/^\s+//;
483     return $str;
484 }
485
486 sub max {
487     my @vals = @_;
488     my $max  = shift @vals;
489     foreach my $val (@vals) {
490         $max = ( $max < $val ) ? $val : $max;
491     }
492     return $max;
493 }
494
495 sub min {
496     my @vals = @_;
497     my $min  = shift @vals;
498     foreach my $val (@vals) {
499         $min = ( $min > $val ) ? $val : $min;
500     }
501     return $min;
502 }
503
504 sub split_words {
505
506     # given a string containing words separated by whitespace,
507     # return the list of words
508     my ($str) = @_;
509     return unless $str;
510     $str =~ s/\s+$//;
511     $str =~ s/^\s+//;
512     return split( /\s+/, $str );
513 }
514
515 sub check_keys {
516     my ( $rtest, $rvalid, $msg, $exact_match ) = @_;
517
518     # Check the keys of a hash:
519     # $rtest   = ref to hash to test
520     # $rvalid  = ref to hash with valid keys
521
522     # $msg = a message to write in case of error
523     # $exact_match defines the type of check:
524     #     = false: test hash must not have unknown key
525     #     = true:  test hash must have exactly same keys as known hash
526     my @unknown_keys =
527       grep { !exists $rvalid->{$_} } keys %{$rtest};
528     my @missing_keys =
529       grep { !exists $rtest->{$_} } keys %{$rvalid};
530     my $error = @unknown_keys;
531     if ($exact_match) { $error ||= @missing_keys }
532     if ($error) {
533         local $" = ')(';
534         my @expected_keys = sort keys %{$rvalid};
535         @unknown_keys = sort @unknown_keys;
536         Die(<<EOM);
537 ------------------------------------------------------------------------
538 Program error detected checking hash keys
539 Message is: '$msg'
540 Expected keys: (@expected_keys)
541 Unknown key(s): (@unknown_keys)
542 Missing key(s): (@missing_keys)
543 ------------------------------------------------------------------------
544 EOM
545     }
546     return;
547 }
548
549 # interface to Perl::Tidy::Logger routines
550 sub warning {
551     my ($msg) = @_;
552     if ($logger_object) { $logger_object->warning($msg); }
553     return;
554 }
555
556 sub complain {
557     my ($msg) = @_;
558     if ($logger_object) {
559         $logger_object->complain($msg);
560     }
561     return;
562 }
563
564 sub write_logfile_entry {
565     my @msg = @_;
566     if ($logger_object) {
567         $logger_object->write_logfile_entry(@msg);
568     }
569     return;
570 }
571
572 sub black_box {
573     my @msg = @_;
574     if ($logger_object) { $logger_object->black_box(@msg); }
575     return;
576 }
577
578 sub report_definite_bug {
579     if ($logger_object) {
580         $logger_object->report_definite_bug();
581     }
582     return;
583 }
584
585 sub get_saw_brace_error {
586     if ($logger_object) {
587         return $logger_object->get_saw_brace_error();
588     }
589     return;
590 }
591
592 sub we_are_at_the_last_line {
593     if ($logger_object) {
594         $logger_object->we_are_at_the_last_line();
595     }
596     return;
597 }
598
599 # interface to Perl::Tidy::Diagnostics routine
600 sub write_diagnostics {
601     my $msg = shift;
602     if ($diagnostics_object) { $diagnostics_object->write_diagnostics($msg); }
603     return;
604 }
605
606 sub get_added_semicolon_count {
607     my $self = shift;
608     return $added_semicolon_count;
609 }
610
611 sub DESTROY {
612     my $self = shift;
613     $self->_decrement_count();
614     return;
615 }
616
617 sub get_output_line_number {
618     return $vertical_aligner_object->get_output_line_number();
619 }
620
621 sub new {
622
623     my ( $class, @args ) = @_;
624
625     # we are given an object with a write_line() method to take lines
626     my %defaults = (
627         sink_object        => undef,
628         diagnostics_object => undef,
629         logger_object      => undef,
630     );
631     my %args = ( %defaults, @args );
632
633     $logger_object      = $args{logger_object};
634     $diagnostics_object = $args{diagnostics_object};
635
636     # we create another object with a get_line() and peek_ahead() method
637     my $sink_object = $args{sink_object};
638     $file_writer_object =
639       Perl::Tidy::FileWriter->new( $sink_object, $rOpts, $logger_object );
640
641     # initialize the leading whitespace stack to negative levels
642     # so that we can never run off the end of the stack
643     $peak_batch_size        = 0;    # flag to determine if we have output code
644     $gnu_position_predictor = 0;    # where the current token is predicted to be
645     $max_gnu_stack_index    = 0;
646     $max_gnu_item_index     = -1;
647     $gnu_stack[0]                = new_lp_indentation_item( 0, -1, -1, 0, 0 );
648     @gnu_item_list               = ();
649     $last_output_indentation     = 0;
650     $last_indentation_written    = 0;
651     $last_unadjusted_indentation = 0;
652     $last_leading_token          = "";
653     $last_output_short_opening_token = 0;
654
655     $saw_VERSION_in_this_file = !$rOpts->{'pass-version-line'};
656     $saw_END_or_DATA_         = 0;
657
658     @block_type_to_go            = ();
659     @type_sequence_to_go         = ();
660     @container_environment_to_go = ();
661     @bond_strength_to_go         = ();
662     @forced_breakpoint_to_go     = ();
663     @summed_lengths_to_go        = ();    # line length to start of ith token
664     @token_lengths_to_go         = ();
665     @levels_to_go                = ();
666     @mate_index_to_go            = ();
667     @ci_levels_to_go             = ();
668     @nesting_depth_to_go         = (0);
669     @nobreak_to_go               = ();
670     @old_breakpoint_to_go        = ();
671     @tokens_to_go                = ();
672     @K_to_go                     = ();
673     @types_to_go                 = ();
674     @leading_spaces_to_go        = ();
675     @reduced_spaces_to_go        = ();
676     @inext_to_go                 = ();
677     @iprev_to_go                 = ();
678
679     @whitespace_level_stack = ();
680     $whitespace_last_level  = -1;
681
682     @dont_align         = ();
683     @has_broken_sublist = ();
684     @want_comma_break   = ();
685
686     @ci_stack                   = ("");
687     $first_tabbing_disagreement = 0;
688     $last_tabbing_disagreement  = 0;
689     $tabbing_disagreement_count = 0;
690     $in_tabbing_disagreement    = 0;
691     $input_line_tabbing         = undef;
692
693     $last_last_line_leading_level = 0;
694     $last_line_leading_level      = 0;
695     $last_line_leading_type       = '#';
696
697     $last_nonblank_token        = ';';
698     $last_nonblank_type         = ';';
699     $last_last_nonblank_token   = ';';
700     $last_last_nonblank_type    = ';';
701     $last_nonblank_block_type   = "";
702     $last_output_level          = 0;
703     $looking_for_else           = 0;
704     $embedded_tab_count         = 0;
705     $first_embedded_tab_at      = 0;
706     $last_embedded_tab_at       = 0;
707     $deleted_semicolon_count    = 0;
708     $first_deleted_semicolon_at = 0;
709     $last_deleted_semicolon_at  = 0;
710     $added_semicolon_count      = 0;
711     $first_added_semicolon_at   = 0;
712     $last_added_semicolon_at    = 0;
713     $is_static_block_comment    = 0;
714     %postponed_breakpoint       = ();
715
716     # variables for adding side comments
717     %block_leading_text        = ();
718     %block_opening_line_number = ();
719     $csc_new_statement_ok      = 1;
720     %csc_block_label           = ();
721
722     %saved_opening_indentation = ();
723
724     reset_block_text_accumulator();
725
726     prepare_for_new_input_lines();
727
728     $vertical_aligner_object =
729       Perl::Tidy::VerticalAligner->initialize( $rOpts, $file_writer_object,
730         $logger_object, $diagnostics_object );
731
732     if ( $rOpts->{'entab-leading-whitespace'} ) {
733         write_logfile_entry(
734 "Leading whitespace will be entabbed with $rOpts->{'entab-leading-whitespace'} spaces per tab\n"
735         );
736     }
737     elsif ( $rOpts->{'tabs'} ) {
738         write_logfile_entry("Indentation will be with a tab character\n");
739     }
740     else {
741         write_logfile_entry(
742             "Indentation will be with $rOpts->{'indent-columns'} spaces\n");
743     }
744
745     # This hash holds the main data structures for formatting
746     # All hash keys must be defined here.
747     $formatter_self = {
748         rlines              => [],       # = ref to array of lines of the file
749         rlines_new          => [],       # = ref to array of output lines
750                                          #   (FOR FUTURE DEVELOPMENT)
751         rLL                 => [],       # = ref to array with all tokens
752                                          # in the file. LL originally meant
753                                          # 'Linked List'. Linked lists were a
754                                          # bad idea but LL is easy to type.
755         Klimit              => undef,    # = maximum K index for rLL. This is
756                                          # needed to catch any autovivification
757                                          # problems.
758         rnested_pairs       => [],       # for welding decisions
759         K_opening_container => {},       # for quickly traversing structure
760         K_closing_container => {},       # for quickly traversing structure
761         K_opening_ternary   => {},       # for quickly traversing structure
762         K_closing_ternary   => {},       # for quickly traversing structure
763         rcontainer_map      => {},       # hierarchical map of containers
764         rK_phantom_semicolons =>
765           undef,    # for undoing phantom semicolons if iterating
766         rpaired_to_inner_container => {},
767         rbreak_container           => {},    # prevent one-line blocks
768         rshort_nested              => {},    # blocks not forced open
769         rvalid_self_keys           => [],    # for checking
770         valign_batch_count         => 0,
771     };
772     my @valid_keys = keys %{$formatter_self};
773     $formatter_self->{rvalid_self_keys} = \@valid_keys;
774
775     bless $formatter_self, $class;
776
777     # Safety check..this is not a class yet
778     if ( _increment_count() > 1 ) {
779         confess
780 "Attempt to create more than 1 object in $class, which is not a true class yet\n";
781     }
782     return $formatter_self;
783 }
784
785 # Future routines for storing new lines
786 sub push_line {
787     my ( $self, $rline ) = @_;
788
789     # my $rline = $rlines->[$index_old];
790     # push @{$rlines_new}, $rline;
791     return;
792 }
793
794 sub push_old_line {
795     my ( $self, $index_old ) = @_;
796
797     # TODO: This will copy line with index $index_old to the new line array
798     # my $rlines = $self->{rlines};
799     # my $rline = $rlines->[$index_old];
800     # $self->push_line($rline);
801     return;
802 }
803
804 sub push_blank_line {
805     my ($self) = @_;
806
807     # my $rline = ...
808     # $self->push_line($rline);
809     return;
810 }
811
812 sub push_CODE_line {
813     my ( $self, $Kmin, $Kmax ) = @_;
814
815     # TODO: This will store the values for one new line of CODE
816     # CHECK TOKEN RANGE HERE
817     # $self->push_line($rline);
818     return;
819 }
820
821 sub increment_valign_batch_count {
822     my ($self) = shift;
823     return ++$self->{valign_batch_count};
824 }
825
826 sub get_valign_batch_count {
827     my ($self) = shift;
828     return $self->{valign_batch_count};
829 }
830
831 sub Fault {
832     my ($msg) = @_;
833
834     # This routine is called for errors that really should not occur
835     # except if there has been a bug introduced by a recent program change
836     my ( $package0, $filename0, $line0, $subroutine0 ) = caller(0);
837     my ( $package1, $filename1, $line1, $subroutine1 ) = caller(1);
838     my ( $package2, $filename2, $line2, $subroutine2 ) = caller(2);
839     my $input_stream_name = $logger_object->get_input_stream_name();
840
841     Die(<<EOM);
842 ==============================================================================
843 While operating on input stream with name: '$input_stream_name'
844 A fault was detected at line $line0 of sub '$subroutine1'
845 in file '$filename1'
846 which was called from line $line1 of sub '$subroutine2'
847 Message: '$msg'
848 This is probably an error introduced by a recent programming change. 
849 ==============================================================================
850 EOM
851
852     # This is for Perl-Critic
853     return;
854 }
855
856 sub check_self_hash {
857     my $self            = shift;
858     my @valid_self_keys = @{ $self->{rvalid_self_keys} };
859     my %valid_self_hash;
860     @valid_self_hash{@valid_self_keys} = (1) x scalar(@valid_self_keys);
861     check_keys( $self, \%valid_self_hash, "Checkpoint: self error", 1 );
862     return;
863 }
864
865 sub check_token_array {
866     my $self = shift;
867
868     # Check for errors in the array of tokens
869     # Uses package variable $NVARS
870     $self->check_self_hash();
871     my $rLL = $self->{rLL};
872     for ( my $KK = 0 ; $KK < @{$rLL} ; $KK++ ) {
873         my $nvars = @{ $rLL->[$KK] };
874         if ( $nvars != $NVARS ) {
875             my $type = $rLL->[$KK]->[_TYPE_];
876             $type = '*' unless defined($type);
877             Fault(
878 "number of vars for node $KK, type '$type', is $nvars but should be $NVARS"
879             );
880         }
881         foreach my $var ( _TOKEN_, _TYPE_ ) {
882             if ( !defined( $rLL->[$KK]->[$var] ) ) {
883                 my $iline = $rLL->[$KK]->[_LINE_INDEX_];
884                 Fault("Undefined variable $var for K=$KK, line=$iline\n");
885             }
886         }
887     }
888     return;
889 }
890
891 sub set_rLL_max_index {
892     my $self = shift;
893
894     # Set the limit of the rLL array, assuming that it is correct.
895     # This should only be called by routines after they make changes
896     # to tokenization
897     my $rLL = $self->{rLL};
898     if ( !defined($rLL) ) {
899
900         # Shouldn't happen because rLL was initialized to be an array ref
901         Fault("Undefined Memory rLL");
902     }
903     my $Klimit_old = $self->{Klimit};
904     my $num        = @{$rLL};
905     my $Klimit;
906     if ( $num > 0 ) { $Klimit = $num - 1 }
907     $self->{Klimit} = $Klimit;
908     return ($Klimit);
909 }
910
911 sub get_rLL_max_index {
912     my $self = shift;
913
914     # the memory location $rLL and number of tokens should be obtained
915     # from this routine so that any autovivication can be immediately caught.
916     my $rLL    = $self->{rLL};
917     my $Klimit = $self->{Klimit};
918     if ( !defined($rLL) ) {
919
920         # Shouldn't happen because rLL was initialized to be an array ref
921         Fault("Undefined Memory rLL");
922     }
923     my $num = @{$rLL};
924     if (   $num == 0 && defined($Klimit)
925         || $num > 0 && !defined($Klimit)
926         || $num > 0 && $Klimit != $num - 1 )
927     {
928
929         # Possible autovivification problem...
930         if ( !defined($Klimit) ) { $Klimit = '*' }
931         Fault("Error getting rLL: Memory items=$num and Klimit=$Klimit");
932     }
933     return ($Klimit);
934 }
935
936 sub prepare_for_new_input_lines {
937
938     # Remember the largest batch size processed. This is needed
939     # by the pad routine to avoid padding the first nonblank token
940     if ( $max_index_to_go && $max_index_to_go > $peak_batch_size ) {
941         $peak_batch_size = $max_index_to_go;
942     }
943
944     $gnu_sequence_number++;    # increment output batch counter
945     %last_gnu_equals                = ();
946     %gnu_comma_count                = ();
947     %gnu_arrow_count                = ();
948     $line_start_index_to_go         = 0;
949     $max_gnu_item_index             = UNDEFINED_INDEX;
950     $index_max_forced_break         = UNDEFINED_INDEX;
951     $max_index_to_go                = UNDEFINED_INDEX;
952     $last_nonblank_index_to_go      = UNDEFINED_INDEX;
953     $last_nonblank_type_to_go       = '';
954     $last_nonblank_token_to_go      = '';
955     $last_last_nonblank_index_to_go = UNDEFINED_INDEX;
956     $last_last_nonblank_type_to_go  = '';
957     $last_last_nonblank_token_to_go = '';
958     $forced_breakpoint_count        = 0;
959     $forced_breakpoint_undo_count   = 0;
960     $rbrace_follower                = undef;
961     $summed_lengths_to_go[0]        = 0;
962     $comma_count_in_batch           = 0;
963     $starting_in_quote              = 0;
964
965     destroy_one_line_block();
966     return;
967 }
968
969 sub keyword_group_scan {
970     my $self = shift;
971
972     # Manipulate blank lines around keyword groups (kgb* flags)
973     # Scan all lines looking for runs of consecutive lines beginning with
974     # selected keywords.  Example keywords are 'my', 'our', 'local', ... but
975     # they may be anything.  We will set flags requesting that blanks be
976     # inserted around and within them according to input parameters.  Note
977     # that we are scanning the lines as they came in in the input stream, so
978     # they are not necessarily well formatted.
979
980     # The output of this sub is a return hash ref whose keys are the indexes of
981     # lines after which we desire a blank line.  For line index i:
982     #     $rhash_of_desires->{$i} = 1 means we want a blank line AFTER line $i
983     #     $rhash_of_desires->{$i} = 2 means we want blank line $i removed
984     my $rhash_of_desires = {};
985
986     my $Opt_blanks_before = $rOpts->{'keyword-group-blanks-before'};   # '-kgbb'
987     my $Opt_blanks_after  = $rOpts->{'keyword-group-blanks-after'};    # '-kgba'
988     my $Opt_blanks_inside = $rOpts->{'keyword-group-blanks-inside'};   # '-kgbi'
989     my $Opt_blanks_delete = $rOpts->{'keyword-group-blanks-delete'};   # '-kgbd'
990     my $Opt_size          = $rOpts->{'keyword-group-blanks-size'};     # '-kgbs'
991
992     # A range of sizes can be input with decimal notation like 'min.max' with
993     # any number of dots between the two numbers. Examples:
994     #    string    =>    min    max  matches
995     #    1.1             1      1    exactly 1
996     #    1.3             1      3    1,2, or 3
997     #    1..3            1      3    1,2, or 3
998     #    5               5      -    5 or more
999     #    6.              6      -    6 or more
1000     #    .2              -      2    up to 2
1001     #    1.0             1      0    nothing
1002     my ( $Opt_size_min, $Opt_size_max ) = split /\.+/, $Opt_size;
1003     if (   $Opt_size_min && $Opt_size_min !~ /^\d+$/
1004         || $Opt_size_max && $Opt_size_max !~ /^\d+$/ )
1005     {
1006         Warn(<<EOM);
1007 Unexpected value for -kgbs: '$Opt_size'; expecting 'min' or 'min.max'; 
1008 ignoring all -kgb flags
1009 EOM
1010         return $rhash_of_desires;
1011     }
1012     $Opt_size_min = 1 unless ($Opt_size_min);
1013
1014     if ( $Opt_size_max && $Opt_size_max < $Opt_size_min ) {
1015         return $rhash_of_desires;
1016     }
1017
1018     # codes for $Opt_blanks_before and $Opt_blanks_after:
1019     # 0 = never (delete if exist)
1020     # 1 = stable (keep unchanged)
1021     # 2 = always (insert if missing)
1022
1023     return $rhash_of_desires
1024       unless $Opt_size_min > 0
1025       && ( $Opt_blanks_before != 1
1026         || $Opt_blanks_after != 1
1027         || $Opt_blanks_inside
1028         || $Opt_blanks_delete );
1029
1030     my $Opt_pattern         = $keyword_group_list_pattern;
1031     my $Opt_comment_pattern = $keyword_group_list_comment_pattern;
1032     my $Opt_repeat_count =
1033       $rOpts->{'keyword-group-blanks-repeat-count'};    # '-kgbr'
1034
1035     my $rlines              = $self->{rlines};
1036     my $rLL                 = $self->{rLL};
1037     my $K_closing_container = $self->{K_closing_container};
1038
1039     # variables for the current group and subgroups:
1040     my ( $ibeg, $iend, $count, $level_beg, $K_closing, @iblanks, @group,
1041         @subgroup );
1042
1043     # Definitions:
1044     # ($ibeg, $iend) = starting and ending line indexes of this entire group
1045     #         $count = total number of keywords seen in this entire group
1046     #     $level_beg = indententation level of this group
1047     #         @group = [ $i, $token, $count ] =list of all keywords & blanks
1048     #      @subgroup =  $j, index of group where token changes
1049     #       @iblanks = line indexes of blank lines in input stream in this group
1050     #  where i=starting line index
1051     #        token (the keyword)
1052     #        count = number of this token in this subgroup
1053     #            j = index in group where token changes
1054     #
1055     # These vars will contain values for the most recently seen line:
1056     my ( $line_type, $CODE_type, $K_first, $K_last );
1057
1058     my $number_of_groups_seen = 0;
1059
1060     ####################
1061     # helper subroutines
1062     ####################
1063
1064     my $insert_blank_after = sub {
1065         my ($i) = @_;
1066         $rhash_of_desires->{$i} = 1;
1067         my $ip = $i + 1;
1068         if ( defined( $rhash_of_desires->{$ip} )
1069             && $rhash_of_desires->{$ip} == 2 )
1070         {
1071             $rhash_of_desires->{$ip} = 0;
1072         }
1073         return;
1074     };
1075
1076     my $split_into_sub_groups = sub {
1077
1078         # place blanks around long sub-groups of keywords
1079         # ...if requested
1080         return unless ($Opt_blanks_inside);
1081
1082         # loop over sub-groups, index k
1083         push @subgroup, scalar @group;
1084         my $kbeg = 1;
1085         my $kend = @subgroup - 1;
1086         for ( my $k = $kbeg ; $k <= $kend ; $k++ ) {
1087
1088             # index j runs through all keywords found
1089             my $j_b = $subgroup[ $k - 1 ];
1090             my $j_e = $subgroup[$k] - 1;
1091
1092             # index i is the actual line number of a keyword
1093             my ( $i_b, $tok_b, $count_b ) = @{ $group[$j_b] };
1094             my ( $i_e, $tok_e, $count_e ) = @{ $group[$j_e] };
1095             my $num = $count_e - $count_b + 1;
1096
1097             # This subgroup runs from line $ib to line $ie-1, but may contain
1098             # blank lines
1099             if ( $num >= $Opt_size_min ) {
1100
1101                 # if there are blank lines, we require that at least $num lines
1102                 # be non-blank up to the boundary with the next subgroup.
1103                 my $nog_b = my $nog_e = 1;
1104                 if ( @iblanks && !$Opt_blanks_delete ) {
1105                     my $j_bb = $j_b + $num - 1;
1106                     my ( $i_bb, $tok_bb, $count_bb ) = @{ $group[$j_bb] };
1107                     $nog_b = $count_bb - $count_b + 1 == $num;
1108
1109                     my $j_ee = $j_e - ( $num - 1 );
1110                     my ( $i_ee, $tok_ee, $count_ee ) = @{ $group[$j_ee] };
1111                     $nog_e = $count_e - $count_ee + 1 == $num;
1112                 }
1113                 if ( $nog_b && $k > $kbeg ) {
1114                     $insert_blank_after->( $i_b - 1 );
1115                 }
1116                 if ( $nog_e && $k < $kend ) {
1117                     my ( $i_ep, $tok_ep, $count_ep ) = @{ $group[ $j_e + 1 ] };
1118                     $insert_blank_after->( $i_ep - 1 );
1119                 }
1120             }
1121         }
1122     };
1123
1124     my $delete_if_blank = sub {
1125         my ($i) = @_;
1126
1127         # delete line $i if it is blank
1128         return unless ( $i >= 0 && $i < @{$rlines} );
1129         my $line_type = $rlines->[$i]->{_line_type};
1130         return if ( $line_type ne 'CODE' );
1131         my $code_type = $rlines->[$i]->{_code_type};
1132         if ( $code_type eq 'BL' ) { $rhash_of_desires->{$i} = 2; }
1133         return;
1134     };
1135
1136     my $delete_inner_blank_lines = sub {
1137
1138         # always remove unwanted trailing blank lines from our list
1139         return unless (@iblanks);
1140         while ( my $ibl = pop(@iblanks) ) {
1141             if ( $ibl < $iend ) { push @iblanks, $ibl; last }
1142             $iend = $ibl;
1143         }
1144
1145         # now mark mark interior blank lines for deletion if requested
1146         return unless ($Opt_blanks_delete);
1147
1148         while ( my $ibl = pop(@iblanks) ) { $rhash_of_desires->{$ibl} = 2 }
1149
1150     };
1151
1152     my $end_group = sub {
1153
1154         # end a group of keywords
1155         my ($bad_ending) = @_;
1156         if ( defined($ibeg) && $ibeg >= 0 ) {
1157
1158             # then handle sufficiently large groups
1159             if ( $count >= $Opt_size_min ) {
1160
1161                 $number_of_groups_seen++;
1162
1163                 # do any blank deletions regardless of the count
1164                 $delete_inner_blank_lines->();
1165
1166                 if ( $ibeg > 0 ) {
1167                     my $code_type = $rlines->[ $ibeg - 1 ]->{_code_type};
1168
1169                     # patch for hash bang line which is not currently marked as
1170                     # a comment; mark it as a comment
1171                     if ( $ibeg == 1 && !$code_type ) {
1172                         my $line_text = $rlines->[ $ibeg - 1 ]->{_line_text};
1173                         $code_type = 'BC'
1174                           if ( $line_text && $line_text =~ /^#/ );
1175                     }
1176
1177                     # Do not insert a blank after a comment
1178                     # (this could be subject to a flag in the future)
1179                     if ( $code_type !~ /(BC|SBC|SBCX)/ ) {
1180                         if ( $Opt_blanks_before == INSERT ) {
1181                             $insert_blank_after->( $ibeg - 1 );
1182
1183                         }
1184                         elsif ( $Opt_blanks_before == DELETE ) {
1185                             $delete_if_blank->( $ibeg - 1 );
1186                         }
1187                     }
1188                 }
1189
1190                 # We will only put blanks before code lines. We could loosen
1191                 # this rule a little, but we have to be very careful because
1192                 # for example we certainly don't want to drop a blank line
1193                 # after a line like this:
1194                 #   my $var = <<EOM;
1195                 if ( $line_type eq 'CODE' && defined($K_first) ) {
1196
1197                     # - Do not put a blank before a line of different level
1198                     # - Do not put a blank line if we ended the search badly
1199                     # - Do not put a blank at the end of the file
1200                     # - Do not put a blank line before a hanging side comment
1201                     my $level    = $rLL->[$K_first]->[_LEVEL_];
1202                     my $ci_level = $rLL->[$K_first]->[_CI_LEVEL_];
1203
1204                     if (   $level == $level_beg
1205                         && $ci_level == 0
1206                         && !$bad_ending
1207                         && $iend < @{$rlines}
1208                         && $CODE_type ne 'HSC' )
1209                     {
1210                         if ( $Opt_blanks_after == INSERT ) {
1211                             $insert_blank_after->($iend);
1212                         }
1213                         elsif ( $Opt_blanks_after == DELETE ) {
1214                             $delete_if_blank->( $iend + 1 );
1215                         }
1216                     }
1217                 }
1218             }
1219             $split_into_sub_groups->();
1220         }
1221
1222         # reset for another group
1223         $ibeg      = -1;
1224         $iend      = undef;
1225         $level_beg = -1;
1226         $K_closing = undef;
1227         @group     = ();
1228         @subgroup  = ();
1229         @iblanks   = ();
1230     };
1231
1232     my $find_container_end = sub {
1233
1234         # If the keyword lines ends with an open token, find the closing token
1235         # '$K_closing' so that we can easily skip past the contents of the
1236         # container.
1237         return if ( $K_last <= $K_first );
1238         my $KK        = $K_last;
1239         my $type_last = $rLL->[$KK]->[_TYPE_];
1240         my $tok_last  = $rLL->[$KK]->[_TOKEN_];
1241         if ( $type_last eq '#' ) {
1242             $KK       = $self->K_previous_nonblank($KK);
1243             $tok_last = $rLL->[$KK]->[_TOKEN_];
1244         }
1245         if ( $KK > $K_first && $tok_last =~ /^[\(\{\[]$/ ) {
1246
1247             my $type_sequence = $rLL->[$KK]->[_TYPE_SEQUENCE_];
1248             my $lev           = $rLL->[$KK]->[_LEVEL_];
1249             if ( $lev == $level_beg ) {
1250                 $K_closing = $K_closing_container->{$type_sequence};
1251             }
1252         }
1253     };
1254
1255     my $add_to_group = sub {
1256         my ( $i, $token, $level ) = @_;
1257
1258         # End the previous group if we have reached the maximum
1259         # group size
1260         if ( $Opt_size_max && @group >= $Opt_size_max ) {
1261             $end_group->();
1262         }
1263
1264         if ( @group == 0 ) {
1265             $ibeg      = $i;
1266             $level_beg = $level;
1267             $count     = 0;
1268         }
1269
1270         $count++;
1271         $iend = $i;
1272
1273         # New sub-group?
1274         if ( !@group || $token ne $group[-1]->[1] ) {
1275             push @subgroup, scalar(@group);
1276         }
1277         push @group, [ $i, $token, $count ];
1278
1279         # remember if this line ends in an open container
1280         $find_container_end->();
1281
1282         return;
1283     };
1284
1285     ###################################
1286     # loop over all lines of the source
1287     ###################################
1288     $end_group->();
1289     my $i = -1;
1290     foreach my $line_of_tokens ( @{$rlines} ) {
1291
1292         $i++;
1293         last
1294           if ( $Opt_repeat_count > 0
1295             && $number_of_groups_seen >= $Opt_repeat_count );
1296
1297         $CODE_type = "";
1298         $K_first   = undef;
1299         $K_last    = undef;
1300         $line_type = $line_of_tokens->{_line_type};
1301
1302         # always end a group at non-CODE
1303         if ( $line_type ne 'CODE' ) { $end_group->(); next }
1304
1305         $CODE_type = $line_of_tokens->{_code_type};
1306
1307         # end any group at a format skipping line
1308         if ( $CODE_type && $CODE_type eq 'FS' ) {
1309             $end_group->();
1310             next;
1311         }
1312
1313         # continue in a verbatim (VB) type; it may be quoted text
1314         if ( $CODE_type eq 'VB' ) {
1315             if ( $ibeg >= 0 ) { $iend = $i; }
1316             next;
1317         }
1318
1319         # and continue in blank (BL) types
1320         if ( $CODE_type eq 'BL' ) {
1321             if ( $ibeg >= 0 ) {
1322                 $iend = $i;
1323                 push @{iblanks}, $i;
1324
1325                 # propagate current subgroup token
1326                 my $tok = $group[-1]->[1];
1327                 push @group, [ $i, $tok, $count ];
1328             }
1329             next;
1330         }
1331
1332         # examine the first token of this line
1333         my $rK_range = $line_of_tokens->{_rK_range};
1334         ( $K_first, $K_last ) = @{$rK_range};
1335         if ( !defined($K_first) ) {
1336
1337             # Unexpected blank line..shouldn't happen
1338             # $rK_range should be defined for line type CODE
1339             Warn(
1340 "Programming Error: Unexpected Blank Line in sub 'keyword_group_scan'. Ignoring"
1341             );
1342             return $rhash_of_desires;
1343         }
1344
1345         my $level    = $rLL->[$K_first]->[_LEVEL_];
1346         my $type     = $rLL->[$K_first]->[_TYPE_];
1347         my $token    = $rLL->[$K_first]->[_TOKEN_];
1348         my $ci_level = $rLL->[$K_first]->[_CI_LEVEL_];
1349
1350         # see if this is a code type we seek (i.e. comment)
1351         if (   $CODE_type
1352             && $Opt_comment_pattern
1353             && $CODE_type =~ /$Opt_comment_pattern/o )
1354         {
1355
1356             my $tok = $CODE_type;
1357
1358             # Continuing a group
1359             if ( $ibeg >= 0 && $level == $level_beg ) {
1360                 $add_to_group->( $i, $tok, $level );
1361             }
1362
1363             # Start new group
1364             else {
1365
1366                 # first end old group if any; we might be starting new
1367                 # keywords at different level
1368                 if ( $ibeg > 0 ) { $end_group->(); }
1369                 $add_to_group->( $i, $tok, $level );
1370             }
1371             next;
1372         }
1373
1374         # See if it is a keyword we seek, but never start a group in a
1375         # continuation line; the code may be badly formatted.
1376         if (   $ci_level == 0
1377             && $type eq 'k'
1378             && $token =~ /$Opt_pattern/o )
1379         {
1380
1381             # Continuing a keyword group
1382             if ( $ibeg >= 0 && $level == $level_beg ) {
1383                 $add_to_group->( $i, $token, $level );
1384             }
1385
1386             # Start new keyword group
1387             else {
1388
1389                 # first end old group if any; we might be starting new
1390                 # keywords at different level
1391                 if ( $ibeg > 0 ) { $end_group->(); }
1392                 $add_to_group->( $i, $token, $level );
1393             }
1394             next;
1395         }
1396
1397         # This is not one of our keywords, but we are in a keyword group
1398         # so see if we should continue or quit
1399         elsif ( $ibeg >= 0 ) {
1400
1401             # - bail out on a large level change; we may have walked into a
1402             #   data structure or anoymous sub code.
1403             if ( $level > $level_beg + 1 || $level < $level_beg ) {
1404                 $end_group->();
1405                 next;
1406             }
1407
1408             # - keep going on a continuation line of the same level, since
1409             #   it is probably a continuation of our previous keyword,
1410             # - and keep going past hanging side comments because we never
1411             #   want to interrupt them.
1412             if ( ( ( $level == $level_beg ) && $ci_level > 0 )
1413                 || $CODE_type eq 'HSC' )
1414             {
1415                 $iend = $i;
1416                 next;
1417             }
1418
1419             # - continue if if we are within in a container which started with
1420             # the line of the previous keyword.
1421             if ( defined($K_closing) && $K_first <= $K_closing ) {
1422
1423                 # continue if entire line is within container
1424                 if ( $K_last <= $K_closing ) { $iend = $i; next }
1425
1426                 # continue at ); or }; or ];
1427                 my $KK = $K_closing + 1;
1428                 if ( $rLL->[$KK]->[_TYPE_] eq ';' ) {
1429                     if ( $KK < $K_last ) {
1430                         if ( $rLL->[ ++$KK ]->[_TYPE_] eq 'b' ) { ++$KK }
1431                         if ( $KK > $K_last || $rLL->[$KK]->[_TYPE_] ne '#' ) {
1432                             $end_group->(1);
1433                             next;
1434                         }
1435                     }
1436                     $iend = $i;
1437                     next;
1438                 }
1439
1440                 $end_group->(1);
1441                 next;
1442             }
1443
1444             # - end the group if none of the above
1445             $end_group->();
1446             next;
1447         }
1448
1449         # not in a keyword group; continue
1450         else { next }
1451     }
1452
1453     # end of loop over all lines
1454     $end_group->();
1455     return $rhash_of_desires;
1456 }
1457
1458 sub break_lines {
1459
1460     # Loop over old lines to set new line break points
1461
1462     my $self   = shift;
1463     my $rlines = $self->{rlines};
1464
1465     # Note for RT#118553, leave only one newline at the end of a file.
1466     # Example code to do this is in comments below:
1467     # my $Opt_trim_ending_blank_lines = 0;
1468     # if ($Opt_trim_ending_blank_lines) {
1469     #     while ( my $line_of_tokens = pop @{$rlines} ) {
1470     #         my $line_type = $line_of_tokens->{_line_type};
1471     #         if ( $line_type eq 'CODE' ) {
1472     #             my $CODE_type = $line_of_tokens->{_code_type};
1473     #             next if ( $CODE_type eq 'BL' );
1474     #         }
1475     #         push @{$rlines}, $line_of_tokens;
1476     #         last;
1477     #     }
1478     # }
1479
1480    # But while this would be a trivial update, it would have very undesirable
1481    # side effects when perltidy is run from within an editor on a small snippet.
1482    # So this is best done with a separate filter, such
1483    # as 'delete_ending_blank_lines.pl' in the examples folder.
1484
1485     # Flag to prevent blank lines when POD occurs in a format skipping sect.
1486     my $in_format_skipping_section;
1487
1488     # set locations for blanks around long runs of keywords
1489     my $rwant_blank_line_after = $self->keyword_group_scan();
1490
1491     my $line_type = "";
1492     my $i         = -1;
1493     foreach my $line_of_tokens ( @{$rlines} ) {
1494         $i++;
1495
1496         # insert blank lines requested for keyword sequences
1497         if (   $i > 0
1498             && defined( $rwant_blank_line_after->{ $i - 1 } )
1499             && $rwant_blank_line_after->{ $i - 1 } == 1 )
1500         {
1501             $self->want_blank_line();
1502         }
1503
1504         my $last_line_type = $line_type;
1505         $line_type = $line_of_tokens->{_line_type};
1506         my $input_line = $line_of_tokens->{_line_text};
1507
1508         # _line_type codes are:
1509         #   SYSTEM         - system-specific code before hash-bang line
1510         #   CODE           - line of perl code (including comments)
1511         #   POD_START      - line starting pod, such as '=head'
1512         #   POD            - pod documentation text
1513         #   POD_END        - last line of pod section, '=cut'
1514         #   HERE           - text of here-document
1515         #   HERE_END       - last line of here-doc (target word)
1516         #   FORMAT         - format section
1517         #   FORMAT_END     - last line of format section, '.'
1518         #   DATA_START     - __DATA__ line
1519         #   DATA           - unidentified text following __DATA__
1520         #   END_START      - __END__ line
1521         #   END            - unidentified text following __END__
1522         #   ERROR          - we are in big trouble, probably not a perl script
1523
1524         # put a blank line after an =cut which comes before __END__ and __DATA__
1525         # (required by podchecker)
1526         if ( $last_line_type eq 'POD_END' && !$saw_END_or_DATA_ ) {
1527             $file_writer_object->reset_consecutive_blank_lines();
1528             if ( !$in_format_skipping_section && $input_line !~ /^\s*$/ ) {
1529                 $self->want_blank_line();
1530             }
1531         }
1532
1533         # handle line of code..
1534         if ( $line_type eq 'CODE' ) {
1535
1536             my $CODE_type = $line_of_tokens->{_code_type};
1537             $in_format_skipping_section = $CODE_type eq 'FS';
1538
1539             # Handle blank lines
1540             if ( $CODE_type eq 'BL' ) {
1541
1542                 # If keep-old-blank-lines is zero, we delete all
1543                 # old blank lines and let the blank line rules generate any
1544                 # needed blanks.
1545
1546                 # We also delete lines requested by the keyword-group logic
1547                 my $kgb_keep = !( defined( $rwant_blank_line_after->{$i} )
1548                     && $rwant_blank_line_after->{$i} == 2 );
1549
1550                 # But the keep-old-blank-lines flag has priority over kgb flags
1551                 $kgb_keep = 1 if ( $rOpts_keep_old_blank_lines == 2 );
1552
1553                 if ( $rOpts_keep_old_blank_lines && $kgb_keep ) {
1554                     $self->flush();
1555                     $file_writer_object->write_blank_code_line(
1556                         $rOpts_keep_old_blank_lines == 2 );
1557                     $last_line_leading_type = 'b';
1558                 }
1559                 next;
1560             }
1561             else {
1562
1563                 # let logger see all non-blank lines of code
1564                 my $output_line_number = get_output_line_number();
1565                 black_box( $line_of_tokens, $output_line_number );
1566             }
1567
1568             # Handle Format Skipping (FS) and Verbatim (VB) Lines
1569             if ( $CODE_type eq 'VB' || $CODE_type eq 'FS' ) {
1570                 $self->write_unindented_line("$input_line");
1571                 $file_writer_object->reset_consecutive_blank_lines();
1572                 next;
1573             }
1574
1575             # Handle block comment to be deleted
1576             elsif ( $CODE_type eq 'DEL' ) {
1577                 $self->flush();
1578                 next;
1579             }
1580
1581             # Handle all other lines of code
1582             $self->print_line_of_tokens($line_of_tokens);
1583         }
1584
1585         # handle line of non-code..
1586         else {
1587
1588             # set special flags
1589             my $skip_line = 0;
1590             my $tee_line  = 0;
1591             if ( $line_type =~ /^POD/ ) {
1592
1593                 # Pod docs should have a preceding blank line.  But stay
1594                 # out of __END__ and __DATA__ sections, because
1595                 # the user may be using this section for any purpose whatsoever
1596                 if ( $rOpts->{'delete-pod'} ) { $skip_line = 1; }
1597                 if ( $rOpts->{'tee-pod'} )    { $tee_line = 1; }
1598                 if ( $rOpts->{'trim-pod'} )   { $input_line =~ s/\s+$// }
1599                 if (   !$skip_line
1600                     && !$in_format_skipping_section
1601                     && $line_type eq 'POD_START'
1602                     && !$saw_END_or_DATA_ )
1603                 {
1604                     $self->want_blank_line();
1605                 }
1606             }
1607
1608             # leave the blank counters in a predictable state
1609             # after __END__ or __DATA__
1610             elsif ( $line_type =~ /^(END_START|DATA_START)$/ ) {
1611                 $file_writer_object->reset_consecutive_blank_lines();
1612                 $saw_END_or_DATA_ = 1;
1613             }
1614
1615             # write unindented non-code line
1616             if ( !$skip_line ) {
1617                 if ($tee_line) { $file_writer_object->tee_on() }
1618                 $self->write_unindented_line($input_line);
1619                 if ($tee_line) { $file_writer_object->tee_off() }
1620             }
1621         }
1622     }
1623     return;
1624 }
1625
1626 {    ## Beginning of routine to check line hashes
1627
1628     my %valid_line_hash;
1629
1630     BEGIN {
1631
1632         # These keys are defined for each line in the formatter
1633         # Each line must have exactly these quantities
1634         my @valid_line_keys = qw(
1635           _curly_brace_depth
1636           _ending_in_quote
1637           _guessed_indentation_level
1638           _line_number
1639           _line_text
1640           _line_type
1641           _paren_depth
1642           _quote_character
1643           _rK_range
1644           _square_bracket_depth
1645           _starting_in_quote
1646           _ended_in_blank_token
1647           _code_type
1648
1649           _ci_level_0
1650           _level_0
1651           _nesting_blocks_0
1652           _nesting_tokens_0
1653         );
1654
1655         @valid_line_hash{@valid_line_keys} = (1) x scalar(@valid_line_keys);
1656     }
1657
1658     sub check_line_hashes {
1659         my $self = shift;
1660         $self->check_self_hash();
1661         my $rlines = $self->{rlines};
1662         foreach my $rline ( @{$rlines} ) {
1663             my $iline     = $rline->{_line_number};
1664             my $line_type = $rline->{_line_type};
1665             check_keys( $rline, \%valid_line_hash,
1666                 "Checkpoint: line number =$iline,  line_type=$line_type", 1 );
1667         }
1668         return;
1669     }
1670
1671 }    ## End check line hashes
1672
1673 sub write_line {
1674
1675     # We are caching tokenized lines as they arrive and converting them to the
1676     # format needed for the final formatting.
1677     my ( $self, $line_of_tokens_old ) = @_;
1678     my $rLL        = $self->{rLL};
1679     my $Klimit     = $self->{Klimit};
1680     my $rlines_new = $self->{rlines};
1681
1682     my $Kfirst;
1683     my $line_of_tokens = {};
1684     foreach my $key (
1685         qw(
1686         _curly_brace_depth
1687         _ending_in_quote
1688         _guessed_indentation_level
1689         _line_number
1690         _line_text
1691         _line_type
1692         _paren_depth
1693         _quote_character
1694         _square_bracket_depth
1695         _starting_in_quote
1696         )
1697       )
1698     {
1699         $line_of_tokens->{$key} = $line_of_tokens_old->{$key};
1700     }
1701
1702     # Data needed by Logger
1703     $line_of_tokens->{_level_0}          = 0;
1704     $line_of_tokens->{_ci_level_0}       = 0;
1705     $line_of_tokens->{_nesting_blocks_0} = "";
1706     $line_of_tokens->{_nesting_tokens_0} = "";
1707
1708     # Needed to avoid trimming quotes
1709     $line_of_tokens->{_ended_in_blank_token} = undef;
1710
1711     my $line_type     = $line_of_tokens_old->{_line_type};
1712     my $input_line_no = $line_of_tokens_old->{_line_number} - 1;
1713     if ( $line_type eq 'CODE' ) {
1714
1715         my $rtokens         = $line_of_tokens_old->{_rtokens};
1716         my $rtoken_type     = $line_of_tokens_old->{_rtoken_type};
1717         my $rblock_type     = $line_of_tokens_old->{_rblock_type};
1718         my $rcontainer_type = $line_of_tokens_old->{_rcontainer_type};
1719         my $rcontainer_environment =
1720           $line_of_tokens_old->{_rcontainer_environment};
1721         my $rtype_sequence  = $line_of_tokens_old->{_rtype_sequence};
1722         my $rlevels         = $line_of_tokens_old->{_rlevels};
1723         my $rslevels        = $line_of_tokens_old->{_rslevels};
1724         my $rci_levels      = $line_of_tokens_old->{_rci_levels};
1725         my $rnesting_blocks = $line_of_tokens_old->{_rnesting_blocks};
1726         my $rnesting_tokens = $line_of_tokens_old->{_rnesting_tokens};
1727
1728         my $jmax = @{$rtokens} - 1;
1729         if ( $jmax >= 0 ) {
1730             $Kfirst = defined($Klimit) ? $Klimit + 1 : 0;
1731             foreach my $j ( 0 .. $jmax ) {
1732
1733                 # Clip negative nesting depths to zero to avoid problems.
1734                 # Negative values can occur in files with unbalanced containers
1735                 my $slevel = $rslevels->[$j];
1736                 if ( $slevel < 0 ) { $slevel = 0 }
1737
1738                 my @tokary;
1739                 @tokary[
1740                   _TOKEN_,                 _TYPE_,
1741                   _BLOCK_TYPE_,            _CONTAINER_TYPE_,
1742                   _CONTAINER_ENVIRONMENT_, _TYPE_SEQUENCE_,
1743                   _LEVEL_,                 _LEVEL_TRUE_,
1744                   _SLEVEL_,                _CI_LEVEL_,
1745                   _LINE_INDEX_,
1746                   ]
1747                   = (
1748                     $rtokens->[$j],                $rtoken_type->[$j],
1749                     $rblock_type->[$j],            $rcontainer_type->[$j],
1750                     $rcontainer_environment->[$j], $rtype_sequence->[$j],
1751                     $rlevels->[$j],                $rlevels->[$j],
1752                     $slevel,                       $rci_levels->[$j],
1753                     $input_line_no,
1754                   );
1755                 push @{$rLL}, \@tokary;
1756             }
1757
1758             $Klimit = @{$rLL} - 1;
1759
1760             # Need to remember if we can trim the input line
1761             $line_of_tokens->{_ended_in_blank_token} =
1762               $rtoken_type->[$jmax] eq 'b';
1763
1764             $line_of_tokens->{_level_0}          = $rlevels->[0];
1765             $line_of_tokens->{_ci_level_0}       = $rci_levels->[0];
1766             $line_of_tokens->{_nesting_blocks_0} = $rnesting_blocks->[0];
1767             $line_of_tokens->{_nesting_tokens_0} = $rnesting_tokens->[0];
1768         }
1769     }
1770
1771     $line_of_tokens->{_rK_range}  = [ $Kfirst, $Klimit ];
1772     $line_of_tokens->{_code_type} = "";
1773     $self->{Klimit}               = $Klimit;
1774
1775     push @{$rlines_new}, $line_of_tokens;
1776     return;
1777 }
1778
1779 sub initialize_whitespace_hashes {
1780
1781     # initialize these global hashes, which control the use of
1782     # whitespace around tokens:
1783     #
1784     # %binary_ws_rules
1785     # %want_left_space
1786     # %want_right_space
1787     # %space_after_keyword
1788     #
1789     # Many token types are identical to the tokens themselves.
1790     # See the tokenizer for a complete list. Here are some special types:
1791     #   k = perl keyword
1792     #   f = semicolon in for statement
1793     #   m = unary minus
1794     #   p = unary plus
1795     # Note that :: is excluded since it should be contained in an identifier
1796     # Note that '->' is excluded because it never gets space
1797     # parentheses and brackets are excluded since they are handled specially
1798     # curly braces are included but may be overridden by logic, such as
1799     # newline logic.
1800
1801     # NEW_TOKENS: create a whitespace rule here.  This can be as
1802     # simple as adding your new letter to @spaces_both_sides, for
1803     # example.
1804
1805     my @opening_type = qw< L { ( [ >;
1806     @is_opening_type{@opening_type} = (1) x scalar(@opening_type);
1807
1808     my @closing_type = qw< R } ) ] >;
1809     @is_closing_type{@closing_type} = (1) x scalar(@closing_type);
1810
1811     my @spaces_both_sides = qw#
1812       + - * / % ? = . : x < > | & ^ .. << >> ** && .. || // => += -=
1813       .= %= x= &= |= ^= *= <> <= >= == =~ !~ /= != ... <<= >>= ~~ !~~
1814       &&= ||= //= <=> A k f w F n C Y U G v
1815       #;
1816
1817     my @spaces_left_side = qw<
1818       t ! ~ m p { \ h pp mm Z j
1819     >;
1820     push( @spaces_left_side, '#' );    # avoids warning message
1821
1822     my @spaces_right_side = qw<
1823       ; } ) ] R J ++ -- **=
1824     >;
1825     push( @spaces_right_side, ',' );    # avoids warning message
1826
1827     # Note that we are in a BEGIN block here.  Later in processing
1828     # the values of %want_left_space and  %want_right_space
1829     # may be overridden by any user settings specified by the
1830     # -wls and -wrs parameters.  However the binary_whitespace_rules
1831     # are hardwired and have priority.
1832     @want_left_space{@spaces_both_sides} =
1833       (1) x scalar(@spaces_both_sides);
1834     @want_right_space{@spaces_both_sides} =
1835       (1) x scalar(@spaces_both_sides);
1836     @want_left_space{@spaces_left_side} =
1837       (1) x scalar(@spaces_left_side);
1838     @want_right_space{@spaces_left_side} =
1839       (-1) x scalar(@spaces_left_side);
1840     @want_left_space{@spaces_right_side} =
1841       (-1) x scalar(@spaces_right_side);
1842     @want_right_space{@spaces_right_side} =
1843       (1) x scalar(@spaces_right_side);
1844     $want_left_space{'->'}      = WS_NO;
1845     $want_right_space{'->'}     = WS_NO;
1846     $want_left_space{'**'}      = WS_NO;
1847     $want_right_space{'**'}     = WS_NO;
1848     $want_right_space{'CORE::'} = WS_NO;
1849
1850     # These binary_ws_rules are hardwired and have priority over the above
1851     # settings.  It would be nice to allow adjustment by the user,
1852     # but it would be complicated to specify.
1853     #
1854     # hash type information must stay tightly bound
1855     # as in :  ${xxxx}
1856     $binary_ws_rules{'i'}{'L'} = WS_NO;
1857     $binary_ws_rules{'i'}{'{'} = WS_YES;
1858     $binary_ws_rules{'k'}{'{'} = WS_YES;
1859     $binary_ws_rules{'U'}{'{'} = WS_YES;
1860     $binary_ws_rules{'i'}{'['} = WS_NO;
1861     $binary_ws_rules{'R'}{'L'} = WS_NO;
1862     $binary_ws_rules{'R'}{'{'} = WS_NO;
1863     $binary_ws_rules{'t'}{'L'} = WS_NO;
1864     $binary_ws_rules{'t'}{'{'} = WS_NO;
1865     $binary_ws_rules{'}'}{'L'} = WS_NO;
1866     $binary_ws_rules{'}'}{'{'} = WS_OPTIONAL;    # RT#129850; was WS_NO
1867     $binary_ws_rules{'$'}{'L'} = WS_NO;
1868     $binary_ws_rules{'$'}{'{'} = WS_NO;
1869     $binary_ws_rules{'@'}{'L'} = WS_NO;
1870     $binary_ws_rules{'@'}{'{'} = WS_NO;
1871     $binary_ws_rules{'='}{'L'} = WS_YES;
1872     $binary_ws_rules{'J'}{'J'} = WS_YES;
1873
1874     # the following includes ') {'
1875     # as in :    if ( xxx ) { yyy }
1876     $binary_ws_rules{']'}{'L'} = WS_NO;
1877     $binary_ws_rules{']'}{'{'} = WS_NO;
1878     $binary_ws_rules{')'}{'{'} = WS_YES;
1879     $binary_ws_rules{')'}{'['} = WS_NO;
1880     $binary_ws_rules{']'}{'['} = WS_NO;
1881     $binary_ws_rules{']'}{'{'} = WS_NO;
1882     $binary_ws_rules{'}'}{'['} = WS_NO;
1883     $binary_ws_rules{'R'}{'['} = WS_NO;
1884
1885     $binary_ws_rules{']'}{'++'} = WS_NO;
1886     $binary_ws_rules{']'}{'--'} = WS_NO;
1887     $binary_ws_rules{')'}{'++'} = WS_NO;
1888     $binary_ws_rules{')'}{'--'} = WS_NO;
1889
1890     $binary_ws_rules{'R'}{'++'} = WS_NO;
1891     $binary_ws_rules{'R'}{'--'} = WS_NO;
1892
1893     $binary_ws_rules{'i'}{'Q'} = WS_YES;
1894     $binary_ws_rules{'n'}{'('} = WS_YES;    # occurs in 'use package n ()'
1895
1896     # FIXME: we could to split 'i' into variables and functions
1897     # and have no space for functions but space for variables.  For now,
1898     # I have a special patch in the special rules below
1899     $binary_ws_rules{'i'}{'('} = WS_NO;
1900
1901     $binary_ws_rules{'w'}{'('} = WS_NO;
1902     $binary_ws_rules{'w'}{'{'} = WS_YES;
1903     return;
1904
1905 } ## end initialize_whitespace_hashes
1906
1907 sub set_whitespace_flags {
1908
1909     #    This routine examines each pair of nonblank tokens and
1910     #    sets a flag indicating if white space is needed.
1911     #
1912     #    $rwhitespace_flags->[$j] is a flag indicating whether a white space
1913     #    BEFORE token $j is needed, with the following values:
1914     #
1915     #             WS_NO      = -1 do not want a space before token $j
1916     #             WS_OPTIONAL=  0 optional space or $j is a whitespace
1917     #             WS_YES     =  1 want a space before token $j
1918     #
1919
1920     my $self = shift;
1921     my $rLL  = $self->{rLL};
1922
1923     my $rwhitespace_flags = [];
1924
1925     my ( $last_token, $last_type, $last_block_type, $last_input_line_no,
1926         $token, $type, $block_type, $input_line_no );
1927     my $j_tight_closing_paren = -1;
1928
1929     $token              = ' ';
1930     $type               = 'b';
1931     $block_type         = '';
1932     $input_line_no      = 0;
1933     $last_token         = ' ';
1934     $last_type          = 'b';
1935     $last_block_type    = '';
1936     $last_input_line_no = 0;
1937
1938     my $jmax = @{$rLL} - 1;
1939
1940     my ($ws);
1941
1942     # This is some logic moved to a sub to avoid deep nesting of if stmts
1943     my $ws_in_container = sub {
1944
1945         my ($j) = @_;
1946         my $ws = WS_YES;
1947         if ( $j + 1 > $jmax ) { return (WS_NO) }
1948
1949         # Patch to count '-foo' as single token so that
1950         # each of  $a{-foo} and $a{foo} and $a{'foo'} do
1951         # not get spaces with default formatting.
1952         my $j_here = $j;
1953         ++$j_here
1954           if ( $token eq '-'
1955             && $last_token eq '{'
1956             && $rLL->[ $j + 1 ]->[_TYPE_] eq 'w' );
1957
1958         # $j_next is where a closing token should be if
1959         # the container has a single token
1960         if ( $j_here + 1 > $jmax ) { return (WS_NO) }
1961         my $j_next =
1962           ( $rLL->[ $j_here + 1 ]->[_TYPE_] eq 'b' )
1963           ? $j_here + 2
1964           : $j_here + 1;
1965
1966         if ( $j_next > $jmax ) { return WS_NO }
1967         my $tok_next  = $rLL->[$j_next]->[_TOKEN_];
1968         my $type_next = $rLL->[$j_next]->[_TYPE_];
1969
1970         # for tightness = 1, if there is just one token
1971         # within the matching pair, we will keep it tight
1972         if (
1973             $tok_next eq $matching_token{$last_token}
1974
1975             # but watch out for this: [ [ ]    (misc.t)
1976             && $last_token ne $token
1977
1978             # double diamond is usually spaced
1979             && $token ne '<<>>'
1980
1981           )
1982         {
1983
1984             # remember where to put the space for the closing paren
1985             $j_tight_closing_paren = $j_next;
1986             return (WS_NO);
1987         }
1988         return (WS_YES);
1989     };
1990
1991     # main loop over all tokens to define the whitespace flags
1992     for ( my $j = 0 ; $j <= $jmax ; $j++ ) {
1993
1994         my $rtokh = $rLL->[$j];
1995
1996         # Set a default
1997         $rwhitespace_flags->[$j] = WS_OPTIONAL;
1998
1999         if ( $rtokh->[_TYPE_] eq 'b' ) {
2000             next;
2001         }
2002
2003         # set a default value, to be changed as needed
2004         $ws                 = undef;
2005         $last_token         = $token;
2006         $last_type          = $type;
2007         $last_block_type    = $block_type;
2008         $last_input_line_no = $input_line_no;
2009         $token              = $rtokh->[_TOKEN_];
2010         $type               = $rtokh->[_TYPE_];
2011         $block_type         = $rtokh->[_BLOCK_TYPE_];
2012         $input_line_no      = $rtokh->[_LINE_INDEX_];
2013
2014         #---------------------------------------------------------------
2015         # Whitespace Rules Section 1:
2016         # Handle space on the inside of opening braces.
2017         #---------------------------------------------------------------
2018
2019         #    /^[L\{\(\[]$/
2020         if ( $is_opening_type{$last_type} ) {
2021
2022             $j_tight_closing_paren = -1;
2023
2024             # let us keep empty matched braces together: () {} []
2025             # except for BLOCKS
2026             if ( $token eq $matching_token{$last_token} ) {
2027                 if ($block_type) {
2028                     $ws = WS_YES;
2029                 }
2030                 else {
2031                     $ws = WS_NO;
2032                 }
2033             }
2034             else {
2035
2036                 # we're considering the right of an opening brace
2037                 # tightness = 0 means always pad inside with space
2038                 # tightness = 1 means pad inside if "complex"
2039                 # tightness = 2 means never pad inside with space
2040
2041                 my $tightness;
2042                 if (   $last_type eq '{'
2043                     && $last_token eq '{'
2044                     && $last_block_type )
2045                 {
2046                     $tightness = $rOpts_block_brace_tightness;
2047                 }
2048                 else { $tightness = $tightness{$last_token} }
2049
2050                #=============================================================
2051                # Patch for test problem <<snippets/fabrice_bug.in>>
2052                # We must always avoid spaces around a bare word beginning
2053                # with ^ as in:
2054                #    my $before = ${^PREMATCH};
2055                # Because all of the following cause an error in perl:
2056                #    my $before = ${ ^PREMATCH };
2057                #    my $before = ${ ^PREMATCH};
2058                #    my $before = ${^PREMATCH };
2059                # So if brace tightness flag is -bt=0 we must temporarily reset
2060                # to bt=1.  Note that here we must set tightness=1 and not 2 so
2061                # that the closing space
2062                # is also avoided (via the $j_tight_closing_paren flag in coding)
2063                 if ( $type eq 'w' && $token =~ /^\^/ ) { $tightness = 1 }
2064
2065                 #=============================================================
2066
2067                 if ( $tightness <= 0 ) {
2068                     $ws = WS_YES;
2069                 }
2070                 elsif ( $tightness > 1 ) {
2071                     $ws = WS_NO;
2072                 }
2073                 else {
2074                     $ws = $ws_in_container->($j);
2075                 }
2076             }
2077         }    # end setting space flag inside opening tokens
2078         my $ws_1;
2079         $ws_1 = $ws
2080           if FORMATTER_DEBUG_FLAG_WHITE;
2081
2082         #---------------------------------------------------------------
2083         # Whitespace Rules Section 2:
2084         # Handle space on inside of closing brace pairs.
2085         #---------------------------------------------------------------
2086
2087         #   /[\}\)\]R]/
2088         if ( $is_closing_type{$type} ) {
2089
2090             if ( $j == $j_tight_closing_paren ) {
2091
2092                 $j_tight_closing_paren = -1;
2093                 $ws                    = WS_NO;
2094             }
2095             else {
2096
2097                 if ( !defined($ws) ) {
2098
2099                     my $tightness;
2100                     if ( $type eq '}' && $token eq '}' && $block_type ) {
2101                         $tightness = $rOpts_block_brace_tightness;
2102                     }
2103                     else { $tightness = $tightness{$token} }
2104
2105                     $ws = ( $tightness > 1 ) ? WS_NO : WS_YES;
2106                 }
2107             }
2108         }    # end setting space flag inside closing tokens
2109
2110         my $ws_2;
2111         $ws_2 = $ws
2112           if FORMATTER_DEBUG_FLAG_WHITE;
2113
2114         #---------------------------------------------------------------
2115         # Whitespace Rules Section 3:
2116         # Use the binary rule table.
2117         #---------------------------------------------------------------
2118         if ( !defined($ws) ) {
2119             $ws = $binary_ws_rules{$last_type}{$type};
2120         }
2121         my $ws_3;
2122         $ws_3 = $ws
2123           if FORMATTER_DEBUG_FLAG_WHITE;
2124
2125         #---------------------------------------------------------------
2126         # Whitespace Rules Section 4:
2127         # Handle some special cases.
2128         #---------------------------------------------------------------
2129         if ( $token eq '(' ) {
2130
2131             # This will have to be tweaked as tokenization changes.
2132             # We usually want a space at '} (', for example:
2133             # <<snippets/space1.in>>
2134             #     map { 1 * $_; } ( $y, $M, $w, $d, $h, $m, $s );
2135             #
2136             # But not others:
2137             #     &{ $_->[1] }( delete $_[$#_]{ $_->[0] } );
2138             # At present, the above & block is marked as type L/R so this case
2139             # won't go through here.
2140             if ( $last_type eq '}' ) { $ws = WS_YES }
2141
2142             # NOTE: some older versions of Perl had occasional problems if
2143             # spaces are introduced between keywords or functions and opening
2144             # parens.  So the default is not to do this except is certain
2145             # cases.  The current Perl seems to tolerate spaces.
2146
2147             # Space between keyword and '('
2148             elsif ( $last_type eq 'k' ) {
2149                 $ws = WS_NO
2150                   unless ( $rOpts_space_keyword_paren
2151                     || $space_after_keyword{$last_token} );
2152             }
2153
2154             # Space between function and '('
2155             # -----------------------------------------------------
2156             # 'w' and 'i' checks for something like:
2157             #   myfun(    &myfun(   ->myfun(
2158             # -----------------------------------------------------
2159             elsif (( $last_type =~ /^[wUG]$/ )
2160                 || ( $last_type =~ /^[wi]$/ && $last_token =~ /^(\&|->)/ ) )
2161             {
2162                 $ws = WS_NO unless ($rOpts_space_function_paren);
2163             }
2164
2165             # space between something like $i and ( in <<snippets/space2.in>>
2166             # for $i ( 0 .. 20 ) {
2167             # FIXME: eventually, type 'i' needs to be split into multiple
2168             # token types so this can be a hardwired rule.
2169             elsif ( $last_type eq 'i' && $last_token =~ /^[\$\%\@]/ ) {
2170                 $ws = WS_YES;
2171             }
2172
2173             # allow constant function followed by '()' to retain no space
2174             elsif ($last_type eq 'C'
2175                 && $rLL->[ $j + 1 ]->[_TOKEN_] eq ')' )
2176             {
2177                 $ws = WS_NO;
2178             }
2179         }
2180
2181         # patch for SWITCH/CASE: make space at ']{' optional
2182         # since the '{' might begin a case or when block
2183         elsif ( ( $token eq '{' && $type ne 'L' ) && $last_token eq ']' ) {
2184             $ws = WS_OPTIONAL;
2185         }
2186
2187         # keep space between 'sub' and '{' for anonymous sub definition
2188         if ( $type eq '{' ) {
2189             if ( $last_token eq 'sub' ) {
2190                 $ws = WS_YES;
2191             }
2192
2193             # this is needed to avoid no space in '){'
2194             if ( $last_token eq ')' && $token eq '{' ) { $ws = WS_YES }
2195
2196             # avoid any space before the brace or bracket in something like
2197             #  @opts{'a','b',...}
2198             if ( $last_type eq 'i' && $last_token =~ /^\@/ ) {
2199                 $ws = WS_NO;
2200             }
2201         }
2202
2203         elsif ( $type eq 'i' ) {
2204
2205             # never a space before ->
2206             if ( $token =~ /^\-\>/ ) {
2207                 $ws = WS_NO;
2208             }
2209         }
2210
2211         # retain any space between '-' and bare word
2212         elsif ( $type eq 'w' || $type eq 'C' ) {
2213             $ws = WS_OPTIONAL if $last_type eq '-';
2214
2215             # never a space before ->
2216             if ( $token =~ /^\-\>/ ) {
2217                 $ws = WS_NO;
2218             }
2219         }
2220
2221         # retain any space between '-' and bare word; for example
2222         # avoid space between 'USER' and '-' here: <<snippets/space2.in>>
2223         #   $myhash{USER-NAME}='steve';
2224         elsif ( $type eq 'm' || $type eq '-' ) {
2225             $ws = WS_OPTIONAL if ( $last_type eq 'w' );
2226         }
2227
2228         # always space before side comment
2229         elsif ( $type eq '#' ) { $ws = WS_YES if $j > 0 }
2230
2231         # always preserver whatever space was used after a possible
2232         # filehandle (except _) or here doc operator
2233         if (
2234             $type ne '#'
2235             && ( ( $last_type eq 'Z' && $last_token ne '_' )
2236                 || $last_type eq 'h' )
2237           )
2238         {
2239             $ws = WS_OPTIONAL;
2240         }
2241
2242         # space_backslash_quote; RT #123774  <<snippets/rt123774.in>>
2243         # allow a space between a backslash and single or double quote
2244         # to avoid fooling html formatters
2245         elsif ( $last_type eq '\\' && $type eq 'Q' && $token =~ /^[\"\']/ ) {
2246             if ($rOpts_space_backslash_quote) {
2247                 if ( $rOpts_space_backslash_quote == 1 ) {
2248                     $ws = WS_OPTIONAL;
2249                 }
2250                 elsif ( $rOpts_space_backslash_quote == 2 ) { $ws = WS_YES }
2251                 else { }    # shouldnt happen
2252             }
2253             else {
2254                 $ws = WS_NO;
2255             }
2256         }
2257
2258         my $ws_4;
2259         $ws_4 = $ws
2260           if FORMATTER_DEBUG_FLAG_WHITE;
2261
2262         #---------------------------------------------------------------
2263         # Whitespace Rules Section 5:
2264         # Apply default rules not covered above.
2265         #---------------------------------------------------------------
2266
2267         # If we fall through to here, look at the pre-defined hash tables for
2268         # the two tokens, and:
2269         #  if (they are equal) use the common value
2270         #  if (either is zero or undef) use the other
2271         #  if (either is -1) use it
2272         # That is,
2273         # left  vs right
2274         #  1    vs    1     -->  1
2275         #  0    vs    0     -->  0
2276         # -1    vs   -1     --> -1
2277         #
2278         #  0    vs   -1     --> -1
2279         #  0    vs    1     -->  1
2280         #  1    vs    0     -->  1
2281         # -1    vs    0     --> -1
2282         #
2283         # -1    vs    1     --> -1
2284         #  1    vs   -1     --> -1
2285         if ( !defined($ws) ) {
2286             my $wl = $want_left_space{$type};
2287             my $wr = $want_right_space{$last_type};
2288             if ( !defined($wl) ) { $wl = 0 }
2289             if ( !defined($wr) ) { $wr = 0 }
2290             $ws = ( ( $wl == $wr ) || ( $wl == -1 ) || !$wr ) ? $wl : $wr;
2291         }
2292
2293         if ( !defined($ws) ) {
2294             $ws = 0;
2295             write_diagnostics(
2296                 "WS flag is undefined for tokens $last_token $token\n");
2297         }
2298
2299         # Treat newline as a whitespace. Otherwise, we might combine
2300         # 'Send' and '-recipients' here according to the above rules:
2301         # <<snippets/space3.in>>
2302         #    my $msg = new Fax::Send
2303         #      -recipients => $to,
2304         #      -data => $data;
2305         if ( $ws == 0 && $input_line_no != $last_input_line_no ) { $ws = 1 }
2306
2307         if (   ( $ws == 0 )
2308             && $j > 0
2309             && $j < $jmax
2310             && ( $last_type !~ /^[Zh]$/ ) )
2311         {
2312
2313             # If this happens, we have a non-fatal but undesirable
2314             # hole in the above rules which should be patched.
2315             write_diagnostics(
2316                 "WS flag is zero for tokens $last_token $token\n");
2317         }
2318
2319         $rwhitespace_flags->[$j] = $ws;
2320
2321         FORMATTER_DEBUG_FLAG_WHITE && do {
2322             my $str = substr( $last_token, 0, 15 );
2323             $str .= ' ' x ( 16 - length($str) );
2324             if ( !defined($ws_1) ) { $ws_1 = "*" }
2325             if ( !defined($ws_2) ) { $ws_2 = "*" }
2326             if ( !defined($ws_3) ) { $ws_3 = "*" }
2327             if ( !defined($ws_4) ) { $ws_4 = "*" }
2328             print STDOUT
2329 "NEW WHITE:  i=$j $str $last_type $type $ws_1 : $ws_2 : $ws_3 : $ws_4 : $ws \n";
2330         };
2331     } ## end main loop
2332
2333     if ( $rOpts->{'tight-secret-operators'} ) {
2334         new_secret_operator_whitespace( $rLL, $rwhitespace_flags );
2335     }
2336     return $rwhitespace_flags;
2337 } ## end sub set_whitespace_flags
2338
2339 sub respace_tokens {
2340
2341     my $self = shift;
2342     return if $rOpts->{'indent-only'};
2343
2344     # This routine makes all necessary changes to the tokenization after the
2345     # file has been read. This consists mostly of inserting and deleting spaces
2346     # according to the selected parameters. In a few cases non-space characters
2347     # are added, deleted or modified.
2348
2349     # The old tokens are copied one-by-one, with changes, from the old
2350     # linear storage array to a new array.
2351
2352     my $rLL                        = $self->{rLL};
2353     my $Klimit_old                 = $self->{Klimit};
2354     my $rlines                     = $self->{rlines};
2355     my $rpaired_to_inner_container = $self->{rpaired_to_inner_container};
2356
2357     my $rLL_new = [];    # This is the new array
2358     my $KK      = 0;
2359     my $rtoken_vars;
2360     my $Kmax = @{$rLL} - 1;
2361
2362     # Set the whitespace flags, which indicate the token spacing preference.
2363     my $rwhitespace_flags = $self->set_whitespace_flags();
2364
2365     # we will be setting token lengths as we go
2366     my $cumulative_length = 0;
2367
2368     # We also define these hash indexes giving container token array indexes
2369     # as a function of the container sequence numbers.  For example,
2370     my $K_opening_container = {};    # opening [ { or (
2371     my $K_closing_container = {};    # closing ] } or )
2372     my $K_opening_ternary   = {};    # opening ? of ternary
2373     my $K_closing_ternary   = {};    # closing : of ternary
2374
2375     # List of new K indexes of phantom semicolons
2376     # This will be needed if we want to undo them for iterations
2377     my $rK_phantom_semicolons = [];
2378
2379     # Temporary hashes for adding semicolons
2380     ##my $rKfirst_new               = {};
2381
2382     # a sub to link preceding nodes forward to a new node type
2383     my $link_back = sub {
2384         my ( $Ktop, $key ) = @_;
2385
2386         my $Kprev = $Ktop - 1;
2387         while ( $Kprev >= 0
2388             && !defined( $rLL_new->[$Kprev]->[$key] ) )
2389         {
2390             $rLL_new->[$Kprev]->[$key] = $Ktop;
2391             $Kprev -= 1;
2392         }
2393     };
2394
2395     # A sub to store one token in the new array
2396     # All new tokens must be stored by this sub so that it can update
2397     # all data structures on the fly.
2398     my $last_nonblank_type       = ';';
2399     my $last_nonblank_token      = ';';
2400     my $last_nonblank_block_type = '';
2401     my $store_token              = sub {
2402         my ($item) = @_;
2403
2404         # This will be the index of this item in the new array
2405         my $KK_new = @{$rLL_new};
2406
2407         # check for a sequenced item (i.e., container or ?/:)
2408         my $type_sequence = $item->[_TYPE_SEQUENCE_];
2409         if ($type_sequence) {
2410
2411             $link_back->( $KK_new, _KNEXT_SEQ_ITEM_ );
2412
2413             my $token = $item->[_TOKEN_];
2414             if ( $is_opening_token{$token} ) {
2415
2416                 $K_opening_container->{$type_sequence} = $KK_new;
2417             }
2418             elsif ( $is_closing_token{$token} ) {
2419
2420                 $K_closing_container->{$type_sequence} = $KK_new;
2421             }
2422
2423             # These are not yet used but could be useful
2424             else {
2425                 if ( $token eq '?' ) {
2426                     $K_opening_ternary->{$type_sequence} = $KK_new;
2427                 }
2428                 elsif ( $token eq ':' ) {
2429                     $K_closing_ternary->{$type_sequence} = $KK_new;
2430                 }
2431                 else {
2432                     # shouldn't happen
2433                     Fault("Ugh: shouldn't happen");
2434                 }
2435             }
2436         }
2437
2438         # find the length of this token
2439         my $token_length = length( $item->[_TOKEN_] );
2440
2441         # and update the cumulative length
2442         $cumulative_length += $token_length;
2443
2444         # Save the length sum to just AFTER this token
2445         $item->[_CUMULATIVE_LENGTH_] = $cumulative_length;
2446
2447         my $type = $item->[_TYPE_];
2448
2449         # trim side comments
2450         if ( $type eq '#' ) {
2451             $item->[_TOKEN_] =~ s/\s*$//;
2452         }
2453
2454         if ( $type && $type ne 'b' && $type ne '#' ) {
2455             $last_nonblank_type       = $type;
2456             $last_nonblank_token      = $item->[_TOKEN_];
2457             $last_nonblank_block_type = $item->[_BLOCK_TYPE_];
2458         }
2459
2460         # and finally, add this item to the new array
2461         push @{$rLL_new}, $item;
2462     };
2463
2464     my $store_token_and_space = sub {
2465         my ( $item, $want_space ) = @_;
2466
2467         # store a token with preceding space if requested and needed
2468
2469         # First store the space
2470         if (   $want_space
2471             && @{$rLL_new}
2472             && $rLL_new->[-1]->[_TYPE_] ne 'b'
2473             && $rOpts_add_whitespace )
2474         {
2475             my $rcopy = copy_token_as_type( $item, 'b', ' ' );
2476             $rcopy->[_LINE_INDEX_] =
2477               $rLL_new->[-1]->[_LINE_INDEX_];
2478             $store_token->($rcopy);
2479         }
2480
2481         # then the token
2482         $store_token->($item);
2483     };
2484
2485     my $K_end_q = sub {
2486         my ($KK)  = @_;
2487         my $K_end = $KK;
2488         my $Kn    = $self->K_next_nonblank($KK);
2489         while ( defined($Kn) && $rLL->[$Kn]->[_TYPE_] eq 'q' ) {
2490             $K_end = $Kn;
2491             $Kn    = $self->K_next_nonblank($Kn);
2492         }
2493         return $K_end;
2494     };
2495
2496     my $add_phantom_semicolon = sub {
2497
2498         my ($KK) = @_;
2499
2500         my $Kp = $self->K_previous_nonblank( undef, $rLL_new );
2501         return unless ( defined($Kp) );
2502
2503         # we are only adding semicolons for certain block types
2504         my $block_type = $rLL->[$KK]->[_BLOCK_TYPE_];
2505         return
2506           unless ( $ok_to_add_semicolon_for_block_type{$block_type}
2507             || $block_type =~ /^(sub|package)/
2508             || $block_type =~ /^\w+\:$/ );
2509
2510         my $type_sequence = $rLL->[$KK]->[_TYPE_SEQUENCE_];
2511
2512         my $previous_nonblank_type  = $rLL_new->[$Kp]->[_TYPE_];
2513         my $previous_nonblank_token = $rLL_new->[$Kp]->[_TOKEN_];
2514
2515         # Do not add a semicolon if...
2516         return
2517           if (
2518
2519             # it would follow a comment (and be isolated)
2520             $previous_nonblank_type eq '#'
2521
2522             # it follows a code block ( because they are not always wanted
2523             # there and may add clutter)
2524             || $rLL_new->[$Kp]->[_BLOCK_TYPE_]
2525
2526             # it would follow a label
2527             || $previous_nonblank_type eq 'J'
2528
2529             # it would be inside a 'format' statement (and cause syntax error)
2530             || (   $previous_nonblank_type eq 'k'
2531                 && $previous_nonblank_token =~ /format/ )
2532
2533             # if it would prevent welding two containers
2534             || $rpaired_to_inner_container->{$type_sequence}
2535
2536           );
2537
2538         # We will insert an empty semicolon here as a placeholder.  Later, if
2539         # it becomes the last token on a line, we will bring it to life.  The
2540         # advantage of doing this is that (1) we just have to check line
2541         # endings, and (2) the phantom semicolon has zero width and therefore
2542         # won't cause needless breaks of one-line blocks.
2543         my $Ktop = -1;
2544         if (   $rLL_new->[$Ktop]->[_TYPE_] eq 'b'
2545             && $want_left_space{';'} == WS_NO )
2546         {
2547
2548             # convert the blank into a semicolon..
2549             # be careful: we are working on the new stack top
2550             # on a token which has been stored.
2551             my $rcopy = copy_token_as_type( $rLL_new->[$Ktop], 'b', ' ' );
2552
2553             # Convert the existing blank to:
2554             #   a phantom semicolon for one_line_block option = 0 or 1
2555             #   a real semicolon    for one_line_block option = 2
2556             my $tok = $rOpts_one_line_block_semicolons == 2 ? ';' : '';
2557
2558             $rLL_new->[$Ktop]->[_TOKEN_] = $tok;    # zero length if phantom
2559             $rLL_new->[$Ktop]->[_TYPE_]  = ';';
2560             $rLL_new->[$Ktop]->[_SLEVEL_] =
2561               $rLL->[$KK]->[_SLEVEL_];
2562
2563             push @{$rK_phantom_semicolons}, @{$rLL_new} - 1;
2564
2565             # Then store a new blank
2566             $store_token->($rcopy);
2567         }
2568         else {
2569
2570             # insert a new token
2571             my $rcopy = copy_token_as_type( $rLL_new->[$Kp], ';', '' );
2572             $rcopy->[_SLEVEL_] = $rLL->[$KK]->[_SLEVEL_];
2573             $store_token->($rcopy);
2574             push @{$rK_phantom_semicolons}, @{$rLL_new} - 1;
2575         }
2576     };
2577
2578     my $check_Q = sub {
2579
2580         # Check that a quote looks okay
2581         # This sub works but needs to by sync'd with the log file output
2582         # before it can be used.
2583         my ( $KK, $Kfirst ) = @_;
2584         my $token = $rLL->[$KK]->[_TOKEN_];
2585         note_embedded_tab() if ( $token =~ "\t" );
2586
2587         my $Kp = $self->K_previous_nonblank( undef, $rLL_new );
2588         return unless ( defined($Kp) );
2589         my $previous_nonblank_type  = $rLL_new->[$Kp]->[_TYPE_];
2590         my $previous_nonblank_token = $rLL_new->[$Kp]->[_TOKEN_];
2591
2592         my $previous_nonblank_type_2  = 'b';
2593         my $previous_nonblank_token_2 = "";
2594         my $Kpp = $self->K_previous_nonblank( $Kp, $rLL_new );
2595         if ( defined($Kpp) ) {
2596             $previous_nonblank_type_2  = $rLL_new->[$Kpp]->[_TYPE_];
2597             $previous_nonblank_token_2 = $rLL_new->[$Kpp]->[_TOKEN_];
2598         }
2599
2600         my $Kn                  = $self->K_next_nonblank($KK);
2601         my $next_nonblank_token = "";
2602         if ( defined($Kn) ) {
2603             $next_nonblank_token = $rLL->[$Kn]->[_TOKEN_];
2604         }
2605
2606         my $token_0 = $rLL->[$Kfirst]->[_TOKEN_];
2607         my $type_0  = $rLL->[$Kfirst]->[_TYPE_];
2608
2609         # make note of something like '$var = s/xxx/yyy/;'
2610         # in case it should have been '$var =~ s/xxx/yyy/;'
2611         if (
2612                $token =~ /^(s|tr|y|m|\/)/
2613             && $previous_nonblank_token =~ /^(=|==|!=)$/
2614
2615             # preceded by simple scalar
2616             && $previous_nonblank_type_2 eq 'i'
2617             && $previous_nonblank_token_2 =~ /^\$/
2618
2619             # followed by some kind of termination
2620             # (but give complaint if we can not see far enough ahead)
2621             && $next_nonblank_token =~ /^[; \)\}]$/
2622
2623             # scalar is not declared
2624             && !( $type_0 eq 'k' && $token_0 =~ /^(my|our|local)$/ )
2625           )
2626         {
2627             my $guess = substr( $last_nonblank_token, 0, 1 ) . '~';
2628             complain(
2629 "Note: be sure you want '$previous_nonblank_token' instead of '$guess' here\n"
2630             );
2631         }
2632     };
2633
2634     # Main loop over all lines of the file
2635     my $last_K_out;
2636     my $CODE_type = "";
2637     my $line_type = "";
2638
2639     # Testing option to break qw.  Do not use; it can make a mess.
2640     my $ALLOW_BREAK_MULTILINE_QW = 0;
2641     my $in_multiline_qw;
2642     foreach my $line_of_tokens ( @{$rlines} ) {
2643
2644         $input_line_number = $line_of_tokens->{_line_number};
2645         my $last_line_type = $line_type;
2646         $line_type = $line_of_tokens->{_line_type};
2647         next unless ( $line_type eq 'CODE' );
2648         my $last_CODE_type = $CODE_type;
2649         $CODE_type = $line_of_tokens->{_code_type};
2650         my $rK_range = $line_of_tokens->{_rK_range};
2651         my ( $Kfirst, $Klast ) = @{$rK_range};
2652         next unless defined($Kfirst);
2653
2654         # Check for correct sequence of token indexes...
2655         # An error here means that sub write_line() did not correctly
2656         # package the tokenized lines as it received them.
2657         if ( defined($last_K_out) ) {
2658             if ( $Kfirst != $last_K_out + 1 ) {
2659                 Fault(
2660                     "Program Bug: last K out was $last_K_out but Kfirst=$Kfirst"
2661                 );
2662             }
2663         }
2664         else {
2665             if ( $Kfirst != 0 ) {
2666                 Fault("Program Bug: first K is $Kfirst but should be 0");
2667             }
2668         }
2669         $last_K_out = $Klast;
2670
2671         # Handle special lines of code
2672         if ( $CODE_type && $CODE_type ne 'NIN' && $CODE_type ne 'VER' ) {
2673
2674             # CODE_types are as follows.
2675             # 'BL' = Blank Line
2676             # 'VB' = Verbatim - line goes out verbatim
2677             # 'FS' = Format Skipping - line goes out verbatim, no blanks
2678             # 'IO' = Indent Only - only indentation may be changed
2679             # 'NIN' = No Internal Newlines - line does not get broken
2680             # 'HSC'=Hanging Side Comment - fix this hanging side comment
2681             # 'BC'=Block Comment - an ordinary full line comment
2682             # 'SBC'=Static Block Comment - a block comment which does not get
2683             #      indented
2684             # 'SBCX'=Static Block Comment Without Leading Space
2685             # 'DEL'=Delete this line
2686             # 'VER'=VERSION statement
2687             # '' or (undefined) - no restructions
2688
2689             # For a hanging side comment we insert an empty quote before
2690             # the comment so that it becomes a normal side comment and
2691             # will be aligned by the vertical aligner
2692             if ( $CODE_type eq 'HSC' ) {
2693
2694                 # Safety Check: This must be a line with one token (a comment)
2695                 my $rtoken_vars = $rLL->[$Kfirst];
2696                 if ( $Kfirst == $Klast && $rtoken_vars->[_TYPE_] eq '#' ) {
2697
2698                     # Note that even if the flag 'noadd-whitespace' is set, we
2699                     # will make an exception here and allow a blank to be
2700                     # inserted to push the comment to the right.  We can think
2701                     # of this as an adjustment of indentation rather than
2702                     # whitespace between tokens. This will also prevent the
2703                     # hanging side comment from getting converted to a block
2704                     # comment if whitespace gets deleted, as for example with
2705                     # the -extrude and -mangle options.
2706                     my $rcopy = copy_token_as_type( $rtoken_vars, 'q', '' );
2707                     $store_token->($rcopy);
2708                     $rcopy = copy_token_as_type( $rtoken_vars, 'b', ' ' );
2709                     $store_token->($rcopy);
2710                     $store_token->($rtoken_vars);
2711                     next;
2712                 }
2713                 else {
2714
2715                     # This line was mis-marked by sub scan_comment
2716                     Fault(
2717                         "Program bug. A hanging side comment has been mismarked"
2718                     );
2719                 }
2720             }
2721
2722             # Copy tokens unchanged
2723             foreach my $KK ( $Kfirst .. $Klast ) {
2724                 $store_token->( $rLL->[$KK] );
2725             }
2726             next;
2727         }
2728
2729         # Handle normal line..
2730
2731         # Insert any essential whitespace between lines
2732         # if last line was normal CODE.
2733         # Patch for rt #125012: use K_previous_code rather than '_nonblank'
2734         # because comments may disappear.
2735         my $type_next  = $rLL->[$Kfirst]->[_TYPE_];
2736         my $token_next = $rLL->[$Kfirst]->[_TOKEN_];
2737         my $Kp         = $self->K_previous_code( undef, $rLL_new );
2738         if (   $last_line_type eq 'CODE'
2739             && $type_next ne 'b'
2740             && defined($Kp) )
2741         {
2742             my $token_p = $rLL_new->[$Kp]->[_TOKEN_];
2743             my $type_p  = $rLL_new->[$Kp]->[_TYPE_];
2744
2745             my ( $token_pp, $type_pp );
2746             my $Kpp = $self->K_previous_code( $Kp, $rLL_new );
2747             if ( defined($Kpp) ) {
2748                 $token_pp = $rLL_new->[$Kpp]->[_TOKEN_];
2749                 $type_pp  = $rLL_new->[$Kpp]->[_TYPE_];
2750             }
2751             else {
2752                 $token_pp = ";";
2753                 $type_pp  = ';';
2754             }
2755
2756             if (
2757                 is_essential_whitespace(
2758                     $token_pp, $type_pp,    $token_p,
2759                     $type_p,   $token_next, $type_next,
2760                 )
2761               )
2762             {
2763
2764                 # Copy this first token as blank, but use previous line number
2765                 my $rcopy = copy_token_as_type( $rLL->[$Kfirst], 'b', ' ' );
2766                 $rcopy->[_LINE_INDEX_] =
2767                   $rLL_new->[-1]->[_LINE_INDEX_];
2768                 $store_token->($rcopy);
2769             }
2770         }
2771
2772         # loop to copy all tokens on this line, with any changes
2773         my $type_sequence;
2774         for ( my $KK = $Kfirst ; $KK <= $Klast ; $KK++ ) {
2775             $rtoken_vars = $rLL->[$KK];
2776             my $token              = $rtoken_vars->[_TOKEN_];
2777             my $type               = $rtoken_vars->[_TYPE_];
2778             my $last_type_sequence = $type_sequence;
2779             $type_sequence = $rtoken_vars->[_TYPE_SEQUENCE_];
2780
2781             # Handle a blank space ...
2782             if ( $type eq 'b' ) {
2783
2784                 # Delete it if not wanted by whitespace rules
2785                 # or we are deleting all whitespace
2786                 # Note that whitespace flag is a flag indicating whether a
2787                 # white space BEFORE the token is needed
2788                 next if ( $KK >= $Klast );    # skip terminal blank
2789                 my $Knext = $KK + 1;
2790                 my $ws    = $rwhitespace_flags->[$Knext];
2791                 if (   $ws == -1
2792                     || $rOpts_delete_old_whitespace )
2793                 {
2794
2795                     # FIXME: maybe switch to using _new
2796                     my $Kp = $self->K_previous_nonblank($KK);
2797                     next unless defined($Kp);
2798                     my $token_p = $rLL->[$Kp]->[_TOKEN_];
2799                     my $type_p  = $rLL->[$Kp]->[_TYPE_];
2800
2801                     my ( $token_pp, $type_pp );
2802
2803                     #my $Kpp = $K_previous_nonblank->($Kp);
2804                     my $Kpp = $self->K_previous_nonblank($Kp);
2805                     if ( defined($Kpp) ) {
2806                         $token_pp = $rLL->[$Kpp]->[_TOKEN_];
2807                         $type_pp  = $rLL->[$Kpp]->[_TYPE_];
2808                     }
2809                     else {
2810                         $token_pp = ";";
2811                         $type_pp  = ';';
2812                     }
2813                     my $token_next = $rLL->[$Knext]->[_TOKEN_];
2814                     my $type_next  = $rLL->[$Knext]->[_TYPE_];
2815
2816                     my $do_not_delete = is_essential_whitespace(
2817                         $token_pp, $type_pp,    $token_p,
2818                         $type_p,   $token_next, $type_next,
2819                     );
2820
2821                     next unless ($do_not_delete);
2822                 }
2823
2824                 # make it just one character if allowed
2825                 if ($rOpts_add_whitespace) {
2826                     $rtoken_vars->[_TOKEN_] = ' ';
2827                 }
2828                 $store_token->($rtoken_vars);
2829                 next;
2830             }
2831
2832             # Handle a nonblank token...
2833
2834             # check for a qw quote
2835             if ( $type eq 'q' ) {
2836
2837                 # trim blanks from right of qw quotes
2838                 # (To avoid trimming qw quotes use -ntqw; the tokenizer handles
2839                 # this)
2840                 $token =~ s/\s*$//;
2841                 $rtoken_vars->[_TOKEN_] = $token;
2842                 note_embedded_tab() if ( $token =~ "\t" );
2843
2844                 if ($in_multiline_qw) {
2845
2846                     # If we are at the end of a multiline qw ..
2847                     if ( $in_multiline_qw == $KK ) {
2848
2849                  # Split off the closing delimiter character
2850                  # so that the formatter can put a line break there if necessary
2851                         my $part1 = $token;
2852                         my $part2 = substr( $part1, -1, 1, "" );
2853
2854                         if ($part1) {
2855                             my $rcopy =
2856                               copy_token_as_type( $rtoken_vars, 'q', $part1 );
2857                             $store_token->($rcopy);
2858                             $token = $part2;
2859                             $rtoken_vars->[_TOKEN_] = $token;
2860
2861                         }
2862                         $in_multiline_qw = undef;
2863
2864                         # store without preceding blank
2865                         $store_token->($rtoken_vars);
2866                         next;
2867                     }
2868                     else {
2869                         # continuing a multiline qw
2870                         $store_token->($rtoken_vars);
2871                         next;
2872                     }
2873                 }
2874
2875                 else {
2876
2877                     # we are encountered new qw token...see if multiline
2878                     my $K_end = $K_end_q->($KK);
2879                     if ( $ALLOW_BREAK_MULTILINE_QW && $K_end != $KK ) {
2880
2881                         # Starting multiline qw...
2882                         # set flag equal to the ending K
2883                         $in_multiline_qw = $K_end;
2884
2885                  # Split off the leading part
2886                  # so that the formatter can put a line break there if necessary
2887                         if ( $token =~ /^(qw\s*.)(.*)$/ ) {
2888                             my $part1 = $1;
2889                             my $part2 = $2;
2890                             if ($part2) {
2891                                 my $rcopy =
2892                                   copy_token_as_type( $rtoken_vars, 'q',
2893                                     $part1 );
2894                                 $store_token_and_space->(
2895                                     $rcopy, $rwhitespace_flags->[$KK] == WS_YES
2896                                 );
2897                                 $token = $part2;
2898                                 $rtoken_vars->[_TOKEN_] = $token;
2899
2900                                 # Second part goes without intermediate blank
2901                                 $store_token->($rtoken_vars);
2902                                 next;
2903                             }
2904                         }
2905                     }
2906                     else {
2907
2908                         # this is a new single token qw -
2909                         # store with possible preceding blank
2910                         $store_token_and_space->(
2911                             $rtoken_vars, $rwhitespace_flags->[$KK] == WS_YES
2912                         );
2913                         next;
2914                     }
2915                 }
2916             } ## end if ( $type eq 'q' )
2917
2918             # Modify certain tokens here for whitespace
2919             # The following is not yet done, but could be:
2920             #   sub (x x x)
2921             elsif ( $type =~ /^[wit]$/ ) {
2922
2923                 # Examples: <<snippets/space1.in>>
2924                 # change '$  var'  to '$var' etc
2925                 #        '-> new'  to '->new'
2926                 if ( $token =~ /^([\$\&\%\*\@]|\-\>)\s/ ) {
2927                     $token =~ s/\s*//g;
2928                     $rtoken_vars->[_TOKEN_] = $token;
2929                 }
2930
2931                 # Split identifiers with leading arrows, inserting blanks if
2932                 # necessary.  It is easier and safer here than in the
2933                 # tokenizer.  For example '->new' becomes two tokens, '->' and
2934                 # 'new' with a possible blank between.
2935                 #
2936                 # Note: there is a related patch in sub set_whitespace_flags
2937                 if ( $token =~ /^\-\>(.*)$/ && $1 ) {
2938                     my $token_save = $1;
2939                     my $type_save  = $type;
2940
2941                     # store a blank to left of arrow if necessary
2942                     my $Kprev = $self->K_previous_nonblank($KK);
2943                     if (   defined($Kprev)
2944                         && $rLL->[$Kprev]->[_TYPE_] ne 'b'
2945                         && $rOpts_add_whitespace
2946                         && $want_left_space{'->'} == WS_YES )
2947                     {
2948                         my $rcopy =
2949                           copy_token_as_type( $rtoken_vars, 'b', ' ' );
2950                         $store_token->($rcopy);
2951                     }
2952
2953                     # then store the arrow
2954                     my $rcopy = copy_token_as_type( $rtoken_vars, '->', '->' );
2955                     $store_token->($rcopy);
2956
2957                     # then reset the current token to be the remainder,
2958                     # and reset the whitespace flag according to the arrow
2959                     $token = $rtoken_vars->[_TOKEN_] = $token_save;
2960                     $type  = $rtoken_vars->[_TYPE_]  = $type_save;
2961                     $store_token->($rtoken_vars);
2962                     next;
2963                 }
2964
2965                 if ( $token =~ /$SUB_PATTERN/ ) {
2966
2967                     # -spp = 0 : no space before opening prototype paren
2968                     # -spp = 1 : stable (follow input spacing)
2969                     # -spp = 2 : always space before opening prototype paren
2970                     my $spp = $rOpts->{'space-prototype-paren'};
2971                     if ( defined($spp) ) {
2972                         if    ( $spp == 0 ) { $token =~ s/\s+\(/\(/; }
2973                         elsif ( $spp == 2 ) { $token =~ s/\(/ (/; }
2974                     }
2975
2976                     # one space max, and no tabs
2977                     $token =~ s/\s+/ /g;
2978                     $rtoken_vars->[_TOKEN_] = $token;
2979                 }
2980
2981                 # trim identifiers of trailing blanks which can occur
2982                 # under some unusual circumstances, such as if the
2983                 # identifier 'witch' has trailing blanks on input here:
2984                 #
2985                 # sub
2986                 # witch
2987                 # ()   # prototype may be on new line ...
2988                 # ...
2989                 if ( $type eq 'i' ) {
2990                     $token =~ s/\s+$//g;
2991                     $rtoken_vars->[_TOKEN_] = $token;
2992                 }
2993             }
2994
2995             # change 'LABEL   :'   to 'LABEL:'
2996             elsif ( $type eq 'J' ) {
2997                 $token =~ s/\s+//g;
2998                 $rtoken_vars->[_TOKEN_] = $token;
2999             }
3000
3001             # patch to add space to something like "x10"
3002             # This avoids having to split this token in the pre-tokenizer
3003             elsif ( $type eq 'n' ) {
3004                 if ( $token =~ /^x\d+/ ) {
3005                     $token =~ s/x/x /;
3006                     $rtoken_vars->[_TOKEN_] = $token;
3007                 }
3008             }
3009
3010             # check a quote for problems
3011             elsif ( $type eq 'Q' ) {
3012                 $check_Q->( $KK, $Kfirst );
3013             }
3014
3015             # handle semicolons
3016             elsif ( $type eq ';' ) {
3017
3018                 # Remove unnecessary semicolons, but not after bare
3019                 # blocks, where it could be unsafe if the brace is
3020                 # mistokenized.
3021                 if (
3022                     $rOpts->{'delete-semicolons'}
3023                     && (
3024                         (
3025                             $last_nonblank_type eq '}'
3026                             && (
3027                                 $is_block_without_semicolon{
3028                                     $last_nonblank_block_type}
3029                                 || $last_nonblank_block_type =~ /$SUB_PATTERN/
3030                                 || $last_nonblank_block_type =~ /^\w+:$/ )
3031                         )
3032                         || $last_nonblank_type eq ';'
3033                     )
3034                   )
3035                 {
3036
3037                     # This looks like a deletable semicolon, but even if a
3038                     # semicolon can be deleted it is necessarily best to do so.
3039                     # We apply these additional rules for deletion:
3040                     # - Always ok to delete a ';' at the end of a line
3041                     # - Never delete a ';' before a '#' because it would
3042                     #   promote it to a block comment.
3043                     # - If a semicolon is not at the end of line, then only
3044                     #   delete if it is followed by another semicolon or closing
3045                     #   token.  This includes the comment rule.  It may take
3046                     #   two passes to get to a final state, but it is a little
3047                     #   safer.  For example, keep the first semicolon here:
3048                     #      eval { sub bubba { ok(0) }; ok(0) } || ok(1);
3049                     #   It is not required but adds some clarity.
3050                     my $ok_to_delete = 1;
3051                     if ( $KK < $Klast ) {
3052                         my $Kn = $self->K_next_nonblank($KK);
3053                         if ( defined($Kn) && $Kn <= $Klast ) {
3054                             my $next_nonblank_token_type =
3055                               $rLL->[$Kn]->[_TYPE_];
3056                             $ok_to_delete = $next_nonblank_token_type eq ';'
3057                               || $next_nonblank_token_type eq '}';
3058                         }
3059                     }
3060
3061                     if ($ok_to_delete) {
3062                         note_deleted_semicolon();
3063                         next;
3064                     }
3065                     else {
3066                         write_logfile_entry("Extra ';'\n");
3067                     }
3068                 }
3069             }
3070
3071             elsif ($type_sequence) {
3072
3073                 #                if ( $is_opening_token{$token} ) {
3074                 #                }
3075
3076                 if ( $is_closing_token{$token} ) {
3077
3078                     # Insert a tentative missing semicolon if the next token is
3079                     # a closing block brace
3080                     if (
3081                            $type eq '}'
3082                         && $token eq '}'
3083
3084                         # not preceded by a ';'
3085                         && $last_nonblank_type ne ';'
3086
3087                    # and this is not a VERSION stmt (is all one line, we are not
3088                    # inserting semicolons on one-line blocks)
3089                         && $CODE_type ne 'VER'
3090
3091                         # and we are allowed to add semicolons
3092                         && $rOpts->{'add-semicolons'}
3093                       )
3094                     {
3095                         $add_phantom_semicolon->($KK);
3096                     }
3097                 }
3098             }
3099
3100             # Store this token with possible previous blank
3101             $store_token_and_space->(
3102                 $rtoken_vars, $rwhitespace_flags->[$KK] == WS_YES
3103             );
3104
3105         }    # End token loop
3106     }    # End line loop
3107
3108     # Reset memory to be the new array
3109     $self->{rLL} = $rLL_new;
3110     $self->set_rLL_max_index();
3111     $self->{K_opening_container}   = $K_opening_container;
3112     $self->{K_closing_container}   = $K_closing_container;
3113     $self->{K_opening_ternary}     = $K_opening_ternary;
3114     $self->{K_closing_ternary}     = $K_closing_ternary;
3115     $self->{rK_phantom_semicolons} = $rK_phantom_semicolons;
3116
3117     # make sure the new array looks okay
3118     $self->check_token_array();
3119
3120     # reset the token limits of each line
3121     $self->resync_lines_and_tokens();
3122
3123     return;
3124 }
3125
3126 {    # scan_comments
3127
3128     my $Last_line_had_side_comment;
3129     my $In_format_skipping_section;
3130     my $Saw_VERSION_in_this_file;
3131
3132     sub scan_comments {
3133         my $self   = shift;
3134         my $rlines = $self->{rlines};
3135
3136         $Last_line_had_side_comment = undef;
3137         $In_format_skipping_section = undef;
3138         $Saw_VERSION_in_this_file   = undef;
3139
3140         # Loop over all lines
3141         foreach my $line_of_tokens ( @{$rlines} ) {
3142             my $line_type = $line_of_tokens->{_line_type};
3143             next unless ( $line_type eq 'CODE' );
3144             my $CODE_type = $self->get_CODE_type($line_of_tokens);
3145             $line_of_tokens->{_code_type} = $CODE_type;
3146         }
3147         return;
3148     }
3149
3150     sub get_CODE_type {
3151         my ( $self, $line_of_tokens ) = @_;
3152
3153         # We are looking at a line of code and setting a flag to
3154         # describe any special processing that it requires
3155
3156         # Possible CODE_types are as follows.
3157         # 'BL' = Blank Line
3158         # 'VB' = Verbatim - line goes out verbatim
3159         # 'IO' = Indent Only - line goes out unchanged except for indentation
3160         # 'NIN' = No Internal Newlines - line does not get broken
3161         # 'HSC'=Hanging Side Comment - fix this hanging side comment
3162         # 'BC'=Block Comment - an ordinary full line comment
3163         # 'SBC'=Static Block Comment - a block comment which does not get
3164         #      indented
3165         # 'SBCX'=Static Block Comment Without Leading Space
3166         # 'DEL'=Delete this line
3167         # 'VER'=VERSION statement
3168         # '' or (undefined) - no restructions
3169
3170         my $rLL    = $self->{rLL};
3171         my $Klimit = $self->{Klimit};
3172
3173         my $CODE_type            = $rOpts->{'indent-only'} ? 'IO' : "";
3174         my $no_internal_newlines = 1 - $rOpts_add_newlines;
3175         if ( !$CODE_type && $no_internal_newlines ) { $CODE_type = 'NIN' }
3176
3177         # extract what we need for this line..
3178
3179         # Global value for error messages:
3180         $input_line_number = $line_of_tokens->{_line_number};
3181
3182         my $rK_range = $line_of_tokens->{_rK_range};
3183         my ( $Kfirst, $Klast ) = @{$rK_range};
3184         my $jmax = -1;
3185         if ( defined($Kfirst) ) { $jmax = $Klast - $Kfirst }
3186         my $input_line         = $line_of_tokens->{_line_text};
3187         my $in_continued_quote = my $starting_in_quote =
3188           $line_of_tokens->{_starting_in_quote};
3189         my $in_quote        = $line_of_tokens->{_ending_in_quote};
3190         my $ending_in_quote = $in_quote;
3191         my $guessed_indentation_level =
3192           $line_of_tokens->{_guessed_indentation_level};
3193
3194         my $is_static_block_comment = 0;
3195
3196         # Handle a continued quote..
3197         if ($in_continued_quote) {
3198
3199             # A line which is entirely a quote or pattern must go out
3200             # verbatim.  Note: the \n is contained in $input_line.
3201             if ( $jmax <= 0 ) {
3202                 if ( ( $input_line =~ "\t" ) ) {
3203                     note_embedded_tab();
3204                 }
3205                 $Last_line_had_side_comment = 0;
3206                 return 'VB';
3207             }
3208         }
3209
3210         my $is_block_comment =
3211           ( $jmax == 0 && $rLL->[$Kfirst]->[_TYPE_] eq '#' );
3212
3213         # Write line verbatim if we are in a formatting skip section
3214         if ($In_format_skipping_section) {
3215             $Last_line_had_side_comment = 0;
3216
3217             # Note: extra space appended to comment simplifies pattern matching
3218             if ( $is_block_comment
3219                 && ( $rLL->[$Kfirst]->[_TOKEN_] . " " ) =~
3220                 /$format_skipping_pattern_end/o )
3221             {
3222                 $In_format_skipping_section = 0;
3223                 write_logfile_entry("Exiting formatting skip section\n");
3224             }
3225             return 'FS';
3226         }
3227
3228         # See if we are entering a formatting skip section
3229         if (   $rOpts_format_skipping
3230             && $is_block_comment
3231             && ( $rLL->[$Kfirst]->[_TOKEN_] . " " ) =~
3232             /$format_skipping_pattern_begin/o )
3233         {
3234             $In_format_skipping_section = 1;
3235             write_logfile_entry("Entering formatting skip section\n");
3236             $Last_line_had_side_comment = 0;
3237             return 'FS';
3238         }
3239
3240         # ignore trailing blank tokens (they will get deleted later)
3241         if ( $jmax > 0 && $rLL->[$Klast]->[_TYPE_] eq 'b' ) {
3242             $jmax--;
3243         }
3244
3245         # Handle a blank line..
3246         if ( $jmax < 0 ) {
3247             $Last_line_had_side_comment = 0;
3248             return 'BL';
3249         }
3250
3251         # see if this is a static block comment (starts with ## by default)
3252         my $is_static_block_comment_without_leading_space = 0;
3253         if (   $is_block_comment
3254             && $rOpts->{'static-block-comments'}
3255             && $input_line =~ /$static_block_comment_pattern/o )
3256         {
3257             $is_static_block_comment = 1;
3258             $is_static_block_comment_without_leading_space =
3259               substr( $input_line, 0, 1 ) eq '#';
3260         }
3261
3262         # Check for comments which are line directives
3263         # Treat exactly as static block comments without leading space
3264         # reference: perlsyn, near end, section Plain Old Comments (Not!)
3265         # example: '# line 42 "new_filename.plx"'
3266         if (
3267                $is_block_comment
3268             && $input_line =~ /^\#   \s*
3269                                line \s+ (\d+)   \s*
3270                                (?:\s("?)([^"]+)\2)? \s*
3271                                $/x
3272           )
3273         {
3274             $is_static_block_comment                       = 1;
3275             $is_static_block_comment_without_leading_space = 1;
3276         }
3277
3278         # look for hanging side comment
3279         if (
3280                $is_block_comment
3281             && $Last_line_had_side_comment  # last line had side comment
3282             && $input_line =~ /^\s/         # there is some leading space
3283             && !$is_static_block_comment    # do not make static comment hanging
3284             && $rOpts->{'hanging-side-comments'}    # user is allowing
3285                                                     # hanging side comments
3286                                                     # like this
3287           )
3288         {
3289             $Last_line_had_side_comment = 1;
3290             return 'HSC';
3291         }
3292
3293         # remember if this line has a side comment
3294         $Last_line_had_side_comment =
3295           ( $jmax > 0 && $rLL->[$Klast]->[_TYPE_] eq '#' );
3296
3297         # Handle a block (full-line) comment..
3298         if ($is_block_comment) {
3299
3300             if ( $rOpts->{'delete-block-comments'} ) { return 'DEL' }
3301
3302             # TRIM COMMENTS -- This could be turned off as a option
3303             $rLL->[$Kfirst]->[_TOKEN_] =~ s/\s*$//;    # trim right end
3304
3305             if ($is_static_block_comment_without_leading_space) {
3306                 return 'SBCX';
3307             }
3308             elsif ($is_static_block_comment) {
3309                 return 'SBC';
3310             }
3311             else {
3312                 return 'BC';
3313             }
3314         }
3315
3316         #   Patch needed for MakeMaker.  Do not break a statement
3317         #   in which $VERSION may be calculated.  See MakeMaker.pm;
3318         #   this is based on the coding in it.
3319         #   The first line of a file that matches this will be eval'd:
3320         #       /([\$*])(([\w\:\']*)\bVERSION)\b.*\=/
3321         #   Examples:
3322         #     *VERSION = \'1.01';
3323         #     ( $VERSION ) = '$Revision: 1.74 $ ' =~ /\$Revision:\s+([^\s]+)/;
3324         #   We will pass such a line straight through without breaking
3325         #   it unless -npvl is used.
3326
3327         #   Patch for problem reported in RT #81866, where files
3328         #   had been flattened into a single line and couldn't be
3329         #   tidied without -npvl.  There are two parts to this patch:
3330         #   First, it is not done for a really long line (80 tokens for now).
3331         #   Second, we will only allow up to one semicolon
3332         #   before the VERSION.  We need to allow at least one semicolon
3333         #   for statements like this:
3334         #      require Exporter;  our $VERSION = $Exporter::VERSION;
3335         #   where both statements must be on a single line for MakeMaker
3336
3337         my $is_VERSION_statement = 0;
3338         if (  !$Saw_VERSION_in_this_file
3339             && $jmax < 80
3340             && $input_line =~
3341             /^[^;]*;?[^;]*([\$*])(([\w\:\']*)\bVERSION)\b.*\=/ )
3342         {
3343             $Saw_VERSION_in_this_file = 1;
3344             write_logfile_entry("passing VERSION line; -npvl deactivates\n");
3345             $CODE_type = 'VER';
3346         }
3347         return $CODE_type;
3348     }
3349 }
3350
3351 sub find_nested_pairs {
3352     my $self = shift;
3353
3354     my $rLL = $self->{rLL};
3355     return unless ( defined($rLL) && @{$rLL} );
3356
3357     # We define an array of pairs of nested containers
3358     my @nested_pairs;
3359
3360     # We also set the following hash values to identify container pairs for
3361     # which the opening and closing tokens are adjacent in the token stream:
3362     # $rpaired_to_inner_container->{$seqno_out}=$seqno_in where $seqno_out and
3363     # $seqno_in are the seqence numbers of the outer and inner containers of
3364     # the pair We need these later to decide if we can insert a missing
3365     # semicolon
3366     my $rpaired_to_inner_container = {};
3367
3368     # This local hash remembers if an outer container has a close following
3369     # inner container;
3370     # The key is the outer sequence number
3371     # The value is the token_hash of the inner container
3372
3373     my %has_close_following_opening;
3374
3375     # Names of calling routines can either be marked as 'i' or 'w',
3376     # and they may invoke a sub call with an '->'. We will consider
3377     # any consecutive string of such types as a single unit when making
3378     # weld decisions.  We also allow a leading !
3379     my $is_name_type = {
3380         'i'  => 1,
3381         'w'  => 1,
3382         'U'  => 1,
3383         '->' => 1,
3384         '!'  => 1,
3385     };
3386
3387     my $is_name = sub {
3388         my $type = shift;
3389         return $type && $is_name_type->{$type};
3390     };
3391
3392     my $last_container;
3393     my $last_last_container;
3394     my $last_nonblank_token_vars;
3395     my $last_count;
3396
3397     my $nonblank_token_count = 0;
3398
3399     # loop over all tokens
3400     foreach my $rtoken_vars ( @{$rLL} ) {
3401
3402         my $type = $rtoken_vars->[_TYPE_];
3403
3404         next if ( $type eq 'b' );
3405
3406         # long identifier-like items are counted as a single item
3407         $nonblank_token_count++
3408           unless ( $is_name->($type)
3409             && $is_name->( $last_nonblank_token_vars->[_TYPE_] ) );
3410
3411         my $type_sequence = $rtoken_vars->[_TYPE_SEQUENCE_];
3412         if ($type_sequence) {
3413
3414             my $token = $rtoken_vars->[_TOKEN_];
3415
3416             if ( $is_opening_token{$token} ) {
3417
3418                 # following previous opening token ...
3419                 if (   $last_container
3420                     && $is_opening_token{ $last_container->[_TOKEN_] } )
3421                 {
3422
3423                     # adjacent to this one
3424                     my $tok_diff = $nonblank_token_count - $last_count;
3425
3426                     my $last_tok = $last_nonblank_token_vars->[_TOKEN_];
3427
3428                     if (   $tok_diff == 1
3429                         || $tok_diff == 2 && $last_container->[_TOKEN_] eq '(' )
3430                     {
3431
3432                         # remember this pair...
3433                         my $outer_seqno = $last_container->[_TYPE_SEQUENCE_];
3434                         my $inner_seqno = $type_sequence;
3435                         $has_close_following_opening{$outer_seqno} =
3436                           $rtoken_vars;
3437                     }
3438                 }
3439             }
3440
3441             elsif ( $is_closing_token{$token} ) {
3442
3443                 # if the corresponding opening token had an adjacent opening
3444                 if (   $has_close_following_opening{$type_sequence}
3445                     && $is_closing_token{ $last_container->[_TOKEN_] }
3446                     && $has_close_following_opening{$type_sequence}
3447                     ->[_TYPE_SEQUENCE_] == $last_container->[_TYPE_SEQUENCE_] )
3448                 {
3449
3450                     # The closing weld tokens must be adjacent
3451                     # NOTE: so intermediate commas and semicolons
3452                     # can currently block a weld.  This is something
3453                     # that could be fixed in the future by including
3454                     # a flag to delete un-necessary commas and semicolons.
3455                     my $tok_diff = $nonblank_token_count - $last_count;
3456
3457                     if ( $tok_diff == 1 ) {
3458
3459                         # This is a closely nested pair ..
3460                         my $inner_seqno = $last_container->[_TYPE_SEQUENCE_];
3461                         my $outer_seqno = $type_sequence;
3462                         $rpaired_to_inner_container->{$outer_seqno} =
3463                           $inner_seqno;
3464
3465                         push @nested_pairs, [ $inner_seqno, $outer_seqno ];
3466                     }
3467                 }
3468             }
3469
3470             $last_last_container = $last_container;
3471             $last_container      = $rtoken_vars;
3472             $last_count          = $nonblank_token_count;
3473         }
3474         $last_nonblank_token_vars = $rtoken_vars;
3475     }
3476     $self->{rnested_pairs}              = \@nested_pairs;
3477     $self->{rpaired_to_inner_container} = $rpaired_to_inner_container;
3478     return;
3479 }
3480
3481 sub dump_tokens {
3482
3483     # a debug routine, not normally used
3484     my ( $self, $msg ) = @_;
3485     my $rLL   = $self->{rLL};
3486     my $nvars = @{$rLL};
3487     print STDERR "$msg\n";
3488     print STDERR "ntokens=$nvars\n";
3489     print STDERR "K\t_TOKEN_\t_TYPE_\n";
3490     my $K = 0;
3491
3492     foreach my $item ( @{$rLL} ) {
3493         print STDERR "$K\t$item->[_TOKEN_]\t$item->[_TYPE_]\n";
3494         $K++;
3495     }
3496     return;
3497 }
3498
3499 sub get_old_line_index {
3500     my ( $self, $K ) = @_;
3501     my $rLL = $self->{rLL};
3502     return 0 unless defined($K);
3503     return $rLL->[$K]->[_LINE_INDEX_];
3504 }
3505
3506 sub get_old_line_count {
3507     my ( $self, $Kbeg, $Kend ) = @_;
3508     my $rLL = $self->{rLL};
3509     return 0 unless defined($Kbeg);
3510     return 0 unless defined($Kend);
3511     return $rLL->[$Kend]->[_LINE_INDEX_] - $rLL->[$Kbeg]->[_LINE_INDEX_] + 1;
3512 }
3513
3514 sub K_next_code {
3515     my ( $self, $KK, $rLL ) = @_;
3516
3517     # return the index K of the next nonblank, non-comment token
3518     return unless ( defined($KK) && $KK >= 0 );
3519
3520     # use the standard array unless given otherwise
3521     $rLL = $self->{rLL} unless ( defined($rLL) );
3522     my $Num  = @{$rLL};
3523     my $Knnb = $KK + 1;
3524     while ( $Knnb < $Num ) {
3525         if ( !defined( $rLL->[$Knnb] ) ) {
3526             Fault("Undefined entry for k=$Knnb");
3527         }
3528         if (   $rLL->[$Knnb]->[_TYPE_] ne 'b'
3529             && $rLL->[$Knnb]->[_TYPE_] ne '#' )
3530         {
3531             return $Knnb;
3532         }
3533         $Knnb++;
3534     }
3535     return;
3536 }
3537
3538 sub K_next_nonblank {
3539     my ( $self, $KK, $rLL ) = @_;
3540
3541     # return the index K of the next nonblank token
3542     return unless ( defined($KK) && $KK >= 0 );
3543
3544     # use the standard array unless given otherwise
3545     $rLL = $self->{rLL} unless ( defined($rLL) );
3546     my $Num  = @{$rLL};
3547     my $Knnb = $KK + 1;
3548     while ( $Knnb < $Num ) {
3549         if ( !defined( $rLL->[$Knnb] ) ) {
3550             Fault("Undefined entry for k=$Knnb");
3551         }
3552         if ( $rLL->[$Knnb]->[_TYPE_] ne 'b' ) { return $Knnb }
3553         $Knnb++;
3554     }
3555     return;
3556 }
3557
3558 sub K_previous_code {
3559
3560     # return the index K of the previous nonblank, non-comment token
3561     # Call with $KK=undef to start search at the top of the array
3562     my ( $self, $KK, $rLL ) = @_;
3563
3564     # use the standard array unless given otherwise
3565     $rLL = $self->{rLL} unless ( defined($rLL) );
3566     my $Num = @{$rLL};
3567     if ( !defined($KK) ) { $KK = $Num }
3568     elsif ( $KK > $Num ) {
3569
3570         # The caller should make the first call with KK_new=undef to
3571         # avoid this error
3572         Fault(
3573 "Program Bug: K_previous_nonblank_new called with K=$KK which exceeds $Num"
3574         );
3575     }
3576     my $Kpnb = $KK - 1;
3577     while ( $Kpnb >= 0 ) {
3578         if (   $rLL->[$Kpnb]->[_TYPE_] ne 'b'
3579             && $rLL->[$Kpnb]->[_TYPE_] ne '#' )
3580         {
3581             return $Kpnb;
3582         }
3583         $Kpnb--;
3584     }
3585     return;
3586 }
3587
3588 sub K_previous_nonblank {
3589
3590     # return index of previous nonblank token before item K;
3591     # Call with $KK=undef to start search at the top of the array
3592     my ( $self, $KK, $rLL ) = @_;
3593
3594     # use the standard array unless given otherwise
3595     $rLL = $self->{rLL} unless ( defined($rLL) );
3596     my $Num = @{$rLL};
3597     if ( !defined($KK) ) { $KK = $Num }
3598     elsif ( $KK > $Num ) {
3599
3600         # The caller should make the first call with KK_new=undef to
3601         # avoid this error
3602         Fault(
3603 "Program Bug: K_previous_nonblank_new called with K=$KK which exceeds $Num"
3604         );
3605     }
3606     my $Kpnb = $KK - 1;
3607     while ( $Kpnb >= 0 ) {
3608         if ( $rLL->[$Kpnb]->[_TYPE_] ne 'b' ) { return $Kpnb }
3609         $Kpnb--;
3610     }
3611     return;
3612 }
3613
3614 sub map_containers {
3615
3616     # Maps the container hierarchy
3617     my $self = shift;
3618     my $rLL  = $self->{rLL};
3619     return unless ( defined($rLL) && @{$rLL} );
3620
3621     my $K_opening_container = $self->{K_opening_container};
3622     my $K_closing_container = $self->{K_closing_container};
3623     my $rcontainer_map      = $self->{rcontainer_map};
3624
3625     # loop over containers
3626     my @stack;    # stack of container sequence numbers
3627     my $KNEXT = 0;
3628     while ( defined($KNEXT) ) {
3629         my $KK = $KNEXT;
3630         $KNEXT = $rLL->[$KNEXT]->[_KNEXT_SEQ_ITEM_];
3631         my $rtoken_vars   = $rLL->[$KK];
3632         my $type_sequence = $rtoken_vars->[_TYPE_SEQUENCE_];
3633         if ( !$type_sequence ) {
3634             next if ( $KK == 0 );    # first token in file may not be container
3635             Fault("sequence = $type_sequence not defined at K=$KK");
3636         }
3637
3638         my $token = $rtoken_vars->[_TOKEN_];
3639         if ( $is_opening_token{$token} ) {
3640             if (@stack) {
3641                 $rcontainer_map->{$type_sequence} = $stack[-1];
3642             }
3643             push @stack, $type_sequence;
3644         }
3645         if ( $is_closing_token{$token} ) {
3646             if (@stack) {
3647                 my $seqno = pop @stack;
3648                 if ( $seqno != $type_sequence ) {
3649
3650                     # shouldn't happen unless file is garbage
3651                 }
3652             }
3653         }
3654     }
3655
3656     # the stack should be empty for a good file
3657     if (@stack) {
3658
3659         # unbalanced containers; file probably bad
3660     }
3661     else {
3662         # ok
3663     }
3664     return;
3665 }
3666
3667 sub mark_short_nested_blocks {
3668
3669     # This routine looks at the entire file and marks any short nested blocks
3670     # which should not be broken.  The results are stored in the hash
3671     #     $rshort_nested->{$type_sequence}
3672     # which will be true if the container should remain intact.
3673     #
3674     # For example, consider the following line:
3675
3676     #   sub cxt_two { sort { $a <=> $b } test_if_list() }
3677
3678     # The 'sort' block is short and nested within an outer sub block.
3679     # Normally, the existance of the 'sort' block will force the sub block to
3680     # break open, but this is not always desirable. Here we will set a flag for
3681     # the sort block to prevent this.  To give the user control, we will
3682     # follow the input file formatting.  If either of the blocks is broken in
3683     # the input file then we will allow it to remain broken. Otherwise we will
3684     # set a flag to keep it together in later formatting steps.
3685
3686     # The flag which is set here will be checked in two places:
3687     # 'sub print_line_of_tokens' and 'sub starting_one_line_block'
3688
3689     my $self = shift;
3690     my $rLL  = $self->{rLL};
3691     return unless ( defined($rLL) && @{$rLL} );
3692
3693     return unless ( $rOpts->{'one-line-block-nesting'} );
3694
3695     my $K_opening_container = $self->{K_opening_container};
3696     my $K_closing_container = $self->{K_closing_container};
3697     my $rbreak_container    = $self->{rbreak_container};
3698     my $rshort_nested       = $self->{rshort_nested};
3699     my $rcontainer_map      = $self->{rcontainer_map};
3700     my $rlines              = $self->{rlines};
3701
3702     # Variables needed for estimating line lengths
3703     my $starting_indent;
3704     my $starting_lentot;
3705     my $length_tol = 1;
3706
3707     my $excess_length_to_K = sub {
3708         my ($K) = @_;
3709
3710         # Estimate the length from the line start to a given token
3711         my $length = $self->cumulative_length_before_K($K) - $starting_lentot;
3712         my $excess_length =
3713           $starting_indent + $length + $length_tol - $rOpts_maximum_line_length;
3714         return ($excess_length);
3715     };
3716
3717     my $is_broken_block = sub {
3718
3719         # a block is broken if the input line numbers of the braces differ
3720         my ($seqno) = @_;
3721         my $K_opening = $K_opening_container->{$seqno};
3722         return unless ( defined($K_opening) );
3723         my $K_closing = $K_closing_container->{$seqno};
3724         return unless ( defined($K_closing) );
3725         return $rbreak_container->{$seqno}
3726           || $rLL->[$K_closing]->[_LINE_INDEX_] !=
3727           $rLL->[$K_opening]->[_LINE_INDEX_];
3728     };
3729
3730     # loop over all containers
3731     my @open_block_stack;
3732     my $iline = -1;
3733     my $KNEXT = 0;
3734     while ( defined($KNEXT) ) {
3735         my $KK = $KNEXT;
3736         $KNEXT = $rLL->[$KNEXT]->[_KNEXT_SEQ_ITEM_];
3737         my $rtoken_vars   = $rLL->[$KK];
3738         my $type_sequence = $rtoken_vars->[_TYPE_SEQUENCE_];
3739         if ( !$type_sequence ) {
3740             next if ( $KK == 0 );    # first token in file may not be container
3741
3742             # an error here is most likely due to a recent programming change
3743             Fault("sequence = $type_sequence not defined at K=$KK");
3744         }
3745
3746         # We are just looking at code blocks
3747         my $token = $rtoken_vars->[_TOKEN_];
3748         my $type  = $rtoken_vars->[_TYPE_];
3749         next unless ( $type eq $token );
3750         my $block_type = $rtoken_vars->[_BLOCK_TYPE_];
3751         next unless ($block_type);
3752
3753         # Keep a stack of all acceptable block braces seen.
3754         # Only consider blocks entirely on one line so dump the stack when line
3755         # changes.
3756         my $iline_last = $iline;
3757         $iline = $rLL->[$KK]->[_LINE_INDEX_];
3758         if ( $iline != $iline_last ) { @open_block_stack = () }
3759
3760         if ( $token eq '}' ) {
3761             if (@open_block_stack) { pop @open_block_stack }
3762         }
3763         next unless ( $token eq '{' );
3764
3765         # block must be balanced (bad scripts may be unbalanced)
3766         my $K_opening = $K_opening_container->{$type_sequence};
3767         my $K_closing = $K_closing_container->{$type_sequence};
3768         next unless ( defined($K_opening) && defined($K_closing) );
3769
3770         # require that this block be entirely on one line
3771         next if ( $is_broken_block->($type_sequence) );
3772
3773         # See if this block fits on one line of allowed length (which may
3774         # be different from the input script)
3775         $starting_lentot =
3776           $KK <= 0 ? 0 : $rLL->[ $KK - 1 ]->[_CUMULATIVE_LENGTH_];
3777         $starting_indent = 0;
3778         if ( !$rOpts_variable_maximum_line_length ) {
3779             my $level = $rLL->[$KK]->[_LEVEL_];
3780             $starting_indent = $rOpts_indent_columns * $level;
3781         }
3782
3783         # Dump the stack if block is too long and skip this block
3784         if ( $excess_length_to_K->($K_closing) > 0 ) {
3785             @open_block_stack = ();
3786             next;
3787         }
3788
3789         # OK, Block passes tests, remember it
3790         push @open_block_stack, $type_sequence;
3791
3792         # We are only marking nested code blocks,
3793         # so check for a previous block on the stack
3794         next unless ( @open_block_stack > 1 );
3795
3796         # Looks OK, mark this as a short nested block
3797         $rshort_nested->{$type_sequence} = 1;
3798
3799     }
3800     return;
3801 }
3802
3803 sub weld_containers {
3804
3805     # do any welding operations
3806     my $self = shift;
3807
3808   # initialize weld length hashes needed later for checking line lengths
3809   # TODO: These should eventually be stored in $self rather than be package vars
3810     %weld_len_left_closing  = ();
3811     %weld_len_right_closing = ();
3812     %weld_len_left_opening  = ();
3813     %weld_len_right_opening = ();
3814
3815     return if ( $rOpts->{'indent-only'} );
3816     return unless ($rOpts_add_newlines);
3817
3818     if ( $rOpts->{'weld-nested-containers'} ) {
3819
3820         # if called, weld_nested_containers must be called before other weld
3821         # operations.  # This is because weld_nested_containers could overwrite
3822         # hash values written by weld_cuddled_blocks and weld_nested_quotes.
3823         $self->weld_nested_containers();
3824
3825         $self->weld_nested_quotes();
3826     }
3827
3828     # Note that weld_nested_containers() changes the _LEVEL_ values, so
3829     # weld_cuddled_blocks must use the _TRUE_LEVEL_ values instead.
3830
3831     # Here is a good test case to  Be sure that both cuddling and welding
3832     # are working and not interfering with each other: <<snippets/ce_wn1.in>>
3833
3834     #   perltidy -wn -ce
3835
3836    # if ($BOLD_MATH) { (
3837    #     $labels, $comment,
3838    #     join( '', '<B>', &make_math( $mode, '', '', $_ ), '</B>' )
3839    # ) } else { (
3840    #     &process_math_in_latex( $mode, $math_style, $slevel, "\\mbox{$text}" ),
3841    #     $after
3842    # ) }
3843
3844     $self->weld_cuddled_blocks();
3845
3846     return;
3847 }
3848
3849 sub cumulative_length_before_K {
3850     my ( $self, $KK ) = @_;
3851     my $rLL = $self->{rLL};
3852     return ( $KK <= 0 ) ? 0 : $rLL->[ $KK - 1 ]->[_CUMULATIVE_LENGTH_];
3853 }
3854
3855 sub cumulative_length_after_K {
3856     my ( $self, $KK ) = @_;
3857     my $rLL = $self->{rLL};
3858     return $rLL->[$KK]->[_CUMULATIVE_LENGTH_];
3859 }
3860
3861 sub weld_cuddled_blocks {
3862     my $self = shift;
3863
3864     # This routine implements the -cb flag by finding the appropriate
3865     # closing and opening block braces and welding them together.
3866     return unless ( %{$rcuddled_block_types} );
3867
3868     my $rLL = $self->{rLL};
3869     return unless ( defined($rLL) && @{$rLL} );
3870     my $rbreak_container = $self->{rbreak_container};
3871
3872     my $K_opening_container = $self->{K_opening_container};
3873     my $K_closing_container = $self->{K_closing_container};
3874
3875     my $length_to_opening_seqno = sub {
3876         my ($seqno) = @_;
3877         my $KK      = $K_opening_container->{$seqno};
3878         my $lentot  = $KK <= 0 ? 0 : $rLL->[ $KK - 1 ]->[_CUMULATIVE_LENGTH_];
3879         return $lentot;
3880     };
3881     my $length_to_closing_seqno = sub {
3882         my ($seqno) = @_;
3883         my $KK      = $K_closing_container->{$seqno};
3884         my $lentot  = $KK <= 0 ? 0 : $rLL->[ $KK - 1 ]->[_CUMULATIVE_LENGTH_];
3885         return $lentot;
3886     };
3887
3888     my $is_broken_block = sub {
3889
3890         # a block is broken if the input line numbers of the braces differ
3891         # we can only cuddle between broken blocks
3892         my ($seqno) = @_;
3893         my $K_opening = $K_opening_container->{$seqno};
3894         return unless ( defined($K_opening) );
3895         my $K_closing = $K_closing_container->{$seqno};
3896         return unless ( defined($K_closing) );
3897         return $rbreak_container->{$seqno}
3898           || $rLL->[$K_closing]->[_LINE_INDEX_] !=
3899           $rLL->[$K_opening]->[_LINE_INDEX_];
3900     };
3901
3902     # A stack to remember open chains at all levels:
3903     # $in_chain[$level] = [$chain_type, $type_sequence];
3904     my @in_chain;
3905     my $CBO = $rOpts->{'cuddled-break-option'};
3906
3907     # loop over structure items to find cuddled pairs
3908     my $level = 0;
3909     my $KNEXT = 0;
3910     while ( defined($KNEXT) ) {
3911         my $KK = $KNEXT;
3912         $KNEXT = $rLL->[$KNEXT]->[_KNEXT_SEQ_ITEM_];
3913         my $rtoken_vars   = $rLL->[$KK];
3914         my $type_sequence = $rtoken_vars->[_TYPE_SEQUENCE_];
3915         if ( !$type_sequence ) {
3916             next if ( $KK == 0 );    # first token in file may not be container
3917             Fault("sequence = $type_sequence not defined at K=$KK");
3918         }
3919
3920         # We use the original levels because they get changed by sub
3921         # 'weld_nested_containers'. So if this were to be called before that
3922         # routine, the levels would be wrong and things would go bad.
3923         my $last_level = $level;
3924         $level = $rtoken_vars->[_LEVEL_TRUE_];
3925
3926         if    ( $level < $last_level ) { $in_chain[$last_level] = undef }
3927         elsif ( $level > $last_level ) { $in_chain[$level]      = undef }
3928
3929         # We are only looking at code blocks
3930         my $token = $rtoken_vars->[_TOKEN_];
3931         my $type  = $rtoken_vars->[_TYPE_];
3932         next unless ( $type eq $token );
3933
3934         if ( $token eq '{' ) {
3935
3936             my $block_type = $rtoken_vars->[_BLOCK_TYPE_];
3937             if ( !$block_type ) {
3938
3939                 # patch for unrecognized block types which may not be labeled
3940                 my $Kp = $self->K_previous_nonblank($KK);
3941                 while ( $Kp && $rLL->[$Kp]->[_TYPE_] eq '#' ) {
3942                     $Kp = $self->K_previous_nonblank($Kp);
3943                 }
3944                 next unless $Kp;
3945                 $block_type = $rLL->[$Kp]->[_TOKEN_];
3946             }
3947             if ( $in_chain[$level] ) {
3948
3949                 # we are in a chain and are at an opening block brace.
3950                 # See if we are welding this opening brace with the previous
3951                 # block brace.  Get their identification numbers:
3952                 my $closing_seqno = $in_chain[$level]->[1];
3953                 my $opening_seqno = $type_sequence;
3954
3955                 # The preceding block must be on multiple lines so that its
3956                 # closing brace will start a new line.
3957                 if ( !$is_broken_block->($closing_seqno) ) {
3958                     next unless ( $CBO == 2 );
3959                     $rbreak_container->{$closing_seqno} = 1;
3960                 }
3961
3962                 # we will let the trailing block be either broken or intact
3963                 ## && $is_broken_block->($opening_seqno);
3964
3965                 # We can weld the closing brace to its following word ..
3966                 my $Ko  = $K_closing_container->{$closing_seqno};
3967                 my $Kon = $self->K_next_nonblank($Ko);
3968
3969                 # ..unless it is a comment
3970                 if ( $rLL->[$Kon]->[_TYPE_] ne '#' ) {
3971                     my $dlen =
3972                       $rLL->[$Kon]->[_CUMULATIVE_LENGTH_] -
3973                       $rLL->[ $Ko - 1 ]->[_CUMULATIVE_LENGTH_];
3974                     $weld_len_right_closing{$closing_seqno} = $dlen;
3975
3976                     # Set flag that we want to break the next container
3977                     # so that the cuddled line is balanced.
3978                     $rbreak_container->{$opening_seqno} = 1
3979                       if ($CBO);
3980                 }
3981
3982             }
3983             else {
3984
3985                 # We are not in a chain. Start a new chain if we see the
3986                 # starting block type.
3987                 if ( $rcuddled_block_types->{$block_type} ) {
3988                     $in_chain[$level] = [ $block_type, $type_sequence ];
3989                 }
3990                 else {
3991                     $block_type = '*';
3992                     $in_chain[$level] = [ $block_type, $type_sequence ];
3993                 }
3994             }
3995         }
3996         elsif ( $token eq '}' ) {
3997             if ( $in_chain[$level] ) {
3998
3999                 # We are in a chain at a closing brace.  See if this chain
4000                 # continues..
4001                 my $Knn = $self->K_next_code($KK);
4002                 next unless $Knn;
4003
4004                 my $chain_type          = $in_chain[$level]->[0];
4005                 my $next_nonblank_token = $rLL->[$Knn]->[_TOKEN_];
4006                 if (
4007                     $rcuddled_block_types->{$chain_type}->{$next_nonblank_token}
4008                   )
4009                 {
4010
4011                     # Note that we do not weld yet because we must wait until
4012                     # we we are sure that an opening brace for this follows.
4013                     $in_chain[$level]->[1] = $type_sequence;
4014                 }
4015                 else { $in_chain[$level] = undef }
4016             }
4017         }
4018     }
4019
4020     return;
4021 }
4022
4023 sub weld_nested_containers {
4024     my $self = shift;
4025
4026     # This routine implements the -wn flag by "welding together"
4027     # the nested closing and opening tokens which were previously
4028     # identified by sub 'find_nested_pairs'.  "welding" simply
4029     # involves setting certain hash values which will be checked
4030     # later during formatting.
4031
4032     my $rLL                 = $self->{rLL};
4033     my $Klimit              = $self->get_rLL_max_index();
4034     my $rnested_pairs       = $self->{rnested_pairs};
4035     my $rlines              = $self->{rlines};
4036     my $K_opening_container = $self->{K_opening_container};
4037     my $K_closing_container = $self->{K_closing_container};
4038
4039     # Return unless there are nested pairs to weld
4040     return unless defined($rnested_pairs) && @{$rnested_pairs};
4041
4042     # This array will hold the sequence numbers of the tokens to be welded.
4043     my @welds;
4044
4045     # Variables needed for estimating line lengths
4046     my $starting_indent;
4047     my $starting_lentot;
4048
4049     # A tolerance to the length for length estimates.  In some rare cases
4050     # this can avoid problems where a final weld slightly exceeds the
4051     # line length and gets broken in a bad spot.
4052     my $length_tol = 1;
4053
4054     my $excess_length_to_K = sub {
4055         my ($K) = @_;
4056
4057         # Estimate the length from the line start to a given token
4058         my $length = $self->cumulative_length_before_K($K) - $starting_lentot;
4059         my $excess_length =
4060           $starting_indent + $length + $length_tol - $rOpts_maximum_line_length;
4061         return ($excess_length);
4062     };
4063
4064     my $length_to_opening_seqno = sub {
4065         my ($seqno) = @_;
4066         my $KK      = $K_opening_container->{$seqno};
4067         my $lentot  = $KK <= 0 ? 0 : $rLL->[ $KK - 1 ]->[_CUMULATIVE_LENGTH_];
4068         return $lentot;
4069     };
4070
4071     my $length_to_closing_seqno = sub {
4072         my ($seqno) = @_;
4073         my $KK      = $K_closing_container->{$seqno};
4074         my $lentot  = $KK <= 0 ? 0 : $rLL->[ $KK - 1 ]->[_CUMULATIVE_LENGTH_];
4075         return $lentot;
4076     };
4077
4078     # Abbreviations:
4079     #  _oo=outer opening, i.e. first of  { {
4080     #  _io=inner opening, i.e. second of { {
4081     #  _oc=outer closing, i.e. second of } {
4082     #  _ic=inner closing, i.e. first of  } }
4083
4084     my $previous_pair;
4085
4086     # We are working from outermost to innermost pairs so that
4087     # level changes will be complete when we arrive at the inner pairs.
4088
4089     while ( my $item = pop( @{$rnested_pairs} ) ) {
4090         my ( $inner_seqno, $outer_seqno ) = @{$item};
4091
4092         my $Kouter_opening = $K_opening_container->{$outer_seqno};
4093         my $Kinner_opening = $K_opening_container->{$inner_seqno};
4094         my $Kouter_closing = $K_closing_container->{$outer_seqno};
4095         my $Kinner_closing = $K_closing_container->{$inner_seqno};
4096
4097         my $outer_opening = $rLL->[$Kouter_opening];
4098         my $inner_opening = $rLL->[$Kinner_opening];
4099         my $outer_closing = $rLL->[$Kouter_closing];
4100         my $inner_closing = $rLL->[$Kinner_closing];
4101
4102         my $iline_oo = $outer_opening->[_LINE_INDEX_];
4103         my $iline_io = $inner_opening->[_LINE_INDEX_];
4104
4105         # Set flag saying if this pair starts a new weld
4106         my $starting_new_weld = !( @welds && $outer_seqno == $welds[-1]->[0] );
4107
4108         # Set flag saying if this pair is adjacent to the previous nesting pair
4109         # (even if previous pair was rejected as a weld)
4110         my $touch_previous_pair =
4111           defined($previous_pair) && $outer_seqno == $previous_pair->[0];
4112         $previous_pair = $item;
4113
4114         # Set a flag if we should not weld. It sometimes looks best not to weld
4115         # when the opening and closing tokens are very close.  However, there
4116         # is a danger that we will create a "blinker", which oscillates between
4117         # two semi-stable states, if we do not weld.  So the rules for
4118         # not welding have to be carefully defined and tested.
4119         my $do_not_weld;
4120         if ( !$touch_previous_pair ) {
4121
4122             # If this pair is not adjacent to the previous pair (skipped or
4123             # not), then measure lengths from the start of line of oo
4124
4125             my $rK_range = $rlines->[$iline_oo]->{_rK_range};
4126             my ( $Kfirst, $Klast ) = @{$rK_range};
4127             $starting_lentot =
4128               $Kfirst <= 0 ? 0 : $rLL->[ $Kfirst - 1 ]->[_CUMULATIVE_LENGTH_];
4129             $starting_indent = 0;
4130             if ( !$rOpts_variable_maximum_line_length ) {
4131                 my $level = $rLL->[$Kfirst]->[_LEVEL_];
4132                 $starting_indent = $rOpts_indent_columns * $level;
4133             }
4134
4135             # DO-NOT-WELD RULE 1:
4136             # Do not weld something that looks like the start of a two-line
4137             # function call, like this: <<snippets/wn6.in>>
4138             #    $trans->add_transformation(
4139             #        PDL::Graphics::TriD::Scale->new( $sx, $sy, $sz ) );
4140             # We will look for a semicolon after the closing paren.
4141
4142             # We want to weld something complex, like this though
4143             # my $compass = uc( opposite_direction( line_to_canvas_direction(
4144             #     @{ $coords[0] }, @{ $coords[1] } ) ) );
4145             # Otherwise we will get a 'blinker'
4146
4147             my $iline_oc = $outer_closing->[_LINE_INDEX_];
4148             if ( $iline_oc <= $iline_oo + 1 ) {
4149
4150                 # Look for following semicolon...
4151                 my $Knext_nonblank = $self->K_next_nonblank($Kouter_closing);
4152                 my $next_nonblank_type =
4153                   defined($Knext_nonblank)
4154                   ? $rLL->[$Knext_nonblank]->[_TYPE_]
4155                   : 'b';
4156                 if ( $next_nonblank_type eq ';' ) {
4157
4158                     # Then do not weld if no other containers between inner
4159                     # opening and closing.
4160                     my $Knext_seq_item = $inner_opening->[_KNEXT_SEQ_ITEM_];
4161                     if ( $Knext_seq_item == $Kinner_closing ) {
4162                         $do_not_weld ||= 1;
4163                     }
4164                 }
4165             }
4166         }
4167
4168         my $iline_ic = $inner_closing->[_LINE_INDEX_];
4169
4170         # DO-NOT-WELD RULE 2:
4171         # Do not weld an opening paren to an inner one line brace block
4172         # We will just use old line numbers for this test and require
4173         # iterations if necessary for convergence
4174
4175         # For example, otherwise we could cause the opening paren
4176         # in the following example to separate from the caller name
4177         # as here:
4178
4179         #    $_[0]->code_handler
4180         #       ( sub { $more .= $_[1] . ":" . $_[0] . "\n" } );
4181
4182         # Here is another example where we do not want to weld:
4183         #  $wrapped->add_around_modifier(
4184         #    sub { push @tracelog => 'around 1'; $_[0]->(); } );
4185
4186         # If the one line sub block gets broken due to length or by the
4187         # user, then we can weld.  The result will then be:
4188         # $wrapped->add_around_modifier( sub {
4189         #    push @tracelog => 'around 1';
4190         #    $_[0]->();
4191         # } );
4192
4193         if ( $iline_ic == $iline_io ) {
4194
4195             my $token_oo      = $outer_opening->[_TOKEN_];
4196             my $block_type_io = $inner_opening->[_BLOCK_TYPE_];
4197             my $token_io      = $inner_opening->[_TOKEN_];
4198             $do_not_weld ||= $token_oo eq '(' && $token_io eq '{';
4199         }
4200
4201         # DO-NOT-WELD RULE 3:
4202         # Do not weld if this makes our line too long
4203         $do_not_weld ||= $excess_length_to_K->($Kinner_opening) > 0;
4204
4205         # DO-NOT-WELD RULE 4; implemented for git#10:
4206         # Do not weld an opening -ce brace if the next container is on a single
4207         # line, different from the opening brace. (This is very rare).  For
4208         # example, given the following with -ce, we will avoid joining the {
4209         # and [
4210
4211         #  } else {
4212         #      [ $_, length($_) ]
4213         #  }
4214
4215         # because this would produce a terminal one-line block:
4216
4217         #  } else { [ $_, length($_) ]  }
4218
4219         # which may not be what is desired. But given this input:
4220
4221         #  } else { [ $_, length($_) ]  }
4222
4223         # then we will do the weld and retain the one-line block
4224         if ( $rOpts->{'cuddled-else'} ) {
4225             my $block_type = $rLL->[$Kouter_opening]->[_BLOCK_TYPE_];
4226             if ( $block_type && $rcuddled_block_types->{'*'}->{$block_type} ) {
4227                 my $io_line = $inner_opening->[_LINE_INDEX_];
4228                 my $ic_line = $inner_closing->[_LINE_INDEX_];
4229                 my $oo_line = $outer_opening->[_LINE_INDEX_];
4230                 $do_not_weld ||=
4231                   ( $oo_line < $io_line && $ic_line == $io_line );
4232             }
4233         }
4234
4235         if ($do_not_weld) {
4236
4237             # After neglecting a pair, we start measuring from start of point io
4238             $starting_lentot =
4239               $self->cumulative_length_before_K($Kinner_opening);
4240             $starting_indent = 0;
4241             if ( !$rOpts_variable_maximum_line_length ) {
4242                 my $level = $inner_opening->[_LEVEL_];
4243                 $starting_indent = $rOpts_indent_columns * $level;
4244             }
4245
4246             # Normally, a broken pair should not decrease indentation of
4247             # intermediate tokens:
4248             ##      if ( $last_pair_broken ) { next }
4249             # However, for long strings of welded tokens, such as '{{{{{{...'
4250             # we will allow broken pairs to also remove indentation.
4251             # This will keep very long strings of opening and closing
4252             # braces from marching off to the right.  We will do this if the
4253             # number of tokens in a weld before the broken weld is 4 or more.
4254             # This rule will mainly be needed for test scripts, since typical
4255             # welds have fewer than about 4 welded tokens.
4256             if ( !@welds || @{ $welds[-1] } < 4 ) { next }
4257         }
4258
4259         # otherwise start new weld ...
4260         elsif ($starting_new_weld) {
4261             push @welds, $item;
4262         }
4263
4264         # ... or extend current weld
4265         else {
4266             unshift @{ $welds[-1] }, $inner_seqno;
4267         }
4268
4269         # After welding, reduce the indentation level if all intermediate tokens
4270         my $dlevel = $outer_opening->[_LEVEL_] - $inner_opening->[_LEVEL_];
4271         if ( $dlevel != 0 ) {
4272             my $Kstart = $Kinner_opening;
4273             my $Kstop  = $Kinner_closing;
4274             for ( my $KK = $Kstart ; $KK <= $Kstop ; $KK++ ) {
4275                 $rLL->[$KK]->[_LEVEL_] += $dlevel;
4276             }
4277         }
4278     }
4279
4280     # Define weld lengths needed later to set line breaks
4281     foreach my $item (@welds) {
4282
4283         # sweep from inner to outer
4284
4285         my $inner_seqno;
4286         my $len_close = 0;
4287         my $len_open  = 0;
4288         foreach my $outer_seqno ( @{$item} ) {
4289             if ($inner_seqno) {
4290
4291                 my $dlen_opening =
4292                   $length_to_opening_seqno->($inner_seqno) -
4293                   $length_to_opening_seqno->($outer_seqno);
4294
4295                 my $dlen_closing =
4296                   $length_to_closing_seqno->($outer_seqno) -
4297                   $length_to_closing_seqno->($inner_seqno);
4298
4299                 $len_open  += $dlen_opening;
4300                 $len_close += $dlen_closing;
4301
4302             }
4303
4304             $weld_len_left_closing{$outer_seqno}  = $len_close;
4305             $weld_len_right_opening{$outer_seqno} = $len_open;
4306
4307             $inner_seqno = $outer_seqno;
4308         }
4309
4310         # sweep from outer to inner
4311         foreach my $seqno ( reverse @{$item} ) {
4312             $weld_len_right_closing{$seqno} =
4313               $len_close - $weld_len_left_closing{$seqno};
4314             $weld_len_left_opening{$seqno} =
4315               $len_open - $weld_len_right_opening{$seqno};
4316         }
4317     }
4318
4319     #####################################
4320     # DEBUG
4321     #####################################
4322     if (0) {
4323         my $count = 0;
4324         local $" = ')(';
4325         foreach my $weld (@welds) {
4326             print "\nWeld number $count has seq: (@{$weld})\n";
4327             foreach my $seq ( @{$weld} ) {
4328                 print <<EOM;
4329         seq=$seq
4330         left_opening=$weld_len_left_opening{$seq};
4331         right_opening=$weld_len_right_opening{$seq};
4332         left_closing=$weld_len_left_closing{$seq};
4333         right_closing=$weld_len_right_closing{$seq};
4334 EOM
4335             }
4336
4337             $count++;
4338         }
4339     }
4340     return;
4341 }
4342
4343 sub weld_nested_quotes {
4344     my $self = shift;
4345
4346     my $rLL = $self->{rLL};
4347     return unless ( defined($rLL) && @{$rLL} );
4348
4349     my $K_opening_container = $self->{K_opening_container};
4350     my $K_closing_container = $self->{K_closing_container};
4351     my $rlines              = $self->{rlines};
4352
4353     my $is_single_quote = sub {
4354         my ( $Kbeg, $Kend, $quote_type ) = @_;
4355         foreach my $K ( $Kbeg .. $Kend ) {
4356             my $test_type = $rLL->[$K]->[_TYPE_];
4357             next   if ( $test_type eq 'b' );
4358             return if ( $test_type ne $quote_type );
4359         }
4360         return 1;
4361     };
4362
4363     my $excess_line_length = sub {
4364         my ( $KK, $Ktest ) = @_;
4365
4366         # what is the excess length if we add token $Ktest to the line with $KK?
4367         my $iline    = $rLL->[$KK]->[_LINE_INDEX_];
4368         my $rK_range = $rlines->[$iline]->{_rK_range};
4369         my ( $Kfirst, $Klast ) = @{$rK_range};
4370         my $starting_lentot =
4371           $Kfirst <= 0 ? 0 : $rLL->[ $Kfirst - 1 ]->[_CUMULATIVE_LENGTH_];
4372         my $starting_indent = 0;
4373         my $length_tol      = 1;
4374         if ( !$rOpts_variable_maximum_line_length ) {
4375             my $level = $rLL->[$Kfirst]->[_LEVEL_];
4376             $starting_indent = $rOpts_indent_columns * $level;
4377         }
4378
4379         my $length = $rLL->[$Ktest]->[_CUMULATIVE_LENGTH_] - $starting_lentot;
4380         my $excess_length =
4381           $starting_indent + $length + $length_tol - $rOpts_maximum_line_length;
4382         return $excess_length;
4383     };
4384
4385     # look for single qw quotes nested in containers
4386     my $KNEXT = 0;
4387     while ( defined($KNEXT) ) {
4388         my $KK = $KNEXT;
4389         $KNEXT = $rLL->[$KNEXT]->[_KNEXT_SEQ_ITEM_];
4390         my $rtoken_vars = $rLL->[$KK];
4391         my $outer_seqno = $rtoken_vars->[_TYPE_SEQUENCE_];
4392         if ( !$outer_seqno ) {
4393             next if ( $KK == 0 );    # first token in file may not be container
4394             Fault("sequence = $outer_seqno not defined at K=$KK");
4395         }
4396
4397         my $token = $rtoken_vars->[_TOKEN_];
4398         if ( $is_opening_token{$token} ) {
4399
4400             # see if the next token is a quote of some type
4401             my $Kn = $self->K_next_nonblank($KK);
4402             next unless $Kn;
4403             my $next_token = $rLL->[$Kn]->[_TOKEN_];
4404             my $next_type  = $rLL->[$Kn]->[_TYPE_];
4405             next
4406               unless ( ( $next_type eq 'q' || $next_type eq 'Q' )
4407                 && $next_token =~ /^q/ );
4408
4409             # The token before the closing container must also be a quote
4410             my $K_closing = $K_closing_container->{$outer_seqno};
4411             my $Kt_end    = $self->K_previous_nonblank($K_closing);
4412             next unless $rLL->[$Kt_end]->[_TYPE_] eq $next_type;
4413
4414             # Do not weld to single-line quotes. Nothing is gained, and it may
4415             # look bad.
4416             next if ( $Kt_end == $Kn );
4417
4418             # Only weld to quotes delimited with container tokens. This is
4419             # because welding to arbitrary quote delimiters can produce code
4420             # which is less readable than without welding.
4421             my $closing_delimiter = substr( $rLL->[$Kt_end]->[_TOKEN_], -1, 1 );
4422             next
4423               unless ( $is_closing_token{$closing_delimiter}
4424                 || $closing_delimiter eq '>' );
4425
4426             # Now make sure that there is just a single quote in the container
4427             next
4428               unless ( $is_single_quote->( $Kn + 1, $Kt_end - 1, $next_type ) );
4429
4430             # If welded, the line must not exceed allowed line length
4431             # Assume old line breaks for this estimate.
4432             next if ( $excess_line_length->( $KK, $Kn ) > 0 );
4433
4434             # OK to weld
4435             # FIXME: Are these always correct?
4436             $weld_len_left_closing{$outer_seqno}  = 1;
4437             $weld_len_right_opening{$outer_seqno} = 2;
4438
4439             # QW PATCH 1 (Testing)
4440             # undo CI for welded quotes
4441             foreach my $K ( $Kn .. $Kt_end ) {
4442                 $rLL->[$K]->[_CI_LEVEL_] = 0;
4443             }
4444
4445             # Change the level of a closing qw token to be that of the outer
4446             # containing token. This will allow -lp indentation to function
4447             # correctly in the vertical aligner.
4448             $rLL->[$Kt_end]->[_LEVEL_] = $rLL->[$K_closing]->[_LEVEL_];
4449         }
4450     }
4451     return;
4452 }
4453
4454 sub weld_len_left {
4455
4456     my ( $seqno, $type_or_tok ) = @_;
4457
4458     # Given the sequence number of a token, and the token or its type,
4459     # return the length of any weld to its left
4460
4461     my $weld_len;
4462     if ($seqno) {
4463         if ( $is_closing_type{$type_or_tok} ) {
4464             $weld_len = $weld_len_left_closing{$seqno};
4465         }
4466         elsif ( $is_opening_type{$type_or_tok} ) {
4467             $weld_len = $weld_len_left_opening{$seqno};
4468         }
4469     }
4470     if ( !defined($weld_len) ) { $weld_len = 0 }
4471     return $weld_len;
4472 }
4473
4474 sub weld_len_right {
4475
4476     my ( $seqno, $type_or_tok ) = @_;
4477
4478     # Given the sequence number of a token, and the token or its type,
4479     # return the length of any weld to its right
4480
4481     my $weld_len;
4482     if ($seqno) {
4483         if ( $is_closing_type{$type_or_tok} ) {
4484             $weld_len = $weld_len_right_closing{$seqno};
4485         }
4486         elsif ( $is_opening_type{$type_or_tok} ) {
4487             $weld_len = $weld_len_right_opening{$seqno};
4488         }
4489     }
4490     if ( !defined($weld_len) ) { $weld_len = 0 }
4491     return $weld_len;
4492 }
4493
4494 sub weld_len_left_to_go {
4495     my ($i) = @_;
4496
4497     # Given the index of a token in the 'to_go' array
4498     # return the length of any weld to its left
4499     return if ( $i < 0 );
4500     my $weld_len =
4501       weld_len_left( $type_sequence_to_go[$i], $types_to_go[$i] );
4502     return $weld_len;
4503 }
4504
4505 sub weld_len_right_to_go {
4506     my ($i) = @_;
4507
4508     # Given the index of a token in the 'to_go' array
4509     # return the length of any weld to its right
4510     return if ( $i < 0 );
4511     if ( $i > 0 && $types_to_go[$i] eq 'b' ) { $i-- }
4512     my $weld_len =
4513       weld_len_right( $type_sequence_to_go[$i], $types_to_go[$i] );
4514     return $weld_len;
4515 }
4516
4517 sub link_sequence_items {
4518
4519     # This has been merged into 'respace_tokens' but retained for reference
4520     my $self   = shift;
4521     my $rlines = $self->{rlines};
4522     my $rLL    = $self->{rLL};
4523
4524     # We walk the token list and make links to the next sequence item.
4525     # We also define these hashes to container tokens using sequence number as
4526     # the key:
4527     my $K_opening_container = {};    # opening [ { or (
4528     my $K_closing_container = {};    # closing ] } or )
4529     my $K_opening_ternary   = {};    # opening ? of ternary
4530     my $K_closing_ternary   = {};    # closing : of ternary
4531
4532     # sub to link preceding nodes forward to a new node type
4533     my $link_back = sub {
4534         my ( $Ktop, $key ) = @_;
4535
4536         my $Kprev = $Ktop - 1;
4537         while ( $Kprev >= 0
4538             && !defined( $rLL->[$Kprev]->[$key] ) )
4539         {
4540             $rLL->[$Kprev]->[$key] = $Ktop;
4541             $Kprev -= 1;
4542         }
4543     };
4544
4545     for ( my $KK = 0 ; $KK < @{$rLL} ; $KK++ ) {
4546
4547         $rLL->[$KK]->[_KNEXT_SEQ_ITEM_] = undef;
4548
4549         my $type = $rLL->[$KK]->[_TYPE_];
4550
4551         next if ( $type eq 'b' );
4552
4553         my $type_sequence = $rLL->[$KK]->[_TYPE_SEQUENCE_];
4554         if ($type_sequence) {
4555
4556             $link_back->( $KK, _KNEXT_SEQ_ITEM_ );
4557
4558             my $token = $rLL->[$KK]->[_TOKEN_];
4559             if ( $is_opening_token{$token} ) {
4560
4561                 $K_opening_container->{$type_sequence} = $KK;
4562             }
4563             elsif ( $is_closing_token{$token} ) {
4564
4565                 $K_closing_container->{$type_sequence} = $KK;
4566             }
4567
4568             # These are not yet used but could be useful
4569             else {
4570                 if ( $token eq '?' ) {
4571                     $K_opening_ternary->{$type_sequence} = $KK;
4572                 }
4573                 elsif ( $token eq ':' ) {
4574                     $K_closing_ternary->{$type_sequence} = $KK;
4575                 }
4576                 else {
4577                     Fault(<<EOM);
4578 Unknown sequenced token type '$type'.  Expecting one of '{[(?:)]}'
4579 EOM
4580                 }
4581             }
4582         }
4583     }
4584
4585     $self->{K_opening_container} = $K_opening_container;
4586     $self->{K_closing_container} = $K_closing_container;
4587     $self->{K_opening_ternary}   = $K_opening_ternary;
4588     $self->{K_closing_ternary}   = $K_closing_ternary;
4589     return;
4590 }
4591
4592 sub sum_token_lengths {
4593     my $self = shift;
4594
4595     # This has been merged into 'respace_tokens' but retained for reference
4596     my $rLL               = $self->{rLL};
4597     my $cumulative_length = 0;
4598     for ( my $KK = 0 ; $KK < @{$rLL} ; $KK++ ) {
4599
4600         # now set the length of this token
4601         my $token_length = length( $rLL->[$KK]->[_TOKEN_] );
4602
4603         $cumulative_length += $token_length;
4604
4605         # Save the length sum to just AFTER this token
4606         $rLL->[$KK]->[_CUMULATIVE_LENGTH_] = $cumulative_length;
4607
4608     }
4609     return;
4610 }
4611
4612 sub resync_lines_and_tokens {
4613
4614     my $self   = shift;
4615     my $rLL    = $self->{rLL};
4616     my $Klimit = $self->{Klimit};
4617     my $rlines = $self->{rlines};
4618
4619     # Re-construct the arrays of tokens associated with the original input lines
4620     # since they have probably changed due to inserting and deleting blanks
4621     # and a few other tokens.
4622
4623     my $Kmax = -1;
4624
4625     # This is the next token and its line index:
4626     my $Knext = 0;
4627     my $inext;
4628     if ( defined($rLL) && @{$rLL} ) {
4629         $Kmax  = @{$rLL} - 1;
4630         $inext = $rLL->[$Knext]->[_LINE_INDEX_];
4631     }
4632
4633     my $get_inext = sub {
4634         if ( $Knext < 0 || $Knext > $Kmax ) { $inext = undef }
4635         else {
4636             $inext = $rLL->[$Knext]->[_LINE_INDEX_];
4637         }
4638         return $inext;
4639     };
4640
4641     # Remember the most recently output token index
4642     my $Klast_out;
4643
4644     my $iline = -1;
4645     foreach my $line_of_tokens ( @{$rlines} ) {
4646         $iline++;
4647         my $line_type = $line_of_tokens->{_line_type};
4648         if ( $line_type eq 'CODE' ) {
4649
4650             my @K_array;
4651             my $rK_range;
4652             $inext = $get_inext->();
4653             while ( defined($inext) && $inext <= $iline ) {
4654                 push @{K_array}, $Knext;
4655                 $Knext += 1;
4656                 $inext = $get_inext->();
4657             }
4658
4659             # Delete any terminal blank token
4660             if (@K_array) {
4661                 if ( $rLL->[ $K_array[-1] ]->[_TYPE_] eq 'b' ) {
4662                     pop @K_array;
4663                 }
4664             }
4665
4666             # Define the range of K indexes for the line:
4667             # $Kfirst = index of first token on line
4668             # $Klast_out = index of last token on line
4669             my ( $Kfirst, $Klast );
4670             if (@K_array) {
4671                 $Kfirst    = $K_array[0];
4672                 $Klast     = $K_array[-1];
4673                 $Klast_out = $Klast;
4674             }
4675
4676             # It is only safe to trim the actual line text if the input
4677             # line had a terminal blank token. Otherwise, we may be
4678             # in a quote.
4679             if ( $line_of_tokens->{_ended_in_blank_token} ) {
4680                 $line_of_tokens->{_line_text} =~ s/\s+$//;
4681             }
4682             $line_of_tokens->{_rK_range} = [ $Kfirst, $Klast ];
4683
4684             # Deleting semicolons can create new empty code lines
4685             # which should be marked as blank
4686             if ( !defined($Kfirst) ) {
4687                 my $code_type = $line_of_tokens->{_code_type};
4688                 if ( !$code_type ) {
4689                     $line_of_tokens->{_code_type} = 'BL';
4690                 }
4691             }
4692         }
4693     }
4694
4695     # There shouldn't be any nodes beyond the last one unless we start
4696     # allowing 'link_after' calls
4697     if ( defined($inext) ) {
4698
4699         Fault("unexpected tokens at end of file when reconstructing lines");
4700     }
4701
4702     return;
4703 }
4704
4705 sub dump_verbatim {
4706     my $self   = shift;
4707     my $rlines = $self->{rlines};
4708     foreach my $line ( @{$rlines} ) {
4709         my $input_line = $line->{_line_text};
4710         $self->write_unindented_line($input_line);
4711     }
4712     return;
4713 }
4714
4715 sub finish_formatting {
4716
4717     my ( $self, $severe_error ) = @_;
4718
4719     # The file has been tokenized and is ready to be formatted.
4720     # All of the relevant data is stored in $self, ready to go.
4721
4722     # output file verbatim if severe error or no formatting requested
4723     if ( $severe_error || $rOpts->{notidy} ) {
4724         $self->dump_verbatim();
4725         $self->wrapup();
4726         return;
4727     }
4728
4729     # Make a pass through the lines, looking at lines of CODE and identifying
4730     # special processing needs, such format skipping sections marked by
4731     # special comments
4732     $self->scan_comments();
4733
4734     # Find nested pairs of container tokens for any welding. This information
4735     # is also needed for adding semicolons, so it is split apart from the
4736     # welding step.
4737     $self->find_nested_pairs();
4738
4739     # Make sure everything looks good
4740     $self->check_line_hashes();
4741
4742     # Future: Place to Begin future Iteration Loop
4743     # foreach my $it_count(1..$maxit) {
4744
4745     # Future: We must reset some things after the first iteration.
4746     # This includes:
4747     #   - resetting levels if there was any welding
4748     #   - resetting any phantom semicolons
4749     #   - dealing with any line numbering issues so we can relate final lines
4750     #     line numbers with input line numbers.
4751     #
4752     # If ($it_count>1) {
4753     #   Copy {level_raw} to [_LEVEL_] if ($it_count>1)
4754     #   Renumber lines
4755     # }
4756
4757     # Make a pass through all tokens, adding or deleting any whitespace as
4758     # required.  Also make any other changes, such as adding semicolons.
4759     # All token changes must be made here so that the token data structure
4760     # remains fixed for the rest of this iteration.
4761     $self->respace_tokens();
4762
4763     # Make a hierarchical map of the containers
4764     $self->map_containers();
4765
4766     # Implement any welding needed for the -wn or -cb options
4767     $self->weld_containers();
4768
4769     # Locate small nested blocks which should not be broken
4770     $self->mark_short_nested_blocks();
4771
4772     # Finishes formatting and write the result to the line sink.
4773     # Eventually this call should just change the 'rlines' data according to the
4774     # new line breaks and then return so that we can do an internal iteration
4775     # before continuing with the next stages of formatting.
4776     $self->break_lines();
4777
4778     ############################################################
4779     # A possible future decomposition of 'break_lines()' follows.
4780     # Benefits:
4781     # - allow perltidy to do an internal iteration which eliminates
4782     #   many unnecessary steps, such as re-parsing and vertical alignment.
4783     #   This will allow iterations to be automatic.
4784     # - consolidate all length calculations to allow utf8 alignment
4785     ############################################################
4786
4787     # Future: Check for convergence of beginning tokens on CODE lines
4788
4789     # Future: End of Iteration Loop
4790
4791     # Future: add_padding($rargs);
4792
4793     # Future: add_closing_side_comments($rargs);
4794
4795     # Future: vertical_alignment($rargs);
4796
4797     # Future: output results
4798
4799     # A final routine to tie up any loose ends
4800     $self->wrapup();
4801     return;
4802 }
4803
4804 sub create_one_line_block {
4805     ( $index_start_one_line_block, $semicolons_before_block_self_destruct ) =
4806       @_;
4807     return;
4808 }
4809
4810 sub destroy_one_line_block {
4811     $index_start_one_line_block            = UNDEFINED_INDEX;
4812     $semicolons_before_block_self_destruct = 0;
4813     return;
4814 }
4815
4816 sub leading_spaces_to_go {
4817
4818     # return the number of indentation spaces for a token in the output stream;
4819     # these were previously stored by 'set_leading_whitespace'.
4820
4821     my $ii = shift;
4822     if ( $ii < 0 ) { $ii = 0 }
4823     return get_spaces( $leading_spaces_to_go[$ii] );
4824
4825 }
4826
4827 sub get_spaces {
4828
4829     # return the number of leading spaces associated with an indentation
4830     # variable $indentation is either a constant number of spaces or an object
4831     # with a get_spaces method.
4832     my $indentation = shift;
4833     return ref($indentation) ? $indentation->get_spaces() : $indentation;
4834 }
4835
4836 sub get_recoverable_spaces {
4837
4838     # return the number of spaces (+ means shift right, - means shift left)
4839     # that we would like to shift a group of lines with the same indentation
4840     # to get them to line up with their opening parens
4841     my $indentation = shift;
4842     return ref($indentation) ? $indentation->get_recoverable_spaces() : 0;
4843 }
4844
4845 sub get_available_spaces_to_go {
4846
4847     my $ii   = shift;
4848     my $item = $leading_spaces_to_go[$ii];
4849
4850     # return the number of available leading spaces associated with an
4851     # indentation variable.  $indentation is either a constant number of
4852     # spaces or an object with a get_available_spaces method.
4853     return ref($item) ? $item->get_available_spaces() : 0;
4854 }
4855
4856 sub new_lp_indentation_item {
4857
4858     # this is an interface to the IndentationItem class
4859     my ( $spaces, $level, $ci_level, $available_spaces, $align_paren ) = @_;
4860
4861     # A negative level implies not to store the item in the item_list
4862     my $index = 0;
4863     if ( $level >= 0 ) { $index = ++$max_gnu_item_index; }
4864
4865     my $item = Perl::Tidy::IndentationItem->new(
4866         $spaces,      $level,
4867         $ci_level,    $available_spaces,
4868         $index,       $gnu_sequence_number,
4869         $align_paren, $max_gnu_stack_index,
4870         $line_start_index_to_go,
4871     );
4872
4873     if ( $level >= 0 ) {
4874         $gnu_item_list[$max_gnu_item_index] = $item;
4875     }
4876
4877     return $item;
4878 }
4879
4880 sub set_leading_whitespace {
4881
4882     # This routine defines leading whitespace
4883     # given: the level and continuation_level of a token,
4884     # define: space count of leading string which would apply if it
4885     # were the first token of a new line.
4886
4887     my ( $level_abs, $ci_level, $in_continued_quote ) = @_;
4888
4889     # Adjust levels if necessary to recycle whitespace:
4890     # given $level_abs, the absolute level
4891     # define $level, a possibly reduced level for whitespace
4892     my $level = $level_abs;
4893     if ( $rOpts_whitespace_cycle && $rOpts_whitespace_cycle > 0 ) {
4894         if ( $level_abs < $whitespace_last_level ) {
4895             pop(@whitespace_level_stack);
4896         }
4897         if ( !@whitespace_level_stack ) {
4898             push @whitespace_level_stack, $level_abs;
4899         }
4900         elsif ( $level_abs > $whitespace_last_level ) {
4901             $level = $whitespace_level_stack[-1] +
4902               ( $level_abs - $whitespace_last_level );
4903
4904             if (
4905                 # 1 Try to break at a block brace
4906                 (
4907                        $level > $rOpts_whitespace_cycle
4908                     && $last_nonblank_type eq '{'
4909                     && $last_nonblank_token eq '{'
4910                 )
4911
4912                 # 2 Then either a brace or bracket
4913                 || (   $level > $rOpts_whitespace_cycle + 1
4914                     && $last_nonblank_token =~ /^[\{\[]$/ )
4915
4916                 # 3 Then a paren too
4917                 || $level > $rOpts_whitespace_cycle + 2
4918               )
4919             {
4920                 $level = 1;
4921             }
4922             push @whitespace_level_stack, $level;
4923         }
4924         $level = $whitespace_level_stack[-1];
4925     }
4926     $whitespace_last_level = $level_abs;
4927
4928     # modify for -bli, which adds one continuation indentation for
4929     # opening braces
4930     if (   $rOpts_brace_left_and_indent
4931         && $max_index_to_go == 0
4932         && $block_type_to_go[$max_index_to_go] =~ /$bli_pattern/o )
4933     {
4934         $ci_level++;
4935     }
4936
4937     # patch to avoid trouble when input file has negative indentation.
4938     # other logic should catch this error.
4939     if ( $level < 0 ) { $level = 0 }
4940
4941     #-------------------------------------------
4942     # handle the standard indentation scheme
4943     #-------------------------------------------
4944     unless ($rOpts_line_up_parentheses) {
4945         my $space_count =
4946           $ci_level * $rOpts_continuation_indentation +
4947           $level * $rOpts_indent_columns;
4948         my $ci_spaces =
4949           ( $ci_level == 0 ) ? 0 : $rOpts_continuation_indentation;
4950
4951         if ($in_continued_quote) {
4952             $space_count = 0;
4953             $ci_spaces   = 0;
4954         }
4955         $leading_spaces_to_go[$max_index_to_go] = $space_count;
4956         $reduced_spaces_to_go[$max_index_to_go] = $space_count - $ci_spaces;
4957         return;
4958     }
4959
4960     #-------------------------------------------------------------
4961     # handle case of -lp indentation..
4962     #-------------------------------------------------------------
4963
4964     # The continued_quote flag means that this is the first token of a
4965     # line, and it is the continuation of some kind of multi-line quote
4966     # or pattern.  It requires special treatment because it must have no
4967     # added leading whitespace. So we create a special indentation item
4968     # which is not in the stack.
4969     if ($in_continued_quote) {
4970         my $space_count     = 0;
4971         my $available_space = 0;
4972         $level = -1;    # flag to prevent storing in item_list
4973         $leading_spaces_to_go[$max_index_to_go] =
4974           $reduced_spaces_to_go[$max_index_to_go] =
4975           new_lp_indentation_item( $space_count, $level, $ci_level,
4976             $available_space, 0 );
4977         return;
4978     }
4979
4980     # get the top state from the stack
4981     my $space_count      = $gnu_stack[$max_gnu_stack_index]->get_spaces();
4982     my $current_level    = $gnu_stack[$max_gnu_stack_index]->get_level();
4983     my $current_ci_level = $gnu_stack[$max_gnu_stack_index]->get_ci_level();
4984
4985     my $type        = $types_to_go[$max_index_to_go];
4986     my $token       = $tokens_to_go[$max_index_to_go];
4987     my $total_depth = $nesting_depth_to_go[$max_index_to_go];
4988
4989     if ( $type eq '{' || $type eq '(' ) {
4990
4991         $gnu_comma_count{ $total_depth + 1 } = 0;
4992         $gnu_arrow_count{ $total_depth + 1 } = 0;
4993
4994         # If we come to an opening token after an '=' token of some type,
4995         # see if it would be helpful to 'break' after the '=' to save space
4996         my $last_equals = $last_gnu_equals{$total_depth};
4997         if ( $last_equals && $last_equals > $line_start_index_to_go ) {
4998
4999             # find the position if we break at the '='
5000             my $i_test = $last_equals;
5001             if ( $types_to_go[ $i_test + 1 ] eq 'b' ) { $i_test++ }
5002
5003             # TESTING
5004             ##my $too_close = ($i_test==$max_index_to_go-1);
5005
5006             my $test_position = total_line_length( $i_test, $max_index_to_go );
5007             my $mll           = maximum_line_length($i_test);
5008
5009             if (
5010
5011                 # the equals is not just before an open paren (testing)
5012                 ##!$too_close &&
5013
5014                 # if we are beyond the midpoint
5015                 $gnu_position_predictor > $mll - $rOpts_maximum_line_length / 2
5016
5017                 # or we are beyond the 1/4 point and there was an old
5018                 # break at the equals
5019                 || (
5020                     $gnu_position_predictor >
5021                     $mll - $rOpts_maximum_line_length * 3 / 4
5022                     && (
5023                         $old_breakpoint_to_go[$last_equals]
5024                         || (   $last_equals > 0
5025                             && $old_breakpoint_to_go[ $last_equals - 1 ] )
5026                         || (   $last_equals > 1
5027                             && $types_to_go[ $last_equals - 1 ] eq 'b'
5028                             && $old_breakpoint_to_go[ $last_equals - 2 ] )
5029                     )
5030                 )
5031               )
5032             {
5033
5034                 # then make the switch -- note that we do not set a real
5035                 # breakpoint here because we may not really need one; sub
5036                 # scan_list will do that if necessary
5037                 $line_start_index_to_go = $i_test + 1;
5038                 $gnu_position_predictor = $test_position;
5039             }
5040         }
5041     }
5042
5043     my $halfway =
5044       maximum_line_length_for_level($level) - $rOpts_maximum_line_length / 2;
5045
5046     # Check for decreasing depth ..
5047     # Note that one token may have both decreasing and then increasing
5048     # depth. For example, (level, ci) can go from (1,1) to (2,0).  So,
5049     # in this example we would first go back to (1,0) then up to (2,0)
5050     # in a single call.
5051     if ( $level < $current_level || $ci_level < $current_ci_level ) {
5052
5053         # loop to find the first entry at or completely below this level
5054         my ( $lev, $ci_lev );
5055         while (1) {
5056             if ($max_gnu_stack_index) {
5057
5058                 # save index of token which closes this level
5059                 $gnu_stack[$max_gnu_stack_index]->set_closed($max_index_to_go);
5060
5061                 # Undo any extra indentation if we saw no commas
5062                 my $available_spaces =
5063                   $gnu_stack[$max_gnu_stack_index]->get_available_spaces();
5064
5065                 my $comma_count = 0;
5066                 my $arrow_count = 0;
5067                 if ( $type eq '}' || $type eq ')' ) {
5068                     $comma_count = $gnu_comma_count{$total_depth};
5069                     $arrow_count = $gnu_arrow_count{$total_depth};
5070                     $comma_count = 0 unless $comma_count;
5071                     $arrow_count = 0 unless $arrow_count;
5072                 }
5073                 $gnu_stack[$max_gnu_stack_index]->set_comma_count($comma_count);
5074                 $gnu_stack[$max_gnu_stack_index]->set_arrow_count($arrow_count);
5075
5076                 if ( $available_spaces > 0 ) {
5077
5078                     if ( $comma_count <= 0 || $arrow_count > 0 ) {
5079
5080                         my $i = $gnu_stack[$max_gnu_stack_index]->get_index();
5081                         my $seqno =
5082                           $gnu_stack[$max_gnu_stack_index]
5083                           ->get_sequence_number();
5084
5085                         # Be sure this item was created in this batch.  This
5086                         # should be true because we delete any available
5087                         # space from open items at the end of each batch.
5088                         if (   $gnu_sequence_number != $seqno
5089                             || $i > $max_gnu_item_index )
5090                         {
5091                             warning(
5092 "Program bug with -lp.  seqno=$seqno should be $gnu_sequence_number and i=$i should be less than max=$max_gnu_item_index\n"
5093                             );
5094                             report_definite_bug();
5095                         }
5096
5097                         else {
5098                             if ( $arrow_count == 0 ) {
5099                                 $gnu_item_list[$i]
5100                                   ->permanently_decrease_available_spaces(
5101                                     $available_spaces);
5102                             }
5103                             else {
5104                                 $gnu_item_list[$i]
5105                                   ->tentatively_decrease_available_spaces(
5106                                     $available_spaces);
5107                             }
5108                             foreach my $j ( $i + 1 .. $max_gnu_item_index ) {
5109                                 $gnu_item_list[$j]
5110                                   ->decrease_SPACES($available_spaces);
5111                             }
5112                         }
5113                     }
5114                 }
5115
5116                 # go down one level
5117                 --$max_gnu_stack_index;
5118                 $lev    = $gnu_stack[$max_gnu_stack_index]->get_level();
5119                 $ci_lev = $gnu_stack[$max_gnu_stack_index]->get_ci_level();
5120
5121                 # stop when we reach a level at or below the current level
5122                 if ( $lev <= $level && $ci_lev <= $ci_level ) {
5123                     $space_count =
5124                       $gnu_stack[$max_gnu_stack_index]->get_spaces();
5125                     $current_level    = $lev;
5126                     $current_ci_level = $ci_lev;
5127                     last;
5128                 }
5129             }
5130
5131             # reached bottom of stack .. should never happen because
5132             # only negative levels can get here, and $level was forced
5133             # to be positive above.
5134             else {
5135                 warning(
5136 "program bug with -lp: stack_error. level=$level; lev=$lev; ci_level=$ci_level; ci_lev=$ci_lev; rerun with -nlp\n"
5137                 );
5138                 report_definite_bug();
5139                 last;
5140             }
5141         }
5142     }
5143
5144     # handle increasing depth
5145     if ( $level > $current_level || $ci_level > $current_ci_level ) {
5146
5147         # Compute the standard incremental whitespace.  This will be
5148         # the minimum incremental whitespace that will be used.  This
5149         # choice results in a smooth transition between the gnu-style
5150         # and the standard style.
5151         my $standard_increment =
5152           ( $level - $current_level ) * $rOpts_indent_columns +
5153           ( $ci_level - $current_ci_level ) * $rOpts_continuation_indentation;
5154
5155         # Now we have to define how much extra incremental space
5156         # ("$available_space") we want.  This extra space will be
5157         # reduced as necessary when long lines are encountered or when
5158         # it becomes clear that we do not have a good list.
5159         my $available_space = 0;
5160         my $align_paren     = 0;
5161         my $excess          = 0;
5162
5163         # initialization on empty stack..
5164         if ( $max_gnu_stack_index == 0 ) {
5165             $space_count = $level * $rOpts_indent_columns;
5166         }
5167
5168         # if this is a BLOCK, add the standard increment
5169         elsif ($last_nonblank_block_type) {
5170             $space_count += $standard_increment;
5171         }
5172
5173         # if last nonblank token was not structural indentation,
5174         # just use standard increment
5175         elsif ( $last_nonblank_type ne '{' ) {
5176             $space_count += $standard_increment;
5177         }
5178
5179         # otherwise use the space to the first non-blank level change token
5180         else {
5181
5182             $space_count = $gnu_position_predictor;
5183
5184             my $min_gnu_indentation =
5185               $gnu_stack[$max_gnu_stack_index]->get_spaces();
5186
5187             $available_space = $space_count - $min_gnu_indentation;
5188             if ( $available_space >= $standard_increment ) {
5189                 $min_gnu_indentation += $standard_increment;
5190             }
5191             elsif ( $available_space > 1 ) {
5192                 $min_gnu_indentation += $available_space + 1;
5193             }
5194             elsif ( $last_nonblank_token =~ /^[\{\[\(]$/ ) {
5195                 if ( ( $tightness{$last_nonblank_token} < 2 ) ) {
5196                     $min_gnu_indentation += 2;
5197                 }
5198                 else {
5199                     $min_gnu_indentation += 1;
5200                 }
5201             }
5202             else {
5203                 $min_gnu_indentation += $standard_increment;
5204             }
5205             $available_space = $space_count - $min_gnu_indentation;
5206
5207             if ( $available_space < 0 ) {
5208                 $space_count     = $min_gnu_indentation;
5209                 $available_space = 0;
5210             }
5211             $align_paren = 1;
5212         }
5213
5214         # update state, but not on a blank token
5215         if ( $types_to_go[$max_index_to_go] ne 'b' ) {
5216
5217             $gnu_stack[$max_gnu_stack_index]->set_have_child(1);
5218
5219             ++$max_gnu_stack_index;
5220             $gnu_stack[$max_gnu_stack_index] =
5221               new_lp_indentation_item( $space_count, $level, $ci_level,
5222                 $available_space, $align_paren );
5223
5224             # If the opening paren is beyond the half-line length, then
5225             # we will use the minimum (standard) indentation.  This will
5226             # help avoid problems associated with running out of space
5227             # near the end of a line.  As a result, in deeply nested
5228             # lists, there will be some indentations which are limited
5229             # to this minimum standard indentation. But the most deeply
5230             # nested container will still probably be able to shift its
5231             # parameters to the right for proper alignment, so in most
5232             # cases this will not be noticeable.
5233             if ( $available_space > 0 && $space_count > $halfway ) {
5234                 $gnu_stack[$max_gnu_stack_index]
5235                   ->tentatively_decrease_available_spaces($available_space);
5236             }
5237         }
5238     }
5239
5240     # Count commas and look for non-list characters.  Once we see a
5241     # non-list character, we give up and don't look for any more commas.
5242     if ( $type eq '=>' ) {
5243         $gnu_arrow_count{$total_depth}++;
5244
5245         # tentatively treating '=>' like '=' for estimating breaks
5246         # TODO: this could use some experimentation
5247         $last_gnu_equals{$total_depth} = $max_index_to_go;
5248     }
5249
5250     elsif ( $type eq ',' ) {
5251         $gnu_comma_count{$total_depth}++;
5252     }
5253
5254     elsif ( $is_assignment{$type} ) {
5255         $last_gnu_equals{$total_depth} = $max_index_to_go;
5256     }
5257
5258     # this token might start a new line
5259     # if this is a non-blank..
5260     if ( $type ne 'b' ) {
5261
5262         # and if ..
5263         if (
5264
5265             # this is the first nonblank token of the line
5266             $max_index_to_go == 1 && $types_to_go[0] eq 'b'
5267
5268             # or previous character was one of these:
5269             || $last_nonblank_type_to_go =~ /^([\:\?\,f])$/
5270
5271             # or previous character was opening and this does not close it
5272             || ( $last_nonblank_type_to_go eq '{' && $type ne '}' )
5273             || ( $last_nonblank_type_to_go eq '(' and $type ne ')' )
5274
5275             # or this token is one of these:
5276             || $type =~ /^([\.]|\|\||\&\&)$/
5277
5278             # or this is a closing structure
5279             || (   $last_nonblank_type_to_go eq '}'
5280                 && $last_nonblank_token_to_go eq $last_nonblank_type_to_go )
5281
5282             # or previous token was keyword 'return'
5283             || ( $last_nonblank_type_to_go eq 'k'
5284                 && ( $last_nonblank_token_to_go eq 'return' && $type ne '{' ) )
5285
5286             # or starting a new line at certain keywords is fine
5287             || (   $type eq 'k'
5288                 && $is_if_unless_and_or_last_next_redo_return{$token} )
5289
5290             # or this is after an assignment after a closing structure
5291             || (
5292                 $is_assignment{$last_nonblank_type_to_go}
5293                 && (
5294                     $last_last_nonblank_type_to_go =~ /^[\}\)\]]$/
5295
5296                     # and it is significantly to the right
5297                     || $gnu_position_predictor > $halfway
5298                 )
5299             )
5300           )
5301         {
5302             check_for_long_gnu_style_lines();
5303             $line_start_index_to_go = $max_index_to_go;
5304
5305             # back up 1 token if we want to break before that type
5306             # otherwise, we may strand tokens like '?' or ':' on a line
5307             if ( $line_start_index_to_go > 0 ) {
5308                 if ( $last_nonblank_type_to_go eq 'k' ) {
5309
5310                     if ( $want_break_before{$last_nonblank_token_to_go} ) {
5311                         $line_start_index_to_go--;
5312                     }
5313                 }
5314                 elsif ( $want_break_before{$last_nonblank_type_to_go} ) {
5315                     $line_start_index_to_go--;
5316                 }
5317             }
5318         }
5319     }
5320
5321     # remember the predicted position of this token on the output line
5322     if ( $max_index_to_go > $line_start_index_to_go ) {
5323         $gnu_position_predictor =
5324           total_line_length( $line_start_index_to_go, $max_index_to_go );
5325     }
5326     else {
5327         $gnu_position_predictor =
5328           $space_count + $token_lengths_to_go[$max_index_to_go];
5329     }
5330
5331     # store the indentation object for this token
5332     # this allows us to manipulate the leading whitespace
5333     # (in case we have to reduce indentation to fit a line) without
5334     # having to change any token values
5335     $leading_spaces_to_go[$max_index_to_go] = $gnu_stack[$max_gnu_stack_index];
5336     $reduced_spaces_to_go[$max_index_to_go] =
5337       ( $max_gnu_stack_index > 0 && $ci_level )
5338       ? $gnu_stack[ $max_gnu_stack_index - 1 ]
5339       : $gnu_stack[$max_gnu_stack_index];
5340     return;
5341 }
5342
5343 sub check_for_long_gnu_style_lines {
5344
5345     # look at the current estimated maximum line length, and
5346     # remove some whitespace if it exceeds the desired maximum
5347
5348     # this is only for the '-lp' style
5349     return unless ($rOpts_line_up_parentheses);
5350
5351     # nothing can be done if no stack items defined for this line
5352     return if ( $max_gnu_item_index == UNDEFINED_INDEX );
5353
5354     # see if we have exceeded the maximum desired line length
5355     # keep 2 extra free because they are needed in some cases
5356     # (result of trial-and-error testing)
5357     my $spaces_needed =
5358       $gnu_position_predictor - maximum_line_length($max_index_to_go) + 2;
5359
5360     return if ( $spaces_needed <= 0 );
5361
5362     # We are over the limit, so try to remove a requested number of
5363     # spaces from leading whitespace.  We are only allowed to remove
5364     # from whitespace items created on this batch, since others have
5365     # already been used and cannot be undone.
5366     my @candidates = ();
5367     my $i;
5368
5369     # loop over all whitespace items created for the current batch
5370     for ( $i = 0 ; $i <= $max_gnu_item_index ; $i++ ) {
5371         my $item = $gnu_item_list[$i];
5372
5373         # item must still be open to be a candidate (otherwise it
5374         # cannot influence the current token)
5375         next if ( $item->get_closed() >= 0 );
5376
5377         my $available_spaces = $item->get_available_spaces();
5378
5379         if ( $available_spaces > 0 ) {
5380             push( @candidates, [ $i, $available_spaces ] );
5381         }
5382     }
5383
5384     return unless (@candidates);
5385
5386     # sort by available whitespace so that we can remove whitespace
5387     # from the maximum available first
5388     @candidates = sort { $b->[1] <=> $a->[1] } @candidates;
5389
5390     # keep removing whitespace until we are done or have no more
5391     foreach my $candidate (@candidates) {
5392         my ( $i, $available_spaces ) = @{$candidate};
5393         my $deleted_spaces =
5394           ( $available_spaces > $spaces_needed )
5395           ? $spaces_needed
5396           : $available_spaces;
5397
5398         # remove the incremental space from this item
5399         $gnu_item_list[$i]->decrease_available_spaces($deleted_spaces);
5400
5401         my $i_debug = $i;
5402
5403         # update the leading whitespace of this item and all items
5404         # that came after it
5405         for ( ; $i <= $max_gnu_item_index ; $i++ ) {
5406
5407             my $old_spaces = $gnu_item_list[$i]->get_spaces();
5408             if ( $old_spaces >= $deleted_spaces ) {
5409                 $gnu_item_list[$i]->decrease_SPACES($deleted_spaces);
5410             }
5411
5412             # shouldn't happen except for code bug:
5413             else {
5414                 my $level        = $gnu_item_list[$i_debug]->get_level();
5415                 my $ci_level     = $gnu_item_list[$i_debug]->get_ci_level();
5416                 my $old_level    = $gnu_item_list[$i]->get_level();
5417                 my $old_ci_level = $gnu_item_list[$i]->get_ci_level();
5418                 warning(
5419 "program bug with -lp: want to delete $deleted_spaces from item $i, but old=$old_spaces deleted: lev=$level ci=$ci_level  deleted: level=$old_level ci=$ci_level\n"
5420                 );
5421                 report_definite_bug();
5422             }
5423         }
5424         $gnu_position_predictor -= $deleted_spaces;
5425         $spaces_needed          -= $deleted_spaces;
5426         last unless ( $spaces_needed > 0 );
5427     }
5428     return;
5429 }
5430
5431 sub finish_lp_batch {
5432
5433     # This routine is called once after each output stream batch is
5434     # finished to undo indentation for all incomplete -lp
5435     # indentation levels.  It is too risky to leave a level open,
5436     # because then we can't backtrack in case of a long line to follow.
5437     # This means that comments and blank lines will disrupt this
5438     # indentation style.  But the vertical aligner may be able to
5439     # get the space back if there are side comments.
5440
5441     # this is only for the 'lp' style
5442     return unless ($rOpts_line_up_parentheses);
5443
5444     # nothing can be done if no stack items defined for this line
5445     return if ( $max_gnu_item_index == UNDEFINED_INDEX );
5446
5447     # loop over all whitespace items created for the current batch
5448     foreach my $i ( 0 .. $max_gnu_item_index ) {
5449         my $item = $gnu_item_list[$i];
5450
5451         # only look for open items
5452         next if ( $item->get_closed() >= 0 );
5453
5454         # Tentatively remove all of the available space
5455         # (The vertical aligner will try to get it back later)
5456         my $available_spaces = $item->get_available_spaces();
5457         if ( $available_spaces > 0 ) {
5458
5459             # delete incremental space for this item
5460             $gnu_item_list[$i]
5461               ->tentatively_decrease_available_spaces($available_spaces);
5462
5463             # Reduce the total indentation space of any nodes that follow
5464             # Note that any such nodes must necessarily be dependents
5465             # of this node.
5466             foreach ( $i + 1 .. $max_gnu_item_index ) {
5467                 $gnu_item_list[$_]->decrease_SPACES($available_spaces);
5468             }
5469         }
5470     }
5471     return;
5472 }
5473
5474 sub reduce_lp_indentation {
5475
5476     # reduce the leading whitespace at token $i if possible by $spaces_needed
5477     # (a large value of $spaces_needed will remove all excess space)
5478     # NOTE: to be called from scan_list only for a sequence of tokens
5479     # contained between opening and closing parens/braces/brackets
5480
5481     my ( $i, $spaces_wanted ) = @_;
5482     my $deleted_spaces = 0;
5483
5484     my $item             = $leading_spaces_to_go[$i];
5485     my $available_spaces = $item->get_available_spaces();
5486
5487     if (
5488         $available_spaces > 0
5489         && ( ( $spaces_wanted <= $available_spaces )
5490             || !$item->get_have_child() )
5491       )
5492     {
5493
5494         # we'll remove these spaces, but mark them as recoverable
5495         $deleted_spaces =
5496           $item->tentatively_decrease_available_spaces($spaces_wanted);
5497     }
5498
5499     return $deleted_spaces;
5500 }
5501
5502 sub token_sequence_length {
5503
5504     # return length of tokens ($ibeg .. $iend) including $ibeg & $iend
5505     # returns 0 if $ibeg > $iend (shouldn't happen)
5506     my ( $ibeg, $iend ) = @_;
5507     return 0                                  if ( $iend < 0 || $ibeg > $iend );
5508     return $summed_lengths_to_go[ $iend + 1 ] if ( $ibeg < 0 );
5509     return $summed_lengths_to_go[ $iend + 1 ] - $summed_lengths_to_go[$ibeg];
5510 }
5511
5512 sub total_line_length {
5513
5514     # return length of a line of tokens ($ibeg .. $iend)
5515     my ( $ibeg, $iend ) = @_;
5516     return leading_spaces_to_go($ibeg) + token_sequence_length( $ibeg, $iend );
5517 }
5518
5519 sub maximum_line_length_for_level {
5520
5521     # return maximum line length for line starting with a given level
5522     my $maximum_line_length = $rOpts_maximum_line_length;
5523
5524     # Modify if -vmll option is selected
5525     if ($rOpts_variable_maximum_line_length) {
5526         my $level = shift;
5527         if ( $level < 0 ) { $level = 0 }
5528         $maximum_line_length += $level * $rOpts_indent_columns;
5529     }
5530     return $maximum_line_length;
5531 }
5532
5533 sub maximum_line_length {
5534
5535     # return maximum line length for line starting with the token at given index
5536     my $ii = shift;
5537     return maximum_line_length_for_level( $levels_to_go[$ii] );
5538 }
5539
5540 sub excess_line_length {
5541
5542     # return number of characters by which a line of tokens ($ibeg..$iend)
5543     # exceeds the allowable line length.
5544     my ( $ibeg, $iend, $ignore_left_weld, $ignore_right_weld ) = @_;
5545
5546     # Include left and right weld lengths unless requested not to
5547     my $wl = $ignore_left_weld  ? 0 : weld_len_left_to_go($iend);
5548     my $wr = $ignore_right_weld ? 0 : weld_len_right_to_go($iend);
5549
5550     return total_line_length( $ibeg, $iend ) + $wl + $wr -
5551       maximum_line_length($ibeg);
5552 }
5553
5554 sub wrapup {
5555
5556     # flush buffer and write any informative messages
5557     my $self = shift;
5558
5559     $self->flush();
5560     $file_writer_object->decrement_output_line_number()
5561       ;    # fix up line number since it was incremented
5562     we_are_at_the_last_line();
5563     if ( $added_semicolon_count > 0 ) {
5564         my $first = ( $added_semicolon_count > 1 ) ? "First" : "";
5565         my $what =
5566           ( $added_semicolon_count > 1 ) ? "semicolons were" : "semicolon was";
5567         write_logfile_entry("$added_semicolon_count $what added:\n");
5568         write_logfile_entry(
5569             "  $first at input line $first_added_semicolon_at\n");
5570
5571         if ( $added_semicolon_count > 1 ) {
5572             write_logfile_entry(
5573                 "   Last at input line $last_added_semicolon_at\n");
5574         }
5575         write_logfile_entry("  (Use -nasc to prevent semicolon addition)\n");
5576         write_logfile_entry("\n");
5577     }
5578
5579     if ( $deleted_semicolon_count > 0 ) {
5580         my $first = ( $deleted_semicolon_count > 1 ) ? "First" : "";
5581         my $what =
5582           ( $deleted_semicolon_count > 1 )
5583           ? "semicolons were"
5584           : "semicolon was";
5585         write_logfile_entry(
5586             "$deleted_semicolon_count unnecessary $what deleted:\n");
5587         write_logfile_entry(
5588             "  $first at input line $first_deleted_semicolon_at\n");
5589
5590         if ( $deleted_semicolon_count > 1 ) {
5591             write_logfile_entry(
5592                 "   Last at input line $last_deleted_semicolon_at\n");
5593         }
5594         write_logfile_entry("  (Use -ndsm to prevent semicolon deletion)\n");
5595         write_logfile_entry("\n");
5596     }
5597
5598     if ( $embedded_tab_count > 0 ) {
5599         my $first = ( $embedded_tab_count > 1 ) ? "First" : "";
5600         my $what =
5601           ( $embedded_tab_count > 1 )
5602           ? "quotes or patterns"
5603           : "quote or pattern";
5604         write_logfile_entry("$embedded_tab_count $what had embedded tabs:\n");
5605         write_logfile_entry(
5606 "This means the display of this script could vary with device or software\n"
5607         );
5608         write_logfile_entry("  $first at input line $first_embedded_tab_at\n");
5609
5610         if ( $embedded_tab_count > 1 ) {
5611             write_logfile_entry(
5612                 "   Last at input line $last_embedded_tab_at\n");
5613         }
5614         write_logfile_entry("\n");
5615     }
5616
5617     if ($first_tabbing_disagreement) {
5618         write_logfile_entry(
5619 "First indentation disagreement seen at input line $first_tabbing_disagreement\n"
5620         );
5621     }
5622
5623     if ($in_tabbing_disagreement) {
5624         write_logfile_entry(
5625 "Ending with indentation disagreement which started at input line $in_tabbing_disagreement\n"
5626         );
5627     }
5628     else {
5629
5630         if ($last_tabbing_disagreement) {
5631
5632             write_logfile_entry(
5633 "Last indentation disagreement seen at input line $last_tabbing_disagreement\n"
5634             );
5635         }
5636         else {
5637             write_logfile_entry("No indentation disagreement seen\n");
5638         }
5639     }
5640     if ($first_tabbing_disagreement) {
5641         write_logfile_entry(
5642 "Note: Indentation disagreement detection is not accurate for outdenting and -lp.\n"
5643         );
5644     }
5645     write_logfile_entry("\n");
5646
5647     $vertical_aligner_object->report_anything_unusual();
5648
5649     $file_writer_object->report_line_length_errors();
5650
5651     return;
5652 }
5653
5654 sub check_options {
5655
5656     # This routine is called to check the Opts hash after it is defined
5657     $rOpts = shift;
5658
5659     initialize_whitespace_hashes();
5660     initialize_bond_strength_hashes();
5661
5662     make_static_block_comment_pattern();
5663     make_static_side_comment_pattern();
5664     make_closing_side_comment_prefix();
5665     make_closing_side_comment_list_pattern();
5666     $format_skipping_pattern_begin =
5667       make_format_skipping_pattern( 'format-skipping-begin', '#<<<' );
5668     $format_skipping_pattern_end =
5669       make_format_skipping_pattern( 'format-skipping-end', '#>>>' );
5670
5671     # If closing side comments ARE selected, then we can safely
5672     # delete old closing side comments unless closing side comment
5673     # warnings are requested.  This is a good idea because it will
5674     # eliminate any old csc's which fall below the line count threshold.
5675     # We cannot do this if warnings are turned on, though, because we
5676     # might delete some text which has been added.  So that must
5677     # be handled when comments are created.
5678     if ( $rOpts->{'closing-side-comments'} ) {
5679         if ( !$rOpts->{'closing-side-comment-warnings'} ) {
5680             $rOpts->{'delete-closing-side-comments'} = 1;
5681         }
5682     }
5683
5684     # If closing side comments ARE NOT selected, but warnings ARE
5685     # selected and we ARE DELETING csc's, then we will pretend to be
5686     # adding with a huge interval.  This will force the comments to be
5687     # generated for comparison with the old comments, but not added.
5688     elsif ( $rOpts->{'closing-side-comment-warnings'} ) {
5689         if ( $rOpts->{'delete-closing-side-comments'} ) {
5690             $rOpts->{'delete-closing-side-comments'}  = 0;
5691             $rOpts->{'closing-side-comments'}         = 1;
5692             $rOpts->{'closing-side-comment-interval'} = 100000000;
5693         }
5694     }
5695
5696     make_sub_matching_pattern();
5697     make_bli_pattern();
5698     make_block_brace_vertical_tightness_pattern();
5699     make_blank_line_pattern();
5700     make_keyword_group_list_pattern();
5701
5702     # Make initial list of desired one line block types
5703     # They will be modified by 'prepare_cuddled_block_types'
5704     %want_one_line_block = %is_sort_map_grep_eval;
5705
5706     prepare_cuddled_block_types();
5707     if ( $rOpts->{'dump-cuddled-block-list'} ) {
5708         dump_cuddled_block_list(*STDOUT);
5709         Exit(0);
5710     }
5711
5712     if ( $rOpts->{'line-up-parentheses'} ) {
5713
5714         if (   $rOpts->{'indent-only'}
5715             || !$rOpts->{'add-newlines'}
5716             || !$rOpts->{'delete-old-newlines'} )
5717         {
5718             Warn(<<EOM);
5719 -----------------------------------------------------------------------
5720 Conflict: -lp  conflicts with -io, -fnl, -nanl, or -ndnl; ignoring -lp
5721     
5722 The -lp indentation logic requires that perltidy be able to coordinate
5723 arbitrarily large numbers of line breakpoints.  This isn't possible
5724 with these flags. Sometimes an acceptable workaround is to use -wocb=3
5725 -----------------------------------------------------------------------
5726 EOM
5727             $rOpts->{'line-up-parentheses'} = 0;
5728         }
5729     }
5730
5731     # At present, tabs are not compatible with the line-up-parentheses style
5732     # (it would be possible to entab the total leading whitespace
5733     # just prior to writing the line, if desired).
5734     if ( $rOpts->{'line-up-parentheses'} && $rOpts->{'tabs'} ) {
5735         Warn(<<EOM);
5736 Conflict: -t (tabs) cannot be used with the -lp  option; ignoring -t; see -et.
5737 EOM
5738         $rOpts->{'tabs'} = 0;
5739     }
5740
5741     # Likewise, tabs are not compatible with outdenting..
5742     if ( $rOpts->{'outdent-keywords'} && $rOpts->{'tabs'} ) {
5743         Warn(<<EOM);
5744 Conflict: -t (tabs) cannot be used with the -okw options; ignoring -t; see -et.
5745 EOM
5746         $rOpts->{'tabs'} = 0;
5747     }
5748
5749     if ( $rOpts->{'outdent-labels'} && $rOpts->{'tabs'} ) {
5750         Warn(<<EOM);
5751 Conflict: -t (tabs) cannot be used with the -ola  option; ignoring -t; see -et.
5752 EOM
5753         $rOpts->{'tabs'} = 0;
5754     }
5755
5756     if ( !$rOpts->{'space-for-semicolon'} ) {
5757         $want_left_space{'f'} = -1;
5758     }
5759
5760     if ( $rOpts->{'space-terminal-semicolon'} ) {
5761         $want_left_space{';'} = 1;
5762     }
5763
5764     # implement outdenting preferences for keywords
5765     %outdent_keyword = ();
5766     my @okw = split_words( $rOpts->{'outdent-keyword-okl'} );
5767     unless (@okw) {
5768         @okw = qw(next last redo goto return);    # defaults
5769     }
5770
5771     # FUTURE: if not a keyword, assume that it is an identifier
5772     foreach (@okw) {
5773         if ( $Perl::Tidy::Tokenizer::is_keyword{$_} ) {
5774             $outdent_keyword{$_} = 1;
5775         }
5776         else {
5777             Warn("ignoring '$_' in -okwl list; not a perl keyword");
5778         }
5779     }
5780
5781     # implement user whitespace preferences
5782     if ( my @q = split_words( $rOpts->{'want-left-space'} ) ) {
5783         @want_left_space{@q} = (1) x scalar(@q);
5784     }
5785
5786     if ( my @q = split_words( $rOpts->{'want-right-space'} ) ) {
5787         @want_right_space{@q} = (1) x scalar(@q);
5788     }
5789
5790     if ( my @q = split_words( $rOpts->{'nowant-left-space'} ) ) {
5791         @want_left_space{@q} = (-1) x scalar(@q);
5792     }
5793
5794     if ( my @q = split_words( $rOpts->{'nowant-right-space'} ) ) {
5795         @want_right_space{@q} = (-1) x scalar(@q);
5796     }
5797     if ( $rOpts->{'dump-want-left-space'} ) {
5798         dump_want_left_space(*STDOUT);
5799         Exit(0);
5800     }
5801
5802     if ( $rOpts->{'dump-want-right-space'} ) {
5803         dump_want_right_space(*STDOUT);
5804         Exit(0);
5805     }
5806
5807     # default keywords for which space is introduced before an opening paren
5808     # (at present, including them messes up vertical alignment)
5809     my @sak = qw(my local our and or err eq ne if else elsif until
5810       unless while for foreach return switch case given when catch);
5811     @space_after_keyword{@sak} = (1) x scalar(@sak);
5812
5813     # first remove any or all of these if desired
5814     if ( my @q = split_words( $rOpts->{'nospace-after-keyword'} ) ) {
5815
5816         # -nsak='*' selects all the above keywords
5817         if ( @q == 1 && $q[0] eq '*' ) { @q = keys(%space_after_keyword) }
5818         @space_after_keyword{@q} = (0) x scalar(@q);
5819     }
5820
5821     # then allow user to add to these defaults
5822     if ( my @q = split_words( $rOpts->{'space-after-keyword'} ) ) {
5823         @space_after_keyword{@q} = (1) x scalar(@q);
5824     }
5825
5826     # implement user break preferences
5827     my @all_operators = qw(% + - * / x != == >= <= =~ !~ < > | &
5828       = **= += *= &= <<= &&= -= /= |= >>= ||= //= .= %= ^= x=
5829       . : ? && || and or err xor
5830     );
5831
5832     my $break_after = sub {
5833         my @toks = @_;
5834         foreach my $tok (@toks) {
5835             if ( $tok eq '?' ) { $tok = ':' }    # patch to coordinate ?/:
5836             my $lbs = $left_bond_strength{$tok};
5837             my $rbs = $right_bond_strength{$tok};
5838             if ( defined($lbs) && defined($rbs) && $lbs < $rbs ) {
5839                 ( $right_bond_strength{$tok}, $left_bond_strength{$tok} ) =
5840                   ( $lbs, $rbs );
5841             }
5842         }
5843     };
5844
5845     my $break_before = sub {
5846         my @toks = @_;
5847         foreach my $tok (@toks) {
5848             my $lbs = $left_bond_strength{$tok};
5849             my $rbs = $right_bond_strength{$tok};
5850             if ( defined($lbs) && defined($rbs) && $rbs < $lbs ) {
5851                 ( $right_bond_strength{$tok}, $left_bond_strength{$tok} ) =
5852                   ( $lbs, $rbs );
5853             }
5854         }
5855     };
5856
5857     $break_after->(@all_operators) if ( $rOpts->{'break-after-all-operators'} );
5858     $break_before->(@all_operators)
5859       if ( $rOpts->{'break-before-all-operators'} );
5860
5861     $break_after->( split_words( $rOpts->{'want-break-after'} ) );
5862     $break_before->( split_words( $rOpts->{'want-break-before'} ) );
5863
5864     # make note if breaks are before certain key types
5865     %want_break_before = ();
5866     foreach my $tok ( @all_operators, ',' ) {
5867         $want_break_before{$tok} =
5868           $left_bond_strength{$tok} < $right_bond_strength{$tok};
5869     }
5870
5871     # Coordinate ?/: breaks, which must be similar
5872     if ( !$want_break_before{':'} ) {
5873         $want_break_before{'?'}   = $want_break_before{':'};
5874         $right_bond_strength{'?'} = $right_bond_strength{':'} + 0.01;
5875         $left_bond_strength{'?'}  = NO_BREAK;
5876     }
5877
5878     # Define here tokens which may follow the closing brace of a do statement
5879     # on the same line, as in:
5880     #   } while ( $something);
5881     my @dof = qw(until while unless if ; : );
5882     push @dof, ',';
5883     @is_do_follower{@dof} = (1) x scalar(@dof);
5884
5885     # What tokens may follow the closing brace of an if or elsif block?
5886     # Not used. Previously used for cuddled else, but no longer needed.
5887     %is_if_brace_follower = ();
5888
5889     # nothing can follow the closing curly of an else { } block:
5890     %is_else_brace_follower = ();
5891
5892     # what can follow a multi-line anonymous sub definition closing curly:
5893     my @asf = qw# ; : => or and  && || ~~ !~~ ) #;
5894     push @asf, ',';
5895     @is_anon_sub_brace_follower{@asf} = (1) x scalar(@asf);
5896
5897     # what can follow a one-line anonymous sub closing curly:
5898     # one-line anonymous subs also have ']' here...
5899     # see tk3.t and PP.pm
5900     my @asf1 = qw#  ; : => or and  && || ) ] ~~ !~~ #;
5901     push @asf1, ',';
5902     @is_anon_sub_1_brace_follower{@asf1} = (1) x scalar(@asf1);
5903
5904     # What can follow a closing curly of a block
5905     # which is not an if/elsif/else/do/sort/map/grep/eval/sub
5906     # Testfiles: 'Toolbar.pm', 'Menubar.pm', bless.t, '3rules.pl'
5907     my @obf = qw#  ; : => or and  && || ) #;
5908     push @obf, ',';
5909     @is_other_brace_follower{@obf} = (1) x scalar(@obf);
5910
5911     $right_bond_strength{'{'} = WEAK;
5912     $left_bond_strength{'{'}  = VERY_STRONG;
5913
5914     # make -l=0  equal to -l=infinite
5915     if ( !$rOpts->{'maximum-line-length'} ) {
5916         $rOpts->{'maximum-line-length'} = 1000000;
5917     }
5918
5919     # make -lbl=0  equal to -lbl=infinite
5920     if ( !$rOpts->{'long-block-line-count'} ) {
5921         $rOpts->{'long-block-line-count'} = 1000000;
5922     }
5923
5924     my $enc = $rOpts->{'character-encoding'};
5925     if ( $enc && $enc !~ /^(none|utf8)$/i ) {
5926         Die(<<EOM);
5927 Unrecognized character-encoding '$enc'; expecting one of: (none, utf8)
5928 EOM
5929     }
5930
5931     my $ole = $rOpts->{'output-line-ending'};
5932     if ($ole) {
5933         my %endings = (
5934             dos  => "\015\012",
5935             win  => "\015\012",
5936             mac  => "\015",
5937             unix => "\012",
5938         );
5939
5940         # Patch for RT #99514, a memoization issue.
5941         # Normally, the user enters one of 'dos', 'win', etc, and we change the
5942         # value in the options parameter to be the corresponding line ending
5943         # character.  But, if we are using memoization, on later passes through
5944         # here the option parameter will already have the desired ending
5945         # character rather than the keyword 'dos', 'win', etc.  So
5946         # we must check to see if conversion has already been done and, if so,
5947         # bypass the conversion step.
5948         my %endings_inverted = (
5949             "\015\012" => 'dos',
5950             "\015\012" => 'win',
5951             "\015"     => 'mac',
5952             "\012"     => 'unix',
5953         );
5954
5955         if ( defined( $endings_inverted{$ole} ) ) {
5956
5957             # we already have valid line ending, nothing more to do
5958         }
5959         else {
5960             $ole = lc $ole;
5961             unless ( $rOpts->{'output-line-ending'} = $endings{$ole} ) {
5962                 my $str = join " ", keys %endings;
5963                 Die(<<EOM);
5964 Unrecognized line ending '$ole'; expecting one of: $str
5965 EOM
5966             }
5967             if ( $rOpts->{'preserve-line-endings'} ) {
5968                 Warn("Ignoring -ple; conflicts with -ole\n");
5969                 $rOpts->{'preserve-line-endings'} = undef;
5970             }
5971         }
5972     }
5973
5974     # hashes used to simplify setting whitespace
5975     %tightness = (
5976         '{' => $rOpts->{'brace-tightness'},
5977         '}' => $rOpts->{'brace-tightness'},
5978         '(' => $rOpts->{'paren-tightness'},
5979         ')' => $rOpts->{'paren-tightness'},
5980         '[' => $rOpts->{'square-bracket-tightness'},
5981         ']' => $rOpts->{'square-bracket-tightness'},
5982     );
5983     %matching_token = (
5984         '{' => '}',
5985         '(' => ')',
5986         '[' => ']',
5987         '?' => ':',
5988     );
5989
5990     if ( $rOpts->{'ignore-old-breakpoints'} ) {
5991         if ( $rOpts->{'break-at-old-method-breakpoints'} ) {
5992             Warn("Conflicting parameters: -iob and -bom; -bom will be ignored\n"
5993             );
5994         }
5995         if ( $rOpts->{'break-at-old-comma-breakpoints'} ) {
5996             Warn("Conflicting parameters: -iob and -boc; -boc will be ignored\n"
5997             );
5998         }
5999
6000         # Note: there are additional parameters that can be made inactive by
6001         # -iob, but they are on by default so we would generate excessive
6002         # warnings if we noted them. They are:
6003         # $rOpts->{'break-at-old-keyword-breakpoints'}
6004         # $rOpts->{'break-at-old-logical-breakpoints'}
6005         # $rOpts->{'break-at-old-ternary-breakpoints'}
6006         # $rOpts->{'break-at-old-attribute-breakpoints'}
6007     }
6008
6009     # frequently used parameters
6010     $rOpts_add_newlines          = $rOpts->{'add-newlines'};
6011     $rOpts_add_whitespace        = $rOpts->{'add-whitespace'};
6012     $rOpts_block_brace_tightness = $rOpts->{'block-brace-tightness'};
6013     $rOpts_block_brace_vertical_tightness =
6014       $rOpts->{'block-brace-vertical-tightness'};
6015     $rOpts_brace_left_and_indent   = $rOpts->{'brace-left-and-indent'};
6016     $rOpts_comma_arrow_breakpoints = $rOpts->{'comma-arrow-breakpoints'};
6017     $rOpts_break_at_old_ternary_breakpoints =
6018       $rOpts->{'break-at-old-ternary-breakpoints'};
6019     $rOpts_break_at_old_attribute_breakpoints =
6020       $rOpts->{'break-at-old-attribute-breakpoints'};
6021     $rOpts_break_at_old_comma_breakpoints =
6022       $rOpts->{'break-at-old-comma-breakpoints'};
6023     $rOpts_break_at_old_keyword_breakpoints =
6024       $rOpts->{'break-at-old-keyword-breakpoints'};
6025     $rOpts_break_at_old_logical_breakpoints =
6026       $rOpts->{'break-at-old-logical-breakpoints'};
6027     $rOpts_break_at_old_method_breakpoints =
6028       $rOpts->{'break-at-old-method-breakpoints'};
6029     $rOpts_closing_side_comment_else_flag =
6030       $rOpts->{'closing-side-comment-else-flag'};
6031     $rOpts_closing_side_comment_maximum_text =
6032       $rOpts->{'closing-side-comment-maximum-text'};
6033     $rOpts_continuation_indentation  = $rOpts->{'continuation-indentation'};
6034     $rOpts_delete_old_whitespace     = $rOpts->{'delete-old-whitespace'};
6035     $rOpts_fuzzy_line_length         = $rOpts->{'fuzzy-line-length'};
6036     $rOpts_indent_columns            = $rOpts->{'indent-columns'};
6037     $rOpts_line_up_parentheses       = $rOpts->{'line-up-parentheses'};
6038     $rOpts_maximum_fields_per_table  = $rOpts->{'maximum-fields-per-table'};
6039     $rOpts_maximum_line_length       = $rOpts->{'maximum-line-length'};
6040     $rOpts_whitespace_cycle          = $rOpts->{'whitespace-cycle'};
6041     $rOpts_one_line_block_semicolons = $rOpts->{'one-line-block-semicolons'};
6042
6043     $rOpts_variable_maximum_line_length =
6044       $rOpts->{'variable-maximum-line-length'};
6045     $rOpts_short_concatenation_item_length =
6046       $rOpts->{'short-concatenation-item-length'};
6047
6048     $rOpts_keep_old_blank_lines     = $rOpts->{'keep-old-blank-lines'};
6049     $rOpts_ignore_old_breakpoints   = $rOpts->{'ignore-old-breakpoints'};
6050     $rOpts_format_skipping          = $rOpts->{'format-skipping'};
6051     $rOpts_space_function_paren     = $rOpts->{'space-function-paren'};
6052     $rOpts_space_keyword_paren      = $rOpts->{'space-keyword-paren'};
6053     $rOpts_keep_interior_semicolons = $rOpts->{'keep-interior-semicolons'};
6054     $rOpts_ignore_side_comment_lengths =
6055       $rOpts->{'ignore-side-comment-lengths'};
6056
6057     # Note that both opening and closing tokens can access the opening
6058     # and closing flags of their container types.
6059     %opening_vertical_tightness = (
6060         '(' => $rOpts->{'paren-vertical-tightness'},
6061         '{' => $rOpts->{'brace-vertical-tightness'},
6062         '[' => $rOpts->{'square-bracket-vertical-tightness'},
6063         ')' => $rOpts->{'paren-vertical-tightness'},
6064         '}' => $rOpts->{'brace-vertical-tightness'},
6065         ']' => $rOpts->{'square-bracket-vertical-tightness'},
6066     );
6067
6068     %closing_vertical_tightness = (
6069         '(' => $rOpts->{'paren-vertical-tightness-closing'},
6070         '{' => $rOpts->{'brace-vertical-tightness-closing'},
6071         '[' => $rOpts->{'square-bracket-vertical-tightness-closing'},
6072         ')' => $rOpts->{'paren-vertical-tightness-closing'},
6073         '}' => $rOpts->{'brace-vertical-tightness-closing'},
6074         ']' => $rOpts->{'square-bracket-vertical-tightness-closing'},
6075     );
6076
6077     # assume flag for '>' same as ')' for closing qw quotes
6078     %closing_token_indentation = (
6079         ')' => $rOpts->{'closing-paren-indentation'},
6080         '}' => $rOpts->{'closing-brace-indentation'},
6081         ']' => $rOpts->{'closing-square-bracket-indentation'},
6082         '>' => $rOpts->{'closing-paren-indentation'},
6083     );
6084
6085     # flag indicating if any closing tokens are indented
6086     $some_closing_token_indentation =
6087          $rOpts->{'closing-paren-indentation'}
6088       || $rOpts->{'closing-brace-indentation'}
6089       || $rOpts->{'closing-square-bracket-indentation'}
6090       || $rOpts->{'indent-closing-brace'};
6091
6092     %opening_token_right = (
6093         '(' => $rOpts->{'opening-paren-right'},
6094         '{' => $rOpts->{'opening-hash-brace-right'},
6095         '[' => $rOpts->{'opening-square-bracket-right'},
6096     );
6097
6098     %stack_opening_token = (
6099         '(' => $rOpts->{'stack-opening-paren'},
6100         '{' => $rOpts->{'stack-opening-hash-brace'},
6101         '[' => $rOpts->{'stack-opening-square-bracket'},
6102     );
6103
6104     %stack_closing_token = (
6105         ')' => $rOpts->{'stack-closing-paren'},
6106         '}' => $rOpts->{'stack-closing-hash-brace'},
6107         ']' => $rOpts->{'stack-closing-square-bracket'},
6108     );
6109     $rOpts_stack_closing_block_brace = $rOpts->{'stack-closing-block-brace'};
6110     $rOpts_space_backslash_quote     = $rOpts->{'space-backslash-quote'};
6111     return;
6112 }
6113
6114 sub bad_pattern {
6115
6116     # See if a pattern will compile. We have to use a string eval here,
6117     # but it should be safe because the pattern has been constructed
6118     # by this program.
6119     my ($pattern) = @_;
6120     eval "'##'=~/$pattern/";
6121     return $@;
6122 }
6123
6124 {
6125     my %no_cuddle;
6126
6127     # Add keywords here which really should not be cuddled
6128     BEGIN {
6129         my @q = qw(if unless for foreach while);
6130         @no_cuddle{@q} = (1) x scalar(@q);
6131     }
6132
6133     sub prepare_cuddled_block_types {
6134
6135         # the cuddled-else style, if used, is controlled by a hash that
6136         # we construct here
6137
6138         # Include keywords here which should not be cuddled
6139
6140         my $cuddled_string = "";
6141         if ( $rOpts->{'cuddled-else'} ) {
6142
6143             # set the default
6144             $cuddled_string = 'elsif else continue catch finally'
6145               unless ( $rOpts->{'cuddled-block-list-exclusive'} );
6146
6147             # This is the old equivalent but more complex version
6148             # $cuddled_string = 'if-elsif-else unless-elsif-else -continue ';
6149
6150             # Add users other blocks to be cuddled
6151             my $cuddled_block_list = $rOpts->{'cuddled-block-list'};
6152             if ($cuddled_block_list) {
6153                 $cuddled_string .= " " . $cuddled_block_list;
6154             }
6155
6156         }
6157
6158         # If we have a cuddled string of the form
6159         #  'try-catch-finally'
6160
6161         # we want to prepare a hash of the form
6162
6163         # $rcuddled_block_types = {
6164         #    'try' => {
6165         #        'catch'   => 1,
6166         #        'finally' => 1
6167         #    },
6168         # };
6169
6170         # use -dcbl to dump this hash
6171
6172         # Multiple such strings are input as a space or comma separated list
6173
6174         # If we get two lists with the same leading type, such as
6175         #   -cbl = "-try-catch-finally  -try-catch-otherwise"
6176         # then they will get merged as follows:
6177         # $rcuddled_block_types = {
6178         #    'try' => {
6179         #        'catch'     => 1,
6180         #        'finally'   => 2,
6181         #        'otherwise' => 1,
6182         #    },
6183         # };
6184         # This will allow either type of chain to be followed.
6185
6186         $cuddled_string =~ s/,/ /g;    # allow space or comma separated lists
6187         my @cuddled_strings = split /\s+/, $cuddled_string;
6188
6189         $rcuddled_block_types = {};
6190
6191         # process each dash-separated string...
6192         my $string_count = 0;
6193         foreach my $string (@cuddled_strings) {
6194             next unless $string;
6195             my @words = split /-+/, $string;    # allow multiple dashes
6196
6197             # we could look for and report possible errors here...
6198             next unless ( @words > 0 );
6199
6200            # allow either '-continue' or *-continue' for arbitrary starting type
6201             my $start = '*';
6202
6203             # a single word without dashes is a secondary block type
6204             if ( @words > 1 ) {
6205                 $start = shift @words;
6206             }
6207
6208             # always make an entry for the leading word. If none follow, this
6209             # will still prevent a wildcard from matching this word.
6210             if ( !defined( $rcuddled_block_types->{$start} ) ) {
6211                 $rcuddled_block_types->{$start} = {};
6212             }
6213
6214             # The count gives the original word order in case we ever want it.
6215             $string_count++;
6216             my $word_count = 0;
6217             foreach my $word (@words) {
6218                 next unless $word;
6219                 if ( $no_cuddle{$word} ) {
6220                     Warn(
6221 "## Ignoring keyword '$word' in -cbl; does not seem right\n"
6222                     );
6223                     next;
6224                 }
6225                 $word_count++;
6226                 $rcuddled_block_types->{$start}->{$word} =
6227                   1;    #"$string_count.$word_count";
6228
6229                 # git#9: Remove this word from the list of desired one-line
6230                 # blocks
6231                 $want_one_line_block{$word} = 0;
6232             }
6233         }
6234         return;
6235     }
6236 }
6237
6238 sub dump_cuddled_block_list {
6239     my ($fh) = @_;
6240
6241     # ORIGINAL METHOD: Here is the format of the cuddled block type hash
6242     # which controls this routine
6243     #    my $rcuddled_block_types = {
6244     #        'if' => {
6245     #            'else'  => 1,
6246     #            'elsif' => 1
6247     #        },
6248     #        'try' => {
6249     #            'catch'   => 1,
6250     #            'finally' => 1
6251     #        },
6252     #    };
6253
6254     # SIMPLFIED METHOD: the simplified method uses a wildcard for
6255     # the starting block type and puts all cuddled blocks together:
6256     #    my $rcuddled_block_types = {
6257     #        '*' => {
6258     #            'else'  => 1,
6259     #            'elsif' => 1
6260     #            'catch'   => 1,
6261     #            'finally' => 1
6262     #        },
6263     #    };
6264
6265     # Both methods work, but the simplified method has proven to be adequate and
6266     # easier to manage.
6267
6268     my $cuddled_string = $rOpts->{'cuddled-block-list'};
6269     $cuddled_string = '' unless $cuddled_string;
6270
6271     my $flags = "";
6272     $flags .= "-ce" if ( $rOpts->{'cuddled-else'} );
6273     $flags .= " -cbl='$cuddled_string'";
6274
6275     unless ( $rOpts->{'cuddled-else'} ) {
6276         $flags .= "\nNote: You must specify -ce to generate a cuddled hash";
6277     }
6278
6279     $fh->print(<<EOM);
6280 ------------------------------------------------------------------------
6281 Hash of cuddled block types prepared for a run with these parameters:
6282   $flags
6283 ------------------------------------------------------------------------
6284 EOM
6285
6286     use Data::Dumper;
6287     $fh->print( Dumper($rcuddled_block_types) );
6288
6289     $fh->print(<<EOM);
6290 ------------------------------------------------------------------------
6291 EOM
6292     return;
6293 }
6294
6295 sub make_static_block_comment_pattern {
6296
6297     # create the pattern used to identify static block comments
6298     $static_block_comment_pattern = '^\s*##';
6299
6300     # allow the user to change it
6301     if ( $rOpts->{'static-block-comment-prefix'} ) {
6302         my $prefix = $rOpts->{'static-block-comment-prefix'};
6303         $prefix =~ s/^\s*//;
6304         my $pattern = $prefix;
6305
6306         # user may give leading caret to force matching left comments only
6307         if ( $prefix !~ /^\^#/ ) {
6308             if ( $prefix !~ /^#/ ) {
6309                 Die(
6310 "ERROR: the -sbcp prefix is '$prefix' but must begin with '#' or '^#'\n"
6311                 );
6312             }
6313             $pattern = '^\s*' . $prefix;
6314         }
6315         if ( bad_pattern($pattern) ) {
6316             Die(
6317 "ERROR: the -sbc prefix '$prefix' causes the invalid regex '$pattern'\n"
6318             );
6319         }
6320         $static_block_comment_pattern = $pattern;
6321     }
6322     return;
6323 }
6324
6325 sub make_format_skipping_pattern {
6326     my ( $opt_name, $default ) = @_;
6327     my $param = $rOpts->{$opt_name};
6328     unless ($param) { $param = $default }
6329     $param =~ s/^\s*//;
6330     if ( $param !~ /^#/ ) {
6331         Die("ERROR: the $opt_name parameter '$param' must begin with '#'\n");
6332     }
6333     my $pattern = '^' . $param . '\s';
6334     if ( bad_pattern($pattern) ) {
6335         Die(
6336 "ERROR: the $opt_name parameter '$param' causes the invalid regex '$pattern'\n"
6337         );
6338     }
6339     return $pattern;
6340 }
6341
6342 sub make_closing_side_comment_list_pattern {
6343
6344     # turn any input list into a regex for recognizing selected block types
6345     $closing_side_comment_list_pattern = '^\w+';
6346     if ( defined( $rOpts->{'closing-side-comment-list'} )
6347         && $rOpts->{'closing-side-comment-list'} )
6348     {
6349         $closing_side_comment_list_pattern =
6350           make_block_pattern( '-cscl', $rOpts->{'closing-side-comment-list'} );
6351     }
6352     return;
6353 }
6354
6355 sub make_sub_matching_pattern {
6356
6357     $SUB_PATTERN  = '^sub\s+(::|\w)';
6358     $ASUB_PATTERN = '^sub$';
6359
6360     if ( $rOpts->{'sub-alias-list'} ) {
6361
6362         # Note that any 'sub-alias-list' has been preprocessed to
6363         # be a trimmed, space-separated list which includes 'sub'
6364         # for example, it might be 'sub method fun'
6365         my $sub_alias_list = $rOpts->{'sub-alias-list'};
6366         $sub_alias_list =~ s/\s+/\|/g;
6367         $SUB_PATTERN    =~ s/sub/\($sub_alias_list\)/;
6368         $ASUB_PATTERN   =~ s/sub/\($sub_alias_list\)/;
6369     }
6370     return;
6371 }
6372
6373 sub make_bli_pattern {
6374
6375     if ( defined( $rOpts->{'brace-left-and-indent-list'} )
6376         && $rOpts->{'brace-left-and-indent-list'} )
6377     {
6378         $bli_list_string = $rOpts->{'brace-left-and-indent-list'};
6379     }
6380
6381     $bli_pattern = make_block_pattern( '-blil', $bli_list_string );
6382     return;
6383 }
6384
6385 sub make_keyword_group_list_pattern {
6386
6387     # turn any input list into a regex for recognizing selected block types.
6388     # Here are the defaults:
6389     $keyword_group_list_pattern         = '^(our|local|my|use|require|)$';
6390     $keyword_group_list_comment_pattern = '';
6391     if ( defined( $rOpts->{'keyword-group-blanks-list'} )
6392         && $rOpts->{'keyword-group-blanks-list'} )
6393     {
6394         my @words = split /\s+/, $rOpts->{'keyword-group-blanks-list'};
6395         my @keyword_list;
6396         my @comment_list;
6397         foreach my $word (@words) {
6398             if ( $word =~ /^(BC|SBC)$/ ) {
6399                 push @comment_list, $word;
6400                 if ( $word eq 'SBC' ) { push @comment_list, 'SBCX' }
6401             }
6402             else {
6403                 push @keyword_list, $word;
6404             }
6405         }
6406         $keyword_group_list_pattern =
6407           make_block_pattern( '-kgbl', $rOpts->{'keyword-group-blanks-list'} );
6408         $keyword_group_list_comment_pattern =
6409           make_block_pattern( '-kgbl', join( ' ', @comment_list ) );
6410     }
6411     return;
6412 }
6413
6414 sub make_block_brace_vertical_tightness_pattern {
6415
6416     # turn any input list into a regex for recognizing selected block types
6417     $block_brace_vertical_tightness_pattern =
6418       '^((if|else|elsif|unless|while|for|foreach|do|\w+:)$|sub)';
6419     if ( defined( $rOpts->{'block-brace-vertical-tightness-list'} )
6420         && $rOpts->{'block-brace-vertical-tightness-list'} )
6421     {
6422         $block_brace_vertical_tightness_pattern =
6423           make_block_pattern( '-bbvtl',
6424             $rOpts->{'block-brace-vertical-tightness-list'} );
6425     }
6426     return;
6427 }
6428
6429 sub make_blank_line_pattern {
6430
6431     $blank_lines_before_closing_block_pattern = $SUB_PATTERN;
6432     my $key = 'blank-lines-before-closing-block-list';
6433     if ( defined( $rOpts->{$key} ) && $rOpts->{$key} ) {
6434         $blank_lines_before_closing_block_pattern =
6435           make_block_pattern( '-blbcl', $rOpts->{$key} );
6436     }
6437
6438     $blank_lines_after_opening_block_pattern = $SUB_PATTERN;
6439     $key = 'blank-lines-after-opening-block-list';
6440     if ( defined( $rOpts->{$key} ) && $rOpts->{$key} ) {
6441         $blank_lines_after_opening_block_pattern =
6442           make_block_pattern( '-blaol', $rOpts->{$key} );
6443     }
6444     return;
6445 }
6446
6447 sub make_block_pattern {
6448
6449     #  given a string of block-type keywords, return a regex to match them
6450     #  The only tricky part is that labels are indicated with a single ':'
6451     #  and the 'sub' token text may have additional text after it (name of
6452     #  sub).
6453     #
6454     #  Example:
6455     #
6456     #   input string: "if else elsif unless while for foreach do : sub";
6457     #   pattern:  '^((if|else|elsif|unless|while|for|foreach|do|\w+:)$|sub)';
6458
6459     #  Minor Update:
6460     #
6461     #  To distinguish between anonymous subs and named subs, use 'sub' to
6462     #   indicate a named sub, and 'asub' to indicate an anonymous sub
6463
6464     my ( $abbrev, $string ) = @_;
6465     my @list  = split_words($string);
6466     my @words = ();
6467     my %seen;
6468     for my $i (@list) {
6469         if ( $i eq '*' ) { my $pattern = '^.*'; return $pattern }
6470         next if $seen{$i};
6471         $seen{$i} = 1;
6472         if ( $i eq 'sub' ) {
6473         }
6474         elsif ( $i eq 'asub' ) {
6475         }
6476         elsif ( $i eq ';' ) {
6477             push @words, ';';
6478         }
6479         elsif ( $i eq '{' ) {
6480             push @words, '\{';
6481         }
6482         elsif ( $i eq ':' ) {
6483             push @words, '\w+:';
6484         }
6485         elsif ( $i =~ /^\w/ ) {
6486             push @words, $i;
6487         }
6488         else {
6489             Warn("unrecognized block type $i after $abbrev, ignoring\n");
6490         }
6491     }
6492     my $pattern      = '(' . join( '|', @words ) . ')$';
6493     my $sub_patterns = "";
6494     if ( $seen{'sub'} ) {
6495         $sub_patterns .= '|' . $SUB_PATTERN;
6496     }
6497     if ( $seen{'asub'} ) {
6498         $sub_patterns .= '|' . $ASUB_PATTERN;
6499     }
6500     if ($sub_patterns) {
6501         $pattern = '(' . $pattern . $sub_patterns . ')';
6502     }
6503     $pattern = '^' . $pattern;
6504     return $pattern;
6505 }
6506
6507 sub make_static_side_comment_pattern {
6508
6509     # create the pattern used to identify static side comments
6510     $static_side_comment_pattern = '^##';
6511
6512     # allow the user to change it
6513     if ( $rOpts->{'static-side-comment-prefix'} ) {
6514         my $prefix = $rOpts->{'static-side-comment-prefix'};
6515         $prefix =~ s/^\s*//;
6516         my $pattern = '^' . $prefix;
6517         if ( bad_pattern($pattern) ) {
6518             Die(
6519 "ERROR: the -sscp prefix '$prefix' causes the invalid regex '$pattern'\n"
6520             );
6521         }
6522         $static_side_comment_pattern = $pattern;
6523     }
6524     return;
6525 }
6526
6527 sub make_closing_side_comment_prefix {
6528
6529     # Be sure we have a valid closing side comment prefix
6530     my $csc_prefix = $rOpts->{'closing-side-comment-prefix'};
6531     my $csc_prefix_pattern;
6532     if ( !defined($csc_prefix) ) {
6533         $csc_prefix         = '## end';
6534         $csc_prefix_pattern = '^##\s+end';
6535     }
6536     else {
6537         my $test_csc_prefix = $csc_prefix;
6538         if ( $test_csc_prefix !~ /^#/ ) {
6539             $test_csc_prefix = '#' . $test_csc_prefix;
6540         }
6541
6542         # make a regex to recognize the prefix
6543         my $test_csc_prefix_pattern = $test_csc_prefix;
6544
6545         # escape any special characters
6546         $test_csc_prefix_pattern =~ s/([^#\s\w])/\\$1/g;
6547
6548         $test_csc_prefix_pattern = '^' . $test_csc_prefix_pattern;
6549
6550         # allow exact number of intermediate spaces to vary
6551         $test_csc_prefix_pattern =~ s/\s+/\\s\+/g;
6552
6553         # make sure we have a good pattern
6554         # if we fail this we probably have an error in escaping
6555         # characters.
6556
6557         if ( bad_pattern($test_csc_prefix_pattern) ) {
6558
6559             # shouldn't happen..must have screwed up escaping, above
6560             report_definite_bug();
6561             Warn(
6562 "Program Error: the -cscp prefix '$csc_prefix' caused the invalid regex '$csc_prefix_pattern'\n"
6563             );
6564
6565             # just warn and keep going with defaults
6566             Warn("Please consider using a simpler -cscp prefix\n");
6567             Warn("Using default -cscp instead; please check output\n");
6568         }
6569         else {
6570             $csc_prefix         = $test_csc_prefix;
6571             $csc_prefix_pattern = $test_csc_prefix_pattern;
6572         }
6573     }
6574     $rOpts->{'closing-side-comment-prefix'} = $csc_prefix;
6575     $closing_side_comment_prefix_pattern = $csc_prefix_pattern;
6576     return;
6577 }
6578
6579 sub dump_want_left_space {
6580     my $fh = shift;
6581     local $" = "\n";
6582     print $fh <<EOM;
6583 These values are the main control of whitespace to the left of a token type;
6584 They may be altered with the -wls parameter.
6585 For a list of token types, use perltidy --dump-token-types (-dtt)
6586  1 means the token wants a space to its left
6587 -1 means the token does not want a space to its left
6588 ------------------------------------------------------------------------
6589 EOM
6590     foreach my $key ( sort keys %want_left_space ) {
6591         print $fh "$key\t$want_left_space{$key}\n";
6592     }
6593     return;
6594 }
6595
6596 sub dump_want_right_space {
6597     my $fh = shift;
6598     local $" = "\n";
6599     print $fh <<EOM;
6600 These values are the main control of whitespace to the right of a token type;
6601 They may be altered with the -wrs parameter.
6602 For a list of token types, use perltidy --dump-token-types (-dtt)
6603  1 means the token wants a space to its right
6604 -1 means the token does not want a space to its right
6605 ------------------------------------------------------------------------
6606 EOM
6607     foreach my $key ( sort keys %want_right_space ) {
6608         print $fh "$key\t$want_right_space{$key}\n";
6609     }
6610     return;
6611 }
6612
6613 {    # begin is_essential_whitespace
6614
6615     my %is_sort_grep_map;
6616     my %is_for_foreach;
6617
6618     BEGIN {
6619
6620         my @q;
6621         @q = qw(sort grep map);
6622         @is_sort_grep_map{@q} = (1) x scalar(@q);
6623
6624         @q = qw(for foreach);
6625         @is_for_foreach{@q} = (1) x scalar(@q);
6626
6627     }
6628
6629     sub is_essential_whitespace {
6630
6631         # Essential whitespace means whitespace which cannot be safely deleted
6632         # without risking the introduction of a syntax error.
6633         # We are given three tokens and their types:
6634         # ($tokenl, $typel) is the token to the left of the space in question
6635         # ($tokenr, $typer) is the token to the right of the space in question
6636         # ($tokenll, $typell) is previous nonblank token to the left of $tokenl
6637         #
6638         # This is a slow routine but is not needed too often except when -mangle
6639         # is used.
6640         #
6641         # Note: This routine should almost never need to be changed.  It is
6642         # for avoiding syntax problems rather than for formatting.
6643         my ( $tokenll, $typell, $tokenl, $typel, $tokenr, $typer ) = @_;
6644
6645         my $result =
6646
6647           # never combine two bare words or numbers
6648           # examples:  and ::ok(1)
6649           #            return ::spw(...)
6650           #            for bla::bla:: abc
6651           # example is "%overload:: and" in files Dumpvalue.pm or colonbug.pl
6652           #            $input eq"quit" to make $inputeq"quit"
6653           #            my $size=-s::SINK if $file;  <==OK but we won't do it
6654           # don't join something like: for bla::bla:: abc
6655           # example is "%overload:: and" in files Dumpvalue.pm or colonbug.pl
6656           (      ( $tokenl =~ /([\'\w]|\:\:)$/ && $typel ne 'CORE::' )
6657               && ( $tokenr =~ /^([\'\w]|\:\:)/ ) )
6658
6659           # do not combine a number with a concatenation dot
6660           # example: pom.caputo:
6661           # $vt100_compatible ? "\e[0;0H" : ('-' x 78 . "\n");
6662           || ( ( $typel eq 'n' ) && ( $tokenr eq '.' ) )
6663           || ( ( $typer eq 'n' ) && ( $tokenl eq '.' ) )
6664
6665           # do not join a minus with a bare word, because you might form
6666           # a file test operator.  Example from Complex.pm:
6667           # if (CORE::abs($z - i) < $eps); "z-i" would be taken as a file test.
6668           || ( ( $tokenl eq '-' ) && ( $tokenr =~ /^[_A-Za-z]$/ ) )
6669
6670           # do not join a bare word with a minus, like between 'Send' and
6671           # '-recipients' here <<snippets/space3.in>>
6672           #   my $msg = new Fax::Send
6673           #     -recipients => $to,
6674           #     -data => $data;
6675           # This is the safest thing to do. If we had the token to the right of
6676           # the minus we could do a better check.
6677           || ( ( $tokenr eq '-' ) && ( $typel eq 'w' ) )
6678
6679           # and something like this could become ambiguous without space
6680           # after the '-':
6681           #   use constant III=>1;
6682           #   $a = $b - III;
6683           # and even this:
6684           #   $a = - III;
6685           || ( ( $tokenl eq '-' )
6686             && ( $typer =~ /^[wC]$/ && $tokenr =~ /^[_A-Za-z]/ ) )
6687
6688           # '= -' should not become =- or you will get a warning
6689           # about reversed -=
6690           # || ($tokenr eq '-')
6691
6692           # keep a space between a quote and a bareword to prevent the
6693           # bareword from becoming a quote modifier.
6694           || ( ( $typel eq 'Q' ) && ( $tokenr =~ /^[a-zA-Z_]/ ) )
6695
6696           # keep a space between a token ending in '$' and any word;
6697           # this caused trouble:  "die @$ if $@"
6698           || ( ( $typel eq 'i' && $tokenl =~ /\$$/ )
6699             && ( $tokenr =~ /^[a-zA-Z_]/ ) )
6700
6701           # perl is very fussy about spaces before <<
6702           || ( $tokenr =~ /^\<\</ )
6703
6704           # avoid combining tokens to create new meanings. Example:
6705           #     $a+ +$b must not become $a++$b
6706           || ( $is_digraph{ $tokenl . $tokenr } )
6707           || ( $is_trigraph{ $tokenl . $tokenr } )
6708
6709           # another example: do not combine these two &'s:
6710           #     allow_options & &OPT_EXECCGI
6711           || ( $is_digraph{ $tokenl . substr( $tokenr, 0, 1 ) } )
6712
6713           # don't combine $$ or $# with any alphanumeric
6714           # (testfile mangle.t with --mangle)
6715           || ( ( $tokenl =~ /^\$[\$\#]$/ ) && ( $tokenr =~ /^\w/ ) )
6716
6717           # retain any space after possible filehandle
6718           # (testfiles prnterr1.t with --extrude and mangle.t with --mangle)
6719           || ( $typel eq 'Z' )
6720
6721           # Perl is sensitive to whitespace after the + here:
6722           #  $b = xvals $a + 0.1 * yvals $a;
6723           || ( $typell eq 'Z' && $typel =~ /^[\/\?\+\-\*]$/ )
6724
6725           # keep paren separate in 'use Foo::Bar ()'
6726           || ( $tokenr eq '('
6727             && $typel eq 'w'
6728             && $typell eq 'k'
6729             && $tokenll eq 'use' )
6730
6731           # keep any space between filehandle and paren:
6732           # file mangle.t with --mangle:
6733           || ( $typel eq 'Y' && $tokenr eq '(' )
6734
6735           # retain any space after here doc operator ( hereerr.t)
6736           || ( $typel eq 'h' )
6737
6738           # be careful with a space around ++ and --, to avoid ambiguity as to
6739           # which token it applies
6740           || ( ( $typer =~ /^(pp|mm)$/ )     && ( $tokenl !~ /^[\;\{\(\[]/ ) )
6741           || ( ( $typel =~ /^(\+\+|\-\-)$/ ) && ( $tokenr !~ /^[\;\}\)\]]/ ) )
6742
6743           # need space after foreach my; for example, this will fail in
6744           # older versions of Perl:
6745           # foreach my$ft(@filetypes)...
6746           || (
6747             $tokenl eq 'my'
6748
6749             #  /^(for|foreach)$/
6750             && $is_for_foreach{$tokenll}
6751             && $tokenr =~ /^\$/
6752           )
6753
6754           # must have space between grep and left paren; "grep(" will fail
6755           || ( $tokenr eq '(' && $is_sort_grep_map{$tokenl} )
6756
6757           # don't stick numbers next to left parens, as in:
6758           #use Mail::Internet 1.28 (); (see Entity.pm, Head.pm, Test.pm)
6759           || ( ( $typel eq 'n' ) && ( $tokenr eq '(' ) )
6760
6761           # We must be sure that a space between a ? and a quoted string
6762           # remains if the space before the ? remains.  [Loca.pm, lockarea]
6763           # ie,
6764           #    $b=join $comma ? ',' : ':', @_;  # ok
6765           #    $b=join $comma?',' : ':', @_;    # ok!
6766           #    $b=join $comma ?',' : ':', @_;   # error!
6767           # Not really required:
6768           ## || ( ( $typel eq '?' ) && ( $typer eq 'Q' ) )
6769
6770           # do not remove space between an '&' and a bare word because
6771           # it may turn into a function evaluation, like here
6772           # between '&' and 'O_ACCMODE', producing a syntax error [File.pm]
6773           #    $opts{rdonly} = (($opts{mode} & O_ACCMODE) == O_RDONLY);
6774           || ( ( $typel eq '&' ) && ( $tokenr =~ /^[a-zA-Z_]/ ) )
6775
6776           # space stacked labels  (TODO: check if really necessary)
6777           || ( $typel eq 'J' && $typer eq 'J' )
6778
6779           ;    # the value of this long logic sequence is the result we want
6780 ##if ($typel eq 'j') {print STDERR "typel=$typel typer=$typer result='$result'\n"}
6781         return $result;
6782     }
6783 }
6784
6785 {
6786     my %secret_operators;
6787     my %is_leading_secret_token;
6788
6789     BEGIN {
6790
6791         # token lists for perl secret operators as compiled by Philippe Bruhat
6792         # at: https://metacpan.org/module/perlsecret
6793         %secret_operators = (
6794             'Goatse'             => [qw#= ( ) =#],        #=( )=
6795             'Venus1'             => [qw#0 +#],            # 0+
6796             'Venus2'             => [qw#+ 0#],            # +0
6797             'Enterprise'         => [qw#) x ! !#],        # ()x!!
6798             'Kite1'              => [qw#~ ~ <>#],         # ~~<>
6799             'Kite2'              => [qw#~~ <>#],          # ~~<>
6800             'Winking Fat Comma'  => [ ( ',', '=>' ) ],    # ,=>
6801             'Bang bang         ' => [qw#! !#],            # !!
6802         );
6803
6804         # The following operators and constants are not included because they
6805         # are normally kept tight by perltidy:
6806         # ~~ <~>
6807         #
6808
6809         # Make a lookup table indexed by the first token of each operator:
6810         # first token => [list, list, ...]
6811         foreach my $value ( values(%secret_operators) ) {
6812             my $tok = $value->[0];
6813             push @{ $is_leading_secret_token{$tok} }, $value;
6814         }
6815     }
6816
6817     sub new_secret_operator_whitespace {
6818
6819         my ( $rlong_array, $rwhitespace_flags ) = @_;
6820
6821         # Loop over all tokens in this line
6822         my ( $token, $type );
6823         my $jmax = @{$rlong_array} - 1;
6824         foreach my $j ( 0 .. $jmax ) {
6825
6826             $token = $rlong_array->[$j]->[_TOKEN_];
6827             $type  = $rlong_array->[$j]->[_TYPE_];
6828
6829             # Skip unless this token might start a secret operator
6830             next if ( $type eq 'b' );
6831             next unless ( $is_leading_secret_token{$token} );
6832
6833             #      Loop over all secret operators with this leading token
6834             foreach my $rpattern ( @{ $is_leading_secret_token{$token} } ) {
6835                 my $jend = $j - 1;
6836                 foreach my $tok ( @{$rpattern} ) {
6837                     $jend++;
6838                     $jend++
6839
6840                       if ( $jend <= $jmax
6841                         && $rlong_array->[$jend]->[_TYPE_] eq 'b' );
6842                     if (   $jend > $jmax
6843                         || $tok ne $rlong_array->[$jend]->[_TOKEN_] )
6844                     {
6845                         $jend = undef;
6846                         last;
6847                     }
6848                 }
6849
6850                 if ($jend) {
6851
6852                     # set flags to prevent spaces within this operator
6853                     foreach my $jj ( $j + 1 .. $jend ) {
6854                         $rwhitespace_flags->[$jj] = WS_NO;
6855                     }
6856                     $j = $jend;
6857                     last;
6858                 }
6859             }    ##      End Loop over all operators
6860         }    ## End loop over all tokens
6861         return;
6862     }    # End sub
6863 }
6864
6865 {        # begin print_line_of_tokens
6866
6867     my $rinput_token_array;    # Current working array
6868     my $rinput_K_array;        # Future working array
6869
6870     my $in_quote;
6871     my $guessed_indentation_level;
6872
6873     # This should be a return variable from extract_token
6874     # These local token variables are stored by store_token_to_go:
6875     my $Ktoken_vars;
6876     my $block_type;
6877     my $ci_level;
6878     my $container_environment;
6879     my $container_type;
6880     my $in_continued_quote;
6881     my $level;
6882     my $no_internal_newlines;
6883     my $slevel;
6884     my $token;
6885     my $type;
6886     my $type_sequence;
6887
6888     # routine to pull the jth token from the line of tokens
6889     sub extract_token {
6890         my ( $self, $j ) = @_;
6891
6892         my $rLL = $self->{rLL};
6893         $Ktoken_vars = $rinput_K_array->[$j];
6894         if ( !defined($Ktoken_vars) ) {
6895
6896        # Shouldn't happen: an error here would be due to a recent program change
6897             Fault("undefined index K for j=$j");
6898         }
6899         my $rtoken_vars = $rLL->[$Ktoken_vars];
6900
6901         if ( $rtoken_vars->[_TOKEN_] ne $rLL->[$Ktoken_vars]->[_TOKEN_] ) {
6902
6903        # Shouldn't happen: an error here would be due to a recent program change
6904             Fault(<<EOM);
6905  j=$j, K=$Ktoken_vars, '$rtoken_vars->[_TOKEN_]' ne '$rLL->[$Ktoken_vars]'
6906 EOM
6907         }
6908
6909         #########################################################
6910         # these are now redundant and can eventually be eliminated
6911
6912         $token                 = $rtoken_vars->[_TOKEN_];
6913         $type                  = $rtoken_vars->[_TYPE_];
6914         $block_type            = $rtoken_vars->[_BLOCK_TYPE_];
6915         $container_type        = $rtoken_vars->[_CONTAINER_TYPE_];
6916         $container_environment = $rtoken_vars->[_CONTAINER_ENVIRONMENT_];
6917         $type_sequence         = $rtoken_vars->[_TYPE_SEQUENCE_];
6918         $level                 = $rtoken_vars->[_LEVEL_];
6919         $slevel                = $rtoken_vars->[_SLEVEL_];
6920         $ci_level              = $rtoken_vars->[_CI_LEVEL_];
6921         #########################################################
6922
6923         return;
6924     }
6925
6926     {
6927         my @saved_token;
6928
6929         sub save_current_token {
6930
6931             @saved_token = (
6932                 $block_type,            $ci_level,
6933                 $container_environment, $container_type,
6934                 $in_continued_quote,    $level,
6935                 $no_internal_newlines,  $slevel,
6936                 $token,                 $type,
6937                 $type_sequence,         $Ktoken_vars,
6938             );
6939             return;
6940         }
6941
6942         sub restore_current_token {
6943             (
6944                 $block_type,            $ci_level,
6945                 $container_environment, $container_type,
6946                 $in_continued_quote,    $level,
6947                 $no_internal_newlines,  $slevel,
6948                 $token,                 $type,
6949                 $type_sequence,         $Ktoken_vars,
6950             ) = @saved_token;
6951             return;
6952         }
6953     }
6954
6955     sub token_length {
6956
6957         # Returns the length of a token, given:
6958         #  $token=text of the token
6959         #  $type = type
6960         #  $not_first_token = should be TRUE if this is not the first token of
6961         #   the line.  It might the index of this token in an array.  It is
6962         #   used to test for a side comment vs a block comment.
6963         # Note: Eventually this should be the only routine determining the
6964         # length of a token in this package.
6965         my ( $token, $type, $not_first_token ) = @_;
6966         my $token_length = length($token);
6967
6968         # We mark lengths of side comments as just 1 if we are
6969         # ignoring their lengths when setting line breaks.
6970         $token_length = 1
6971           if ( $rOpts_ignore_side_comment_lengths
6972             && $not_first_token
6973             && $type eq '#' );
6974         return $token_length;
6975     }
6976
6977     sub rtoken_length {
6978
6979         # return length of ith token in @{$rtokens}
6980         my ($i) = @_;
6981         return token_length( $rinput_token_array->[$i]->[_TOKEN_],
6982             $rinput_token_array->[$i]->[_TYPE_], $i );
6983     }
6984
6985     # Routine to place the current token into the output stream.
6986     # Called once per output token.
6987     sub store_token_to_go {
6988
6989         my ( $self, $side_comment_follows ) = @_;
6990
6991         my $flag = $side_comment_follows ? 1 : $no_internal_newlines;
6992
6993         ++$max_index_to_go;
6994         $K_to_go[$max_index_to_go]                     = $Ktoken_vars;
6995         $tokens_to_go[$max_index_to_go]                = $token;
6996         $types_to_go[$max_index_to_go]                 = $type;
6997         $nobreak_to_go[$max_index_to_go]               = $flag;
6998         $old_breakpoint_to_go[$max_index_to_go]        = 0;
6999         $forced_breakpoint_to_go[$max_index_to_go]     = 0;
7000         $block_type_to_go[$max_index_to_go]            = $block_type;
7001         $type_sequence_to_go[$max_index_to_go]         = $type_sequence;
7002         $container_environment_to_go[$max_index_to_go] = $container_environment;
7003         $ci_levels_to_go[$max_index_to_go]             = $ci_level;
7004         $mate_index_to_go[$max_index_to_go]            = -1;
7005         $bond_strength_to_go[$max_index_to_go]         = 0;
7006
7007         # Note: negative levels are currently retained as a diagnostic so that
7008         # the 'final indentation level' is correctly reported for bad scripts.
7009         # But this means that every use of $level as an index must be checked.
7010         # If this becomes too much of a problem, we might give up and just clip
7011         # them at zero.
7012         ## $levels_to_go[$max_index_to_go] = ( $level > 0 ) ? $level : 0;
7013         $levels_to_go[$max_index_to_go]        = $level;
7014         $nesting_depth_to_go[$max_index_to_go] = ( $slevel >= 0 ) ? $slevel : 0;
7015
7016         # link the non-blank tokens
7017         my $iprev = $max_index_to_go - 1;
7018         $iprev-- if ( $iprev >= 0 && $types_to_go[$iprev] eq 'b' );
7019         $iprev_to_go[$max_index_to_go] = $iprev;
7020         $inext_to_go[$iprev]           = $max_index_to_go
7021           if ( $iprev >= 0 && $type ne 'b' );
7022         $inext_to_go[$max_index_to_go] = $max_index_to_go + 1;
7023
7024         $token_lengths_to_go[$max_index_to_go] =
7025           token_length( $token, $type, $max_index_to_go );
7026
7027         # We keep a running sum of token lengths from the start of this batch:
7028         #   summed_lengths_to_go[$i]   = total length to just before token $i
7029         #   summed_lengths_to_go[$i+1] = total length to just after token $i
7030         $summed_lengths_to_go[ $max_index_to_go + 1 ] =
7031           $summed_lengths_to_go[$max_index_to_go] +
7032           $token_lengths_to_go[$max_index_to_go];
7033
7034         # Define the indentation that this token would have if it started
7035         # a new line.  We have to do this now because we need to know this
7036         # when considering one-line blocks.
7037         set_leading_whitespace( $level, $ci_level, $in_continued_quote );
7038
7039         # remember previous nonblank tokens seen
7040         if ( $type ne 'b' ) {
7041             $last_last_nonblank_index_to_go = $last_nonblank_index_to_go;
7042             $last_last_nonblank_type_to_go  = $last_nonblank_type_to_go;
7043             $last_last_nonblank_token_to_go = $last_nonblank_token_to_go;
7044             $last_nonblank_index_to_go      = $max_index_to_go;
7045             $last_nonblank_type_to_go       = $type;
7046             $last_nonblank_token_to_go      = $token;
7047             if ( $type eq ',' ) {
7048                 $comma_count_in_batch++;
7049             }
7050         }
7051
7052         FORMATTER_DEBUG_FLAG_STORE && do {
7053             my ( $a, $b, $c ) = caller();
7054             print STDOUT
7055 "STORE: from $a $c: storing token $token type $type lev=$level slev=$slevel at $max_index_to_go\n";
7056         };
7057         return;
7058     }
7059
7060     sub copy_hash {
7061         my ($rold_token_hash) = @_;
7062         my %new_token_hash =
7063           map { ( $_, $rold_token_hash->{$_} ) } keys %{$rold_token_hash};
7064         return \%new_token_hash;
7065     }
7066
7067     sub copy_array {
7068         my ($rold) = @_;
7069         my @new = map { $_ } @{$rold};
7070         return \@new;
7071     }
7072
7073     sub copy_token_as_type {
7074         my ( $rold_token, $type, $token ) = @_;
7075         if ( $type eq 'b' ) {
7076             $token = " " unless defined($token);
7077         }
7078         elsif ( $type eq 'q' ) {
7079             $token = '' unless defined($token);
7080         }
7081         elsif ( $type eq '->' ) {
7082             $token = '->' unless defined($token);
7083         }
7084         elsif ( $type eq ';' ) {
7085             $token = ';' unless defined($token);
7086         }
7087         else {
7088             Fault(
7089 "Programming error: copy_token_as has type $type but should be 'b' or 'q'"
7090             );
7091         }
7092         my $rnew_token = copy_array($rold_token);
7093         $rnew_token->[_TYPE_]                  = $type;
7094         $rnew_token->[_TOKEN_]                 = $token;
7095         $rnew_token->[_BLOCK_TYPE_]            = '';
7096         $rnew_token->[_CONTAINER_TYPE_]        = '';
7097         $rnew_token->[_CONTAINER_ENVIRONMENT_] = '';
7098         $rnew_token->[_TYPE_SEQUENCE_]         = '';
7099         return $rnew_token;
7100     }
7101
7102     sub boolean_equals {
7103         my ( $val1, $val2 ) = @_;
7104         return ( $val1 && $val2 || !$val1 && !$val2 );
7105     }
7106
7107     sub print_line_of_tokens {
7108
7109         my ( $self, $line_of_tokens ) = @_;
7110
7111         # This routine is called once per input line to process all of
7112         # the tokens on that line.  This is the first stage of
7113         # beautification.
7114         #
7115         # Full-line comments and blank lines may be processed immediately.
7116         #
7117         # For normal lines of code, the tokens are stored one-by-one,
7118         # via calls to 'sub store_token_to_go', until a known line break
7119         # point is reached.  Then, the batch of collected tokens is
7120         # passed along to 'sub output_line_to_go' for further
7121         # processing.  This routine decides if there should be
7122         # whitespace between each pair of non-white tokens, so later
7123         # routines only need to decide on any additional line breaks.
7124         # Any whitespace is initially a single space character.  Later,
7125         # the vertical aligner may expand that to be multiple space
7126         # characters if necessary for alignment.
7127
7128         $input_line_number = $line_of_tokens->{_line_number};
7129         my $input_line = $line_of_tokens->{_line_text};
7130         my $CODE_type  = $line_of_tokens->{_code_type};
7131
7132         my $rK_range = $line_of_tokens->{_rK_range};
7133         my ( $K_first, $K_last ) = @{$rK_range};
7134
7135         my $rLL              = $self->{rLL};
7136         my $rbreak_container = $self->{rbreak_container};
7137         my $rshort_nested    = $self->{rshort_nested};
7138
7139         if ( !defined($K_first) ) {
7140
7141             # Empty line: This can happen if tokens are deleted, for example
7142             # with the -mangle parameter
7143             return;
7144         }
7145
7146         $no_internal_newlines = 1 - $rOpts_add_newlines;
7147         my $is_comment =
7148           ( $K_first == $K_last && $rLL->[$K_first]->[_TYPE_] eq '#' );
7149         my $is_static_block_comment_without_leading_space =
7150           $CODE_type eq 'SBCX';
7151         $is_static_block_comment =
7152           $CODE_type eq 'SBC' || $is_static_block_comment_without_leading_space;
7153         my $is_hanging_side_comment = $CODE_type eq 'HSC';
7154         my $is_VERSION_statement    = $CODE_type eq 'VER';
7155         if ($is_VERSION_statement) {
7156             $saw_VERSION_in_this_file = 1;
7157             $no_internal_newlines     = 1;
7158         }
7159
7160         # Add interline blank if any
7161         my $last_old_nonblank_type   = "b";
7162         my $first_new_nonblank_type  = "b";
7163         my $first_new_nonblank_token = " ";
7164         if ( $max_index_to_go >= 0 ) {
7165             $last_old_nonblank_type   = $types_to_go[$max_index_to_go];
7166             $first_new_nonblank_type  = $rLL->[$K_first]->[_TYPE_];
7167             $first_new_nonblank_token = $rLL->[$K_first]->[_TOKEN_];
7168             if (  !$is_comment
7169                 && $types_to_go[$max_index_to_go] ne 'b'
7170                 && $K_first > 0
7171                 && $rLL->[ $K_first - 1 ]->[_TYPE_] eq 'b' )
7172             {
7173                 $K_first -= 1;
7174             }
7175         }
7176
7177         # Copy the tokens into local arrays
7178         $rinput_token_array = [];
7179         $rinput_K_array     = [];
7180         $rinput_K_array     = [ ( $K_first .. $K_last ) ];
7181         $rinput_token_array = [ map { $rLL->[$_] } @{$rinput_K_array} ];
7182         my $jmax = @{$rinput_K_array} - 1;
7183
7184         $in_continued_quote = $starting_in_quote =
7185           $line_of_tokens->{_starting_in_quote};
7186         $in_quote        = $line_of_tokens->{_ending_in_quote};
7187         $ending_in_quote = $in_quote;
7188         $guessed_indentation_level =
7189           $line_of_tokens->{_guessed_indentation_level};
7190
7191         my $j_next;
7192         my $next_nonblank_token;
7193         my $next_nonblank_token_type;
7194
7195         $block_type            = "";
7196         $container_type        = "";
7197         $container_environment = "";
7198         $type_sequence         = "";
7199
7200         ######################################
7201         # Handle a block (full-line) comment..
7202         ######################################
7203         if ($is_comment) {
7204
7205             if ( $rOpts->{'tee-block-comments'} ) {
7206                 $file_writer_object->tee_on();
7207             }
7208
7209             destroy_one_line_block();
7210             $self->output_line_to_go();
7211
7212             # output a blank line before block comments
7213             if (
7214                 # unless we follow a blank or comment line
7215                 $last_line_leading_type !~ /^[#b]$/
7216
7217                 # only if allowed
7218                 && $rOpts->{'blanks-before-comments'}
7219
7220                 # if this is NOT an empty comment line
7221                 && $rinput_token_array->[0]->[_TOKEN_] ne '#'
7222
7223                 # not after a short line ending in an opening token
7224                 # because we already have space above this comment.
7225                 # Note that the first comment in this if block, after
7226                 # the 'if (', does not get a blank line because of this.
7227                 && !$last_output_short_opening_token
7228
7229                 # never before static block comments
7230                 && !$is_static_block_comment
7231               )
7232             {
7233                 $self->flush();    # switching to new output stream
7234                 $file_writer_object->write_blank_code_line();
7235                 $last_line_leading_type = 'b';
7236             }
7237
7238             # TRIM COMMENTS -- This could be turned off as a option
7239             $rinput_token_array->[0]->[_TOKEN_] =~ s/\s*$//;    # trim right end
7240
7241             if (
7242                 $rOpts->{'indent-block-comments'}
7243                 && (  !$rOpts->{'indent-spaced-block-comments'}
7244                     || $input_line =~ /^\s+/ )
7245                 && !$is_static_block_comment_without_leading_space
7246               )
7247             {
7248                 $self->extract_token(0);
7249                 $self->store_token_to_go();
7250                 $self->output_line_to_go();
7251             }
7252             else {
7253                 $self->flush();    # switching to new output stream
7254                 $file_writer_object->write_code_line(
7255                     $rinput_token_array->[0]->[_TOKEN_] . "\n" );
7256                 $last_line_leading_type = '#';
7257             }
7258             if ( $rOpts->{'tee-block-comments'} ) {
7259                 $file_writer_object->tee_off();
7260             }
7261             return;
7262         }
7263
7264         # compare input/output indentation except for continuation lines
7265         # (because they have an unknown amount of initial blank space)
7266         # and lines which are quotes (because they may have been outdented)
7267         my $structural_indentation_level = $rinput_token_array->[0]->[_LEVEL_];
7268         compare_indentation_levels( $guessed_indentation_level,
7269             $structural_indentation_level )
7270           unless ( $is_hanging_side_comment
7271             || $rinput_token_array->[0]->[_CI_LEVEL_] > 0
7272             || $guessed_indentation_level == 0
7273             && $rinput_token_array->[0]->[_TYPE_] eq 'Q' );
7274
7275         ##########################
7276         # Handle indentation-only
7277         ##########################
7278
7279         # NOTE: In previous versions we sent all qw lines out immediately here.
7280         # No longer doing this: also write a line which is entirely a 'qw' list
7281         # to allow stacking of opening and closing tokens.  Note that interior
7282         # qw lines will still go out at the end of this routine.
7283         if ( $CODE_type eq 'IO' ) {
7284             $self->flush();
7285             my $line = $input_line;
7286
7287             # delete side comments if requested with -io, but
7288             # we will not allow deleting of closing side comments with -io
7289             # because the coding would be more complex
7290             if (   $rOpts->{'delete-side-comments'}
7291                 && $rinput_token_array->[$jmax]->[_TYPE_] eq '#' )
7292             {
7293
7294                 $line = "";
7295                 foreach my $jj ( 0 .. $jmax - 1 ) {
7296                     $line .= $rinput_token_array->[$jj]->[_TOKEN_];
7297                 }
7298             }
7299
7300             # Fix for rt #125506 Unexpected string formating
7301             # in which leading space of a terminal quote was removed
7302             $line =~ s/\s+$//;
7303             $line =~ s/^\s+// unless ($in_continued_quote);
7304
7305             $self->extract_token(0);
7306             $token                 = $line;
7307             $type                  = 'q';
7308             $block_type            = "";
7309             $container_type        = "";
7310             $container_environment = "";
7311             $type_sequence         = "";
7312             $self->store_token_to_go();
7313             $self->output_line_to_go();
7314             return;
7315         }
7316
7317         ############################
7318         # Handle all other lines ...
7319         ############################
7320
7321         #######################################################
7322         # FIXME: this should become unnecessary
7323         # making $j+2 valid simplifies coding
7324         my $rnew_blank =
7325           copy_token_as_type( $rinput_token_array->[$jmax], 'b' );
7326         push @{$rinput_token_array}, $rnew_blank;
7327         push @{$rinput_token_array}, $rnew_blank;
7328         #######################################################
7329
7330         # If we just saw the end of an elsif block, write nag message
7331         # if we do not see another elseif or an else.
7332         if ($looking_for_else) {
7333
7334             unless ( $rinput_token_array->[0]->[_TOKEN_] =~ /^(elsif|else)$/ ) {
7335                 write_logfile_entry("(No else block)\n");
7336             }
7337             $looking_for_else = 0;
7338         }
7339
7340         # This is a good place to kill incomplete one-line blocks
7341         if (
7342             (
7343                    ( $semicolons_before_block_self_destruct == 0 )
7344                 && ( $max_index_to_go >= 0 )
7345                 && ( $last_old_nonblank_type eq ';' )
7346                 && ( $first_new_nonblank_token ne '}' )
7347             )
7348
7349             # Patch for RT #98902. Honor request to break at old commas.
7350             || (   $rOpts_break_at_old_comma_breakpoints
7351                 && $max_index_to_go >= 0
7352                 && $last_old_nonblank_type eq ',' )
7353           )
7354         {
7355             $forced_breakpoint_to_go[$max_index_to_go] = 1
7356               if ($rOpts_break_at_old_comma_breakpoints);
7357             destroy_one_line_block();
7358             $self->output_line_to_go();
7359         }
7360
7361         # loop to process the tokens one-by-one
7362         $type  = 'b';
7363         $token = "";
7364
7365         # We do not want a leading blank if the previous batch just got output
7366         my $jmin = 0;
7367         if ( $max_index_to_go < 0 && $rLL->[$K_first]->[_TYPE_] eq 'b' ) {
7368             $jmin = 1;
7369         }
7370
7371         foreach my $j ( $jmin .. $jmax ) {
7372
7373             # pull out the local values for this token
7374             $self->extract_token($j);
7375
7376             if ( $type eq '#' ) {
7377
7378                 if (
7379                     $rOpts->{'delete-side-comments'}
7380
7381                     # delete closing side comments if necessary
7382                     || (   $rOpts->{'delete-closing-side-comments'}
7383                         && $token =~ /$closing_side_comment_prefix_pattern/o
7384                         && $last_nonblank_block_type =~
7385                         /$closing_side_comment_list_pattern/o )
7386                   )
7387                 {
7388                     if ( $types_to_go[$max_index_to_go] eq 'b' ) {
7389                         unstore_token_to_go();
7390                     }
7391                     last;
7392                 }
7393             }
7394
7395             # If we are continuing after seeing a right curly brace, flush
7396             # buffer unless we see what we are looking for, as in
7397             #   } else ...
7398             if ( $rbrace_follower && $type ne 'b' ) {
7399
7400                 unless ( $rbrace_follower->{$token} ) {
7401                     $self->output_line_to_go();
7402                 }
7403                 $rbrace_follower = undef;
7404             }
7405
7406             $j_next =
7407               ( $rinput_token_array->[ $j + 1 ]->[_TYPE_] eq 'b' )
7408               ? $j + 2
7409               : $j + 1;
7410             $next_nonblank_token = $rinput_token_array->[$j_next]->[_TOKEN_];
7411             $next_nonblank_token_type =
7412               $rinput_token_array->[$j_next]->[_TYPE_];
7413
7414             # Do not allow breaks which would promote a side comment to a
7415             # block comment.  In order to allow a break before an opening
7416             # or closing BLOCK, followed by a side comment, those sections
7417             # of code will handle this flag separately.
7418             my $side_comment_follows = ( $next_nonblank_token_type eq '#' );
7419             my $is_opening_BLOCK =
7420               (      $type eq '{'
7421                   && $token eq '{'
7422                   && $block_type
7423                   && !$rshort_nested->{$type_sequence}
7424                   && $block_type ne 't' );
7425             my $is_closing_BLOCK =
7426               (      $type eq '}'
7427                   && $token eq '}'
7428                   && $block_type
7429                   && !$rshort_nested->{$type_sequence}
7430                   && $block_type ne 't' );
7431
7432             if (   $side_comment_follows
7433                 && !$is_opening_BLOCK
7434                 && !$is_closing_BLOCK )
7435             {
7436                 $no_internal_newlines = 1;
7437             }
7438
7439             # We're only going to handle breaking for code BLOCKS at this
7440             # (top) level.  Other indentation breaks will be handled by
7441             # sub scan_list, which is better suited to dealing with them.
7442             if ($is_opening_BLOCK) {
7443
7444                 # Tentatively output this token.  This is required before
7445                 # calling starting_one_line_block.  We may have to unstore
7446                 # it, though, if we have to break before it.
7447                 $self->store_token_to_go($side_comment_follows);
7448
7449                 # Look ahead to see if we might form a one-line block..
7450                 my $too_long =
7451                   $self->starting_one_line_block( $j, $jmax, $level, $slevel,
7452                     $ci_level, $rinput_token_array );
7453                 clear_breakpoint_undo_stack();
7454
7455                 # to simplify the logic below, set a flag to indicate if
7456                 # this opening brace is far from the keyword which introduces it
7457                 my $keyword_on_same_line = 1;
7458                 if (   ( $max_index_to_go >= 0 )
7459                     && ( $last_nonblank_type eq ')' )
7460                     && ( ( $slevel < $nesting_depth_to_go[0] ) || $too_long ) )
7461                 {
7462                     $keyword_on_same_line = 0;
7463                 }
7464
7465                 # decide if user requested break before '{'
7466                 my $want_break =
7467
7468                   # use -bl flag if not a sub block of any type
7469                   $block_type !~ /^sub\b/
7470                   ? $rOpts->{'opening-brace-on-new-line'}
7471
7472                   # use -sbl flag for a named sub block
7473                   : $block_type !~ /$ASUB_PATTERN/
7474                   ? $rOpts->{'opening-sub-brace-on-new-line'}
7475
7476                   # use -asbl flag for an anonymous sub block
7477                   : $rOpts->{'opening-anonymous-sub-brace-on-new-line'};
7478
7479                 # Do not break if this token is welded to the left
7480                 if ( weld_len_left( $type_sequence, $token ) ) {
7481                     $want_break = 0;
7482                 }
7483
7484                 # Break before an opening '{' ...
7485                 if (
7486
7487                     # if requested
7488                     $want_break
7489
7490                     # and we were unable to start looking for a block,
7491                     && $index_start_one_line_block == UNDEFINED_INDEX
7492
7493                     # or if it will not be on same line as its keyword, so that
7494                     # it will be outdented (eval.t, overload.t), and the user
7495                     # has not insisted on keeping it on the right
7496                     || (   !$keyword_on_same_line
7497                         && !$rOpts->{'opening-brace-always-on-right'} )
7498
7499                   )
7500                 {
7501
7502                     # but only if allowed
7503                     unless ($no_internal_newlines) {
7504
7505                         # since we already stored this token, we must unstore it
7506                         $self->unstore_token_to_go();
7507
7508                         # then output the line
7509                         $self->output_line_to_go();
7510
7511                         # and now store this token at the start of a new line
7512                         $self->store_token_to_go($side_comment_follows);
7513                     }
7514                 }
7515
7516                 # Now update for side comment
7517                 if ($side_comment_follows) { $no_internal_newlines = 1 }
7518
7519                 # now output this line
7520                 unless ($no_internal_newlines) {
7521                     $self->output_line_to_go();
7522                 }
7523             }
7524
7525             elsif ($is_closing_BLOCK) {
7526
7527                 # If there is a pending one-line block ..
7528                 if ( $index_start_one_line_block != UNDEFINED_INDEX ) {
7529
7530                     # we have to terminate it if..
7531                     if (
7532
7533                         # it is too long (final length may be different from
7534                         # initial estimate). note: must allow 1 space for this
7535                         # token
7536                         excess_line_length( $index_start_one_line_block,
7537                             $max_index_to_go ) >= 0
7538
7539                         # or if it has too many semicolons
7540                         || (   $semicolons_before_block_self_destruct == 0
7541                             && $last_nonblank_type ne ';' )
7542                       )
7543                     {
7544                         destroy_one_line_block();
7545                     }
7546                 }
7547
7548                 # put a break before this closing curly brace if appropriate
7549                 unless ( $no_internal_newlines
7550                     || $index_start_one_line_block != UNDEFINED_INDEX )
7551                 {
7552
7553                     # write out everything before this closing curly brace
7554                     $self->output_line_to_go();
7555                 }
7556
7557                 # Now update for side comment
7558                 if ($side_comment_follows) { $no_internal_newlines = 1 }
7559
7560                 # store the closing curly brace
7561                 $self->store_token_to_go();
7562
7563                 # ok, we just stored a closing curly brace.  Often, but
7564                 # not always, we want to end the line immediately.
7565                 # So now we have to check for special cases.
7566
7567                 # if this '}' successfully ends a one-line block..
7568                 my $is_one_line_block = 0;
7569                 my $keep_going        = 0;
7570                 if ( $index_start_one_line_block != UNDEFINED_INDEX ) {
7571
7572                     # Remember the type of token just before the
7573                     # opening brace.  It would be more general to use
7574                     # a stack, but this will work for one-line blocks.
7575                     $is_one_line_block =
7576                       $types_to_go[$index_start_one_line_block];
7577
7578                     # we have to actually make it by removing tentative
7579                     # breaks that were set within it
7580                     undo_forced_breakpoint_stack(0);
7581                     set_nobreaks( $index_start_one_line_block,
7582                         $max_index_to_go - 1 );
7583
7584                     # then re-initialize for the next one-line block
7585                     destroy_one_line_block();
7586
7587                     # then decide if we want to break after the '}' ..
7588                     # We will keep going to allow certain brace followers as in:
7589                     #   do { $ifclosed = 1; last } unless $losing;
7590                     #
7591                     # But make a line break if the curly ends a
7592                     # significant block:
7593                     if (
7594                         (
7595                             $is_block_without_semicolon{$block_type}
7596
7597                             # Follow users break point for
7598                             # one line block types U & G, such as a 'try' block
7599                             || $is_one_line_block =~ /^[UG]$/ && $j == $jmax
7600                         )
7601
7602                         # if needless semicolon follows we handle it later
7603                         && $next_nonblank_token ne ';'
7604                       )
7605                     {
7606                         $self->output_line_to_go()
7607                           unless ($no_internal_newlines);
7608                     }
7609                 }
7610
7611                 # set string indicating what we need to look for brace follower
7612                 # tokens
7613                 if ( $block_type eq 'do' ) {
7614                     $rbrace_follower = \%is_do_follower;
7615                 }
7616                 elsif ( $block_type =~ /^(if|elsif|unless)$/ ) {
7617                     $rbrace_follower = \%is_if_brace_follower;
7618                 }
7619                 elsif ( $block_type eq 'else' ) {
7620                     $rbrace_follower = \%is_else_brace_follower;
7621                 }
7622
7623                 # added eval for borris.t
7624                 elsif ($is_sort_map_grep_eval{$block_type}
7625                     || $is_one_line_block eq 'G' )
7626                 {
7627                     $rbrace_follower = undef;
7628                     $keep_going      = 1;
7629                 }
7630
7631                 # anonymous sub
7632                 elsif ( $block_type =~ /$ASUB_PATTERN/ ) {
7633
7634                     if ($is_one_line_block) {
7635                         $rbrace_follower = \%is_anon_sub_1_brace_follower;
7636                     }
7637                     else {
7638                         $rbrace_follower = \%is_anon_sub_brace_follower;
7639                     }
7640                 }
7641
7642                 # None of the above: specify what can follow a closing
7643                 # brace of a block which is not an
7644                 # if/elsif/else/do/sort/map/grep/eval
7645                 # Testfiles:
7646                 # 'Toolbar.pm', 'Menubar.pm', bless.t, '3rules.pl', 'break1.t
7647                 else {
7648                     $rbrace_follower = \%is_other_brace_follower;
7649                 }
7650
7651                 # See if an elsif block is followed by another elsif or else;
7652                 # complain if not.
7653                 if ( $block_type eq 'elsif' ) {
7654
7655                     if ( $next_nonblank_token_type eq 'b' ) {    # end of line?
7656                         $looking_for_else = 1;    # ok, check on next line
7657                     }
7658                     else {
7659
7660                         unless ( $next_nonblank_token =~ /^(elsif|else)$/ ) {
7661                             write_logfile_entry("No else block :(\n");
7662                         }
7663                     }
7664                 }
7665
7666                 # keep going after certain block types (map,sort,grep,eval)
7667                 # added eval for borris.t
7668                 if ($keep_going) {
7669
7670                     # keep going
7671                 }
7672
7673                 # if no more tokens, postpone decision until re-entring
7674                 elsif ( ( $next_nonblank_token_type eq 'b' )
7675                     && $rOpts_add_newlines )
7676                 {
7677                     unless ($rbrace_follower) {
7678                         $self->output_line_to_go()
7679                           unless ($no_internal_newlines);
7680                     }
7681                 }
7682
7683                 elsif ($rbrace_follower) {
7684
7685                     unless ( $rbrace_follower->{$next_nonblank_token} ) {
7686                         $self->output_line_to_go()
7687                           unless ($no_internal_newlines);
7688                     }
7689                     $rbrace_follower = undef;
7690                 }
7691
7692                 else {
7693                     $self->output_line_to_go() unless ($no_internal_newlines);
7694                 }
7695
7696             }    # end treatment of closing block token
7697
7698             # handle semicolon
7699             elsif ( $type eq ';' ) {
7700
7701                 # kill one-line blocks with too many semicolons
7702                 $semicolons_before_block_self_destruct--;
7703                 if (
7704                     ( $semicolons_before_block_self_destruct < 0 )
7705                     || (   $semicolons_before_block_self_destruct == 0
7706                         && $next_nonblank_token_type !~ /^[b\}]$/ )
7707                   )
7708                 {
7709                     destroy_one_line_block();
7710                 }
7711
7712                 $self->store_token_to_go();
7713
7714                 $self->output_line_to_go()
7715                   unless ( $no_internal_newlines
7716                     || ( $rOpts_keep_interior_semicolons && $j < $jmax )
7717                     || ( $next_nonblank_token eq '}' ) );
7718
7719             }
7720
7721             # handle here_doc target string
7722             elsif ( $type eq 'h' ) {
7723
7724                 # no newlines after seeing here-target
7725                 $no_internal_newlines = 1;
7726                 destroy_one_line_block();
7727                 $self->store_token_to_go();
7728             }
7729
7730             # handle all other token types
7731             else {
7732
7733                 $self->store_token_to_go();
7734             }
7735
7736             # remember two previous nonblank OUTPUT tokens
7737             if ( $type ne '#' && $type ne 'b' ) {
7738                 $last_last_nonblank_token = $last_nonblank_token;
7739                 $last_last_nonblank_type  = $last_nonblank_type;
7740                 $last_nonblank_token      = $token;
7741                 $last_nonblank_type       = $type;
7742                 $last_nonblank_block_type = $block_type;
7743             }
7744
7745             # unset the continued-quote flag since it only applies to the
7746             # first token, and we want to resume normal formatting if
7747             # there are additional tokens on the line
7748             $in_continued_quote = 0;
7749
7750         }    # end of loop over all tokens in this 'line_of_tokens'
7751
7752         # we have to flush ..
7753         if (
7754
7755             # if there is a side comment
7756             ( ( $type eq '#' ) && !$rOpts->{'delete-side-comments'} )
7757
7758             # if this line ends in a quote
7759             # NOTE: This is critically important for insuring that quoted lines
7760             # do not get processed by things like -sot and -sct
7761             || $in_quote
7762
7763             # if this is a VERSION statement
7764             || $is_VERSION_statement
7765
7766             # to keep a label at the end of a line
7767             || $type eq 'J'
7768
7769             # if we are instructed to keep all old line breaks
7770             || !$rOpts->{'delete-old-newlines'}
7771           )
7772         {
7773             destroy_one_line_block();
7774             $self->output_line_to_go();
7775         }
7776
7777         # mark old line breakpoints in current output stream
7778         if ( $max_index_to_go >= 0 && !$rOpts_ignore_old_breakpoints ) {
7779             my $jobp = $max_index_to_go;
7780             if ( $types_to_go[$max_index_to_go] eq 'b' && $max_index_to_go > 0 )
7781             {
7782                 $jobp--;
7783             }
7784             $old_breakpoint_to_go[$jobp] = 1;
7785         }
7786         return;
7787     } ## end sub print_line_of_tokens
7788 } ## end block print_line_of_tokens
7789
7790 sub consecutive_nonblank_lines {
7791     return $file_writer_object->get_consecutive_nonblank_lines() +
7792       $vertical_aligner_object->get_cached_line_count();
7793 }
7794
7795 # sub output_line_to_go sends one logical line of tokens on down the
7796 # pipeline to the VerticalAligner package, breaking the line into continuation
7797 # lines as necessary.  The line of tokens is ready to go in the "to_go"
7798 # arrays.
7799 sub output_line_to_go {
7800
7801     my $self = shift;
7802     my $rLL  = $self->{rLL};
7803
7804     # debug stuff; this routine can be called from many points
7805     FORMATTER_DEBUG_FLAG_OUTPUT && do {
7806         my ( $a, $b, $c ) = caller;
7807         write_diagnostics(
7808 "OUTPUT: output_line_to_go called: $a $c $last_nonblank_type $last_nonblank_token, one_line=$index_start_one_line_block, tokens to write=$max_index_to_go\n"
7809         );
7810         my $output_str = join "", @tokens_to_go[ 0 .. $max_index_to_go ];
7811         write_diagnostics("$output_str\n");
7812     };
7813
7814     # Do not end line in a weld
7815     return if ( weld_len_right_to_go($max_index_to_go) );
7816
7817     # just set a tentative breakpoint if we might be in a one-line block
7818     if ( $index_start_one_line_block != UNDEFINED_INDEX ) {
7819         set_forced_breakpoint($max_index_to_go);
7820         return;
7821     }
7822
7823     my $comma_arrow_count_contained = match_opening_and_closing_tokens();
7824
7825     # tell the -lp option we are outputting a batch so it can close
7826     # any unfinished items in its stack
7827     finish_lp_batch();
7828
7829     # If this line ends in a code block brace, set breaks at any
7830     # previous closing code block braces to breakup a chain of code
7831     # blocks on one line.  This is very rare but can happen for
7832     # user-defined subs.  For example we might be looking at this:
7833     #  BOOL { $server_data{uptime} > 0; } NUM { $server_data{load}; } STR {
7834     my $saw_good_break = 0;    # flag to force breaks even if short line
7835     if (
7836
7837         # looking for opening or closing block brace
7838         $block_type_to_go[$max_index_to_go]
7839
7840         # but not one of these which are never duplicated on a line:
7841         # until|while|for|if|elsif|else
7842         && !$is_block_without_semicolon{ $block_type_to_go[$max_index_to_go] }
7843       )
7844     {
7845         my $lev = $nesting_depth_to_go[$max_index_to_go];
7846
7847         # Walk backwards from the end and
7848         # set break at any closing block braces at the same level.
7849         # But quit if we are not in a chain of blocks.
7850         for ( my $i = $max_index_to_go - 1 ; $i >= 0 ; $i-- ) {
7851             last if ( $levels_to_go[$i] < $lev );    # stop at a lower level
7852             next if ( $levels_to_go[$i] > $lev );    # skip past higher level
7853
7854             if ( $block_type_to_go[$i] ) {
7855                 if ( $tokens_to_go[$i] eq '}' ) {
7856                     set_forced_breakpoint($i);
7857                     $saw_good_break = 1;
7858                 }
7859             }
7860
7861             # quit if we see anything besides words, function, blanks
7862             # at this level
7863             elsif ( $types_to_go[$i] !~ /^[\(\)Gwib]$/ ) { last }
7864         }
7865     }
7866
7867     my $imin = 0;
7868     my $imax = $max_index_to_go;
7869
7870     # trim any blank tokens
7871     if ( $max_index_to_go >= 0 ) {
7872         if ( $types_to_go[$imin] eq 'b' ) { $imin++ }
7873         if ( $types_to_go[$imax] eq 'b' ) { $imax-- }
7874     }
7875
7876     # anything left to write?
7877     if ( $imin <= $imax ) {
7878
7879         # add a blank line before certain key types but not after a comment
7880         if ( $last_line_leading_type !~ /^[#]/ ) {
7881             my $want_blank    = 0;
7882             my $leading_token = $tokens_to_go[$imin];
7883             my $leading_type  = $types_to_go[$imin];
7884
7885             # blank lines before subs except declarations and one-liners
7886             if ( $leading_token =~ /^(sub\s)/ && $leading_type eq 'i' ) {
7887                 $want_blank = $rOpts->{'blank-lines-before-subs'}
7888                   if ( $self->terminal_type_i( $imin, $imax ) !~ /^[\;\}]$/ );
7889             }
7890
7891             # break before all package declarations
7892             elsif ($leading_token =~ /^(package\s)/
7893                 && $leading_type eq 'i' )
7894             {
7895                 $want_blank = $rOpts->{'blank-lines-before-packages'};
7896             }
7897
7898             # break before certain key blocks except one-liners
7899             if ( $leading_token =~ /^(BEGIN|END)$/ && $leading_type eq 'k' ) {
7900                 $want_blank = $rOpts->{'blank-lines-before-subs'}
7901                   if ( $self->terminal_type_i( $imin, $imax ) ne '}' );
7902             }
7903
7904             # Break before certain block types if we haven't had a
7905             # break at this level for a while.  This is the
7906             # difficult decision..
7907             elsif ($leading_type eq 'k'
7908                 && $last_line_leading_type ne 'b'
7909                 && $leading_token =~ /^(unless|if|while|until|for|foreach)$/ )
7910             {
7911                 my $lc = $nonblank_lines_at_depth[$last_line_leading_level];
7912                 if ( !defined($lc) ) { $lc = 0 }
7913
7914                 # patch for RT #128216: no blank line inserted at a level change
7915                 if ( $levels_to_go[$imin] != $last_line_leading_level ) {
7916                     $lc = 0;
7917                 }
7918
7919                 $want_blank =
7920                      $rOpts->{'blanks-before-blocks'}
7921                   && $lc >= $rOpts->{'long-block-line-count'}
7922                   && consecutive_nonblank_lines() >=
7923                   $rOpts->{'long-block-line-count'}
7924                   && $self->terminal_type_i( $imin, $imax ) ne '}';
7925             }
7926
7927             # Check for blank lines wanted before a closing brace
7928             if ( $leading_token eq '}' ) {
7929                 if (   $rOpts->{'blank-lines-before-closing-block'}
7930                     && $block_type_to_go[$imin]
7931                     && $block_type_to_go[$imin] =~
7932                     /$blank_lines_before_closing_block_pattern/ )
7933                 {
7934                     my $nblanks = $rOpts->{'blank-lines-before-closing-block'};
7935                     if ( $nblanks > $want_blank ) {
7936                         $want_blank = $nblanks;
7937                     }
7938                 }
7939             }
7940
7941             if ($want_blank) {
7942
7943                 # future: send blank line down normal path to VerticalAligner
7944                 Perl::Tidy::VerticalAligner::flush();
7945                 $file_writer_object->require_blank_code_lines($want_blank);
7946             }
7947         }
7948
7949         # update blank line variables and count number of consecutive
7950         # non-blank, non-comment lines at this level
7951         $last_last_line_leading_level = $last_line_leading_level;
7952         $last_line_leading_level      = $levels_to_go[$imin];
7953         if ( $last_line_leading_level < 0 ) { $last_line_leading_level = 0 }
7954         $last_line_leading_type = $types_to_go[$imin];
7955         if (   $last_line_leading_level == $last_last_line_leading_level
7956             && $last_line_leading_type ne 'b'
7957             && $last_line_leading_type ne '#'
7958             && defined( $nonblank_lines_at_depth[$last_line_leading_level] ) )
7959         {
7960             $nonblank_lines_at_depth[$last_line_leading_level]++;
7961         }
7962         else {
7963             $nonblank_lines_at_depth[$last_line_leading_level] = 1;
7964         }
7965
7966         FORMATTER_DEBUG_FLAG_FLUSH && do {
7967             my ( $package, $file, $line ) = caller;
7968             print STDOUT
7969 "FLUSH: flushing from $package $file $line, types= $types_to_go[$imin] to $types_to_go[$imax]\n";
7970         };
7971
7972         # add a couple of extra terminal blank tokens
7973         pad_array_to_go();
7974
7975         # set all forced breakpoints for good list formatting
7976         my $is_long_line = excess_line_length( $imin, $max_index_to_go ) > 0;
7977
7978         my $old_line_count_in_batch =
7979           $self->get_old_line_count( $K_to_go[0], $K_to_go[$max_index_to_go] );
7980
7981         if (
7982                $is_long_line
7983             || $old_line_count_in_batch > 1
7984
7985             # must always call scan_list() with unbalanced batches because it
7986             # is maintaining some stacks
7987             || is_unbalanced_batch()
7988
7989             # call scan_list if we might want to break at commas
7990             || (
7991                 $comma_count_in_batch
7992                 && (   $rOpts_maximum_fields_per_table > 0
7993                     || $rOpts_comma_arrow_breakpoints == 0 )
7994             )
7995
7996             # call scan_list if user may want to break open some one-line
7997             # hash references
7998             || (   $comma_arrow_count_contained
7999                 && $rOpts_comma_arrow_breakpoints != 3 )
8000           )
8001         {
8002             ## This caused problems in one version of perl for unknown reasons:
8003             ## $saw_good_break ||= scan_list();
8004             my $sgb = scan_list();
8005             $saw_good_break ||= $sgb;
8006         }
8007
8008         # let $ri_first and $ri_last be references to lists of
8009         # first and last tokens of line fragments to output..
8010         my ( $ri_first, $ri_last );
8011
8012         # write a single line if..
8013         if (
8014
8015             # we aren't allowed to add any newlines
8016             !$rOpts_add_newlines
8017
8018             # or, we don't already have an interior breakpoint
8019             # and we didn't see a good breakpoint
8020             || (
8021                    !$forced_breakpoint_count
8022                 && !$saw_good_break
8023
8024                 # and this line is 'short'
8025                 && !$is_long_line
8026             )
8027           )
8028         {
8029             @{$ri_first} = ($imin);
8030             @{$ri_last}  = ($imax);
8031         }
8032
8033         # otherwise use multiple lines
8034         else {
8035
8036             ( $ri_first, $ri_last, my $colon_count ) =
8037               $self->set_continuation_breaks($saw_good_break);
8038
8039             $self->break_all_chain_tokens( $ri_first, $ri_last );
8040
8041             break_equals( $ri_first, $ri_last );
8042
8043             # now we do a correction step to clean this up a bit
8044             # (The only time we would not do this is for debugging)
8045             if ( $rOpts->{'recombine'} ) {
8046                 ( $ri_first, $ri_last ) =
8047                   recombine_breakpoints( $ri_first, $ri_last );
8048             }
8049
8050             $self->insert_final_breaks( $ri_first, $ri_last ) if $colon_count;
8051         }
8052
8053         # do corrector step if -lp option is used
8054         my $do_not_pad = 0;
8055         if ($rOpts_line_up_parentheses) {
8056             $do_not_pad = correct_lp_indentation( $ri_first, $ri_last );
8057         }
8058         $self->unmask_phantom_semicolons( $ri_first, $ri_last );
8059         if ( $rOpts_one_line_block_semicolons == 0 ) {
8060             $self->delete_one_line_semicolons( $ri_first, $ri_last );
8061         }
8062
8063         # The line breaks for this batch of code have been finalized. Now we
8064         # can to package the results for further processing.  We will switch
8065         # from the local '_to_go' buffer arrays (i-index) back to the global
8066         # token arrays (K-index) at this point.
8067         my $rlines_K;
8068         my $index_error;
8069         for ( my $n = 0 ; $n < @{$ri_first} ; $n++ ) {
8070             my $ibeg = $ri_first->[$n];
8071             my $Kbeg = $K_to_go[$ibeg];
8072             my $iend = $ri_last->[$n];
8073             my $Kend = $K_to_go[$iend];
8074             if ( $iend - $ibeg != $Kend - $Kbeg ) {
8075                 $index_error = $n unless defined($index_error);
8076             }
8077             push @{$rlines_K},
8078               [ $Kbeg, $Kend, $forced_breakpoint_to_go[$iend] ];
8079         }
8080
8081         # Check correctness of the mapping between the i and K token indexes
8082         if ( defined($index_error) ) {
8083
8084             # Temporary debug code - should never get here
8085             for ( my $n = 0 ; $n < @{$ri_first} ; $n++ ) {
8086                 my $ibeg  = $ri_first->[$n];
8087                 my $Kbeg  = $K_to_go[$ibeg];
8088                 my $iend  = $ri_last->[$n];
8089                 my $Kend  = $K_to_go[$iend];
8090                 my $idiff = $iend - $ibeg;
8091                 my $Kdiff = $Kend - $Kbeg;
8092                 print STDERR <<EOM;
8093 line $n, irange $ibeg-$iend = $idiff, Krange $Kbeg-$Kend = $Kdiff;
8094 EOM
8095             }
8096             Fault("Index error at line $index_error; i and K ranges differ");
8097         }
8098
8099         my $rbatch_hash = {
8100             rlines_K   => $rlines_K,
8101             do_not_pad => $do_not_pad,
8102             ibeg0      => $ri_first->[0],
8103         };
8104
8105         $self->send_lines_to_vertical_aligner($rbatch_hash);
8106
8107         # Insert any requested blank lines after an opening brace.  We have to
8108         # skip back before any side comment to find the terminal token
8109         my $iterm;
8110         for ( $iterm = $imax ; $iterm >= $imin ; $iterm-- ) {
8111             next if $types_to_go[$iterm] eq '#';
8112             next if $types_to_go[$iterm] eq 'b';
8113             last;
8114         }
8115
8116         # write requested number of blank lines after an opening block brace
8117         if ( $iterm >= $imin && $types_to_go[$iterm] eq '{' ) {
8118             if (   $rOpts->{'blank-lines-after-opening-block'}
8119                 && $block_type_to_go[$iterm]
8120                 && $block_type_to_go[$iterm] =~
8121                 /$blank_lines_after_opening_block_pattern/ )
8122             {
8123                 my $nblanks = $rOpts->{'blank-lines-after-opening-block'};
8124                 Perl::Tidy::VerticalAligner::flush();
8125                 $file_writer_object->require_blank_code_lines($nblanks);
8126             }
8127         }
8128     }
8129
8130     prepare_for_new_input_lines();
8131
8132     return;
8133 }
8134
8135 sub note_added_semicolon {
8136     my ($line_number) = @_;
8137     $last_added_semicolon_at = $line_number;
8138     if ( $added_semicolon_count == 0 ) {
8139         $first_added_semicolon_at = $last_added_semicolon_at;
8140     }
8141     $added_semicolon_count++;
8142     write_logfile_entry("Added ';' here\n");
8143     return;
8144 }
8145
8146 sub note_deleted_semicolon {
8147     $last_deleted_semicolon_at = $input_line_number;
8148     if ( $deleted_semicolon_count == 0 ) {
8149         $first_deleted_semicolon_at = $last_deleted_semicolon_at;
8150     }
8151     $deleted_semicolon_count++;
8152     write_logfile_entry("Deleted unnecessary ';' at line $input_line_number\n");
8153     return;
8154 }
8155
8156 sub note_embedded_tab {
8157     $embedded_tab_count++;
8158     $last_embedded_tab_at = $input_line_number;
8159     if ( !$first_embedded_tab_at ) {
8160         $first_embedded_tab_at = $last_embedded_tab_at;
8161     }
8162
8163     if ( $embedded_tab_count <= MAX_NAG_MESSAGES ) {
8164         write_logfile_entry("Embedded tabs in quote or pattern\n");
8165     }
8166     return;
8167 }
8168
8169 sub starting_one_line_block {
8170
8171     # after seeing an opening curly brace, look for the closing brace
8172     # and see if the entire block will fit on a line.  This routine is
8173     # not always right because it uses the old whitespace, so a check
8174     # is made later (at the closing brace) to make sure we really
8175     # have a one-line block.  We have to do this preliminary check,
8176     # though, because otherwise we would always break at a semicolon
8177     # within a one-line block if the block contains multiple statements.
8178
8179     my ( $self, $j, $jmax, $level, $slevel, $ci_level, $rtoken_array ) = @_;
8180     my $rbreak_container = $self->{rbreak_container};
8181     my $rshort_nested    = $self->{rshort_nested};
8182
8183     my $jmax_check = @{$rtoken_array};
8184     if ( $jmax_check < $jmax ) {
8185         Fault("jmax=$jmax > $jmax_check");
8186     }
8187
8188     # kill any current block - we can only go 1 deep
8189     destroy_one_line_block();
8190
8191     # return value:
8192     #  1=distance from start of block to opening brace exceeds line length
8193     #  0=otherwise
8194
8195     my $i_start = 0;
8196
8197     # shouldn't happen: there must have been a prior call to
8198     # store_token_to_go to put the opening brace in the output stream
8199     if ( $max_index_to_go < 0 ) {
8200         Fault("program bug: store_token_to_go called incorrectly\n");
8201     }
8202
8203     # return if block should be broken
8204     my $type_sequence = $rtoken_array->[$j]->[_TYPE_SEQUENCE_];
8205     if ( $rbreak_container->{$type_sequence} ) {
8206         return 0;
8207     }
8208
8209     my $block_type = $rtoken_array->[$j]->[_BLOCK_TYPE_];
8210
8211     # find the starting keyword for this block (such as 'if', 'else', ...)
8212
8213     if ( $block_type =~ /^[\{\}\;\:]$/ || $block_type =~ /^package/ ) {
8214         $i_start = $max_index_to_go;
8215     }
8216
8217     # the previous nonblank token should start these block types
8218     elsif (( $last_last_nonblank_token_to_go eq $block_type )
8219         || ( $block_type =~ /^sub\b/ )
8220         || $block_type =~ /\(\)/ )
8221     {
8222         $i_start = $last_last_nonblank_index_to_go;
8223
8224         # For signatures and extended syntax ...
8225         # If this brace follows a parenthesized list, we should look back to
8226         # find the keyword before the opening paren because otherwise we might
8227         # form a one line block which stays intack, and cause the parenthesized
8228         # expression to break open. That looks bad.  However, actually
8229         # searching for the opening paren is slow and tedius.
8230         # The actual keyword is often at the start of a line, but might not be.
8231         # For example, we might have an anonymous sub with signature list
8232         # following a =>.  It is safe to mark the start anywhere before the
8233         # opening paren, so we just go back to the prevoious break (or start of
8234         # the line) if that is before the opening paren.  The minor downside is
8235         # that we may very occasionally break open a block unnecessarily.
8236         if ( $tokens_to_go[$i_start] eq ')' ) {
8237             $i_start = $index_max_forced_break + 1;
8238             if ( $types_to_go[$i_start] eq 'b' ) { $i_start++; }
8239             my $lev = $levels_to_go[$i_start];
8240             if ( $lev > $level ) { return 0 }
8241         }
8242     }
8243
8244     elsif ( $last_last_nonblank_token_to_go eq ')' ) {
8245
8246         # For something like "if (xxx) {", the keyword "if" will be
8247         # just after the most recent break. This will be 0 unless
8248         # we have just killed a one-line block and are starting another.
8249         # (doif.t)
8250         # Note: cannot use inext_index_to_go[] here because that array
8251         # is still being constructed.
8252         $i_start = $index_max_forced_break + 1;
8253         if ( $types_to_go[$i_start] eq 'b' ) {
8254             $i_start++;
8255         }
8256
8257         # Patch to avoid breaking short blocks defined with extended_syntax:
8258         # Strip off any trailing () which was added in the parser to mark
8259         # the opening keyword.  For example, in the following
8260         #    create( TypeFoo $e) {$bubba}
8261         # the blocktype would be marked as create()
8262         my $stripped_block_type = $block_type;
8263         $stripped_block_type =~ s/\(\)$//;
8264
8265         unless ( $tokens_to_go[$i_start] eq $stripped_block_type ) {
8266             return 0;
8267         }
8268     }
8269
8270     # patch for SWITCH/CASE to retain one-line case/when blocks
8271     elsif ( $block_type eq 'case' || $block_type eq 'when' ) {
8272
8273         # Note: cannot use inext_index_to_go[] here because that array
8274         # is still being constructed.
8275         $i_start = $index_max_forced_break + 1;
8276         if ( $types_to_go[$i_start] eq 'b' ) {
8277             $i_start++;
8278         }
8279         unless ( $tokens_to_go[$i_start] eq $block_type ) {
8280             return 0;
8281         }
8282     }
8283
8284     else {
8285         return 1;
8286     }
8287
8288     my $pos = total_line_length( $i_start, $max_index_to_go ) - 1;
8289
8290     # see if length is too long to even start
8291     if ( $pos > maximum_line_length($i_start) ) {
8292         return 1;
8293     }
8294
8295     foreach my $i ( $j + 1 .. $jmax ) {
8296
8297         # old whitespace could be arbitrarily large, so don't use it
8298         if ( $rtoken_array->[$i]->[_TYPE_] eq 'b' ) { $pos += 1 }
8299         else { $pos += rtoken_length($i) }
8300
8301         # ignore some small blocks
8302         my $type_sequence = $rtoken_array->[$i]->[_TYPE_SEQUENCE_];
8303         my $nobreak       = $rshort_nested->{$type_sequence};
8304
8305         # Return false result if we exceed the maximum line length,
8306         if ( $pos > maximum_line_length($i_start) ) {
8307             return 0;
8308         }
8309
8310         # keep going for non-containers
8311         elsif ( !$type_sequence ) {
8312
8313         }
8314
8315         # return if we encounter another opening brace before finding the
8316         # closing brace.
8317         elsif ($rtoken_array->[$i]->[_TOKEN_] eq '{'
8318             && $rtoken_array->[$i]->[_TYPE_] eq '{'
8319             && $rtoken_array->[$i]->[_BLOCK_TYPE_]
8320             && !$nobreak )
8321         {
8322             return 0;
8323         }
8324
8325         # if we find our closing brace..
8326         elsif ($rtoken_array->[$i]->[_TOKEN_] eq '}'
8327             && $rtoken_array->[$i]->[_TYPE_] eq '}'
8328             && $rtoken_array->[$i]->[_BLOCK_TYPE_]
8329             && !$nobreak )
8330         {
8331
8332             # be sure any trailing comment also fits on the line
8333             my $i_nonblank =
8334               ( $rtoken_array->[ $i + 1 ]->[_TYPE_] eq 'b' ) ? $i + 2 : $i + 1;
8335
8336             # Patch for one-line sort/map/grep/eval blocks with side comments:
8337             # We will ignore the side comment length for sort/map/grep/eval
8338             # because this can lead to statements which change every time
8339             # perltidy is run.  Here is an example from Denis Moskowitz which
8340             # oscillates between these two states without this patch:
8341
8342 ## --------
8343 ## grep { $_->foo ne 'bar' } # asdfa asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf
8344 ##  @baz;
8345 ##
8346 ## grep {
8347 ##     $_->foo ne 'bar'
8348 ##   }    # asdfa asdf asdf asdf asdf asdf asdf asdf asdf asdf asdf
8349 ##   @baz;
8350 ## --------
8351
8352             # When the first line is input it gets broken apart by the main
8353             # line break logic in sub print_line_of_tokens.
8354             # When the second line is input it gets recombined by
8355             # print_line_of_tokens and passed to the output routines.  The
8356             # output routines (set_continuation_breaks) do not break it apart
8357             # because the bond strengths are set to the highest possible value
8358             # for grep/map/eval/sort blocks, so the first version gets output.
8359             # It would be possible to fix this by changing bond strengths,
8360             # but they are high to prevent errors in older versions of perl.
8361
8362             if ( $rtoken_array->[$i_nonblank]->[_TYPE_] eq '#'
8363                 && !$is_sort_map_grep{$block_type} )
8364             {
8365
8366                 $pos += rtoken_length($i_nonblank);
8367
8368                 if ( $i_nonblank > $i + 1 ) {
8369
8370                     # source whitespace could be anything, assume
8371                     # at least one space before the hash on output
8372                     if ( $rtoken_array->[ $i + 1 ]->[_TYPE_] eq 'b' ) {
8373                         $pos += 1;
8374                     }
8375                     else { $pos += rtoken_length( $i + 1 ) }
8376                 }
8377
8378                 if ( $pos >= maximum_line_length($i_start) ) {
8379                     return 0;
8380                 }
8381             }
8382
8383             # ok, it's a one-line block
8384             create_one_line_block( $i_start, 20 );
8385             return 0;
8386         }
8387
8388         # just keep going for other characters
8389         else {
8390         }
8391     }
8392
8393     # Allow certain types of new one-line blocks to form by joining
8394     # input lines.  These can be safely done, but for other block types,
8395     # we keep old one-line blocks but do not form new ones. It is not
8396     # always a good idea to make as many one-line blocks as possible,
8397     # so other types are not done.  The user can always use -mangle.
8398     if ( $want_one_line_block{$block_type} ) {
8399         create_one_line_block( $i_start, 1 );
8400     }
8401     return 0;
8402 }
8403
8404 sub unstore_token_to_go {
8405
8406     # remove most recent token from output stream
8407     my $self = shift;
8408     if ( $max_index_to_go > 0 ) {
8409         $max_index_to_go--;
8410     }
8411     else {
8412         $max_index_to_go = UNDEFINED_INDEX;
8413     }
8414     return;
8415 }
8416
8417 sub want_blank_line {
8418     my $self = shift;
8419     $self->flush();
8420     $file_writer_object->want_blank_line();
8421     return;
8422 }
8423
8424 sub write_unindented_line {
8425     my ( $self, $line ) = @_;
8426     $self->flush();
8427     $file_writer_object->write_line($line);
8428     return;
8429 }
8430
8431 sub undo_ci {
8432
8433     # Undo continuation indentation in certain sequences
8434     # For example, we can undo continuation indentation in sort/map/grep chains
8435     #    my $dat1 = pack( "n*",
8436     #        map { $_, $lookup->{$_} }
8437     #          sort { $a <=> $b }
8438     #          grep { $lookup->{$_} ne $default } keys %$lookup );
8439     # To align the map/sort/grep keywords like this:
8440     #    my $dat1 = pack( "n*",
8441     #        map { $_, $lookup->{$_} }
8442     #        sort { $a <=> $b }
8443     #        grep { $lookup->{$_} ne $default } keys %$lookup );
8444     my ( $self, $ri_first, $ri_last ) = @_;
8445     my ( $line_1, $line_2, $lev_last );
8446     my $this_line_is_semicolon_terminated;
8447     my $max_line = @{$ri_first} - 1;
8448
8449     # looking at each line of this batch..
8450     # We are looking at leading tokens and looking for a sequence
8451     # all at the same level and higher level than enclosing lines.
8452     foreach my $line ( 0 .. $max_line ) {
8453
8454         my $ibeg = $ri_first->[$line];
8455         my $lev  = $levels_to_go[$ibeg];
8456         if ( $line > 0 ) {
8457
8458             # if we have started a chain..
8459             if ($line_1) {
8460
8461                 # see if it continues..
8462                 if ( $lev == $lev_last ) {
8463                     if (   $types_to_go[$ibeg] eq 'k'
8464                         && $is_sort_map_grep{ $tokens_to_go[$ibeg] } )
8465                     {
8466
8467                         # chain continues...
8468                         # check for chain ending at end of a statement
8469                         if ( $line == $max_line ) {
8470
8471                             # see of this line ends a statement
8472                             my $iend = $ri_last->[$line];
8473                             $this_line_is_semicolon_terminated =
8474                               $types_to_go[$iend] eq ';'
8475
8476                               # with possible side comment
8477                               || ( $types_to_go[$iend] eq '#'
8478                                 && $iend - $ibeg >= 2
8479                                 && $types_to_go[ $iend - 2 ] eq ';'
8480                                 && $types_to_go[ $iend - 1 ] eq 'b' );
8481                         }
8482                         $line_2 = $line if ($this_line_is_semicolon_terminated);
8483                     }
8484                     else {
8485
8486                         # kill chain
8487                         $line_1 = undef;
8488                     }
8489                 }
8490                 elsif ( $lev < $lev_last ) {
8491
8492                     # chain ends with previous line
8493                     $line_2 = $line - 1;
8494                 }
8495                 elsif ( $lev > $lev_last ) {
8496
8497                     # kill chain
8498                     $line_1 = undef;
8499                 }
8500
8501                 # undo the continuation indentation if a chain ends
8502                 if ( defined($line_2) && defined($line_1) ) {
8503                     my $continuation_line_count = $line_2 - $line_1 + 1;
8504                     @ci_levels_to_go[ @{$ri_first}[ $line_1 .. $line_2 ] ] =
8505                       (0) x ($continuation_line_count)
8506                       if ( $continuation_line_count >= 0 );
8507                     @leading_spaces_to_go[ @{$ri_first}[ $line_1 .. $line_2 ] ]
8508                       = @reduced_spaces_to_go[ @{$ri_first}
8509                       [ $line_1 .. $line_2 ] ];
8510                     $line_1 = undef;
8511                 }
8512             }
8513
8514             # not in a chain yet..
8515             else {
8516
8517                 # look for start of a new sort/map/grep chain
8518                 if ( $lev > $lev_last ) {
8519                     if (   $types_to_go[$ibeg] eq 'k'
8520                         && $is_sort_map_grep{ $tokens_to_go[$ibeg] } )
8521                     {
8522                         $line_1 = $line;
8523                     }
8524                 }
8525             }
8526         }
8527         $lev_last = $lev;
8528     }
8529     return;
8530 }
8531
8532 sub undo_lp_ci {
8533
8534     # If there is a single, long parameter within parens, like this:
8535     #
8536     #  $self->command( "/msg "
8537     #        . $infoline->chan
8538     #        . " You said $1, but did you know that it's square was "
8539     #        . $1 * $1 . " ?" );
8540     #
8541     # we can remove the continuation indentation of the 2nd and higher lines
8542     # to achieve this effect, which is more pleasing:
8543     #
8544     #  $self->command("/msg "
8545     #                 . $infoline->chan
8546     #                 . " You said $1, but did you know that it's square was "
8547     #                 . $1 * $1 . " ?");
8548
8549     my ( $line_open, $i_start, $closing_index, $ri_first, $ri_last ) = @_;
8550     my $max_line = @{$ri_first} - 1;
8551
8552     # must be multiple lines
8553     return unless $max_line > $line_open;
8554
8555     my $lev_start     = $levels_to_go[$i_start];
8556     my $ci_start_plus = 1 + $ci_levels_to_go[$i_start];
8557
8558     # see if all additional lines in this container have continuation
8559     # indentation
8560     my $n;
8561     my $line_1 = 1 + $line_open;
8562     for ( $n = $line_1 ; $n <= $max_line ; ++$n ) {
8563         my $ibeg = $ri_first->[$n];
8564         my $iend = $ri_last->[$n];
8565         if ( $ibeg eq $closing_index ) { $n--; last }
8566         return if ( $lev_start != $levels_to_go[$ibeg] );
8567         return if ( $ci_start_plus != $ci_levels_to_go[$ibeg] );
8568         last   if ( $closing_index <= $iend );
8569     }
8570
8571     # we can reduce the indentation of all continuation lines
8572     my $continuation_line_count = $n - $line_open;
8573     @ci_levels_to_go[ @{$ri_first}[ $line_1 .. $n ] ] =
8574       (0) x ($continuation_line_count);
8575     @leading_spaces_to_go[ @{$ri_first}[ $line_1 .. $n ] ] =
8576       @reduced_spaces_to_go[ @{$ri_first}[ $line_1 .. $n ] ];
8577     return;
8578 }
8579
8580 sub pad_token {
8581
8582     # insert $pad_spaces before token number $ipad
8583     my ( $self, $ipad, $pad_spaces ) = @_;
8584     my $rLL = $self->{rLL};
8585     if ( $pad_spaces > 0 ) {
8586         $tokens_to_go[$ipad] = ' ' x $pad_spaces . $tokens_to_go[$ipad];
8587     }
8588     elsif ( $pad_spaces == -1 && $tokens_to_go[$ipad] eq ' ' ) {
8589         $tokens_to_go[$ipad] = "";
8590     }
8591     else {
8592
8593         # shouldn't happen
8594         return;
8595     }
8596
8597     # Keep token arrays in sync
8598     $self->sync_token_K($ipad);
8599
8600     $token_lengths_to_go[$ipad] += $pad_spaces;
8601     foreach my $i ( $ipad .. $max_index_to_go ) {
8602         $summed_lengths_to_go[ $i + 1 ] += $pad_spaces;
8603     }
8604     return;
8605 }
8606
8607 {
8608     my %is_math_op;
8609
8610     BEGIN {
8611
8612         my @q = qw( + - * / );
8613         @is_math_op{@q} = (1) x scalar(@q);
8614     }
8615
8616     sub set_logical_padding {
8617
8618         # Look at a batch of lines and see if extra padding can improve the
8619         # alignment when there are certain leading operators. Here is an
8620         # example, in which some extra space is introduced before
8621         # '( $year' to make it line up with the subsequent lines:
8622         #
8623         #       if (   ( $Year < 1601 )
8624         #           || ( $Year > 2899 )
8625         #           || ( $EndYear < 1601 )
8626         #           || ( $EndYear > 2899 ) )
8627         #       {
8628         #           &Error_OutOfRange;
8629         #       }
8630         #
8631         my ( $self, $ri_first, $ri_last ) = @_;
8632         my $max_line = @{$ri_first} - 1;
8633
8634         # FIXME: move these declarations below
8635         my ( $ibeg, $ibeg_next, $ibegm, $iend, $iendm, $ipad, $pad_spaces,
8636             $tok_next, $type_next, $has_leading_op_next, $has_leading_op );
8637
8638         # looking at each line of this batch..
8639         foreach my $line ( 0 .. $max_line - 1 ) {
8640
8641             # see if the next line begins with a logical operator
8642             $ibeg      = $ri_first->[$line];
8643             $iend      = $ri_last->[$line];
8644             $ibeg_next = $ri_first->[ $line + 1 ];
8645             $tok_next  = $tokens_to_go[$ibeg_next];
8646             $type_next = $types_to_go[$ibeg_next];
8647
8648             $has_leading_op_next = ( $tok_next =~ /^\w/ )
8649               ? $is_chain_operator{$tok_next}      # + - * / : ? && ||
8650               : $is_chain_operator{$type_next};    # and, or
8651
8652             next unless ($has_leading_op_next);
8653
8654             # next line must not be at lesser depth
8655             next
8656               if ( $nesting_depth_to_go[$ibeg] >
8657                 $nesting_depth_to_go[$ibeg_next] );
8658
8659             # identify the token in this line to be padded on the left
8660             $ipad = undef;
8661
8662             # handle lines at same depth...
8663             if ( $nesting_depth_to_go[$ibeg] ==
8664                 $nesting_depth_to_go[$ibeg_next] )
8665             {
8666
8667                 # if this is not first line of the batch ...
8668                 if ( $line > 0 ) {
8669
8670                     # and we have leading operator..
8671                     next if $has_leading_op;
8672
8673                     # Introduce padding if..
8674                     # 1. the previous line is at lesser depth, or
8675                     # 2. the previous line ends in an assignment
8676                     # 3. the previous line ends in a 'return'
8677                     # 4. the previous line ends in a comma
8678                     # Example 1: previous line at lesser depth
8679                     #       if (   ( $Year < 1601 )      # <- we are here but
8680                     #           || ( $Year > 2899 )      #  list has not yet
8681                     #           || ( $EndYear < 1601 )   # collapsed vertically
8682                     #           || ( $EndYear > 2899 ) )
8683                     #       {
8684                     #
8685                     # Example 2: previous line ending in assignment:
8686                     #    $leapyear =
8687                     #        $year % 4   ? 0     # <- We are here
8688                     #      : $year % 100 ? 1
8689                     #      : $year % 400 ? 0
8690                     #      : 1;
8691                     #
8692                     # Example 3: previous line ending in comma:
8693                     #    push @expr,
8694                     #        /test/   ? undef
8695                     #      : eval($_) ? 1
8696                     #      : eval($_) ? 1
8697                     #      :            0;
8698
8699                    # be sure levels agree (do not indent after an indented 'if')
8700                     next
8701                       if ( $levels_to_go[$ibeg] ne $levels_to_go[$ibeg_next] );
8702
8703                     # allow padding on first line after a comma but only if:
8704                     # (1) this is line 2 and
8705                     # (2) there are at more than three lines and
8706                     # (3) lines 3 and 4 have the same leading operator
8707                     # These rules try to prevent padding within a long
8708                     # comma-separated list.
8709                     my $ok_comma;
8710                     if (   $types_to_go[$iendm] eq ','
8711                         && $line == 1
8712                         && $max_line > 2 )
8713                     {
8714                         my $ibeg_next_next = $ri_first->[ $line + 2 ];
8715                         my $tok_next_next  = $tokens_to_go[$ibeg_next_next];
8716                         $ok_comma = $tok_next_next eq $tok_next;
8717                     }
8718
8719                     next
8720                       unless (
8721                            $is_assignment{ $types_to_go[$iendm] }
8722                         || $ok_comma
8723                         || ( $nesting_depth_to_go[$ibegm] <
8724                             $nesting_depth_to_go[$ibeg] )
8725                         || (   $types_to_go[$iendm] eq 'k'
8726                             && $tokens_to_go[$iendm] eq 'return' )
8727                       );
8728
8729                     # we will add padding before the first token
8730                     $ipad = $ibeg;
8731                 }
8732
8733                 # for first line of the batch..
8734                 else {
8735
8736                     # WARNING: Never indent if first line is starting in a
8737                     # continued quote, which would change the quote.
8738                     next if $starting_in_quote;
8739
8740                     # if this is text after closing '}'
8741                     # then look for an interior token to pad
8742                     if ( $types_to_go[$ibeg] eq '}' ) {
8743
8744                     }
8745
8746                     # otherwise, we might pad if it looks really good
8747                     else {
8748
8749                         # we might pad token $ibeg, so be sure that it
8750                         # is at the same depth as the next line.
8751                         next
8752                           if ( $nesting_depth_to_go[$ibeg] !=
8753                             $nesting_depth_to_go[$ibeg_next] );
8754
8755                         # We can pad on line 1 of a statement if at least 3
8756                         # lines will be aligned. Otherwise, it
8757                         # can look very confusing.
8758
8759                  # We have to be careful not to pad if there are too few
8760                  # lines.  The current rule is:
8761                  # (1) in general we require at least 3 consecutive lines
8762                  # with the same leading chain operator token,
8763                  # (2) but an exception is that we only require two lines
8764                  # with leading colons if there are no more lines.  For example,
8765                  # the first $i in the following snippet would get padding
8766                  # by the second rule:
8767                  #
8768                  #   $i == 1 ? ( "First", "Color" )
8769                  # : $i == 2 ? ( "Then",  "Rarity" )
8770                  # :           ( "Then",  "Name" );
8771
8772                         if ( $max_line > 1 ) {
8773                             my $leading_token = $tokens_to_go[$ibeg_next];
8774                             my $tokens_differ;
8775
8776                             # never indent line 1 of a '.' series because
8777                             # previous line is most likely at same level.
8778                             # TODO: we should also look at the leasing_spaces
8779                             # of the last output line and skip if it is same
8780                             # as this line.
8781                             next if ( $leading_token eq '.' );
8782
8783                             my $count = 1;
8784                             foreach my $l ( 2 .. 3 ) {
8785                                 last if ( $line + $l > $max_line );
8786                                 my $ibeg_next_next = $ri_first->[ $line + $l ];
8787                                 if ( $tokens_to_go[$ibeg_next_next] ne
8788                                     $leading_token )
8789                                 {
8790                                     $tokens_differ = 1;
8791                                     last;
8792                                 }
8793                                 $count++;
8794                             }
8795                             next if ($tokens_differ);
8796                             next if ( $count < 3 && $leading_token ne ':' );
8797                             $ipad = $ibeg;
8798                         }
8799                         else {
8800                             next;
8801                         }
8802                     }
8803                 }
8804             }
8805
8806             # find interior token to pad if necessary
8807             if ( !defined($ipad) ) {
8808
8809                 for ( my $i = $ibeg ; ( $i < $iend ) && !$ipad ; $i++ ) {
8810
8811                     # find any unclosed container
8812                     next
8813                       unless ( $type_sequence_to_go[$i]
8814                         && $self->mate_index_to_go($i) > $iend );
8815
8816                     # find next nonblank token to pad
8817                     $ipad = $inext_to_go[$i];
8818                     last if ( $ipad > $iend );
8819                 }
8820                 last unless $ipad;
8821             }
8822
8823             # We cannot pad the first leading token of a file because
8824             # it could cause a bug in which the starting indentation
8825             # level is guessed incorrectly each time the code is run
8826             # though perltidy, thus causing the code to march off to
8827             # the right.  For example, the following snippet would have
8828             # this problem:
8829
8830 ##     ov_method mycan( $package, '(""' ),       $package
8831 ##  or ov_method mycan( $package, '(0+' ),       $package
8832 ##  or ov_method mycan( $package, '(bool' ),     $package
8833 ##  or ov_method mycan( $package, '(nomethod' ), $package;
8834
8835             # If this snippet is within a block this won't happen
8836             # unless the user just processes the snippet alone within
8837             # an editor.  In that case either the user will see and
8838             # fix the problem or it will be corrected next time the
8839             # entire file is processed with perltidy.
8840             next if ( $ipad == 0 && $peak_batch_size <= 1 );
8841
8842 ## THIS PATCH REMOVES THE FOLLOWING POOR PADDING (math.t) with -pbp, BUT
8843 ## IT DID MORE HARM THAN GOOD
8844 ##            ceil(
8845 ##                      $font->{'loca'}->{'glyphs'}[$x]->read->{'xMin'} * 1000
8846 ##                    / $upem
8847 ##            ),
8848 ##?            # do not put leading padding for just 2 lines of math
8849 ##?            if (   $ipad == $ibeg
8850 ##?                && $line > 0
8851 ##?                && $levels_to_go[$ipad] > $levels_to_go[ $ipad - 1 ]
8852 ##?                && $is_math_op{$type_next}
8853 ##?                && $line + 2 <= $max_line )
8854 ##?            {
8855 ##?                my $ibeg_next_next = $ri_first->[ $line + 2 ];
8856 ##?                my $type_next_next = $types_to_go[$ibeg_next_next];
8857 ##?                next if !$is_math_op{$type_next_next};
8858 ##?            }
8859
8860             # next line must not be at greater depth
8861             my $iend_next = $ri_last->[ $line + 1 ];
8862             next
8863               if ( $nesting_depth_to_go[ $iend_next + 1 ] >
8864                 $nesting_depth_to_go[$ipad] );
8865
8866             # lines must be somewhat similar to be padded..
8867             my $inext_next = $inext_to_go[$ibeg_next];
8868             my $type       = $types_to_go[$ipad];
8869             my $type_next  = $types_to_go[ $ipad + 1 ];
8870
8871             # see if there are multiple continuation lines
8872             my $logical_continuation_lines = 1;
8873             if ( $line + 2 <= $max_line ) {
8874                 my $leading_token  = $tokens_to_go[$ibeg_next];
8875                 my $ibeg_next_next = $ri_first->[ $line + 2 ];
8876                 if (   $tokens_to_go[$ibeg_next_next] eq $leading_token
8877                     && $nesting_depth_to_go[$ibeg_next] eq
8878                     $nesting_depth_to_go[$ibeg_next_next] )
8879                 {
8880                     $logical_continuation_lines++;
8881                 }
8882             }
8883
8884             # see if leading types match
8885             my $types_match = $types_to_go[$inext_next] eq $type;
8886             my $matches_without_bang;
8887
8888             # if first line has leading ! then compare the following token
8889             if ( !$types_match && $type eq '!' ) {
8890                 $types_match = $matches_without_bang =
8891                   $types_to_go[$inext_next] eq $types_to_go[ $ipad + 1 ];
8892             }
8893
8894             if (
8895
8896                 # either we have multiple continuation lines to follow
8897                 # and we are not padding the first token
8898                 ( $logical_continuation_lines > 1 && $ipad > 0 )
8899
8900                 # or..
8901                 || (
8902
8903                     # types must match
8904                     $types_match
8905
8906                     # and keywords must match if keyword
8907                     && !(
8908                            $type eq 'k'
8909                         && $tokens_to_go[$ipad] ne $tokens_to_go[$inext_next]
8910                     )
8911                 )
8912               )
8913             {
8914
8915                 #----------------------begin special checks--------------
8916                 #
8917                 # SPECIAL CHECK 1:
8918                 # A check is needed before we can make the pad.
8919                 # If we are in a list with some long items, we want each
8920                 # item to stand out.  So in the following example, the
8921                 # first line beginning with '$casefold->' would look good
8922                 # padded to align with the next line, but then it
8923                 # would be indented more than the last line, so we
8924                 # won't do it.
8925                 #
8926                 #  ok(
8927                 #      $casefold->{code}         eq '0041'
8928                 #        && $casefold->{status}  eq 'C'
8929                 #        && $casefold->{mapping} eq '0061',
8930                 #      'casefold 0x41'
8931                 #  );
8932                 #
8933                 # Note:
8934                 # It would be faster, and almost as good, to use a comma
8935                 # count, and not pad if comma_count > 1 and the previous
8936                 # line did not end with a comma.
8937                 #
8938                 my $ok_to_pad = 1;
8939
8940                 my $ibg   = $ri_first->[ $line + 1 ];
8941                 my $depth = $nesting_depth_to_go[ $ibg + 1 ];
8942
8943                 # just use simplified formula for leading spaces to avoid
8944                 # needless sub calls
8945                 my $lsp = $levels_to_go[$ibg] + $ci_levels_to_go[$ibg];
8946
8947                 # look at each line beyond the next ..
8948                 my $l = $line + 1;
8949                 foreach my $ltest ( $line + 2 .. $max_line ) {
8950                     $l = $ltest;
8951                     my $ibg = $ri_first->[$l];
8952
8953                     # quit looking at the end of this container
8954                     last
8955                       if ( $nesting_depth_to_go[ $ibg + 1 ] < $depth )
8956                       || ( $nesting_depth_to_go[$ibg] < $depth );
8957
8958                     # cannot do the pad if a later line would be
8959                     # outdented more
8960                     if ( $levels_to_go[$ibg] + $ci_levels_to_go[$ibg] < $lsp ) {
8961                         $ok_to_pad = 0;
8962                         last;
8963                     }
8964                 }
8965
8966                 # don't pad if we end in a broken list
8967                 if ( $l == $max_line ) {
8968                     my $i2 = $ri_last->[$l];
8969                     if ( $types_to_go[$i2] eq '#' ) {
8970                         my $i1 = $ri_first->[$l];
8971                         next if $self->terminal_type_i( $i1, $i2 ) eq ',';
8972                     }
8973                 }
8974
8975                 # SPECIAL CHECK 2:
8976                 # a minus may introduce a quoted variable, and we will
8977                 # add the pad only if this line begins with a bare word,
8978                 # such as for the word 'Button' here:
8979                 #    [
8980                 #         Button      => "Print letter \"~$_\"",
8981                 #        -command     => [ sub { print "$_[0]\n" }, $_ ],
8982                 #        -accelerator => "Meta+$_"
8983                 #    ];
8984                 #
8985                 #  On the other hand, if 'Button' is quoted, it looks best
8986                 #  not to pad:
8987                 #    [
8988                 #        'Button'     => "Print letter \"~$_\"",
8989                 #        -command     => [ sub { print "$_[0]\n" }, $_ ],
8990                 #        -accelerator => "Meta+$_"
8991                 #    ];
8992                 if ( $types_to_go[$ibeg_next] eq 'm' ) {
8993                     $ok_to_pad = 0 if $types_to_go[$ibeg] eq 'Q';
8994                 }
8995
8996                 next unless $ok_to_pad;
8997
8998                 #----------------------end special check---------------
8999
9000                 my $length_1 = total_line_length( $ibeg,      $ipad - 1 );
9001                 my $length_2 = total_line_length( $ibeg_next, $inext_next - 1 );
9002                 $pad_spaces = $length_2 - $length_1;
9003
9004                 # If the first line has a leading ! and the second does
9005                 # not, then remove one space to try to align the next
9006                 # leading characters, which are often the same.  For example:
9007                 #  if (  !$ts
9008                 #      || $ts == $self->Holder
9009                 #      || $self->Holder->Type eq "Arena" )
9010                 #
9011                 # This usually helps readability, but if there are subsequent
9012                 # ! operators things will still get messed up.  For example:
9013                 #
9014                 #  if (  !exists $Net::DNS::typesbyname{$qtype}
9015                 #      && exists $Net::DNS::classesbyname{$qtype}
9016                 #      && !exists $Net::DNS::classesbyname{$qclass}
9017                 #      && exists $Net::DNS::typesbyname{$qclass} )
9018                 # We can't fix that.
9019                 if ($matches_without_bang) { $pad_spaces-- }
9020
9021                 # make sure this won't change if -lp is used
9022                 my $indentation_1 = $leading_spaces_to_go[$ibeg];
9023                 if ( ref($indentation_1) ) {
9024                     if ( $indentation_1->get_recoverable_spaces() == 0 ) {
9025                         my $indentation_2 = $leading_spaces_to_go[$ibeg_next];
9026                         unless ( $indentation_2->get_recoverable_spaces() == 0 )
9027                         {
9028                             $pad_spaces = 0;
9029                         }
9030                     }
9031                 }
9032
9033                 # we might be able to handle a pad of -1 by removing a blank
9034                 # token
9035                 if ( $pad_spaces < 0 ) {
9036
9037                     if ( $pad_spaces == -1 ) {
9038                         if ( $ipad > $ibeg && $types_to_go[ $ipad - 1 ] eq 'b' )
9039                         {
9040                             $self->pad_token( $ipad - 1, $pad_spaces );
9041                         }
9042                     }
9043                     $pad_spaces = 0;
9044                 }
9045
9046                 # now apply any padding for alignment
9047                 if ( $ipad >= 0 && $pad_spaces ) {
9048
9049                     my $length_t = total_line_length( $ibeg, $iend );
9050                     if ( $pad_spaces + $length_t <= maximum_line_length($ibeg) )
9051                     {
9052                         $self->pad_token( $ipad, $pad_spaces );
9053                     }
9054                 }
9055             }
9056         }
9057         continue {
9058             $iendm          = $iend;
9059             $ibegm          = $ibeg;
9060             $has_leading_op = $has_leading_op_next;
9061         }    # end of loop over lines
9062         return;
9063     }
9064 }
9065
9066 sub correct_lp_indentation {
9067
9068     # When the -lp option is used, we need to make a last pass through
9069     # each line to correct the indentation positions in case they differ
9070     # from the predictions.  This is necessary because perltidy uses a
9071     # predictor/corrector method for aligning with opening parens.  The
9072     # predictor is usually good, but sometimes stumbles.  The corrector
9073     # tries to patch things up once the actual opening paren locations
9074     # are known.
9075     my ( $ri_first, $ri_last ) = @_;
9076     my $do_not_pad = 0;
9077
9078     #  Note on flag '$do_not_pad':
9079     #  We want to avoid a situation like this, where the aligner inserts
9080     #  whitespace before the '=' to align it with a previous '=', because
9081     #  otherwise the parens might become mis-aligned in a situation like
9082     #  this, where the '=' has become aligned with the previous line,
9083     #  pushing the opening '(' forward beyond where we want it.
9084     #
9085     #  $mkFloor::currentRoom = '';
9086     #  $mkFloor::c_entry     = $c->Entry(
9087     #                                 -width        => '10',
9088     #                                 -relief       => 'sunken',
9089     #                                 ...
9090     #                                 );
9091     #
9092     #  We leave it to the aligner to decide how to do this.
9093
9094     # first remove continuation indentation if appropriate
9095     my $max_line = @{$ri_first} - 1;
9096
9097     # looking at each line of this batch..
9098     my ( $ibeg, $iend );
9099     foreach my $line ( 0 .. $max_line ) {
9100         $ibeg = $ri_first->[$line];
9101         $iend = $ri_last->[$line];
9102
9103         # looking at each token in this output line..
9104         foreach my $i ( $ibeg .. $iend ) {
9105
9106             # How many space characters to place before this token
9107             # for special alignment.  Actual padding is done in the
9108             # continue block.
9109
9110             # looking for next unvisited indentation item
9111             my $indentation = $leading_spaces_to_go[$i];
9112             if ( !$indentation->get_marked() ) {
9113                 $indentation->set_marked(1);
9114
9115                 # looking for indentation item for which we are aligning
9116                 # with parens, braces, and brackets
9117                 next unless ( $indentation->get_align_paren() );
9118
9119                 # skip closed container on this line
9120                 if ( $i > $ibeg ) {
9121                     my $im = max( $ibeg, $iprev_to_go[$i] );
9122                     if (   $type_sequence_to_go[$im]
9123                         && $mate_index_to_go[$im] <= $iend )
9124                     {
9125                         next;
9126                     }
9127                 }
9128
9129                 if ( $line == 1 && $i == $ibeg ) {
9130                     $do_not_pad = 1;
9131                 }
9132
9133                 # Ok, let's see what the error is and try to fix it
9134                 my $actual_pos;
9135                 my $predicted_pos = $indentation->get_spaces();
9136                 if ( $i > $ibeg ) {
9137
9138                     # token is mid-line - use length to previous token
9139                     $actual_pos = total_line_length( $ibeg, $i - 1 );
9140
9141                     # for mid-line token, we must check to see if all
9142                     # additional lines have continuation indentation,
9143                     # and remove it if so.  Otherwise, we do not get
9144                     # good alignment.
9145                     my $closing_index = $indentation->get_closed();
9146                     if ( $closing_index > $iend ) {
9147                         my $ibeg_next = $ri_first->[ $line + 1 ];
9148                         if ( $ci_levels_to_go[$ibeg_next] > 0 ) {
9149                             undo_lp_ci( $line, $i, $closing_index, $ri_first,
9150                                 $ri_last );
9151                         }
9152                     }
9153                 }
9154                 elsif ( $line > 0 ) {
9155
9156                     # handle case where token starts a new line;
9157                     # use length of previous line
9158                     my $ibegm = $ri_first->[ $line - 1 ];
9159                     my $iendm = $ri_last->[ $line - 1 ];
9160                     $actual_pos = total_line_length( $ibegm, $iendm );
9161
9162                     # follow -pt style
9163                     ++$actual_pos
9164                       if ( $types_to_go[ $iendm + 1 ] eq 'b' );
9165                 }
9166                 else {
9167
9168                     # token is first character of first line of batch
9169                     $actual_pos = $predicted_pos;
9170                 }
9171
9172                 my $move_right = $actual_pos - $predicted_pos;
9173
9174                 # done if no error to correct (gnu2.t)
9175                 if ( $move_right == 0 ) {
9176                     $indentation->set_recoverable_spaces($move_right);
9177                     next;
9178                 }
9179
9180                 # if we have not seen closure for this indentation in
9181                 # this batch, we can only pass on a request to the
9182                 # vertical aligner
9183                 my $closing_index = $indentation->get_closed();
9184
9185                 if ( $closing_index < 0 ) {
9186                     $indentation->set_recoverable_spaces($move_right);
9187                     next;
9188                 }
9189
9190                 # If necessary, look ahead to see if there is really any
9191                 # leading whitespace dependent on this whitespace, and
9192                 # also find the longest line using this whitespace.
9193                 # Since it is always safe to move left if there are no
9194                 # dependents, we only need to do this if we may have
9195                 # dependent nodes or need to move right.
9196
9197                 my $right_margin = 0;
9198                 my $have_child   = $indentation->get_have_child();
9199
9200                 my %saw_indentation;
9201                 my $line_count = 1;
9202                 $saw_indentation{$indentation} = $indentation;
9203
9204                 if ( $have_child || $move_right > 0 ) {
9205                     $have_child = 0;
9206                     my $max_length = 0;
9207                     if ( $i == $ibeg ) {
9208                         $max_length = total_line_length( $ibeg, $iend );
9209                     }
9210
9211                     # look ahead at the rest of the lines of this batch..
9212                     foreach my $line_t ( $line + 1 .. $max_line ) {
9213                         my $ibeg_t = $ri_first->[$line_t];
9214                         my $iend_t = $ri_last->[$line_t];
9215                         last if ( $closing_index <= $ibeg_t );
9216
9217                         # remember all different indentation objects
9218                         my $indentation_t = $leading_spaces_to_go[$ibeg_t];
9219                         $saw_indentation{$indentation_t} = $indentation_t;
9220                         $line_count++;
9221
9222                         # remember longest line in the group
9223                         my $length_t = total_line_length( $ibeg_t, $iend_t );
9224                         if ( $length_t > $max_length ) {
9225                             $max_length = $length_t;
9226                         }
9227                     }
9228                     $right_margin = maximum_line_length($ibeg) - $max_length;
9229                     if ( $right_margin < 0 ) { $right_margin = 0 }
9230                 }
9231
9232                 my $first_line_comma_count =
9233                   grep { $_ eq ',' } @types_to_go[ $ibeg .. $iend ];
9234                 my $comma_count = $indentation->get_comma_count();
9235                 my $arrow_count = $indentation->get_arrow_count();
9236
9237                 # This is a simple approximate test for vertical alignment:
9238                 # if we broke just after an opening paren, brace, bracket,
9239                 # and there are 2 or more commas in the first line,
9240                 # and there are no '=>'s,
9241                 # then we are probably vertically aligned.  We could set
9242                 # an exact flag in sub scan_list, but this is good
9243                 # enough.
9244                 my $indentation_count = keys %saw_indentation;
9245                 my $is_vertically_aligned =
9246                   (      $i == $ibeg
9247                       && $first_line_comma_count > 1
9248                       && $indentation_count == 1
9249                       && ( $arrow_count == 0 || $arrow_count == $line_count ) );
9250
9251                 # Make the move if possible ..
9252                 if (
9253
9254                     # we can always move left
9255                     $move_right < 0
9256
9257                     # but we should only move right if we are sure it will
9258                     # not spoil vertical alignment
9259                     || ( $comma_count == 0 )
9260                     || ( $comma_count > 0 && !$is_vertically_aligned )
9261                   )
9262                 {
9263                     my $move =
9264                       ( $move_right <= $right_margin )
9265                       ? $move_right
9266                       : $right_margin;
9267
9268                     foreach ( keys %saw_indentation ) {
9269                         $saw_indentation{$_}
9270                           ->permanently_decrease_available_spaces( -$move );
9271                     }
9272                 }
9273
9274                 # Otherwise, record what we want and the vertical aligner
9275                 # will try to recover it.
9276                 else {
9277                     $indentation->set_recoverable_spaces($move_right);
9278                 }
9279             }
9280         }
9281     }
9282     return $do_not_pad;
9283 }
9284
9285 # flush is called to output any tokens in the pipeline, so that
9286 # an alternate source of lines can be written in the correct order
9287
9288 sub flush {
9289     my $self = shift;
9290     destroy_one_line_block();
9291     $self->output_line_to_go();
9292     Perl::Tidy::VerticalAligner::flush();
9293     return;
9294 }
9295
9296 sub reset_block_text_accumulator {
9297
9298     # save text after 'if' and 'elsif' to append after 'else'
9299     if ($accumulating_text_for_block) {
9300
9301         if ( $accumulating_text_for_block =~ /^(if|elsif)$/ ) {
9302             push @{$rleading_block_if_elsif_text}, $leading_block_text;
9303         }
9304     }
9305     $accumulating_text_for_block        = "";
9306     $leading_block_text                 = "";
9307     $leading_block_text_level           = 0;
9308     $leading_block_text_length_exceeded = 0;
9309     $leading_block_text_line_number     = 0;
9310     $leading_block_text_line_length     = 0;
9311     return;
9312 }
9313
9314 sub set_block_text_accumulator {
9315     my $i = shift;
9316     $accumulating_text_for_block = $tokens_to_go[$i];
9317     if ( $accumulating_text_for_block !~ /^els/ ) {
9318         $rleading_block_if_elsif_text = [];
9319     }
9320     $leading_block_text                 = "";
9321     $leading_block_text_level           = $levels_to_go[$i];
9322     $leading_block_text_line_number     = get_output_line_number();
9323     $leading_block_text_length_exceeded = 0;
9324
9325     # this will contain the column number of the last character
9326     # of the closing side comment
9327     $leading_block_text_line_length =
9328       length($csc_last_label) +
9329       length($accumulating_text_for_block) +
9330       length( $rOpts->{'closing-side-comment-prefix'} ) +
9331       $leading_block_text_level * $rOpts_indent_columns + 3;
9332     return;
9333 }
9334
9335 sub accumulate_block_text {
9336     my $i = shift;
9337
9338     # accumulate leading text for -csc, ignoring any side comments
9339     if (   $accumulating_text_for_block
9340         && !$leading_block_text_length_exceeded
9341         && $types_to_go[$i] ne '#' )
9342     {
9343
9344         my $added_length = $token_lengths_to_go[$i];
9345         $added_length += 1 if $i == 0;
9346         my $new_line_length = $leading_block_text_line_length + $added_length;
9347
9348         # we can add this text if we don't exceed some limits..
9349         if (
9350
9351             # we must not have already exceeded the text length limit
9352             length($leading_block_text) <
9353             $rOpts_closing_side_comment_maximum_text
9354
9355             # and either:
9356             # the new total line length must be below the line length limit
9357             # or the new length must be below the text length limit
9358             # (ie, we may allow one token to exceed the text length limit)
9359             && (
9360                 $new_line_length <
9361                 maximum_line_length_for_level($leading_block_text_level)
9362
9363                 || length($leading_block_text) + $added_length <
9364                 $rOpts_closing_side_comment_maximum_text
9365             )
9366
9367             # UNLESS: we are adding a closing paren before the brace we seek.
9368             # This is an attempt to avoid situations where the ... to be
9369             # added are longer than the omitted right paren, as in:
9370
9371             #   foreach my $item (@a_rather_long_variable_name_here) {
9372             #      &whatever;
9373             #   } ## end foreach my $item (@a_rather_long_variable_name_here...
9374
9375             || (
9376                 $tokens_to_go[$i] eq ')'
9377                 && (
9378                     (
9379                            $i + 1 <= $max_index_to_go
9380                         && $block_type_to_go[ $i + 1 ] eq
9381                         $accumulating_text_for_block
9382                     )
9383                     || (   $i + 2 <= $max_index_to_go
9384                         && $block_type_to_go[ $i + 2 ] eq
9385                         $accumulating_text_for_block )
9386                 )
9387             )
9388           )
9389         {
9390
9391             # add an extra space at each newline
9392             if ( $i == 0 ) { $leading_block_text .= ' ' }
9393
9394             # add the token text
9395             $leading_block_text .= $tokens_to_go[$i];
9396             $leading_block_text_line_length = $new_line_length;
9397         }
9398
9399         # show that text was truncated if necessary
9400         elsif ( $types_to_go[$i] ne 'b' ) {
9401             $leading_block_text_length_exceeded = 1;
9402             $leading_block_text .= '...';
9403         }
9404     }
9405     return;
9406 }
9407
9408 {
9409     my %is_if_elsif_else_unless_while_until_for_foreach;
9410
9411     BEGIN {
9412
9413         # These block types may have text between the keyword and opening
9414         # curly.  Note: 'else' does not, but must be included to allow trailing
9415         # if/elsif text to be appended.
9416         # patch for SWITCH/CASE: added 'case' and 'when'
9417         my @q =
9418           qw(if elsif else unless while until for foreach case when catch);
9419         @is_if_elsif_else_unless_while_until_for_foreach{@q} =
9420           (1) x scalar(@q);
9421     }
9422
9423     sub accumulate_csc_text {
9424
9425         # called once per output buffer when -csc is used. Accumulates
9426         # the text placed after certain closing block braces.
9427         # Defines and returns the following for this buffer:
9428
9429         my $block_leading_text = "";    # the leading text of the last '}'
9430         my $rblock_leading_if_elsif_text;
9431         my $i_block_leading_text =
9432           -1;    # index of token owning block_leading_text
9433         my $block_line_count    = 100;    # how many lines the block spans
9434         my $terminal_type       = 'b';    # type of last nonblank token
9435         my $i_terminal          = 0;      # index of last nonblank token
9436         my $terminal_block_type = "";
9437
9438         # update most recent statement label
9439         $csc_last_label = "" unless ($csc_last_label);
9440         if ( $types_to_go[0] eq 'J' ) { $csc_last_label = $tokens_to_go[0] }
9441         my $block_label = $csc_last_label;
9442
9443         # Loop over all tokens of this batch
9444         for my $i ( 0 .. $max_index_to_go ) {
9445             my $type       = $types_to_go[$i];
9446             my $block_type = $block_type_to_go[$i];
9447             my $token      = $tokens_to_go[$i];
9448
9449             # remember last nonblank token type
9450             if ( $type ne '#' && $type ne 'b' ) {
9451                 $terminal_type       = $type;
9452                 $terminal_block_type = $block_type;
9453                 $i_terminal          = $i;
9454             }
9455
9456             my $type_sequence = $type_sequence_to_go[$i];
9457             if ( $block_type && $type_sequence ) {
9458
9459                 if ( $token eq '}' ) {
9460
9461                     # restore any leading text saved when we entered this block
9462                     if ( defined( $block_leading_text{$type_sequence} ) ) {
9463                         ( $block_leading_text, $rblock_leading_if_elsif_text )
9464                           = @{ $block_leading_text{$type_sequence} };
9465                         $i_block_leading_text = $i;
9466                         delete $block_leading_text{$type_sequence};
9467                         $rleading_block_if_elsif_text =
9468                           $rblock_leading_if_elsif_text;
9469                     }
9470
9471                     if ( defined( $csc_block_label{$type_sequence} ) ) {
9472                         $block_label = $csc_block_label{$type_sequence};
9473                         delete $csc_block_label{$type_sequence};
9474                     }
9475
9476                     # if we run into a '}' then we probably started accumulating
9477                     # at something like a trailing 'if' clause..no harm done.
9478                     if (   $accumulating_text_for_block
9479                         && $levels_to_go[$i] <= $leading_block_text_level )
9480                     {
9481                         my $lev = $levels_to_go[$i];
9482                         reset_block_text_accumulator();
9483                     }
9484
9485                     if ( defined( $block_opening_line_number{$type_sequence} ) )
9486                     {
9487                         my $output_line_number = get_output_line_number();
9488                         $block_line_count =
9489                           $output_line_number -
9490                           $block_opening_line_number{$type_sequence} + 1;
9491                         delete $block_opening_line_number{$type_sequence};
9492                     }
9493                     else {
9494
9495                         # Error: block opening line undefined for this line..
9496                         # This shouldn't be possible, but it is not a
9497                         # significant problem.
9498                     }
9499                 }
9500
9501                 elsif ( $token eq '{' ) {
9502
9503                     my $line_number = get_output_line_number();
9504                     $block_opening_line_number{$type_sequence} = $line_number;
9505
9506                     # set a label for this block, except for
9507                     # a bare block which already has the label
9508                     # A label can only be used on the next {
9509                     if ( $block_type =~ /:$/ ) { $csc_last_label = "" }
9510                     $csc_block_label{$type_sequence} = $csc_last_label;
9511                     $csc_last_label = "";
9512
9513                     if (   $accumulating_text_for_block
9514                         && $levels_to_go[$i] == $leading_block_text_level )
9515                     {
9516
9517                         if ( $accumulating_text_for_block eq $block_type ) {
9518
9519                             # save any leading text before we enter this block
9520                             $block_leading_text{$type_sequence} = [
9521                                 $leading_block_text,
9522                                 $rleading_block_if_elsif_text
9523                             ];
9524                             $block_opening_line_number{$type_sequence} =
9525                               $leading_block_text_line_number;
9526                             reset_block_text_accumulator();
9527                         }
9528                         else {
9529
9530                             # shouldn't happen, but not a serious error.
9531                             # We were accumulating -csc text for block type
9532                             # $accumulating_text_for_block and unexpectedly
9533                             # encountered a '{' for block type $block_type.
9534                         }
9535                     }
9536                 }
9537             }
9538
9539             if (   $type eq 'k'
9540                 && $csc_new_statement_ok
9541                 && $is_if_elsif_else_unless_while_until_for_foreach{$token}
9542                 && $token =~ /$closing_side_comment_list_pattern/o )
9543             {
9544                 set_block_text_accumulator($i);
9545             }
9546             else {
9547
9548                 # note: ignoring type 'q' because of tricks being played
9549                 # with 'q' for hanging side comments
9550                 if ( $type ne 'b' && $type ne '#' && $type ne 'q' ) {
9551                     $csc_new_statement_ok =
9552                       ( $block_type || $type eq 'J' || $type eq ';' );
9553                 }
9554                 if (   $type eq ';'
9555                     && $accumulating_text_for_block
9556                     && $levels_to_go[$i] == $leading_block_text_level )
9557                 {
9558                     reset_block_text_accumulator();
9559                 }
9560                 else {
9561                     accumulate_block_text($i);
9562                 }
9563             }
9564         }
9565
9566         # Treat an 'else' block specially by adding preceding 'if' and
9567         # 'elsif' text.  Otherwise, the 'end else' is not helpful,
9568         # especially for cuddled-else formatting.
9569         if ( $terminal_block_type =~ /^els/ && $rblock_leading_if_elsif_text ) {
9570             $block_leading_text =
9571               make_else_csc_text( $i_terminal, $terminal_block_type,
9572                 $block_leading_text, $rblock_leading_if_elsif_text );
9573         }
9574
9575         # if this line ends in a label then remember it for the next pass
9576         $csc_last_label = "";
9577         if ( $terminal_type eq 'J' ) {
9578             $csc_last_label = $tokens_to_go[$i_terminal];
9579         }
9580
9581         return ( $terminal_type, $i_terminal, $i_block_leading_text,
9582             $block_leading_text, $block_line_count, $block_label );
9583     }
9584 }
9585
9586 sub make_else_csc_text {
9587
9588     # create additional -csc text for an 'else' and optionally 'elsif',
9589     # depending on the value of switch
9590     # $rOpts_closing_side_comment_else_flag:
9591     #
9592     #  = 0 add 'if' text to trailing else
9593     #  = 1 same as 0 plus:
9594     #      add 'if' to 'elsif's if can fit in line length
9595     #      add last 'elsif' to trailing else if can fit in one line
9596     #  = 2 same as 1 but do not check if exceed line length
9597     #
9598     # $rif_elsif_text = a reference to a list of all previous closing
9599     # side comments created for this if block
9600     #
9601     my ( $i_terminal, $block_type, $block_leading_text, $rif_elsif_text ) = @_;
9602     my $csc_text = $block_leading_text;
9603
9604     if (   $block_type eq 'elsif'
9605         && $rOpts_closing_side_comment_else_flag == 0 )
9606     {
9607         return $csc_text;
9608     }
9609
9610     my $count = @{$rif_elsif_text};
9611     return $csc_text unless ($count);
9612
9613     my $if_text = '[ if' . $rif_elsif_text->[0];
9614
9615     # always show the leading 'if' text on 'else'
9616     if ( $block_type eq 'else' ) {
9617         $csc_text .= $if_text;
9618     }
9619
9620     # see if that's all
9621     if ( $rOpts_closing_side_comment_else_flag == 0 ) {
9622         return $csc_text;
9623     }
9624
9625     my $last_elsif_text = "";
9626     if ( $count > 1 ) {
9627         $last_elsif_text = ' [elsif' . $rif_elsif_text->[ $count - 1 ];
9628         if ( $count > 2 ) { $last_elsif_text = ' [...' . $last_elsif_text; }
9629     }
9630
9631     # tentatively append one more item
9632     my $saved_text = $csc_text;
9633     if ( $block_type eq 'else' ) {
9634         $csc_text .= $last_elsif_text;
9635     }
9636     else {
9637         $csc_text .= ' ' . $if_text;
9638     }
9639
9640     # all done if no length checks requested
9641     if ( $rOpts_closing_side_comment_else_flag == 2 ) {
9642         return $csc_text;
9643     }
9644
9645     # undo it if line length exceeded
9646     my $length =
9647       length($csc_text) +
9648       length($block_type) +
9649       length( $rOpts->{'closing-side-comment-prefix'} ) +
9650       $levels_to_go[$i_terminal] * $rOpts_indent_columns + 3;
9651     if ( $length > maximum_line_length_for_level($leading_block_text_level) ) {
9652         $csc_text = $saved_text;
9653     }
9654     return $csc_text;
9655 }
9656
9657 {    # sub balance_csc_text
9658
9659     my %matching_char;
9660
9661     BEGIN {
9662         %matching_char = (
9663             '{' => '}',
9664             '(' => ')',
9665             '[' => ']',
9666             '}' => '{',
9667             ')' => '(',
9668             ']' => '[',
9669         );
9670     }
9671
9672     sub balance_csc_text {
9673
9674         # Append characters to balance a closing side comment so that editors
9675         # such as vim can correctly jump through code.
9676         # Simple Example:
9677         #  input  = ## end foreach my $foo ( sort { $b  ...
9678         #  output = ## end foreach my $foo ( sort { $b  ...})
9679
9680         # NOTE: This routine does not currently filter out structures within
9681         # quoted text because the bounce algorithms in text editors do not
9682         # necessarily do this either (a version of vim was checked and
9683         # did not do this).
9684
9685         # Some complex examples which will cause trouble for some editors:
9686         #  while ( $mask_string =~ /\{[^{]*?\}/g ) {
9687         #  if ( $mask_str =~ /\}\s*els[^\{\}]+\{$/ ) {
9688         #  if ( $1 eq '{' ) {
9689         # test file test1/braces.pl has many such examples.
9690
9691         my ($csc) = @_;
9692
9693         # loop to examine characters one-by-one, RIGHT to LEFT and
9694         # build a balancing ending, LEFT to RIGHT.
9695         for ( my $pos = length($csc) - 1 ; $pos >= 0 ; $pos-- ) {
9696
9697             my $char = substr( $csc, $pos, 1 );
9698
9699             # ignore everything except structural characters
9700             next unless ( $matching_char{$char} );
9701
9702             # pop most recently appended character
9703             my $top = chop($csc);
9704
9705             # push it back plus the mate to the newest character
9706             # unless they balance each other.
9707             $csc = $csc . $top . $matching_char{$char} unless $top eq $char;
9708         }
9709
9710         # return the balanced string
9711         return $csc;
9712     }
9713 }
9714
9715 sub add_closing_side_comment {
9716
9717     my $self = shift;
9718
9719     # add closing side comments after closing block braces if -csc used
9720     my ( $closing_side_comment, $cscw_block_comment );
9721
9722     #---------------------------------------------------------------
9723     # Step 1: loop through all tokens of this line to accumulate
9724     # the text needed to create the closing side comments. Also see
9725     # how the line ends.
9726     #---------------------------------------------------------------
9727
9728     my ( $terminal_type, $i_terminal, $i_block_leading_text,
9729         $block_leading_text, $block_line_count, $block_label )
9730       = accumulate_csc_text();
9731
9732     #---------------------------------------------------------------
9733     # Step 2: make the closing side comment if this ends a block
9734     #---------------------------------------------------------------
9735     my $have_side_comment = $types_to_go[$max_index_to_go] eq '#';
9736
9737     # if this line might end in a block closure..
9738     if (
9739         $terminal_type eq '}'
9740
9741         # ..and either
9742         && (
9743
9744             # the block is long enough
9745             ( $block_line_count >= $rOpts->{'closing-side-comment-interval'} )
9746
9747             # or there is an existing comment to check
9748             || (   $have_side_comment
9749                 && $rOpts->{'closing-side-comment-warnings'} )
9750         )
9751
9752         # .. and if this is one of the types of interest
9753         && $block_type_to_go[$i_terminal] =~
9754         /$closing_side_comment_list_pattern/o
9755
9756         # .. but not an anonymous sub
9757         # These are not normally of interest, and their closing braces are
9758         # often followed by commas or semicolons anyway.  This also avoids
9759         # possible erratic output due to line numbering inconsistencies
9760         # in the cases where their closing braces terminate a line.
9761         && $block_type_to_go[$i_terminal] ne 'sub'
9762
9763         # ..and the corresponding opening brace must is not in this batch
9764         # (because we do not need to tag one-line blocks, although this
9765         # should also be caught with a positive -csci value)
9766         && $self->mate_index_to_go($i_terminal) < 0
9767
9768         # ..and either
9769         && (
9770
9771             # this is the last token (line doesn't have a side comment)
9772             !$have_side_comment
9773
9774             # or the old side comment is a closing side comment
9775             || $tokens_to_go[$max_index_to_go] =~
9776             /$closing_side_comment_prefix_pattern/o
9777         )
9778       )
9779     {
9780
9781         # then make the closing side comment text
9782         if ($block_label) { $block_label .= " " }
9783         my $token =
9784 "$rOpts->{'closing-side-comment-prefix'} $block_label$block_type_to_go[$i_terminal]";
9785
9786         # append any extra descriptive text collected above
9787         if ( $i_block_leading_text == $i_terminal ) {
9788             $token .= $block_leading_text;
9789         }
9790
9791         $token = balance_csc_text($token)
9792           if $rOpts->{'closing-side-comments-balanced'};
9793
9794         $token =~ s/\s*$//;    # trim any trailing whitespace
9795
9796         # handle case of existing closing side comment
9797         if ($have_side_comment) {
9798
9799             # warn if requested and tokens differ significantly
9800             if ( $rOpts->{'closing-side-comment-warnings'} ) {
9801                 my $old_csc = $tokens_to_go[$max_index_to_go];
9802                 my $new_csc = $token;
9803                 $new_csc =~ s/\s+//g;            # trim all whitespace
9804                 $old_csc =~ s/\s+//g;            # trim all whitespace
9805                 $new_csc =~ s/[\]\)\}\s]*$//;    # trim trailing structures
9806                 $old_csc =~ s/[\]\)\}\s]*$//;    # trim trailing structures
9807                 $new_csc =~ s/(\.\.\.)$//;       # trim trailing '...'
9808                 my $new_trailing_dots = $1;
9809                 $old_csc =~ s/(\.\.\.)\s*$//;    # trim trailing '...'
9810
9811                 # Patch to handle multiple closing side comments at
9812                 # else and elsif's.  These have become too complicated
9813                 # to check, so if we see an indication of
9814                 # '[ if' or '[ # elsif', then assume they were made
9815                 # by perltidy.
9816                 if ( $block_type_to_go[$i_terminal] eq 'else' ) {
9817                     if ( $old_csc =~ /\[\s*elsif/ ) { $old_csc = $new_csc }
9818                 }
9819                 elsif ( $block_type_to_go[$i_terminal] eq 'elsif' ) {
9820                     if ( $old_csc =~ /\[\s*if/ ) { $old_csc = $new_csc }
9821                 }
9822
9823                 # if old comment is contained in new comment,
9824                 # only compare the common part.
9825                 if ( length($new_csc) > length($old_csc) ) {
9826                     $new_csc = substr( $new_csc, 0, length($old_csc) );
9827                 }
9828
9829                 # if the new comment is shorter and has been limited,
9830                 # only compare the common part.
9831                 if ( length($new_csc) < length($old_csc)
9832                     && $new_trailing_dots )
9833                 {
9834                     $old_csc = substr( $old_csc, 0, length($new_csc) );
9835                 }
9836
9837                 # any remaining difference?
9838                 if ( $new_csc ne $old_csc ) {
9839
9840                     # just leave the old comment if we are below the threshold
9841                     # for creating side comments
9842                     if ( $block_line_count <
9843                         $rOpts->{'closing-side-comment-interval'} )
9844                     {
9845                         $token = undef;
9846                     }
9847
9848                     # otherwise we'll make a note of it
9849                     else {
9850
9851                         warning(
9852 "perltidy -cscw replaced: $tokens_to_go[$max_index_to_go]\n"
9853                         );
9854
9855                         # save the old side comment in a new trailing block
9856                         # comment
9857                         my $timestamp = "";
9858                         if ( $rOpts->{'timestamp'} ) {
9859                             my ( $day, $month, $year ) = (localtime)[ 3, 4, 5 ];
9860                             $year  += 1900;
9861                             $month += 1;
9862                             $timestamp = "$year-$month-$day";
9863                         }
9864                         $cscw_block_comment =
9865 "## perltidy -cscw $timestamp: $tokens_to_go[$max_index_to_go]";
9866 ## "## perltidy -cscw $year-$month-$day: $tokens_to_go[$max_index_to_go]";
9867                     }
9868                 }
9869                 else {
9870
9871                     # No differences.. we can safely delete old comment if we
9872                     # are below the threshold
9873                     if ( $block_line_count <
9874                         $rOpts->{'closing-side-comment-interval'} )
9875                     {
9876                         $token = undef;
9877                         $self->unstore_token_to_go()
9878                           if ( $types_to_go[$max_index_to_go] eq '#' );
9879                         $self->unstore_token_to_go()
9880                           if ( $types_to_go[$max_index_to_go] eq 'b' );
9881                     }
9882                 }
9883             }
9884
9885             # switch to the new csc (unless we deleted it!)
9886             if ($token) {
9887                 $tokens_to_go[$max_index_to_go] = $token;
9888                 $self->sync_token_K($max_index_to_go);
9889             }
9890         }
9891
9892         # handle case of NO existing closing side comment
9893         else {
9894
9895             # To avoid inserting a new token in the token arrays, we
9896             # will just return the new side comment so that it can be
9897             # inserted just before it is needed in the call to the
9898             # vertical aligner.
9899             $closing_side_comment = $token;
9900         }
9901     }
9902     return ( $closing_side_comment, $cscw_block_comment );
9903 }
9904
9905 sub previous_nonblank_token {
9906     my ($i)  = @_;
9907     my $name = "";
9908     my $im   = $i - 1;
9909     return "" if ( $im < 0 );
9910     if ( $types_to_go[$im] eq 'b' ) { $im--; }
9911     return "" if ( $im < 0 );
9912     $name = $tokens_to_go[$im];
9913
9914     # prepend any sub name to an isolated -> to avoid unwanted alignments
9915     # [test case is test8/penco.pl]
9916     if ( $name eq '->' ) {
9917         $im--;
9918         if ( $im >= 0 && $types_to_go[$im] ne 'b' ) {
9919             $name = $tokens_to_go[$im] . $name;
9920         }
9921     }
9922     return $name;
9923 }
9924
9925 sub send_lines_to_vertical_aligner {
9926
9927     my ( $self, $rbatch_hash ) = @_;
9928
9929    # This routine receives a batch of code for which the final line breaks
9930    # have been defined. Here we prepare the lines for passing to the vertical
9931    # aligner.  We do the following tasks:
9932    # - mark certain vertical alignment tokens tokens, such as '=', in each line.
9933    # - make minor indentation adjustments
9934    # - insert extra blank spaces to help display certain logical constructions
9935
9936     my $rlines_K = $rbatch_hash->{rlines_K};
9937     if ( !@{$rlines_K} ) {
9938         Fault("Unexpected call with no lines");
9939         return;
9940     }
9941     my $n_last_line = @{$rlines_K} - 1;
9942     my $do_not_pad  = $rbatch_hash->{do_not_pad};
9943
9944     my $rLL    = $self->{rLL};
9945     my $Klimit = $self->{Klimit};
9946
9947     my ( $Kbeg_next, $Kend_next ) = @{ $rlines_K->[0] };
9948     my $type_beg_next  = $rLL->[$Kbeg_next]->[_TYPE_];
9949     my $token_beg_next = $rLL->[$Kbeg_next]->[_TOKEN_];
9950     my $type_end_next  = $rLL->[$Kend_next]->[_TYPE_];
9951
9952     # Construct indexes to the global_to_go arrays so that called routines can
9953     # still access those arrays. This might eventually be removed
9954     # when all called routines have been converted to access token values
9955     # in the rLL array instead.
9956     my $ibeg0 = $rbatch_hash->{ibeg0};
9957     my $Kbeg0 = $Kbeg_next;
9958     my ( $ri_first, $ri_last );
9959     foreach my $rline ( @{$rlines_K} ) {
9960         my ( $Kbeg, $Kend ) = @{$rline};
9961         my $ibeg = $ibeg0 + $Kbeg - $Kbeg0;
9962         my $iend = $ibeg0 + $Kend - $Kbeg0;
9963         push @{$ri_first}, $ibeg;
9964         push @{$ri_last},  $iend;
9965     }
9966     #####################################################################
9967
9968     my $valign_batch_number = $self->increment_valign_batch_count();
9969
9970     my ( $cscw_block_comment, $closing_side_comment );
9971     if ( $rOpts->{'closing-side-comments'} ) {
9972         ( $closing_side_comment, $cscw_block_comment ) =
9973           $self->add_closing_side_comment();
9974     }
9975
9976     my $rindentation_list = [0];    # ref to indentations for each line
9977
9978     # define the array @{$ralignment_type_to_go} for the output tokens
9979     # which will be non-blank for each special token (such as =>)
9980     # for which alignment is required.
9981     my $ralignment_type_to_go =
9982       $self->set_vertical_alignment_markers( $ri_first, $ri_last );
9983
9984     # flush before a long if statement to avoid unwanted alignment
9985     if (   $n_last_line > 0
9986         && $type_beg_next eq 'k'
9987         && $token_beg_next =~ /^(if|unless)$/ )
9988     {
9989         Perl::Tidy::VerticalAligner::flush();
9990     }
9991
9992     $self->undo_ci( $ri_first, $ri_last );
9993
9994     $self->set_logical_padding( $ri_first, $ri_last );
9995
9996     # loop to prepare each line for shipment
9997     my $in_comma_list;
9998     my ( $Kbeg, $type_beg, $token_beg );
9999     my ( $Kend, $type_end );
10000     for my $n ( 0 .. $n_last_line ) {
10001
10002         my $ibeg              = $ri_first->[$n];
10003         my $iend              = $ri_last->[$n];
10004         my $rline             = $rlines_K->[$n];
10005         my $forced_breakpoint = $rline->[2];
10006
10007         # we may need to look at variables on three consecutive lines ...
10008
10009         # Some vars on line [n-1], if any:
10010         my $Kbeg_last      = $Kbeg;
10011         my $type_beg_last  = $type_beg;
10012         my $token_beg_last = $token_beg;
10013         my $Kend_last      = $Kend;
10014         my $type_end_last  = $type_end;
10015
10016         # Some vars on line [n]:
10017         $Kbeg      = $Kbeg_next;
10018         $type_beg  = $type_beg_next;
10019         $token_beg = $token_beg_next;
10020         $Kend      = $Kend_next;
10021         $type_end  = $type_end_next;
10022
10023         # We use two slightly different definitions of level jump at the end
10024         # of line:
10025         #  $ljump is the level jump needed by 'sub set_adjusted_indentation'
10026         #  $level_jump is the level jump needed by the vertical aligner.
10027         my $ljump = 0;    # level jump at end of line
10028
10029         # Get some vars on line [n+1], if any:
10030         if ( $n < $n_last_line ) {
10031             ( $Kbeg_next, $Kend_next ) =
10032               @{ $rlines_K->[ $n + 1 ] };
10033             $type_beg_next  = $rLL->[$Kbeg_next]->[_TYPE_];
10034             $token_beg_next = $rLL->[$Kbeg_next]->[_TOKEN_];
10035             $type_end_next  = $rLL->[$Kend_next]->[_TYPE_];
10036             $ljump = $rLL->[$Kbeg_next]->[_LEVEL_] - $rLL->[$Kend]->[_LEVEL_];
10037         }
10038
10039         # level jump at end of line for the vertical aligner:
10040         my $level_jump =
10041           $Kend >= $Klimit
10042           ? 0
10043           : $rLL->[ $Kend + 1 ]->[_SLEVEL_] - $rLL->[$Kbeg]->[_SLEVEL_];
10044
10045         $self->delete_needless_alignments( $ibeg, $iend,
10046             $ralignment_type_to_go );
10047
10048         my ( $rtokens, $rfields, $rpatterns ) =
10049           $self->make_alignment_patterns( $ibeg, $iend,
10050             $ralignment_type_to_go );
10051
10052         my ( $indentation, $lev, $level_end, $terminal_type,
10053             $is_semicolon_terminated, $is_outdented_line )
10054           = $self->set_adjusted_indentation( $ibeg, $iend, $rfields, $rpatterns,
10055             $ri_first, $ri_last, $rindentation_list, $ljump );
10056
10057         # we will allow outdenting of long lines..
10058         my $outdent_long_lines = (
10059
10060             # which are long quotes, if allowed
10061             ( $type_beg eq 'Q' && $rOpts->{'outdent-long-quotes'} )
10062
10063             # which are long block comments, if allowed
10064               || (
10065                    $type_beg eq '#'
10066                 && $rOpts->{'outdent-long-comments'}
10067
10068                 # but not if this is a static block comment
10069                 && !$is_static_block_comment
10070               )
10071         );
10072
10073         my $rvertical_tightness_flags =
10074           $self->set_vertical_tightness_flags( $n, $n_last_line, $ibeg, $iend,
10075             $ri_first, $ri_last );
10076
10077         # flush an outdented line to avoid any unwanted vertical alignment
10078         Perl::Tidy::VerticalAligner::flush() if ($is_outdented_line);
10079
10080         # Set a flag at the final ':' of a ternary chain to request
10081         # vertical alignment of the final term.  Here is a
10082         # slightly complex example:
10083         #
10084         # $self->{_text} = (
10085         #    !$section        ? ''
10086         #   : $type eq 'item' ? "the $section entry"
10087         #   :                   "the section on $section"
10088         # )
10089         # . (
10090         #   $page
10091         #   ? ( $section ? ' in ' : '' ) . "the $page$page_ext manpage"
10092         #   : ' elsewhere in this document'
10093         # );
10094         #
10095         my $is_terminal_ternary = 0;
10096
10097         if ( $type_beg eq ':' || $n > 0 && $type_end_last eq ':' ) {
10098             my $last_leading_type = $n > 0 ? $type_beg_last : ':';
10099             if (   $terminal_type ne ';'
10100                 && $n_last_line > $n
10101                 && $level_end == $lev )
10102             {
10103                 $level_end     = $rLL->[$Kbeg_next]->[_LEVEL_];
10104                 $terminal_type = $rLL->[$Kbeg_next]->[_TYPE_];
10105             }
10106             if (
10107                 $last_leading_type eq ':'
10108                 && (   ( $terminal_type eq ';' && $level_end <= $lev )
10109                     || ( $terminal_type ne ':' && $level_end < $lev ) )
10110               )
10111             {
10112
10113                 # the terminal term must not contain any ternary terms, as in
10114                 # my $ECHO = (
10115                 #       $Is_MSWin32 ? ".\\echo$$"
10116                 #     : $Is_MacOS   ? ":echo$$"
10117                 #     : ( $Is_NetWare ? "echo$$" : "./echo$$" )
10118                 # );
10119                 $is_terminal_ternary = 1;
10120
10121                 my $KP = $rLL->[$Kbeg]->[_KNEXT_SEQ_ITEM_];
10122                 while ( defined($KP) && $KP <= $Kend ) {
10123                     my $type_KP = $rLL->[$KP]->[_TYPE_];
10124                     if ( $type_KP eq '?' || $type_KP eq ':' ) {
10125                         $is_terminal_ternary = 0;
10126                         last;
10127                     }
10128                     $KP = $rLL->[$KP]->[_KNEXT_SEQ_ITEM_];
10129                 }
10130             }
10131         }
10132
10133         # add any new closing side comment to the last line
10134         if ( $closing_side_comment && $n == $n_last_line && @{$rfields} ) {
10135             $rfields->[-1] .= " $closing_side_comment";
10136         }
10137
10138         # send this new line down the pipe
10139         my $rvalign_hash = {};
10140         $rvalign_hash->{level}           = $lev;
10141         $rvalign_hash->{level_end}       = $level_end;
10142         $rvalign_hash->{indentation}     = $indentation;
10143         $rvalign_hash->{is_forced_break} = $forced_breakpoint || $in_comma_list;
10144         $rvalign_hash->{outdent_long_lines}        = $outdent_long_lines;
10145         $rvalign_hash->{is_terminal_ternary}       = $is_terminal_ternary;
10146         $rvalign_hash->{is_terminal_statement}     = $is_semicolon_terminated;
10147         $rvalign_hash->{do_not_pad}                = $do_not_pad;
10148         $rvalign_hash->{rvertical_tightness_flags} = $rvertical_tightness_flags;
10149         $rvalign_hash->{level_jump}                = $level_jump;
10150
10151         $rvalign_hash->{valign_batch_number} = $valign_batch_number;
10152
10153         Perl::Tidy::VerticalAligner::valign_input( $rvalign_hash, $rfields,
10154             $rtokens, $rpatterns );
10155
10156         $in_comma_list = $type_end eq ',' && $forced_breakpoint;
10157
10158         # flush an outdented line to avoid any unwanted vertical alignment
10159         Perl::Tidy::VerticalAligner::flush() if ($is_outdented_line);
10160
10161         $do_not_pad = 0;
10162
10163         # Set flag indicating if this line ends in an opening
10164         # token and is very short, so that a blank line is not
10165         # needed if the subsequent line is a comment.
10166         # Examples of what we are looking for:
10167         #   {
10168         #   && (
10169         #   BEGIN {
10170         #   default {
10171         #   sub {
10172         $last_output_short_opening_token
10173
10174           # line ends in opening token
10175           = $type_end =~ /^[\{\(\[L]$/
10176
10177           # and either
10178           && (
10179             # line has either single opening token
10180             $Kend == $Kbeg
10181
10182             # or is a single token followed by opening token.
10183             # Note that sub identifiers have blanks like 'sub doit'
10184             || ( $Kend - $Kbeg <= 2 && $token_beg !~ /\s+/ )
10185           )
10186
10187           # and limit total to 10 character widths
10188           && token_sequence_length( $ibeg, $iend ) <= 10;
10189
10190     }    # end of loop to output each line
10191
10192     # remember indentation of lines containing opening containers for
10193     # later use by sub set_adjusted_indentation
10194     $self->save_opening_indentation( $ri_first, $ri_last, $rindentation_list );
10195
10196     # output any new -cscw block comment
10197     if ($cscw_block_comment) {
10198         Perl::Tidy::VerticalAligner::flush();
10199         $file_writer_object->write_code_line( $cscw_block_comment . "\n" );
10200     }
10201     return;
10202 }
10203
10204 {    # begin make_alignment_patterns
10205
10206     my %block_type_map;
10207     my %keyword_map;
10208     my %operator_map;
10209
10210     BEGIN {
10211
10212         # map related block names into a common name to
10213         # allow alignment
10214         %block_type_map = (
10215             'unless'  => 'if',
10216             'else'    => 'if',
10217             'elsif'   => 'if',
10218             'when'    => 'if',
10219             'default' => 'if',
10220             'case'    => 'if',
10221             'sort'    => 'map',
10222             'grep'    => 'map',
10223         );
10224
10225         # map certain keywords to the same 'if' class to align
10226         # long if/elsif sequences. [elsif.pl]
10227         %keyword_map = (
10228             'unless'  => 'if',
10229             'else'    => 'if',
10230             'elsif'   => 'if',
10231             'when'    => 'given',
10232             'default' => 'given',
10233             'case'    => 'switch',
10234
10235             # treat an 'undef' similar to numbers and quotes
10236             'undef' => 'Q',
10237         );
10238
10239         # map certain operators to the same class for pattern matching
10240         %operator_map = (
10241             '!~' => '=~',
10242             '+=' => '+=',
10243             '-=' => '+=',
10244             '*=' => '+=',
10245             '/=' => '+=',
10246         );
10247     }
10248
10249     sub delete_needless_alignments {
10250         my ( $self, $ibeg, $iend, $ralignment_type_to_go ) = @_;
10251
10252         # Remove unwanted alignments.  This routine is a place to remove
10253         # alignments which might cause problems at later stages.  There are
10254         # currently two types of fixes:
10255
10256         # 1. Remove excess parens
10257         # 2. Remove alignments within 'elsif' conditions
10258
10259         # Patch #1: Excess alignment of parens can prevent other good
10260         # alignments.  For example, note the parens in the first two rows of
10261         # the following snippet.  They would normally get marked for alignment
10262         # and aligned as follows:
10263
10264         #    my $w = $columns * $cell_w + ( $columns + 1 ) * $border;
10265         #    my $h = $rows * $cell_h +    ( $rows + 1 ) * $border;
10266         #    my $img = new Gimp::Image( $w, $h, RGB );
10267
10268         # This causes unnecessary paren alignment and prevents the third equals
10269         # from aligning. If we remove the unwanted alignments we get:
10270
10271         #    my $w   = $columns * $cell_w + ( $columns + 1 ) * $border;
10272         #    my $h   = $rows * $cell_h + ( $rows + 1 ) * $border;
10273         #    my $img = new Gimp::Image( $w, $h, RGB );
10274
10275         # A rule for doing this which works well is to remove alignment of
10276         # parens whose containers do not contain other aligning tokens, with
10277         # the exception that we always keep alignment of the first opening
10278         # paren on a line (for things like 'if' and 'elsif' statements).
10279
10280         # Setup needed constants
10281         my $i_good_paren  = -1;
10282         my $imin_match    = $iend + 1;
10283         my $i_elsif_close = $ibeg - 1;
10284         my $i_elsif_open  = $iend + 1;
10285         if ( $iend > $ibeg ) {
10286             if ( $types_to_go[$ibeg] eq 'k' ) {
10287
10288                 # Paren patch: mark a location of a paren we should keep, such
10289                 # as one following something like a leading 'if', 'elsif',..
10290                 $i_good_paren = $ibeg + 1;
10291                 if ( $types_to_go[$i_good_paren] eq 'b' ) {
10292                     $i_good_paren++;
10293                 }
10294
10295                 # 'elsif' patch: remember the range of the parens of an elsif,
10296                 # and do not make alignments within them because this can cause
10297                 # loss of padding and overall brace alignment in the vertical
10298                 # aligner.
10299                 if (   $tokens_to_go[$ibeg] eq 'elsif'
10300                     && $i_good_paren < $iend
10301                     && $tokens_to_go[$i_good_paren] eq '(' )
10302                 {
10303                     $i_elsif_open  = $i_good_paren;
10304                     $i_elsif_close = $self->mate_index_to_go($i_good_paren);
10305                 }
10306             }
10307         }
10308
10309         # Loop to make the fixes on this line
10310         my @imatch_list;
10311         for my $i ( $ibeg .. $iend ) {
10312
10313             if ( $ralignment_type_to_go->[$i] ne '' ) {
10314
10315                 # Patch #2: undo alignment within elsif parens
10316                 if ( $i > $i_elsif_open && $i < $i_elsif_close ) {
10317                     $ralignment_type_to_go->[$i] = '';
10318                     next;
10319                 }
10320                 push @imatch_list, $i;
10321
10322             }
10323             if ( $tokens_to_go[$i] eq ')' ) {
10324
10325                 # Patch #1: undo the corresponding opening paren if:
10326                 # - it is at the top of the stack
10327                 # - and not the first overall opening paren
10328                 # - does not follow a leading keyword on this line
10329                 my $imate = $self->mate_index_to_go($i);
10330                 if (   @imatch_list
10331                     && $imatch_list[-1] eq $imate
10332                     && ( $ibeg > 1 || @imatch_list > 1 )
10333                     && $imate > $i_good_paren )
10334                 {
10335                     $ralignment_type_to_go->[$imate] = '';
10336                     pop @imatch_list;
10337                 }
10338             }
10339         }
10340         return;
10341     }
10342
10343     sub make_alignment_patterns {
10344
10345         # Here we do some important preliminary work for the
10346         # vertical aligner.  We create three arrays for one
10347         # output line. These arrays contain strings that can
10348         # be tested by the vertical aligner to see if
10349         # consecutive lines can be aligned vertically.
10350         #
10351         # The three arrays are indexed on the vertical
10352         # alignment fields and are:
10353         # @tokens - a list of any vertical alignment tokens for this line.
10354         #   These are tokens, such as '=' '&&' '#' etc which
10355         #   we want to might align vertically.  These are
10356         #   decorated with various information such as
10357         #   nesting depth to prevent unwanted vertical
10358         #   alignment matches.
10359         # @fields - the actual text of the line between the vertical alignment
10360         #   tokens.
10361         # @patterns - a modified list of token types, one for each alignment
10362         #   field.  These should normally each match before alignment is
10363         #   allowed, even when the alignment tokens match.
10364         my ( $self, $ibeg, $iend, $ralignment_type_to_go ) = @_;
10365         my @tokens   = ();
10366         my @fields   = ();
10367         my @patterns = ();
10368         my $i_start  = $ibeg;
10369
10370         my $depth                 = 0;
10371         my @container_name        = ("");
10372         my @multiple_comma_arrows = (undef);
10373
10374         my $j = 0;    # field index
10375
10376         $patterns[0] = "";
10377         my %token_count;
10378         for my $i ( $ibeg .. $iend ) {
10379
10380             # Keep track of containers balanced on this line only.
10381             # These are used below to prevent unwanted cross-line alignments.
10382             # Unbalanced containers already avoid aligning across
10383             # container boundaries.
10384             my $tok = $tokens_to_go[$i];
10385             if ( $tok =~ /^[\(\{\[]/ ) {    #'(' ) {
10386
10387                 # if container is balanced on this line...
10388                 my $i_mate = $self->mate_index_to_go($i);
10389                 if ( $i_mate > $i && $i_mate <= $iend ) {
10390                     $depth++;
10391                     my $seqno = $type_sequence_to_go[$i];
10392                     my $count = comma_arrow_count($seqno);
10393                     $multiple_comma_arrows[$depth] = $count && $count > 1;
10394
10395                     # Append the previous token name to make the container name
10396                     # more unique.  This name will also be given to any commas
10397                     # within this container, and it helps avoid undesirable
10398                     # alignments of different types of containers.
10399
10400                  # Containers beginning with { and [ are given those names
10401                  # for uniqueness. That way commas in different containers
10402                  # will not match. Here is an example of what this prevents:
10403                  #      a => [ 1,       2, 3 ],
10404                  #   b => { b1 => 4, b2 => 5 },
10405                  # Here is another example of what we avoid by labeling the
10406                  # commas properly:
10407                  #   is_d( [ $a,        $a ], [ $b,               $c ] );
10408                  #   is_d( { foo => $a, bar => $a }, { foo => $b, bar => $c } );
10409                  #   is_d( [ \$a,       \$a ], [ \$b,             \$c ] );
10410
10411                     my $name = $tok;
10412                     if ( $tok eq '(' ) {
10413                         $name = previous_nonblank_token($i);
10414                         $name =~ s/^->//;
10415                     }
10416                     $container_name[$depth] = "+" . $name;
10417
10418                     # Make the container name even more unique if necessary.
10419                     # If we are not vertically aligning this opening paren,
10420                     # append a character count to avoid bad alignment because
10421                     # it usually looks bad to align commas within containers
10422                     # for which the opening parens do not align.  Here
10423                     # is an example very BAD alignment of commas (because
10424                     # the atan2 functions are not all aligned):
10425                     #    $XY =
10426                     #      $X * $RTYSQP1 * atan2( $X, $RTYSQP1 ) +
10427                     #      $Y * $RTXSQP1 * atan2( $Y, $RTXSQP1 ) -
10428                     #      $X * atan2( $X,            1 ) -
10429                     #      $Y * atan2( $Y,            1 );
10430                     #
10431                     # On the other hand, it is usually okay to align commas if
10432                     # opening parens align, such as:
10433                     #    glVertex3d( $cx + $s * $xs, $cy,            $z );
10434                     #    glVertex3d( $cx,            $cy + $s * $ys, $z );
10435                     #    glVertex3d( $cx - $s * $xs, $cy,            $z );
10436                     #    glVertex3d( $cx,            $cy - $s * $ys, $z );
10437                     #
10438                     # To distinguish between these situations, we will
10439                     # append the length of the line from the previous matching
10440                     # token, or beginning of line, to the function name.  This
10441                     # will allow the vertical aligner to reject undesirable
10442                     # matches.
10443
10444                     # if we are not aligning on this paren...
10445                     if ( $ralignment_type_to_go->[$i] eq '' ) {
10446
10447                         # Sum length from previous alignment
10448                         my $len = token_sequence_length( $i_start, $i - 1 );
10449                         if ( $i_start == $ibeg ) {
10450
10451                             # For first token, use distance from start of line
10452                             # but subtract off the indentation due to level.
10453                             # Otherwise, results could vary with indentation.
10454                             $len += leading_spaces_to_go($ibeg) -
10455                               $levels_to_go[$i_start] * $rOpts_indent_columns;
10456                             if ( $len < 0 ) { $len = 0 }
10457                         }
10458
10459                         # tack this length onto the container name to try
10460                         # to make a unique token name
10461                         $container_name[$depth] .= "-" . $len;
10462                     }
10463                 }
10464             }
10465             elsif ( $tokens_to_go[$i] =~ /^[\)\}\]]/ ) {
10466                 $depth-- if $depth > 0;
10467             }
10468
10469             # if we find a new synchronization token, we are done with
10470             # a field
10471             if ( $i > $i_start && $ralignment_type_to_go->[$i] ne '' ) {
10472
10473                 my $tok = my $raw_tok = $ralignment_type_to_go->[$i];
10474
10475                 # map similar items
10476                 my $tok_map = $operator_map{$tok};
10477                 $tok = $tok_map if ($tok_map);
10478
10479                 # make separators in different nesting depths unique
10480                 # by appending the nesting depth digit.
10481                 if ( $raw_tok ne '#' ) {
10482                     $tok .= "$nesting_depth_to_go[$i]";
10483                 }
10484
10485                 # also decorate commas with any container name to avoid
10486                 # unwanted cross-line alignments.
10487                 if ( $raw_tok eq ',' || $raw_tok eq '=>' ) {
10488                     if ( $container_name[$depth] ) {
10489                         $tok .= $container_name[$depth];
10490                     }
10491                 }
10492
10493                 # Patch to avoid aligning leading and trailing if, unless.
10494                 # Mark trailing if, unless statements with container names.
10495                 # This makes them different from leading if, unless which
10496                 # are not so marked at present.  If we ever need to name
10497                 # them too, we could use ci to distinguish them.
10498                 # Example problem to avoid:
10499                 #    return ( 2, "DBERROR" )
10500                 #      if ( $retval == 2 );
10501                 #    if   ( scalar @_ ) {
10502                 #        my ( $a, $b, $c, $d, $e, $f ) = @_;
10503                 #    }
10504                 if ( $raw_tok eq '(' ) {
10505                     my $ci = $ci_levels_to_go[$ibeg];
10506                     if (   $container_name[$depth] =~ /^\+(if|unless)/
10507                         && $ci )
10508                     {
10509                         $tok .= $container_name[$depth];
10510                     }
10511                 }
10512
10513                 # Decorate block braces with block types to avoid
10514                 # unwanted alignments such as the following:
10515                 # foreach ( @{$routput_array} ) { $fh->print($_) }
10516                 # eval                          { $fh->close() };
10517                 if ( $raw_tok eq '{' && $block_type_to_go[$i] ) {
10518                     my $block_type = $block_type_to_go[$i];
10519
10520                     # map certain related block types to allow
10521                     # else blocks to align
10522                     $block_type = $block_type_map{$block_type}
10523                       if ( defined( $block_type_map{$block_type} ) );
10524
10525                     # remove sub names to allow one-line sub braces to align
10526                     # regardless of name
10527                     #if ( $block_type =~ /^sub / ) { $block_type = 'sub' }
10528                     if ( $block_type =~ /$SUB_PATTERN/ ) { $block_type = 'sub' }
10529
10530                     # allow all control-type blocks to align
10531                     if ( $block_type =~ /^[A-Z]+$/ ) { $block_type = 'BEGIN' }
10532
10533                     $tok .= $block_type;
10534                 }
10535
10536                 # Mark multiple copies of certain tokens with the copy number
10537                 # This will allow the aligner to decide if they are matched.
10538                 # For now, only do this for equals. For example, the two
10539                 # equals on the next line will be labeled '=0' and '=0.2'.
10540                 # Later, the '=0.2' will be ignored in alignment because it
10541                 # has no match.
10542
10543                 # $|          = $debug = 1 if $opt_d;
10544                 # $full_index = 1          if $opt_i;
10545
10546                 if ( $raw_tok eq '=' || $raw_tok eq '=>' ) {
10547                     $token_count{$tok}++;
10548                     if ( $token_count{$tok} > 1 ) {
10549                         $tok .= '.' . $token_count{$tok};
10550                     }
10551                 }
10552
10553                 # concatenate the text of the consecutive tokens to form
10554                 # the field
10555                 push( @fields,
10556                     join( '', @tokens_to_go[ $i_start .. $i - 1 ] ) );
10557
10558                 # store the alignment token for this field
10559                 push( @tokens, $tok );
10560
10561                 # get ready for the next batch
10562                 $i_start = $i;
10563                 $j++;
10564                 $patterns[$j] = "";
10565             }
10566
10567             # continue accumulating tokens
10568             # handle non-keywords..
10569             if ( $types_to_go[$i] ne 'k' ) {
10570                 my $type = $types_to_go[$i];
10571
10572                 # Mark most things before arrows as a quote to
10573                 # get them to line up. Testfile: mixed.pl.
10574                 if ( ( $i < $iend - 1 ) && ( $type =~ /^[wnC]$/ ) ) {
10575                     my $next_type = $types_to_go[ $i + 1 ];
10576                     my $i_next_nonblank =
10577                       ( ( $next_type eq 'b' ) ? $i + 2 : $i + 1 );
10578
10579                     if ( $types_to_go[$i_next_nonblank] eq '=>' ) {
10580                         $type = 'Q';
10581
10582                         # Patch to ignore leading minus before words,
10583                         # by changing pattern 'mQ' into just 'Q',
10584                         # so that we can align things like this:
10585                         #  Button   => "Print letter \"~$_\"",
10586                         #  -command => [ sub { print "$_[0]\n" }, $_ ],
10587                         if ( $patterns[$j] eq 'm' ) { $patterns[$j] = "" }
10588                     }
10589                 }
10590
10591          # Convert a bareword within braces into a quote for matching. This will
10592          # allow alignment of expressions like this:
10593          #    local ( $SIG{'INT'} ) = IGNORE;
10594          #    local ( $SIG{ALRM} )  = 'POSTMAN';
10595                 if (   $type eq 'w'
10596                     && $i > $ibeg
10597                     && $i < $iend
10598                     && $types_to_go[ $i - 1 ] eq 'L'
10599                     && $types_to_go[ $i + 1 ] eq 'R' )
10600                 {
10601                     $type = 'Q';
10602                 }
10603
10604                 # patch to make numbers and quotes align
10605                 if ( $type eq 'n' ) { $type = 'Q' }
10606
10607                 # patch to ignore any ! in patterns
10608                 if ( $type eq '!' ) { $type = '' }
10609
10610                 $patterns[$j] .= $type;
10611             }
10612
10613             # for keywords we have to use the actual text
10614             else {
10615
10616                 my $tok = $tokens_to_go[$i];
10617
10618                 # but map certain keywords to a common string to allow
10619                 # alignment.
10620                 $tok = $keyword_map{$tok}
10621                   if ( defined( $keyword_map{$tok} ) );
10622                 $patterns[$j] .= $tok;
10623             }
10624         }
10625
10626         # done with this line .. join text of tokens to make the last field
10627         push( @fields, join( '', @tokens_to_go[ $i_start .. $iend ] ) );
10628         return ( \@tokens, \@fields, \@patterns );
10629     }
10630
10631 }    # end make_alignment_patterns
10632
10633 {    # begin unmatched_indexes
10634
10635     # closure to keep track of unbalanced containers.
10636     # arrays shared by the routines in this block:
10637     my @unmatched_opening_indexes_in_this_batch;
10638     my @unmatched_closing_indexes_in_this_batch;
10639     my %comma_arrow_count;
10640
10641     sub is_unbalanced_batch {
10642         return @unmatched_opening_indexes_in_this_batch +
10643           @unmatched_closing_indexes_in_this_batch;
10644     }
10645
10646     sub comma_arrow_count {
10647         my $seqno = shift;
10648         return $comma_arrow_count{$seqno};
10649     }
10650
10651     sub match_opening_and_closing_tokens {
10652
10653         # Match up indexes of opening and closing braces, etc, in this batch.
10654         # This has to be done after all tokens are stored because unstoring
10655         # of tokens would otherwise cause trouble.
10656
10657         @unmatched_opening_indexes_in_this_batch = ();
10658         @unmatched_closing_indexes_in_this_batch = ();
10659         %comma_arrow_count                       = ();
10660         my $comma_arrow_count_contained = 0;
10661
10662         foreach my $i ( 0 .. $max_index_to_go ) {
10663             if ( $type_sequence_to_go[$i] ) {
10664                 my $token = $tokens_to_go[$i];
10665                 if ( $token =~ /^[\(\[\{\?]$/ ) {
10666                     push @unmatched_opening_indexes_in_this_batch, $i;
10667                 }
10668                 elsif ( $token =~ /^[\)\]\}\:]$/ ) {
10669
10670                     my $i_mate = pop @unmatched_opening_indexes_in_this_batch;
10671                     if ( defined($i_mate) && $i_mate >= 0 ) {
10672                         if ( $type_sequence_to_go[$i_mate] ==
10673                             $type_sequence_to_go[$i] )
10674                         {
10675                             $mate_index_to_go[$i]      = $i_mate;
10676                             $mate_index_to_go[$i_mate] = $i;
10677                             my $seqno = $type_sequence_to_go[$i];
10678                             if ( $comma_arrow_count{$seqno} ) {
10679                                 $comma_arrow_count_contained +=
10680                                   $comma_arrow_count{$seqno};
10681                             }
10682                         }
10683                         else {
10684                             push @unmatched_opening_indexes_in_this_batch,
10685                               $i_mate;
10686                             push @unmatched_closing_indexes_in_this_batch, $i;
10687                         }
10688                     }
10689                     else {
10690                         push @unmatched_closing_indexes_in_this_batch, $i;
10691                     }
10692                 }
10693             }
10694             elsif ( $tokens_to_go[$i] eq '=>' ) {
10695                 if (@unmatched_opening_indexes_in_this_batch) {
10696                     my $j     = $unmatched_opening_indexes_in_this_batch[-1];
10697                     my $seqno = $type_sequence_to_go[$j];
10698                     $comma_arrow_count{$seqno}++;
10699                 }
10700             }
10701         }
10702         return $comma_arrow_count_contained;
10703     }
10704
10705     sub save_opening_indentation {
10706
10707         # This should be called after each batch of tokens is output. It
10708         # saves indentations of lines of all unmatched opening tokens.
10709         # These will be used by sub get_opening_indentation.
10710
10711         my ( $self, $ri_first, $ri_last, $rindentation_list ) = @_;
10712
10713         # we no longer need indentations of any saved indentations which
10714         # are unmatched closing tokens in this batch, because we will
10715         # never encounter them again.  So we can delete them to keep
10716         # the hash size down.
10717         foreach (@unmatched_closing_indexes_in_this_batch) {
10718             my $seqno = $type_sequence_to_go[$_];
10719             delete $saved_opening_indentation{$seqno};
10720         }
10721
10722         # we need to save indentations of any unmatched opening tokens
10723         # in this batch because we may need them in a subsequent batch.
10724         foreach (@unmatched_opening_indexes_in_this_batch) {
10725             my $seqno = $type_sequence_to_go[$_];
10726             $saved_opening_indentation{$seqno} = [
10727                 lookup_opening_indentation(
10728                     $_, $ri_first, $ri_last, $rindentation_list
10729                 )
10730             ];
10731         }
10732         return;
10733     }
10734 }    # end unmatched_indexes
10735
10736 sub get_opening_indentation {
10737
10738     # get the indentation of the line which output the opening token
10739     # corresponding to a given closing token in the current output batch.
10740     #
10741     # given:
10742     # $i_closing - index in this line of a closing token ')' '}' or ']'
10743     #
10744     # $ri_first - reference to list of the first index $i for each output
10745     #               line in this batch
10746     # $ri_last - reference to list of the last index $i for each output line
10747     #              in this batch
10748     # $rindentation_list - reference to a list containing the indentation
10749     #            used for each line.
10750     #
10751     # return:
10752     #   -the indentation of the line which contained the opening token
10753     #    which matches the token at index $i_opening
10754     #   -and its offset (number of columns) from the start of the line
10755     #
10756     my ( $self, $i_closing, $ri_first, $ri_last, $rindentation_list ) = @_;
10757
10758     # first, see if the opening token is in the current batch
10759     my $i_opening = $mate_index_to_go[$i_closing];
10760     my ( $indent, $offset, $is_leading, $exists );
10761     $exists = 1;
10762     if ( $i_opening >= 0 ) {
10763
10764         # it is..look up the indentation
10765         ( $indent, $offset, $is_leading ) =
10766           lookup_opening_indentation( $i_opening, $ri_first, $ri_last,
10767             $rindentation_list );
10768     }
10769
10770     # if not, it should have been stored in the hash by a previous batch
10771     else {
10772         my $seqno = $type_sequence_to_go[$i_closing];
10773         if ($seqno) {
10774             if ( $saved_opening_indentation{$seqno} ) {
10775                 ( $indent, $offset, $is_leading ) =
10776                   @{ $saved_opening_indentation{$seqno} };
10777             }
10778
10779             # some kind of serious error
10780             # (example is badfile.t)
10781             else {
10782                 $indent     = 0;
10783                 $offset     = 0;
10784                 $is_leading = 0;
10785                 $exists     = 0;
10786             }
10787         }
10788
10789         # if no sequence number it must be an unbalanced container
10790         else {
10791             $indent     = 0;
10792             $offset     = 0;
10793             $is_leading = 0;
10794             $exists     = 0;
10795         }
10796     }
10797     return ( $indent, $offset, $is_leading, $exists );
10798 }
10799
10800 sub lookup_opening_indentation {
10801
10802     # get the indentation of the line in the current output batch
10803     # which output a selected opening token
10804     #
10805     # given:
10806     #   $i_opening - index of an opening token in the current output batch
10807     #                whose line indentation we need
10808     #   $ri_first - reference to list of the first index $i for each output
10809     #               line in this batch
10810     #   $ri_last - reference to list of the last index $i for each output line
10811     #              in this batch
10812     #   $rindentation_list - reference to a list containing the indentation
10813     #            used for each line.  (NOTE: the first slot in
10814     #            this list is the last returned line number, and this is
10815     #            followed by the list of indentations).
10816     #
10817     # return
10818     #   -the indentation of the line which contained token $i_opening
10819     #   -and its offset (number of columns) from the start of the line
10820
10821     my ( $i_opening, $ri_start, $ri_last, $rindentation_list ) = @_;
10822
10823     if ( !@{$ri_last} ) {
10824         warning("Error in opening_indentation: no lines");
10825         return;
10826     }
10827
10828     my $nline = $rindentation_list->[0];    # line number of previous lookup
10829
10830     # reset line location if necessary
10831     $nline = 0 if ( $i_opening < $ri_start->[$nline] );
10832
10833     # find the correct line
10834     unless ( $i_opening > $ri_last->[-1] ) {
10835         while ( $i_opening > $ri_last->[$nline] ) { $nline++; }
10836     }
10837
10838     # error - token index is out of bounds - shouldn't happen
10839     else {
10840         warning(
10841 "non-fatal program bug in lookup_opening_indentation - index out of range\n"
10842         );
10843         report_definite_bug();
10844         $nline = $#{$ri_last};
10845     }
10846
10847     $rindentation_list->[0] =
10848       $nline;    # save line number to start looking next call
10849     my $ibeg       = $ri_start->[$nline];
10850     my $offset     = token_sequence_length( $ibeg, $i_opening ) - 1;
10851     my $is_leading = ( $ibeg == $i_opening );
10852     return ( $rindentation_list->[ $nline + 1 ], $offset, $is_leading );
10853 }
10854
10855 {
10856     my %is_if_elsif_else_unless_while_until_for_foreach;
10857
10858     BEGIN {
10859
10860         # These block types may have text between the keyword and opening
10861         # curly.  Note: 'else' does not, but must be included to allow trailing
10862         # if/elsif text to be appended.
10863         # patch for SWITCH/CASE: added 'case' and 'when'
10864         my @q = qw(if elsif else unless while until for foreach case when);
10865         @is_if_elsif_else_unless_while_until_for_foreach{@q} =
10866           (1) x scalar(@q);
10867     }
10868
10869     sub set_adjusted_indentation {
10870
10871         # This routine has the final say regarding the actual indentation of
10872         # a line.  It starts with the basic indentation which has been
10873         # defined for the leading token, and then takes into account any
10874         # options that the user has set regarding special indenting and
10875         # outdenting.
10876
10877         my (
10878             $self,    $ibeg,              $iend,
10879             $rfields, $rpatterns,         $ri_first,
10880             $ri_last, $rindentation_list, $level_jump
10881         ) = @_;
10882
10883         my $rLL = $self->{rLL};
10884
10885         # we need to know the last token of this line
10886         my ( $terminal_type, $i_terminal ) =
10887           $self->terminal_type_i( $ibeg, $iend );
10888
10889         my $is_outdented_line = 0;
10890
10891         my $is_semicolon_terminated = $terminal_type eq ';'
10892           && $nesting_depth_to_go[$iend] < $nesting_depth_to_go[$ibeg];
10893
10894         # NOTE: A future improvement would be to make it semicolon terminated
10895         # even if it does not have a semicolon but is followed by a closing
10896         # block brace. This would undo ci even for something like the
10897         # following, in which the final paren does not have a semicolon because
10898         # it is a possible weld location:
10899
10900         # if ($BOLD_MATH) {
10901         #     (
10902         #         $labels, $comment,
10903         #         join( '', '<B>', &make_math( $mode, '', '', $_ ), '</B>' )
10904         #     )
10905         # }
10906         #
10907
10908         # MOJO: Set a flag if this lines begins with ')->'
10909         my $leading_paren_arrow = (
10910                  $types_to_go[$ibeg] eq '}'
10911               && $tokens_to_go[$ibeg] eq ')'
10912               && (
10913                 ( $ibeg < $i_terminal && $types_to_go[ $ibeg + 1 ] eq '->' )
10914                 || (   $ibeg < $i_terminal - 1
10915                     && $types_to_go[ $ibeg + 1 ] eq 'b'
10916                     && $types_to_go[ $ibeg + 2 ] eq '->' )
10917               )
10918         );
10919
10920         ##########################################################
10921         # Section 1: set a flag and a default indentation
10922         #
10923         # Most lines are indented according to the initial token.
10924         # But it is common to outdent to the level just after the
10925         # terminal token in certain cases...
10926         # adjust_indentation flag:
10927         #       0 - do not adjust
10928         #       1 - outdent
10929         #       2 - vertically align with opening token
10930         #       3 - indent
10931         ##########################################################
10932         my $adjust_indentation         = 0;
10933         my $default_adjust_indentation = $adjust_indentation;
10934
10935         my (
10936             $opening_indentation, $opening_offset,
10937             $is_leading,          $opening_exists
10938         );
10939
10940         my $type_beg      = $types_to_go[$ibeg];
10941         my $token_beg     = $tokens_to_go[$ibeg];
10942         my $K_beg         = $K_to_go[$ibeg];
10943         my $ibeg_weld_fix = $ibeg;
10944
10945         # QW PATCH 2 (Testing)
10946         # At an isolated closing token of a qw quote which is welded to
10947         # a following closing token, we will locally change its type to
10948         # be the same as its token. This will allow formatting to be the
10949         # same as for an ordinary closing token.
10950
10951         # For -lp formatting se use $ibeg_weld_fix to get around the problem
10952         # that with -lp type formatting the opening and closing tokens to not
10953         # have sequence numbers.
10954         if ( $type_beg eq 'q' && $token_beg =~ /^[\)\}\]\>]/ ) {
10955             my $K_next_nonblank = $self->K_next_code($K_beg);
10956             if ( defined($K_next_nonblank) ) {
10957                 my $type_sequence = $rLL->[$K_next_nonblank]->[_TYPE_SEQUENCE_];
10958                 my $token         = $rLL->[$K_next_nonblank]->[_TOKEN_];
10959                 my $welded        = weld_len_left( $type_sequence, $token );
10960                 if ($welded) {
10961                     $ibeg_weld_fix = $ibeg + ( $K_next_nonblank - $K_beg );
10962                     $type_beg = ')';    ##$token_beg;
10963                 }
10964             }
10965         }
10966
10967         # if we are at a closing token of some type..
10968         if ( $type_beg =~ /^[\)\}\]R]$/ ) {
10969
10970             # get the indentation of the line containing the corresponding
10971             # opening token
10972             (
10973                 $opening_indentation, $opening_offset,
10974                 $is_leading,          $opening_exists
10975               )
10976               = $self->get_opening_indentation( $ibeg_weld_fix, $ri_first,
10977                 $ri_last, $rindentation_list );
10978
10979             # First set the default behavior:
10980             if (
10981
10982                 # default behavior is to outdent closing lines
10983                 # of the form:   ");  };  ];  )->xxx;"
10984                 $is_semicolon_terminated
10985
10986                 # and 'cuddled parens' of the form:   ")->pack("
10987                 # Bug fix for RT #123749]: the types here were
10988                 # incorrectly '(' and ')'.  Corrected to be '{' and '}'
10989                 || (
10990                        $terminal_type eq '{'
10991                     && $type_beg eq '}'
10992                     && ( $nesting_depth_to_go[$iend] + 1 ==
10993                         $nesting_depth_to_go[$ibeg] )
10994                 )
10995
10996                 # remove continuation indentation for any line like
10997                 #       } ... {
10998                 # or without ending '{' and unbalanced, such as
10999                 #       such as '}->{$operator}'
11000                 || (
11001                     $type_beg eq '}'
11002
11003                     && (   $types_to_go[$iend] eq '{'
11004                         || $levels_to_go[$iend] < $levels_to_go[$ibeg] )
11005                 )
11006
11007                 # and when the next line is at a lower indentation level
11008                 # PATCH: and only if the style allows undoing continuation
11009                 # for all closing token types. We should really wait until
11010                 # the indentation of the next line is known and then make
11011                 # a decision, but that would require another pass.
11012                 || ( $level_jump < 0 && !$some_closing_token_indentation )
11013
11014                 # Patch for -wn=2, multiple welded closing tokens
11015                 || (   $i_terminal > $ibeg
11016                     && $types_to_go[$iend] =~ /^[\)\}\]R]$/ )
11017
11018               )
11019             {
11020                 $adjust_indentation = 1;
11021             }
11022
11023             # outdent something like '),'
11024             if (
11025                 $terminal_type eq ','
11026
11027                 # Removed this constraint for -wn
11028                 # OLD: allow just one character before the comma
11029                 # && $i_terminal == $ibeg + 1
11030
11031                 # require LIST environment; otherwise, we may outdent too much -
11032                 # this can happen in calls without parentheses (overload.t);
11033                 && $container_environment_to_go[$i_terminal] eq 'LIST'
11034               )
11035             {
11036                 $adjust_indentation = 1;
11037             }
11038
11039             # undo continuation indentation of a terminal closing token if
11040             # it is the last token before a level decrease.  This will allow
11041             # a closing token to line up with its opening counterpart, and
11042             # avoids an indentation jump larger than 1 level.
11043             if (   $types_to_go[$i_terminal] =~ /^[\}\]\)R]$/
11044                 && $i_terminal == $ibeg
11045                 && defined($K_beg) )
11046             {
11047                 my $K_next_nonblank = $self->K_next_code($K_beg);
11048
11049                 # Patch for RT#131115: honor -bli flag at closing brace
11050                 my $is_bli =
11051                      $rOpts_brace_left_and_indent
11052                   && $block_type_to_go[$i_terminal]
11053                   && $block_type_to_go[$i_terminal] =~ /$bli_pattern/o;
11054
11055                 if ( !$is_bli && defined($K_next_nonblank) ) {
11056                     my $lev        = $rLL->[$K_beg]->[_LEVEL_];
11057                     my $level_next = $rLL->[$K_next_nonblank]->[_LEVEL_];
11058                     $adjust_indentation = 1 if ( $level_next < $lev );
11059                 }
11060
11061                 # Patch for RT #96101, in which closing brace of anonymous subs
11062                 # was not outdented.  We should look ahead and see if there is
11063                 # a level decrease at the next token (i.e., a closing token),
11064                 # but right now we do not have that information.  For now
11065                 # we see if we are in a list, and this works well.
11066                 # See test files 'sub*.t' for good test cases.
11067                 if (   $block_type_to_go[$ibeg] =~ /$ASUB_PATTERN/
11068                     && $container_environment_to_go[$i_terminal] eq 'LIST'
11069                     && !$rOpts->{'indent-closing-brace'} )
11070                 {
11071                     (
11072                         $opening_indentation, $opening_offset,
11073                         $is_leading,          $opening_exists
11074                       )
11075                       = $self->get_opening_indentation( $ibeg, $ri_first,
11076                         $ri_last, $rindentation_list );
11077                     my $indentation = $leading_spaces_to_go[$ibeg];
11078                     if ( defined($opening_indentation)
11079                         && get_spaces($indentation) >
11080                         get_spaces($opening_indentation) )
11081                     {
11082                         $adjust_indentation = 1;
11083                     }
11084                 }
11085             }
11086
11087             # YVES patch 1 of 2:
11088             # Undo ci of line with leading closing eval brace,
11089             # but not beyond the indention of the line with
11090             # the opening brace.
11091             if (   $block_type_to_go[$ibeg] eq 'eval'
11092                 && !$rOpts->{'line-up-parentheses'}
11093                 && !$rOpts->{'indent-closing-brace'} )
11094             {
11095                 (
11096                     $opening_indentation, $opening_offset,
11097                     $is_leading,          $opening_exists
11098                   )
11099                   = $self->get_opening_indentation( $ibeg, $ri_first, $ri_last,
11100                     $rindentation_list );
11101                 my $indentation = $leading_spaces_to_go[$ibeg];
11102                 if ( defined($opening_indentation)
11103                     && get_spaces($indentation) >
11104                     get_spaces($opening_indentation) )
11105                 {
11106                     $adjust_indentation = 1;
11107                 }
11108             }
11109
11110             $default_adjust_indentation = $adjust_indentation;
11111
11112             # Now modify default behavior according to user request:
11113             # handle option to indent non-blocks of the form );  };  ];
11114             # But don't do special indentation to something like ')->pack('
11115             if ( !$block_type_to_go[$ibeg] ) {
11116                 my $cti = $closing_token_indentation{ $tokens_to_go[$ibeg] };
11117                 if ( $cti == 1 ) {
11118                     if (   $i_terminal <= $ibeg + 1
11119                         || $is_semicolon_terminated )
11120                     {
11121                         $adjust_indentation = 2;
11122                     }
11123                     else {
11124                         $adjust_indentation = 0;
11125                     }
11126                 }
11127                 elsif ( $cti == 2 ) {
11128                     if ($is_semicolon_terminated) {
11129                         $adjust_indentation = 3;
11130                     }
11131                     else {
11132                         $adjust_indentation = 0;
11133                     }
11134                 }
11135                 elsif ( $cti == 3 ) {
11136                     $adjust_indentation = 3;
11137                 }
11138             }
11139
11140             # handle option to indent blocks
11141             else {
11142                 if (
11143                     $rOpts->{'indent-closing-brace'}
11144                     && (
11145                         $i_terminal == $ibeg    #  isolated terminal '}'
11146                         || $is_semicolon_terminated
11147                     )
11148                   )                             #  } xxxx ;
11149                 {
11150                     $adjust_indentation = 3;
11151                 }
11152             }
11153         }
11154
11155         # if at ');', '};', '>;', and '];' of a terminal qw quote
11156         elsif ($rpatterns->[0] =~ /^qb*;$/
11157             && $rfields->[0] =~ /^([\)\}\]\>]);$/ )
11158         {
11159             if ( $closing_token_indentation{$1} == 0 ) {
11160                 $adjust_indentation = 1;
11161             }
11162             else {
11163                 $adjust_indentation = 3;
11164             }
11165         }
11166
11167         # if line begins with a ':', align it with any
11168         # previous line leading with corresponding ?
11169         elsif ( $types_to_go[$ibeg] eq ':' ) {
11170             (
11171                 $opening_indentation, $opening_offset,
11172                 $is_leading,          $opening_exists
11173               )
11174               = $self->get_opening_indentation( $ibeg, $ri_first, $ri_last,
11175                 $rindentation_list );
11176             if ($is_leading) { $adjust_indentation = 2; }
11177         }
11178
11179         ##########################################################
11180         # Section 2: set indentation according to flag set above
11181         #
11182         # Select the indentation object to define leading
11183         # whitespace.  If we are outdenting something like '} } );'
11184         # then we want to use one level below the last token
11185         # ($i_terminal) in order to get it to fully outdent through
11186         # all levels.
11187         ##########################################################
11188         my $indentation;
11189         my $lev;
11190         my $level_end = $levels_to_go[$iend];
11191
11192         if ( $adjust_indentation == 0 ) {
11193             $indentation = $leading_spaces_to_go[$ibeg];
11194             $lev         = $levels_to_go[$ibeg];
11195         }
11196         elsif ( $adjust_indentation == 1 ) {
11197
11198             # Change the indentation to be that of a different token on the line
11199             # Previously, the indentation of the terminal token was used:
11200             # OLD CODING:
11201             # $indentation = $reduced_spaces_to_go[$i_terminal];
11202             # $lev         = $levels_to_go[$i_terminal];
11203
11204             # Generalization for MOJO:
11205             # Use the lowest level indentation of the tokens on the line.
11206             # For example, here we can use the indentation of the ending ';':
11207             #    } until ($selection > 0 and $selection < 10);   # ok to use ';'
11208             # But this will not outdent if we use the terminal indentation:
11209             #    )->then( sub {      # use indentation of the ->, not the {
11210             # Warning: reduced_spaces_to_go[] may be a reference, do not
11211             # do numerical checks with it
11212
11213             my $i_ind = $ibeg;
11214             $indentation = $reduced_spaces_to_go[$i_ind];
11215             $lev         = $levels_to_go[$i_ind];
11216             while ( $i_ind < $i_terminal ) {
11217                 $i_ind++;
11218                 if ( $levels_to_go[$i_ind] < $lev ) {
11219                     $indentation = $reduced_spaces_to_go[$i_ind];
11220                     $lev         = $levels_to_go[$i_ind];
11221                 }
11222             }
11223         }
11224
11225         # handle indented closing token which aligns with opening token
11226         elsif ( $adjust_indentation == 2 ) {
11227
11228             # handle option to align closing token with opening token
11229             $lev = $levels_to_go[$ibeg];
11230
11231             # calculate spaces needed to align with opening token
11232             my $space_count =
11233               get_spaces($opening_indentation) + $opening_offset;
11234
11235             # Indent less than the previous line.
11236             #
11237             # Problem: For -lp we don't exactly know what it was if there
11238             # were recoverable spaces sent to the aligner.  A good solution
11239             # would be to force a flush of the vertical alignment buffer, so
11240             # that we would know.  For now, this rule is used for -lp:
11241             #
11242             # When the last line did not start with a closing token we will
11243             # be optimistic that the aligner will recover everything wanted.
11244             #
11245             # This rule will prevent us from breaking a hierarchy of closing
11246             # tokens, and in a worst case will leave a closing paren too far
11247             # indented, but this is better than frequently leaving it not
11248             # indented enough.
11249             my $last_spaces = get_spaces($last_indentation_written);
11250             if ( $last_leading_token !~ /^[\}\]\)]$/ ) {
11251                 $last_spaces +=
11252                   get_recoverable_spaces($last_indentation_written);
11253             }
11254
11255             # reset the indentation to the new space count if it works
11256             # only options are all or none: nothing in-between looks good
11257             $lev = $levels_to_go[$ibeg];
11258             if ( $space_count < $last_spaces ) {
11259                 if ($rOpts_line_up_parentheses) {
11260                     my $lev = $levels_to_go[$ibeg];
11261                     $indentation =
11262                       new_lp_indentation_item( $space_count, $lev, 0, 0, 0 );
11263                 }
11264                 else {
11265                     $indentation = $space_count;
11266                 }
11267             }
11268
11269             # revert to default if it doesn't work
11270             else {
11271                 $space_count = leading_spaces_to_go($ibeg);
11272                 if ( $default_adjust_indentation == 0 ) {
11273                     $indentation = $leading_spaces_to_go[$ibeg];
11274                 }
11275                 elsif ( $default_adjust_indentation == 1 ) {
11276                     $indentation = $reduced_spaces_to_go[$i_terminal];
11277                     $lev         = $levels_to_go[$i_terminal];
11278                 }
11279             }
11280         }
11281
11282         # Full indentaion of closing tokens (-icb and -icp or -cti=2)
11283         else {
11284
11285             # handle -icb (indented closing code block braces)
11286             # Updated method for indented block braces: indent one full level if
11287             # there is no continuation indentation.  This will occur for major
11288             # structures such as sub, if, else, but not for things like map
11289             # blocks.
11290             #
11291             # Note: only code blocks without continuation indentation are
11292             # handled here (if, else, unless, ..). In the following snippet,
11293             # the terminal brace of the sort block will have continuation
11294             # indentation as shown so it will not be handled by the coding
11295             # here.  We would have to undo the continuation indentation to do
11296             # this, but it probably looks ok as is.  This is a possible future
11297             # update for semicolon terminated lines.
11298             #
11299             #     if ($sortby eq 'date' or $sortby eq 'size') {
11300             #         @files = sort {
11301             #             $file_data{$a}{$sortby} <=> $file_data{$b}{$sortby}
11302             #                 or $a cmp $b
11303             #                 } @files;
11304             #         }
11305             #
11306             if (   $block_type_to_go[$ibeg]
11307                 && $ci_levels_to_go[$i_terminal] == 0 )
11308             {
11309                 my $spaces = get_spaces( $leading_spaces_to_go[$i_terminal] );
11310                 $indentation = $spaces + $rOpts_indent_columns;
11311
11312                 # NOTE: for -lp we could create a new indentation object, but
11313                 # there is probably no need to do it
11314             }
11315
11316             # handle -icp and any -icb block braces which fall through above
11317             # test such as the 'sort' block mentioned above.
11318             else {
11319
11320                 # There are currently two ways to handle -icp...
11321                 # One way is to use the indentation of the previous line:
11322                 # $indentation = $last_indentation_written;
11323
11324                 # The other way is to use the indentation that the previous line
11325                 # would have had if it hadn't been adjusted:
11326                 $indentation = $last_unadjusted_indentation;
11327
11328                 # Current method: use the minimum of the two. This avoids
11329                 # inconsistent indentation.
11330                 if ( get_spaces($last_indentation_written) <
11331                     get_spaces($indentation) )
11332                 {
11333                     $indentation = $last_indentation_written;
11334                 }
11335             }
11336
11337             # use previous indentation but use own level
11338             # to cause list to be flushed properly
11339             $lev = $levels_to_go[$ibeg];
11340         }
11341
11342         # remember indentation except for multi-line quotes, which get
11343         # no indentation
11344         unless ( $ibeg == 0 && $starting_in_quote ) {
11345             $last_indentation_written    = $indentation;
11346             $last_unadjusted_indentation = $leading_spaces_to_go[$ibeg];
11347             $last_leading_token          = $tokens_to_go[$ibeg];
11348         }
11349
11350         # be sure lines with leading closing tokens are not outdented more
11351         # than the line which contained the corresponding opening token.
11352
11353         #############################################################
11354         # updated per bug report in alex_bug.pl: we must not
11355         # mess with the indentation of closing logical braces so
11356         # we must treat something like '} else {' as if it were
11357         # an isolated brace
11358         #############################################################
11359         my $is_isolated_block_brace = $block_type_to_go[$ibeg]
11360           && ( $i_terminal == $ibeg
11361             || $is_if_elsif_else_unless_while_until_for_foreach{
11362                 $block_type_to_go[$ibeg]
11363             } );
11364
11365         # only do this for a ':; which is aligned with its leading '?'
11366         my $is_unaligned_colon = $types_to_go[$ibeg] eq ':' && !$is_leading;
11367
11368         if (
11369             defined($opening_indentation)
11370             && !$leading_paren_arrow    # MOJO
11371             && !$is_isolated_block_brace
11372             && !$is_unaligned_colon
11373           )
11374         {
11375             if ( get_spaces($opening_indentation) > get_spaces($indentation) ) {
11376                 $indentation = $opening_indentation;
11377             }
11378         }
11379
11380         # remember the indentation of each line of this batch
11381         push @{$rindentation_list}, $indentation;
11382
11383         # outdent lines with certain leading tokens...
11384         if (
11385
11386             # must be first word of this batch
11387             $ibeg == 0
11388
11389             # and ...
11390             && (
11391
11392                 # certain leading keywords if requested
11393                 (
11394                        $rOpts->{'outdent-keywords'}
11395                     && $types_to_go[$ibeg] eq 'k'
11396                     && $outdent_keyword{ $tokens_to_go[$ibeg] }
11397                 )
11398
11399                 # or labels if requested
11400                 || ( $rOpts->{'outdent-labels'} && $types_to_go[$ibeg] eq 'J' )
11401
11402                 # or static block comments if requested
11403                 || (   $types_to_go[$ibeg] eq '#'
11404                     && $rOpts->{'outdent-static-block-comments'}
11405                     && $is_static_block_comment )
11406             )
11407           )
11408
11409         {
11410             my $space_count = leading_spaces_to_go($ibeg);
11411             if ( $space_count > 0 ) {
11412                 $space_count -= $rOpts_continuation_indentation;
11413                 $is_outdented_line = 1;
11414                 if ( $space_count < 0 ) { $space_count = 0 }
11415
11416                 # do not promote a spaced static block comment to non-spaced;
11417                 # this is not normally necessary but could be for some
11418                 # unusual user inputs (such as -ci = -i)
11419                 if ( $types_to_go[$ibeg] eq '#' && $space_count == 0 ) {
11420                     $space_count = 1;
11421                 }
11422
11423                 if ($rOpts_line_up_parentheses) {
11424                     $indentation =
11425                       new_lp_indentation_item( $space_count, $lev, 0, 0, 0 );
11426                 }
11427                 else {
11428                     $indentation = $space_count;
11429                 }
11430             }
11431         }
11432
11433         return ( $indentation, $lev, $level_end, $terminal_type,
11434             $is_semicolon_terminated, $is_outdented_line );
11435     }
11436 }
11437
11438 sub mate_index_to_go {
11439     my ( $self, $i ) = @_;
11440
11441     # Return the matching index of a container or ternary pair
11442     # This is equivalent to the array @mate_index_to_go
11443     my $K      = $K_to_go[$i];
11444     my $K_mate = $self->K_mate_index($K);
11445     my $i_mate = -1;
11446     if ( defined($K_mate) ) {
11447         $i_mate = $i + ( $K_mate - $K );
11448         if ( $i_mate < 0 || $i_mate > $max_index_to_go ) {
11449             $i_mate = -1;
11450         }
11451     }
11452     my $i_mate_alt = $mate_index_to_go[$i];
11453
11454     # Debug code to eventually be removed
11455     if ( 0 && $i_mate_alt != $i_mate ) {
11456         my $tok       = $tokens_to_go[$i];
11457         my $type      = $types_to_go[$i];
11458         my $tok_mate  = '*';
11459         my $type_mate = '*';
11460         if ( $i_mate >= 0 && $i_mate <= $max_index_to_go ) {
11461             $tok_mate  = $tokens_to_go[$i_mate];
11462             $type_mate = $types_to_go[$i_mate];
11463         }
11464         my $seq  = $type_sequence_to_go[$i];
11465         my $file = $logger_object->get_input_stream_name();
11466
11467         Warn(
11468 "mate_index: file '$file': i=$i, imate=$i_mate, should be $i_mate_alt, K=$K, K_mate=$K_mate\ntype=$type, tok=$tok, seq=$seq, max=$max_index_to_go, tok_mate=$tok_mate, type_mate=$type_mate"
11469         );
11470     }
11471     return $i_mate;
11472 }
11473
11474 sub K_mate_index {
11475
11476    # Given the index K of an opening or closing container,  or ?/: ternary pair,
11477    # return the index K of the other member of the pair.
11478     my ( $self, $K ) = @_;
11479     return unless defined($K);
11480     my $rLL   = $self->{rLL};
11481     my $seqno = $rLL->[$K]->[_TYPE_SEQUENCE_];
11482     return unless ($seqno);
11483
11484     my $K_opening = $self->{K_opening_container}->{$seqno};
11485     if ( defined($K_opening) ) {
11486         if ( $K != $K_opening ) { return $K_opening }
11487         return $self->{K_closing_container}->{$seqno};
11488     }
11489
11490     $K_opening = $self->{K_opening_ternary}->{$seqno};
11491     if ( defined($K_opening) ) {
11492         if ( $K != $K_opening ) { return $K_opening }
11493         return $self->{K_closing_ternary}->{$seqno};
11494     }
11495     return;
11496 }
11497
11498 sub set_vertical_tightness_flags {
11499
11500     my ( $self, $n, $n_last_line, $ibeg, $iend, $ri_first, $ri_last ) = @_;
11501
11502     # Define vertical tightness controls for the nth line of a batch.
11503     # We create an array of parameters which tell the vertical aligner
11504     # if we should combine this line with the next line to achieve the
11505     # desired vertical tightness.  The array of parameters contains:
11506     #
11507     #   [0] type: 1=opening non-block    2=closing non-block
11508     #             3=opening block brace  4=closing block brace
11509     #
11510     #   [1] flag: if opening: 1=no multiple steps, 2=multiple steps ok
11511     #             if closing: spaces of padding to use
11512     #   [2] sequence number of container
11513     #   [3] valid flag: do not append if this flag is false. Will be
11514     #       true if appropriate -vt flag is set.  Otherwise, Will be
11515     #       made true only for 2 line container in parens with -lp
11516     #
11517     # These flags are used by sub set_leading_whitespace in
11518     # the vertical aligner
11519
11520     my $rvertical_tightness_flags = [ 0, 0, 0, 0, 0, 0 ];
11521
11522     #--------------------------------------------------------------
11523     # Vertical Tightness Flags Section 1:
11524     # Handle Lines 1 .. n-1 but not the last line
11525     # For non-BLOCK tokens, we will need to examine the next line
11526     # too, so we won't consider the last line.
11527     #--------------------------------------------------------------
11528     if ( $n < $n_last_line ) {
11529
11530         #--------------------------------------------------------------
11531         # Vertical Tightness Flags Section 1a:
11532         # Look for Type 1, last token of this line is a non-block opening token
11533         #--------------------------------------------------------------
11534         my $ibeg_next = $ri_first->[ $n + 1 ];
11535         my $token_end = $tokens_to_go[$iend];
11536         my $iend_next = $ri_last->[ $n + 1 ];
11537         if (
11538                $type_sequence_to_go[$iend]
11539             && !$block_type_to_go[$iend]
11540             && $is_opening_token{$token_end}
11541             && (
11542                 $opening_vertical_tightness{$token_end} > 0
11543
11544                 # allow 2-line method call to be closed up
11545                 || (   $rOpts_line_up_parentheses
11546                     && $token_end eq '('
11547                     && $iend > $ibeg
11548                     && $types_to_go[ $iend - 1 ] ne 'b' )
11549             )
11550           )
11551         {
11552
11553             # avoid multiple jumps in nesting depth in one line if
11554             # requested
11555             my $ovt       = $opening_vertical_tightness{$token_end};
11556             my $iend_next = $ri_last->[ $n + 1 ];
11557             unless (
11558                 $ovt < 2
11559                 && ( $nesting_depth_to_go[ $iend_next + 1 ] !=
11560                     $nesting_depth_to_go[$ibeg_next] )
11561               )
11562             {
11563
11564                 # If -vt flag has not been set, mark this as invalid
11565                 # and aligner will validate it if it sees the closing paren
11566                 # within 2 lines.
11567                 my $valid_flag = $ovt;
11568                 @{$rvertical_tightness_flags} =
11569                   ( 1, $ovt, $type_sequence_to_go[$iend], $valid_flag );
11570             }
11571         }
11572
11573         #--------------------------------------------------------------
11574         # Vertical Tightness Flags Section 1b:
11575         # Look for Type 2, first token of next line is a non-block closing
11576         # token .. and be sure this line does not have a side comment
11577         #--------------------------------------------------------------
11578         my $token_next = $tokens_to_go[$ibeg_next];
11579         if (   $type_sequence_to_go[$ibeg_next]
11580             && !$block_type_to_go[$ibeg_next]
11581             && $is_closing_token{$token_next}
11582             && $types_to_go[$iend] !~ '#' )    # for safety, shouldn't happen!
11583         {
11584             my $ovt = $opening_vertical_tightness{$token_next};
11585             my $cvt = $closing_vertical_tightness{$token_next};
11586             if (
11587
11588                 # never append a trailing line like   )->pack(
11589                 # because it will throw off later alignment
11590                 (
11591                     $nesting_depth_to_go[$ibeg_next] ==
11592                     $nesting_depth_to_go[ $iend_next + 1 ] + 1
11593                 )
11594                 && (
11595                     $cvt == 2
11596                     || (
11597                         $container_environment_to_go[$ibeg_next] ne 'LIST'
11598                         && (
11599                             $cvt == 1
11600
11601                             # allow closing up 2-line method calls
11602                             || (   $rOpts_line_up_parentheses
11603                                 && $token_next eq ')' )
11604                         )
11605                     )
11606                 )
11607               )
11608             {
11609
11610                 # decide which trailing closing tokens to append..
11611                 my $ok = 0;
11612                 if ( $cvt == 2 || $iend_next == $ibeg_next ) { $ok = 1 }
11613                 else {
11614                     my $str = join( '',
11615                         @types_to_go[ $ibeg_next + 1 .. $ibeg_next + 2 ] );
11616
11617                     # append closing token if followed by comment or ';'
11618                     if ( $str =~ /^b?[#;]/ ) { $ok = 1 }
11619                 }
11620
11621                 if ($ok) {
11622                     my $valid_flag = $cvt;
11623                     @{$rvertical_tightness_flags} = (
11624                         2,
11625                         $tightness{$token_next} == 2 ? 0 : 1,
11626                         $type_sequence_to_go[$ibeg_next], $valid_flag,
11627                     );
11628                 }
11629             }
11630         }
11631
11632         #--------------------------------------------------------------
11633         # Vertical Tightness Flags Section 1c:
11634         # Implement the Opening Token Right flag (Type 2)..
11635         # If requested, move an isolated trailing opening token to the end of
11636         # the previous line which ended in a comma.  We could do this
11637         # in sub recombine_breakpoints but that would cause problems
11638         # with -lp formatting.  The problem is that indentation will
11639         # quickly move far to the right in nested expressions.  By
11640         # doing it after indentation has been set, we avoid changes
11641         # to the indentation.  Actual movement of the token takes place
11642         # in sub valign_output_step_B.
11643         #--------------------------------------------------------------
11644         if (
11645             $opening_token_right{ $tokens_to_go[$ibeg_next] }
11646
11647             # previous line is not opening
11648             # (use -sot to combine with it)
11649             && !$is_opening_token{$token_end}
11650
11651             # previous line ended in one of these
11652             # (add other cases if necessary; '=>' and '.' are not necessary
11653             && !$block_type_to_go[$ibeg_next]
11654
11655             # this is a line with just an opening token
11656             && (   $iend_next == $ibeg_next
11657                 || $iend_next == $ibeg_next + 2
11658                 && $types_to_go[$iend_next] eq '#' )
11659
11660             # looks bad if we align vertically with the wrong container
11661             && $tokens_to_go[$ibeg] ne $tokens_to_go[$ibeg_next]
11662           )
11663         {
11664             my $valid_flag = 1;
11665             my $spaces     = ( $types_to_go[ $ibeg_next - 1 ] eq 'b' ) ? 1 : 0;
11666             @{$rvertical_tightness_flags} =
11667               ( 2, $spaces, $type_sequence_to_go[$ibeg_next], $valid_flag, );
11668         }
11669
11670         #--------------------------------------------------------------
11671         # Vertical Tightness Flags Section 1d:
11672         # Stacking of opening and closing tokens (Type 2)
11673         #--------------------------------------------------------------
11674         my $stackable;
11675         my $token_beg_next = $tokens_to_go[$ibeg_next];
11676
11677         # patch to make something like 'qw(' behave like an opening paren
11678         # (aran.t)
11679         if ( $types_to_go[$ibeg_next] eq 'q' ) {
11680             if ( $token_beg_next =~ /^qw\s*([\[\(\{])$/ ) {
11681                 $token_beg_next = $1;
11682             }
11683         }
11684
11685         if (   $is_closing_token{$token_end}
11686             && $is_closing_token{$token_beg_next} )
11687         {
11688             $stackable = $stack_closing_token{$token_beg_next}
11689               unless ( $block_type_to_go[$ibeg_next] )
11690               ;    # shouldn't happen; just checking
11691         }
11692         elsif ($is_opening_token{$token_end}
11693             && $is_opening_token{$token_beg_next} )
11694         {
11695             $stackable = $stack_opening_token{$token_beg_next}
11696               unless ( $block_type_to_go[$ibeg_next] )
11697               ;    # shouldn't happen; just checking
11698         }
11699
11700         if ($stackable) {
11701
11702             my $is_semicolon_terminated;
11703             if ( $n + 1 == $n_last_line ) {
11704                 my ( $terminal_type, $i_terminal ) =
11705                   $self->terminal_type_i( $ibeg_next, $iend_next );
11706                 $is_semicolon_terminated = $terminal_type eq ';'
11707                   && $nesting_depth_to_go[$iend_next] <
11708                   $nesting_depth_to_go[$ibeg_next];
11709             }
11710
11711             # this must be a line with just an opening token
11712             # or end in a semicolon
11713             if (
11714                 $is_semicolon_terminated
11715                 || (   $iend_next == $ibeg_next
11716                     || $iend_next == $ibeg_next + 2
11717                     && $types_to_go[$iend_next] eq '#' )
11718               )
11719             {
11720                 my $valid_flag = 1;
11721                 my $spaces = ( $types_to_go[ $ibeg_next - 1 ] eq 'b' ) ? 1 : 0;
11722                 @{$rvertical_tightness_flags} =
11723                   ( 2, $spaces, $type_sequence_to_go[$ibeg_next], $valid_flag,
11724                   );
11725             }
11726         }
11727     }
11728
11729     #--------------------------------------------------------------
11730     # Vertical Tightness Flags Section 2:
11731     # Handle type 3, opening block braces on last line of the batch
11732     # Check for a last line with isolated opening BLOCK curly
11733     #--------------------------------------------------------------
11734     elsif ($rOpts_block_brace_vertical_tightness
11735         && $ibeg eq $iend
11736         && $types_to_go[$iend] eq '{'
11737         && $block_type_to_go[$iend] =~
11738         /$block_brace_vertical_tightness_pattern/o )
11739     {
11740         @{$rvertical_tightness_flags} =
11741           ( 3, $rOpts_block_brace_vertical_tightness, 0, 1 );
11742     }
11743
11744     #--------------------------------------------------------------
11745     # Vertical Tightness Flags Section 3:
11746     # Handle type 4, a closing block brace on the last line of the batch Check
11747     # for a last line with isolated closing BLOCK curly
11748     #--------------------------------------------------------------
11749     elsif ($rOpts_stack_closing_block_brace
11750         && $ibeg eq $iend
11751         && $block_type_to_go[$iend]
11752         && $types_to_go[$iend] eq '}' )
11753     {
11754         my $spaces = $rOpts_block_brace_tightness == 2 ? 0 : 1;
11755         @{$rvertical_tightness_flags} =
11756           ( 4, $spaces, $type_sequence_to_go[$iend], 1 );
11757     }
11758
11759     # pack in the sequence numbers of the ends of this line
11760     $rvertical_tightness_flags->[4] = get_seqno($ibeg);
11761     $rvertical_tightness_flags->[5] = get_seqno($iend);
11762     return $rvertical_tightness_flags;
11763 }
11764
11765 sub get_seqno {
11766
11767     # get opening and closing sequence numbers of a token for the vertical
11768     # aligner.  Assign qw quotes a value to allow qw opening and closing tokens
11769     # to be treated somewhat like opening and closing tokens for stacking
11770     # tokens by the vertical aligner.
11771     my ($ii) = @_;
11772     my $seqno = $type_sequence_to_go[$ii];
11773     if ( $types_to_go[$ii] eq 'q' ) {
11774         my $SEQ_QW = -1;
11775         if ( $ii > 0 ) {
11776             $seqno = $SEQ_QW if ( $tokens_to_go[$ii] =~ /^qw\s*[\(\{\[]/ );
11777         }
11778         else {
11779             if ( !$ending_in_quote ) {
11780                 $seqno = $SEQ_QW if ( $tokens_to_go[$ii] =~ /[\)\}\]]$/ );
11781             }
11782         }
11783     }
11784     return ($seqno);
11785 }
11786
11787 {
11788     my %is_vertical_alignment_type;
11789     my %is_not_vertical_alignment_token;
11790     my %is_vertical_alignment_keyword;
11791     my %is_terminal_alignment_type;
11792     my %is_low_level_alignment_token;
11793
11794     BEGIN {
11795
11796         my @q;
11797
11798         # Replaced =~ and // in the list.  // had been removed in RT 119588
11799         @q = qw#
11800           = **= += *= &= <<= &&= -= /= |= >>= ||= //= .= %= ^= x=
11801           { ? : => && || ~~ !~~ =~ !~ //
11802           #;
11803         @is_vertical_alignment_type{@q} = (1) x scalar(@q);
11804
11805         # These 'tokens' are not aligned. We need this to remove [
11806         # from the above list because it has type ='{'
11807         @q = qw([);
11808         @is_not_vertical_alignment_token{@q} = (1) x scalar(@q);
11809
11810         # these are the only types aligned at a line end
11811         @q = qw(&& ||);
11812         @is_terminal_alignment_type{@q} = (1) x scalar(@q);
11813
11814         # these tokens only align at line level
11815         @q = ( '{', '(' );
11816         @is_low_level_alignment_token{@q} = (1) x scalar(@q);
11817
11818         # eq and ne were removed from this list to improve alignment chances
11819         @q = qw(if unless and or err for foreach while until);
11820         @is_vertical_alignment_keyword{@q} = (1) x scalar(@q);
11821     }
11822
11823     sub set_vertical_alignment_markers {
11824
11825         # This routine takes the first step toward vertical alignment of the
11826         # lines of output text.  It looks for certain tokens which can serve as
11827         # vertical alignment markers (such as an '=').
11828         #
11829         # Method: We look at each token $i in this output batch and set
11830         # $ralignment_type_to_go->[$i] equal to those tokens at which we would
11831         # accept vertical alignment.
11832
11833         my ( $self, $ri_first, $ri_last ) = @_;
11834
11835         my $ralignment_type_to_go;
11836         for my $i ( 0 .. $max_index_to_go ) {
11837             $ralignment_type_to_go->[$i] = '';
11838         }
11839
11840         # nothing to do if we aren't allowed to change whitespace
11841         if ( !$rOpts_add_whitespace ) {
11842             return $ralignment_type_to_go;
11843         }
11844
11845         # remember the index of last nonblank token before any sidecomment
11846         my $i_terminal = $max_index_to_go;
11847         if ( $types_to_go[$i_terminal] eq '#' ) {
11848             if ( $i_terminal > 0 && $types_to_go[ --$i_terminal ] eq 'b' ) {
11849                 if ( $i_terminal > 0 ) { --$i_terminal }
11850             }
11851         }
11852
11853         # look at each line of this batch..
11854         my $last_vertical_alignment_before_index;
11855         my $vert_last_nonblank_type;
11856         my $vert_last_nonblank_token;
11857         my $vert_last_nonblank_block_type;
11858         my $max_line = @{$ri_first} - 1;
11859
11860         foreach my $line ( 0 .. $max_line ) {
11861             my $ibeg = $ri_first->[$line];
11862             my $iend = $ri_last->[$line];
11863             $last_vertical_alignment_before_index = -1;
11864             $vert_last_nonblank_type              = '';
11865             $vert_last_nonblank_token             = '';
11866             $vert_last_nonblank_block_type        = '';
11867
11868             # look at each token in this output line..
11869             my $level_beg = $levels_to_go[$ibeg];
11870             foreach my $i ( $ibeg .. $iend ) {
11871                 my $alignment_type = '';
11872                 my $type           = $types_to_go[$i];
11873                 my $block_type     = $block_type_to_go[$i];
11874                 my $token          = $tokens_to_go[$i];
11875
11876                 # do not align tokens at lower level then start of line
11877                 # except for side comments
11878                 if (   $levels_to_go[$i] < $levels_to_go[$ibeg]
11879                     && $types_to_go[$i] ne '#' )
11880                 {
11881                     $ralignment_type_to_go->[$i] = '';
11882                     next;
11883                 }
11884
11885                 #--------------------------------------------------------
11886                 # First see if we want to align BEFORE this token
11887                 #--------------------------------------------------------
11888
11889                 # The first possible token that we can align before
11890                 # is index 2 because: 1) it doesn't normally make sense to
11891                 # align before the first token and 2) the second
11892                 # token must be a blank if we are to align before
11893                 # the third
11894                 if ( $i < $ibeg + 2 ) { }
11895
11896                 # must follow a blank token
11897                 elsif ( $types_to_go[ $i - 1 ] ne 'b' ) { }
11898
11899                 # align a side comment --
11900                 elsif ( $type eq '#' ) {
11901
11902                     unless (
11903
11904                         # it is a static side comment
11905                         (
11906                                $rOpts->{'static-side-comments'}
11907                             && $token =~ /$static_side_comment_pattern/o
11908                         )
11909
11910                         # or a closing side comment
11911                         || (   $vert_last_nonblank_block_type
11912                             && $token =~
11913                             /$closing_side_comment_prefix_pattern/o )
11914                       )
11915                     {
11916                         $alignment_type = $type;
11917                     }    ## Example of a static side comment
11918                 }
11919
11920                 # otherwise, do not align two in a row to create a
11921                 # blank field
11922                 elsif ( $last_vertical_alignment_before_index == $i - 2 ) { }
11923
11924                 # align before one of these keywords
11925                 # (within a line, since $i>1)
11926                 elsif ( $type eq 'k' ) {
11927
11928                     #  /^(if|unless|and|or|eq|ne)$/
11929                     if ( $is_vertical_alignment_keyword{$token} ) {
11930                         $alignment_type = $token;
11931                     }
11932                 }
11933
11934                 # align before one of these types..
11935                 # Note: add '.' after new vertical aligner is operational
11936                 elsif ( $is_vertical_alignment_type{$type}
11937                     && !$is_not_vertical_alignment_token{$token} )
11938                 {
11939                     $alignment_type = $token;
11940
11941                     # Do not align a terminal token.  Although it might
11942                     # occasionally look ok to do this, this has been found to be
11943                     # a good general rule.  The main problems are:
11944                     # (1) that the terminal token (such as an = or :) might get
11945                     # moved far to the right where it is hard to see because
11946                     # nothing follows it, and
11947                     # (2) doing so may prevent other good alignments.
11948                     # Current exceptions are && and ||
11949                     if ( $i == $iend || $i >= $i_terminal ) {
11950                         $alignment_type = ""
11951                           unless ( $is_terminal_alignment_type{$type} );
11952                     }
11953
11954                     # Do not align leading ': (' or '. ('.  This would prevent
11955                     # alignment in something like the following:
11956                     #   $extra_space .=
11957                     #       ( $input_line_number < 10 )  ? "  "
11958                     #     : ( $input_line_number < 100 ) ? " "
11959                     #     :                                "";
11960                     # or
11961                     #  $code =
11962                     #      ( $case_matters ? $accessor : " lc($accessor) " )
11963                     #    . ( $yesno        ? " eq "       : " ne " )
11964
11965                     # Also, do not align a ( following a leading ? so we can
11966                     # align something like this:
11967                     #   $converter{$_}->{ushortok} =
11968                     #     $PDL::IO::Pic::biggrays
11969                     #     ? ( m/GIF/          ? 0 : 1 )
11970                     #     : ( m/GIF|RAST|IFF/ ? 0 : 1 );
11971                     if (   $i == $ibeg + 2
11972                         && $types_to_go[$ibeg] =~ /^[\.\:\?]$/
11973                         && $types_to_go[ $i - 1 ] eq 'b' )
11974                     {
11975                         $alignment_type = "";
11976                     }
11977
11978                     # Certain tokens only align at the same level as the
11979                     # initial line level
11980                     if (   $is_low_level_alignment_token{$token}
11981                         && $levels_to_go[$i] != $level_beg )
11982                     {
11983                         $alignment_type = "";
11984                     }
11985
11986                     # For a paren after keyword, only align something like this:
11987                     #    if    ( $a ) { &a }
11988                     #    elsif ( $b ) { &b }
11989                     if ( $token eq '(' ) {
11990
11991                         if ( $vert_last_nonblank_type eq 'k' ) {
11992                             $alignment_type = ""
11993                               unless $vert_last_nonblank_token =~
11994                               /^(if|unless|elsif)$/;
11995                         }
11996                     }
11997
11998                     # be sure the alignment tokens are unique
11999                     # This didn't work well: reason not determined
12000                     # if ($token ne $type) {$alignment_type .= $type}
12001                 }
12002
12003                 # NOTE: This is deactivated because it causes the previous
12004                 # if/elsif alignment to fail
12005                 #elsif ( $type eq '}' && $token eq '}' && $block_type_to_go[$i])
12006                 #{ $alignment_type = $type; }
12007
12008                 if ($alignment_type) {
12009                     $last_vertical_alignment_before_index = $i;
12010                 }
12011
12012                 #--------------------------------------------------------
12013                 # Next see if we want to align AFTER the previous nonblank
12014                 #--------------------------------------------------------
12015
12016                 # We want to line up ',' and interior ';' tokens, with the added
12017                 # space AFTER these tokens.  (Note: interior ';' is included
12018                 # because it may occur in short blocks).
12019                 if (
12020
12021                     # we haven't already set it
12022                     !$alignment_type
12023
12024                     # and its not the first token of the line
12025                     && ( $i > $ibeg )
12026
12027                     # and it follows a blank
12028                     && $types_to_go[ $i - 1 ] eq 'b'
12029
12030                     # and previous token IS one of these:
12031                     && ( $vert_last_nonblank_type =~ /^[\,\;]$/ )
12032
12033                     # and it's NOT one of these
12034                     && ( $type !~ /^[b\#\)\]\}]$/ )
12035
12036                     # then go ahead and align
12037                   )
12038
12039                 {
12040                     $alignment_type = $vert_last_nonblank_type;
12041                 }
12042
12043                 #--------------------------------------------------------
12044                 # then store the value
12045                 #--------------------------------------------------------
12046                 $ralignment_type_to_go->[$i] = $alignment_type;
12047                 if ( $type ne 'b' ) {
12048                     $vert_last_nonblank_type       = $type;
12049                     $vert_last_nonblank_token      = $token;
12050                     $vert_last_nonblank_block_type = $block_type;
12051                 }
12052             }
12053         }
12054         return $ralignment_type_to_go;
12055     }
12056 }
12057
12058 sub terminal_type_i {
12059
12060     #    returns type of last token on this line (terminal token), as follows:
12061     #    returns # for a full-line comment
12062     #    returns ' ' for a blank line
12063     #    otherwise returns final token type
12064
12065     my ( $self, $ibeg, $iend ) = @_;
12066
12067     # Start at the end and work backwards
12068     my $i      = $iend;
12069     my $type_i = $types_to_go[$i];
12070
12071     # Check for side comment
12072     if ( $type_i eq '#' ) {
12073         $i--;
12074         if ( $i < $ibeg ) {
12075             return wantarray ? ( $type_i, $ibeg ) : $type_i;
12076         }
12077         $type_i = $types_to_go[$i];
12078     }
12079
12080     # Skip past a blank
12081     if ( $type_i eq 'b' ) {
12082         $i--;
12083         if ( $i < $ibeg ) {
12084             return wantarray ? ( $type_i, $ibeg ) : $type_i;
12085         }
12086         $type_i = $types_to_go[$i];
12087     }
12088
12089     # Found it..make sure it is a BLOCK termination,
12090     # but hide a terminal } after sort/grep/map because it is not
12091     # necessarily the end of the line.  (terminal.t)
12092     my $block_type = $block_type_to_go[$i];
12093     if (
12094         $type_i eq '}'
12095         && ( !$block_type
12096             || ( $is_sort_map_grep_eval_do{$block_type} ) )
12097       )
12098     {
12099         $type_i = 'b';
12100     }
12101     return wantarray ? ( $type_i, $i ) : $type_i;
12102 }
12103
12104 sub terminal_type_K {
12105
12106     #    returns type of last token on this line (terminal token), as follows:
12107     #    returns # for a full-line comment
12108     #    returns ' ' for a blank line
12109     #    otherwise returns final token type
12110
12111     my ( $self, $Kbeg, $Kend ) = @_;
12112     my $rLL = $self->{rLL};
12113
12114     if ( !defined($Kend) ) {
12115         Fault("Error in terminal_type_K: Kbeg=$Kbeg > $Kend=Kend");
12116     }
12117
12118     # Start at the end and work backwards
12119     my $K      = $Kend;
12120     my $type_K = $rLL->[$K]->[_TYPE_];
12121
12122     # Check for side comment
12123     if ( $type_K eq '#' ) {
12124         $K--;
12125         if ( $K < $Kbeg ) {
12126             return wantarray ? ( $type_K, $Kbeg ) : $type_K;
12127         }
12128         $type_K = $rLL->[$K]->[_TYPE_];
12129     }
12130
12131     # Skip past a blank
12132     if ( $type_K eq 'b' ) {
12133         $K--;
12134         if ( $K < $Kbeg ) {
12135             return wantarray ? ( $type_K, $Kbeg ) : $type_K;
12136         }
12137         $type_K = $rLL->[$K]->[_TYPE_];
12138     }
12139
12140     # found it..make sure it is a BLOCK termination,
12141     # but hide a terminal } after sort/grep/map because it is not
12142     # necessarily the end of the line.  (terminal.t)
12143     my $block_type = $rLL->[$K]->[_BLOCK_TYPE_];
12144     if (
12145         $type_K eq '}'
12146         && ( !$block_type
12147             || ( $is_sort_map_grep_eval_do{$block_type} ) )
12148       )
12149     {
12150         $type_K = 'b';
12151     }
12152     return wantarray ? ( $type_K, $K ) : $type_K;
12153
12154 }
12155
12156 {    # set_bond_strengths
12157
12158     my %is_good_keyword_breakpoint;
12159     my %is_lt_gt_le_ge;
12160
12161     my %binary_bond_strength;
12162     my %nobreak_lhs;
12163     my %nobreak_rhs;
12164
12165     my @bias_tokens;
12166     my $delta_bias;
12167
12168     sub bias_table_key {
12169         my ( $type, $token ) = @_;
12170         my $bias_table_key = $type;
12171         if ( $type eq 'k' ) {
12172             $bias_table_key = $token;
12173             if ( $token eq 'err' ) { $bias_table_key = 'or' }
12174         }
12175         return $bias_table_key;
12176     }
12177
12178     sub initialize_bond_strength_hashes {
12179
12180         my @q;
12181         @q = qw(if unless while until for foreach);
12182         @is_good_keyword_breakpoint{@q} = (1) x scalar(@q);
12183
12184         @q = qw(lt gt le ge);
12185         @is_lt_gt_le_ge{@q} = (1) x scalar(@q);
12186         #
12187         # The decision about where to break a line depends upon a "bond
12188         # strength" between tokens.  The LOWER the bond strength, the MORE
12189         # likely a break.  A bond strength may be any value but to simplify
12190         # things there are several pre-defined strength levels:
12191
12192         #    NO_BREAK    => 10000;
12193         #    VERY_STRONG => 100;
12194         #    STRONG      => 2.1;
12195         #    NOMINAL     => 1.1;
12196         #    WEAK        => 0.8;
12197         #    VERY_WEAK   => 0.55;
12198
12199         # The strength values are based on trial-and-error, and need to be
12200         # tweaked occasionally to get desired results.  Some comments:
12201         #
12202         #   1. Only relative strengths are important.  small differences
12203         #      in strengths can make big formatting differences.
12204         #   2. Each indentation level adds one unit of bond strength.
12205         #   3. A value of NO_BREAK makes an unbreakable bond
12206         #   4. A value of VERY_WEAK is the strength of a ','
12207         #   5. Values below NOMINAL are considered ok break points.
12208         #   6. Values above NOMINAL are considered poor break points.
12209         #
12210         # The bond strengths should roughly follow precedence order where
12211         # possible.  If you make changes, please check the results very
12212         # carefully on a variety of scripts.  Testing with the -extrude
12213         # options is particularly helpful in exercising all of the rules.
12214
12215         # Wherever possible, bond strengths are defined in the following
12216         # tables.  There are two main stages to setting bond strengths and
12217         # two types of tables:
12218         #
12219         # The first stage involves looking at each token individually and
12220         # defining left and right bond strengths, according to if we want
12221         # to break to the left or right side, and how good a break point it
12222         # is.  For example tokens like =, ||, && make good break points and
12223         # will have low strengths, but one might want to break on either
12224         # side to put them at the end of one line or beginning of the next.
12225         #
12226         # The second stage involves looking at certain pairs of tokens and
12227         # defining a bond strength for that particular pair.  This second
12228         # stage has priority.
12229
12230         #---------------------------------------------------------------
12231         # Bond Strength BEGIN Section 1.
12232         # Set left and right bond strengths of individual tokens.
12233         #---------------------------------------------------------------
12234
12235         # NOTE: NO_BREAK's set in this section first are HINTS which will
12236         # probably not be honored. Essential NO_BREAKS's should be set in
12237         # BEGIN Section 2 or hardwired in the NO_BREAK coding near the end
12238         # of this subroutine.
12239
12240         # Note that we are setting defaults in this section.  The user
12241         # cannot change bond strengths but can cause the left and right
12242         # bond strengths of any token type to be swapped through the use of
12243         # the -wba and -wbb flags. In this way the user can determine if a
12244         # breakpoint token should appear at the end of one line or the
12245         # beginning of the next line.
12246
12247         # The hash keys in this section are token types, plus the text of
12248         # certain keywords like 'or', 'and'.
12249
12250         # no break around possible filehandle
12251         $left_bond_strength{'Z'}  = NO_BREAK;
12252         $right_bond_strength{'Z'} = NO_BREAK;
12253
12254         # never put a bare word on a new line:
12255         # example print (STDERR, "bla"); will fail with break after (
12256         $left_bond_strength{'w'} = NO_BREAK;
12257
12258         # blanks always have infinite strength to force breaks after
12259         # real tokens
12260         $right_bond_strength{'b'} = NO_BREAK;
12261
12262         # try not to break on exponentation
12263         @q                       = qw# ** .. ... <=> #;
12264         @left_bond_strength{@q}  = (STRONG) x scalar(@q);
12265         @right_bond_strength{@q} = (STRONG) x scalar(@q);
12266
12267         # The comma-arrow has very low precedence but not a good break point
12268         $left_bond_strength{'=>'}  = NO_BREAK;
12269         $right_bond_strength{'=>'} = NOMINAL;
12270
12271         # ok to break after label
12272         $left_bond_strength{'J'}  = NO_BREAK;
12273         $right_bond_strength{'J'} = NOMINAL;
12274         $left_bond_strength{'j'}  = STRONG;
12275         $right_bond_strength{'j'} = STRONG;
12276         $left_bond_strength{'A'}  = STRONG;
12277         $right_bond_strength{'A'} = STRONG;
12278
12279         $left_bond_strength{'->'}  = STRONG;
12280         $right_bond_strength{'->'} = VERY_STRONG;
12281
12282         $left_bond_strength{'CORE::'}  = NOMINAL;
12283         $right_bond_strength{'CORE::'} = NO_BREAK;
12284
12285         # breaking AFTER modulus operator is ok:
12286         @q = qw< % >;
12287         @left_bond_strength{@q} = (STRONG) x scalar(@q);
12288         @right_bond_strength{@q} =
12289           ( 0.1 * NOMINAL + 0.9 * STRONG ) x scalar(@q);
12290
12291         # Break AFTER math operators * and /
12292         @q                       = qw< * / x  >;
12293         @left_bond_strength{@q}  = (STRONG) x scalar(@q);
12294         @right_bond_strength{@q} = (NOMINAL) x scalar(@q);
12295
12296         # Break AFTER weakest math operators + and -
12297         # Make them weaker than * but a bit stronger than '.'
12298         @q = qw< + - >;
12299         @left_bond_strength{@q} = (STRONG) x scalar(@q);
12300         @right_bond_strength{@q} =
12301           ( 0.91 * NOMINAL + 0.09 * WEAK ) x scalar(@q);
12302
12303         # breaking BEFORE these is just ok:
12304         @q                       = qw# >> << #;
12305         @right_bond_strength{@q} = (STRONG) x scalar(@q);
12306         @left_bond_strength{@q}  = (NOMINAL) x scalar(@q);
12307
12308         # breaking before the string concatenation operator seems best
12309         # because it can be hard to see at the end of a line
12310         $right_bond_strength{'.'} = STRONG;
12311         $left_bond_strength{'.'}  = 0.9 * NOMINAL + 0.1 * WEAK;
12312
12313         @q                       = qw< } ] ) R >;
12314         @left_bond_strength{@q}  = (STRONG) x scalar(@q);
12315         @right_bond_strength{@q} = (NOMINAL) x scalar(@q);
12316
12317         # make these a little weaker than nominal so that they get
12318         # favored for end-of-line characters
12319         @q = qw< != == =~ !~ ~~ !~~ >;
12320         @left_bond_strength{@q} = (STRONG) x scalar(@q);
12321         @right_bond_strength{@q} =
12322           ( 0.9 * NOMINAL + 0.1 * WEAK ) x scalar(@q);
12323
12324         # break AFTER these
12325         @q = qw# < >  | & >= <= #;
12326         @left_bond_strength{@q} = (VERY_STRONG) x scalar(@q);
12327         @right_bond_strength{@q} =
12328           ( 0.8 * NOMINAL + 0.2 * WEAK ) x scalar(@q);
12329
12330         # breaking either before or after a quote is ok
12331         # but bias for breaking before a quote
12332         $left_bond_strength{'Q'}  = NOMINAL;
12333         $right_bond_strength{'Q'} = NOMINAL + 0.02;
12334         $left_bond_strength{'q'}  = NOMINAL;
12335         $right_bond_strength{'q'} = NOMINAL;
12336
12337         # starting a line with a keyword is usually ok
12338         $left_bond_strength{'k'} = NOMINAL;
12339
12340         # we usually want to bond a keyword strongly to what immediately
12341         # follows, rather than leaving it stranded at the end of a line
12342         $right_bond_strength{'k'} = STRONG;
12343
12344         $left_bond_strength{'G'}  = NOMINAL;
12345         $right_bond_strength{'G'} = STRONG;
12346
12347         # assignment operators
12348         @q = qw(
12349           = **= += *= &= <<= &&=
12350           -= /= |= >>= ||= //=
12351           .= %= ^=
12352           x=
12353         );
12354
12355         # Default is to break AFTER various assignment operators
12356         @left_bond_strength{@q} = (STRONG) x scalar(@q);
12357         @right_bond_strength{@q} =
12358           ( 0.4 * WEAK + 0.6 * VERY_WEAK ) x scalar(@q);
12359
12360         # Default is to break BEFORE '&&' and '||' and '//'
12361         # set strength of '||' to same as '=' so that chains like
12362         # $a = $b || $c || $d   will break before the first '||'
12363         $right_bond_strength{'||'} = NOMINAL;
12364         $left_bond_strength{'||'}  = $right_bond_strength{'='};
12365
12366         # same thing for '//'
12367         $right_bond_strength{'//'} = NOMINAL;
12368         $left_bond_strength{'//'}  = $right_bond_strength{'='};
12369
12370         # set strength of && a little higher than ||
12371         $right_bond_strength{'&&'} = NOMINAL;
12372         $left_bond_strength{'&&'}  = $left_bond_strength{'||'} + 0.1;
12373
12374         $left_bond_strength{';'}  = VERY_STRONG;
12375         $right_bond_strength{';'} = VERY_WEAK;
12376         $left_bond_strength{'f'}  = VERY_STRONG;
12377
12378         # make right strength of for ';' a little less than '='
12379         # to make for contents break after the ';' to avoid this:
12380         #   for ( $j = $number_of_fields - 1 ; $j < $item_count ; $j +=
12381         #     $number_of_fields )
12382         # and make it weaker than ',' and 'and' too
12383         $right_bond_strength{'f'} = VERY_WEAK - 0.03;
12384
12385         # The strengths of ?/: should be somewhere between
12386         # an '=' and a quote (NOMINAL),
12387         # make strength of ':' slightly less than '?' to help
12388         # break long chains of ? : after the colons
12389         $left_bond_strength{':'}  = 0.4 * WEAK + 0.6 * NOMINAL;
12390         $right_bond_strength{':'} = NO_BREAK;
12391         $left_bond_strength{'?'}  = $left_bond_strength{':'} + 0.01;
12392         $right_bond_strength{'?'} = NO_BREAK;
12393
12394         $left_bond_strength{','}  = VERY_STRONG;
12395         $right_bond_strength{','} = VERY_WEAK;
12396
12397         # remaining digraphs and trigraphs not defined above
12398         @q                       = qw( :: <> ++ --);
12399         @left_bond_strength{@q}  = (WEAK) x scalar(@q);
12400         @right_bond_strength{@q} = (STRONG) x scalar(@q);
12401
12402         # Set bond strengths of certain keywords
12403         # make 'or', 'err', 'and' slightly weaker than a ','
12404         $left_bond_strength{'and'}  = VERY_WEAK - 0.01;
12405         $left_bond_strength{'or'}   = VERY_WEAK - 0.02;
12406         $left_bond_strength{'err'}  = VERY_WEAK - 0.02;
12407         $left_bond_strength{'xor'}  = NOMINAL;
12408         $right_bond_strength{'and'} = NOMINAL;
12409         $right_bond_strength{'or'}  = NOMINAL;
12410         $right_bond_strength{'err'} = NOMINAL;
12411         $right_bond_strength{'xor'} = STRONG;
12412
12413         #---------------------------------------------------------------
12414         # Bond Strength BEGIN Section 2.
12415         # Set binary rules for bond strengths between certain token types.
12416         #---------------------------------------------------------------
12417
12418         #  We have a little problem making tables which apply to the
12419         #  container tokens.  Here is a list of container tokens and
12420         #  their types:
12421         #
12422         #   type    tokens // meaning
12423         #      {    {, [, ( // indent
12424         #      }    }, ], ) // outdent
12425         #      [    [ // left non-structural [ (enclosing an array index)
12426         #      ]    ] // right non-structural square bracket
12427         #      (    ( // left non-structural paren
12428         #      )    ) // right non-structural paren
12429         #      L    { // left non-structural curly brace (enclosing a key)
12430         #      R    } // right non-structural curly brace
12431         #
12432         #  Some rules apply to token types and some to just the token
12433         #  itself.  We solve the problem by combining type and token into a
12434         #  new hash key for the container types.
12435         #
12436         #  If a rule applies to a token 'type' then we need to make rules
12437         #  for each of these 'type.token' combinations:
12438         #  Type    Type.Token
12439         #  {       {{, {[, {(
12440         #  [       [[
12441         #  (       ((
12442         #  L       L{
12443         #  }       }}, }], })
12444         #  ]       ]]
12445         #  )       ))
12446         #  R       R}
12447         #
12448         #  If a rule applies to a token then we need to make rules for
12449         #  these 'type.token' combinations:
12450         #  Token   Type.Token
12451         #  {       {{, L{
12452         #  [       {[, [[
12453         #  (       {(, ((
12454         #  }       }}, R}
12455         #  ]       }], ]]
12456         #  )       }), ))
12457
12458         # allow long lines before final { in an if statement, as in:
12459         #    if (..........
12460         #      ..........)
12461         #    {
12462         #
12463         # Otherwise, the line before the { tends to be too short.
12464
12465         $binary_bond_strength{'))'}{'{{'} = VERY_WEAK + 0.03;
12466         $binary_bond_strength{'(('}{'{{'} = NOMINAL;
12467
12468         # break on something like '} (', but keep this stronger than a ','
12469         # example is in 'howe.pl'
12470         $binary_bond_strength{'R}'}{'(('} = 0.8 * VERY_WEAK + 0.2 * WEAK;
12471         $binary_bond_strength{'}}'}{'(('} = 0.8 * VERY_WEAK + 0.2 * WEAK;
12472
12473         # keep matrix and hash indices together
12474         # but make them a little below STRONG to allow breaking open
12475         # something like {'some-word'}{'some-very-long-word'} at the }{
12476         # (bracebrk.t)
12477         $binary_bond_strength{']]'}{'[['} = 0.9 * STRONG + 0.1 * NOMINAL;
12478         $binary_bond_strength{']]'}{'L{'} = 0.9 * STRONG + 0.1 * NOMINAL;
12479         $binary_bond_strength{'R}'}{'[['} = 0.9 * STRONG + 0.1 * NOMINAL;
12480         $binary_bond_strength{'R}'}{'L{'} = 0.9 * STRONG + 0.1 * NOMINAL;
12481
12482         # increase strength to the point where a break in the following
12483         # will be after the opening paren rather than at the arrow:
12484         #    $a->$b($c);
12485         $binary_bond_strength{'i'}{'->'} = 1.45 * STRONG;
12486
12487         $binary_bond_strength{'))'}{'->'} = 0.1 * STRONG + 0.9 * NOMINAL;
12488         $binary_bond_strength{']]'}{'->'} = 0.1 * STRONG + 0.9 * NOMINAL;
12489         $binary_bond_strength{'})'}{'->'} = 0.1 * STRONG + 0.9 * NOMINAL;
12490         $binary_bond_strength{'}]'}{'->'} = 0.1 * STRONG + 0.9 * NOMINAL;
12491         $binary_bond_strength{'}}'}{'->'} = 0.1 * STRONG + 0.9 * NOMINAL;
12492         $binary_bond_strength{'R}'}{'->'} = 0.1 * STRONG + 0.9 * NOMINAL;
12493
12494         $binary_bond_strength{'))'}{'[['} = 0.2 * STRONG + 0.8 * NOMINAL;
12495         $binary_bond_strength{'})'}{'[['} = 0.2 * STRONG + 0.8 * NOMINAL;
12496         $binary_bond_strength{'))'}{'{['} = 0.2 * STRONG + 0.8 * NOMINAL;
12497         $binary_bond_strength{'})'}{'{['} = 0.2 * STRONG + 0.8 * NOMINAL;
12498
12499         #---------------------------------------------------------------
12500         # Binary NO_BREAK rules
12501         #---------------------------------------------------------------
12502
12503         # use strict requires that bare word and => not be separated
12504         $binary_bond_strength{'C'}{'=>'} = NO_BREAK;
12505         $binary_bond_strength{'U'}{'=>'} = NO_BREAK;
12506
12507         # Never break between a bareword and a following paren because
12508         # perl may give an error.  For example, if a break is placed
12509         # between 'to_filehandle' and its '(' the following line will
12510         # give a syntax error [Carp.pm]: my( $no) =fileno(
12511         # to_filehandle( $in)) ;
12512         $binary_bond_strength{'C'}{'(('} = NO_BREAK;
12513         $binary_bond_strength{'C'}{'{('} = NO_BREAK;
12514         $binary_bond_strength{'U'}{'(('} = NO_BREAK;
12515         $binary_bond_strength{'U'}{'{('} = NO_BREAK;
12516
12517         # use strict requires that bare word within braces not start new
12518         # line
12519         $binary_bond_strength{'L{'}{'w'} = NO_BREAK;
12520
12521         $binary_bond_strength{'w'}{'R}'} = NO_BREAK;
12522
12523         # use strict requires that bare word and => not be separated
12524         $binary_bond_strength{'w'}{'=>'} = NO_BREAK;
12525
12526         # use strict does not allow separating type info from trailing { }
12527         # testfile is readmail.pl
12528         $binary_bond_strength{'t'}{'L{'} = NO_BREAK;
12529         $binary_bond_strength{'i'}{'L{'} = NO_BREAK;
12530
12531         # As a defensive measure, do not break between a '(' and a
12532         # filehandle.  In some cases, this can cause an error.  For
12533         # example, the following program works:
12534         #    my $msg="hi!\n";
12535         #    print
12536         #    ( STDOUT
12537         #    $msg
12538         #    );
12539         #
12540         # But this program fails:
12541         #    my $msg="hi!\n";
12542         #    print
12543         #    (
12544         #    STDOUT
12545         #    $msg
12546         #    );
12547         #
12548         # This is normally only a problem with the 'extrude' option
12549         $binary_bond_strength{'(('}{'Y'} = NO_BREAK;
12550         $binary_bond_strength{'{('}{'Y'} = NO_BREAK;
12551
12552         # never break between sub name and opening paren
12553         $binary_bond_strength{'w'}{'(('} = NO_BREAK;
12554         $binary_bond_strength{'w'}{'{('} = NO_BREAK;
12555
12556         # keep '}' together with ';'
12557         $binary_bond_strength{'}}'}{';'} = NO_BREAK;
12558
12559         # Breaking before a ++ can cause perl to guess wrong. For
12560         # example the following line will cause a syntax error
12561         # with -extrude if we break between '$i' and '++' [fixstyle2]
12562         #   print( ( $i++ & 1 ) ? $_ : ( $change{$_} || $_ ) );
12563         $nobreak_lhs{'++'} = NO_BREAK;
12564
12565         # Do not break before a possible file handle
12566         $nobreak_lhs{'Z'} = NO_BREAK;
12567
12568         # use strict hates bare words on any new line.  For
12569         # example, a break before the underscore here provokes the
12570         # wrath of use strict:
12571         # if ( -r $fn && ( -s _ || $AllowZeroFilesize)) {
12572         $nobreak_rhs{'F'}      = NO_BREAK;
12573         $nobreak_rhs{'CORE::'} = NO_BREAK;
12574
12575         #---------------------------------------------------------------
12576         # Bond Strength BEGIN Section 3.
12577         # Define tables and values for applying a small bias to the above
12578         # values.
12579         #---------------------------------------------------------------
12580         # Adding a small 'bias' to strengths is a simple way to make a line
12581         # break at the first of a sequence of identical terms.  For
12582         # example, to force long string of conditional operators to break
12583         # with each line ending in a ':', we can add a small number to the
12584         # bond strength of each ':' (colon.t)
12585         @bias_tokens = qw( : && || f and or . );   # tokens which get bias
12586         $delta_bias  = 0.0001;                     # a very small strength level
12587         return;
12588
12589     } ## end sub initialize_bond_strength_hashes
12590
12591     sub set_bond_strengths {
12592
12593         # patch-its always ok to break at end of line
12594         $nobreak_to_go[$max_index_to_go] = 0;
12595
12596         # we start a new set of bias values for each line
12597         my %bias;
12598         @bias{@bias_tokens} = (0) x scalar(@bias_tokens);
12599         my $code_bias = -.01;    # bias for closing block braces
12600
12601         my $type  = 'b';
12602         my $token = ' ';
12603         my $last_type;
12604         my $last_nonblank_type  = $type;
12605         my $last_nonblank_token = $token;
12606         my $list_str            = $left_bond_strength{'?'};
12607
12608         my ( $block_type, $i_next, $i_next_nonblank, $next_nonblank_token,
12609             $next_nonblank_type, $next_token, $next_type, $total_nesting_depth,
12610         );
12611
12612         # main loop to compute bond strengths between each pair of tokens
12613         foreach my $i ( 0 .. $max_index_to_go ) {
12614             $last_type = $type;
12615             if ( $type ne 'b' ) {
12616                 $last_nonblank_type  = $type;
12617                 $last_nonblank_token = $token;
12618             }
12619             $type = $types_to_go[$i];
12620
12621             # strength on both sides of a blank is the same
12622             if ( $type eq 'b' && $last_type ne 'b' ) {
12623                 $bond_strength_to_go[$i] = $bond_strength_to_go[ $i - 1 ];
12624                 next;
12625             }
12626
12627             $token               = $tokens_to_go[$i];
12628             $block_type          = $block_type_to_go[$i];
12629             $i_next              = $i + 1;
12630             $next_type           = $types_to_go[$i_next];
12631             $next_token          = $tokens_to_go[$i_next];
12632             $total_nesting_depth = $nesting_depth_to_go[$i_next];
12633             $i_next_nonblank     = ( ( $next_type eq 'b' ) ? $i + 2 : $i + 1 );
12634             $next_nonblank_type  = $types_to_go[$i_next_nonblank];
12635             $next_nonblank_token = $tokens_to_go[$i_next_nonblank];
12636
12637             # We are computing the strength of the bond between the current
12638             # token and the NEXT token.
12639
12640             #---------------------------------------------------------------
12641             # Bond Strength Section 1:
12642             # First Approximation.
12643             # Use minimum of individual left and right tabulated bond
12644             # strengths.
12645             #---------------------------------------------------------------
12646             my $bsr = $right_bond_strength{$type};
12647             my $bsl = $left_bond_strength{$next_nonblank_type};
12648
12649             # define right bond strengths of certain keywords
12650             if ( $type eq 'k' && defined( $right_bond_strength{$token} ) ) {
12651                 $bsr = $right_bond_strength{$token};
12652             }
12653             elsif ( $token eq 'ne' or $token eq 'eq' ) {
12654                 $bsr = NOMINAL;
12655             }
12656
12657             # set terminal bond strength to the nominal value
12658             # this will cause good preceding breaks to be retained
12659             if ( $i_next_nonblank > $max_index_to_go ) {
12660                 $bsl = NOMINAL;
12661             }
12662
12663             # define right bond strengths of certain keywords
12664             if ( $next_nonblank_type eq 'k'
12665                 && defined( $left_bond_strength{$next_nonblank_token} ) )
12666             {
12667                 $bsl = $left_bond_strength{$next_nonblank_token};
12668             }
12669             elsif ($next_nonblank_token eq 'ne'
12670                 or $next_nonblank_token eq 'eq' )
12671             {
12672                 $bsl = NOMINAL;
12673             }
12674             elsif ( $is_lt_gt_le_ge{$next_nonblank_token} ) {
12675                 $bsl = 0.9 * NOMINAL + 0.1 * STRONG;
12676             }
12677
12678             # Use the minimum of the left and right strengths.  Note: it might
12679             # seem that we would want to keep a NO_BREAK if either token has
12680             # this value.  This didn't work, for example because in an arrow
12681             # list, it prevents the comma from separating from the following
12682             # bare word (which is probably quoted by its arrow).  So necessary
12683             # NO_BREAK's have to be handled as special cases in the final
12684             # section.
12685             if ( !defined($bsr) ) { $bsr = VERY_STRONG }
12686             if ( !defined($bsl) ) { $bsl = VERY_STRONG }
12687             my $bond_str   = ( $bsr < $bsl ) ? $bsr : $bsl;
12688             my $bond_str_1 = $bond_str;
12689
12690             #---------------------------------------------------------------
12691             # Bond Strength Section 2:
12692             # Apply hardwired rules..
12693             #---------------------------------------------------------------
12694
12695             # Patch to put terminal or clauses on a new line: Weaken the bond
12696             # at an || followed by die or similar keyword to make the terminal
12697             # or clause fall on a new line, like this:
12698             #
12699             #   my $class = shift
12700             #     || die "Cannot add broadcast:  No class identifier found";
12701             #
12702             # Otherwise the break will be at the previous '=' since the || and
12703             # = have the same starting strength and the or is biased, like
12704             # this:
12705             #
12706             # my $class =
12707             #   shift || die "Cannot add broadcast:  No class identifier found";
12708             #
12709             # In any case if the user places a break at either the = or the ||
12710             # it should remain there.
12711             if ( $type eq '||' || $type eq 'k' && $token eq 'or' ) {
12712                 if ( $next_nonblank_token =~ /^(die|confess|croak|warn)$/ ) {
12713                     if ( $want_break_before{$token} && $i > 0 ) {
12714                         $bond_strength_to_go[ $i - 1 ] -= $delta_bias;
12715                     }
12716                     else {
12717                         $bond_str -= $delta_bias;
12718                     }
12719                 }
12720             }
12721
12722             # good to break after end of code blocks
12723             if ( $type eq '}' && $block_type && $next_nonblank_type ne ';' ) {
12724
12725                 $bond_str = 0.5 * WEAK + 0.5 * VERY_WEAK + $code_bias;
12726                 $code_bias += $delta_bias;
12727             }
12728
12729             if ( $type eq 'k' ) {
12730
12731                 # allow certain control keywords to stand out
12732                 if (   $next_nonblank_type eq 'k'
12733                     && $is_last_next_redo_return{$token} )
12734                 {
12735                     $bond_str = 0.45 * WEAK + 0.55 * VERY_WEAK;
12736                 }
12737
12738                 # Don't break after keyword my.  This is a quick fix for a
12739                 # rare problem with perl. An example is this line from file
12740                 # Container.pm:
12741
12742                 # foreach my $question( Debian::DebConf::ConfigDb::gettree(
12743                 # $this->{'question'} ) )
12744
12745                 if ( $token eq 'my' ) {
12746                     $bond_str = NO_BREAK;
12747                 }
12748
12749             }
12750
12751             # good to break before 'if', 'unless', etc
12752             if ( $is_if_brace_follower{$next_nonblank_token} ) {
12753                 $bond_str = VERY_WEAK;
12754             }
12755
12756             if ( $next_nonblank_type eq 'k' && $type ne 'CORE::' ) {
12757
12758                 # FIXME: needs more testing
12759                 if ( $is_keyword_returning_list{$next_nonblank_token} ) {
12760                     $bond_str = $list_str if ( $bond_str > $list_str );
12761                 }
12762
12763                 # keywords like 'unless', 'if', etc, within statements
12764                 # make good breaks
12765                 if ( $is_good_keyword_breakpoint{$next_nonblank_token} ) {
12766                     $bond_str = VERY_WEAK / 1.05;
12767                 }
12768             }
12769
12770             # try not to break before a comma-arrow
12771             elsif ( $next_nonblank_type eq '=>' ) {
12772                 if ( $bond_str < STRONG ) { $bond_str = STRONG }
12773             }
12774
12775             #---------------------------------------------------------------
12776             # Additional hardwired NOBREAK rules
12777             #---------------------------------------------------------------
12778
12779             # map1.t -- correct for a quirk in perl
12780             if (   $token eq '('
12781                 && $next_nonblank_type eq 'i'
12782                 && $last_nonblank_type eq 'k'
12783                 && $is_sort_map_grep{$last_nonblank_token} )
12784
12785               #     /^(sort|map|grep)$/ )
12786             {
12787                 $bond_str = NO_BREAK;
12788             }
12789
12790             # extrude.t: do not break before paren at:
12791             #    -l pid_filename(
12792             if ( $last_nonblank_type eq 'F' && $next_nonblank_token eq '(' ) {
12793                 $bond_str = NO_BREAK;
12794             }
12795
12796             # in older version of perl, use strict can cause problems with
12797             # breaks before bare words following opening parens.  For example,
12798             # this will fail under older versions if a break is made between
12799             # '(' and 'MAIL': use strict; open( MAIL, "a long filename or
12800             # command"); close MAIL;
12801             if ( $type eq '{' ) {
12802
12803                 if ( $token eq '(' && $next_nonblank_type eq 'w' ) {
12804
12805                     # but it's fine to break if the word is followed by a '=>'
12806                     # or if it is obviously a sub call
12807                     my $i_next_next_nonblank = $i_next_nonblank + 1;
12808                     my $next_next_type = $types_to_go[$i_next_next_nonblank];
12809                     if (   $next_next_type eq 'b'
12810                         && $i_next_nonblank < $max_index_to_go )
12811                     {
12812                         $i_next_next_nonblank++;
12813                         $next_next_type = $types_to_go[$i_next_next_nonblank];
12814                     }
12815
12816                     # We'll check for an old breakpoint and keep a leading
12817                     # bareword if it was that way in the input file.
12818                     # Presumably it was ok that way.  For example, the
12819                     # following would remain unchanged:
12820                     #
12821                     # @months = (
12822                     #   January,   February, March,    April,
12823                     #   May,       June,     July,     August,
12824                     #   September, October,  November, December,
12825                     # );
12826                     #
12827                     # This should be sufficient:
12828                     if (
12829                         !$old_breakpoint_to_go[$i]
12830                         && (   $next_next_type eq ','
12831                             || $next_next_type eq '}' )
12832                       )
12833                     {
12834                         $bond_str = NO_BREAK;
12835                     }
12836                 }
12837             }
12838
12839             # Do not break between a possible filehandle and a ? or / and do
12840             # not introduce a break after it if there is no blank
12841             # (extrude.t)
12842             elsif ( $type eq 'Z' ) {
12843
12844                 # don't break..
12845                 if (
12846
12847                     # if there is no blank and we do not want one. Examples:
12848                     #    print $x++    # do not break after $x
12849                     #    print HTML"HELLO"   # break ok after HTML
12850                     (
12851                            $next_type ne 'b'
12852                         && defined( $want_left_space{$next_type} )
12853                         && $want_left_space{$next_type} == WS_NO
12854                     )
12855
12856                     # or we might be followed by the start of a quote
12857                     || $next_nonblank_type =~ /^[\/\?]$/
12858                   )
12859                 {
12860                     $bond_str = NO_BREAK;
12861                 }
12862             }
12863
12864             # Breaking before a ? before a quote can cause trouble if
12865             # they are not separated by a blank.
12866             # Example: a syntax error occurs if you break before the ? here
12867             #  my$logic=join$all?' && ':' || ',@regexps;
12868             # From: Professional_Perl_Programming_Code/multifind.pl
12869             if ( $next_nonblank_type eq '?' ) {
12870                 $bond_str = NO_BREAK
12871                   if ( $types_to_go[ $i_next_nonblank + 1 ] eq 'Q' );
12872             }
12873
12874             # Breaking before a . followed by a number
12875             # can cause trouble if there is no intervening space
12876             # Example: a syntax error occurs if you break before the .2 here
12877             #  $str .= pack($endian.2, ensurrogate($ord));
12878             # From: perl58/Unicode.pm
12879             elsif ( $next_nonblank_type eq '.' ) {
12880                 $bond_str = NO_BREAK
12881                   if ( $types_to_go[ $i_next_nonblank + 1 ] eq 'n' );
12882             }
12883
12884             my $bond_str_2 = $bond_str;
12885
12886             #---------------------------------------------------------------
12887             # End of hardwired rules
12888             #---------------------------------------------------------------
12889
12890             #---------------------------------------------------------------
12891             # Bond Strength Section 3:
12892             # Apply table rules. These have priority over the above
12893             # hardwired rules.
12894             #---------------------------------------------------------------
12895
12896             my $tabulated_bond_str;
12897             my $ltype = $type;
12898             my $rtype = $next_nonblank_type;
12899             if ( $token =~ /^[\(\[\{\)\]\}]/ ) { $ltype = $type . $token }
12900             if ( $next_nonblank_token =~ /^[\(\[\{\)\]\}]/ ) {
12901                 $rtype = $next_nonblank_type . $next_nonblank_token;
12902             }
12903
12904             if ( $binary_bond_strength{$ltype}{$rtype} ) {
12905                 $bond_str           = $binary_bond_strength{$ltype}{$rtype};
12906                 $tabulated_bond_str = $bond_str;
12907             }
12908
12909             if ( $nobreak_rhs{$ltype} || $nobreak_lhs{$rtype} ) {
12910                 $bond_str           = NO_BREAK;
12911                 $tabulated_bond_str = $bond_str;
12912             }
12913             my $bond_str_3 = $bond_str;
12914
12915             # If the hardwired rules conflict with the tabulated bond
12916             # strength then there is an inconsistency that should be fixed
12917             FORMATTER_DEBUG_FLAG_BOND_TABLES
12918               && $tabulated_bond_str
12919               && $bond_str_1
12920               && $bond_str_1 != $bond_str_2
12921               && $bond_str_2 != $tabulated_bond_str
12922               && do {
12923                 print STDERR
12924 "BOND_TABLES: ltype=$ltype rtype=$rtype $bond_str_1->$bond_str_2->$bond_str_3\n";
12925               };
12926
12927            #-----------------------------------------------------------------
12928            # Bond Strength Section 4:
12929            # Modify strengths of certain tokens which often occur in sequence
12930            # by adding a small bias to each one in turn so that the breaks
12931            # occur from left to right.
12932            #
12933            # Note that we only changing strengths by small amounts here,
12934            # and usually increasing, so we should not be altering any NO_BREAKs.
12935            # Other routines which check for NO_BREAKs will use a tolerance
12936            # of one to avoid any problem.
12937            #-----------------------------------------------------------------
12938
12939             # The bias tables use special keys
12940             my $left_key = bias_table_key( $type, $token );
12941             my $right_key =
12942               bias_table_key( $next_nonblank_type, $next_nonblank_token );
12943
12944             # add any bias set by sub scan_list at old comma break points.
12945             if ( $type eq ',' ) { $bond_str += $bond_strength_to_go[$i] }
12946
12947             # bias left token
12948             elsif ( defined( $bias{$left_key} ) ) {
12949                 if ( !$want_break_before{$left_key} ) {
12950                     $bias{$left_key} += $delta_bias;
12951                     $bond_str += $bias{$left_key};
12952                 }
12953             }
12954
12955             # bias right token
12956             if ( defined( $bias{$right_key} ) ) {
12957                 if ( $want_break_before{$right_key} ) {
12958
12959                     # for leading '.' align all but 'short' quotes; the idea
12960                     # is to not place something like "\n" on a single line.
12961                     if ( $right_key eq '.' ) {
12962                         unless (
12963                             $last_nonblank_type eq '.'
12964                             && (
12965                                 length($token) <=
12966                                 $rOpts_short_concatenation_item_length )
12967                             && ( !$is_closing_token{$token} )
12968                           )
12969                         {
12970                             $bias{$right_key} += $delta_bias;
12971                         }
12972                     }
12973                     else {
12974                         $bias{$right_key} += $delta_bias;
12975                     }
12976                     $bond_str += $bias{$right_key};
12977                 }
12978             }
12979             my $bond_str_4 = $bond_str;
12980
12981             #---------------------------------------------------------------
12982             # Bond Strength Section 5:
12983             # Fifth Approximation.
12984             # Take nesting depth into account by adding the nesting depth
12985             # to the bond strength.
12986             #---------------------------------------------------------------
12987             my $strength;
12988
12989             if ( defined($bond_str) && !$nobreak_to_go[$i] ) {
12990                 if ( $total_nesting_depth > 0 ) {
12991                     $strength = $bond_str + $total_nesting_depth;
12992                 }
12993                 else {
12994                     $strength = $bond_str;
12995                 }
12996             }
12997             else {
12998                 $strength = NO_BREAK;
12999             }
13000
13001             #---------------------------------------------------------------
13002             # Bond Strength Section 6:
13003             # Sixth Approximation. Welds.
13004             #---------------------------------------------------------------
13005
13006             # Do not allow a break within welds,
13007             if ( weld_len_right_to_go($i) ) { $strength = NO_BREAK }
13008
13009             # But encourage breaking after opening welded tokens
13010             elsif ( weld_len_left_to_go($i) && $is_opening_token{$token} ) {
13011                 $strength -= 1;
13012             }
13013
13014             # always break after side comment
13015             if ( $type eq '#' ) { $strength = 0 }
13016
13017             $bond_strength_to_go[$i] = $strength;
13018
13019             FORMATTER_DEBUG_FLAG_BOND && do {
13020                 my $str = substr( $token, 0, 15 );
13021                 $str .= ' ' x ( 16 - length($str) );
13022                 print STDOUT
13023 "BOND:  i=$i $str $type $next_nonblank_type depth=$total_nesting_depth strength=$bond_str_1 -> $bond_str_2 -> $bond_str_3 -> $bond_str_4 $bond_str -> $strength \n";
13024             };
13025         } ## end main loop
13026         return;
13027     } ## end sub set_bond_strengths
13028 }
13029
13030 sub pad_array_to_go {
13031
13032     # to simplify coding in scan_list and set_bond_strengths, it helps
13033     # to create some extra blank tokens at the end of the arrays
13034     $tokens_to_go[ $max_index_to_go + 1 ] = '';
13035     $tokens_to_go[ $max_index_to_go + 2 ] = '';
13036     $types_to_go[ $max_index_to_go + 1 ]  = 'b';
13037     $types_to_go[ $max_index_to_go + 2 ]  = 'b';
13038     $nesting_depth_to_go[ $max_index_to_go + 1 ] =
13039       $nesting_depth_to_go[$max_index_to_go];
13040
13041     #    /^[R\}\)\]]$/
13042     if ( $is_closing_type{ $types_to_go[$max_index_to_go] } ) {
13043         if ( $nesting_depth_to_go[$max_index_to_go] <= 0 ) {
13044
13045             # shouldn't happen:
13046             unless ( get_saw_brace_error() ) {
13047                 warning(
13048 "Program bug in scan_list: hit nesting error which should have been caught\n"
13049                 );
13050                 report_definite_bug();
13051             }
13052         }
13053         else {
13054             $nesting_depth_to_go[ $max_index_to_go + 1 ] -= 1;
13055         }
13056     }
13057
13058     #       /^[L\{\(\[]$/
13059     elsif ( $is_opening_type{ $types_to_go[$max_index_to_go] } ) {
13060         $nesting_depth_to_go[ $max_index_to_go + 1 ] += 1;
13061     }
13062     return;
13063 }
13064
13065 {    # begin scan_list
13066
13067     my (
13068         $block_type,               $current_depth,
13069         $depth,                    $i,
13070         $i_last_nonblank_token,    $last_colon_sequence_number,
13071         $last_nonblank_token,      $last_nonblank_type,
13072         $last_nonblank_block_type, $last_old_breakpoint_count,
13073         $minimum_depth,            $next_nonblank_block_type,
13074         $next_nonblank_token,      $next_nonblank_type,
13075         $old_breakpoint_count,     $starting_breakpoint_count,
13076         $starting_depth,           $token,
13077         $type,                     $type_sequence,
13078     );
13079
13080     my (
13081         @breakpoint_stack,              @breakpoint_undo_stack,
13082         @comma_index,                   @container_type,
13083         @identifier_count_stack,        @index_before_arrow,
13084         @interrupted_list,              @item_count_stack,
13085         @last_comma_index,              @last_dot_index,
13086         @last_nonblank_type,            @old_breakpoint_count_stack,
13087         @opening_structure_index_stack, @rfor_semicolon_list,
13088         @has_old_logical_breakpoints,   @rand_or_list,
13089         @i_equals,
13090     );
13091
13092     # routine to define essential variables when we go 'up' to
13093     # a new depth
13094     sub check_for_new_minimum_depth {
13095         my $depth = shift;
13096         if ( $depth < $minimum_depth ) {
13097
13098             $minimum_depth = $depth;
13099
13100             # these arrays need not retain values between calls
13101             $breakpoint_stack[$depth]              = $starting_breakpoint_count;
13102             $container_type[$depth]                = "";
13103             $identifier_count_stack[$depth]        = 0;
13104             $index_before_arrow[$depth]            = -1;
13105             $interrupted_list[$depth]              = 1;
13106             $item_count_stack[$depth]              = 0;
13107             $last_nonblank_type[$depth]            = "";
13108             $opening_structure_index_stack[$depth] = -1;
13109
13110             $breakpoint_undo_stack[$depth]       = undef;
13111             $comma_index[$depth]                 = undef;
13112             $last_comma_index[$depth]            = undef;
13113             $last_dot_index[$depth]              = undef;
13114             $old_breakpoint_count_stack[$depth]  = undef;
13115             $has_old_logical_breakpoints[$depth] = 0;
13116             $rand_or_list[$depth]                = [];
13117             $rfor_semicolon_list[$depth]         = [];
13118             $i_equals[$depth]                    = -1;
13119
13120             # these arrays must retain values between calls
13121             if ( !defined( $has_broken_sublist[$depth] ) ) {
13122                 $dont_align[$depth]         = 0;
13123                 $has_broken_sublist[$depth] = 0;
13124                 $want_comma_break[$depth]   = 0;
13125             }
13126         }
13127         return;
13128     }
13129
13130     # routine to decide which commas to break at within a container;
13131     # returns:
13132     #   $bp_count = number of comma breakpoints set
13133     #   $do_not_break_apart = a flag indicating if container need not
13134     #     be broken open
13135     sub set_comma_breakpoints {
13136
13137         my $dd                 = shift;
13138         my $bp_count           = 0;
13139         my $do_not_break_apart = 0;
13140
13141         # anything to do?
13142         if ( $item_count_stack[$dd] ) {
13143
13144             # handle commas not in containers...
13145             if ( $dont_align[$dd] ) {
13146                 do_uncontained_comma_breaks($dd);
13147             }
13148
13149             # handle commas within containers...
13150             else {
13151                 my $fbc = $forced_breakpoint_count;
13152
13153                 # always open comma lists not preceded by keywords,
13154                 # barewords, identifiers (that is, anything that doesn't
13155                 # look like a function call)
13156                 my $must_break_open = $last_nonblank_type[$dd] !~ /^[kwiU]$/;
13157
13158                 set_comma_breakpoints_do(
13159                     $dd,
13160                     $opening_structure_index_stack[$dd],
13161                     $i,
13162                     $item_count_stack[$dd],
13163                     $identifier_count_stack[$dd],
13164                     $comma_index[$dd],
13165                     $next_nonblank_type,
13166                     $container_type[$dd],
13167                     $interrupted_list[$dd],
13168                     \$do_not_break_apart,
13169                     $must_break_open,
13170                 );
13171                 $bp_count           = $forced_breakpoint_count - $fbc;
13172                 $do_not_break_apart = 0 if $must_break_open;
13173             }
13174         }
13175         return ( $bp_count, $do_not_break_apart );
13176     }
13177
13178     sub do_uncontained_comma_breaks {
13179
13180         # Handle commas not in containers...
13181         # This is a catch-all routine for commas that we
13182         # don't know what to do with because the don't fall
13183         # within containers.  We will bias the bond strength
13184         # to break at commas which ended lines in the input
13185         # file.  This usually works better than just trying
13186         # to put as many items on a line as possible.  A
13187         # downside is that if the input file is garbage it
13188         # won't work very well. However, the user can always
13189         # prevent following the old breakpoints with the
13190         # -iob flag.
13191         my $dd                    = shift;
13192         my $bias                  = -.01;
13193         my $old_comma_break_count = 0;
13194         foreach my $ii ( @{ $comma_index[$dd] } ) {
13195             if ( $old_breakpoint_to_go[$ii] ) {
13196                 $old_comma_break_count++;
13197                 $bond_strength_to_go[$ii] = $bias;
13198
13199                 # reduce bias magnitude to force breaks in order
13200                 $bias *= 0.99;
13201             }
13202         }
13203
13204         # Also put a break before the first comma if
13205         # (1) there was a break there in the input, and
13206         # (2) there was exactly one old break before the first comma break
13207         # (3) OLD: there are multiple old comma breaks
13208         # (3) NEW: there are one or more old comma breaks (see return example)
13209         #
13210         # For example, we will follow the user and break after
13211         # 'print' in this snippet:
13212         #    print
13213         #      "conformability (Not the same dimension)\n",
13214         #      "\t", $have, " is ", text_unit($hu), "\n",
13215         #      "\t", $want, " is ", text_unit($wu), "\n",
13216         #      ;
13217         #
13218         # Another example, just one comma, where we will break after
13219         # the return:
13220         #  return
13221         #    $x * cos($a) - $y * sin($a),
13222         #    $x * sin($a) + $y * cos($a);
13223
13224         # Breaking a print statement:
13225         # print SAVEOUT
13226         #   ( $? & 127 ) ? " (SIG#" . ( $? & 127 ) . ")" : "",
13227         #   ( $? & 128 ) ? " -- core dumped" : "", "\n";
13228         #
13229         #  But we will not force a break after the opening paren here
13230         #  (causes a blinker):
13231         #        $heap->{stream}->set_output_filter(
13232         #            poe::filter::reference->new('myotherfreezer') ),
13233         #          ;
13234         #
13235         my $i_first_comma = $comma_index[$dd]->[0];
13236         if ( $old_breakpoint_to_go[$i_first_comma] ) {
13237             my $level_comma = $levels_to_go[$i_first_comma];
13238             my $ibreak      = -1;
13239             my $obp_count   = 0;
13240             for ( my $ii = $i_first_comma - 1 ; $ii >= 0 ; $ii -= 1 ) {
13241                 if ( $old_breakpoint_to_go[$ii] ) {
13242                     $obp_count++;
13243                     last if ( $obp_count > 1 );
13244                     $ibreak = $ii
13245                       if ( $levels_to_go[$ii] == $level_comma );
13246                 }
13247             }
13248
13249             # Changed rule from multiple old commas to just one here:
13250             if ( $ibreak >= 0 && $obp_count == 1 && $old_comma_break_count > 0 )
13251             {
13252                 # Do not to break before an opening token because
13253                 # it can lead to "blinkers".
13254                 my $ibreakm = $ibreak;
13255                 $ibreakm-- if ( $types_to_go[$ibreakm] eq 'b' );
13256                 if ( $ibreakm >= 0 && $types_to_go[$ibreakm] !~ /^[\(\{\[L]$/ )
13257                 {
13258                     set_forced_breakpoint($ibreak);
13259                 }
13260             }
13261         }
13262         return;
13263     }
13264
13265     my %is_logical_container;
13266
13267     BEGIN {
13268         my @q = qw# if elsif unless while and or err not && | || ? : ! #;
13269         @is_logical_container{@q} = (1) x scalar(@q);
13270     }
13271
13272     sub set_for_semicolon_breakpoints {
13273         my $dd = shift;
13274         foreach ( @{ $rfor_semicolon_list[$dd] } ) {
13275             set_forced_breakpoint($_);
13276         }
13277         return;
13278     }
13279
13280     sub set_logical_breakpoints {
13281         my $dd = shift;
13282         if (
13283                $item_count_stack[$dd] == 0
13284             && $is_logical_container{ $container_type[$dd] }
13285
13286             || $has_old_logical_breakpoints[$dd]
13287           )
13288         {
13289
13290             # Look for breaks in this order:
13291             # 0   1    2   3
13292             # or  and  ||  &&
13293             foreach my $i ( 0 .. 3 ) {
13294                 if ( $rand_or_list[$dd][$i] ) {
13295                     foreach ( @{ $rand_or_list[$dd][$i] } ) {
13296                         set_forced_breakpoint($_);
13297                     }
13298
13299                     # break at any 'if' and 'unless' too
13300                     foreach ( @{ $rand_or_list[$dd][4] } ) {
13301                         set_forced_breakpoint($_);
13302                     }
13303                     $rand_or_list[$dd] = [];
13304                     last;
13305                 }
13306             }
13307         }
13308         return;
13309     }
13310
13311     sub is_unbreakable_container {
13312
13313         # never break a container of one of these types
13314         # because bad things can happen (map1.t)
13315         my $dd = shift;
13316         return $is_sort_map_grep{ $container_type[$dd] };
13317     }
13318
13319     sub scan_list {
13320
13321         # This routine is responsible for setting line breaks for all lists,
13322         # so that hierarchical structure can be displayed and so that list
13323         # items can be vertically aligned.  The output of this routine is
13324         # stored in the array @forced_breakpoint_to_go, which is used to set
13325         # final breakpoints.
13326
13327         $starting_depth = $nesting_depth_to_go[0];
13328
13329         $block_type                 = ' ';
13330         $current_depth              = $starting_depth;
13331         $i                          = -1;
13332         $last_colon_sequence_number = -1;
13333         $last_nonblank_token        = ';';
13334         $last_nonblank_type         = ';';
13335         $last_nonblank_block_type   = ' ';
13336         $last_old_breakpoint_count  = 0;
13337         $minimum_depth = $current_depth + 1;    # forces update in check below
13338         $old_breakpoint_count      = 0;
13339         $starting_breakpoint_count = $forced_breakpoint_count;
13340         $token                     = ';';
13341         $type                      = ';';
13342         $type_sequence             = '';
13343
13344         my $total_depth_variation = 0;
13345         my $i_old_assignment_break;
13346         my $depth_last = $starting_depth;
13347
13348         check_for_new_minimum_depth($current_depth);
13349
13350         my $is_long_line = excess_line_length( 0, $max_index_to_go ) > 0;
13351         my $want_previous_breakpoint = -1;
13352
13353         my $saw_good_breakpoint;
13354         my $i_line_end   = -1;
13355         my $i_line_start = -1;
13356
13357         # loop over all tokens in this batch
13358         while ( ++$i <= $max_index_to_go ) {
13359             if ( $type ne 'b' ) {
13360                 $i_last_nonblank_token    = $i - 1;
13361                 $last_nonblank_type       = $type;
13362                 $last_nonblank_token      = $token;
13363                 $last_nonblank_block_type = $block_type;
13364             } ## end if ( $type ne 'b' )
13365             $type          = $types_to_go[$i];
13366             $block_type    = $block_type_to_go[$i];
13367             $token         = $tokens_to_go[$i];
13368             $type_sequence = $type_sequence_to_go[$i];
13369             my $next_type       = $types_to_go[ $i + 1 ];
13370             my $next_token      = $tokens_to_go[ $i + 1 ];
13371             my $i_next_nonblank = ( ( $next_type eq 'b' ) ? $i + 2 : $i + 1 );
13372             $next_nonblank_type       = $types_to_go[$i_next_nonblank];
13373             $next_nonblank_token      = $tokens_to_go[$i_next_nonblank];
13374             $next_nonblank_block_type = $block_type_to_go[$i_next_nonblank];
13375
13376             # set break if flag was set
13377             if ( $want_previous_breakpoint >= 0 ) {
13378                 set_forced_breakpoint($want_previous_breakpoint);
13379                 $want_previous_breakpoint = -1;
13380             }
13381
13382             $last_old_breakpoint_count = $old_breakpoint_count;
13383             if ( $old_breakpoint_to_go[$i] ) {
13384                 $i_line_end   = $i;
13385                 $i_line_start = $i_next_nonblank;
13386
13387                 $old_breakpoint_count++;
13388
13389                 # Break before certain keywords if user broke there and
13390                 # this is a 'safe' break point. The idea is to retain
13391                 # any preferred breaks for sequential list operations,
13392                 # like a schwartzian transform.
13393                 if ($rOpts_break_at_old_keyword_breakpoints) {
13394                     if (
13395                            $next_nonblank_type eq 'k'
13396                         && $is_keyword_returning_list{$next_nonblank_token}
13397                         && (   $type =~ /^[=\)\]\}Riw]$/
13398                             || $type eq 'k'
13399                             && $is_keyword_returning_list{$token} )
13400                       )
13401                     {
13402
13403                         # we actually have to set this break next time through
13404                         # the loop because if we are at a closing token (such
13405                         # as '}') which forms a one-line block, this break might
13406                         # get undone.
13407                         $want_previous_breakpoint = $i;
13408                     } ## end if ( $next_nonblank_type...)
13409                 } ## end if ($rOpts_break_at_old_keyword_breakpoints)
13410
13411                 # Break before attributes if user broke there
13412                 if ($rOpts_break_at_old_attribute_breakpoints) {
13413                     if ( $next_nonblank_type eq 'A' ) {
13414                         $want_previous_breakpoint = $i;
13415                     }
13416                 }
13417
13418                 # remember an = break as possible good break point
13419                 if ( $is_assignment{$type} ) {
13420                     $i_old_assignment_break = $i;
13421                 }
13422                 elsif ( $is_assignment{$next_nonblank_type} ) {
13423                     $i_old_assignment_break = $i_next_nonblank;
13424                 }
13425             } ## end if ( $old_breakpoint_to_go...)
13426
13427             next if ( $type eq 'b' );
13428             $depth = $nesting_depth_to_go[ $i + 1 ];
13429
13430             $total_depth_variation += abs( $depth - $depth_last );
13431             $depth_last = $depth;
13432
13433             # safety check - be sure we always break after a comment
13434             # Shouldn't happen .. an error here probably means that the
13435             # nobreak flag did not get turned off correctly during
13436             # formatting.
13437             if ( $type eq '#' ) {
13438                 if ( $i != $max_index_to_go ) {
13439                     warning(
13440 "Non-fatal program bug: backup logic needed to break after a comment\n"
13441                     );
13442                     report_definite_bug();
13443                     $nobreak_to_go[$i] = 0;
13444                     set_forced_breakpoint($i);
13445                 } ## end if ( $i != $max_index_to_go)
13446             } ## end if ( $type eq '#' )
13447
13448             # Force breakpoints at certain tokens in long lines.
13449             # Note that such breakpoints will be undone later if these tokens
13450             # are fully contained within parens on a line.
13451             if (
13452
13453                 # break before a keyword within a line
13454                 $type eq 'k'
13455                 && $i > 0
13456
13457                 # if one of these keywords:
13458                 && $token =~ /^(if|unless|while|until|for)$/
13459
13460                 # but do not break at something like '1 while'
13461                 && ( $last_nonblank_type ne 'n' || $i > 2 )
13462
13463                 # and let keywords follow a closing 'do' brace
13464                 && $last_nonblank_block_type ne 'do'
13465
13466                 && (
13467                     $is_long_line
13468
13469                     # or container is broken (by side-comment, etc)
13470                     || (   $next_nonblank_token eq '('
13471                         && $mate_index_to_go[$i_next_nonblank] < $i )
13472                 )
13473               )
13474             {
13475                 set_forced_breakpoint( $i - 1 );
13476             } ## end if ( $type eq 'k' && $i...)
13477
13478             # remember locations of -> if this is a pre-broken method chain
13479             if ( $type eq '->' ) {
13480                 if ($rOpts_break_at_old_method_breakpoints) {
13481
13482                     # Case 1: look for lines with leading pointers
13483                     if ( $i == $i_line_start ) {
13484                         set_forced_breakpoint( $i - 1 );
13485                     }
13486
13487                     # Case 2: look for cuddled pointer calls
13488                     else {
13489
13490                         # look for old lines with leading ')->' or ') ->'
13491                         # and, when found, force a break before the
13492                         # opening paren and after the previous closing paren.
13493                         if (
13494                             $types_to_go[$i_line_start] eq '}'
13495                             && (   $i == $i_line_start + 1
13496                                 || $i == $i_line_start + 2
13497                                 && $types_to_go[ $i - 1 ] eq 'b' )
13498                           )
13499                         {
13500                             set_forced_breakpoint( $i_line_start - 1 );
13501                             set_forced_breakpoint(
13502                                 $mate_index_to_go[$i_line_start] );
13503                         }
13504                     }
13505                 }
13506             } ## end if ( $type eq '->' )
13507
13508             # remember locations of '||'  and '&&' for possible breaks if we
13509             # decide this is a long logical expression.
13510             elsif ( $type eq '||' ) {
13511                 push @{ $rand_or_list[$depth][2] }, $i;
13512                 ++$has_old_logical_breakpoints[$depth]
13513                   if ( ( $i == $i_line_start || $i == $i_line_end )
13514                     && $rOpts_break_at_old_logical_breakpoints );
13515             } ## end elsif ( $type eq '||' )
13516             elsif ( $type eq '&&' ) {
13517                 push @{ $rand_or_list[$depth][3] }, $i;
13518                 ++$has_old_logical_breakpoints[$depth]
13519                   if ( ( $i == $i_line_start || $i == $i_line_end )
13520                     && $rOpts_break_at_old_logical_breakpoints );
13521             } ## end elsif ( $type eq '&&' )
13522             elsif ( $type eq 'f' ) {
13523                 push @{ $rfor_semicolon_list[$depth] }, $i;
13524             }
13525             elsif ( $type eq 'k' ) {
13526                 if ( $token eq 'and' ) {
13527                     push @{ $rand_or_list[$depth][1] }, $i;
13528                     ++$has_old_logical_breakpoints[$depth]
13529                       if ( ( $i == $i_line_start || $i == $i_line_end )
13530                         && $rOpts_break_at_old_logical_breakpoints );
13531                 } ## end if ( $token eq 'and' )
13532
13533                 # break immediately at 'or's which are probably not in a logical
13534                 # block -- but we will break in logical breaks below so that
13535                 # they do not add to the forced_breakpoint_count
13536                 elsif ( $token eq 'or' ) {
13537                     push @{ $rand_or_list[$depth][0] }, $i;
13538                     ++$has_old_logical_breakpoints[$depth]
13539                       if ( ( $i == $i_line_start || $i == $i_line_end )
13540                         && $rOpts_break_at_old_logical_breakpoints );
13541                     if ( $is_logical_container{ $container_type[$depth] } ) {
13542                     }
13543                     else {
13544                         if ($is_long_line) { set_forced_breakpoint($i) }
13545                         elsif ( ( $i == $i_line_start || $i == $i_line_end )
13546                             && $rOpts_break_at_old_logical_breakpoints )
13547                         {
13548                             $saw_good_breakpoint = 1;
13549                         }
13550                     } ## end else [ if ( $is_logical_container...)]
13551                 } ## end elsif ( $token eq 'or' )
13552                 elsif ( $token eq 'if' || $token eq 'unless' ) {
13553                     push @{ $rand_or_list[$depth][4] }, $i;
13554                     if ( ( $i == $i_line_start || $i == $i_line_end )
13555                         && $rOpts_break_at_old_logical_breakpoints )
13556                     {
13557                         set_forced_breakpoint($i);
13558                     }
13559                 } ## end elsif ( $token eq 'if' ||...)
13560             } ## end elsif ( $type eq 'k' )
13561             elsif ( $is_assignment{$type} ) {
13562                 $i_equals[$depth] = $i;
13563             }
13564
13565             if ($type_sequence) {
13566
13567                 # handle any postponed closing breakpoints
13568                 if ( $token =~ /^[\)\]\}\:]$/ ) {
13569                     if ( $type eq ':' ) {
13570                         $last_colon_sequence_number = $type_sequence;
13571
13572                         # retain break at a ':' line break
13573                         if ( ( $i == $i_line_start || $i == $i_line_end )
13574                             && $rOpts_break_at_old_ternary_breakpoints )
13575                         {
13576
13577                             set_forced_breakpoint($i);
13578
13579                             # break at previous '='
13580                             if ( $i_equals[$depth] > 0 ) {
13581                                 set_forced_breakpoint( $i_equals[$depth] );
13582                                 $i_equals[$depth] = -1;
13583                             }
13584                         } ## end if ( ( $i == $i_line_start...))
13585                     } ## end if ( $type eq ':' )
13586                     if ( defined( $postponed_breakpoint{$type_sequence} ) ) {
13587                         my $inc = ( $type eq ':' ) ? 0 : 1;
13588                         set_forced_breakpoint( $i - $inc );
13589                         delete $postponed_breakpoint{$type_sequence};
13590                     }
13591                 } ## end if ( $token =~ /^[\)\]\}\:]$/[{[(])
13592
13593                 # set breaks at ?/: if they will get separated (and are
13594                 # not a ?/: chain), or if the '?' is at the end of the
13595                 # line
13596                 elsif ( $token eq '?' ) {
13597                     my $i_colon = $mate_index_to_go[$i];
13598                     if (
13599                         $i_colon <= 0  # the ':' is not in this batch
13600                         || $i == 0     # this '?' is the first token of the line
13601                         || $i ==
13602                         $max_index_to_go    # or this '?' is the last token
13603                       )
13604                     {
13605
13606                         # don't break at a '?' if preceded by ':' on
13607                         # this line of previous ?/: pair on this line.
13608                         # This is an attempt to preserve a chain of ?/:
13609                         # expressions (elsif2.t).  And don't break if
13610                         # this has a side comment.
13611                         set_forced_breakpoint($i)
13612                           unless (
13613                             $type_sequence == (
13614                                 $last_colon_sequence_number +
13615                                   TYPE_SEQUENCE_INCREMENT
13616                             )
13617                             || $tokens_to_go[$max_index_to_go] eq '#'
13618                           );
13619                         set_closing_breakpoint($i);
13620                     } ## end if ( $i_colon <= 0  ||...)
13621                 } ## end elsif ( $token eq '?' )
13622             } ## end if ($type_sequence)
13623
13624 #print "LISTX sees: i=$i type=$type  tok=$token  block=$block_type depth=$depth\n";
13625
13626             #------------------------------------------------------------
13627             # Handle Increasing Depth..
13628             #
13629             # prepare for a new list when depth increases
13630             # token $i is a '(','{', or '['
13631             #------------------------------------------------------------
13632             if ( $depth > $current_depth ) {
13633
13634                 $breakpoint_stack[$depth]       = $forced_breakpoint_count;
13635                 $breakpoint_undo_stack[$depth]  = $forced_breakpoint_undo_count;
13636                 $has_broken_sublist[$depth]     = 0;
13637                 $identifier_count_stack[$depth] = 0;
13638                 $index_before_arrow[$depth]     = -1;
13639                 $interrupted_list[$depth]       = 0;
13640                 $item_count_stack[$depth]       = 0;
13641                 $last_comma_index[$depth]       = undef;
13642                 $last_dot_index[$depth]         = undef;
13643                 $last_nonblank_type[$depth]     = $last_nonblank_type;
13644                 $old_breakpoint_count_stack[$depth]    = $old_breakpoint_count;
13645                 $opening_structure_index_stack[$depth] = $i;
13646                 $rand_or_list[$depth]                  = [];
13647                 $rfor_semicolon_list[$depth]           = [];
13648                 $i_equals[$depth]                      = -1;
13649                 $want_comma_break[$depth]              = 0;
13650                 $container_type[$depth] =
13651                   ( $last_nonblank_type =~ /^(k|=>|&&|\|\||\?|\:|\.)$/ )
13652                   ? $last_nonblank_token
13653                   : "";
13654                 $has_old_logical_breakpoints[$depth] = 0;
13655
13656                 # if line ends here then signal closing token to break
13657                 if ( $next_nonblank_type eq 'b' || $next_nonblank_type eq '#' )
13658                 {
13659                     set_closing_breakpoint($i);
13660                 }
13661
13662                 # Not all lists of values should be vertically aligned..
13663                 $dont_align[$depth] =
13664
13665                   # code BLOCKS are handled at a higher level
13666                   ( $block_type ne "" )
13667
13668                   # certain paren lists
13669                   || ( $type eq '(' ) && (
13670
13671                     # it does not usually look good to align a list of
13672                     # identifiers in a parameter list, as in:
13673                     #    my($var1, $var2, ...)
13674                     # (This test should probably be refined, for now I'm just
13675                     # testing for any keyword)
13676                     ( $last_nonblank_type eq 'k' )
13677
13678                     # a trailing '(' usually indicates a non-list
13679                     || ( $next_nonblank_type eq '(' )
13680                   );
13681
13682                 # patch to outdent opening brace of long if/for/..
13683                 # statements (like this one).  See similar coding in
13684                 # set_continuation breaks.  We have also catch it here for
13685                 # short line fragments which otherwise will not go through
13686                 # set_continuation_breaks.
13687                 if (
13688                     $block_type
13689
13690                     # if we have the ')' but not its '(' in this batch..
13691                     && ( $last_nonblank_token eq ')' )
13692                     && $mate_index_to_go[$i_last_nonblank_token] < 0
13693
13694                     # and user wants brace to left
13695                     && !$rOpts->{'opening-brace-always-on-right'}
13696
13697                     && ( $type eq '{' )     # should be true
13698                     && ( $token eq '{' )    # should be true
13699                   )
13700                 {
13701                     set_forced_breakpoint( $i - 1 );
13702                 } ## end if ( $block_type && ( ...))
13703             } ## end if ( $depth > $current_depth)
13704
13705             #------------------------------------------------------------
13706             # Handle Decreasing Depth..
13707             #
13708             # finish off any old list when depth decreases
13709             # token $i is a ')','}', or ']'
13710             #------------------------------------------------------------
13711             elsif ( $depth < $current_depth ) {
13712
13713                 check_for_new_minimum_depth($depth);
13714
13715                 # force all outer logical containers to break after we see on
13716                 # old breakpoint
13717                 $has_old_logical_breakpoints[$depth] ||=
13718                   $has_old_logical_breakpoints[$current_depth];
13719
13720                 # Patch to break between ') {' if the paren list is broken.
13721                 # There is similar logic in set_continuation_breaks for
13722                 # non-broken lists.
13723                 if (   $token eq ')'
13724                     && $next_nonblank_block_type
13725                     && $interrupted_list[$current_depth]
13726                     && $next_nonblank_type eq '{'
13727                     && !$rOpts->{'opening-brace-always-on-right'} )
13728                 {
13729                     set_forced_breakpoint($i);
13730                 } ## end if ( $token eq ')' && ...
13731
13732 #print "LISTY sees: i=$i type=$type  tok=$token  block=$block_type depth=$depth next=$next_nonblank_type next_block=$next_nonblank_block_type inter=$interrupted_list[$current_depth]\n";
13733
13734                 # set breaks at commas if necessary
13735                 my ( $bp_count, $do_not_break_apart ) =
13736                   set_comma_breakpoints($current_depth);
13737
13738                 my $i_opening = $opening_structure_index_stack[$current_depth];
13739                 my $saw_opening_structure = ( $i_opening >= 0 );
13740
13741                 # this term is long if we had to break at interior commas..
13742                 my $is_long_term = $bp_count > 0;
13743
13744                 # If this is a short container with one or more comma arrows,
13745                 # then we will mark it as a long term to open it if requested.
13746                 # $rOpts_comma_arrow_breakpoints =
13747                 #    0 - open only if comma precedes closing brace
13748                 #    1 - stable: except for one line blocks
13749                 #    2 - try to form 1 line blocks
13750                 #    3 - ignore =>
13751                 #    4 - always open up if vt=0
13752                 #    5 - stable: even for one line blocks if vt=0
13753                 if (  !$is_long_term
13754                     && $tokens_to_go[$i_opening] =~ /^[\(\{\[]$/
13755                     && $index_before_arrow[ $depth + 1 ] > 0
13756                     && !$opening_vertical_tightness{ $tokens_to_go[$i_opening] }
13757                   )
13758                 {
13759                     $is_long_term = $rOpts_comma_arrow_breakpoints == 4
13760                       || ( $rOpts_comma_arrow_breakpoints == 0
13761                         && $last_nonblank_token eq ',' )
13762                       || ( $rOpts_comma_arrow_breakpoints == 5
13763                         && $old_breakpoint_to_go[$i_opening] );
13764                 } ## end if ( !$is_long_term &&...)
13765
13766                 # mark term as long if the length between opening and closing
13767                 # parens exceeds allowed line length
13768                 if ( !$is_long_term && $saw_opening_structure ) {
13769                     my $i_opening_minus = find_token_starting_list($i_opening);
13770
13771                     # Note: we have to allow for one extra space after a
13772                     # closing token so that we do not strand a comma or
13773                     # semicolon, hence the '>=' here (oneline.t)
13774                     # Note: we ignore left weld lengths here for best results
13775                     $is_long_term =
13776                       excess_line_length( $i_opening_minus, $i, 1 ) >= 0;
13777                 } ## end if ( !$is_long_term &&...)
13778
13779                 # We've set breaks after all comma-arrows.  Now we have to
13780                 # undo them if this can be a one-line block
13781                 # (the only breakpoints set will be due to comma-arrows)
13782                 if (
13783
13784                     # user doesn't require breaking after all comma-arrows
13785                     ( $rOpts_comma_arrow_breakpoints != 0 )
13786                     && ( $rOpts_comma_arrow_breakpoints != 4 )
13787
13788                     # and if the opening structure is in this batch
13789                     && $saw_opening_structure
13790
13791                     # and either on the same old line
13792                     && (
13793                         $old_breakpoint_count_stack[$current_depth] ==
13794                         $last_old_breakpoint_count
13795
13796                         # or user wants to form long blocks with arrows
13797                         || $rOpts_comma_arrow_breakpoints == 2
13798                     )
13799
13800                   # and we made some breakpoints between the opening and closing
13801                     && ( $breakpoint_undo_stack[$current_depth] <
13802                         $forced_breakpoint_undo_count )
13803
13804                     # and this block is short enough to fit on one line
13805                     # Note: use < because need 1 more space for possible comma
13806                     && !$is_long_term
13807
13808                   )
13809                 {
13810                     undo_forced_breakpoint_stack(
13811                         $breakpoint_undo_stack[$current_depth] );
13812                 } ## end if ( ( $rOpts_comma_arrow_breakpoints...))
13813
13814                 # now see if we have any comma breakpoints left
13815                 my $has_comma_breakpoints =
13816                   ( $breakpoint_stack[$current_depth] !=
13817                       $forced_breakpoint_count );
13818
13819                 # update broken-sublist flag of the outer container
13820                 $has_broken_sublist[$depth] =
13821                      $has_broken_sublist[$depth]
13822                   || $has_broken_sublist[$current_depth]
13823                   || $is_long_term
13824                   || $has_comma_breakpoints;
13825
13826 # Having come to the closing ')', '}', or ']', now we have to decide if we
13827 # should 'open up' the structure by placing breaks at the opening and
13828 # closing containers.  This is a tricky decision.  Here are some of the
13829 # basic considerations:
13830 #
13831 # -If this is a BLOCK container, then any breakpoints will have already
13832 # been set (and according to user preferences), so we need do nothing here.
13833 #
13834 # -If we have a comma-separated list for which we can align the list items,
13835 # then we need to do so because otherwise the vertical aligner cannot
13836 # currently do the alignment.
13837 #
13838 # -If this container does itself contain a container which has been broken
13839 # open, then it should be broken open to properly show the structure.
13840 #
13841 # -If there is nothing to align, and no other reason to break apart,
13842 # then do not do it.
13843 #
13844 # We will not break open the parens of a long but 'simple' logical expression.
13845 # For example:
13846 #
13847 # This is an example of a simple logical expression and its formatting:
13848 #
13849 #     if ( $bigwasteofspace1 && $bigwasteofspace2
13850 #         || $bigwasteofspace3 && $bigwasteofspace4 )
13851 #
13852 # Most people would prefer this than the 'spacey' version:
13853 #
13854 #     if (
13855 #         $bigwasteofspace1 && $bigwasteofspace2
13856 #         || $bigwasteofspace3 && $bigwasteofspace4
13857 #     )
13858 #
13859 # To illustrate the rules for breaking logical expressions, consider:
13860 #
13861 #             FULLY DENSE:
13862 #             if ( $opt_excl
13863 #                 and ( exists $ids_excl_uc{$id_uc}
13864 #                     or grep $id_uc =~ /$_/, @ids_excl_uc ))
13865 #
13866 # This is on the verge of being difficult to read.  The current default is to
13867 # open it up like this:
13868 #
13869 #             DEFAULT:
13870 #             if (
13871 #                 $opt_excl
13872 #                 and ( exists $ids_excl_uc{$id_uc}
13873 #                     or grep $id_uc =~ /$_/, @ids_excl_uc )
13874 #               )
13875 #
13876 # This is a compromise which tries to avoid being too dense and to spacey.
13877 # A more spaced version would be:
13878 #
13879 #             SPACEY:
13880 #             if (
13881 #                 $opt_excl
13882 #                 and (
13883 #                     exists $ids_excl_uc{$id_uc}
13884 #                     or grep $id_uc =~ /$_/, @ids_excl_uc
13885 #                 )
13886 #               )
13887 #
13888 # Some people might prefer the spacey version -- an option could be added.  The
13889 # innermost expression contains a long block '( exists $ids_...  ')'.
13890 #
13891 # Here is how the logic goes: We will force a break at the 'or' that the
13892 # innermost expression contains, but we will not break apart its opening and
13893 # closing containers because (1) it contains no multi-line sub-containers itself,
13894 # and (2) there is no alignment to be gained by breaking it open like this
13895 #
13896 #             and (
13897 #                 exists $ids_excl_uc{$id_uc}
13898 #                 or grep $id_uc =~ /$_/, @ids_excl_uc
13899 #             )
13900 #
13901 # (although this looks perfectly ok and might be good for long expressions).  The
13902 # outer 'if' container, though, contains a broken sub-container, so it will be
13903 # broken open to avoid too much density.  Also, since it contains no 'or's, there
13904 # will be a forced break at its 'and'.
13905
13906                 # set some flags telling something about this container..
13907                 my $is_simple_logical_expression = 0;
13908                 if (   $item_count_stack[$current_depth] == 0
13909                     && $saw_opening_structure
13910                     && $tokens_to_go[$i_opening] eq '('
13911                     && $is_logical_container{ $container_type[$current_depth] }
13912                   )
13913                 {
13914
13915                     # This seems to be a simple logical expression with
13916                     # no existing breakpoints.  Set a flag to prevent
13917                     # opening it up.
13918                     if ( !$has_comma_breakpoints ) {
13919                         $is_simple_logical_expression = 1;
13920                     }
13921
13922                     # This seems to be a simple logical expression with
13923                     # breakpoints (broken sublists, for example).  Break
13924                     # at all 'or's and '||'s.
13925                     else {
13926                         set_logical_breakpoints($current_depth);
13927                     }
13928                 } ## end if ( $item_count_stack...)
13929
13930                 if ( $is_long_term
13931                     && @{ $rfor_semicolon_list[$current_depth] } )
13932                 {
13933                     set_for_semicolon_breakpoints($current_depth);
13934
13935                     # open up a long 'for' or 'foreach' container to allow
13936                     # leading term alignment unless -lp is used.
13937                     $has_comma_breakpoints = 1
13938                       unless $rOpts_line_up_parentheses;
13939                 } ## end if ( $is_long_term && ...)
13940
13941                 if (
13942
13943                     # breaks for code BLOCKS are handled at a higher level
13944                     !$block_type
13945
13946                     # we do not need to break at the top level of an 'if'
13947                     # type expression
13948                     && !$is_simple_logical_expression
13949
13950                     ## modification to keep ': (' containers vertically tight;
13951                     ## but probably better to let user set -vt=1 to avoid
13952                     ## inconsistency with other paren types
13953                     ## && ($container_type[$current_depth] ne ':')
13954
13955                     # otherwise, we require one of these reasons for breaking:
13956                     && (
13957
13958                         # - this term has forced line breaks
13959                         $has_comma_breakpoints
13960
13961                        # - the opening container is separated from this batch
13962                        #   for some reason (comment, blank line, code block)
13963                        # - this is a non-paren container spanning multiple lines
13964                         || !$saw_opening_structure
13965
13966                         # - this is a long block contained in another breakable
13967                         #   container
13968                         || (   $is_long_term
13969                             && $container_environment_to_go[$i_opening] ne
13970                             'BLOCK' )
13971                     )
13972                   )
13973                 {
13974
13975                     # For -lp option, we must put a breakpoint before
13976                     # the token which has been identified as starting
13977                     # this indentation level.  This is necessary for
13978                     # proper alignment.
13979                     if ( $rOpts_line_up_parentheses && $saw_opening_structure )
13980                     {
13981                         my $item = $leading_spaces_to_go[ $i_opening + 1 ];
13982                         if (   $i_opening + 1 < $max_index_to_go
13983                             && $types_to_go[ $i_opening + 1 ] eq 'b' )
13984                         {
13985                             $item = $leading_spaces_to_go[ $i_opening + 2 ];
13986                         }
13987                         if ( defined($item) ) {
13988                             my $i_start_2 = $item->get_starting_index();
13989                             if (
13990                                 defined($i_start_2)
13991
13992                                 # we are breaking after an opening brace, paren,
13993                                 # so don't break before it too
13994                                 && $i_start_2 ne $i_opening
13995                               )
13996                             {
13997
13998                                 # Only break for breakpoints at the same
13999                                 # indentation level as the opening paren
14000                                 my $test1 = $nesting_depth_to_go[$i_opening];
14001                                 my $test2 = $nesting_depth_to_go[$i_start_2];
14002                                 if ( $test2 == $test1 ) {
14003                                     set_forced_breakpoint( $i_start_2 - 1 );
14004                                 }
14005                             } ## end if ( defined($i_start_2...))
14006                         } ## end if ( defined($item) )
14007                     } ## end if ( $rOpts_line_up_parentheses...)
14008
14009                     # break after opening structure.
14010                     # note: break before closing structure will be automatic
14011                     if ( $minimum_depth <= $current_depth ) {
14012
14013                         set_forced_breakpoint($i_opening)
14014                           unless ( $do_not_break_apart
14015                             || is_unbreakable_container($current_depth) );
14016
14017                         # break at ',' of lower depth level before opening token
14018                         if ( $last_comma_index[$depth] ) {
14019                             set_forced_breakpoint( $last_comma_index[$depth] );
14020                         }
14021
14022                         # break at '.' of lower depth level before opening token
14023                         if ( $last_dot_index[$depth] ) {
14024                             set_forced_breakpoint( $last_dot_index[$depth] );
14025                         }
14026
14027                         # break before opening structure if preceded by another
14028                         # closing structure and a comma.  This is normally
14029                         # done by the previous closing brace, but not
14030                         # if it was a one-line block.
14031                         if ( $i_opening > 2 ) {
14032                             my $i_prev =
14033                               ( $types_to_go[ $i_opening - 1 ] eq 'b' )
14034                               ? $i_opening - 2
14035                               : $i_opening - 1;
14036
14037                             if (   $types_to_go[$i_prev] eq ','
14038                                 && $types_to_go[ $i_prev - 1 ] =~ /^[\)\}]$/ )
14039                             {
14040                                 set_forced_breakpoint($i_prev);
14041                             }
14042
14043                             # also break before something like ':('  or '?('
14044                             # if appropriate.
14045                             elsif (
14046                                 $types_to_go[$i_prev] =~ /^([k\:\?]|&&|\|\|)$/ )
14047                             {
14048                                 my $token_prev = $tokens_to_go[$i_prev];
14049                                 if ( $want_break_before{$token_prev} ) {
14050                                     set_forced_breakpoint($i_prev);
14051                                 }
14052                             } ## end elsif ( $types_to_go[$i_prev...])
14053                         } ## end if ( $i_opening > 2 )
14054                     } ## end if ( $minimum_depth <=...)
14055
14056                     # break after comma following closing structure
14057                     if ( $next_type eq ',' ) {
14058                         set_forced_breakpoint( $i + 1 );
14059                     }
14060
14061                     # break before an '=' following closing structure
14062                     if (
14063                         $is_assignment{$next_nonblank_type}
14064                         && ( $breakpoint_stack[$current_depth] !=
14065                             $forced_breakpoint_count )
14066                       )
14067                     {
14068                         set_forced_breakpoint($i);
14069                     } ## end if ( $is_assignment{$next_nonblank_type...})
14070
14071                     # break at any comma before the opening structure Added
14072                     # for -lp, but seems to be good in general.  It isn't
14073                     # obvious how far back to look; the '5' below seems to
14074                     # work well and will catch the comma in something like
14075                     #  push @list, myfunc( $param, $param, ..
14076
14077                     my $icomma = $last_comma_index[$depth];
14078                     if ( defined($icomma) && ( $i_opening - $icomma ) < 5 ) {
14079                         unless ( $forced_breakpoint_to_go[$icomma] ) {
14080                             set_forced_breakpoint($icomma);
14081                         }
14082                     }
14083                 }    # end logic to open up a container
14084
14085                 # Break open a logical container open if it was already open
14086                 elsif ($is_simple_logical_expression
14087                     && $has_old_logical_breakpoints[$current_depth] )
14088                 {
14089                     set_logical_breakpoints($current_depth);
14090                 }
14091
14092                 # Handle long container which does not get opened up
14093                 elsif ($is_long_term) {
14094
14095                     # must set fake breakpoint to alert outer containers that
14096                     # they are complex
14097                     set_fake_breakpoint();
14098                 } ## end elsif ($is_long_term)
14099
14100             } ## end elsif ( $depth < $current_depth)
14101
14102             #------------------------------------------------------------
14103             # Handle this token
14104             #------------------------------------------------------------
14105
14106             $current_depth = $depth;
14107
14108             # handle comma-arrow
14109             if ( $type eq '=>' ) {
14110                 next if ( $last_nonblank_type eq '=>' );
14111                 next if $rOpts_break_at_old_comma_breakpoints;
14112                 next if $rOpts_comma_arrow_breakpoints == 3;
14113                 $want_comma_break[$depth]   = 1;
14114                 $index_before_arrow[$depth] = $i_last_nonblank_token;
14115                 next;
14116             } ## end if ( $type eq '=>' )
14117
14118             elsif ( $type eq '.' ) {
14119                 $last_dot_index[$depth] = $i;
14120             }
14121
14122             # Turn off alignment if we are sure that this is not a list
14123             # environment.  To be safe, we will do this if we see certain
14124             # non-list tokens, such as ';', and also the environment is
14125             # not a list.  Note that '=' could be in any of the = operators
14126             # (lextest.t). We can't just use the reported environment
14127             # because it can be incorrect in some cases.
14128             elsif ( ( $type =~ /^[\;\<\>\~]$/ || $is_assignment{$type} )
14129                 && $container_environment_to_go[$i] ne 'LIST' )
14130             {
14131                 $dont_align[$depth]         = 1;
14132                 $want_comma_break[$depth]   = 0;
14133                 $index_before_arrow[$depth] = -1;
14134             } ## end elsif ( ( $type =~ /^[\;\<\>\~]$/...))
14135
14136             # now just handle any commas
14137             next unless ( $type eq ',' );
14138
14139             $last_dot_index[$depth]   = undef;
14140             $last_comma_index[$depth] = $i;
14141
14142             # break here if this comma follows a '=>'
14143             # but not if there is a side comment after the comma
14144             if ( $want_comma_break[$depth] ) {
14145
14146                 if ( $next_nonblank_type =~ /^[\)\}\]R]$/ ) {
14147                     if ($rOpts_comma_arrow_breakpoints) {
14148                         $want_comma_break[$depth] = 0;
14149                         next;
14150                     }
14151                 }
14152
14153                 set_forced_breakpoint($i) unless ( $next_nonblank_type eq '#' );
14154
14155                 # break before the previous token if it looks safe
14156                 # Example of something that we will not try to break before:
14157                 #   DBI::SQL_SMALLINT() => $ado_consts->{adSmallInt},
14158                 # Also we don't want to break at a binary operator (like +):
14159                 # $c->createOval(
14160                 #    $x + $R, $y +
14161                 #    $R => $x - $R,
14162                 #    $y - $R, -fill   => 'black',
14163                 # );
14164                 my $ibreak = $index_before_arrow[$depth] - 1;
14165                 if (   $ibreak > 0
14166                     && $tokens_to_go[ $ibreak + 1 ] !~ /^[\)\}\]]$/ )
14167                 {
14168                     if ( $tokens_to_go[$ibreak] eq '-' ) { $ibreak-- }
14169                     if ( $types_to_go[$ibreak] eq 'b' )  { $ibreak-- }
14170                     if ( $types_to_go[$ibreak] =~ /^[,wiZCUG\(\{\[]$/ ) {
14171
14172                         # don't break pointer calls, such as the following:
14173                         #  File::Spec->curdir  => 1,
14174                         # (This is tokenized as adjacent 'w' tokens)
14175                         ##if ( $tokens_to_go[ $ibreak + 1 ] !~ /^->/ ) {
14176
14177                         # And don't break before a comma, as in the following:
14178                         # ( LONGER_THAN,=> 1,
14179                         #    EIGHTY_CHARACTERS,=> 2,
14180                         #    CAUSES_FORMATTING,=> 3,
14181                         #    LIKE_THIS,=> 4,
14182                         # );
14183                         # This example is for -tso but should be general rule
14184                         if (   $tokens_to_go[ $ibreak + 1 ] ne '->'
14185                             && $tokens_to_go[ $ibreak + 1 ] ne ',' )
14186                         {
14187                             set_forced_breakpoint($ibreak);
14188                         }
14189                     } ## end if ( $types_to_go[$ibreak...])
14190                 } ## end if ( $ibreak > 0 && $tokens_to_go...)
14191
14192                 $want_comma_break[$depth]   = 0;
14193                 $index_before_arrow[$depth] = -1;
14194
14195                 # handle list which mixes '=>'s and ','s:
14196                 # treat any list items so far as an interrupted list
14197                 $interrupted_list[$depth] = 1;
14198                 next;
14199             } ## end if ( $want_comma_break...)
14200
14201             # break after all commas above starting depth
14202             if ( $depth < $starting_depth && !$dont_align[$depth] ) {
14203                 set_forced_breakpoint($i) unless ( $next_nonblank_type eq '#' );
14204                 next;
14205             }
14206
14207             # add this comma to the list..
14208             my $item_count = $item_count_stack[$depth];
14209             if ( $item_count == 0 ) {
14210
14211                 # but do not form a list with no opening structure
14212                 # for example:
14213
14214                 #            open INFILE_COPY, ">$input_file_copy"
14215                 #              or die ("very long message");
14216
14217                 if ( ( $opening_structure_index_stack[$depth] < 0 )
14218                     && $container_environment_to_go[$i] eq 'BLOCK' )
14219                 {
14220                     $dont_align[$depth] = 1;
14221                 }
14222             } ## end if ( $item_count == 0 )
14223
14224             $comma_index[$depth][$item_count] = $i;
14225             ++$item_count_stack[$depth];
14226             if ( $last_nonblank_type =~ /^[iR\]]$/ ) {
14227                 $identifier_count_stack[$depth]++;
14228             }
14229         } ## end while ( ++$i <= $max_index_to_go)
14230
14231         #-------------------------------------------
14232         # end of loop over all tokens in this batch
14233         #-------------------------------------------
14234
14235         # set breaks for any unfinished lists ..
14236         for ( my $dd = $current_depth ; $dd >= $minimum_depth ; $dd-- ) {
14237
14238             $interrupted_list[$dd]   = 1;
14239             $has_broken_sublist[$dd] = 1 if ( $dd < $current_depth );
14240             set_comma_breakpoints($dd);
14241             set_logical_breakpoints($dd)
14242               if ( $has_old_logical_breakpoints[$dd] );
14243             set_for_semicolon_breakpoints($dd);
14244
14245             # break open container...
14246             my $i_opening = $opening_structure_index_stack[$dd];
14247             set_forced_breakpoint($i_opening)
14248               unless (
14249                 is_unbreakable_container($dd)
14250
14251                 # Avoid a break which would place an isolated ' or "
14252                 # on a line
14253                 || (   $type eq 'Q'
14254                     && $i_opening >= $max_index_to_go - 2
14255                     && $token =~ /^['"]$/ )
14256               );
14257         } ## end for ( my $dd = $current_depth...)
14258
14259         # Return a flag indicating if the input file had some good breakpoints.
14260         # This flag will be used to force a break in a line shorter than the
14261         # allowed line length.
14262         if ( $has_old_logical_breakpoints[$current_depth] ) {
14263             $saw_good_breakpoint = 1;
14264         }
14265
14266         # A complex line with one break at an = has a good breakpoint.
14267         # This is not complex ($total_depth_variation=0):
14268         # $res1
14269         #   = 10;
14270         #
14271         # This is complex ($total_depth_variation=6):
14272         # $res2 =
14273         #  (is_boundp("a", 'self-insert') && is_boundp("b", 'self-insert'));
14274         elsif ($i_old_assignment_break
14275             && $total_depth_variation > 4
14276             && $old_breakpoint_count == 1 )
14277         {
14278             $saw_good_breakpoint = 1;
14279         } ## end elsif ( $i_old_assignment_break...)
14280
14281         return $saw_good_breakpoint;
14282     } ## end sub scan_list
14283 }    # end scan_list
14284
14285 sub find_token_starting_list {
14286
14287     # When testing to see if a block will fit on one line, some
14288     # previous token(s) may also need to be on the line; particularly
14289     # if this is a sub call.  So we will look back at least one
14290     # token. NOTE: This isn't perfect, but not critical, because
14291     # if we mis-identify a block, it will be wrapped and therefore
14292     # fixed the next time it is formatted.
14293     my $i_opening_paren = shift;
14294     my $i_opening_minus = $i_opening_paren;
14295     my $im1             = $i_opening_paren - 1;
14296     my $im2             = $i_opening_paren - 2;
14297     my $im3             = $i_opening_paren - 3;
14298     my $typem1          = $types_to_go[$im1];
14299     my $typem2          = $im2 >= 0 ? $types_to_go[$im2] : 'b';
14300
14301     if ( $typem1 eq ',' || ( $typem1 eq 'b' && $typem2 eq ',' ) ) {
14302         $i_opening_minus = $i_opening_paren;
14303     }
14304     elsif ( $tokens_to_go[$i_opening_paren] eq '(' ) {
14305         $i_opening_minus = $im1 if $im1 >= 0;
14306
14307         # walk back to improve length estimate
14308         for ( my $j = $im1 ; $j >= 0 ; $j-- ) {
14309             last if ( $types_to_go[$j] =~ /^[\(\[\{L\}\]\)Rb,]$/ );
14310             $i_opening_minus = $j;
14311         }
14312         if ( $types_to_go[$i_opening_minus] eq 'b' ) { $i_opening_minus++ }
14313     }
14314     elsif ( $typem1 eq 'k' ) { $i_opening_minus = $im1 }
14315     elsif ( $typem1 eq 'b' && $im2 >= 0 && $types_to_go[$im2] eq 'k' ) {
14316         $i_opening_minus = $im2;
14317     }
14318     return $i_opening_minus;
14319 }
14320
14321 {    # begin set_comma_breakpoints_do
14322
14323     my %is_keyword_with_special_leading_term;
14324
14325     BEGIN {
14326
14327         # These keywords have prototypes which allow a special leading item
14328         # followed by a list
14329         my @q =
14330           qw(formline grep kill map printf sprintf push chmod join pack unshift);
14331         @is_keyword_with_special_leading_term{@q} = (1) x scalar(@q);
14332     }
14333
14334     sub set_comma_breakpoints_do {
14335
14336         # Given a list with some commas, set breakpoints at some of the
14337         # commas, if necessary, to make it easy to read.  This list is
14338         # an example:
14339         my (
14340             $depth,               $i_opening_paren,  $i_closing_paren,
14341             $item_count,          $identifier_count, $rcomma_index,
14342             $next_nonblank_type,  $list_type,        $interrupted,
14343             $rdo_not_break_apart, $must_break_open,
14344         ) = @_;
14345
14346         # nothing to do if no commas seen
14347         return if ( $item_count < 1 );
14348         my $i_first_comma     = $rcomma_index->[0];
14349         my $i_true_last_comma = $rcomma_index->[ $item_count - 1 ];
14350         my $i_last_comma      = $i_true_last_comma;
14351         if ( $i_last_comma >= $max_index_to_go ) {
14352             $i_last_comma = $rcomma_index->[ --$item_count - 1 ];
14353             return if ( $item_count < 1 );
14354         }
14355
14356         #---------------------------------------------------------------
14357         # find lengths of all items in the list to calculate page layout
14358         #---------------------------------------------------------------
14359         my $comma_count = $item_count;
14360         my @item_lengths;
14361         my @i_term_begin;
14362         my @i_term_end;
14363         my @i_term_comma;
14364         my $i_prev_plus;
14365         my @max_length = ( 0, 0 );
14366         my $first_term_length;
14367         my $i      = $i_opening_paren;
14368         my $is_odd = 1;
14369
14370         foreach my $j ( 0 .. $comma_count - 1 ) {
14371             $is_odd      = 1 - $is_odd;
14372             $i_prev_plus = $i + 1;
14373             $i           = $rcomma_index->[$j];
14374
14375             my $i_term_end =
14376               ( $types_to_go[ $i - 1 ] eq 'b' ) ? $i - 2 : $i - 1;
14377             my $i_term_begin =
14378               ( $types_to_go[$i_prev_plus] eq 'b' )
14379               ? $i_prev_plus + 1
14380               : $i_prev_plus;
14381             push @i_term_begin, $i_term_begin;
14382             push @i_term_end,   $i_term_end;
14383             push @i_term_comma, $i;
14384
14385             # note: currently adding 2 to all lengths (for comma and space)
14386             my $length =
14387               2 + token_sequence_length( $i_term_begin, $i_term_end );
14388             push @item_lengths, $length;
14389
14390             if ( $j == 0 ) {
14391                 $first_term_length = $length;
14392             }
14393             else {
14394
14395                 if ( $length > $max_length[$is_odd] ) {
14396                     $max_length[$is_odd] = $length;
14397                 }
14398             }
14399         }
14400
14401         # now we have to make a distinction between the comma count and item
14402         # count, because the item count will be one greater than the comma
14403         # count if the last item is not terminated with a comma
14404         my $i_b =
14405           ( $types_to_go[ $i_last_comma + 1 ] eq 'b' )
14406           ? $i_last_comma + 1
14407           : $i_last_comma;
14408         my $i_e =
14409           ( $types_to_go[ $i_closing_paren - 1 ] eq 'b' )
14410           ? $i_closing_paren - 2
14411           : $i_closing_paren - 1;
14412         my $i_effective_last_comma = $i_last_comma;
14413
14414         my $last_item_length = token_sequence_length( $i_b + 1, $i_e );
14415
14416         if ( $last_item_length > 0 ) {
14417
14418             # add 2 to length because other lengths include a comma and a blank
14419             $last_item_length += 2;
14420             push @item_lengths, $last_item_length;
14421             push @i_term_begin, $i_b + 1;
14422             push @i_term_end,   $i_e;
14423             push @i_term_comma, undef;
14424
14425             my $i_odd = $item_count % 2;
14426
14427             if ( $last_item_length > $max_length[$i_odd] ) {
14428                 $max_length[$i_odd] = $last_item_length;
14429             }
14430
14431             $item_count++;
14432             $i_effective_last_comma = $i_e + 1;
14433
14434             if ( $types_to_go[ $i_b + 1 ] =~ /^[iR\]]$/ ) {
14435                 $identifier_count++;
14436             }
14437         }
14438
14439         #---------------------------------------------------------------
14440         # End of length calculations
14441         #---------------------------------------------------------------
14442
14443         #---------------------------------------------------------------
14444         # Compound List Rule 1:
14445         # Break at (almost) every comma for a list containing a broken
14446         # sublist.  This has higher priority than the Interrupted List
14447         # Rule.
14448         #---------------------------------------------------------------
14449         if ( $has_broken_sublist[$depth] ) {
14450
14451             # Break at every comma except for a comma between two
14452             # simple, small terms.  This prevents long vertical
14453             # columns of, say, just 0's.
14454             my $small_length = 10;    # 2 + actual maximum length wanted
14455
14456             # We'll insert a break in long runs of small terms to
14457             # allow alignment in uniform tables.
14458             my $skipped_count = 0;
14459             my $columns       = table_columns_available($i_first_comma);
14460             my $fields        = int( $columns / $small_length );
14461             if (   $rOpts_maximum_fields_per_table
14462                 && $fields > $rOpts_maximum_fields_per_table )
14463             {
14464                 $fields = $rOpts_maximum_fields_per_table;
14465             }
14466             my $max_skipped_count = $fields - 1;
14467
14468             my $is_simple_last_term = 0;
14469             my $is_simple_next_term = 0;
14470             foreach my $j ( 0 .. $item_count ) {
14471                 $is_simple_last_term = $is_simple_next_term;
14472                 $is_simple_next_term = 0;
14473                 if (   $j < $item_count
14474                     && $i_term_end[$j] == $i_term_begin[$j]
14475                     && $item_lengths[$j] <= $small_length )
14476                 {
14477                     $is_simple_next_term = 1;
14478                 }
14479                 next if $j == 0;
14480                 if (   $is_simple_last_term
14481                     && $is_simple_next_term
14482                     && $skipped_count < $max_skipped_count )
14483                 {
14484                     $skipped_count++;
14485                 }
14486                 else {
14487                     $skipped_count = 0;
14488                     my $i = $i_term_comma[ $j - 1 ];
14489                     last unless defined $i;
14490                     set_forced_breakpoint($i);
14491                 }
14492             }
14493
14494             # always break at the last comma if this list is
14495             # interrupted; we wouldn't want to leave a terminal '{', for
14496             # example.
14497             if ($interrupted) { set_forced_breakpoint($i_true_last_comma) }
14498             return;
14499         }
14500
14501 #my ( $a, $b, $c ) = caller();
14502 #print "LISTX: in set_list $a $c interrupt=$interrupted count=$item_count
14503 #i_first = $i_first_comma  i_last=$i_last_comma max=$max_index_to_go\n";
14504 #print "depth=$depth has_broken=$has_broken_sublist[$depth] is_multi=$is_multiline opening_paren=($i_opening_paren) \n";
14505
14506         #---------------------------------------------------------------
14507         # Interrupted List Rule:
14508         # A list is forced to use old breakpoints if it was interrupted
14509         # by side comments or blank lines, or requested by user.
14510         #---------------------------------------------------------------
14511         if (   $rOpts_break_at_old_comma_breakpoints
14512             || $interrupted
14513             || $i_opening_paren < 0 )
14514         {
14515             copy_old_breakpoints( $i_first_comma, $i_true_last_comma );
14516             return;
14517         }
14518
14519         #---------------------------------------------------------------
14520         # Looks like a list of items.  We have to look at it and size it up.
14521         #---------------------------------------------------------------
14522
14523         my $opening_token = $tokens_to_go[$i_opening_paren];
14524         my $opening_environment =
14525           $container_environment_to_go[$i_opening_paren];
14526
14527         #-------------------------------------------------------------------
14528         # Return if this will fit on one line
14529         #-------------------------------------------------------------------
14530
14531         my $i_opening_minus = find_token_starting_list($i_opening_paren);
14532         return
14533           unless excess_line_length( $i_opening_minus, $i_closing_paren ) > 0;
14534
14535         #-------------------------------------------------------------------
14536         # Now we know that this block spans multiple lines; we have to set
14537         # at least one breakpoint -- real or fake -- as a signal to break
14538         # open any outer containers.
14539         #-------------------------------------------------------------------
14540         set_fake_breakpoint();
14541
14542         # be sure we do not extend beyond the current list length
14543         if ( $i_effective_last_comma >= $max_index_to_go ) {
14544             $i_effective_last_comma = $max_index_to_go - 1;
14545         }
14546
14547         # Set a flag indicating if we need to break open to keep -lp
14548         # items aligned.  This is necessary if any of the list terms
14549         # exceeds the available space after the '('.
14550         my $need_lp_break_open = $must_break_open;
14551         if ( $rOpts_line_up_parentheses && !$must_break_open ) {
14552             my $columns_if_unbroken =
14553               maximum_line_length($i_opening_minus) -
14554               total_line_length( $i_opening_minus, $i_opening_paren );
14555             $need_lp_break_open =
14556                  ( $max_length[0] > $columns_if_unbroken )
14557               || ( $max_length[1] > $columns_if_unbroken )
14558               || ( $first_term_length > $columns_if_unbroken );
14559         }
14560
14561         # Specify if the list must have an even number of fields or not.
14562         # It is generally safest to assume an even number, because the
14563         # list items might be a hash list.  But if we can be sure that
14564         # it is not a hash, then we can allow an odd number for more
14565         # flexibility.
14566         my $odd_or_even = 2;    # 1 = odd field count ok, 2 = want even count
14567
14568         if (   $identifier_count >= $item_count - 1
14569             || $is_assignment{$next_nonblank_type}
14570             || ( $list_type && $list_type ne '=>' && $list_type !~ /^[\:\?]$/ )
14571           )
14572         {
14573             $odd_or_even = 1;
14574         }
14575
14576         # do we have a long first term which should be
14577         # left on a line by itself?
14578         my $use_separate_first_term = (
14579             $odd_or_even == 1       # only if we can use 1 field/line
14580               && $item_count > 3    # need several items
14581               && $first_term_length >
14582               2 * $max_length[0] - 2    # need long first term
14583               && $first_term_length >
14584               2 * $max_length[1] - 2    # need long first term
14585         );
14586
14587         # or do we know from the type of list that the first term should
14588         # be placed alone?
14589         if ( !$use_separate_first_term ) {
14590             if ( $is_keyword_with_special_leading_term{$list_type} ) {
14591                 $use_separate_first_term = 1;
14592
14593                 # should the container be broken open?
14594                 if ( $item_count < 3 ) {
14595                     if ( $i_first_comma - $i_opening_paren < 4 ) {
14596                         ${$rdo_not_break_apart} = 1;
14597                     }
14598                 }
14599                 elsif ($first_term_length < 20
14600                     && $i_first_comma - $i_opening_paren < 4 )
14601                 {
14602                     my $columns = table_columns_available($i_first_comma);
14603                     if ( $first_term_length < $columns ) {
14604                         ${$rdo_not_break_apart} = 1;
14605                     }
14606                 }
14607             }
14608         }
14609
14610         # if so,
14611         if ($use_separate_first_term) {
14612
14613             # ..set a break and update starting values
14614             $use_separate_first_term = 1;
14615             set_forced_breakpoint($i_first_comma);
14616             $i_opening_paren = $i_first_comma;
14617             $i_first_comma   = $rcomma_index->[1];
14618             $item_count--;
14619             return if $comma_count == 1;
14620             shift @item_lengths;
14621             shift @i_term_begin;
14622             shift @i_term_end;
14623             shift @i_term_comma;
14624         }
14625
14626         # if not, update the metrics to include the first term
14627         else {
14628             if ( $first_term_length > $max_length[0] ) {
14629                 $max_length[0] = $first_term_length;
14630             }
14631         }
14632
14633         # Field width parameters
14634         my $pair_width = ( $max_length[0] + $max_length[1] );
14635         my $max_width =
14636           ( $max_length[0] > $max_length[1] ) ? $max_length[0] : $max_length[1];
14637
14638         # Number of free columns across the page width for laying out tables
14639         my $columns = table_columns_available($i_first_comma);
14640
14641         # Estimated maximum number of fields which fit this space
14642         # This will be our first guess
14643         my $number_of_fields_max =
14644           maximum_number_of_fields( $columns, $odd_or_even, $max_width,
14645             $pair_width );
14646         my $number_of_fields = $number_of_fields_max;
14647
14648         # Find the best-looking number of fields
14649         # and make this our second guess if possible
14650         my ( $number_of_fields_best, $ri_ragged_break_list,
14651             $new_identifier_count )
14652           = study_list_complexity( \@i_term_begin, \@i_term_end, \@item_lengths,
14653             $max_width );
14654
14655         if (   $number_of_fields_best != 0
14656             && $number_of_fields_best < $number_of_fields_max )
14657         {
14658             $number_of_fields = $number_of_fields_best;
14659         }
14660
14661         # ----------------------------------------------------------------------
14662         # If we are crowded and the -lp option is being used, try to
14663         # undo some indentation
14664         # ----------------------------------------------------------------------
14665         if (
14666             $rOpts_line_up_parentheses
14667             && (
14668                 $number_of_fields == 0
14669                 || (   $number_of_fields == 1
14670                     && $number_of_fields != $number_of_fields_best )
14671             )
14672           )
14673         {
14674             my $available_spaces = get_available_spaces_to_go($i_first_comma);
14675             if ( $available_spaces > 0 ) {
14676
14677                 my $spaces_wanted = $max_width - $columns;    # for 1 field
14678
14679                 if ( $number_of_fields_best == 0 ) {
14680                     $number_of_fields_best =
14681                       get_maximum_fields_wanted( \@item_lengths );
14682                 }
14683
14684                 if ( $number_of_fields_best != 1 ) {
14685                     my $spaces_wanted_2 =
14686                       1 + $pair_width - $columns;             # for 2 fields
14687                     if ( $available_spaces > $spaces_wanted_2 ) {
14688                         $spaces_wanted = $spaces_wanted_2;
14689                     }
14690                 }
14691
14692                 if ( $spaces_wanted > 0 ) {
14693                     my $deleted_spaces =
14694                       reduce_lp_indentation( $i_first_comma, $spaces_wanted );
14695
14696                     # redo the math
14697                     if ( $deleted_spaces > 0 ) {
14698                         $columns = table_columns_available($i_first_comma);
14699                         $number_of_fields_max =
14700                           maximum_number_of_fields( $columns, $odd_or_even,
14701                             $max_width, $pair_width );
14702                         $number_of_fields = $number_of_fields_max;
14703
14704                         if (   $number_of_fields_best == 1
14705                             && $number_of_fields >= 1 )
14706                         {
14707                             $number_of_fields = $number_of_fields_best;
14708                         }
14709                     }
14710                 }
14711             }
14712         }
14713
14714         # try for one column if two won't work
14715         if ( $number_of_fields <= 0 ) {
14716             $number_of_fields = int( $columns / $max_width );
14717         }
14718
14719         # The user can place an upper bound on the number of fields,
14720         # which can be useful for doing maintenance on tables
14721         if (   $rOpts_maximum_fields_per_table
14722             && $number_of_fields > $rOpts_maximum_fields_per_table )
14723         {
14724             $number_of_fields = $rOpts_maximum_fields_per_table;
14725         }
14726
14727         # How many columns (characters) and lines would this container take
14728         # if no additional whitespace were added?
14729         my $packed_columns = token_sequence_length( $i_opening_paren + 1,
14730             $i_effective_last_comma + 1 );
14731         if ( $columns <= 0 ) { $columns = 1 }    # avoid divide by zero
14732         my $packed_lines = 1 + int( $packed_columns / $columns );
14733
14734         # are we an item contained in an outer list?
14735         my $in_hierarchical_list = $next_nonblank_type =~ /^[\}\,]$/;
14736
14737         if ( $number_of_fields <= 0 ) {
14738
14739 #         #---------------------------------------------------------------
14740 #         # We're in trouble.  We can't find a single field width that works.
14741 #         # There is no simple answer here; we may have a single long list
14742 #         # item, or many.
14743 #         #---------------------------------------------------------------
14744 #
14745 #         In many cases, it may be best to not force a break if there is just one
14746 #         comma, because the standard continuation break logic will do a better
14747 #         job without it.
14748 #
14749 #         In the common case that all but one of the terms can fit
14750 #         on a single line, it may look better not to break open the
14751 #         containing parens.  Consider, for example
14752 #
14753 #             $color =
14754 #               join ( '/',
14755 #                 sort { $color_value{$::a} <=> $color_value{$::b}; }
14756 #                 keys %colors );
14757 #
14758 #         which will look like this with the container broken:
14759 #
14760 #             $color = join (
14761 #                 '/',
14762 #                 sort { $color_value{$::a} <=> $color_value{$::b}; } keys %colors
14763 #             );
14764 #
14765 #         Here is an example of this rule for a long last term:
14766 #
14767 #             log_message( 0, 256, 128,
14768 #                 "Number of routes in adj-RIB-in to be considered: $peercount" );
14769 #
14770 #         And here is an example with a long first term:
14771 #
14772 #         $s = sprintf(
14773 # "%2d wallclock secs (%$f usr %$f sys + %$f cusr %$f csys = %$f CPU)",
14774 #             $r, $pu, $ps, $cu, $cs, $tt
14775 #           )
14776 #           if $style eq 'all';
14777
14778             my $i_last_comma   = $rcomma_index->[ $comma_count - 1 ];
14779             my $long_last_term = excess_line_length( 0, $i_last_comma ) <= 0;
14780             my $long_first_term =
14781               excess_line_length( $i_first_comma + 1, $max_index_to_go ) <= 0;
14782
14783             # break at every comma ...
14784             if (
14785
14786                 # if requested by user or is best looking
14787                 $number_of_fields_best == 1
14788
14789                 # or if this is a sublist of a larger list
14790                 || $in_hierarchical_list
14791
14792                 # or if multiple commas and we don't have a long first or last
14793                 # term
14794                 || ( $comma_count > 1
14795                     && !( $long_last_term || $long_first_term ) )
14796               )
14797             {
14798                 foreach ( 0 .. $comma_count - 1 ) {
14799                     set_forced_breakpoint( $rcomma_index->[$_] );
14800                 }
14801             }
14802             elsif ($long_last_term) {
14803
14804                 set_forced_breakpoint($i_last_comma);
14805                 ${$rdo_not_break_apart} = 1 unless $must_break_open;
14806             }
14807             elsif ($long_first_term) {
14808
14809                 set_forced_breakpoint($i_first_comma);
14810             }
14811             else {
14812
14813                 # let breaks be defined by default bond strength logic
14814             }
14815             return;
14816         }
14817
14818         # --------------------------------------------------------
14819         # We have a tentative field count that seems to work.
14820         # How many lines will this require?
14821         # --------------------------------------------------------
14822         my $formatted_lines = $item_count / ($number_of_fields);
14823         if ( $formatted_lines != int $formatted_lines ) {
14824             $formatted_lines = 1 + int $formatted_lines;
14825         }
14826
14827         # So far we've been trying to fill out to the right margin.  But
14828         # compact tables are easier to read, so let's see if we can use fewer
14829         # fields without increasing the number of lines.
14830         $number_of_fields =
14831           compactify_table( $item_count, $number_of_fields, $formatted_lines,
14832             $odd_or_even );
14833
14834         # How many spaces across the page will we fill?
14835         my $columns_per_line =
14836           ( int $number_of_fields / 2 ) * $pair_width +
14837           ( $number_of_fields % 2 ) * $max_width;
14838
14839         my $formatted_columns;
14840
14841         if ( $number_of_fields > 1 ) {
14842             $formatted_columns =
14843               ( $pair_width * ( int( $item_count / 2 ) ) +
14844                   ( $item_count % 2 ) * $max_width );
14845         }
14846         else {
14847             $formatted_columns = $max_width * $item_count;
14848         }
14849         if ( $formatted_columns < $packed_columns ) {
14850             $formatted_columns = $packed_columns;
14851         }
14852
14853         my $unused_columns = $formatted_columns - $packed_columns;
14854
14855         # set some empirical parameters to help decide if we should try to
14856         # align; high sparsity does not look good, especially with few lines
14857         my $sparsity = ($unused_columns) / ($formatted_columns);
14858         my $max_allowed_sparsity =
14859             ( $item_count < 3 )    ? 0.1
14860           : ( $packed_lines == 1 ) ? 0.15
14861           : ( $packed_lines == 2 ) ? 0.4
14862           :                          0.7;
14863
14864         # Begin check for shortcut methods, which avoid treating a list
14865         # as a table for relatively small parenthesized lists.  These
14866         # are usually easier to read if not formatted as tables.
14867         if (
14868             $packed_lines <= 2                    # probably can fit in 2 lines
14869             && $item_count < 9                    # doesn't have too many items
14870             && $opening_environment eq 'BLOCK'    # not a sub-container
14871             && $opening_token eq '('              # is paren list
14872           )
14873         {
14874
14875             # Shortcut method 1: for -lp and just one comma:
14876             # This is a no-brainer, just break at the comma.
14877             if (
14878                 $rOpts_line_up_parentheses    # -lp
14879                 && $item_count == 2           # two items, one comma
14880                 && !$must_break_open
14881               )
14882             {
14883                 my $i_break = $rcomma_index->[0];
14884                 set_forced_breakpoint($i_break);
14885                 ${$rdo_not_break_apart} = 1;
14886                 return;
14887
14888             }
14889
14890             # method 2 is for most small ragged lists which might look
14891             # best if not displayed as a table.
14892             if (
14893                 ( $number_of_fields == 2 && $item_count == 3 )
14894                 || (
14895                     $new_identifier_count > 0    # isn't all quotes
14896                     && $sparsity > 0.15
14897                 )    # would be fairly spaced gaps if aligned
14898               )
14899             {
14900
14901                 my $break_count = set_ragged_breakpoints( \@i_term_comma,
14902                     $ri_ragged_break_list );
14903                 ++$break_count if ($use_separate_first_term);
14904
14905                 # NOTE: we should really use the true break count here,
14906                 # which can be greater if there are large terms and
14907                 # little space, but usually this will work well enough.
14908                 unless ($must_break_open) {
14909
14910                     if ( $break_count <= 1 ) {
14911                         ${$rdo_not_break_apart} = 1;
14912                     }
14913                     elsif ( $rOpts_line_up_parentheses && !$need_lp_break_open )
14914                     {
14915                         ${$rdo_not_break_apart} = 1;
14916                     }
14917                 }
14918                 return;
14919             }
14920
14921         }    # end shortcut methods
14922
14923         # debug stuff
14924
14925         FORMATTER_DEBUG_FLAG_SPARSE && do {
14926             print STDOUT
14927 "SPARSE:cols=$columns commas=$comma_count items:$item_count ids=$identifier_count pairwidth=$pair_width fields=$number_of_fields lines packed: $packed_lines packed_cols=$packed_columns fmtd:$formatted_lines cols /line:$columns_per_line  unused:$unused_columns fmtd:$formatted_columns sparsity=$sparsity allow=$max_allowed_sparsity\n";
14928
14929         };
14930
14931         #---------------------------------------------------------------
14932         # Compound List Rule 2:
14933         # If this list is too long for one line, and it is an item of a
14934         # larger list, then we must format it, regardless of sparsity
14935         # (ian.t).  One reason that we have to do this is to trigger
14936         # Compound List Rule 1, above, which causes breaks at all commas of
14937         # all outer lists.  In this way, the structure will be properly
14938         # displayed.
14939         #---------------------------------------------------------------
14940
14941         # Decide if this list is too long for one line unless broken
14942         my $total_columns = table_columns_available($i_opening_paren);
14943         my $too_long      = $packed_columns > $total_columns;
14944
14945         # For a paren list, include the length of the token just before the
14946         # '(' because this is likely a sub call, and we would have to
14947         # include the sub name on the same line as the list.  This is still
14948         # imprecise, but not too bad.  (steve.t)
14949         if ( !$too_long && $i_opening_paren > 0 && $opening_token eq '(' ) {
14950
14951             $too_long = excess_line_length( $i_opening_minus,
14952                 $i_effective_last_comma + 1 ) > 0;
14953         }
14954
14955         # FIXME: For an item after a '=>', try to include the length of the
14956         # thing before the '=>'.  This is crude and should be improved by
14957         # actually looking back token by token.
14958         if ( !$too_long && $i_opening_paren > 0 && $list_type eq '=>' ) {
14959             my $i_opening_minus = $i_opening_paren - 4;
14960             if ( $i_opening_minus >= 0 ) {
14961                 $too_long = excess_line_length( $i_opening_minus,
14962                     $i_effective_last_comma + 1 ) > 0;
14963             }
14964         }
14965
14966         # Always break lists contained in '[' and '{' if too long for 1 line,
14967         # and always break lists which are too long and part of a more complex
14968         # structure.
14969         my $must_break_open_container = $must_break_open
14970           || ( $too_long
14971             && ( $in_hierarchical_list || $opening_token ne '(' ) );
14972
14973 #print "LISTX: next=$next_nonblank_type  avail cols=$columns packed=$packed_columns must format = $must_break_open_container too-long=$too_long  opening=$opening_token list_type=$list_type formatted_lines=$formatted_lines  packed=$packed_lines max_sparsity= $max_allowed_sparsity sparsity=$sparsity \n";
14974
14975         #---------------------------------------------------------------
14976         # The main decision:
14977         # Now decide if we will align the data into aligned columns.  Do not
14978         # attempt to align columns if this is a tiny table or it would be
14979         # too spaced.  It seems that the more packed lines we have, the
14980         # sparser the list that can be allowed and still look ok.
14981         #---------------------------------------------------------------
14982
14983         if (   ( $formatted_lines < 3 && $packed_lines < $formatted_lines )
14984             || ( $formatted_lines < 2 )
14985             || ( $unused_columns > $max_allowed_sparsity * $formatted_columns )
14986           )
14987         {
14988
14989             #---------------------------------------------------------------
14990             # too sparse: would look ugly if aligned in a table;
14991             #---------------------------------------------------------------
14992
14993             # use old breakpoints if this is a 'big' list
14994             # FIXME: goal is to improve set_ragged_breakpoints so that
14995             # this is not necessary.
14996             if ( $packed_lines > 2 && $item_count > 10 ) {
14997                 write_logfile_entry("List sparse: using old breakpoints\n");
14998                 copy_old_breakpoints( $i_first_comma, $i_last_comma );
14999             }
15000
15001             # let the continuation logic handle it if 2 lines
15002             else {
15003
15004                 my $break_count = set_ragged_breakpoints( \@i_term_comma,
15005                     $ri_ragged_break_list );
15006                 ++$break_count if ($use_separate_first_term);
15007
15008                 unless ($must_break_open_container) {
15009                     if ( $break_count <= 1 ) {
15010                         ${$rdo_not_break_apart} = 1;
15011                     }
15012                     elsif ( $rOpts_line_up_parentheses && !$need_lp_break_open )
15013                     {
15014                         ${$rdo_not_break_apart} = 1;
15015                     }
15016                 }
15017             }
15018             return;
15019         }
15020
15021         #---------------------------------------------------------------
15022         # go ahead and format as a table
15023         #---------------------------------------------------------------
15024         write_logfile_entry(
15025             "List: auto formatting with $number_of_fields fields/row\n");
15026
15027         my $j_first_break =
15028           $use_separate_first_term ? $number_of_fields : $number_of_fields - 1;
15029
15030         for (
15031             my $j = $j_first_break ;
15032             $j < $comma_count ;
15033             $j += $number_of_fields
15034           )
15035         {
15036             my $i = $rcomma_index->[$j];
15037             set_forced_breakpoint($i);
15038         }
15039         return;
15040     }
15041 }
15042
15043 sub study_list_complexity {
15044
15045     # Look for complex tables which should be formatted with one term per line.
15046     # Returns the following:
15047     #
15048     #  \@i_ragged_break_list = list of good breakpoints to avoid lines
15049     #    which are hard to read
15050     #  $number_of_fields_best = suggested number of fields based on
15051     #    complexity; = 0 if any number may be used.
15052     #
15053     my ( $ri_term_begin, $ri_term_end, $ritem_lengths, $max_width ) = @_;
15054     my $item_count            = @{$ri_term_begin};
15055     my $complex_item_count    = 0;
15056     my $number_of_fields_best = $rOpts_maximum_fields_per_table;
15057     my $i_max                 = @{$ritem_lengths} - 1;
15058     ##my @item_complexity;
15059
15060     my $i_last_last_break = -3;
15061     my $i_last_break      = -2;
15062     my @i_ragged_break_list;
15063
15064     my $definitely_complex = 30;
15065     my $definitely_simple  = 12;
15066     my $quote_count        = 0;
15067
15068     for my $i ( 0 .. $i_max ) {
15069         my $ib = $ri_term_begin->[$i];
15070         my $ie = $ri_term_end->[$i];
15071
15072         # define complexity: start with the actual term length
15073         my $weighted_length = ( $ritem_lengths->[$i] - 2 );
15074
15075         ##TBD: join types here and check for variations
15076         ##my $str=join "", @tokens_to_go[$ib..$ie];
15077
15078         my $is_quote = 0;
15079         if ( $types_to_go[$ib] =~ /^[qQ]$/ ) {
15080             $is_quote = 1;
15081             $quote_count++;
15082         }
15083         elsif ( $types_to_go[$ib] =~ /^[w\-]$/ ) {
15084             $quote_count++;
15085         }
15086
15087         if ( $ib eq $ie ) {
15088             if ( $is_quote && $tokens_to_go[$ib] =~ /\s/ ) {
15089                 $complex_item_count++;
15090                 $weighted_length *= 2;
15091             }
15092             else {
15093             }
15094         }
15095         else {
15096             if ( grep { $_ eq 'b' } @types_to_go[ $ib .. $ie ] ) {
15097                 $complex_item_count++;
15098                 $weighted_length *= 2;
15099             }
15100             if ( grep { $_ eq '..' } @types_to_go[ $ib .. $ie ] ) {
15101                 $weighted_length += 4;
15102             }
15103         }
15104
15105         # add weight for extra tokens.
15106         $weighted_length += 2 * ( $ie - $ib );
15107
15108 ##        my $BUB = join '', @tokens_to_go[$ib..$ie];
15109 ##        print "# COMPLEXITY:$weighted_length   $BUB\n";
15110
15111 ##push @item_complexity, $weighted_length;
15112
15113         # now mark a ragged break after this item it if it is 'long and
15114         # complex':
15115         if ( $weighted_length >= $definitely_complex ) {
15116
15117             # if we broke after the previous term
15118             # then break before it too
15119             if (   $i_last_break == $i - 1
15120                 && $i > 1
15121                 && $i_last_last_break != $i - 2 )
15122             {
15123
15124                 ## FIXME: don't strand a small term
15125                 pop @i_ragged_break_list;
15126                 push @i_ragged_break_list, $i - 2;
15127                 push @i_ragged_break_list, $i - 1;
15128             }
15129
15130             push @i_ragged_break_list, $i;
15131             $i_last_last_break = $i_last_break;
15132             $i_last_break      = $i;
15133         }
15134
15135         # don't break before a small last term -- it will
15136         # not look good on a line by itself.
15137         elsif ($i == $i_max
15138             && $i_last_break == $i - 1
15139             && $weighted_length <= $definitely_simple )
15140         {
15141             pop @i_ragged_break_list;
15142         }
15143     }
15144
15145     my $identifier_count = $i_max + 1 - $quote_count;
15146
15147     # Need more tuning here..
15148     if (   $max_width > 12
15149         && $complex_item_count > $item_count / 2
15150         && $number_of_fields_best != 2 )
15151     {
15152         $number_of_fields_best = 1;
15153     }
15154
15155     return ( $number_of_fields_best, \@i_ragged_break_list, $identifier_count );
15156 }
15157
15158 sub get_maximum_fields_wanted {
15159
15160     # Not all tables look good with more than one field of items.
15161     # This routine looks at a table and decides if it should be
15162     # formatted with just one field or not.
15163     # This coding is still under development.
15164     my ($ritem_lengths) = @_;
15165
15166     my $number_of_fields_best = 0;
15167
15168     # For just a few items, we tentatively assume just 1 field.
15169     my $item_count = @{$ritem_lengths};
15170     if ( $item_count <= 5 ) {
15171         $number_of_fields_best = 1;
15172     }
15173
15174     # For larger tables, look at it both ways and see what looks best
15175     else {
15176
15177         my $is_odd            = 1;
15178         my @max_length        = ( 0, 0 );
15179         my @last_length_2     = ( undef, undef );
15180         my @first_length_2    = ( undef, undef );
15181         my $last_length       = undef;
15182         my $total_variation_1 = 0;
15183         my $total_variation_2 = 0;
15184         my @total_variation_2 = ( 0, 0 );
15185
15186         foreach my $j ( 0 .. $item_count - 1 ) {
15187
15188             $is_odd = 1 - $is_odd;
15189             my $length = $ritem_lengths->[$j];
15190             if ( $length > $max_length[$is_odd] ) {
15191                 $max_length[$is_odd] = $length;
15192             }
15193
15194             if ( defined($last_length) ) {
15195                 my $dl = abs( $length - $last_length );
15196                 $total_variation_1 += $dl;
15197             }
15198             $last_length = $length;
15199
15200             my $ll = $last_length_2[$is_odd];
15201             if ( defined($ll) ) {
15202                 my $dl = abs( $length - $ll );
15203                 $total_variation_2[$is_odd] += $dl;
15204             }
15205             else {
15206                 $first_length_2[$is_odd] = $length;
15207             }
15208             $last_length_2[$is_odd] = $length;
15209         }
15210         $total_variation_2 = $total_variation_2[0] + $total_variation_2[1];
15211
15212         my $factor = ( $item_count > 10 ) ? 1 : ( $item_count > 5 ) ? 0.75 : 0;
15213         unless ( $total_variation_2 < $factor * $total_variation_1 ) {
15214             $number_of_fields_best = 1;
15215         }
15216     }
15217     return ($number_of_fields_best);
15218 }
15219
15220 sub table_columns_available {
15221     my $i_first_comma = shift;
15222     my $columns =
15223       maximum_line_length($i_first_comma) -
15224       leading_spaces_to_go($i_first_comma);
15225
15226     # Patch: the vertical formatter does not line up lines whose lengths
15227     # exactly equal the available line length because of allowances
15228     # that must be made for side comments.  Therefore, the number of
15229     # available columns is reduced by 1 character.
15230     $columns -= 1;
15231     return $columns;
15232 }
15233
15234 sub maximum_number_of_fields {
15235
15236     # how many fields will fit in the available space?
15237     my ( $columns, $odd_or_even, $max_width, $pair_width ) = @_;
15238     my $max_pairs        = int( $columns / $pair_width );
15239     my $number_of_fields = $max_pairs * 2;
15240     if (   $odd_or_even == 1
15241         && $max_pairs * $pair_width + $max_width <= $columns )
15242     {
15243         $number_of_fields++;
15244     }
15245     return $number_of_fields;
15246 }
15247
15248 sub compactify_table {
15249
15250     # given a table with a certain number of fields and a certain number
15251     # of lines, see if reducing the number of fields will make it look
15252     # better.
15253     my ( $item_count, $number_of_fields, $formatted_lines, $odd_or_even ) = @_;
15254     if ( $number_of_fields >= $odd_or_even * 2 && $formatted_lines > 0 ) {
15255         my $min_fields;
15256
15257         for (
15258             $min_fields = $number_of_fields ;
15259             $min_fields >= $odd_or_even
15260             && $min_fields * $formatted_lines >= $item_count ;
15261             $min_fields -= $odd_or_even
15262           )
15263         {
15264             $number_of_fields = $min_fields;
15265         }
15266     }
15267     return $number_of_fields;
15268 }
15269
15270 sub set_ragged_breakpoints {
15271
15272     # Set breakpoints in a list that cannot be formatted nicely as a
15273     # table.
15274     my ( $ri_term_comma, $ri_ragged_break_list ) = @_;
15275
15276     my $break_count = 0;
15277     foreach ( @{$ri_ragged_break_list} ) {
15278         my $j = $ri_term_comma->[$_];
15279         if ($j) {
15280             set_forced_breakpoint($j);
15281             $break_count++;
15282         }
15283     }
15284     return $break_count;
15285 }
15286
15287 sub copy_old_breakpoints {
15288     my ( $i_first_comma, $i_last_comma ) = @_;
15289     for my $i ( $i_first_comma .. $i_last_comma ) {
15290         if ( $old_breakpoint_to_go[$i] ) {
15291             set_forced_breakpoint($i);
15292         }
15293     }
15294     return;
15295 }
15296
15297 sub set_nobreaks {
15298     my ( $i, $j ) = @_;
15299     if ( $i >= 0 && $i <= $j && $j <= $max_index_to_go ) {
15300
15301         FORMATTER_DEBUG_FLAG_NOBREAK && do {
15302             my ( $a, $b, $c ) = caller();
15303             print STDOUT
15304 "NOBREAK: forced_breakpoint $forced_breakpoint_count from $a $c with i=$i max=$max_index_to_go type=$types_to_go[$i]\n";
15305         };
15306
15307         @nobreak_to_go[ $i .. $j ] = (1) x ( $j - $i + 1 );
15308     }
15309
15310     # shouldn't happen; non-critical error
15311     else {
15312         FORMATTER_DEBUG_FLAG_NOBREAK && do {
15313             my ( $a, $b, $c ) = caller();
15314             print STDOUT
15315               "NOBREAK ERROR: from $a $c with i=$i j=$j max=$max_index_to_go\n";
15316         };
15317     }
15318     return;
15319 }
15320
15321 sub set_fake_breakpoint {
15322
15323     # Just bump up the breakpoint count as a signal that there are breaks.
15324     # This is useful if we have breaks but may want to postpone deciding where
15325     # to make them.
15326     $forced_breakpoint_count++;
15327     return;
15328 }
15329
15330 sub set_forced_breakpoint {
15331     my $i = shift;
15332
15333     return unless defined $i && $i >= 0;
15334
15335     # no breaks between welded tokens
15336     return if ( weld_len_right_to_go($i) );
15337
15338     # when called with certain tokens, use bond strengths to decide
15339     # if we break before or after it
15340     my $token = $tokens_to_go[$i];
15341
15342     if ( $token =~ /^([\=\.\,\:\?]|and|or|xor|&&|\|\|)$/ ) {
15343         if ( $want_break_before{$token} && $i >= 0 ) { $i-- }
15344     }
15345
15346     # breaks are forced before 'if' and 'unless'
15347     elsif ( $is_if_unless{$token} ) { $i-- }
15348
15349     if ( $i >= 0 && $i <= $max_index_to_go ) {
15350         my $i_nonblank = ( $types_to_go[$i] ne 'b' ) ? $i : $i - 1;
15351
15352         FORMATTER_DEBUG_FLAG_FORCE && do {
15353             my ( $a, $b, $c ) = caller();
15354             print STDOUT
15355 "FORCE $forced_breakpoint_count from $a $c with i=$i_nonblank max=$max_index_to_go tok=$tokens_to_go[$i_nonblank] type=$types_to_go[$i_nonblank] nobr=$nobreak_to_go[$i_nonblank]\n";
15356         };
15357
15358         if ( $i_nonblank >= 0 && $nobreak_to_go[$i_nonblank] == 0 ) {
15359             $forced_breakpoint_to_go[$i_nonblank] = 1;
15360
15361             if ( $i_nonblank > $index_max_forced_break ) {
15362                 $index_max_forced_break = $i_nonblank;
15363             }
15364             $forced_breakpoint_count++;
15365             $forced_breakpoint_undo_stack[ $forced_breakpoint_undo_count++ ] =
15366               $i_nonblank;
15367
15368             # if we break at an opening container..break at the closing
15369             if ( $tokens_to_go[$i_nonblank] =~ /^[\{\[\(\?]$/ ) {
15370                 set_closing_breakpoint($i_nonblank);
15371             }
15372         }
15373     }
15374     return;
15375 }
15376
15377 sub clear_breakpoint_undo_stack {
15378     $forced_breakpoint_undo_count = 0;
15379     return;
15380 }
15381
15382 sub undo_forced_breakpoint_stack {
15383
15384     my $i_start = shift;
15385     if ( $i_start < 0 ) {
15386         $i_start = 0;
15387         my ( $a, $b, $c ) = caller();
15388         warning(
15389 "Program Bug: undo_forced_breakpoint_stack from $a $c has i=$i_start "
15390         );
15391     }
15392
15393     while ( $forced_breakpoint_undo_count > $i_start ) {
15394         my $i =
15395           $forced_breakpoint_undo_stack[ --$forced_breakpoint_undo_count ];
15396         if ( $i >= 0 && $i <= $max_index_to_go ) {
15397             $forced_breakpoint_to_go[$i] = 0;
15398             $forced_breakpoint_count--;
15399
15400             FORMATTER_DEBUG_FLAG_UNDOBP && do {
15401                 my ( $a, $b, $c ) = caller();
15402                 print STDOUT
15403 "UNDOBP: undo forced_breakpoint i=$i $forced_breakpoint_undo_count from $a $c max=$max_index_to_go\n";
15404             };
15405         }
15406
15407         # shouldn't happen, but not a critical error
15408         else {
15409             FORMATTER_DEBUG_FLAG_UNDOBP && do {
15410                 my ( $a, $b, $c ) = caller();
15411                 print STDOUT
15412 "Program Bug: undo_forced_breakpoint from $a $c has i=$i but max=$max_index_to_go";
15413             };
15414         }
15415     }
15416     return;
15417 }
15418
15419 sub sync_token_K {
15420     my ( $self, $i ) = @_;
15421
15422     # Keep tokens in the rLL array in sync with the _to_go array
15423     my $rLL = $self->{rLL};
15424     my $K   = $K_to_go[$i];
15425     if ( defined($K) ) {
15426         $rLL->[$K]->[_TOKEN_] = $tokens_to_go[$i];
15427     }
15428     else {
15429         # shouldn't happen
15430     }
15431     return;
15432 }
15433
15434 {    # begin recombine_breakpoints
15435
15436     my %is_amp_amp;
15437     my %is_ternary;
15438     my %is_math_op;
15439     my %is_plus_minus;
15440     my %is_mult_div;
15441
15442     BEGIN {
15443
15444         my @q;
15445         @q = qw( && || );
15446         @is_amp_amp{@q} = (1) x scalar(@q);
15447
15448         @q = qw( ? : );
15449         @is_ternary{@q} = (1) x scalar(@q);
15450
15451         @q = qw( + - * / );
15452         @is_math_op{@q} = (1) x scalar(@q);
15453
15454         @q = qw( + - );
15455         @is_plus_minus{@q} = (1) x scalar(@q);
15456
15457         @q = qw( * / );
15458         @is_mult_div{@q} = (1) x scalar(@q);
15459     }
15460
15461     sub DUMP_BREAKPOINTS {
15462
15463         # Debug routine to dump current breakpoints...not normally called
15464         # We are given indexes to the current lines:
15465         # $ri_beg = ref to array of BEGinning indexes of each line
15466         # $ri_end = ref to array of ENDing indexes of each line
15467         my ( $ri_beg, $ri_end, $msg ) = @_;
15468         print STDERR "----Dumping breakpoints from: $msg----\n";
15469         for my $n ( 0 .. @{$ri_end} - 1 ) {
15470             my $ibeg = $ri_beg->[$n];
15471             my $iend = $ri_end->[$n];
15472             my $text = "";
15473             foreach my $i ( $ibeg .. $iend ) {
15474                 $text .= $tokens_to_go[$i];
15475             }
15476             print STDERR "$n ($ibeg:$iend) $text\n";
15477         }
15478         print STDERR "----\n";
15479         return;
15480     }
15481
15482     sub delete_one_line_semicolons {
15483
15484         my ( $self, $ri_beg, $ri_end ) = @_;
15485         my $rLL                 = $self->{rLL};
15486         my $K_opening_container = $self->{K_opening_container};
15487
15488         # Walk down the lines of this batch and delete any semicolons
15489         # terminating one-line blocks;
15490         my $nmax = @{$ri_end} - 1;
15491
15492         foreach my $n ( 0 .. $nmax ) {
15493             my $i_beg    = $ri_beg->[$n];
15494             my $i_e      = $ri_end->[$n];
15495             my $K_beg    = $K_to_go[$i_beg];
15496             my $K_e      = $K_to_go[$i_e];
15497             my $K_end    = $K_e;
15498             my $type_end = $rLL->[$K_end]->[_TYPE_];
15499             if ( $type_end eq '#' ) {
15500                 $K_end = $self->K_previous_nonblank($K_end);
15501                 if ( defined($K_end) ) { $type_end = $rLL->[$K_end]->[_TYPE_]; }
15502             }
15503
15504             # we are looking for a line ending in closing brace
15505             next
15506               unless ( $type_end eq '}' && $rLL->[$K_end]->[_TOKEN_] eq '}' );
15507
15508             # ...and preceded by a semicolon on the same line
15509             my $K_semicolon = $self->K_previous_nonblank($K_end);
15510             my $i_semicolon = $i_beg + ( $K_semicolon - $K_beg );
15511             next if ( $i_semicolon <= $i_beg );
15512             next unless ( $rLL->[$K_semicolon]->[_TYPE_] eq ';' );
15513
15514             # safety check - shouldn't happen
15515             if ( $types_to_go[$i_semicolon] ne ';' ) {
15516                 Fault("unexpected type looking for semicolon, ignoring");
15517                 next;
15518             }
15519
15520             # ... with the corresponding opening brace on the same line
15521             my $type_sequence = $rLL->[$K_end]->[_TYPE_SEQUENCE_];
15522             my $K_opening     = $K_opening_container->{$type_sequence};
15523             my $i_opening     = $i_beg + ( $K_opening - $K_beg );
15524             next if ( $i_opening < $i_beg );
15525
15526             # ... and only one semicolon between these braces
15527             my $semicolon_count = 0;
15528             foreach my $K ( $K_opening + 1 .. $K_semicolon - 1 ) {
15529                 if ( $rLL->[$K]->[_TYPE_] eq ';' ) {
15530                     $semicolon_count++;
15531                     last;
15532                 }
15533             }
15534             next if ($semicolon_count);
15535
15536             # ...ok, then make the semicolon invisible
15537             $tokens_to_go[$i_semicolon] = "";
15538         }
15539         return;
15540     }
15541
15542     sub unmask_phantom_semicolons {
15543
15544         my ( $self, $ri_beg, $ri_end ) = @_;
15545
15546         # Walk down the lines of this batch and unmask any invisible line-ending
15547         # semicolons.  They were placed by sub respace_tokens but we only now
15548         # know if we actually need them.
15549
15550         my $nmax = @{$ri_end} - 1;
15551         foreach my $n ( 0 .. $nmax ) {
15552
15553             my $i = $ri_end->[$n];
15554             if ( $types_to_go[$i] eq ';' && $tokens_to_go[$i] eq '' ) {
15555
15556                 $tokens_to_go[$i] = $want_left_space{';'} == WS_NO ? ';' : ' ;';
15557                 $self->sync_token_K($i);
15558
15559                 my $line_number = 1 + $self->get_old_line_index( $K_to_go[$i] );
15560                 note_added_semicolon($line_number);
15561             }
15562         }
15563         return;
15564     }
15565
15566     sub recombine_breakpoints {
15567
15568         # sub set_continuation_breaks is very liberal in setting line breaks
15569         # for long lines, always setting breaks at good breakpoints, even
15570         # when that creates small lines.  Sometimes small line fragments
15571         # are produced which would look better if they were combined.
15572         # That's the task of this routine.
15573         #
15574         # We are given indexes to the current lines:
15575         # $ri_beg = ref to array of BEGinning indexes of each line
15576         # $ri_end = ref to array of ENDing indexes of each line
15577         my ( $ri_beg, $ri_end ) = @_;
15578
15579         # Make a list of all good joining tokens between the lines
15580         # n-1 and n.
15581         my @joint;
15582         my $nmax = @{$ri_end} - 1;
15583         for my $n ( 1 .. $nmax ) {
15584             my $ibeg_1 = $ri_beg->[ $n - 1 ];
15585             my $iend_1 = $ri_end->[ $n - 1 ];
15586             my $iend_2 = $ri_end->[$n];
15587             my $ibeg_2 = $ri_beg->[$n];
15588
15589             my ( $itok, $itokp, $itokm );
15590
15591             foreach my $itest ( $iend_1, $ibeg_2 ) {
15592                 my $type = $types_to_go[$itest];
15593                 if (   $is_math_op{$type}
15594                     || $is_amp_amp{$type}
15595                     || $is_assignment{$type}
15596                     || $type eq ':' )
15597                 {
15598                     $itok = $itest;
15599                 }
15600             }
15601             $joint[$n] = [$itok];
15602         }
15603
15604         my $more_to_do = 1;
15605
15606         # We keep looping over all of the lines of this batch
15607         # until there are no more possible recombinations
15608         my $nmax_last = @{$ri_end};
15609         my $reverse   = 0;
15610         while ($more_to_do) {
15611             my $n_best = 0;
15612             my $bs_best;
15613             my $nmax = @{$ri_end} - 1;
15614
15615             # Safety check for infinite loop
15616             unless ( $nmax < $nmax_last ) {
15617
15618                 # Shouldn't happen because splice below decreases nmax on each
15619                 # pass.
15620                 Fault("Program bug-infinite loop in recombine breakpoints\n");
15621             }
15622             $nmax_last  = $nmax;
15623             $more_to_do = 0;
15624             my $skip_Section_3;
15625             my $leading_amp_count = 0;
15626             my $this_line_is_semicolon_terminated;
15627
15628             # loop over all remaining lines in this batch
15629             for my $iter ( 1 .. $nmax ) {
15630
15631                 # alternating sweep direction gives symmetric results
15632                 # for recombining lines which exceed the line length
15633                 # such as eval {{{{.... }}}}
15634                 my $n;
15635                 if   ($reverse) { $n = 1 + $nmax - $iter; }
15636                 else            { $n = $iter }
15637
15638                 #----------------------------------------------------------
15639                 # If we join the current pair of lines,
15640                 # line $n-1 will become the left part of the joined line
15641                 # line $n will become the right part of the joined line
15642                 #
15643                 # Here are Indexes of the endpoint tokens of the two lines:
15644                 #
15645                 #  -----line $n-1--- | -----line $n-----
15646                 #  $ibeg_1   $iend_1 | $ibeg_2   $iend_2
15647                 #                    ^
15648                 #                    |
15649                 # We want to decide if we should remove the line break
15650                 # between the tokens at $iend_1 and $ibeg_2
15651                 #
15652                 # We will apply a number of ad-hoc tests to see if joining
15653                 # here will look ok.  The code will just issue a 'next'
15654                 # command if the join doesn't look good.  If we get through
15655                 # the gauntlet of tests, the lines will be recombined.
15656                 #----------------------------------------------------------
15657                 #
15658                 # beginning and ending tokens of the lines we are working on
15659                 my $ibeg_1    = $ri_beg->[ $n - 1 ];
15660                 my $iend_1    = $ri_end->[ $n - 1 ];
15661                 my $iend_2    = $ri_end->[$n];
15662                 my $ibeg_2    = $ri_beg->[$n];
15663                 my $ibeg_nmax = $ri_beg->[$nmax];
15664
15665                 # combined line cannot be too long
15666                 my $excess = excess_line_length( $ibeg_1, $iend_2, 1, 1 );
15667                 next if ( $excess > 0 );
15668
15669                 my $type_iend_1 = $types_to_go[$iend_1];
15670                 my $type_iend_2 = $types_to_go[$iend_2];
15671                 my $type_ibeg_1 = $types_to_go[$ibeg_1];
15672                 my $type_ibeg_2 = $types_to_go[$ibeg_2];
15673
15674                 # terminal token of line 2 if any side comment is ignored:
15675                 my $iend_2t      = $iend_2;
15676                 my $type_iend_2t = $type_iend_2;
15677
15678                 # some beginning indexes of other lines, which may not exist
15679                 my $ibeg_0 = $n > 1          ? $ri_beg->[ $n - 2 ] : -1;
15680                 my $ibeg_3 = $n < $nmax      ? $ri_beg->[ $n + 1 ] : -1;
15681                 my $ibeg_4 = $n + 2 <= $nmax ? $ri_beg->[ $n + 2 ] : -1;
15682
15683                 my $bs_tweak = 0;
15684
15685                 #my $depth_increase=( $nesting_depth_to_go[$ibeg_2] -
15686                 #        $nesting_depth_to_go[$ibeg_1] );
15687
15688                 FORMATTER_DEBUG_FLAG_RECOMBINE && do {
15689                     print STDERR
15690 "RECOMBINE: n=$n imid=$iend_1 if=$ibeg_1 type=$type_ibeg_1 =$tokens_to_go[$ibeg_1] next_type=$type_ibeg_2 next_tok=$tokens_to_go[$ibeg_2]\n";
15691                 };
15692
15693                 # If line $n is the last line, we set some flags and
15694                 # do any special checks for it
15695                 if ( $n == $nmax ) {
15696
15697                     # a terminal '{' should stay where it is
15698                     # unless preceded by a fat comma
15699                     next if ( $type_ibeg_2 eq '{' && $type_iend_1 ne '=>' );
15700
15701                     if (   $type_iend_2 eq '#'
15702                         && $iend_2 - $ibeg_2 >= 2
15703                         && $types_to_go[ $iend_2 - 1 ] eq 'b' )
15704                     {
15705                         $iend_2t      = $iend_2 - 2;
15706                         $type_iend_2t = $types_to_go[$iend_2t];
15707                     }
15708
15709                     $this_line_is_semicolon_terminated = $type_iend_2t eq ';';
15710                 }
15711
15712                 #----------------------------------------------------------
15713                 # Recombine Section 0:
15714                 # Examine the special token joining this line pair, if any.
15715                 # Put as many tests in this section to avoid duplicate code and
15716                 # to make formatting independent of whether breaks are to the
15717                 # left or right of an operator.
15718                 #----------------------------------------------------------
15719
15720                 my ($itok) = @{ $joint[$n] };
15721                 if ($itok) {
15722
15723                     # FIXME: Patch - may not be necessary
15724                     my $iend_1 =
15725                         $type_iend_1 eq 'b'
15726                       ? $iend_1 - 1
15727                       : $iend_1;
15728
15729                     my $iend_2 =
15730                         $type_iend_2 eq 'b'
15731                       ? $iend_2 - 1
15732                       : $iend_2;
15733                     ## END PATCH
15734
15735                     my $type = $types_to_go[$itok];
15736
15737                     if ( $type eq ':' ) {
15738
15739                    # do not join at a colon unless it disobeys the break request
15740                         if ( $itok eq $iend_1 ) {
15741                             next unless $want_break_before{$type};
15742                         }
15743                         else {
15744                             $leading_amp_count++;
15745                             next if $want_break_before{$type};
15746                         }
15747                     } ## end if ':'
15748
15749                     # handle math operators + - * /
15750                     elsif ( $is_math_op{$type} ) {
15751
15752                         # Combine these lines if this line is a single
15753                         # number, or if it is a short term with same
15754                         # operator as the previous line.  For example, in
15755                         # the following code we will combine all of the
15756                         # short terms $A, $B, $C, $D, $E, $F, together
15757                         # instead of leaving them one per line:
15758                         #  my $time =
15759                         #    $A * $B * $C * $D * $E * $F *
15760                         #    ( 2. * $eps * $sigma * $area ) *
15761                         #    ( 1. / $tcold**3 - 1. / $thot**3 );
15762
15763                         # This can be important in math-intensive code.
15764
15765                         my $good_combo;
15766
15767                         my $itokp  = min( $inext_to_go[$itok],  $iend_2 );
15768                         my $itokpp = min( $inext_to_go[$itokp], $iend_2 );
15769                         my $itokm  = max( $iprev_to_go[$itok],  $ibeg_1 );
15770                         my $itokmm = max( $iprev_to_go[$itokm], $ibeg_1 );
15771
15772                         # check for a number on the right
15773                         if ( $types_to_go[$itokp] eq 'n' ) {
15774
15775                             # ok if nothing else on right
15776                             if ( $itokp == $iend_2 ) {
15777                                 $good_combo = 1;
15778                             }
15779                             else {
15780
15781                                 # look one more token to right..
15782                                 # okay if math operator or some termination
15783                                 $good_combo =
15784                                   ( ( $itokpp == $iend_2 )
15785                                       && $is_math_op{ $types_to_go[$itokpp] } )
15786                                   || $types_to_go[$itokpp] =~ /^[#,;]$/;
15787                             }
15788                         }
15789
15790                         # check for a number on the left
15791                         if ( !$good_combo && $types_to_go[$itokm] eq 'n' ) {
15792
15793                             # okay if nothing else to left
15794                             if ( $itokm == $ibeg_1 ) {
15795                                 $good_combo = 1;
15796                             }
15797
15798                             # otherwise look one more token to left
15799                             else {
15800
15801                                 # okay if math operator, comma, or assignment
15802                                 $good_combo = ( $itokmm == $ibeg_1 )
15803                                   && ( $is_math_op{ $types_to_go[$itokmm] }
15804                                     || $types_to_go[$itokmm] =~ /^[,]$/
15805                                     || $is_assignment{ $types_to_go[$itokmm] }
15806                                   );
15807                             }
15808                         }
15809
15810                         # look for a single short token either side of the
15811                         # operator
15812                         if ( !$good_combo ) {
15813
15814                             # Slight adjustment factor to make results
15815                             # independent of break before or after operator in
15816                             # long summed lists.  (An operator and a space make
15817                             # two spaces).
15818                             my $two = ( $itok eq $iend_1 ) ? 2 : 0;
15819
15820                             $good_combo =
15821
15822                               # numbers or id's on both sides of this joint
15823                               $types_to_go[$itokp] =~ /^[in]$/
15824                               && $types_to_go[$itokm] =~ /^[in]$/
15825
15826                               # one of the two lines must be short:
15827                               && (
15828                                 (
15829                                     # no more than 2 nonblank tokens right of
15830                                     # joint
15831                                     $itokpp == $iend_2
15832
15833                                     # short
15834                                     && token_sequence_length( $itokp, $iend_2 )
15835                                     < $two +
15836                                     $rOpts_short_concatenation_item_length
15837                                 )
15838                                 || (
15839                                     # no more than 2 nonblank tokens left of
15840                                     # joint
15841                                     $itokmm == $ibeg_1
15842
15843                                     # short
15844                                     && token_sequence_length( $ibeg_1, $itokm )
15845                                     < 2 - $two +
15846                                     $rOpts_short_concatenation_item_length
15847                                 )
15848
15849                               )
15850
15851                               # keep pure terms; don't mix +- with */
15852                               && !(
15853                                 $is_plus_minus{$type}
15854                                 && (   $is_mult_div{ $types_to_go[$itokmm] }
15855                                     || $is_mult_div{ $types_to_go[$itokpp] } )
15856                               )
15857                               && !(
15858                                 $is_mult_div{$type}
15859                                 && (   $is_plus_minus{ $types_to_go[$itokmm] }
15860                                     || $is_plus_minus{ $types_to_go[$itokpp] } )
15861                               )
15862
15863                               ;
15864                         }
15865
15866                         # it is also good to combine if we can reduce to 2 lines
15867                         if ( !$good_combo ) {
15868
15869                             # index on other line where same token would be in a
15870                             # long chain.
15871                             my $iother =
15872                               ( $itok == $iend_1 ) ? $iend_2 : $ibeg_1;
15873
15874                             $good_combo =
15875                                  $n == 2
15876                               && $n == $nmax
15877                               && $types_to_go[$iother] ne $type;
15878                         }
15879
15880                         next unless ($good_combo);
15881
15882                     } ## end math
15883
15884                     elsif ( $is_amp_amp{$type} ) {
15885                         ##TBD
15886                     } ## end &&, ||
15887
15888                     elsif ( $is_assignment{$type} ) {
15889                         ##TBD
15890                     } ## end assignment
15891                 }
15892
15893                 #----------------------------------------------------------
15894                 # Recombine Section 1:
15895                 # Join welded nested containers immediately
15896                 #----------------------------------------------------------
15897                 if (   weld_len_right_to_go($iend_1)
15898                     || weld_len_left_to_go($ibeg_2) )
15899                 {
15900                     $n_best = $n;
15901
15902                     # Old coding alternated sweep direction: no longer needed
15903                     # $reverse = 1 - $reverse;
15904                     last;
15905                 }
15906                 $reverse = 0;
15907
15908                 #----------------------------------------------------------
15909                 # Recombine Section 2:
15910                 # Examine token at $iend_1 (right end of first line of pair)
15911                 #----------------------------------------------------------
15912
15913                 # an isolated '}' may join with a ';' terminated segment
15914                 if ( $type_iend_1 eq '}' ) {
15915
15916                     # Check for cases where combining a semicolon terminated
15917                     # statement with a previous isolated closing paren will
15918                     # allow the combined line to be outdented.  This is
15919                     # generally a good move.  For example, we can join up
15920                     # the last two lines here:
15921                     #  (
15922                     #      $dev,  $ino,   $mode,  $nlink, $uid,     $gid, $rdev,
15923                     #      $size, $atime, $mtime, $ctime, $blksize, $blocks
15924                     #    )
15925                     #    = stat($file);
15926                     #
15927                     # to get:
15928                     #  (
15929                     #      $dev,  $ino,   $mode,  $nlink, $uid,     $gid, $rdev,
15930                     #      $size, $atime, $mtime, $ctime, $blksize, $blocks
15931                     #  ) = stat($file);
15932                     #
15933                     # which makes the parens line up.
15934                     #
15935                     # Another example, from Joe Matarazzo, probably looks best
15936                     # with the 'or' clause appended to the trailing paren:
15937                     #  $self->some_method(
15938                     #      PARAM1 => 'foo',
15939                     #      PARAM2 => 'bar'
15940                     #  ) or die "Some_method didn't work";
15941                     #
15942                     # But we do not want to do this for something like the -lp
15943                     # option where the paren is not outdentable because the
15944                     # trailing clause will be far to the right.
15945                     #
15946                     # The logic here is synchronized with the logic in sub
15947                     # sub set_adjusted_indentation, which actually does
15948                     # the outdenting.
15949                     #
15950                     $skip_Section_3 ||= $this_line_is_semicolon_terminated
15951
15952                       # only one token on last line
15953                       && $ibeg_1 == $iend_1
15954
15955                       # must be structural paren
15956                       && $tokens_to_go[$iend_1] eq ')'
15957
15958                       # style must allow outdenting,
15959                       && !$closing_token_indentation{')'}
15960
15961                       # only leading '&&', '||', and ':' if no others seen
15962                       # (but note: our count made below could be wrong
15963                       # due to intervening comments)
15964                       && ( $leading_amp_count == 0
15965                         || $type_ibeg_2 !~ /^(:|\&\&|\|\|)$/ )
15966
15967                       # but leading colons probably line up with a
15968                       # previous colon or question (count could be wrong).
15969                       && $type_ibeg_2 ne ':'
15970
15971                       # only one step in depth allowed.  this line must not
15972                       # begin with a ')' itself.
15973                       && ( $nesting_depth_to_go[$iend_1] ==
15974                         $nesting_depth_to_go[$iend_2] + 1 );
15975
15976                     # YVES patch 2 of 2:
15977                     # Allow cuddled eval chains, like this:
15978                     #   eval {
15979                     #       #STUFF;
15980                     #       1; # return true
15981                     #   } or do {
15982                     #       #handle error
15983                     #   };
15984                     # This patch works together with a patch in
15985                     # setting adjusted indentation (where the closing eval
15986                     # brace is outdented if possible).
15987                     # The problem is that an 'eval' block has continuation
15988                     # indentation and it looks better to undo it in some
15989                     # cases.  If we do not use this patch we would get:
15990                     #   eval {
15991                     #       #STUFF;
15992                     #       1; # return true
15993                     #       }
15994                     #       or do {
15995                     #       #handle error
15996                     #     };
15997                     # The alternative, for uncuddled style, is to create
15998                     # a patch in set_adjusted_indentation which undoes
15999                     # the indentation of a leading line like 'or do {'.
16000                     # This doesn't work well with -icb through
16001                     if (
16002                            $block_type_to_go[$iend_1] eq 'eval'
16003                         && !$rOpts->{'line-up-parentheses'}
16004                         && !$rOpts->{'indent-closing-brace'}
16005                         && $tokens_to_go[$iend_2] eq '{'
16006                         && (
16007                             ( $type_ibeg_2 =~ /^(|\&\&|\|\|)$/ )
16008                             || (   $type_ibeg_2 eq 'k'
16009                                 && $is_and_or{ $tokens_to_go[$ibeg_2] } )
16010                             || $is_if_unless{ $tokens_to_go[$ibeg_2] }
16011                         )
16012                       )
16013                     {
16014                         $skip_Section_3 ||= 1;
16015                     }
16016
16017                     next
16018                       unless (
16019                         $skip_Section_3
16020
16021                         # handle '.' and '?' specially below
16022                         || ( $type_ibeg_2 =~ /^[\.\?]$/ )
16023                       );
16024                 }
16025
16026                 elsif ( $type_iend_1 eq '{' ) {
16027
16028                     # YVES
16029                     # honor breaks at opening brace
16030                     # Added to prevent recombining something like this:
16031                     #  } || eval { package main;
16032                     next if $forced_breakpoint_to_go[$iend_1];
16033                 }
16034
16035                 # do not recombine lines with ending &&, ||,
16036                 elsif ( $is_amp_amp{$type_iend_1} ) {
16037                     next unless $want_break_before{$type_iend_1};
16038                 }
16039
16040                 # Identify and recombine a broken ?/: chain
16041                 elsif ( $type_iend_1 eq '?' ) {
16042
16043                     # Do not recombine different levels
16044                     next
16045                       if ( $levels_to_go[$ibeg_1] ne $levels_to_go[$ibeg_2] );
16046
16047                     # do not recombine unless next line ends in :
16048                     next unless $type_iend_2 eq ':';
16049                 }
16050
16051                 # for lines ending in a comma...
16052                 elsif ( $type_iend_1 eq ',' ) {
16053
16054                     # Do not recombine at comma which is following the
16055                     # input bias.
16056                     # TODO: might be best to make a special flag
16057                     next if ( $old_breakpoint_to_go[$iend_1] );
16058
16059                  # an isolated '},' may join with an identifier + ';'
16060                  # this is useful for the class of a 'bless' statement (bless.t)
16061                     if (   $type_ibeg_1 eq '}'
16062                         && $type_ibeg_2 eq 'i' )
16063                     {
16064                         next
16065                           unless ( ( $ibeg_1 == ( $iend_1 - 1 ) )
16066                             && ( $iend_2 == ( $ibeg_2 + 1 ) )
16067                             && $this_line_is_semicolon_terminated );
16068
16069                         # override breakpoint
16070                         $forced_breakpoint_to_go[$iend_1] = 0;
16071                     }
16072
16073                     # but otherwise ..
16074                     else {
16075
16076                         # do not recombine after a comma unless this will leave
16077                         # just 1 more line
16078                         next unless ( $n + 1 >= $nmax );
16079
16080                     # do not recombine if there is a change in indentation depth
16081                         next
16082                           if (
16083                             $levels_to_go[$iend_1] != $levels_to_go[$iend_2] );
16084
16085                         # do not recombine a "complex expression" after a
16086                         # comma.  "complex" means no parens.
16087                         my $saw_paren;
16088                         foreach my $ii ( $ibeg_2 .. $iend_2 ) {
16089                             if ( $tokens_to_go[$ii] eq '(' ) {
16090                                 $saw_paren = 1;
16091                                 last;
16092                             }
16093                         }
16094                         next if $saw_paren;
16095                     }
16096                 }
16097
16098                 # opening paren..
16099                 elsif ( $type_iend_1 eq '(' ) {
16100
16101                     # No longer doing this
16102                 }
16103
16104                 elsif ( $type_iend_1 eq ')' ) {
16105
16106                     # No longer doing this
16107                 }
16108
16109                 # keep a terminal for-semicolon
16110                 elsif ( $type_iend_1 eq 'f' ) {
16111                     next;
16112                 }
16113
16114                 # if '=' at end of line ...
16115                 elsif ( $is_assignment{$type_iend_1} ) {
16116
16117                     # keep break after = if it was in input stream
16118                     # this helps prevent 'blinkers'
16119                     next if $old_breakpoint_to_go[$iend_1]
16120
16121                       # don't strand an isolated '='
16122                       && $iend_1 != $ibeg_1;
16123
16124                     my $is_short_quote =
16125                       (      $type_ibeg_2 eq 'Q'
16126                           && $ibeg_2 == $iend_2
16127                           && token_sequence_length( $ibeg_2, $ibeg_2 ) <
16128                           $rOpts_short_concatenation_item_length );
16129                     my $is_ternary =
16130                       ( $type_ibeg_1 eq '?'
16131                           && ( $ibeg_3 >= 0 && $types_to_go[$ibeg_3] eq ':' ) );
16132
16133                     # always join an isolated '=', a short quote, or if this
16134                     # will put ?/: at start of adjacent lines
16135                     if (   $ibeg_1 != $iend_1
16136                         && !$is_short_quote
16137                         && !$is_ternary )
16138                     {
16139                         next
16140                           unless (
16141                             (
16142
16143                                 # unless we can reduce this to two lines
16144                                 $nmax < $n + 2
16145
16146                              # or three lines, the last with a leading semicolon
16147                                 || (   $nmax == $n + 2
16148                                     && $types_to_go[$ibeg_nmax] eq ';' )
16149
16150                                 # or the next line ends with a here doc
16151                                 || $type_iend_2 eq 'h'
16152
16153                                # or the next line ends in an open paren or brace
16154                                # and the break hasn't been forced [dima.t]
16155                                 || (  !$forced_breakpoint_to_go[$iend_1]
16156                                     && $type_iend_2 eq '{' )
16157                             )
16158
16159                             # do not recombine if the two lines might align well
16160                             # this is a very approximate test for this
16161                             && (
16162
16163                               # RT#127633 - the leading tokens are not operators
16164                                 ( $type_ibeg_2 ne $tokens_to_go[$ibeg_2] )
16165
16166                                 # or they are different
16167                                 || (   $ibeg_3 >= 0
16168                                     && $type_ibeg_2 ne $types_to_go[$ibeg_3] )
16169                             )
16170                           );
16171
16172                         if (
16173
16174                             # Recombine if we can make two lines
16175                             $nmax >= $n + 2
16176
16177                             # -lp users often prefer this:
16178                             #  my $title = function($env, $env, $sysarea,
16179                             #                       "bubba Borrower Entry");
16180                             #  so we will recombine if -lp is used we have
16181                             #  ending comma
16182                             && (  !$rOpts_line_up_parentheses
16183                                 || $type_iend_2 ne ',' )
16184                           )
16185                         {
16186
16187                            # otherwise, scan the rhs line up to last token for
16188                            # complexity.  Note that we are not counting the last
16189                            # token in case it is an opening paren.
16190                             my $tv    = 0;
16191                             my $depth = $nesting_depth_to_go[$ibeg_2];
16192                             foreach my $i ( $ibeg_2 + 1 .. $iend_2 - 1 ) {
16193                                 if ( $nesting_depth_to_go[$i] != $depth ) {
16194                                     $tv++;
16195                                     last if ( $tv > 1 );
16196                                 }
16197                                 $depth = $nesting_depth_to_go[$i];
16198                             }
16199
16200                          # ok to recombine if no level changes before last token
16201                             if ( $tv > 0 ) {
16202
16203                                 # otherwise, do not recombine if more than two
16204                                 # level changes.
16205                                 next if ( $tv > 1 );
16206
16207                               # check total complexity of the two adjacent lines
16208                               # that will occur if we do this join
16209                                 my $istop =
16210                                   ( $n < $nmax )
16211                                   ? $ri_end->[ $n + 1 ]
16212                                   : $iend_2;
16213                                 foreach my $i ( $iend_2 .. $istop ) {
16214                                     if ( $nesting_depth_to_go[$i] != $depth ) {
16215                                         $tv++;
16216                                         last if ( $tv > 2 );
16217                                     }
16218                                     $depth = $nesting_depth_to_go[$i];
16219                                 }
16220
16221                         # do not recombine if total is more than 2 level changes
16222                                 next if ( $tv > 2 );
16223                             }
16224                         }
16225                     }
16226
16227                     unless ( $tokens_to_go[$ibeg_2] =~ /^[\{\(\[]$/ ) {
16228                         $forced_breakpoint_to_go[$iend_1] = 0;
16229                     }
16230                 }
16231
16232                 # for keywords..
16233                 elsif ( $type_iend_1 eq 'k' ) {
16234
16235                     # make major control keywords stand out
16236                     # (recombine.t)
16237                     next
16238                       if (
16239
16240                         #/^(last|next|redo|return)$/
16241                         $is_last_next_redo_return{ $tokens_to_go[$iend_1] }
16242
16243                         # but only if followed by multiple lines
16244                         && $n < $nmax
16245                       );
16246
16247                     if ( $is_and_or{ $tokens_to_go[$iend_1] } ) {
16248                         next
16249                           unless $want_break_before{ $tokens_to_go[$iend_1] };
16250                     }
16251                 }
16252
16253                 #----------------------------------------------------------
16254                 # Recombine Section 3:
16255                 # Examine token at $ibeg_2 (left end of second line of pair)
16256                 #----------------------------------------------------------
16257
16258                 # join lines identified above as capable of
16259                 # causing an outdented line with leading closing paren
16260                 # Note that we are skipping the rest of this section
16261                 # and the rest of the loop to do the join
16262                 if ($skip_Section_3) {
16263                     $forced_breakpoint_to_go[$iend_1] = 0;
16264                     $n_best = $n;
16265                     last;
16266                 }
16267
16268                 # handle lines with leading &&, ||
16269                 elsif ( $is_amp_amp{$type_ibeg_2} ) {
16270
16271                     $leading_amp_count++;
16272
16273                     # ok to recombine if it follows a ? or :
16274                     # and is followed by an open paren..
16275                     my $ok =
16276                       (      $is_ternary{$type_ibeg_1}
16277                           && $tokens_to_go[$iend_2] eq '(' )
16278
16279                     # or is followed by a ? or : at same depth
16280                     #
16281                     # We are looking for something like this. We can
16282                     # recombine the && line with the line above to make the
16283                     # structure more clear:
16284                     #  return
16285                     #    exists $G->{Attr}->{V}
16286                     #    && exists $G->{Attr}->{V}->{$u}
16287                     #    ? %{ $G->{Attr}->{V}->{$u} }
16288                     #    : ();
16289                     #
16290                     # We should probably leave something like this alone:
16291                     #  return
16292                     #       exists $G->{Attr}->{E}
16293                     #    && exists $G->{Attr}->{E}->{$u}
16294                     #    && exists $G->{Attr}->{E}->{$u}->{$v}
16295                     #    ? %{ $G->{Attr}->{E}->{$u}->{$v} }
16296                     #    : ();
16297                     # so that we either have all of the &&'s (or ||'s)
16298                     # on one line, as in the first example, or break at
16299                     # each one as in the second example.  However, it
16300                     # sometimes makes things worse to check for this because
16301                     # it prevents multiple recombinations.  So this is not done.
16302                       || ( $ibeg_3 >= 0
16303                         && $is_ternary{ $types_to_go[$ibeg_3] }
16304                         && $nesting_depth_to_go[$ibeg_3] ==
16305                         $nesting_depth_to_go[$ibeg_2] );
16306
16307                     next if !$ok && $want_break_before{$type_ibeg_2};
16308                     $forced_breakpoint_to_go[$iend_1] = 0;
16309
16310                     # tweak the bond strength to give this joint priority
16311                     # over ? and :
16312                     $bs_tweak = 0.25;
16313                 }
16314
16315                 # Identify and recombine a broken ?/: chain
16316                 elsif ( $type_ibeg_2 eq '?' ) {
16317
16318                     # Do not recombine different levels
16319                     my $lev = $levels_to_go[$ibeg_2];
16320                     next if ( $lev ne $levels_to_go[$ibeg_1] );
16321
16322                     # Do not recombine a '?' if either next line or
16323                     # previous line does not start with a ':'.  The reasons
16324                     # are that (1) no alignment of the ? will be possible
16325                     # and (2) the expression is somewhat complex, so the
16326                     # '?' is harder to see in the interior of the line.
16327                     my $follows_colon = $ibeg_1 >= 0 && $type_ibeg_1 eq ':';
16328                     my $precedes_colon =
16329                       $ibeg_3 >= 0 && $types_to_go[$ibeg_3] eq ':';
16330                     next unless ( $follows_colon || $precedes_colon );
16331
16332                     # we will always combining a ? line following a : line
16333                     if ( !$follows_colon ) {
16334
16335                         # ...otherwise recombine only if it looks like a chain.
16336                         # we will just look at a few nearby lines to see if
16337                         # this looks like a chain.
16338                         my $local_count = 0;
16339                         foreach my $ii ( $ibeg_0, $ibeg_1, $ibeg_3, $ibeg_4 ) {
16340                             $local_count++
16341                               if $ii >= 0
16342                               && $types_to_go[$ii] eq ':'
16343                               && $levels_to_go[$ii] == $lev;
16344                         }
16345                         next unless ( $local_count > 1 );
16346                     }
16347                     $forced_breakpoint_to_go[$iend_1] = 0;
16348                 }
16349
16350                 # do not recombine lines with leading '.'
16351                 elsif ( $type_ibeg_2 eq '.' ) {
16352                     my $i_next_nonblank = min( $inext_to_go[$ibeg_2], $iend_2 );
16353                     next
16354                       unless (
16355
16356                    # ... unless there is just one and we can reduce
16357                    # this to two lines if we do.  For example, this
16358                    #
16359                    #
16360                    #  $bodyA .=
16361                    #    '($dummy, $pat) = &get_next_tex_cmd;' . '$args .= $pat;'
16362                    #
16363                    #  looks better than this:
16364                    #  $bodyA .= '($dummy, $pat) = &get_next_tex_cmd;'
16365                    #    . '$args .= $pat;'
16366
16367                         (
16368                                $n == 2
16369                             && $n == $nmax
16370                             && $type_ibeg_1 ne $type_ibeg_2
16371                         )
16372
16373                         #  ... or this would strand a short quote , like this
16374                         #                . "some long quote"
16375                         #                . "\n";
16376
16377                         || (   $types_to_go[$i_next_nonblank] eq 'Q'
16378                             && $i_next_nonblank >= $iend_2 - 1
16379                             && $token_lengths_to_go[$i_next_nonblank] <
16380                             $rOpts_short_concatenation_item_length )
16381                       );
16382                 }
16383
16384                 # handle leading keyword..
16385                 elsif ( $type_ibeg_2 eq 'k' ) {
16386
16387                     # handle leading "or"
16388                     if ( $tokens_to_go[$ibeg_2] eq 'or' ) {
16389                         next
16390                           unless (
16391                             $this_line_is_semicolon_terminated
16392                             && (
16393                                 $type_ibeg_1 eq '}'
16394                                 || (
16395
16396                                     # following 'if' or 'unless' or 'or'
16397                                     $type_ibeg_1 eq 'k'
16398                                     && $is_if_unless{ $tokens_to_go[$ibeg_1] }
16399
16400                                     # important: only combine a very simple or
16401                                     # statement because the step below may have
16402                                     # combined a trailing 'and' with this or,
16403                                     # and we do not want to then combine
16404                                     # everything together
16405                                     && ( $iend_2 - $ibeg_2 <= 7 )
16406                                 )
16407                             )
16408                           );
16409
16410                         #X: RT #81854
16411                         $forced_breakpoint_to_go[$iend_1] = 0
16412                           unless $old_breakpoint_to_go[$iend_1];
16413                     }
16414
16415                     # handle leading 'and'
16416                     elsif ( $tokens_to_go[$ibeg_2] eq 'and' ) {
16417
16418                         # Decide if we will combine a single terminal 'and'
16419                         # after an 'if' or 'unless'.
16420
16421                         #     This looks best with the 'and' on the same
16422                         #     line as the 'if':
16423                         #
16424                         #         $a = 1
16425                         #           if $seconds and $nu < 2;
16426                         #
16427                         #     But this looks better as shown:
16428                         #
16429                         #         $a = 1
16430                         #           if !$this->{Parents}{$_}
16431                         #           or $this->{Parents}{$_} eq $_;
16432                         #
16433                         next
16434                           unless (
16435                             $this_line_is_semicolon_terminated
16436                             && (
16437
16438                                 # following 'if' or 'unless' or 'or'
16439                                 $type_ibeg_1 eq 'k'
16440                                 && (   $is_if_unless{ $tokens_to_go[$ibeg_1] }
16441                                     || $tokens_to_go[$ibeg_1] eq 'or' )
16442                             )
16443                           );
16444                     }
16445
16446                     # handle leading "if" and "unless"
16447                     elsif ( $is_if_unless{ $tokens_to_go[$ibeg_2] } ) {
16448
16449                       # FIXME: This is still experimental..may not be too useful
16450                         next
16451                           unless (
16452                             $this_line_is_semicolon_terminated
16453
16454                             #  previous line begins with 'and' or 'or'
16455                             && $type_ibeg_1 eq 'k'
16456                             && $is_and_or{ $tokens_to_go[$ibeg_1] }
16457
16458                           );
16459                     }
16460
16461                     # handle all other leading keywords
16462                     else {
16463
16464                         # keywords look best at start of lines,
16465                         # but combine things like "1 while"
16466                         unless ( $is_assignment{$type_iend_1} ) {
16467                             next
16468                               if ( ( $type_iend_1 ne 'k' )
16469                                 && ( $tokens_to_go[$ibeg_2] ne 'while' ) );
16470                         }
16471                     }
16472                 }
16473
16474                 # similar treatment of && and || as above for 'and' and 'or':
16475                 # NOTE: This block of code is currently bypassed because
16476                 # of a previous block but is retained for possible future use.
16477                 elsif ( $is_amp_amp{$type_ibeg_2} ) {
16478
16479                     # maybe looking at something like:
16480                     # unless $TEXTONLY || $item =~ m%</?(hr>|p>|a|img)%i;
16481
16482                     next
16483                       unless (
16484                         $this_line_is_semicolon_terminated
16485
16486                         # previous line begins with an 'if' or 'unless' keyword
16487                         && $type_ibeg_1 eq 'k'
16488                         && $is_if_unless{ $tokens_to_go[$ibeg_1] }
16489
16490                       );
16491                 }
16492
16493                 # handle line with leading = or similar
16494                 elsif ( $is_assignment{$type_ibeg_2} ) {
16495                     next unless ( $n == 1 || $n == $nmax );
16496                     next if $old_breakpoint_to_go[$iend_1];
16497                     next
16498                       unless (
16499
16500                         # unless we can reduce this to two lines
16501                         $nmax == 2
16502
16503                         # or three lines, the last with a leading semicolon
16504                         || ( $nmax == 3 && $types_to_go[$ibeg_nmax] eq ';' )
16505
16506                         # or the next line ends with a here doc
16507                         || $type_iend_2 eq 'h'
16508
16509                         # or this is a short line ending in ;
16510                         || ( $n == $nmax && $this_line_is_semicolon_terminated )
16511                       );
16512                     $forced_breakpoint_to_go[$iend_1] = 0;
16513                 }
16514
16515                 #----------------------------------------------------------
16516                 # Recombine Section 4:
16517                 # Combine the lines if we arrive here and it is possible
16518                 #----------------------------------------------------------
16519
16520                 # honor hard breakpoints
16521                 next if ( $forced_breakpoint_to_go[$iend_1] > 0 );
16522
16523                 my $bs = $bond_strength_to_go[$iend_1] + $bs_tweak;
16524
16525                 # Require a few extra spaces before recombining lines if we are
16526                 # at an old breakpoint unless this is a simple list or terminal
16527                 # line.  The goal is to avoid oscillating between two
16528                 # quasi-stable end states.  For example this snippet caused
16529                 # problems:
16530 ##    my $this =
16531 ##    bless {
16532 ##        TText => "[" . ( join ',', map { "\"$_\"" } split "\n", $_ ) . "]"
16533 ##      },
16534 ##      $type;
16535                 next
16536                   if ( $old_breakpoint_to_go[$iend_1]
16537                     && !$this_line_is_semicolon_terminated
16538                     && $n < $nmax
16539                     && $excess + 4 > 0
16540                     && $type_iend_2 ne ',' );
16541
16542                 # do not recombine if we would skip in indentation levels
16543                 if ( $n < $nmax ) {
16544                     my $if_next = $ri_beg->[ $n + 1 ];
16545                     next
16546                       if (
16547                            $levels_to_go[$ibeg_1] < $levels_to_go[$ibeg_2]
16548                         && $levels_to_go[$ibeg_2] < $levels_to_go[$if_next]
16549
16550                         # but an isolated 'if (' is undesirable
16551                         && !(
16552                                $n == 1
16553                             && $iend_1 - $ibeg_1 <= 2
16554                             && $type_ibeg_1 eq 'k'
16555                             && $tokens_to_go[$ibeg_1] eq 'if'
16556                             && $tokens_to_go[$iend_1] ne '('
16557                         )
16558                       );
16559                 }
16560
16561                 # honor no-break's
16562                 next if ( $bs >= NO_BREAK - 1 );
16563
16564                 # remember the pair with the greatest bond strength
16565                 if ( !$n_best ) {
16566                     $n_best  = $n;
16567                     $bs_best = $bs;
16568                 }
16569                 else {
16570
16571                     if ( $bs > $bs_best ) {
16572                         $n_best  = $n;
16573                         $bs_best = $bs;
16574                     }
16575                 }
16576             }
16577
16578             # recombine the pair with the greatest bond strength
16579             if ($n_best) {
16580                 splice @{$ri_beg}, $n_best, 1;
16581                 splice @{$ri_end}, $n_best - 1, 1;
16582                 splice @joint, $n_best, 1;
16583
16584                 # keep going if we are still making progress
16585                 $more_to_do++;
16586             }
16587         }
16588         return ( $ri_beg, $ri_end );
16589     }
16590 }    # end recombine_breakpoints
16591
16592 sub break_all_chain_tokens {
16593
16594     # scan the current breakpoints looking for breaks at certain "chain
16595     # operators" (. : && || + etc) which often occur repeatedly in a long
16596     # statement.  If we see a break at any one, break at all similar tokens
16597     # within the same container.
16598     #
16599     my ( $self, $ri_left, $ri_right ) = @_;
16600
16601     my %saw_chain_type;
16602     my %left_chain_type;
16603     my %right_chain_type;
16604     my %interior_chain_type;
16605     my $nmax = @{$ri_right} - 1;
16606
16607     # scan the left and right end tokens of all lines
16608     my $count = 0;
16609     for my $n ( 0 .. $nmax ) {
16610         my $il    = $ri_left->[$n];
16611         my $ir    = $ri_right->[$n];
16612         my $typel = $types_to_go[$il];
16613         my $typer = $types_to_go[$ir];
16614         $typel = '+' if ( $typel eq '-' );    # treat + and - the same
16615         $typer = '+' if ( $typer eq '-' );
16616         $typel = '*' if ( $typel eq '/' );    # treat * and / the same
16617         $typer = '*' if ( $typer eq '/' );
16618         my $tokenl = $tokens_to_go[$il];
16619         my $tokenr = $tokens_to_go[$ir];
16620
16621         if ( $is_chain_operator{$tokenl} && $want_break_before{$typel} ) {
16622             next if ( $typel eq '?' );
16623             push @{ $left_chain_type{$typel} }, $il;
16624             $saw_chain_type{$typel} = 1;
16625             $count++;
16626         }
16627         if ( $is_chain_operator{$tokenr} && !$want_break_before{$typer} ) {
16628             next if ( $typer eq '?' );
16629             push @{ $right_chain_type{$typer} }, $ir;
16630             $saw_chain_type{$typer} = 1;
16631             $count++;
16632         }
16633     }
16634     return unless $count;
16635
16636     # now look for any interior tokens of the same types
16637     $count = 0;
16638     for my $n ( 0 .. $nmax ) {
16639         my $il = $ri_left->[$n];
16640         my $ir = $ri_right->[$n];
16641         foreach my $i ( $il + 1 .. $ir - 1 ) {
16642             my $type = $types_to_go[$i];
16643             $type = '+' if ( $type eq '-' );
16644             $type = '*' if ( $type eq '/' );
16645             if ( $saw_chain_type{$type} ) {
16646                 push @{ $interior_chain_type{$type} }, $i;
16647                 $count++;
16648             }
16649         }
16650     }
16651     return unless $count;
16652
16653     # now make a list of all new break points
16654     my @insert_list;
16655
16656     # loop over all chain types
16657     foreach my $type ( keys %saw_chain_type ) {
16658
16659         # quit if just ONE continuation line with leading .  For example--
16660         # print LATEXFILE '\framebox{\parbox[c][' . $h . '][t]{' . $w . '}{'
16661         #  . $contents;
16662         last if ( $nmax == 1 && $type =~ /^[\.\+]$/ );
16663
16664         # loop over all interior chain tokens
16665         foreach my $itest ( @{ $interior_chain_type{$type} } ) {
16666
16667             # loop over all left end tokens of same type
16668             if ( $left_chain_type{$type} ) {
16669                 next if $nobreak_to_go[ $itest - 1 ];
16670                 foreach my $i ( @{ $left_chain_type{$type} } ) {
16671                     next unless $self->in_same_container_i( $i, $itest );
16672                     push @insert_list, $itest - 1;
16673
16674                     # Break at matching ? if this : is at a different level.
16675                     # For example, the ? before $THRf_DEAD in the following
16676                     # should get a break if its : gets a break.
16677                     #
16678                     # my $flags =
16679                     #     ( $_ & 1 ) ? ( $_ & 4 ) ? $THRf_DEAD : $THRf_ZOMBIE
16680                     #   : ( $_ & 4 ) ? $THRf_R_DETACHED
16681                     #   :              $THRf_R_JOINABLE;
16682                     if (   $type eq ':'
16683                         && $levels_to_go[$i] != $levels_to_go[$itest] )
16684                     {
16685                         my $i_question = $mate_index_to_go[$itest];
16686                         if ( $i_question > 0 ) {
16687                             push @insert_list, $i_question - 1;
16688                         }
16689                     }
16690                     last;
16691                 }
16692             }
16693
16694             # loop over all right end tokens of same type
16695             if ( $right_chain_type{$type} ) {
16696                 next if $nobreak_to_go[$itest];
16697                 foreach my $i ( @{ $right_chain_type{$type} } ) {
16698                     next unless $self->in_same_container_i( $i, $itest );
16699                     push @insert_list, $itest;
16700
16701                     # break at matching ? if this : is at a different level
16702                     if (   $type eq ':'
16703                         && $levels_to_go[$i] != $levels_to_go[$itest] )
16704                     {
16705                         my $i_question = $mate_index_to_go[$itest];
16706                         if ( $i_question >= 0 ) {
16707                             push @insert_list, $i_question;
16708                         }
16709                     }
16710                     last;
16711                 }
16712             }
16713         }
16714     }
16715
16716     # insert any new break points
16717     if (@insert_list) {
16718         insert_additional_breaks( \@insert_list, $ri_left, $ri_right );
16719     }
16720     return;
16721 }
16722
16723 sub break_equals {
16724
16725     # Look for assignment operators that could use a breakpoint.
16726     # For example, in the following snippet
16727     #
16728     #    $HOME = $ENV{HOME}
16729     #      || $ENV{LOGDIR}
16730     #      || $pw[7]
16731     #      || die "no home directory for user $<";
16732     #
16733     # we could break at the = to get this, which is a little nicer:
16734     #    $HOME =
16735     #         $ENV{HOME}
16736     #      || $ENV{LOGDIR}
16737     #      || $pw[7]
16738     #      || die "no home directory for user $<";
16739     #
16740     # The logic here follows the logic in set_logical_padding, which
16741     # will add the padding in the second line to improve alignment.
16742     #
16743     my ( $ri_left, $ri_right ) = @_;
16744     my $nmax = @{$ri_right} - 1;
16745     return unless ( $nmax >= 2 );
16746
16747     # scan the left ends of first two lines
16748     my $tokbeg = "";
16749     my $depth_beg;
16750     for my $n ( 1 .. 2 ) {
16751         my $il     = $ri_left->[$n];
16752         my $typel  = $types_to_go[$il];
16753         my $tokenl = $tokens_to_go[$il];
16754
16755         my $has_leading_op = ( $tokenl =~ /^\w/ )
16756           ? $is_chain_operator{$tokenl}    # + - * / : ? && ||
16757           : $is_chain_operator{$typel};    # and, or
16758         return unless ($has_leading_op);
16759         if ( $n > 1 ) {
16760             return
16761               unless ( $tokenl eq $tokbeg
16762                 && $nesting_depth_to_go[$il] eq $depth_beg );
16763         }
16764         $tokbeg    = $tokenl;
16765         $depth_beg = $nesting_depth_to_go[$il];
16766     }
16767
16768     # now look for any interior tokens of the same types
16769     my $il = $ri_left->[0];
16770     my $ir = $ri_right->[0];
16771
16772     # now make a list of all new break points
16773     my @insert_list;
16774     for ( my $i = $ir - 1 ; $i > $il ; $i-- ) {
16775         my $type = $types_to_go[$i];
16776         if (   $is_assignment{$type}
16777             && $nesting_depth_to_go[$i] eq $depth_beg )
16778         {
16779             if ( $want_break_before{$type} ) {
16780                 push @insert_list, $i - 1;
16781             }
16782             else {
16783                 push @insert_list, $i;
16784             }
16785         }
16786     }
16787
16788     # Break after a 'return' followed by a chain of operators
16789     #  return ( $^O !~ /win32|dos/i )
16790     #    && ( $^O ne 'VMS' )
16791     #    && ( $^O ne 'OS2' )
16792     #    && ( $^O ne 'MacOS' );
16793     # To give:
16794     #  return
16795     #       ( $^O !~ /win32|dos/i )
16796     #    && ( $^O ne 'VMS' )
16797     #    && ( $^O ne 'OS2' )
16798     #    && ( $^O ne 'MacOS' );
16799     my $i = 0;
16800     if (   $types_to_go[$i] eq 'k'
16801         && $tokens_to_go[$i] eq 'return'
16802         && $ir > $il
16803         && $nesting_depth_to_go[$i] eq $depth_beg )
16804     {
16805         push @insert_list, $i;
16806     }
16807
16808     return unless (@insert_list);
16809
16810     # One final check...
16811     # scan second and third lines and be sure there are no assignments
16812     # we want to avoid breaking at an = to make something like this:
16813     #    unless ( $icon =
16814     #           $html_icons{"$type-$state"}
16815     #        or $icon = $html_icons{$type}
16816     #        or $icon = $html_icons{$state} )
16817     for my $n ( 1 .. 2 ) {
16818         my $il = $ri_left->[$n];
16819         my $ir = $ri_right->[$n];
16820         foreach my $i ( $il + 1 .. $ir ) {
16821             my $type = $types_to_go[$i];
16822             return
16823               if ( $is_assignment{$type}
16824                 && $nesting_depth_to_go[$i] eq $depth_beg );
16825         }
16826     }
16827
16828     # ok, insert any new break point
16829     if (@insert_list) {
16830         insert_additional_breaks( \@insert_list, $ri_left, $ri_right );
16831     }
16832     return;
16833 }
16834
16835 sub insert_final_breaks {
16836
16837     my ( $self, $ri_left, $ri_right ) = @_;
16838
16839     my $nmax = @{$ri_right} - 1;
16840
16841     # scan the left and right end tokens of all lines
16842     my $count         = 0;
16843     my $i_first_colon = -1;
16844     for my $n ( 0 .. $nmax ) {
16845         my $il    = $ri_left->[$n];
16846         my $ir    = $ri_right->[$n];
16847         my $typel = $types_to_go[$il];
16848         my $typer = $types_to_go[$ir];
16849         return if ( $typel eq '?' );
16850         return if ( $typer eq '?' );
16851         if    ( $typel eq ':' ) { $i_first_colon = $il; last; }
16852         elsif ( $typer eq ':' ) { $i_first_colon = $ir; last; }
16853     }
16854
16855     # For long ternary chains,
16856     # if the first : we see has its ? is in the interior
16857     # of a preceding line, then see if there are any good
16858     # breakpoints before the ?.
16859     if ( $i_first_colon > 0 ) {
16860         my $i_question = $mate_index_to_go[$i_first_colon];
16861         if ( $i_question > 0 ) {
16862             my @insert_list;
16863             for ( my $ii = $i_question - 1 ; $ii >= 0 ; $ii -= 1 ) {
16864                 my $token = $tokens_to_go[$ii];
16865                 my $type  = $types_to_go[$ii];
16866
16867                 # For now, a good break is either a comma or,
16868                 # in a long chain, a 'return'.
16869                 # Patch for RT #126633: added the $nmax>1 check to avoid
16870                 # breaking after a return for a simple ternary.  For longer
16871                 # chains the break after return allows vertical alignment, so
16872                 # it is still done.  So perltidy -wba='?' will not break
16873                 # immediately after the return in the following statement:
16874                 # sub x {
16875                 #    return 0 ? 'aaaaaaaaaaaaaaaaaaaaa' :
16876                 #      'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb';
16877                 # }
16878                 if (
16879                     (
16880                            $type eq ','
16881                         || $type eq 'k' && ( $nmax > 1 && $token eq 'return' )
16882                     )
16883                     && $self->in_same_container_i( $ii, $i_question )
16884                   )
16885                 {
16886                     push @insert_list, $ii;
16887                     last;
16888                 }
16889             }
16890
16891             # insert any new break points
16892             if (@insert_list) {
16893                 insert_additional_breaks( \@insert_list, $ri_left, $ri_right );
16894             }
16895         }
16896     }
16897     return;
16898 }
16899
16900 sub in_same_container_i {
16901
16902     # check to see if tokens at i1 and i2 are in the
16903     # same container, and not separated by a comma, ? or :
16904     # This is an interface between the _to_go arrays to the rLL array
16905     my ( $self, $i1, $i2 ) = @_;
16906     return $self->in_same_container_K( $K_to_go[$i1], $K_to_go[$i2] );
16907 }
16908
16909 {    # sub in_same_container_K
16910     my $ris_break_token;
16911     my $ris_comma_token;
16912
16913     BEGIN {
16914
16915         # all cases break on seeing commas at same level
16916         my @q = qw( => );
16917         push @q, ',';
16918         @{$ris_comma_token}{@q} = (1) x scalar(@q);
16919
16920         # Non-ternary text also breaks on seeing any of qw(? : || or )
16921         # Example: we would not want to break at any of these .'s
16922         #  : "<A HREF=\"#item_" . htmlify( 0, $s2 ) . "\">$str</A>"
16923         push @q, qw( or || ? : );
16924         @{$ris_break_token}{@q} = (1) x scalar(@q);
16925     }
16926
16927     sub in_same_container_K {
16928
16929         # Check to see if tokens at K1 and K2 are in the same container,
16930         # and not separated by certain characters: => , ? : || or
16931         # This version uses the newer $rLL data structure
16932
16933         my ( $self, $K1, $K2 ) = @_;
16934         if ( $K2 < $K1 ) { ( $K1, $K2 ) = ( $K2, $K1 ) }
16935         my $rLL     = $self->{rLL};
16936         my $depth_1 = $rLL->[$K1]->[_SLEVEL_];
16937         return if ( $depth_1 < 0 );
16938         return unless ( $rLL->[$K2]->[_SLEVEL_] == $depth_1 );
16939
16940         # Select character set to scan for
16941         my $type_1 = $rLL->[$K1]->[_TYPE_];
16942         my $rbreak = ( $type_1 ne ':' ) ? $ris_break_token : $ris_comma_token;
16943
16944         # Fast preliminary loop to verify that tokens are in the same container
16945         my $KK = $K1;
16946         while (1) {
16947             $KK = $rLL->[$KK]->[_KNEXT_SEQ_ITEM_];
16948             last if !defined($KK);
16949             last if ( $KK >= $K2 );
16950             my $depth_K = $rLL->[$KK]->[_SLEVEL_];
16951             return if ( $depth_K < $depth_1 );
16952             next   if ( $depth_K > $depth_1 );
16953             if ( $type_1 ne ':' ) {
16954                 my $tok_K = $rLL->[$KK]->[_TOKEN_];
16955                 return if ( $tok_K eq '?' || $tok_K eq ':' );
16956             }
16957         }
16958
16959         # Slow loop checking for certain characters
16960
16961         ###########################################################
16962         # This is potentially a slow routine and not critical.
16963         # For safety just give up for large differences.
16964         # See test file 'infinite_loop.txt'
16965         ###########################################################
16966         return if ( $K2 - $K1 > 200 );
16967
16968         foreach my $K ( $K1 + 1 .. $K2 - 1 ) {
16969
16970             my $depth_K = $rLL->[$K]->[_SLEVEL_];
16971             next   if ( $depth_K > $depth_1 );
16972             return if ( $depth_K < $depth_1 );    # redundant, checked above
16973             my $tok = $rLL->[$K]->[_TOKEN_];
16974             return if ( $rbreak->{$tok} );
16975         }
16976         return 1;
16977     }
16978 }
16979
16980 sub set_continuation_breaks {
16981
16982     # Define an array of indexes for inserting newline characters to
16983     # keep the line lengths below the maximum desired length.  There is
16984     # an implied break after the last token, so it need not be included.
16985
16986     # Method:
16987     # This routine is part of series of routines which adjust line
16988     # lengths.  It is only called if a statement is longer than the
16989     # maximum line length, or if a preliminary scanning located
16990     # desirable break points.   Sub scan_list has already looked at
16991     # these tokens and set breakpoints (in array
16992     # $forced_breakpoint_to_go[$i]) where it wants breaks (for example
16993     # after commas, after opening parens, and before closing parens).
16994     # This routine will honor these breakpoints and also add additional
16995     # breakpoints as necessary to keep the line length below the maximum
16996     # requested.  It bases its decision on where the 'bond strength' is
16997     # lowest.
16998
16999     # Output: returns references to the arrays:
17000     #  @i_first
17001     #  @i_last
17002     # which contain the indexes $i of the first and last tokens on each
17003     # line.
17004
17005     # In addition, the array:
17006     #   $forced_breakpoint_to_go[$i]
17007     # may be updated to be =1 for any index $i after which there must be
17008     # a break.  This signals later routines not to undo the breakpoint.
17009
17010     my ( $self, $saw_good_break ) = @_;
17011     my @i_first        = ();    # the first index to output
17012     my @i_last         = ();    # the last index to output
17013     my @i_colon_breaks = ();    # needed to decide if we have to break at ?'s
17014     if ( $types_to_go[0] eq ':' ) { push @i_colon_breaks, 0 }
17015
17016     set_bond_strengths();
17017
17018     my $imin = 0;
17019     my $imax = $max_index_to_go;
17020     if ( $types_to_go[$imin] eq 'b' ) { $imin++ }
17021     if ( $types_to_go[$imax] eq 'b' ) { $imax-- }
17022     my $i_begin = $imin;        # index for starting next iteration
17023
17024     my $leading_spaces          = leading_spaces_to_go($imin);
17025     my $line_count              = 0;
17026     my $last_break_strength     = NO_BREAK;
17027     my $i_last_break            = -1;
17028     my $max_bias                = 0.001;
17029     my $tiny_bias               = 0.0001;
17030     my $leading_alignment_token = "";
17031     my $leading_alignment_type  = "";
17032
17033     # see if any ?/:'s are in order
17034     my $colons_in_order = 1;
17035     my $last_tok        = "";
17036     my @colon_list  = grep { /^[\?\:]$/ } @types_to_go[ 0 .. $max_index_to_go ];
17037     my $colon_count = @colon_list;
17038     foreach (@colon_list) {
17039         if ( $_ eq $last_tok ) { $colons_in_order = 0; last }
17040         $last_tok = $_;
17041     }
17042
17043     # This is a sufficient but not necessary condition for colon chain
17044     my $is_colon_chain = ( $colons_in_order && @colon_list > 2 );
17045
17046     #-------------------------------------------------------
17047     # BEGINNING of main loop to set continuation breakpoints
17048     # Keep iterating until we reach the end
17049     #-------------------------------------------------------
17050     while ( $i_begin <= $imax ) {
17051         my $lowest_strength        = NO_BREAK;
17052         my $starting_sum           = $summed_lengths_to_go[$i_begin];
17053         my $i_lowest               = -1;
17054         my $i_test                 = -1;
17055         my $lowest_next_token      = '';
17056         my $lowest_next_type       = 'b';
17057         my $i_lowest_next_nonblank = -1;
17058
17059         #-------------------------------------------------------
17060         # BEGINNING of inner loop to find the best next breakpoint
17061         #-------------------------------------------------------
17062         for ( $i_test = $i_begin ; $i_test <= $imax ; $i_test++ ) {
17063             my $type                     = $types_to_go[$i_test];
17064             my $token                    = $tokens_to_go[$i_test];
17065             my $next_type                = $types_to_go[ $i_test + 1 ];
17066             my $next_token               = $tokens_to_go[ $i_test + 1 ];
17067             my $i_next_nonblank          = $inext_to_go[$i_test];
17068             my $next_nonblank_type       = $types_to_go[$i_next_nonblank];
17069             my $next_nonblank_token      = $tokens_to_go[$i_next_nonblank];
17070             my $next_nonblank_block_type = $block_type_to_go[$i_next_nonblank];
17071             my $strength                 = $bond_strength_to_go[$i_test];
17072             my $maximum_line_length      = maximum_line_length($i_begin);
17073
17074             # use old breaks as a tie-breaker.  For example to
17075             # prevent blinkers with -pbp in this code:
17076
17077 ##@keywords{
17078 ##    qw/ARG OUTPUT PROTO CONSTRUCTOR RETURNS DESC PARAMS SEEALSO EXAMPLE/}
17079 ##    = ();
17080
17081             # At the same time try to prevent a leading * in this code
17082             # with the default formatting:
17083             #
17084 ##                return
17085 ##                    factorial( $a + $b - 1 ) / factorial( $a - 1 ) / factorial( $b - 1 )
17086 ##                  * ( $x**( $a - 1 ) )
17087 ##                  * ( ( 1 - $x )**( $b - 1 ) );
17088
17089             # reduce strength a bit to break ties at an old breakpoint ...
17090             if (
17091                 $old_breakpoint_to_go[$i_test]
17092
17093                 # which is a 'good' breakpoint, meaning ...
17094                 # we don't want to break before it
17095                 && !$want_break_before{$type}
17096
17097                 # and either we want to break before the next token
17098                 # or the next token is not short (i.e. not a '*', '/' etc.)
17099                 && $i_next_nonblank <= $imax
17100                 && (   $want_break_before{$next_nonblank_type}
17101                     || $token_lengths_to_go[$i_next_nonblank] > 2
17102                     || $next_nonblank_type =~ /^[\,\(\[\{L]$/ )
17103               )
17104             {
17105                 $strength -= $tiny_bias;
17106             }
17107
17108             # otherwise increase strength a bit if this token would be at the
17109             # maximum line length.  This is necessary to avoid blinking
17110             # in the above example when the -iob flag is added.
17111             else {
17112                 my $len =
17113                   $leading_spaces +
17114                   $summed_lengths_to_go[ $i_test + 1 ] -
17115                   $starting_sum;
17116                 if ( $len >= $maximum_line_length ) {
17117                     $strength += $tiny_bias;
17118                 }
17119             }
17120
17121             my $must_break = 0;
17122
17123             # Force an immediate break at certain operators
17124             # with lower level than the start of the line,
17125             # unless we've already seen a better break.
17126             #
17127             ##############################################
17128             # Note on an issue with a preceding ?
17129             ##############################################
17130             # We don't include a ? in the above list, but there may
17131             # be a break at a previous ? if the line is long.
17132             # Because of this we do not want to force a break if
17133             # there is a previous ? on this line.  For now the best way
17134             # to do this is to not break if we have seen a lower strength
17135             # point, which is probably a ?.
17136             #
17137             # Example of unwanted breaks we are avoiding at a '.' following a ?
17138             # from pod2html using perltidy -gnu:
17139             # )
17140             # ? "\n&lt;A NAME=\""
17141             # . $value
17142             # . "\"&gt;\n$text&lt;/A&gt;\n"
17143             # : "\n$type$pod2.html\#" . $value . "\"&gt;$text&lt;\/A&gt;\n";
17144             if (
17145                 (
17146                     $next_nonblank_type =~ /^(\.|\&\&|\|\|)$/
17147                     || (   $next_nonblank_type eq 'k'
17148                         && $next_nonblank_token =~ /^(and|or)$/ )
17149                 )
17150                 && ( $nesting_depth_to_go[$i_begin] >
17151                     $nesting_depth_to_go[$i_next_nonblank] )
17152                 && ( $strength <= $lowest_strength )
17153               )
17154             {
17155                 set_forced_breakpoint($i_next_nonblank);
17156             }
17157
17158             if (
17159
17160                 # Try to put a break where requested by scan_list
17161                 $forced_breakpoint_to_go[$i_test]
17162
17163                 # break between ) { in a continued line so that the '{' can
17164                 # be outdented
17165                 # See similar logic in scan_list which catches instances
17166                 # where a line is just something like ') {'.  We have to
17167                 # be careful because the corresponding block keyword might
17168                 # not be on the first line, such as 'for' here:
17169                 #
17170                 # eval {
17171                 #     for ("a") {
17172                 #         for $x ( 1, 2 ) { local $_ = "b"; s/(.*)/+$1/ }
17173                 #     }
17174                 # };
17175                 #
17176                 || (
17177                        $line_count
17178                     && ( $token eq ')' )
17179                     && ( $next_nonblank_type eq '{' )
17180                     && ($next_nonblank_block_type)
17181                     && ( $next_nonblank_block_type ne $tokens_to_go[$i_begin] )
17182
17183                     # RT #104427: Dont break before opening sub brace because
17184                     # sub block breaks handled at higher level, unless
17185                     # it looks like the preceding list is long and broken
17186                     && !(
17187                         $next_nonblank_block_type =~ /^sub\b/
17188                         && ( $nesting_depth_to_go[$i_begin] ==
17189                             $nesting_depth_to_go[$i_next_nonblank] )
17190                     )
17191
17192                     && !$rOpts->{'opening-brace-always-on-right'}
17193                 )
17194
17195                 # There is an implied forced break at a terminal opening brace
17196                 || ( ( $type eq '{' ) && ( $i_test == $imax ) )
17197               )
17198             {
17199
17200                 # Forced breakpoints must sometimes be overridden, for example
17201                 # because of a side comment causing a NO_BREAK.  It is easier
17202                 # to catch this here than when they are set.
17203                 if ( $strength < NO_BREAK - 1 ) {
17204                     $strength   = $lowest_strength - $tiny_bias;
17205                     $must_break = 1;
17206                 }
17207             }
17208
17209             # quit if a break here would put a good terminal token on
17210             # the next line and we already have a possible break
17211             if (
17212                    !$must_break
17213                 && ( $next_nonblank_type =~ /^[\;\,]$/ )
17214                 && (
17215                     (
17216                         $leading_spaces +
17217                         $summed_lengths_to_go[ $i_next_nonblank + 1 ] -
17218                         $starting_sum
17219                     ) > $maximum_line_length
17220                 )
17221               )
17222             {
17223                 last if ( $i_lowest >= 0 );
17224             }
17225
17226             # Avoid a break which would strand a single punctuation
17227             # token.  For example, we do not want to strand a leading
17228             # '.' which is followed by a long quoted string.
17229             # But note that we do want to do this with -extrude (l=1)
17230             # so please test any changes to this code on -extrude.
17231             if (
17232                    !$must_break
17233                 && ( $i_test == $i_begin )
17234                 && ( $i_test < $imax )
17235                 && ( $token eq $type )
17236                 && (
17237                     (
17238                         $leading_spaces +
17239                         $summed_lengths_to_go[ $i_test + 1 ] -
17240                         $starting_sum
17241                     ) < $maximum_line_length
17242                 )
17243               )
17244             {
17245                 $i_test = min( $imax, $inext_to_go[$i_test] );
17246                 redo;
17247             }
17248
17249             if ( ( $strength <= $lowest_strength ) && ( $strength < NO_BREAK ) )
17250             {
17251
17252                 # break at previous best break if it would have produced
17253                 # a leading alignment of certain common tokens, and it
17254                 # is different from the latest candidate break
17255                 last
17256                   if ($leading_alignment_type);
17257
17258                 # Force at least one breakpoint if old code had good
17259                 # break It is only called if a breakpoint is required or
17260                 # desired.  This will probably need some adjustments
17261                 # over time.  A goal is to try to be sure that, if a new
17262                 # side comment is introduced into formatted text, then
17263                 # the same breakpoints will occur.  scbreak.t
17264                 last
17265                   if (
17266                     $i_test == $imax              # we are at the end
17267                     && !$forced_breakpoint_count  #
17268                     && $saw_good_break            # old line had good break
17269                     && $type =~ /^[#;\{]$/        # and this line ends in
17270                                                   # ';' or side comment
17271                     && $i_last_break < 0          # and we haven't made a break
17272                     && $i_lowest >= 0             # and we saw a possible break
17273                     && $i_lowest < $imax - 1      # (but not just before this ;)
17274                     && $strength - $lowest_strength < 0.5 * WEAK # and it's good
17275                   );
17276
17277                 # Do not skip past an important break point in a short final
17278                 # segment.  For example, without this check we would miss the
17279                 # break at the final / in the following code:
17280                 #
17281                 #  $depth_stop =
17282                 #    ( $tau * $mass_pellet * $q_0 *
17283                 #        ( 1. - exp( -$t_stop / $tau ) ) -
17284                 #        4. * $pi * $factor * $k_ice *
17285                 #        ( $t_melt - $t_ice ) *
17286                 #        $r_pellet *
17287                 #        $t_stop ) /
17288                 #    ( $rho_ice * $Qs * $pi * $r_pellet**2 );
17289                 #
17290                 if (   $line_count > 2
17291                     && $i_lowest < $i_test
17292                     && $i_test > $imax - 2
17293                     && $nesting_depth_to_go[$i_begin] >
17294                     $nesting_depth_to_go[$i_lowest]
17295                     && $lowest_strength < $last_break_strength - .5 * WEAK )
17296                 {
17297                     # Make this break for math operators for now
17298                     my $ir = $inext_to_go[$i_lowest];
17299                     my $il = $iprev_to_go[$ir];
17300                     last
17301                       if ( $types_to_go[$il] =~ /^[\/\*\+\-\%]$/
17302                         || $types_to_go[$ir] =~ /^[\/\*\+\-\%]$/ );
17303                 }
17304
17305                 # Update the minimum bond strength location
17306                 $lowest_strength        = $strength;
17307                 $i_lowest               = $i_test;
17308                 $lowest_next_token      = $next_nonblank_token;
17309                 $lowest_next_type       = $next_nonblank_type;
17310                 $i_lowest_next_nonblank = $i_next_nonblank;
17311                 last if $must_break;
17312
17313                 # set flags to remember if a break here will produce a
17314                 # leading alignment of certain common tokens
17315                 if (   $line_count > 0
17316                     && $i_test < $imax
17317                     && ( $lowest_strength - $last_break_strength <= $max_bias )
17318                   )
17319                 {
17320                     my $i_last_end = $iprev_to_go[$i_begin];
17321                     my $tok_beg    = $tokens_to_go[$i_begin];
17322                     my $type_beg   = $types_to_go[$i_begin];
17323                     if (
17324
17325                         # check for leading alignment of certain tokens
17326                         (
17327                                $tok_beg eq $next_nonblank_token
17328                             && $is_chain_operator{$tok_beg}
17329                             && (   $type_beg eq 'k'
17330                                 || $type_beg eq $tok_beg )
17331                             && $nesting_depth_to_go[$i_begin] >=
17332                             $nesting_depth_to_go[$i_next_nonblank]
17333                         )
17334
17335                         || (   $tokens_to_go[$i_last_end] eq $token
17336                             && $is_chain_operator{$token}
17337                             && ( $type eq 'k' || $type eq $token )
17338                             && $nesting_depth_to_go[$i_last_end] >=
17339                             $nesting_depth_to_go[$i_test] )
17340                       )
17341                     {
17342                         $leading_alignment_token = $next_nonblank_token;
17343                         $leading_alignment_type  = $next_nonblank_type;
17344                     }
17345                 }
17346             }
17347
17348             my $too_long = ( $i_test >= $imax );
17349             if ( !$too_long ) {
17350                 my $next_length =
17351                   $leading_spaces +
17352                   $summed_lengths_to_go[ $i_test + 2 ] -
17353                   $starting_sum;
17354                 $too_long = $next_length > $maximum_line_length;
17355
17356                 # To prevent blinkers we will avoid leaving a token exactly at
17357                 # the line length limit unless it is the last token or one of
17358                 # several "good" types.
17359                 #
17360                 # The following code was a blinker with -pbp before this
17361                 # modification:
17362 ##                    $last_nonblank_token eq '('
17363 ##                        && $is_indirect_object_taker{ $paren_type
17364 ##                            [$paren_depth] }
17365                 # The issue causing the problem is that if the
17366                 # term [$paren_depth] gets broken across a line then
17367                 # the whitespace routine doesn't see both opening and closing
17368                 # brackets and will format like '[ $paren_depth ]'.  This
17369                 # leads to an oscillation in length depending if we break
17370                 # before the closing bracket or not.
17371                 if (  !$too_long
17372                     && $i_test + 1 < $imax
17373                     && $next_nonblank_type !~ /^[,\}\]\)R]$/ )
17374                 {
17375                     $too_long = $next_length >= $maximum_line_length;
17376                 }
17377             }
17378
17379             FORMATTER_DEBUG_FLAG_BREAK
17380               && do {
17381                 my $ltok     = $token;
17382                 my $rtok     = $next_nonblank_token ? $next_nonblank_token : "";
17383                 my $i_testp2 = $i_test + 2;
17384                 if ( $i_testp2 > $max_index_to_go + 1 ) {
17385                     $i_testp2 = $max_index_to_go + 1;
17386                 }
17387                 if ( length($ltok) > 6 ) { $ltok = substr( $ltok, 0, 8 ) }
17388                 if ( length($rtok) > 6 ) { $rtok = substr( $rtok, 0, 8 ) }
17389                 print STDOUT
17390 "BREAK: i=$i_test imax=$imax $types_to_go[$i_test] $next_nonblank_type sp=($leading_spaces) lnext= $summed_lengths_to_go[$i_testp2] 2long=$too_long str=$strength    $ltok $rtok\n";
17391               };
17392
17393             # allow one extra terminal token after exceeding line length
17394             # if it would strand this token.
17395             if (   $rOpts_fuzzy_line_length
17396                 && $too_long
17397                 && $i_lowest == $i_test
17398                 && $token_lengths_to_go[$i_test] > 1
17399                 && $next_nonblank_type =~ /^[\;\,]$/ )
17400             {
17401                 $too_long = 0;
17402             }
17403
17404             last
17405               if (
17406                 ( $i_test == $imax )    # we're done if no more tokens,
17407                 || (
17408                     ( $i_lowest >= 0 )    # or no more space and we have a break
17409                     && $too_long
17410                 )
17411               );
17412         }
17413
17414         #-------------------------------------------------------
17415         # END of inner loop to find the best next breakpoint
17416         # Now decide exactly where to put the breakpoint
17417         #-------------------------------------------------------
17418
17419         # it's always ok to break at imax if no other break was found
17420         if ( $i_lowest < 0 ) { $i_lowest = $imax }
17421
17422         # semi-final index calculation
17423         my $i_next_nonblank     = $inext_to_go[$i_lowest];
17424         my $next_nonblank_type  = $types_to_go[$i_next_nonblank];
17425         my $next_nonblank_token = $tokens_to_go[$i_next_nonblank];
17426
17427         #-------------------------------------------------------
17428         # ?/: rule 1 : if a break here will separate a '?' on this
17429         # line from its closing ':', then break at the '?' instead.
17430         #-------------------------------------------------------
17431         foreach my $i ( $i_begin + 1 .. $i_lowest - 1 ) {
17432             next unless ( $tokens_to_go[$i] eq '?' );
17433
17434             # do not break if probable sequence of ?/: statements
17435             next if ($is_colon_chain);
17436
17437             # do not break if statement is broken by side comment
17438             next
17439               if ( $tokens_to_go[$max_index_to_go] eq '#'
17440                 && $self->terminal_type_i( 0, $max_index_to_go ) !~
17441                 /^[\;\}]$/ );
17442
17443             # no break needed if matching : is also on the line
17444             next
17445               if ( $mate_index_to_go[$i] >= 0
17446                 && $mate_index_to_go[$i] <= $i_next_nonblank );
17447
17448             $i_lowest = $i;
17449             if ( $want_break_before{'?'} ) { $i_lowest-- }
17450             last;
17451         }
17452
17453         #-------------------------------------------------------
17454         # END of inner loop to find the best next breakpoint:
17455         # Break the line after the token with index i=$i_lowest
17456         #-------------------------------------------------------
17457
17458         # final index calculation
17459         $i_next_nonblank     = $inext_to_go[$i_lowest];
17460         $next_nonblank_type  = $types_to_go[$i_next_nonblank];
17461         $next_nonblank_token = $tokens_to_go[$i_next_nonblank];
17462
17463         FORMATTER_DEBUG_FLAG_BREAK
17464           && print STDOUT
17465           "BREAK: best is i = $i_lowest strength = $lowest_strength\n";
17466
17467         #-------------------------------------------------------
17468         # ?/: rule 2 : if we break at a '?', then break at its ':'
17469         #
17470         # Note: this rule is also in sub scan_list to handle a break
17471         # at the start and end of a line (in case breaks are dictated
17472         # by side comments).
17473         #-------------------------------------------------------
17474         if ( $next_nonblank_type eq '?' ) {
17475             set_closing_breakpoint($i_next_nonblank);
17476         }
17477         elsif ( $types_to_go[$i_lowest] eq '?' ) {
17478             set_closing_breakpoint($i_lowest);
17479         }
17480
17481         #-------------------------------------------------------
17482         # ?/: rule 3 : if we break at a ':' then we save
17483         # its location for further work below.  We may need to go
17484         # back and break at its '?'.
17485         #-------------------------------------------------------
17486         if ( $next_nonblank_type eq ':' ) {
17487             push @i_colon_breaks, $i_next_nonblank;
17488         }
17489         elsif ( $types_to_go[$i_lowest] eq ':' ) {
17490             push @i_colon_breaks, $i_lowest;
17491         }
17492
17493         # here we should set breaks for all '?'/':' pairs which are
17494         # separated by this line
17495
17496         $line_count++;
17497
17498         # save this line segment, after trimming blanks at the ends
17499         push( @i_first,
17500             ( $types_to_go[$i_begin] eq 'b' ) ? $i_begin + 1 : $i_begin );
17501         push( @i_last,
17502             ( $types_to_go[$i_lowest] eq 'b' ) ? $i_lowest - 1 : $i_lowest );
17503
17504         # set a forced breakpoint at a container opening, if necessary, to
17505         # signal a break at a closing container.  Excepting '(' for now.
17506         if ( $tokens_to_go[$i_lowest] =~ /^[\{\[]$/
17507             && !$forced_breakpoint_to_go[$i_lowest] )
17508         {
17509             set_closing_breakpoint($i_lowest);
17510         }
17511
17512         # get ready to go again
17513         $i_begin                 = $i_lowest + 1;
17514         $last_break_strength     = $lowest_strength;
17515         $i_last_break            = $i_lowest;
17516         $leading_alignment_token = "";
17517         $leading_alignment_type  = "";
17518         $lowest_next_token       = '';
17519         $lowest_next_type        = 'b';
17520
17521         if ( ( $i_begin <= $imax ) && ( $types_to_go[$i_begin] eq 'b' ) ) {
17522             $i_begin++;
17523         }
17524
17525         # update indentation size
17526         if ( $i_begin <= $imax ) {
17527             $leading_spaces = leading_spaces_to_go($i_begin);
17528         }
17529     }
17530
17531     #-------------------------------------------------------
17532     # END of main loop to set continuation breakpoints
17533     # Now go back and make any necessary corrections
17534     #-------------------------------------------------------
17535
17536     #-------------------------------------------------------
17537     # ?/: rule 4 -- if we broke at a ':', then break at
17538     # corresponding '?' unless this is a chain of ?: expressions
17539     #-------------------------------------------------------
17540     if (@i_colon_breaks) {
17541
17542         # using a simple method for deciding if we are in a ?/: chain --
17543         # this is a chain if it has multiple ?/: pairs all in order;
17544         # otherwise not.
17545         # Note that if line starts in a ':' we count that above as a break
17546         my $is_chain = ( $colons_in_order && @i_colon_breaks > 1 );
17547
17548         unless ($is_chain) {
17549             my @insert_list = ();
17550             foreach (@i_colon_breaks) {
17551                 my $i_question = $mate_index_to_go[$_];
17552                 if ( $i_question >= 0 ) {
17553                     if ( $want_break_before{'?'} ) {
17554                         $i_question = $iprev_to_go[$i_question];
17555                     }
17556
17557                     if ( $i_question >= 0 ) {
17558                         push @insert_list, $i_question;
17559                     }
17560                 }
17561                 insert_additional_breaks( \@insert_list, \@i_first, \@i_last );
17562             }
17563         }
17564     }
17565     return ( \@i_first, \@i_last, $colon_count );
17566 }
17567
17568 sub insert_additional_breaks {
17569
17570     # this routine will add line breaks at requested locations after
17571     # sub set_continuation_breaks has made preliminary breaks.
17572
17573     my ( $ri_break_list, $ri_first, $ri_last ) = @_;
17574     my $i_f;
17575     my $i_l;
17576     my $line_number = 0;
17577     foreach my $i_break_left ( sort { $a <=> $b } @{$ri_break_list} ) {
17578
17579         $i_f = $ri_first->[$line_number];
17580         $i_l = $ri_last->[$line_number];
17581         while ( $i_break_left >= $i_l ) {
17582             $line_number++;
17583
17584             # shouldn't happen unless caller passes bad indexes
17585             if ( $line_number >= @{$ri_last} ) {
17586                 warning(
17587 "Non-fatal program bug: couldn't set break at $i_break_left\n"
17588                 );
17589                 report_definite_bug();
17590                 return;
17591             }
17592             $i_f = $ri_first->[$line_number];
17593             $i_l = $ri_last->[$line_number];
17594         }
17595
17596         # Do not leave a blank at the end of a line; back up if necessary
17597         if ( $types_to_go[$i_break_left] eq 'b' ) { $i_break_left-- }
17598
17599         my $i_break_right = $inext_to_go[$i_break_left];
17600         if (   $i_break_left >= $i_f
17601             && $i_break_left < $i_l
17602             && $i_break_right > $i_f
17603             && $i_break_right <= $i_l )
17604         {
17605             splice( @{$ri_first}, $line_number, 1, ( $i_f, $i_break_right ) );
17606             splice( @{$ri_last}, $line_number, 1, ( $i_break_left, $i_l ) );
17607         }
17608     }
17609     return;
17610 }
17611
17612 sub set_closing_breakpoint {
17613
17614     # set a breakpoint at a matching closing token
17615     # at present, this is only used to break at a ':' which matches a '?'
17616     my $i_break = shift;
17617
17618     if ( $mate_index_to_go[$i_break] >= 0 ) {
17619
17620         # CAUTION: infinite recursion possible here:
17621         #   set_closing_breakpoint calls set_forced_breakpoint, and
17622         #   set_forced_breakpoint call set_closing_breakpoint
17623         #   ( test files attrib.t, BasicLyx.pm.html).
17624         # Don't reduce the '2' in the statement below
17625         if ( $mate_index_to_go[$i_break] > $i_break + 2 ) {
17626
17627             # break before } ] and ), but sub set_forced_breakpoint will decide
17628             # to break before or after a ? and :
17629             my $inc = ( $tokens_to_go[$i_break] eq '?' ) ? 0 : 1;
17630             set_forced_breakpoint( $mate_index_to_go[$i_break] - $inc );
17631         }
17632     }
17633     else {
17634         my $type_sequence = $type_sequence_to_go[$i_break];
17635         if ($type_sequence) {
17636             my $closing_token = $matching_token{ $tokens_to_go[$i_break] };
17637             $postponed_breakpoint{$type_sequence} = 1;
17638         }
17639     }
17640     return;
17641 }
17642
17643 sub compare_indentation_levels {
17644
17645     # check to see if output line tabbing agrees with input line
17646     # this can be very useful for debugging a script which has an extra
17647     # or missing brace
17648     my ( $guessed_indentation_level, $structural_indentation_level ) = @_;
17649     if ( $guessed_indentation_level ne $structural_indentation_level ) {
17650         $last_tabbing_disagreement = $input_line_number;
17651
17652         if ($in_tabbing_disagreement) {
17653         }
17654         else {
17655             $tabbing_disagreement_count++;
17656
17657             if ( $tabbing_disagreement_count <= MAX_NAG_MESSAGES ) {
17658                 write_logfile_entry(
17659 "Start indentation disagreement: input=$guessed_indentation_level; output=$structural_indentation_level\n"
17660                 );
17661             }
17662             $in_tabbing_disagreement    = $input_line_number;
17663             $first_tabbing_disagreement = $in_tabbing_disagreement
17664               unless ($first_tabbing_disagreement);
17665         }
17666     }
17667     else {
17668
17669         if ($in_tabbing_disagreement) {
17670
17671             if ( $tabbing_disagreement_count <= MAX_NAG_MESSAGES ) {
17672                 write_logfile_entry(
17673 "End indentation disagreement from input line $in_tabbing_disagreement\n"
17674                 );
17675
17676                 if ( $tabbing_disagreement_count == MAX_NAG_MESSAGES ) {
17677                     write_logfile_entry(
17678                         "No further tabbing disagreements will be noted\n");
17679                 }
17680             }
17681             $in_tabbing_disagreement = 0;
17682         }
17683     }
17684     return;
17685 }
17686 1;