File Coverage

blib/lib/Perl/Tidy/Tokenizer.pm
Criterion Covered Total %
statement 2691 3715 72.4
branch 1261 1934 65.2
condition 755 1199 62.9
subroutine 168 202 83.1
pod 0 147 0.0
total 4875 7197 67.7


line stmt bran cond sub pod time code
1             package Perl::Tidy::Tokenizer;
2              
3             #####################################################################
4             #
5             # Perl::Tidy::Tokenizer reads a source and breaks it into a stream of tokens
6             #
7             # Usage Outline:
8             #
9             # STEP 1: initialize or re-initialize Tokenizer with user options
10             # Perl::Tidy::Tokenizer::check_options($rOpts);
11             #
12             # STEP 2: create a tokenizer for a specific input source object
13             # my $tokenizer = Perl::Tidy::Tokenizer->new(
14             # source_object => $source,
15             # ...
16             # );
17             #
18             # STEP 3: get and process each tokenized 'line' (a hash ref of token info)
19             # while ( my $line = $tokenizer->get_line() ) {
20             # $formatter->write_line($line);
21             # }
22             #
23             # STEP 4: report errors
24             # my $severe_error = $tokenizer->report_tokenization_errors();
25             #
26             # The source object can be a STRING ref, an ARRAY ref, or an object with a
27             # get_line() method which supplies one line (a character string) perl call.
28             #
29             # NOTE: This is not a real class. Only one tokenizer my be used.
30             #
31             ########################################################################
32              
33 44     44   249 use strict;
  44         75  
  44         1375  
34 44     44   149 use warnings;
  44         63  
  44         1729  
35 44     44   172 use English qw( -no_match_vars );
  44         63  
  44         229  
36              
37             our $VERSION = '20260705';
38              
39 44     44   13504 use Carp;
  44         90  
  44         2222  
40              
41 44     44   179 use constant DEVEL_MODE => 0;
  44         84  
  44         2185  
42 44     44   172 use constant DEBUG_GUESS_MODE => 0;
  44         65  
  44         1727  
43 44     44   164 use constant EMPTY_STRING => q{};
  44         68  
  44         1525  
44 44     44   167 use constant SPACE => q{ };
  44         57  
  44         1586  
45 44     44   176 use constant COMMA => q{,};
  44         67  
  44         1573  
46 44     44   155 use constant BACKSLASH => q{\\};
  44         65  
  44         2277  
47              
48             { #<<< A non-indenting brace to contain all lexical variables
49              
50             # List of hash keys to prevent -duk from listing them.
51             # (note the backtick in this list)
52             my @unique_hash_keys_uu = qw( ` RPerl _rtype_sequence _ending_in_quote );
53              
54             # Parent sequence number of tree of containers; must be 1
55 44     44   185 use constant SEQ_ROOT => 1;
  44         78  
  44         1515  
56              
57             # Defaults for guessing old indentation
58 44     44   175 use constant INDENT_COLUMNS_DEFAULT => 4;
  44         102  
  44         1495  
59 44     44   166 use constant TAB_SIZE_DEFAULT => 8;
  44         84  
  44         1417  
60              
61             # Decimal values of some ascii characters for quick checks
62 44     44   152 use constant ORD_TAB => 9;
  44         81  
  44         1369  
63 44     44   194 use constant ORD_SPACE => 32;
  44         102  
  44         1800  
64 44     44   163 use constant ORD_PRINTABLE_MIN => 33;
  44         69  
  44         1232  
65 44     44   168 use constant ORD_PRINTABLE_MAX => 126;
  44         62  
  44         8079  
66              
67             # GLOBAL VARIABLES which change during tokenization:
68             # These could also be stored in $self but it is more convenient and
69             # efficient to make them global lexical variables.
70             # INITIALIZER: sub prepare_for_a_new_file
71             my (
72              
73             $brace_depth,
74             $context,
75             $current_package,
76             $last_nonblank_block_type,
77             $last_nonblank_token,
78             $last_nonblank_type,
79             $next_sequence_number,
80             $paren_depth,
81             $rbrace_context,
82             $rbrace_package,
83             $rbrace_structural_type,
84             $rbrace_type,
85             $rcurrent_depth,
86             $rcurrent_sequence_number,
87             $ris_lexical_sub,
88             $rdepth_array,
89             $ris_block_function,
90             $ris_block_list_function,
91             $ris_constant,
92             $ris_user_function,
93             $rnested_statement_type,
94             $rnested_ternary_flag,
95             $rparen_semicolon_count,
96             $rparen_vars,
97             $rparen_type,
98             $rsaw_function_definition,
99             $rsaw_use_module,
100             $rsquare_bracket_structural_type,
101             $rsquare_bracket_type,
102             $rstarting_line_of_current_depth,
103             $rtotal_depth,
104             $ruser_function_prototype,
105             $square_bracket_depth,
106             $statement_type,
107             $total_depth,
108             );
109              
110             my (
111              
112             # GLOBAL CONSTANTS for routines in this package,
113             # INITIALIZER: BEGIN block.
114             %can_start_digraph,
115             %expecting_operator_token,
116             %expecting_operator_types,
117             %expecting_term_token,
118             %expecting_term_types,
119             %is_block_operator,
120             %is_digraph,
121             %is_file_test_operator,
122             %is_if_elsif_unless,
123             %is_if_elsif_unless_case_when,
124             %is_indirect_object_taker,
125             %is_keyword_rejecting_question_as_pattern_delimiter,
126             %is_keyword_rejecting_slash_as_pattern_delimiter,
127             %is_keyword_taking_list,
128             %is_keyword_taking_optional_arg,
129             %is_q_qq_qw_qx_qr_s_y_tr_m,
130             %is_q_qq_qx_qr_s_y_tr_m,
131             %quote_modifiers,
132             %is_semicolon_or_t,
133             %is_sort_map_grep,
134             %is_sort_map_grep_eval_do_sub,
135             %is_tetragraph,
136             %is_trigraph,
137             %is_valid_token_type,
138             %other_line_endings,
139             %is_binary_operator_type,
140             %is_binary_keyword,
141             %is_binary_or_unary_operator_type,
142             %is_binary_or_unary_keyword,
143             %is_not_a_TERM_producer_type,
144             @closing_brace_names,
145             @opening_brace_names,
146              
147             # GLOBAL CONSTANT hash lookup table of operator expected values
148             # INITIALIZER: BEGIN block
149             %op_expected_table,
150              
151             # GLOBAL VARIABLES which are constant after being configured.
152             # INITIALIZER: BEGIN block and modified by sub check_options
153             %is_code_block_token,
154             %is_zero_continuation_block_type,
155             %is_keyword,
156             %is_TERM_keyword,
157             %is_my_our_state,
158             %is_package,
159             %matching_end_token,
160              
161             # INITIALIZER: sub check_options
162             $code_skipping_pattern_begin,
163             $code_skipping_pattern_end,
164             $format_skipping_pattern_begin,
165             $format_skipping_pattern_end,
166              
167             $rOpts_code_skipping,
168             $rOpts_code_skipping_begin,
169             $rOpts_format_skipping,
170             $rOpts_format_skipping_begin,
171             $rOpts_format_skipping_end,
172             $rOpts_starting_indentation_level,
173             $rOpts_indent_columns,
174             $rOpts_look_for_hash_bang,
175             $rOpts_look_for_autoloader,
176             $rOpts_look_for_selfloader,
177             $rOpts_trim_qw,
178             $rOpts_extended_syntax,
179             $rOpts_continuation_indentation,
180             $rOpts_outdent_labels,
181             $rOpts_maximum_level_errors,
182             $rOpts_maximum_unexpected_errors,
183             $rOpts_indent_closing_brace,
184             $rOpts_non_indenting_braces,
185             $rOpts_non_indenting_brace_prefix,
186             $rOpts_whitespace_cycle,
187              
188             $tabsize,
189             %is_END_DATA_format_sub,
190             %is_grep_alias,
191             %is_sub,
192             $guess_if_method,
193             );
194              
195             # possible values of operator_expected()
196 44     44   206 use constant TERM => -1;
  44         113  
  44         1901  
197 44     44   203 use constant UNKNOWN => 0;
  44         95  
  44         1452  
198 44     44   169 use constant OPERATOR => 1;
  44         66  
  44         1729  
199              
200             # possible values of context
201 44     44   186 use constant SCALAR_CONTEXT => -1;
  44         70  
  44         1443  
202 44     44   224 use constant UNKNOWN_CONTEXT => 0;
  44         77  
  44         1355  
203 44     44   154 use constant LIST_CONTEXT => 1;
  44         76  
  44         1496  
204              
205             # Maximum number of little messages; probably need not be changed.
206 44     44   171 use constant MAX_NAG_MESSAGES => 6;
  44         69  
  44         8716  
207              
208 0         0 BEGIN {
209              
210             # Array index names for $self.
211             # Do not combine with other BEGIN blocks (c101).
212 44     44   314839 my $i = 0;
213             use constant {
214 44         14712 _rhere_target_list_ => $i++,
215             _in_here_doc_ => $i++,
216             _here_doc_target_ => $i++,
217             _here_quote_character_ => $i++,
218             _in_data_ => $i++,
219             _in_end_ => $i++,
220             _in_format_ => $i++,
221             _in_error_ => $i++,
222             _do_not_format_ => $i++,
223             _warning_count_ => $i++,
224             _html_tag_count_ => $i++,
225             _in_pod_ => $i++,
226             _in_code_skipping_ => $i++,
227             _in_format_skipping_ => $i++,
228             _rformat_skipping_list_ => $i++,
229             _in_attribute_list_ => $i++,
230             _in_quote_ => $i++,
231             _quote_target_ => $i++,
232             _line_start_quote_ => $i++,
233             _starting_level_ => $i++,
234             _know_starting_level_ => $i++,
235             _last_line_number_ => $i++,
236             _saw_perl_dash_P_ => $i++,
237             _saw_perl_dash_w_ => $i++,
238             _saw_use_strict_ => $i++,
239             _saw_brace_error_ => $i++,
240             _hit_bug_ => $i++,
241             _look_for_autoloader_ => $i++,
242             _look_for_selfloader_ => $i++,
243             _saw_autoloader_ => $i++,
244             _saw_selfloader_ => $i++,
245             _saw_hash_bang_ => $i++,
246             _saw_end_ => $i++,
247             _saw_data_ => $i++,
248             _saw_negative_indentation_ => $i++,
249             _started_tokenizing_ => $i++,
250             _debugger_object_ => $i++,
251             _diagnostics_object_ => $i++,
252             _logger_object_ => $i++,
253             _save_logfile_ => $i++,
254             _unexpected_error_count_ => $i++,
255             _started_looking_for_here_target_at_ => $i++,
256             _nearly_matched_here_target_at_ => $i++,
257             _line_of_text_ => $i++,
258             _rlower_case_labels_at_ => $i++,
259             _maximum_level_ => $i++,
260             _true_brace_error_count_ => $i++,
261             _rOpts_ => $i++,
262             _rinput_lines_ => $i++,
263             _input_line_index_next_ => $i++,
264             _rtrimmed_input_lines_ => $i++,
265             _rclosing_brace_indentation_hash_ => $i++,
266             _show_indentation_table_ => $i++,
267             _rnon_indenting_brace_stack_ => $i++,
268             _rseqno_at_depth_ => $i++,
269             _rbareword_info_ => $i++,
270             _rsaw_unknown_syntax_in_seqno_ => $i++,
271 44     44   259 };
  44         74  
272             } ## end BEGIN
273              
274             { ## closure for subs to count instances
275              
276             # methods to count instances
277             my $_count = 0;
278 0     0 0 0 sub get_count { return $_count; }
279 659     659   1825 sub _increment_count { return ++$_count }
280 659     659   1028 sub _decrement_count { return --$_count }
281             }
282              
283             sub DESTROY {
284 659     659   1096 my $self = shift;
285 659         1902 _decrement_count();
286 659         14305 return;
287             }
288              
289             sub AUTOLOAD {
290              
291             # Catch any undefined sub calls so that we are sure to get
292             # some diagnostic information. This sub should never be called
293             # except for a programming error.
294 0     0   0 our $AUTOLOAD;
295 0 0       0 return if ( $AUTOLOAD =~ /\bDESTROY$/ );
296 0         0 my ( $pkg, $fname, $lno ) = caller();
297 0         0 my $my_package = __PACKAGE__;
298 0         0 print {*STDERR} <<EOM;
  0         0  
299             ======================================================================
300             Error detected in package '$my_package', version $VERSION
301             Received unexpected AUTOLOAD call for sub '$AUTOLOAD'
302             Called from package: '$pkg'
303             Called from File '$fname' at line '$lno'
304             This error is probably due to a recent programming change
305             ======================================================================
306             EOM
307 0         0 exit 1;
308             } ## end sub AUTOLOAD
309              
310             sub Die {
311 0     0 0 0 my ($msg) = @_;
312 0         0 Perl::Tidy::Die($msg);
313 0         0 croak "unexpected return from Perl::Tidy::Die";
314             }
315              
316             sub Warn {
317 0     0 0 0 my ($msg) = @_;
318 0         0 Perl::Tidy::Warn($msg);
319 0         0 return;
320             }
321              
322             sub Fault {
323 0     0 0 0 my ($msg) = @_;
324              
325             # This routine is called for errors that really should not occur
326             # except if there has been a bug introduced by a recent program change.
327             # Please add comments at calls to Fault to explain why the call
328             # should not occur, and where to look to fix it.
329 0         0 my ( $package0_uu, $filename0_uu, $line0, $subroutine0_uu ) = caller(0);
330 0         0 my ( $package1_uu, $filename1, $line1, $subroutine1 ) = caller(1);
331 0         0 my ( $package2_uu, $filename2_uu, $line2_uu, $subroutine2 ) = caller(2);
332 0         0 my $pkg = __PACKAGE__;
333 0         0 my $input_stream_name = Perl::Tidy::get_input_stream_name();
334              
335 0         0 Die(<<EOM);
336             ==============================================================================
337             While operating on input stream with name: '$input_stream_name'
338             A fault was detected at line $line0 of sub '$subroutine1'
339             in file '$filename1'
340             which was called from line $line1 of sub '$subroutine2'
341             Message: '$msg'
342             This is probably an error introduced by a recent programming change.
343             $pkg reports VERSION='$VERSION'.
344             ==============================================================================
345             EOM
346              
347 0         0 croak "unexpected return from sub Die";
348             } ## end sub Fault
349              
350             sub bad_pattern {
351 2628     2628 0 3537 my ($pattern) = @_;
352              
353             # Return true if a regex pattern has an error
354             # Note: Formatter.pm also has a copy of this
355 2628         3051 my $regex_uu = eval { qr/$pattern/ };
  2628         74611  
356 2628         7648 return $EVAL_ERROR;
357             } ## end sub bad_pattern
358              
359             sub make_skipping_pattern {
360 2628     2628 0 4256 my ( $rOpts, $opt_name, $default ) = @_;
361              
362             # Make regex patterns for the format-skipping and code-skipping options
363 2628         3738 my $param = $rOpts->{$opt_name};
364 2628 100       4020 if ( !$param ) { $param = $default }
  2624         2958  
365 2628         5467 $param =~ s/^\s+//;
366 2628 50       5431 if ( $param !~ /^#/ ) {
367 0         0 Die("ERROR: the $opt_name parameter '$param' must begin with '#'\n");
368             }
369              
370             # Note that the ending \s will match a newline
371 2628         3678 my $pattern = '^\s*' . $param . '\s';
372 2628 50       4437 if ( bad_pattern($pattern) ) {
373 0         0 Die(
374             "ERROR: the $opt_name parameter '$param' causes the invalid regex '$pattern'\n"
375             );
376             }
377 2628         4534 return $pattern;
378             } ## end sub make_skipping_pattern
379              
380             sub check_options {
381              
382             # Check and pre-process tokenizer parameters
383 657     657 0 1250 my $rOpts = shift;
384              
385 657         1714 %is_sub = ();
386 657         1551 $is_sub{'sub'} = 1;
387              
388 657         3641 %is_END_DATA_format_sub = (
389             '__END__' => 1,
390             '__DATA__' => 1,
391             'format' => 1,
392             'sub' => 1,
393             );
394              
395             # Install any aliases to 'sub'
396 657 100       1878 if ( $rOpts->{'sub-alias-list'} ) {
397              
398             # Note that any 'sub-alias-list' has been preprocessed to
399             # be a trimmed, space-separated list which includes 'sub'
400             # for example, it might be 'sub method fun'
401 3         14 my @sub_alias_list = split /\s+/, $rOpts->{'sub-alias-list'};
402 3         6 foreach my $word (@sub_alias_list) {
403 11         17 $is_sub{$word} = 1;
404 11         16 $is_END_DATA_format_sub{$word} = 1;
405             }
406             }
407              
408             # Set global flag to say if we have to guess if bareword 'method' is
409             # a sub when 'method' is in %is_sub. This will be true unless:
410             # (1) the user entered 'method' as sub alias, or
411             # (2) the user set --use-feature=class
412             # In these two cases we can assume that 'method' is a sub alias.
413 657         1007 $guess_if_method = 1;
414 657 100       1681 if ( $is_sub{'method'} ) { $guess_if_method = 0 }
  2         3  
415              
416             #------------------------------------------------
417             # Update hash values for any -use-feature options
418             #------------------------------------------------
419              
420 657         996 my $use_feature_class = 1;
421              
422 657         1307 my $str = $rOpts->{'use-feature'};
423 657 50 33     1806 if ( defined($str) && length($str) ) {
424 0         0 $str =~ s/^\s+//;
425 0         0 $str =~ s/\s+$//;
426 0 0       0 if ( !length($str) ) {
    0          
    0          
427             ## all spaces
428             }
429             elsif ( $str =~ /\bnoclass\b/ ) {
430 0         0 $use_feature_class = 0;
431             }
432             elsif ( $str =~ /\bclass\b/ ) {
433 0         0 $guess_if_method = 0;
434             }
435             else {
436             # At present, only 'class' and 'noclass' are valid strings
437             # This is just a Warn, for testing, but will eventually be Die
438 0         0 Warn(
439             "Unexpected text in --use-feature: expecting 'class' or 'noclass'\n"
440             );
441             }
442             }
443              
444             # These are the main updates for this option. There are additional
445             # changes elsewhere, usually indicated with a comment 'rt145706'
446              
447             # Update hash values for use_feature=class, added for rt145706
448             # see 'perlclass.pod'
449              
450             # IMPORTANT: We are changing global hash values initially set in a BEGIN
451             # block. Values must be defined (true or false) for each of these new
452             # words whether true or false. Otherwise, programs using the module which
453             # change options between runs (such as test code) will have
454             # incorrect settings and fail.
455              
456             # There are 4 new keywords:
457              
458             # 'class' - treated specially as generalization of 'package'
459             # Note: we must not set 'class' to be a keyword to avoid problems
460             # with older uses.
461 657         1603 $is_package{'class'} = $use_feature_class;
462              
463             # 'method' - treated like sub using the sub-alias-list option
464             # Note: we must not set 'method' to be a keyword to avoid problems
465             # with older uses.
466 657 50       1459 if ($use_feature_class) {
467 657         1201 $is_sub{'method'} = 1;
468 657         1263 $is_END_DATA_format_sub{'method'} = 1;
469             }
470              
471             # 'field' - added as a keyword, and works like 'my'
472             # Setting zero_continuation_block_type allows inclusion in table of level
473             # differences in case of a missing or extra brace (see sub wrapup).
474 657         1469 $is_keyword{'field'} = $use_feature_class;
475 657         1279 $is_my_our_state{'field'} = $use_feature_class;
476 657         1251 $is_zero_continuation_block_type{'field'} = $use_feature_class;
477              
478             # 'ADJUST' - added as a keyword and works like 'BEGIN'
479             # See update git #182 for 'ADJUST :params'
480             # Setting zero_continuation_block_type allows inclusion in table of level
481             # differences in case of a missing or extra brace (see sub wrapup).
482 657         1318 $is_keyword{'ADJUST'} = $use_feature_class;
483 657         1208 $is_code_block_token{'ADJUST'} = $use_feature_class;
484 657         1098 $is_zero_continuation_block_type{'ADJUST'} = $use_feature_class;
485              
486 657         1722 %is_grep_alias = ();
487 657 50       1676 if ( $rOpts->{'grep-alias-list'} ) {
488              
489             # Note that 'grep-alias-list' has been preprocessed to be a trimmed,
490             # space-separated list
491 657         2510 my @q = split /\s+/, $rOpts->{'grep-alias-list'};
492 657         3864 $is_grep_alias{$_} = 1 for @q;
493             }
494              
495 657         1276 $rOpts_starting_indentation_level = $rOpts->{'starting-indentation-level'};
496 657         1271 $rOpts_indent_columns = $rOpts->{'indent-columns'};
497 657         1070 $rOpts_look_for_hash_bang = $rOpts->{'look-for-hash-bang'};
498 657         1124 $rOpts_look_for_autoloader = $rOpts->{'look-for-autoloader'};
499 657         1042 $rOpts_look_for_selfloader = $rOpts->{'look-for-selfloader'};
500 657         1067 $rOpts_trim_qw = $rOpts->{'trim-qw'};
501 657         1056 $rOpts_extended_syntax = $rOpts->{'extended-syntax'};
502 657         1145 $rOpts_continuation_indentation = $rOpts->{'continuation-indentation'};
503 657         1065 $rOpts_outdent_labels = $rOpts->{'outdent-labels'};
504 657         1144 $rOpts_maximum_level_errors = $rOpts->{'maximum-level-errors'};
505 657         1068 $rOpts_maximum_unexpected_errors = $rOpts->{'maximum-unexpected-errors'};
506 657         996 $rOpts_code_skipping = $rOpts->{'code-skipping'};
507 657         1066 $rOpts_code_skipping_begin = $rOpts->{'code-skipping-begin'};
508 657         996 $rOpts_format_skipping = $rOpts->{'format-skipping'};
509 657         1039 $rOpts_format_skipping_begin = $rOpts->{'format-skipping-begin'};
510 657         1096 $rOpts_format_skipping_end = $rOpts->{'format-skipping-end'};
511 657         1001 $rOpts_indent_closing_brace = $rOpts->{'indent-closing-brace'};
512 657         1092 $rOpts_non_indenting_braces = $rOpts->{'non-indenting-braces'};
513 657         1022 $rOpts_non_indenting_brace_prefix = $rOpts->{'non-indenting-brace-prefix'};
514 657         1008 $rOpts_whitespace_cycle = $rOpts->{'whitespace-cycle'};
515              
516             # In the Tokenizer, --indent-columns is just used for guessing old
517             # indentation, and must be positive. If -i=0 is used for this run (which
518             # is possible) we'll just guess that the old run used 4 spaces per level.
519 657 100       1479 if ( !$rOpts_indent_columns ) {
520 12         25 $rOpts_indent_columns = INDENT_COLUMNS_DEFAULT;
521             }
522              
523             # Define $tabsize, the number of spaces per tab for use in
524             # guessing the indentation of source lines with leading tabs.
525             # Assume same as for this run if tabs are used, otherwise assume
526             # a default value, typically 8
527             $tabsize =
528             $rOpts->{'entab-leading-whitespace'}
529             ? $rOpts->{'entab-leading-whitespace'}
530             : $rOpts->{'tabs'} ? $rOpts->{'indent-columns'}
531 657 50       2310 : $rOpts->{'default-tabsize'};
    100          
532 657 50       1470 if ( !$tabsize ) { $tabsize = TAB_SIZE_DEFAULT }
  0         0  
533              
534             $code_skipping_pattern_begin =
535 657         2130 make_skipping_pattern( $rOpts, 'code-skipping-begin', '#<<V' );
536 657         1643 $code_skipping_pattern_end =
537             make_skipping_pattern( $rOpts, 'code-skipping-end', '#>>V' );
538              
539 657         1715 $format_skipping_pattern_begin =
540             make_skipping_pattern( $rOpts, 'format-skipping-begin', '#<<<' );
541 657         1523 $format_skipping_pattern_end =
542             make_skipping_pattern( $rOpts, 'format-skipping-end', '#>>>' );
543              
544 657         1697 return;
545             } ## end sub check_options
546              
547             sub new {
548              
549 659     659 0 2370 my ( $class, @arglist ) = @_;
550 659 50       1803 if ( @arglist % 2 ) { croak "Odd number of items in arg hash list\n" }
  0         0  
551              
552 659         4838 my %defaults = (
553             source_object => undef,
554             debugger_object => undef,
555             diagnostics_object => undef,
556             logger_object => undef,
557             starting_level => undef,
558             starting_line_number => 1,
559             rOpts => {},
560             );
561 659         3471 my %args = ( %defaults, @arglist );
562              
563             # we are given an object with a get_line() method to supply source lines
564 659         1592 my $source_object = $args{source_object};
565 659         1043 my $rOpts = $args{rOpts};
566              
567             # Check call args
568 659 50       1659 if ( !defined($source_object) ) {
569 0         0 Die(
570             "Perl::Tidy::Tokenizer::new called without a 'source_object' parameter\n"
571             );
572             }
573 659 50       1592 if ( !ref($source_object) ) {
574 0         0 Die(<<EOM);
575             sub Perl::Tidy::Tokenizer::new received a 'source_object' parameter which is not a reference;
576             'source_object' must be a reference to a STRING, ARRAY, or object with a 'getline' method
577             EOM
578             }
579              
580 659         1080 my $logger_object = $args{logger_object};
581              
582             # Tokenizer state data is as follows:
583             # _rhere_target_list_ reference to list of here-doc targets
584             # _here_doc_target_ the target string for a here document
585             # _here_quote_character_ the type of here-doc quoting (" ' ` or none)
586             # to determine if interpolation is done
587             # _quote_target_ character we seek if chasing a quote
588             # _line_start_quote_ line where we started looking for a long quote
589             # _in_here_doc_ flag indicating if we are in a here-doc
590             # _in_pod_ flag set if we are in pod documentation
591             # _in_code_skipping_ flag set if we are in a code skipping section
592             # _in_format_skipping_ flag set if we are in a format skipping section
593             # _in_error_ flag set if we saw severe error (binary in script)
594             # _do_not_format_ flag set if formatting should be skipped
595             # _warning_count_ number of calls to logger sub warning
596             # _html_tag_count_ number of apparent html tags seen (indicates html)
597             # _in_data_ flag set if we are in __DATA__ section
598             # _in_end_ flag set if we are in __END__ section
599             # _in_format_ flag set if we are in a format description
600             # _in_attribute_list_ flag telling if we are looking for attributes
601             # _in_quote_ flag telling if we are chasing a quote
602             # _starting_level_ indentation level of first line
603             # _diagnostics_object_ place to write debugging information
604             # _unexpected_error_count_ error count used to limit output
605             # _lower_case_labels_at_ line numbers where lower case labels seen
606             # _hit_bug_ program bug detected
607              
608 659         951 my $self = [];
609 659         1363 $self->[_rhere_target_list_] = [];
610 659         1319 $self->[_in_here_doc_] = 0;
611 659         1378 $self->[_here_doc_target_] = EMPTY_STRING;
612 659         1108 $self->[_here_quote_character_] = EMPTY_STRING;
613 659         1259 $self->[_in_data_] = 0;
614 659         1434 $self->[_in_end_] = 0;
615 659         1233 $self->[_in_format_] = 0;
616 659         1019 $self->[_in_error_] = 0;
617 659         1206 $self->[_do_not_format_] = 0;
618 659         1009 $self->[_warning_count_] = 0;
619 659         1189 $self->[_html_tag_count_] = 0;
620 659         931 $self->[_in_pod_] = 0;
621             $self->[_in_code_skipping_] =
622 659   33     1936 $rOpts->{'code-skipping-from-start'} && $rOpts_code_skipping;
623 659         953 $self->[_in_format_skipping_] = 0;
624 659         1115 $self->[_rformat_skipping_list_] = [];
625 659         1200 $self->[_in_attribute_list_] = 0;
626 659         1128 $self->[_in_quote_] = 0;
627 659         1002 $self->[_quote_target_] = EMPTY_STRING;
628 659         1433 $self->[_line_start_quote_] = -1;
629 659         1145 $self->[_starting_level_] = $args{starting_level};
630 659         1410 $self->[_know_starting_level_] = defined( $args{starting_level} );
631 659         1257 $self->[_last_line_number_] = $args{starting_line_number} - 1;
632 659         1433 $self->[_saw_perl_dash_P_] = 0;
633 659         1049 $self->[_saw_perl_dash_w_] = 0;
634 659         1061 $self->[_saw_use_strict_] = 0;
635 659         1067 $self->[_saw_brace_error_] = 0;
636 659         1005 $self->[_hit_bug_] = 0;
637 659         1336 $self->[_look_for_autoloader_] = $rOpts_look_for_autoloader;
638 659         1042 $self->[_look_for_selfloader_] = $rOpts_look_for_selfloader;
639 659         1026 $self->[_saw_autoloader_] = 0;
640 659         997 $self->[_saw_selfloader_] = 0;
641 659         993 $self->[_saw_hash_bang_] = 0;
642 659         959 $self->[_saw_end_] = 0;
643 659         1269 $self->[_saw_data_] = 0;
644 659         969 $self->[_saw_negative_indentation_] = 0;
645 659         973 $self->[_started_tokenizing_] = 0;
646 659         983 $self->[_debugger_object_] = $args{debugger_object};
647 659         1031 $self->[_diagnostics_object_] = $args{diagnostics_object};
648 659         1001 $self->[_logger_object_] = $logger_object;
649 659         1176 $self->[_unexpected_error_count_] = 0;
650 659         966 $self->[_started_looking_for_here_target_at_] = 0;
651 659         977 $self->[_nearly_matched_here_target_at_] = undef;
652 659         1022 $self->[_line_of_text_] = EMPTY_STRING;
653 659         995 $self->[_rlower_case_labels_at_] = undef;
654 659         993 $self->[_maximum_level_] = 0;
655 659         1019 $self->[_true_brace_error_count_] = 0;
656 659         1336 $self->[_rnon_indenting_brace_stack_] = [];
657 659         1425 $self->[_rseqno_at_depth_] = [SEQ_ROOT];
658 659         1055 $self->[_show_indentation_table_] = 0;
659 659         1027 $self->[_rbareword_info_] = {};
660 659         1221 $self->[_rsaw_unknown_syntax_in_seqno_] = {};
661              
662 659         4412 $self->[_rclosing_brace_indentation_hash_] = {
663             valid => undef,
664             rhistory_line_number => [0],
665             rhistory_level_diff => [0],
666             rhistory_anchor_point => [1],
667             };
668              
669 659         1291 $self->[_rOpts_] = $rOpts;
670 659   100     2747 $self->[_save_logfile_] =
671             defined($logger_object) && $logger_object->get_save_logfile();
672              
673 659         1366 bless $self, $class;
674              
675 659         3169 $self->prepare_for_a_new_file($source_object);
676 659         2837 $self->find_starting_indentation_level();
677              
678             # This is not a full class yet, so die if an attempt is made to
679             # create more than one object.
680              
681 659 50       1980 if ( _increment_count() > 1 ) {
682 0         0 confess
683             "Attempt to create more than 1 object in $class, which is not a true class yet\n";
684             }
685              
686 659         4395 return $self;
687              
688             } ## end sub new
689              
690             # Called externally
691             sub get_unexpected_error_count {
692 4     4 0 9 my ($self) = @_;
693 4         14 return $self->[_unexpected_error_count_];
694             }
695              
696             # Called externally
697             sub is_keyword {
698 4     4 0 9 my ($str) = @_;
699 4         17 return $is_keyword{$str};
700             }
701              
702             #----------------------------------------------------------------
703             # Line input routines, previously handled by the LineBuffer class
704             #----------------------------------------------------------------
705             sub make_source_array {
706              
707 659     659 0 1234 my ( $self, $line_source_object ) = @_;
708              
709             # Convert the source into an array of lines
710             # Given:
711             # $line_source_object = the input source stream
712             # Task:
713             # Convert the source to an array ref and store in $self
714              
715 659         966 my $rinput_lines = [];
716              
717 659         1160 my $rsource = ref($line_source_object);
718 659         940 my $source_string;
719              
720 659 50       2840 if ( !$rsource ) {
    50          
    50          
721              
722             # shouldn't happen: this should have been checked in sub new
723 0         0 Fault(<<EOM);
724             sub Perl::Tidy::Tokenizer::new received a 'source_object' parameter which is not a reference;
725             'source_object' must be a reference to a STRING, ARRAY, or object with a 'getline' method
726             EOM
727             }
728              
729             # handle an ARRAY ref
730             elsif ( $rsource eq 'ARRAY' ) {
731 0         0 $rinput_lines = $line_source_object;
732 0         0 $source_string = join( EMPTY_STRING, @{$line_source_object} );
  0         0  
733             }
734              
735             # handle a SCALAR ref
736             elsif ( $rsource eq 'SCALAR' ) {
737 659         896 $source_string = ${$line_source_object};
  659         1279  
738 659         3725 my @lines = split /^/, $source_string;
739 659         1546 $rinput_lines = \@lines;
740             }
741              
742             # handle an object - must have a get_line method
743             else {
744              
745             # This will die if user's object does have a 'get_line' method
746 0         0 my $line;
747 0         0 while ( defined( $line = $line_source_object->get_line() ) ) {
748 0         0 push( @{$rinput_lines}, $line );
  0         0  
749             }
750 0         0 $source_string = join( EMPTY_STRING, @{$rinput_lines} );
  0         0  
751             }
752              
753             # Get trimmed lines. It is much faster to strip leading whitespace from
754             # the whole input file at once than line-by-line.
755              
756             # Add a terminal newline if needed to keep line count unchanged:
757             # - avoids problem of losing a last line which is just \r and no \n (c283)
758             # - but check input line count to avoid adding line to an empty file (c286)
759 659 100 100     957 if ( @{$rinput_lines} && $source_string !~ /\n$/ ) {
  659         4748  
760 1         2 $source_string .= "\n";
761             }
762              
763             # Remove leading whitespace except newlines
764 659         6793 $source_string =~ s/^ [^\S\n]+ //gxm;
765              
766             # Then break the string into lines
767 659         3314 my @trimmed_lines = split /^/, $source_string;
768              
769             # Safety check - a change in number of lines would be a disaster
770 659 50       1034 if ( @trimmed_lines != @{$rinput_lines} ) {
  659         1649  
771              
772             # Shouldn't happen - die in DEVEL_MODE and fix
773 0         0 my $ntr = @trimmed_lines;
774 0         0 my $utr = @{$rinput_lines};
  0         0  
775 0         0 DEVEL_MODE
776             && Fault("trimmed / untrimmed line counts differ: $ntr / $utr\n");
777              
778             # Otherwise we can safely continue with undefined trimmed lines. They
779             # will be detected and fixed later.
780 0         0 @trimmed_lines = ();
781             }
782              
783 659         1371 $self->[_rinput_lines_] = $rinput_lines;
784 659         1320 $self->[_rtrimmed_input_lines_] = \@trimmed_lines;
785 659         1123 $self->[_input_line_index_next_] = 0;
786 659         1254 return;
787             } ## end sub make_source_array
788              
789             sub peek_ahead {
790 1395     1395 0 2207 my ( $self, $buffer_index ) = @_;
791              
792             # look $buffer_index lines ahead of the current location in the input
793             # stream without disturbing the input
794 1395         1612 my $line;
795 1395         1791 my $rinput_lines = $self->[_rinput_lines_];
796 1395         2020 my $line_index = $buffer_index + $self->[_input_line_index_next_];
797 1395 100       1600 if ( $line_index < @{$rinput_lines} ) {
  1395         2805  
798 1383         2075 $line = $rinput_lines->[$line_index];
799             }
800 1395         3597 return $line;
801             } ## end sub peek_ahead
802              
803             #-----------------------------------------
804             # interface to Perl::Tidy::Logger routines
805             #-----------------------------------------
806             sub warning {
807              
808 0     0 0 0 my ( $self, $msg ) = @_;
809              
810 0         0 my $logger_object = $self->[_logger_object_];
811 0         0 $self->[_warning_count_]++;
812 0 0       0 if ($logger_object) {
813 0         0 my $msg_line_number = $self->[_last_line_number_];
814 0         0 $logger_object->warning( $msg, $msg_line_number );
815             }
816 0         0 return;
817             } ## end sub warning
818              
819             sub warning_do_not_format {
820 0     0 0 0 my ( $self, $msg ) = @_;
821              
822             # Issue a warning message and set a flag to skip formatting this file.
823 0         0 $self->warning($msg);
824 0         0 $self->[_do_not_format_] = 1;
825 0         0 return;
826             } ## end sub warning_do_not_format
827              
828             sub complain {
829              
830 35     35 0 74 my ( $self, $msg ) = @_;
831              
832 35         62 my $logger_object = $self->[_logger_object_];
833 35 50       100 if ($logger_object) {
834 35         54 my $input_line_number = $self->[_last_line_number_];
835 35         170 $logger_object->complain( $msg, $input_line_number );
836             }
837 35         55 return;
838             } ## end sub complain
839              
840             sub write_logfile_entry {
841              
842 2240     2240 0 3845 my ( $self, $msg ) = @_;
843              
844 2240         3041 my $logger_object = $self->[_logger_object_];
845 2240 100       3958 if ($logger_object) {
846 2234         5484 $logger_object->write_logfile_entry($msg);
847             }
848 2240         3499 return;
849             } ## end sub write_logfile_entry
850              
851             sub interrupt_logfile {
852              
853 0     0 0 0 my $self = shift;
854              
855 0         0 my $logger_object = $self->[_logger_object_];
856 0 0       0 if ($logger_object) {
857 0         0 $logger_object->interrupt_logfile();
858             }
859 0         0 return;
860             } ## end sub interrupt_logfile
861              
862             sub resume_logfile {
863              
864 0     0 0 0 my $self = shift;
865              
866 0         0 my $logger_object = $self->[_logger_object_];
867 0 0       0 if ($logger_object) {
868 0         0 $logger_object->resume_logfile();
869             }
870 0         0 return;
871             } ## end sub resume_logfile
872              
873             sub brace_warning {
874 0     0 0 0 my ( $self, $msg ) = @_;
875 0         0 $self->[_saw_brace_error_]++;
876              
877 0         0 my $logger_object = $self->[_logger_object_];
878 0 0       0 if ($logger_object) {
879 0         0 my $msg_line_number = $self->[_last_line_number_];
880 0         0 $logger_object->brace_warning( $msg, $msg_line_number );
881             }
882 0         0 return;
883             } ## end sub brace_warning
884              
885             sub increment_brace_error {
886              
887             # This is same as sub brace_warning but without a message
888 0     0 0 0 my $self = shift;
889 0         0 $self->[_saw_brace_error_]++;
890              
891 0         0 my $logger_object = $self->[_logger_object_];
892 0 0       0 if ($logger_object) {
893 0         0 $logger_object->increment_brace_error();
894             }
895 0         0 return;
896             } ## end sub increment_brace_error
897              
898             sub get_saw_brace_error {
899 0     0 0 0 my $self = shift;
900 0         0 return $self->[_saw_brace_error_];
901             }
902              
903             sub report_definite_bug {
904 0     0 0 0 my $self = shift;
905 0         0 $self->[_hit_bug_] = 1;
906 0         0 my $logger_object = $self->[_logger_object_];
907 0 0       0 if ($logger_object) {
908 0         0 $logger_object->report_definite_bug();
909             }
910 0         0 return;
911             } ## end sub report_definite_bug
912              
913             #-------------------------------------
914             # Interface to Perl::Tidy::Diagnostics
915             #-------------------------------------
916             sub write_diagnostics {
917 0     0 0 0 my ( $self, $msg ) = @_;
918 0         0 my $input_line_number = $self->[_last_line_number_];
919 0         0 my $diagnostics_object = $self->[_diagnostics_object_];
920 0 0       0 if ($diagnostics_object) {
921 0         0 $diagnostics_object->write_diagnostics( $msg, $input_line_number );
922             }
923 0         0 return;
924             } ## end sub write_diagnostics
925              
926             sub report_tokenization_errors {
927              
928 659     659 0 1357 my ($self) = @_;
929              
930             # Report any tokenization errors and return a flag '$severe_error'.
931             # Set $severe_error = 1 if the tokenization errors are so severe that
932             # the formatter should not attempt to format the file. Instead, it will
933             # just output the file verbatim.
934              
935             # set severe error flag if tokenizer has encountered file reading problems
936             # (i.e. unexpected binary characters)
937             # or code which may not be formatted correctly (such as 'my sub q')
938             # The difference between _in_error_ and _do_not_format_ is that
939             # _in_error_ stops the tokenizer immediately whereas
940             # _do_not_format_ lets the tokenizer finish so that all errors are seen
941             # Both block formatting and cause the input stream to be output verbatim.
942 659   33     2948 my $severe_error = $self->[_in_error_] || $self->[_do_not_format_];
943              
944             # And do not format if it looks like an html file (c209)
945 659   33     3297 $severe_error ||= $self->[_html_tag_count_] && $self->[_warning_count_];
      33        
946              
947             # Inform the logger object on length of input stream
948 659         1316 my $logger_object = $self->[_logger_object_];
949 659 100       1703 if ($logger_object) {
950 657         1116 my $last_line_number = $self->[_last_line_number_];
951 657         3031 $logger_object->set_last_input_line_number($last_line_number);
952             }
953              
954 659         1027 my $maxle = $rOpts_maximum_level_errors;
955 659         955 my $maxue = $rOpts_maximum_unexpected_errors;
956 659 50       1462 $maxle = 1 unless ( defined($maxle) );
957 659 50       1342 $maxue = 0 unless ( defined($maxue) );
958              
959 659         2065 my $level = get_indentation_level();
960 659 50       1821 if ( $level != $self->[_starting_level_] ) {
961 0         0 $self->warning("final indentation level: $level\n");
962              
963 0         0 $self->[_show_indentation_table_] = 1;
964              
965 0         0 my $level_diff = $self->[_starting_level_] - $level;
966 0 0       0 if ( $level_diff < 0 ) { $level_diff = -$level_diff }
  0         0  
967              
968             # Set severe error flag if the level error is greater than 1.
969             # The formatter can function for any level error but it is probably
970             # best not to attempt formatting for a high level error.
971 0 0 0     0 if ( $maxle >= 0 && $level_diff > $maxle ) {
972 0         0 $severe_error = 1;
973 0         0 $self->warning(<<EOM);
974             Formatting will be skipped because level error '$level_diff' exceeds -maxle=$maxle; use -maxle=-1 to force formatting
975             EOM
976             }
977             }
978              
979 659         2946 $self->check_final_nesting_depths();
980              
981 659 50       1629 if ( $self->[_show_indentation_table_] ) {
982 0         0 $self->show_indentation_table();
983             }
984              
985             # Likewise, large numbers of brace errors usually indicate non-perl
986             # scripts, so set the severe error flag at a low number. This is similar
987             # to the level check, but different because braces may balance but be
988             # incorrectly interlaced.
989 659 50       1695 if ( $self->[_true_brace_error_count_] > 2 ) {
990 0         0 $severe_error = 1;
991             }
992              
993 659 50 66     1890 if ( $rOpts_look_for_hash_bang
994             && !$self->[_saw_hash_bang_] )
995             {
996 0         0 $self->warning(
997             "hit EOF without seeing hash-bang line; maybe don't need -x?\n");
998             }
999              
1000 659 50       1685 if ( $self->[_in_format_] ) {
1001 0         0 $self->warning("hit EOF while in format description\n");
1002             }
1003              
1004 659 50       1719 if ( $self->[_in_code_skipping_] ) {
1005 0         0 $self->write_logfile_entry(
1006             "hit EOF while in lines skipped with --code-skipping\n");
1007             }
1008              
1009 659 50       1711 if ( $self->[_in_pod_] ) {
1010              
1011             # Just write log entry if this is after __END__ or __DATA__
1012             # because this happens to often, and it is not likely to be
1013             # a parsing error.
1014 0 0 0     0 if ( $self->[_saw_data_] || $self->[_saw_end_] ) {
1015 0         0 $self->write_logfile_entry(
1016             "hit eof while in pod documentation (no =cut seen)\n\tthis can cause trouble with some pod utilities\n"
1017             );
1018             }
1019              
1020             else {
1021 0         0 $self->complain(
1022             "hit eof while in pod documentation (no =cut seen)\n\tthis can cause trouble with some pod utilities\n"
1023             );
1024             }
1025              
1026             }
1027              
1028 659 50       1702 if ( $self->[_in_here_doc_] ) {
1029 0         0 $severe_error = 1;
1030 0         0 my $here_doc_target = $self->[_here_doc_target_];
1031 0         0 my $started_looking_for_here_target_at =
1032             $self->[_started_looking_for_here_target_at_];
1033 0 0       0 if ($here_doc_target) {
1034 0         0 $self->warning(
1035             "hit EOF in here document starting at line $started_looking_for_here_target_at with target: $here_doc_target\n"
1036             );
1037             }
1038             else {
1039 0         0 $self->warning(<<EOM);
1040             Hit EOF in here document starting at line $started_looking_for_here_target_at with empty target string.
1041             (Perl will match to the end of file but this may not be intended).
1042             EOM
1043             }
1044 0         0 my $nearly_matched_here_target_at =
1045             $self->[_nearly_matched_here_target_at_];
1046 0 0       0 if ($nearly_matched_here_target_at) {
1047 0         0 $self->warning(
1048             "NOTE: almost matched at input line $nearly_matched_here_target_at except for whitespace\n"
1049             );
1050             }
1051             }
1052              
1053             # Something is seriously wrong if we ended inside a quote
1054 659 50       1683 if ( $self->[_in_quote_] ) {
1055 0         0 $severe_error = 1;
1056 0         0 my $line_start_quote = $self->[_line_start_quote_];
1057 0         0 my $quote_target = $self->[_quote_target_];
1058 0 0       0 my $what =
1059             ( $self->[_in_attribute_list_] )
1060             ? "attribute list"
1061             : "quote/pattern";
1062 0         0 $self->warning(
1063             "hit EOF seeking end of $what starting at line $line_start_quote ending in $quote_target\n"
1064             );
1065             }
1066              
1067 659 50       1610 if ( $self->[_hit_bug_] ) {
1068 0         0 $severe_error = 1;
1069             }
1070              
1071             # Multiple "unexpected" type tokenization errors usually indicate parsing
1072             # non-perl scripts, or that something is seriously wrong, so we should
1073             # avoid formatting them. This can happen for example if we run perltidy on
1074             # a shell script or an html file. But unfortunately this check can
1075             # interfere with some extended syntaxes, such as RPerl, so it has to be off
1076             # by default.
1077 659         1189 my $ue_count = $self->[_unexpected_error_count_];
1078 659 50 33     1906 if ( $maxue > 0 && $ue_count > $maxue ) {
1079 0         0 $self->warning(<<EOM);
1080             Formatting will be skipped since unexpected token count = $ue_count > -maxue=$maxue; use -maxue=0 to force formatting
1081             EOM
1082 0         0 $severe_error = 1;
1083             }
1084              
1085 659 100       1643 if ( !$self->[_saw_perl_dash_w_] ) {
1086 642         1930 $self->write_logfile_entry("Suggest including 'use warnings;'\n");
1087             }
1088              
1089 659 50       1717 if ( $self->[_saw_perl_dash_P_] ) {
1090 0         0 $self->write_logfile_entry(
1091             "Use of -P parameter for defines is discouraged\n");
1092             }
1093              
1094 659 100       1667 if ( !$self->[_saw_use_strict_] ) {
1095 645         1362 $self->write_logfile_entry("Suggest including 'use strict;'\n");
1096             }
1097              
1098             # it is suggested that labels have at least one upper case character
1099             # for legibility and to avoid code breakage as new keywords are introduced
1100 659 100       1718 if ( $self->[_rlower_case_labels_at_] ) {
1101 12         18 my @lower_case_labels_at = @{ $self->[_rlower_case_labels_at_] };
  12         35  
1102 12         38 $self->write_logfile_entry(
1103             "Suggest using upper case characters in label(s)\n");
1104 12         25 local $LIST_SEPARATOR = ')(';
1105 12         57 $self->write_logfile_entry(
1106             " defined at line(s): (@lower_case_labels_at)\n");
1107             }
1108              
1109             # Get the text of any leading format skipping tag
1110 659         1051 my $early_FS_end_marker;
1111 659         1054 my $rformat_skipping_list = $self->[_rformat_skipping_list_];
1112 659 100 100     838 if ( @{$rformat_skipping_list} && $rformat_skipping_list->[0]->[0] == -1 ) {
  659         1914  
1113 3         8 $early_FS_end_marker = $rformat_skipping_list->[0]->[2];
1114             }
1115              
1116             return {
1117 659         3080 severe_error => $severe_error,
1118             early_FS_end_marker => $early_FS_end_marker,
1119             };
1120              
1121             } ## end sub report_tokenization_errors
1122              
1123             sub show_indentation_table {
1124 0     0 0 0 my ($self) = @_;
1125              
1126             # Output indentation table made at closing braces. This can be helpful for
1127             # the case of a missing brace in a previously formatted file.
1128              
1129             # skip if problem reading file
1130 0 0       0 return if ( $self->[_in_error_] );
1131              
1132             # skip if -wc is used (rare); it is too complex to use
1133 0 0       0 return if ($rOpts_whitespace_cycle);
1134              
1135             # skip if non-indenting-brace-prefix (very rare, but could be fixed)
1136 0 0       0 return if ($rOpts_non_indenting_brace_prefix);
1137              
1138             # skip if starting level is not zero (probably in editor)
1139 0 0       0 return if ($rOpts_starting_indentation_level);
1140              
1141             # skip if indentation analysis is not valid
1142 0         0 my $rhash = $self->[_rclosing_brace_indentation_hash_];
1143 0 0       0 return if ( !$rhash->{valid} );
1144              
1145 0         0 my $rhistory_line_number = $rhash->{rhistory_line_number};
1146 0         0 my $rhistory_level_diff = $rhash->{rhistory_level_diff};
1147 0         0 my $rhistory_anchor_point = $rhash->{rhistory_anchor_point};
1148              
1149             # Remove the first artificial point from the table
1150 0         0 shift @{$rhistory_line_number};
  0         0  
1151 0         0 shift @{$rhistory_level_diff};
  0         0  
1152 0         0 shift @{$rhistory_anchor_point};
  0         0  
1153              
1154             # Remove dubious points at an anchor point = 2 and beyond
1155             # These can occur when non-indenting braces are used
1156 0         0 my $num_his = @{$rhistory_level_diff};
  0         0  
1157 0         0 foreach my $i ( 0 .. $num_his - 1 ) {
1158 0 0       0 if ( $rhistory_anchor_point->[$i] == 2 ) {
1159 0         0 $num_his = $i;
1160 0         0 last;
1161             }
1162             }
1163 0 0       0 return if ( $num_his <= 1 );
1164              
1165             # Ignore an ending non-anchor point
1166 0 0       0 if ( !$rhistory_anchor_point->[-1] ) {
1167 0         0 $num_his -= 1;
1168             }
1169              
1170             # Ignore an ending point which is the same as the previous point
1171 0 0       0 if ( $num_his > 1 ) {
1172 0 0       0 if ( $rhistory_level_diff->[ $num_his - 1 ] ==
1173             $rhistory_level_diff->[ $num_his - 2 ] )
1174             {
1175 0         0 $num_his -= 1;
1176             }
1177             }
1178              
1179             # Skip if the table does not have at least 2 points to pinpoint an error
1180 0 0       0 return if ( $num_his <= 1 );
1181              
1182             # Skip if first point shows a level error - the analysis may not be valid
1183 0 0       0 return if ( $rhistory_level_diff->[0] );
1184              
1185             # Remove table points which return from negative to zero; they follow
1186             # an error and may not be correct. c448.
1187 0         0 my $min_lev = $rhistory_level_diff->[0];
1188 0         0 foreach my $ii ( 1 .. $num_his - 1 ) {
1189 0         0 my $lev = $rhistory_level_diff->[$ii];
1190 0 0       0 if ( $lev < $min_lev ) { $min_lev = $lev; next }
  0         0  
  0         0  
1191 0 0 0     0 if ( $min_lev < 0 && $lev >= 0 ) {
1192 0         0 $num_his = $ii;
1193 0         0 last;
1194             }
1195             }
1196              
1197             # Since the table could be arbitrarily large, we will limit the table to N
1198             # lines. If there are more lines than that, we will show N-3 lines, then
1199             # ..., then the last 2 lines. Allow about 3 lines per error, so a table
1200             # limit of 10 can localize up to about 3 errors in a file.
1201 0         0 my $nlines_max = 10;
1202 0         0 my @pre_indexes = ( 0 .. $num_his - 1 );
1203 0         0 my @post_indexes = ();
1204 0 0       0 if ( @pre_indexes > $nlines_max ) {
1205 0 0       0 if ( $nlines_max >= 5 ) {
1206 0         0 @pre_indexes = ( 0 .. $nlines_max - 4 );
1207 0         0 @post_indexes = ( $num_his - 2, $num_his - 1 );
1208             }
1209             else {
1210 0         0 @pre_indexes = ( 0 .. $nlines_max - 1 );
1211             }
1212             }
1213              
1214 0         0 my @output_lines;
1215 0         0 push @output_lines, <<EOM;
1216             Table of initial nesting level differences at closing braces.
1217             This might help localize brace errors IF perltidy previously formatted the file.
1218             line: error=[new brace level]-[old indentation level]
1219             EOM
1220 0         0 foreach my $i (@pre_indexes) {
1221 0         0 my $lno = $rhistory_line_number->[$i];
1222 0         0 my $diff = $rhistory_level_diff->[$i];
1223 0         0 push @output_lines, <<EOM;
1224             $lno: $diff
1225             EOM
1226             }
1227 0 0       0 if (@post_indexes) {
1228 0         0 push @output_lines, "...\n";
1229 0         0 foreach my $i (@post_indexes) {
1230 0         0 my $lno = $rhistory_line_number->[$i];
1231 0         0 my $diff = $rhistory_level_diff->[$i];
1232 0         0 push @output_lines, <<EOM;
1233             $lno: $diff
1234             EOM
1235             }
1236             }
1237              
1238             # Try to give a hint
1239 0         0 my $level_diff_1 = $rhistory_level_diff->[1];
1240 0         0 my $ln_0 = $rhistory_line_number->[0];
1241 0         0 my $ln_1 = $rhistory_line_number->[1];
1242 0 0       0 if ( $level_diff_1 < 0 ) {
    0          
1243 0         0 push @output_lines,
1244             "There may be an extra '}' or missing '{' between lines $ln_0 and $ln_1\n";
1245             }
1246             elsif ( $level_diff_1 > 0 ) {
1247 0         0 push @output_lines,
1248             "There may be a missing '}' or extra '{' between lines $ln_0 and $ln_1\n";
1249             }
1250             else {
1251             ## two leading zeros in the table - probably can't happen - no hint
1252             }
1253              
1254 0         0 push @output_lines, "\n";
1255 0         0 my $output_str = join EMPTY_STRING, @output_lines;
1256              
1257 0         0 $self->interrupt_logfile();
1258 0         0 $self->warning($output_str);
1259 0         0 $self->resume_logfile();
1260              
1261 0         0 return;
1262             } ## end sub show_indentation_table
1263              
1264             sub report_v_string {
1265              
1266             # warn if this version can't handle v-strings
1267 2     2 0 6 my ( $self, $tok ) = @_;
1268 2 50       6 if ( $] < 5.006 ) {
1269 0         0 $self->warning(
1270             "Found v-string '$tok' but v-strings are not implemented in your version of perl; see Camel 3 book ch 2\n"
1271             );
1272             }
1273 2         4 return;
1274             } ## end sub report_v_string
1275              
1276             sub is_valid_token_type {
1277 448     448 0 495 my ($type) = @_;
1278 448         934 return $is_valid_token_type{$type};
1279             }
1280              
1281             sub log_numbered_msg {
1282 256     256 0 483 my ( $self, $msg ) = @_;
1283              
1284             # write input line number + message to logfile
1285 256         379 my $input_line_number = $self->[_last_line_number_];
1286 256         926 $self->write_logfile_entry("Line $input_line_number: $msg");
1287 256         384 return;
1288             } ## end sub log_numbered_msg
1289              
1290             sub get_line {
1291              
1292 9814     9814 0 12537 my $self = shift;
1293              
1294             # Read the next input line and tokenize it
1295             # Returns:
1296             # $line_of_tokens = ref to hash of info for the tokenized line
1297              
1298             # USES GLOBAL VARIABLES:
1299             # $brace_depth, $square_bracket_depth, $paren_depth
1300              
1301             # get the next line from the input array
1302 9814         12145 my $input_line;
1303             my $trimmed_input_line;
1304 9814         13182 my $line_index = $self->[_input_line_index_next_];
1305 9814         11360 my $rinput_lines = $self->[_rinput_lines_];
1306 9814 100       10895 if ( $line_index < @{$rinput_lines} ) {
  9814         15277  
1307 9155         15043 $trimmed_input_line = $self->[_rtrimmed_input_lines_]->[$line_index];
1308 9155         14320 $input_line = $rinput_lines->[ $line_index++ ];
1309 9155         11651 $self->[_input_line_index_next_] = $line_index;
1310             }
1311              
1312             # End of file .. check if file ends in a binary operator (c565)
1313             else {
1314 659 0 33     3311 if (
      33        
1315             $is_binary_or_unary_operator_type{$last_nonblank_type}
1316             || ( $last_nonblank_type eq 'k'
1317             && $is_binary_or_unary_keyword{$last_nonblank_token} )
1318             )
1319             {
1320 0         0 $self->warning(
1321             "Unexpected EOF at operator '$last_nonblank_token'\n");
1322              
1323             # avoid repeating this message
1324 0         0 $last_nonblank_token = ';';
1325 0         0 $last_nonblank_type = ';';
1326             }
1327             }
1328              
1329 9814         13299 $self->[_line_of_text_] = $input_line;
1330              
1331 9814 100       16864 return if ( !defined($input_line) );
1332              
1333 9155         11516 my $input_line_number = ++$self->[_last_line_number_];
1334              
1335             # Find and remove what characters terminate this line, including any
1336             # control r
1337 9155         11471 my $input_line_separator = EMPTY_STRING;
1338 9155 100       18678 if ( chomp $input_line ) {
1339 9154         16980 $input_line_separator = $INPUT_RECORD_SEPARATOR;
1340             }
1341              
1342             # The first test here very significantly speeds things up, but be sure to
1343             # keep the regex and hash %other_line_endings the same.
1344 9155 50       20435 if ( $other_line_endings{ substr( $input_line, -1 ) } ) {
1345 0 0       0 if ( $input_line =~ s/([\r\035\032])+$// ) {
1346 0         0 $input_line_separator = $1 . $input_line_separator;
1347              
1348             # This could make the trimmed input line incorrect, so the
1349             # safe thing to do is to make it undef to force it to be
1350             # recomputed later.
1351 0         0 $trimmed_input_line = undef;
1352             }
1353             }
1354              
1355             # For backwards compatibility we keep the line text terminated with
1356             # a newline character
1357 9155         11719 $input_line .= "\n";
1358 9155         11623 $self->[_line_of_text_] = $input_line;
1359              
1360             # create a data structure describing this line which will be
1361             # returned to the caller.
1362              
1363             # _line_type codes are:
1364             # SYSTEM - system-specific code before hash-bang line
1365             # CODE - line of perl code (including comments)
1366             # POD_START - line starting pod, such as '=head'
1367             # POD - pod documentation text
1368             # POD_END - last line of pod section, '=cut'
1369             # HERE - text of here-document
1370             # HERE_END - last line of here-doc (target word)
1371             # FORMAT - format section
1372             # FORMAT_END - last line of format section, '.'
1373             # SKIP - code skipping section
1374             # SKIP_END - last line of code skipping section, '#>>V'
1375             # DATA_START - __DATA__ line
1376             # DATA - unidentified text following __DATA__
1377             # END_START - __END__ line
1378             # END - unidentified text following __END__
1379             # ERROR - we are in big trouble, probably not a perl script
1380              
1381             # Other variables:
1382             # _curly_brace_depth - depth of curly braces at start of line
1383             # _square_bracket_depth - depth of square brackets at start of line
1384             # _paren_depth - depth of parens at start of line
1385             # _starting_in_quote - this line continues a multi-line quote
1386             # (so don't trim leading blanks!)
1387             # _ending_in_quote - this line ends in a multi-line quote
1388             # (so don't trim trailing blanks!)
1389 9155         39489 my $line_of_tokens = {
1390             _line_type => 'EOF',
1391             _line_text => $input_line,
1392             _line_number => $input_line_number,
1393             _guessed_indentation_level => 0,
1394             _curly_brace_depth => $brace_depth,
1395             _square_bracket_depth => $square_bracket_depth,
1396             _paren_depth => $paren_depth,
1397             ## Skip these needless initializations for efficiency:
1398             ## _rtoken_type => undef,
1399             ## _rtokens => undef,
1400             ## _rlevels => undef,
1401             ## _rblock_type => undef,
1402             ## _rtype_sequence => undef,
1403             ## _starting_in_quote => 0,
1404             ## _ending_in_quote => 0,
1405             };
1406              
1407             # Must print line unchanged if we are in a here document
1408 9155 100       36210 if ( $self->[_in_here_doc_] ) {
    100          
    100          
    100          
    50          
    100          
    100          
1409              
1410 96         130 $line_of_tokens->{_line_type} = 'HERE';
1411 96         123 my $here_doc_target = $self->[_here_doc_target_];
1412 96         113 my $here_quote_character = $self->[_here_quote_character_];
1413 96         114 my $candidate_target = $input_line;
1414 96         126 my $leading_whitespace = EMPTY_STRING;
1415 96         122 chomp $candidate_target;
1416              
1417             # Handle <<~ targets, which are indicated here by a leading space on
1418             # the here quote character. c603 has test cases.
1419             # the leading whitespace of all here text lines match it.
1420 96         140 my $ix = rindex( $candidate_target, $here_doc_target );
1421 96 100 66     318 if ( $ix > 0 && $here_quote_character =~ /^\s/ ) {
1422 18         34 $leading_whitespace = substr( $candidate_target, 0, $ix );
1423 18 50       65 if ( $leading_whitespace !~ /^\s*$/ ) {
1424 0         0 $leading_whitespace = EMPTY_STRING;
1425             }
1426             }
1427              
1428 96 100       210 if ( $candidate_target eq $leading_whitespace . $here_doc_target ) {
1429 37         1146 $self->[_nearly_matched_here_target_at_] = undef;
1430 37         62 $line_of_tokens->{_line_type} = 'HERE_END';
1431 37         125 $self->log_numbered_msg("Exiting HERE document $here_doc_target\n");
1432              
1433 37         56 my $rhere_target_list = $self->[_rhere_target_list_];
1434 37 100       50 if ( @{$rhere_target_list} ) { # there can be multiple here targets
  37         92  
1435             ( $here_doc_target, $here_quote_character ) =
1436 10         13 @{ shift @{$rhere_target_list} };
  10         13  
  10         24  
1437 10         23 $self->[_here_doc_target_] = $here_doc_target;
1438 10         12 $self->[_here_quote_character_] = $here_quote_character;
1439 10         25 $self->log_numbered_msg(
1440             "Entering HERE document $here_doc_target\n");
1441 10         16 $self->[_nearly_matched_here_target_at_] = undef;
1442 10         19 $self->[_started_looking_for_here_target_at_] =
1443             $input_line_number;
1444             }
1445             else {
1446 27         44 $self->[_in_here_doc_] = 0;
1447 27         56 $self->[_here_doc_target_] = EMPTY_STRING;
1448 27         45 $self->[_here_quote_character_] = EMPTY_STRING;
1449             }
1450             }
1451              
1452             # check for error of extra whitespace
1453             # note for PERL6: leading whitespace is allowed
1454             else {
1455 59         351 $candidate_target =~ s/^ \s+ | \s+ $//gx; # trim both ends
1456 59 50       131 if ( $candidate_target eq $here_doc_target ) {
1457 0         0 $self->[_nearly_matched_here_target_at_] = $input_line_number;
1458             }
1459             }
1460 96         286 return $line_of_tokens;
1461             }
1462              
1463             # Print line unchanged if we are in a format section
1464             elsif ( $self->[_in_format_] ) {
1465              
1466 3 100       11 if ( $input_line =~ /^\.[\s#]*$/ ) {
1467              
1468             # Decrement format depth count at a '.' after a 'format'
1469 1         2 $self->[_in_format_]--;
1470              
1471             # This is the end when count reaches 0
1472 1 50       5 if ( !$self->[_in_format_] ) {
1473 1         4 $self->log_numbered_msg("Exiting format section\n");
1474 1         2 $line_of_tokens->{_line_type} = 'FORMAT_END';
1475              
1476             # Make the tokenizer mark an opening brace which follows
1477             # as a code block. Fixes issue c202/t032.
1478 1         2 $last_nonblank_token = ';';
1479 1         2 $last_nonblank_type = ';';
1480             }
1481             }
1482             else {
1483 2         4 $line_of_tokens->{_line_type} = 'FORMAT';
1484 2 50       7 if ( $input_line =~ /^\s*format\s+\w+/ ) {
1485              
1486             # Increment format depth count at a 'format' within a 'format'
1487             # This is a simple way to handle nested formats (issue c019).
1488 0         0 $self->[_in_format_]++;
1489             }
1490             }
1491 3         9 return $line_of_tokens;
1492             }
1493              
1494             # must print line unchanged if we are in pod documentation
1495             elsif ( $self->[_in_pod_] ) {
1496              
1497 51         74 $line_of_tokens->{_line_type} = 'POD';
1498 51 100       115 if ( $input_line =~ /^=cut/ ) {
1499 22         57 $line_of_tokens->{_line_type} = 'POD_END';
1500 22         54 $self->log_numbered_msg("Exiting POD section\n");
1501 22         31 $self->[_in_pod_] = 0;
1502             }
1503 51 50 33     126 if ( $input_line =~ /^\#\!.*perl\b/ && !$self->[_in_end_] ) {
1504 0         0 $self->warning(
1505             "Hash-bang in pod can cause older versions of perl to fail! \n"
1506             );
1507             }
1508              
1509 51         118 return $line_of_tokens;
1510             }
1511              
1512             # print line unchanged if in skipped section
1513             elsif ( $self->[_in_code_skipping_] ) {
1514              
1515 8         12 $line_of_tokens->{_line_type} = 'SKIP';
1516 8 100       113 if ( $input_line =~ /$code_skipping_pattern_end/ ) {
    50          
1517 2         3 $line_of_tokens->{_line_type} = 'SKIP_END';
1518 2         6 $self->log_numbered_msg("Exiting code-skipping section\n");
1519 2         2 $self->[_in_code_skipping_] = 0;
1520             }
1521             elsif ( $input_line =~ /$code_skipping_pattern_begin/ ) {
1522              
1523             # warn of duplicate starting comment lines, git #118
1524 0         0 my $lno = $self->[_in_code_skipping_];
1525 0         0 $self->warning(
1526             "Already in code-skipping section which started at line $lno\n"
1527             );
1528             }
1529             else {
1530             ## not a code-skipping control line
1531             }
1532 8         32 return $line_of_tokens;
1533             }
1534              
1535             # must print line unchanged if we have seen a severe error (i.e., we
1536             # are seeing illegal tokens and cannot continue. Syntax errors do
1537             # not pass this route). Calling routine can decide what to do, but
1538             # the default can be to just pass all lines as if they were after __END__
1539             elsif ( $self->[_in_error_] ) {
1540 0         0 $line_of_tokens->{_line_type} = 'ERROR';
1541 0         0 return $line_of_tokens;
1542             }
1543              
1544             # print line unchanged if we are __DATA__ section
1545             elsif ( $self->[_in_data_] ) {
1546              
1547             # ...but look for POD
1548             # Note that the _in_data and _in_end flags remain set
1549             # so that we return to that state after seeing the
1550             # end of a pod section
1551 1 50 33     7 if ( $input_line =~ /^=(\w+)\b/ && $1 ne 'cut' ) {
1552 0         0 $line_of_tokens->{_line_type} = 'POD_START';
1553 0         0 $self->log_numbered_msg("Entering POD section\n");
1554 0         0 $self->[_in_pod_] = 1;
1555 0         0 return $line_of_tokens;
1556             }
1557             else {
1558 1         2 $line_of_tokens->{_line_type} = 'DATA';
1559 1         3 return $line_of_tokens;
1560             }
1561             }
1562              
1563             # print line unchanged if we are in __END__ section
1564             elsif ( $self->[_in_end_] ) {
1565              
1566             # ...but look for POD
1567             # Note that the _in_data and _in_end flags remain set
1568             # so that we return to that state after seeing the
1569             # end of a pod section
1570 56 100 66     159 if ( $input_line =~ /^=(\w+)\b/ && $1 ne 'cut' ) {
1571 7         14 $line_of_tokens->{_line_type} = 'POD_START';
1572 7         25 $self->log_numbered_msg("Entering POD section\n");
1573 7         8 $self->[_in_pod_] = 1;
1574 7         22 return $line_of_tokens;
1575             }
1576             else {
1577 49         63 $line_of_tokens->{_line_type} = 'END';
1578 49         96 return $line_of_tokens;
1579             }
1580             }
1581             else {
1582             ## not a special control line
1583             }
1584              
1585             # check for a hash-bang line if we haven't seen one
1586 8940 100 100     30426 if ( !$self->[_saw_hash_bang_]
      66        
1587             && substr( $input_line, 0, 2 ) eq '#!'
1588             && $input_line =~ /^\#\!.*perl\b/ )
1589             {
1590 16         34 $self->[_saw_hash_bang_] = $input_line_number;
1591              
1592             # check for -w and -P flags
1593 16 50       74 if ( $input_line =~ /^\#\!.*perl\s.*-.*P/ ) {
1594 0         0 $self->[_saw_perl_dash_P_] = 1;
1595             }
1596              
1597 16 100       65 if ( $input_line =~ /^\#\!.*perl\s.*-.*w/ ) {
1598 9         17 $self->[_saw_perl_dash_w_] = 1;
1599             }
1600              
1601 16 100 33     94 if (
      66        
      100        
      66        
1602             $input_line_number > 1
1603              
1604             # leave any hash bang in a BEGIN block alone
1605             # i.e. see 'debugger-duck_type.t'
1606             && !(
1607             $last_nonblank_block_type
1608             && $last_nonblank_block_type eq 'BEGIN'
1609             )
1610             && !$rOpts_look_for_hash_bang
1611              
1612             # Try to avoid giving a false alarm at a simple comment.
1613             # These look like valid hash-bang lines:
1614              
1615             #!/usr/bin/perl -w
1616             #! /usr/bin/perl -w
1617             #!c:\perl\bin\perl.exe
1618              
1619             # These are comments:
1620             #! I love perl
1621             #! sunos does not yet provide a /usr/bin/perl
1622              
1623             # Comments typically have multiple spaces, which suggests
1624             # the filter
1625             && $input_line =~ /^\#\!(\s+)?(\S+)?perl/
1626             )
1627             {
1628              
1629             # this is helpful for VMS systems; we may have accidentally
1630             # tokenized some DCL commands
1631 1 50       3 if ( $self->[_started_tokenizing_] ) {
1632 0         0 $self->warning(
1633             "There seems to be a hash-bang after line 1; do you need to run with -x ?\n"
1634             );
1635             }
1636             else {
1637 1         5 $self->complain("Useless hash-bang after line 1\n");
1638             }
1639             }
1640              
1641             # Report the leading hash-bang as a system line
1642             # This will prevent -dac from deleting it
1643             else {
1644 15         35 $line_of_tokens->{_line_type} = 'SYSTEM';
1645 15         61 return $line_of_tokens;
1646             }
1647             }
1648              
1649             # wait for a hash-bang before parsing if the user invoked us with -x
1650 8925 100 100     16481 if ( $rOpts_look_for_hash_bang
1651             && !$self->[_saw_hash_bang_] )
1652             {
1653 5         8 $line_of_tokens->{_line_type} = 'SYSTEM';
1654 5         11 return $line_of_tokens;
1655             }
1656              
1657             # a first line of the form ': #' will be marked as SYSTEM
1658             # since lines of this form may be used by tcsh
1659 8920 50 66     17702 if ( $input_line_number == 1 && $input_line =~ /^\s*\:\s*\#/ ) {
1660 0         0 $line_of_tokens->{_line_type} = 'SYSTEM';
1661 0         0 return $line_of_tokens;
1662             }
1663              
1664             # now we know that it is ok to tokenize the line...
1665             # the line tokenizer will modify any of these private variables:
1666             # _rhere_target_list_
1667             # _in_data_
1668             # _in_end_
1669             # _in_format_
1670             # _in_error_
1671             # _in_code_skipping_
1672             # _in_format_skipping_
1673             # _in_pod_
1674             # _in_quote_
1675              
1676 8920         22173 $self->tokenize_this_line( $line_of_tokens, $trimmed_input_line );
1677              
1678             # Now finish defining the return structure and return it
1679 8920         16050 $line_of_tokens->{_ending_in_quote} = $self->[_in_quote_];
1680              
1681             # handle severe error (binary data in script)
1682 8920 50       15222 if ( $self->[_in_error_] ) {
1683 0         0 $self->[_in_quote_] = 0; # to avoid any more messages
1684 0         0 $self->warning("Giving up after error\n");
1685 0         0 $line_of_tokens->{_line_type} = 'ERROR';
1686 0         0 reset_indentation_level(0); # avoid error messages
1687 0         0 return $line_of_tokens;
1688             }
1689              
1690             # handle start of pod documentation
1691 8920 100       14175 if ( $self->[_in_pod_] ) {
1692              
1693             # This gets tricky..above a __DATA__ or __END__ section, perl
1694             # accepts '=cut' as the start of pod section. But afterwards,
1695             # only pod utilities see it and they may ignore an =cut without
1696             # leading =head. In any case, this isn't good.
1697 15 50       42 if ( $input_line =~ /^=cut\b/ ) {
1698 0 0 0     0 if ( $self->[_saw_data_] || $self->[_saw_end_] ) {
1699 0         0 $self->complain("=cut while not in pod ignored\n");
1700 0         0 $self->[_in_pod_] = 0;
1701 0         0 $line_of_tokens->{_line_type} = 'POD_END';
1702             }
1703             else {
1704 0         0 $line_of_tokens->{_line_type} = 'POD_START';
1705 0         0 if ( !DEVEL_MODE ) {
1706 0         0 $self->warning(
1707             "=cut starts a pod section .. this can fool pod utilities.\n"
1708             );
1709             }
1710 0         0 $self->log_numbered_msg("Entering POD section\n");
1711             }
1712             }
1713              
1714             else {
1715 15         30 $line_of_tokens->{_line_type} = 'POD_START';
1716 15         44 $self->log_numbered_msg("Entering POD section\n");
1717             }
1718              
1719 15         67 return $line_of_tokens;
1720             }
1721              
1722             # handle start of skipped section
1723 8905 100       14303 if ( $self->[_in_code_skipping_] ) {
1724              
1725 2         5 $line_of_tokens->{_line_type} = 'SKIP';
1726 2         8 $self->log_numbered_msg("Entering code-skipping section\n");
1727 2         7 return $line_of_tokens;
1728             }
1729              
1730             # see if this line contains here doc targets
1731 8903         11295 my $rhere_target_list = $self->[_rhere_target_list_];
1732 8903 100       9174 if ( @{$rhere_target_list} ) {
  8903         14715  
1733              
1734             my ( $here_doc_target, $here_quote_character ) =
1735 27         54 @{ shift @{$rhere_target_list} };
  27         34  
  27         81  
1736 27         63 $self->[_in_here_doc_] = 1;
1737 27         46 $self->[_here_doc_target_] = $here_doc_target;
1738 27         63 $self->[_here_quote_character_] = $here_quote_character;
1739 27         144 $self->log_numbered_msg("Entering HERE document $here_doc_target\n");
1740 27         54 $self->[_started_looking_for_here_target_at_] = $input_line_number;
1741             }
1742              
1743             # NOTE: __END__ and __DATA__ statements are written unformatted
1744             # because they can theoretically contain additional characters
1745             # which are not tokenized (and cannot be read with <DATA> either!).
1746 8903 100       17809 if ( $self->[_in_data_] ) {
    100          
1747 1         3 $line_of_tokens->{_line_type} = 'DATA_START';
1748 1         4 $self->log_numbered_msg("Starting __DATA__ section\n");
1749 1         1 $self->[_saw_data_] = 1;
1750              
1751             # keep parsing after __DATA__ if use SelfLoader was seen
1752 1 50       3 if ( $self->[_saw_selfloader_] ) {
1753 0         0 $self->[_in_data_] = 0;
1754 0         0 $self->log_numbered_msg(
1755             "SelfLoader seen, continuing; -nlsl deactivates\n");
1756             }
1757              
1758 1         5 return $line_of_tokens;
1759             }
1760              
1761             elsif ( $self->[_in_end_] ) {
1762 7         15 $line_of_tokens->{_line_type} = 'END_START';
1763 7         31 $self->log_numbered_msg("Starting __END__ section\n");
1764 7         11 $self->[_saw_end_] = 1;
1765              
1766             # keep parsing after __END__ if use AutoLoader was seen
1767 7 50       28 if ( $self->[_saw_autoloader_] ) {
1768 0         0 $self->[_in_end_] = 0;
1769 0         0 $self->log_numbered_msg(
1770             "AutoLoader seen, continuing; -nlal deactivates\n");
1771             }
1772 7         28 return $line_of_tokens;
1773             }
1774             else {
1775             ## not in __END__ or __DATA__
1776             }
1777              
1778             # now, finally, we know that this line is type 'CODE'
1779 8895         13521 $line_of_tokens->{_line_type} = 'CODE';
1780              
1781             # remember if we have seen any real code
1782 8895 100 100     20747 if ( !$self->[_started_tokenizing_]
      100        
1783             && $input_line !~ /^\s*$/
1784             && $input_line !~ /^\s*#/ )
1785             {
1786 655         1257 $self->[_started_tokenizing_] = 1;
1787             }
1788              
1789 8895 100       13693 if ( $self->[_debugger_object_] ) {
1790 7         22 $self->[_debugger_object_]->write_debug_entry($line_of_tokens);
1791             }
1792              
1793             # Note: if keyword 'format' occurs in this line code, it is still CODE
1794             # (keyword 'format' need not start a line)
1795 8895 100       13870 if ( $self->[_in_format_] ) {
1796 1         6 $self->log_numbered_msg("Entering format section\n");
1797             }
1798              
1799 8895 100 100     24664 if ( $self->[_in_quote_]
    100 100        
1800             and ( $self->[_line_start_quote_] < 0 ) )
1801             {
1802 63 100       382 if ( ( my $quote_target = $self->[_quote_target_] ) !~ /^\s*$/ ) {
1803 62         112 $self->[_line_start_quote_] = $input_line_number;
1804 62         315 $self->log_numbered_msg(
1805             "Start multi-line quote or pattern ending in $quote_target\n");
1806             }
1807             }
1808             elsif ( ( $self->[_line_start_quote_] >= 0 )
1809             && !$self->[_in_quote_] )
1810             {
1811 62         107 $self->[_line_start_quote_] = -1;
1812 62         179 $self->log_numbered_msg("End of multi-line quote or pattern\n");
1813             }
1814             else {
1815             ## not at the edge of a quote
1816             }
1817              
1818             # we are returning a line of CODE
1819 8895         29041 return $line_of_tokens;
1820             } ## end sub get_line
1821              
1822             sub find_starting_indentation_level {
1823              
1824             # We need to find the indentation level of the first line of the
1825             # script being formatted. Often it will be zero for an entire file,
1826             # but if we are formatting a local block of code (within an editor for
1827             # example) it may not be zero. The user may specify this with the
1828             # -sil=n parameter but normally doesn't so we have to guess.
1829             #
1830 659     659 0 1360 my ($self) = @_;
1831 659         1297 my $starting_level = 0;
1832              
1833             # use value if given as parameter
1834 659 100       2244 if ( $self->[_know_starting_level_] ) {
    100          
1835 1         2 $starting_level = $self->[_starting_level_];
1836             }
1837              
1838             # if we know there is a hash_bang line, the level must be zero
1839             elsif ($rOpts_look_for_hash_bang) {
1840 1         2 $self->[_know_starting_level_] = 1;
1841             }
1842              
1843             # otherwise figure it out from the input file
1844             else {
1845 657         900 my $line;
1846 657         907 my $i = 0;
1847              
1848             # keep looking at lines until we find a hash bang or piece of code
1849             # ( or, for now, an =pod line)
1850 657         979 my $msg = EMPTY_STRING;
1851 657         1111 my $in_code_skipping;
1852             my $line_for_guess;
1853 657         2369 while ( defined( $line = $self->peek_ahead( $i++ ) ) ) {
1854              
1855             # if first line is #! then assume starting level is zero
1856 983 100 100     4045 if ( $i == 1 && $line =~ /^\#\!/ ) {
1857 14         26 $starting_level = 0;
1858 14         30 last;
1859             }
1860              
1861             # ignore lines fenced off with code-skipping comments
1862 969 100       3122 if ( $line =~ /^\s*#/ ) {
1863              
1864             # use first comment for indentation guess in case of no code
1865 310 100       784 if ( !defined($line_for_guess) ) { $line_for_guess = $line }
  254         443  
1866              
1867 310 50       682 if ( !$in_code_skipping ) {
1868 310 50 33     3389 if ( $rOpts_code_skipping
1869             && $line =~ /$code_skipping_pattern_begin/ )
1870             {
1871 0         0 $in_code_skipping = 1;
1872 0         0 next;
1873             }
1874             }
1875             else {
1876 0 0       0 if ( $line =~ /$code_skipping_pattern_end/ ) {
1877 0         0 $in_code_skipping = 0;
1878             }
1879 0         0 next;
1880             }
1881              
1882             # Note that we could also ignore format-skipping lines here
1883             # but it isn't clear if that would be best.
1884             # See c326 for example code.
1885              
1886 310         763 next;
1887             }
1888 659 50       1481 next if ($in_code_skipping);
1889              
1890 659 100       2446 next if ( $line =~ /^\s*$/ ); # skip past blank lines
1891              
1892             # use first line of code for indentation guess
1893 641         984 $line_for_guess = $line;
1894 641         1007 last;
1895             } ## end while ( defined( $line = ...))
1896              
1897 657 100       1451 if ( defined($line_for_guess) ) {
1898 641         2102 $starting_level =
1899             $self->guess_old_indentation_level($line_for_guess);
1900             }
1901 657         1529 $msg = "Line $i implies starting-indentation-level = $starting_level\n";
1902 657         2818 $self->write_logfile_entry("$msg");
1903             }
1904 659         1378 $self->[_starting_level_] = $starting_level;
1905 659         2396 reset_indentation_level($starting_level);
1906 659         871 return;
1907             } ## end sub find_starting_indentation_level
1908              
1909             sub guess_old_indentation_level {
1910 644     644 0 1357 my ( $self, $line ) = @_;
1911              
1912             # Guess the indentation level of an input line.
1913             #
1914             # For the first line of code this result will define the starting
1915             # indentation level. It will mainly be non-zero when perltidy is applied
1916             # within an editor to a local block of code.
1917             #
1918             # This is an impossible task in general because we can't know what tabs
1919             # meant for the old script and how many spaces were used for one
1920             # indentation level in the given input script. For example it may have
1921             # been previously formatted with -i=7 -et=3. But we can at least try to
1922             # make sure that perltidy guesses correctly if it is applied repeatedly to
1923             # a block of code within an editor, so that the block stays at the same
1924             # level when perltidy is applied repeatedly.
1925             #
1926             # USES GLOBAL VARIABLES: (none)
1927 644         939 my $level = 0;
1928              
1929             # find leading tabs, spaces, and any statement label
1930 644         967 my $spaces = 0;
1931 644 50       3548 if ( $line =~ /^(\t+)?(\s+)?(\w+:[^:])?/ ) {
1932              
1933             # If there are leading tabs, we use the tab scheme for this run, if
1934             # any, so that the code will remain stable when editing.
1935 644 100       2247 if ($1) { $spaces += length($1) * $tabsize }
  2         5  
1936              
1937 644 100       1641 if ($2) { $spaces += length($2) }
  90         217  
1938              
1939             # correct for outdented labels
1940 644 50 66     2546 if ( $3
      66        
1941             && $rOpts_outdent_labels
1942             && $rOpts_continuation_indentation > 0 )
1943             {
1944 1         3 $spaces += $rOpts_continuation_indentation;
1945             }
1946             }
1947              
1948 644         1616 $level = int( $spaces / $rOpts_indent_columns );
1949 644         1291 return ($level);
1950             } ## end sub guess_old_indentation_level
1951              
1952             sub dump_functions {
1953              
1954             # This is an unused debug routine, save for future use
1955              
1956 0     0 0 0 my $fh = *STDOUT;
1957 0         0 foreach my $pkg ( keys %{$ris_user_function} ) {
  0         0  
1958 0         0 $fh->print("\nnon-constant subs in package $pkg\n");
1959              
1960 0         0 foreach my $sub ( keys %{ $ris_user_function->{$pkg} } ) {
  0         0  
1961 0         0 my $msg = EMPTY_STRING;
1962 0 0       0 if ( $ris_block_list_function->{$pkg}->{$sub} ) {
1963 0         0 $msg = 'block_list';
1964             }
1965              
1966 0 0       0 if ( $ris_block_function->{$pkg}->{$sub} ) {
1967 0         0 $msg = 'block';
1968             }
1969 0         0 $fh->print("$sub $msg\n");
1970             }
1971             }
1972              
1973 0         0 foreach my $pkg ( keys %{$ris_constant} ) {
  0         0  
1974 0         0 $fh->print("\nconstants and constant subs in package $pkg\n");
1975              
1976 0         0 foreach my $sub ( keys %{ $ris_constant->{$pkg} } ) {
  0         0  
1977 0         0 $fh->print("$sub\n");
1978             }
1979             }
1980 0         0 return;
1981             } ## end sub dump_functions
1982              
1983             sub prepare_for_a_new_file {
1984              
1985 659     659 0 1450 my ( $self, $source_object ) = @_;
1986              
1987             # copy the source object lines to an array of lines
1988 659         2538 $self->make_source_array($source_object);
1989              
1990             # previous tokens needed to determine what to expect next
1991 659         1339 $last_nonblank_token = ';'; # the only possible starting state which
1992 659         1099 $last_nonblank_type = ';'; # will make a leading brace a code block
1993 659         1053 $last_nonblank_block_type = EMPTY_STRING;
1994              
1995             # scalars for remembering statement types across multiple lines
1996 659         1079 $statement_type = EMPTY_STRING; # '' or 'use' or 'sub..' or 'case..'
1997              
1998             # scalars for remembering where we are in the file
1999 659         1019 $current_package = "main";
2000 659         1025 $context = UNKNOWN_CONTEXT;
2001              
2002             # hashes used to remember function information
2003 659         980 $ris_constant = {}; # user-defined constants
2004 659         1472 $ris_user_function = {}; # user-defined functions
2005 659         1344 $ruser_function_prototype = {}; # their prototypes
2006 659         1161 $ris_block_function = {};
2007 659         1164 $ris_block_list_function = {};
2008 659         1238 $rsaw_function_definition = {};
2009 659         1247 $rsaw_use_module = {};
2010              
2011             # variables used to track depths of various containers
2012             # and report nesting errors
2013 659         1193 $paren_depth = 0;
2014 659         970 $brace_depth = 0;
2015 659         832 $square_bracket_depth = 0;
2016 659         2378 $rcurrent_depth = [ (0) x scalar(@closing_brace_names) ];
2017 659         982 $total_depth = 0;
2018 659         890 $rtotal_depth = [];
2019 659         1725 $rcurrent_sequence_number = [];
2020 659         1717 $ris_lexical_sub = {};
2021 659         1091 $next_sequence_number = SEQ_ROOT + 1;
2022              
2023 659         915 $rparen_type = [];
2024 659         1513 $rparen_semicolon_count = [];
2025 659         1251 $rparen_vars = [];
2026 659         2005 $rbrace_type = [];
2027 659         1440 $rbrace_structural_type = [];
2028 659         1493 $rbrace_context = [];
2029 659         1255 $rbrace_package = [];
2030 659         1345 $rsquare_bracket_type = [];
2031 659         1231 $rsquare_bracket_structural_type = [];
2032 659         1207 $rdepth_array = [];
2033 659         3371 $rnested_ternary_flag = [];
2034 659         1069 $rnested_statement_type = [];
2035 659         3406 $rstarting_line_of_current_depth = [];
2036              
2037 659         3481 $rparen_type->[$paren_depth] = EMPTY_STRING;
2038 659         1341 $rparen_semicolon_count->[$paren_depth] = 0;
2039 659         1254 $rparen_vars->[$paren_depth] = [];
2040 659         1193 $rbrace_type->[$brace_depth] = ';'; # identify opening brace as code block
2041 659         1176 $rbrace_structural_type->[$brace_depth] = EMPTY_STRING;
2042 659         1207 $rbrace_context->[$brace_depth] = UNKNOWN_CONTEXT;
2043 659         1150 $rbrace_package->[$paren_depth] = $current_package;
2044 659         1176 $rsquare_bracket_type->[$square_bracket_depth] = EMPTY_STRING;
2045 659         1064 $rsquare_bracket_structural_type->[$square_bracket_depth] = EMPTY_STRING;
2046              
2047 659         2369 initialize_tokenizer_state();
2048 659         1026 return;
2049             } ## end sub prepare_for_a_new_file
2050              
2051             { ## closure for sub tokenize_this_line
2052              
2053 44     44   360 use constant BRACE => 0;
  44         69  
  44         3116  
2054 44     44   244 use constant SQUARE_BRACKET => 1;
  44         91  
  44         1864  
2055 44     44   235 use constant PAREN => 2;
  44         67  
  44         1676  
2056 44     44   201 use constant QUESTION_COLON => 3;
  44         76  
  44         74119  
2057              
2058             # TV1: scalars for processing one LINE.
2059             # Re-initialized on each entry to sub tokenize_this_line.
2060             my (
2061             $block_type, $container_type, $expecting,
2062             $i, $i_tok, $input_line,
2063             $input_line_number, $last_nonblank_i, $max_token_index,
2064             $next_tok, $next_type, $peeked_ahead,
2065             $prototype, $rhere_target_list, $rtoken_map,
2066             $rtoken_type, $rtokens, $tok,
2067             $type, $type_sequence, $indent_flag,
2068             );
2069              
2070             # TV2: refs to ARRAYS for processing one LINE
2071             # Re-initialized on each call.
2072             my $routput_token_list = []; # stack of output token indexes
2073             my $routput_token_type = []; # token types
2074             my $routput_block_type = []; # types of code block
2075             my $routput_type_sequence = []; # nesting sequential number
2076             my $routput_indent_flag = []; #
2077              
2078             # TV3: SCALARS for quote variables. These are initialized with a
2079             # subroutine call and continually updated as lines are processed.
2080             my (
2081             $in_quote, $quote_type,
2082             $quote_character, $quote_pos,
2083             $quote_depth, $quoted_string_1,
2084             $quoted_string_2, $allowed_quote_modifiers,
2085             $quote_starting_tok, $quote_here_target_2,
2086             );
2087              
2088             # TV4: SCALARS for multi-line identifiers and
2089             # statements. These are initialized with a subroutine call
2090             # and continually updated as lines are processed.
2091             my ( $id_scan_state, $identifier, $want_paren );
2092              
2093             # TV5: SCALARS for tracking indentation level.
2094             # Initialized once and continually updated as lines are
2095             # processed.
2096             my (
2097             $nesting_token_string, $nesting_block_string,
2098             $nesting_block_flag, $level_in_tokenizer,
2099             );
2100              
2101             # TV6: SCALARS for remembering several previous
2102             # tokens. Initialized once and continually updated as
2103             # lines are processed.
2104             my (
2105             $last_nonblank_container_type, $last_nonblank_type_sequence,
2106             $last_last_nonblank_token, $last_last_nonblank_type,
2107             $last_nonblank_prototype,
2108             );
2109              
2110             # ----------------------------------------------------------------
2111             # beginning of tokenizer variable access and manipulation routines
2112             # ----------------------------------------------------------------
2113              
2114             sub initialize_tokenizer_state {
2115              
2116             # GV1: initialized once
2117             # TV1: initialized on each call
2118             # TV2: initialized on each call
2119             # TV3:
2120 659     659 0 1083 $in_quote = 0;
2121 659         1142 $quote_type = 'Q';
2122 659         1061 $quote_character = EMPTY_STRING;
2123 659         926 $quote_pos = 0;
2124 659         943 $quote_depth = 0;
2125 659         983 $quoted_string_1 = EMPTY_STRING;
2126 659         935 $quoted_string_2 = EMPTY_STRING;
2127 659         986 $allowed_quote_modifiers = EMPTY_STRING;
2128 659         1011 $quote_starting_tok = EMPTY_STRING;
2129 659         930 $quote_here_target_2 = undef;
2130              
2131             # TV4:
2132 659         897 $id_scan_state = EMPTY_STRING;
2133 659         936 $identifier = EMPTY_STRING;
2134 659         966 $want_paren = EMPTY_STRING;
2135              
2136             # TV5:
2137 659         994 $nesting_token_string = EMPTY_STRING;
2138 659         904 $nesting_block_string = '1'; # initially in a block
2139 659         941 $nesting_block_flag = 1;
2140 659         880 $level_in_tokenizer = 0;
2141              
2142             # TV6:
2143 659         942 $last_nonblank_container_type = EMPTY_STRING;
2144 659         869 $last_nonblank_type_sequence = EMPTY_STRING;
2145 659         951 $last_last_nonblank_token = ';';
2146 659         963 $last_last_nonblank_type = ';';
2147 659         878 $last_nonblank_prototype = EMPTY_STRING;
2148 659         914 return;
2149             } ## end sub initialize_tokenizer_state
2150              
2151             sub save_tokenizer_state {
2152              
2153             # Global variables:
2154 0     0 0 0 my $rGV1 = [
2155             $brace_depth,
2156             $context,
2157             $current_package,
2158             $last_nonblank_block_type,
2159             $last_nonblank_token,
2160             $last_nonblank_type,
2161             $next_sequence_number,
2162             $paren_depth,
2163             $rbrace_context,
2164             $rbrace_package,
2165             $rbrace_structural_type,
2166             $rbrace_type,
2167             $rcurrent_depth,
2168             $rcurrent_sequence_number,
2169             $ris_lexical_sub,
2170             $rdepth_array,
2171             $ris_block_function,
2172             $ris_block_list_function,
2173             $ris_constant,
2174             $ris_user_function,
2175             $rnested_statement_type,
2176             $rnested_ternary_flag,
2177             $rparen_semicolon_count,
2178             $rparen_vars,
2179             $rparen_type,
2180             $rsaw_function_definition,
2181             $rsaw_use_module,
2182             $rsquare_bracket_structural_type,
2183             $rsquare_bracket_type,
2184             $rstarting_line_of_current_depth,
2185             $rtotal_depth,
2186             $ruser_function_prototype,
2187             $square_bracket_depth,
2188             $statement_type,
2189             $total_depth,
2190              
2191             ];
2192              
2193             # Tokenizer closure variables:
2194 0         0 my $rTV1 = [
2195             $block_type, $container_type, $expecting,
2196             $i, $i_tok, $input_line,
2197             $input_line_number, $last_nonblank_i, $max_token_index,
2198             $next_tok, $next_type, $peeked_ahead,
2199             $prototype, $rhere_target_list, $rtoken_map,
2200             $rtoken_type, $rtokens, $tok,
2201             $type, $type_sequence, $indent_flag,
2202             ];
2203              
2204 0         0 my $rTV2 = [
2205             $routput_token_list, $routput_token_type,
2206             $routput_block_type, $routput_type_sequence,
2207             $routput_indent_flag,
2208             ];
2209              
2210 0         0 my $rTV3 = [
2211             $in_quote, $quote_type,
2212             $quote_character, $quote_pos,
2213             $quote_depth, $quoted_string_1,
2214             $quoted_string_2, $allowed_quote_modifiers,
2215             $quote_starting_tok, $quote_here_target_2,
2216             ];
2217              
2218 0         0 my $rTV4 = [ $id_scan_state, $identifier, $want_paren ];
2219              
2220 0         0 my $rTV5 = [
2221             $nesting_token_string, $nesting_block_string,
2222             $nesting_block_flag, $level_in_tokenizer,
2223             ];
2224              
2225 0         0 my $rTV6 = [
2226             $last_nonblank_container_type, $last_nonblank_type_sequence,
2227             $last_last_nonblank_token, $last_last_nonblank_type,
2228             $last_nonblank_prototype,
2229             ];
2230 0         0 return [ $rGV1, $rTV1, $rTV2, $rTV3, $rTV4, $rTV5, $rTV6 ];
2231             } ## end sub save_tokenizer_state
2232              
2233             sub restore_tokenizer_state {
2234 0     0 0 0 my ($rstate) = @_;
2235 0         0 my ( $rGV1, $rTV1, $rTV2, $rTV3, $rTV4, $rTV5, $rTV6 ) = @{$rstate};
  0         0  
2236              
2237             (
2238             $brace_depth,
2239             $context,
2240             $current_package,
2241             $last_nonblank_block_type,
2242             $last_nonblank_token,
2243             $last_nonblank_type,
2244             $next_sequence_number,
2245             $paren_depth,
2246             $rbrace_context,
2247             $rbrace_package,
2248             $rbrace_structural_type,
2249             $rbrace_type,
2250             $rcurrent_depth,
2251             $rcurrent_sequence_number,
2252             $ris_lexical_sub,
2253             $rdepth_array,
2254             $ris_block_function,
2255             $ris_block_list_function,
2256             $ris_constant,
2257             $ris_user_function,
2258             $rnested_statement_type,
2259             $rnested_ternary_flag,
2260             $rparen_semicolon_count,
2261             $rparen_vars,
2262             $rparen_type,
2263             $rsaw_function_definition,
2264             $rsaw_use_module,
2265             $rsquare_bracket_structural_type,
2266             $rsquare_bracket_type,
2267             $rstarting_line_of_current_depth,
2268             $rtotal_depth,
2269             $ruser_function_prototype,
2270             $square_bracket_depth,
2271             $statement_type,
2272             $total_depth,
2273              
2274 0         0 ) = @{$rGV1};
  0         0  
2275              
2276             (
2277             $block_type, $container_type, $expecting,
2278             $i, $i_tok, $input_line,
2279             $input_line_number, $last_nonblank_i, $max_token_index,
2280             $next_tok, $next_type, $peeked_ahead,
2281             $prototype, $rhere_target_list, $rtoken_map,
2282             $rtoken_type, $rtokens, $tok,
2283             $type, $type_sequence, $indent_flag,
2284 0         0 ) = @{$rTV1};
  0         0  
2285              
2286             (
2287             $routput_token_list, $routput_token_type,
2288             $routput_block_type, $routput_type_sequence,
2289             $routput_indent_flag,
2290 0         0 ) = @{$rTV2};
  0         0  
2291              
2292             (
2293             $in_quote, $quote_type,
2294             $quote_character, $quote_pos,
2295             $quote_depth, $quoted_string_1,
2296             $quoted_string_2, $allowed_quote_modifiers,
2297             $quote_starting_tok, $quote_here_target_2,
2298 0         0 ) = @{$rTV3};
  0         0  
2299              
2300 0         0 ( $id_scan_state, $identifier, $want_paren ) = @{$rTV4};
  0         0  
2301              
2302             (
2303             $nesting_token_string, $nesting_block_string,
2304             $nesting_block_flag, $level_in_tokenizer,
2305 0         0 ) = @{$rTV5};
  0         0  
2306              
2307             (
2308             $last_nonblank_container_type, $last_nonblank_type_sequence,
2309             $last_last_nonblank_token, $last_last_nonblank_type,
2310             $last_nonblank_prototype,
2311 0         0 ) = @{$rTV6};
  0         0  
2312 0         0 return;
2313             } ## end sub restore_tokenizer_state
2314              
2315             sub split_pretoken {
2316              
2317 8     8 0 16 my ( $self, $numc ) = @_;
2318              
2319             # This provides a way to work around the limitations of the
2320             # pre-tokenization scheme upon which perltidy is based. It is rarely
2321             # needed.
2322              
2323             # Split the leading $numc characters from the current token (at
2324             # index=$i) which is pre-type 'w' and insert the remainder back into
2325             # the pretoken stream with appropriate settings. Since we are
2326             # splitting a pre-type 'w', there are three cases, depending on if the
2327             # remainder starts with a digit:
2328             # Case 1: remainder is type 'd', all digits
2329             # Case 2: remainder is type 'd' and type 'w': digits & other characters
2330             # Case 3: remainder is type 'w'
2331              
2332             # Examples, for $numc=1:
2333             # $tok => $tok_0 $tok_1 $tok_2
2334             # 'x10' => 'x' '10' # case 1
2335             # 'x10if' => 'x' '10' 'if' # case 2
2336             # '0ne => 'O' 'ne' # case 3
2337              
2338             # where:
2339             # $tok_1 is a possible string of digits (pre-type 'd')
2340             # $tok_2 is a possible word (pre-type 'w')
2341              
2342             # return 1 if successful
2343             # return undef if error (shouldn't happen)
2344              
2345             # Calling routine should update '$type' and '$tok' if successful.
2346              
2347 8         17 my $pretoken = $rtokens->[$i];
2348 8 50 33     60 if ( $pretoken
      33        
2349             && length($pretoken) > $numc
2350             && substr( $pretoken, $numc ) =~ /^(\d*)(.*)$/ )
2351             {
2352              
2353             # Split $tok into up to 3 tokens:
2354 8         14 my $tok_0 = substr( $pretoken, 0, $numc );
2355 8 50       24 my $tok_1 = defined($1) ? $1 : EMPTY_STRING;
2356 8 50       15 my $tok_2 = defined($2) ? $2 : EMPTY_STRING;
2357              
2358 8         15 my $len_0 = length($tok_0);
2359 8         9 my $len_1 = length($tok_1);
2360 8         9 my $len_2 = length($tok_2);
2361              
2362             ##my $pre_type_0 = 'w';
2363 8         10 my $pre_type_1 = 'd';
2364 8         9 my $pre_type_2 = 'w';
2365              
2366 8         11 my $pos_0 = $rtoken_map->[$i];
2367 8         11 my $pos_1 = $pos_0 + $len_0;
2368 8         12 my $pos_2 = $pos_1 + $len_1;
2369              
2370 8         10 my $isplice = $i + 1;
2371              
2372             # Splice in any digits
2373 8 100       28 if ($len_1) {
2374 5         7 splice @{$rtoken_map}, $isplice, 0, $pos_1;
  5         10  
2375 5         9 splice @{$rtokens}, $isplice, 0, $tok_1;
  5         10  
2376 5         8 splice @{$rtoken_type}, $isplice, 0, $pre_type_1;
  5         10  
2377 5         8 $max_token_index++;
2378 5         6 $isplice++;
2379             }
2380              
2381             # Splice in any trailing word
2382 8 100       16 if ($len_2) {
2383 4         6 splice @{$rtoken_map}, $isplice, 0, $pos_2;
  4         8  
2384 4         5 splice @{$rtokens}, $isplice, 0, $tok_2;
  4         7  
2385 4         7 splice @{$rtoken_type}, $isplice, 0, $pre_type_2;
  4         5  
2386 4         5 $max_token_index++;
2387             }
2388              
2389 8         10 $rtokens->[$i] = $tok_0;
2390 8         26 return 1;
2391             }
2392              
2393             # Shouldn't get here - bad call parameters
2394 0         0 if (DEVEL_MODE) {
2395             Fault(<<EOM);
2396             While working near line number $input_line_number, bad arg '$tok' passed to sub split_pretoken()
2397             EOM
2398             }
2399 0         0 return;
2400             } ## end sub split_pretoken
2401              
2402             sub get_indentation_level {
2403 659     659 0 1436 return $level_in_tokenizer;
2404             }
2405              
2406             sub reset_indentation_level {
2407 659     659 0 1092 $level_in_tokenizer = shift;
2408 659         930 return;
2409             }
2410              
2411             sub peeked_ahead {
2412 288     288 0 459 ( ( my $flag ) ) = @_;
2413              
2414             # get or set the closure flag '$peeked_ahead':
2415             # - set $peeked_ahead to $flag if given, then
2416             # - return current value
2417 288 100       538 $peeked_ahead = defined($flag) ? $flag : $peeked_ahead;
2418 288         573 return $peeked_ahead;
2419             } ## end sub peeked_ahead
2420              
2421             # ------------------------------------------------------------
2422             # end of tokenizer variable access and manipulation routines
2423             # ------------------------------------------------------------
2424              
2425             #------------------------------
2426             # beginning of tokenizer hashes
2427             #------------------------------
2428              
2429             my %matching_start_token = ( '}' => '{', ']' => '[', ')' => '(' );
2430              
2431             my @q;
2432              
2433             # 'L' is token for opening { at hash key
2434             my %is_opening_type;
2435             @q = qw< L { ( [ >;
2436             $is_opening_type{$_} = 1 for @q;
2437              
2438             my %is_opening_or_ternary_type;
2439             push @q, '?';
2440             $is_opening_or_ternary_type{$_} = 1 for @q;
2441              
2442             # 'R' is token for closing } at hash key
2443             my %is_closing_type;
2444             @q = qw< R } ) ] >;
2445             $is_closing_type{$_} = 1 for @q;
2446              
2447             my %is_closing_or_ternary_type;
2448             push @q, ':';
2449             $is_closing_or_ternary_type{$_} = 1 for @q;
2450              
2451             my %is_redo_last_next_goto;
2452             @q = qw( redo last next goto );
2453             $is_redo_last_next_goto{$_} = 1 for @q;
2454              
2455             my %is_use_require;
2456             @q = qw( use require );
2457             $is_use_require{$_} = 1 for @q;
2458              
2459             # This hash holds the array index in $self for these keywords:
2460             # Fix for issue c035: removed 'format' from this hash
2461             my %is_END_DATA = (
2462             '__END__' => _in_end_,
2463             '__DATA__' => _in_data_,
2464             );
2465              
2466             # table showing how many quoted things to look for after quote operator..
2467             # s, y, tr have 2 (pattern and replacement)
2468             # others have 1 (pattern only)
2469             my %quote_items = (
2470             's' => 2,
2471             'y' => 2,
2472             'tr' => 2,
2473             'm' => 1,
2474             'qr' => 1,
2475             'q' => 1,
2476             'qq' => 1,
2477             'qw' => 1,
2478             'qx' => 1,
2479             );
2480              
2481             my %is_for_foreach;
2482             @q = qw( for foreach );
2483             $is_for_foreach{$_} = 1 for @q;
2484              
2485             # These keywords may introduce blocks after parenthesized expressions,
2486             # in the form:
2487             # keyword ( .... ) { BLOCK }
2488             # patch for SWITCH/CASE: added 'switch' 'case' 'given' 'when'
2489             my %is_blocktype_with_paren;
2490             @q =
2491             qw(if elsif unless while until for foreach switch case given when catch);
2492             $is_blocktype_with_paren{$_} = 1 for @q;
2493              
2494             my %is_case_default;
2495             @q = qw( case default );
2496             $is_case_default{$_} = 1 for @q;
2497              
2498             #------------------------
2499             # end of tokenizer hashes
2500             #------------------------
2501              
2502             # ------------------------------------------------------------
2503             # beginning of various scanner interface routines
2504             # ------------------------------------------------------------
2505             sub scan_replacement_text {
2506              
2507             # check for here-docs in replacement text invoked by
2508             # a substitution operator with executable modifier 'e'.
2509             #
2510             # given:
2511             # $replacement_text
2512             # return:
2513             # $rht = reference to any here-doc targets
2514 0     0 0 0 my ( $self, $replacement_text ) = @_;
2515              
2516             # quick check
2517 0 0       0 return if ( $replacement_text !~ /<</ );
2518              
2519 0         0 $self->write_logfile_entry(
2520             "scanning replacement text for here-doc targets\n");
2521              
2522             # save the logger object for error messages
2523 0         0 my $logger_object = $self->[_logger_object_];
2524              
2525             # save all lexical variables
2526 0         0 my $rstate = save_tokenizer_state();
2527 0         0 _decrement_count(); # avoid error check for multiple tokenizers
2528              
2529             # make a new tokenizer
2530 0         0 my $tokenizer = Perl::Tidy::Tokenizer->new(
2531             source_object => \$replacement_text,
2532             logger_object => $logger_object,
2533             starting_line_number => $input_line_number,
2534             );
2535              
2536             # scan the replacement text
2537 0         0 while ( $tokenizer->get_line() ) { }
2538              
2539             # remove any here doc targets
2540 0         0 my $rht = undef;
2541 0 0       0 if ( $tokenizer->[_in_here_doc_] ) {
2542 0         0 $rht = [];
2543 0         0 push @{$rht},
  0         0  
2544             [
2545             $tokenizer->[_here_doc_target_],
2546             $tokenizer->[_here_quote_character_],
2547             ];
2548 0 0       0 if ( $tokenizer->[_rhere_target_list_] ) {
2549 0         0 push @{$rht}, @{ $tokenizer->[_rhere_target_list_] };
  0         0  
  0         0  
2550 0         0 $tokenizer->[_rhere_target_list_] = undef;
2551             }
2552 0         0 $tokenizer->[_in_here_doc_] = undef;
2553             }
2554              
2555             # now its safe to report errors
2556 0         0 my $rtokenization_info_uu = $tokenizer->report_tokenization_errors();
2557              
2558             # TODO: Could propagate a severe error up
2559              
2560             # restore all tokenizer lexical variables
2561 0         0 restore_tokenizer_state($rstate);
2562              
2563             # return the here doc targets
2564 0         0 return $rht;
2565             } ## end sub scan_replacement_text
2566              
2567             sub scan_bare_identifier {
2568 1866     1866 0 2310 my $self = shift;
2569              
2570             # Scan a token starting with an alphanumeric variable or package
2571             # separator, :: or '.
2572              
2573 1866         5332 ( $i, $tok, $type, $prototype ) = $self->scan_bare_identifier_do(
2574              
2575             $input_line,
2576             $i,
2577             $tok,
2578             $type,
2579             $prototype,
2580             $rtoken_map,
2581             $max_token_index,
2582             );
2583 1866         3219 return;
2584             } ## end sub scan_bare_identifier
2585              
2586             sub scan_identifier {
2587              
2588             # Scan for an identifier following a sigil or -> or other
2589             # identifier prefix, such as '::'
2590              
2591 551     551 0 738 my $self = shift;
2592              
2593             (
2594              
2595 551         1949 $i,
2596             $tok,
2597             $type,
2598             $id_scan_state,
2599             $identifier,
2600             my $split_pretoken_flag,
2601              
2602             ) = $self->scan_complex_identifier(
2603              
2604             $i,
2605             $id_scan_state,
2606             $identifier,
2607             $rtokens,
2608             $max_token_index,
2609             $expecting,
2610             $rparen_type->[$paren_depth],
2611             );
2612              
2613             # Check for signal to fix a special variable adjacent to a keyword,
2614             # such as '$^One$0'.
2615 551 100       1282 if ($split_pretoken_flag) {
2616              
2617             # Try to fix it by splitting the pretoken
2618 3 50 33     19 if ( $i > 0
      33        
2619             && $rtokens->[ $i - 1 ] eq '^'
2620             && $self->split_pretoken(1) )
2621             {
2622 3         3 $identifier = substr( $identifier, 0, 3 );
2623 3         5 $tok = $identifier;
2624             }
2625             else {
2626              
2627             # This shouldn't happen ...
2628 0         0 my $var = substr( $tok, 0, 3 );
2629 0         0 my $excess = substr( $tok, 3 );
2630 0         0 $self->interrupt_logfile();
2631 0         0 $self->warning(<<EOM);
2632             $input_line_number: Trouble parsing at characters '$excess' after special variable '$var'.
2633             A space may be needed after '$var'.
2634             EOM
2635 0         0 $self->resume_logfile();
2636             }
2637             }
2638 551         805 return;
2639             } ## end sub scan_identifier
2640              
2641 44     44   356 use constant VERIFY_FASTSCAN => 0;
  44         88  
  44         3841  
2642             my %fast_scan_context;
2643              
2644             BEGIN {
2645 44     44   55586 %fast_scan_context = (
2646             '$' => SCALAR_CONTEXT,
2647             '*' => SCALAR_CONTEXT,
2648             '@' => LIST_CONTEXT,
2649             '%' => LIST_CONTEXT,
2650             '&' => UNKNOWN_CONTEXT,
2651             );
2652             } ## end BEGIN
2653              
2654             sub scan_simple_identifier {
2655              
2656 5735     5735 0 6486 my $self = shift;
2657              
2658             # This is a wrapper for sub scan_identifier. It does a fast preliminary
2659             # scan for certain common identifiers:
2660             # '$var', '@var', %var, *var, &var, '@{...}', '%{...}'
2661             # If it does not find one of these, or this is a restart, it calls the
2662             # original scanner directly.
2663              
2664             # This gives the same results as the full scanner in about 1/4 the
2665             # total runtime for a typical input stream.
2666              
2667             # Notation:
2668             # $var * 2
2669             # ^^ ^
2670             # || |
2671             # || ---- $i_next [= next nonblank pretoken ]
2672             # |----$i_plus_1 [= a bareword ]
2673             # ---$i_begin [= a sigil]
2674              
2675 5735         6408 my $i_begin = $i;
2676 5735         6582 my $tok_begin = $tok;
2677 5735         6519 my $i_plus_1 = $i + 1;
2678 5735         6402 my $fast_scan_type;
2679              
2680             #-------------------------------------------------------
2681             # Do full scan for anything following a pointer, such as
2682             # $cref->&*; # a postderef
2683             #-------------------------------------------------------
2684 5735 100 66     23615 if ( $last_nonblank_token eq '->' ) {
    100 66        
    50 33        
      0        
      33        
2685              
2686             }
2687              
2688             #------------------------------
2689             # quick scan with leading sigil
2690             #------------------------------
2691             elsif ( !$id_scan_state
2692             && $i_plus_1 <= $max_token_index
2693             && $fast_scan_context{$tok} )
2694             {
2695 5621         7603 $context = $fast_scan_context{$tok};
2696              
2697             # look for $var, @var, ...
2698 5621 100 100     9966 if ( $rtoken_type->[$i_plus_1] eq 'w' ) {
    100 66        
2699 5264         6392 my $pretype_next = EMPTY_STRING;
2700 5264 100       8251 if ( $i_plus_1 < $max_token_index ) {
2701 5142         5864 my $i_next = $i_plus_1 + 1;
2702 5142 100 100     11882 if ( $rtoken_type->[$i_next] eq 'b'
2703             && $i_next < $max_token_index )
2704             {
2705 2063         2664 $i_next += 1;
2706             }
2707 5142         6938 $pretype_next = $rtoken_type->[$i_next];
2708             }
2709 5264 100 100     13400 if ( $pretype_next ne ':' && $pretype_next ne "'" ) {
2710              
2711             # Found type 'i' like '$var', '@var', or '%var'
2712 5148         8203 $identifier = $tok . $rtokens->[$i_plus_1];
2713 5148         5841 $tok = $identifier;
2714 5148         5826 $type = 'i';
2715 5148         5516 $i = $i_plus_1;
2716 5148         6711 $fast_scan_type = $type;
2717             }
2718             }
2719              
2720             # Look for @{ or %{ .
2721             # But we must let the full scanner handle things ${ because it may
2722             # keep going to get a complete identifier like '${#}' .
2723             elsif (
2724             $rtoken_type->[$i_plus_1] eq '{'
2725             && ( $tok_begin eq '@'
2726             || $tok_begin eq '%' )
2727             )
2728             {
2729              
2730 43         90 $identifier = $tok;
2731 43         74 $type = 't';
2732 43         64 $fast_scan_type = $type;
2733             }
2734             else {
2735             ## out of tricks
2736             }
2737             }
2738              
2739             #---------------------------
2740             # Quick scan with leading ->
2741             # Look for ->[ and ->{
2742             #---------------------------
2743             elsif (
2744             $tok eq '->'
2745             && $i < $max_token_index
2746             && ( $rtokens->[$i_plus_1] eq '{'
2747             || $rtokens->[$i_plus_1] eq '[' )
2748             )
2749             {
2750 0         0 $type = $tok;
2751 0         0 $fast_scan_type = $type;
2752 0         0 $identifier = $tok;
2753 0         0 $context = UNKNOWN_CONTEXT;
2754             }
2755             else {
2756             ## out of tricks
2757             }
2758              
2759             #--------------------------------------
2760             # Verify correctness during development
2761             #--------------------------------------
2762 5735         6344 if ( VERIFY_FASTSCAN && $fast_scan_type ) {
2763              
2764             # We will call the full method
2765             my $identifier_simple = $identifier;
2766             my $tok_simple = $tok;
2767             my $i_simple = $i;
2768             my $context_simple = $context;
2769              
2770             $tok = $tok_begin;
2771             $i = $i_begin;
2772             $self->scan_identifier();
2773              
2774             if ( $tok ne $tok_simple
2775             || $type ne $fast_scan_type
2776             || $i != $i_simple
2777             || $identifier ne $identifier_simple
2778             || $id_scan_state
2779             || $context ne $context_simple )
2780             {
2781             print {*STDERR} <<EOM;
2782             scan_simple_identifier differs from scan_identifier:
2783             simple: i=$i_simple, tok=$tok_simple, type=$fast_scan_type, ident=$identifier_simple, context='$context_simple
2784             full: i=$i, tok=$tok, type=$type, ident=$identifier, context='$context state=$id_scan_state
2785             EOM
2786             }
2787             }
2788              
2789             #-------------------------------------------------
2790             # call full scanner if fast method did not succeed
2791             #-------------------------------------------------
2792 5735 100       8996 if ( !$fast_scan_type ) {
2793 544         1365 $self->scan_identifier();
2794             }
2795 5735         7742 return;
2796             } ## end sub scan_simple_identifier
2797              
2798             sub method_ok_here {
2799              
2800 14     14 0 30 my ( $self, $next_nonblank_token ) = @_;
2801              
2802             # Return:
2803             # false if this is definitely an invalid method declaration
2804             # true otherwise (even if not sure)
2805              
2806             # We are trying to avoid problems with old uses of 'method'
2807             # when --use-feature=class is set (rt145706).
2808             # For example, this should cause a return of 'false':
2809              
2810             # method paint => sub {
2811             # return;
2812             # };
2813              
2814             # Assume non-method if an error would occur
2815 14 50       38 return if ( $expecting == OPERATOR );
2816              
2817             # Currently marking a line-ending 'method' as a bareword (fix c532)
2818 14 50       32 return if ( $i_tok >= $max_token_index );
2819              
2820             # If a '$' follows 'method'...
2821             # Check for possible Object::Pad lexical method like
2822             # 'method $var {'
2823             # TODO: maybe merge this with the code below by increasing pos by 1
2824 14 100 66     47 if ( $next_nonblank_token eq '$' && new_statement_ok() ) {
2825 2         7 return 1;
2826             }
2827              
2828             # Otherwise, not a method if non-word follows ..
2829 12 100       46 if ( $next_nonblank_token !~ /^[\w\:]/ ) { return }
  4         12  
2830              
2831             # from do_scan_sub:
2832 8         15 my $i_beg = $i + 1;
2833 8         14 my $pos_beg = $rtoken_map->[$i_beg];
2834 8         23 pos($input_line) = $pos_beg;
2835              
2836             # TEST 1: look a valid sub NAME
2837 8 50       45 if (
2838             $input_line =~ m{\G\s*
2839             ((?:\w*(?:'|::))*) # package - something that ends in :: or '
2840             (\w+) # NAME - required
2841             }gcx
2842             )
2843             {
2844             # For possible future use..
2845             ##my $subname = $2;
2846             ##my $package = $1 ? $1 : EMPTY_STRING;
2847             }
2848             else {
2849 0         0 return;
2850             }
2851              
2852             # TEST 2: look for invalid characters after name, such as here:
2853             # method paint => sub {
2854             # ...
2855             # }
2856 8         19 my $next_char = EMPTY_STRING;
2857 8 100       23 if ( $input_line =~ m/\s*(\S)/gcx ) { $next_char = $1 }
  7         15  
2858 8 100 66     34 if ( !$next_char || $next_char eq '#' ) {
2859 1         3 ( $next_char, my $i_next_uu ) =
2860             $self->find_next_nonblank_token( $max_token_index,
2861             $rtokens, $max_token_index );
2862             }
2863              
2864 8 50       21 if ( !$next_char ) {
2865              
2866             # out of characters - give up
2867 0         0 return;
2868             }
2869              
2870             # Possibly valid next token types:
2871             # '(' could start prototype or signature
2872             # ':' could start ATTRIBUTE
2873             # '{' cold start BLOCK
2874             # ';' or '}' could end a statement
2875 8 100       23 if ( $next_char !~ /^[\(\:\{\;\}]/ ) {
2876              
2877             # This does not match use feature 'class' syntax
2878 3         9 return;
2879             }
2880              
2881             # We will stop here and assume that this is valid syntax for
2882             # use feature 'class'.
2883 5         18 return 1;
2884             } ## end sub method_ok_here
2885              
2886             sub class_ok_here {
2887              
2888 12     12 0 35 my $self = shift;
2889              
2890             # Return:
2891             # false if this is definitely an invalid class declaration
2892             # true otherwise (even if not sure)
2893              
2894             # We are trying to avoid problems with old uses of 'class'
2895             # when --use-feature=class is set (rt145706). We look ahead
2896             # see if this use of 'class' is obviously inconsistent with
2897             # the syntax of use feature 'class'. This allows the default
2898             # setting --use-feature=class to work for old syntax too.
2899              
2900             # Valid class declarations look like
2901             # class NAME ?ATTRS ?VERSION ?BLOCK
2902             # where ATTRS VERSION and BLOCK are optional
2903              
2904             # For example, this should produce a return of 'false':
2905             #
2906             # class ExtendsBasicAttributes is BasicAttributes{
2907              
2908             # TEST 1: class stmt can only go where a new statement can start
2909 12 50       29 if ( !new_statement_ok() ) { return }
  0         0  
2910              
2911 12         22 my $i_beg = $i + 1;
2912 12         22 my $pos_beg = $rtoken_map->[$i_beg];
2913 12         36 pos($input_line) = $pos_beg;
2914              
2915             # TEST 2: look for a valid NAME
2916 12 50       75 if (
2917             $input_line =~ m{\G\s*
2918             ((?:\w*(?:'|::))*) # package - something that ends in :: or '
2919             (\w+) # NAME - required
2920             }gcx
2921             )
2922             {
2923             # For possible future use..
2924             ##my $subname = $2;
2925             ##my $package = $1 ? $1 : EMPTY_STRING;
2926             }
2927             else {
2928 0         0 return;
2929             }
2930              
2931             # TEST 3: look for valid characters after NAME
2932 12         18 my $next_char = EMPTY_STRING;
2933 12 100       39 if ( $input_line =~ m/\s*(\S)/gcx ) { $next_char = $1 }
  11         25  
2934 12 100 66     55 if ( !$next_char || $next_char eq '#' ) {
2935 1         5 ( $next_char, my $i_next_uu ) =
2936             $self->find_next_nonblank_token( $max_token_index,
2937             $rtokens, $max_token_index );
2938             }
2939 12 50       27 if ( !$next_char ) {
2940              
2941             # out of characters - give up
2942 0         0 return;
2943             }
2944              
2945             # Must see one of: ATTRIBUTE, VERSION, BLOCK, or end stmt
2946              
2947             # Possibly valid next token types:
2948             # ':' could start ATTRIBUTE
2949             # '\d' could start VERSION
2950             # '{' cold start BLOCK
2951             # ';' could end a statement
2952             # '}' could end statement but would be strange
2953              
2954 12 100       39 if ( $next_char !~ /^[\:\d\{\;\}]/ ) {
2955              
2956             # This does not match use feature 'class' syntax
2957 2         8 return;
2958             }
2959              
2960             # We will stop here and assume that this is valid syntax for
2961             # use feature 'class'.
2962 10         32 return 1;
2963             } ## end sub class_ok_here
2964              
2965             sub scan_id {
2966 425     425 0 589 my $self = shift;
2967              
2968             # Scan for a sub or package name
2969              
2970 425         1545 ( $i, $tok, $type, $id_scan_state ) = $self->scan_id_do(
2971              
2972             $input_line,
2973             $i, $tok,
2974             $rtokens,
2975             $rtoken_map,
2976             $id_scan_state,
2977             $max_token_index,
2978             );
2979 425         886 return;
2980             } ## end sub scan_id
2981              
2982             sub scan_number {
2983 687     687 0 823 my $self = shift;
2984 687         762 my $number;
2985 687         1573 ( $i, $type, $number ) =
2986             $self->scan_number_do( $input_line, $i, $rtoken_map, $type,
2987             $max_token_index );
2988 687         1291 return $number;
2989             } ## end sub scan_number
2990              
2991 44     44   332 use constant VERIFY_FASTNUM => 0;
  44         80  
  44         26991  
2992              
2993             sub scan_number_fast {
2994              
2995 2906     2906 0 3428 my $self = shift;
2996              
2997             # This is a wrapper for sub scan_number. It does a fast preliminary
2998             # scan for a simple integer. It calls the original scan_number if it
2999             # does not find one.
3000              
3001 2906         3479 my $i_begin = $i;
3002 2906         3405 my $tok_begin = $tok;
3003 2906         3079 my $number;
3004              
3005             #---------------------------------
3006             # Quick check for (signed) integer
3007             #---------------------------------
3008              
3009             # This will be the string of digits:
3010 2906         3378 my $i_d = $i;
3011 2906         3288 my $tok_d = $tok;
3012 2906         3845 my $typ_d = $rtoken_type->[$i_d];
3013              
3014             # check for signed integer
3015 2906         3794 my $sign = EMPTY_STRING;
3016 2906 50 66     6851 if ( $typ_d ne 'd'
      66        
      33        
3017             && ( $typ_d eq '+' || $typ_d eq '-' )
3018             && $i_d < $max_token_index )
3019             {
3020 392         494 $sign = $tok_d;
3021 392         490 $i_d++;
3022 392         559 $tok_d = $rtokens->[$i_d];
3023 392         584 $typ_d = $rtoken_type->[$i_d];
3024             }
3025              
3026             # Handle integers
3027 2906 100 100     15025 if (
      100        
3028             $typ_d eq 'd'
3029             && (
3030             $i_d == $max_token_index
3031             || ( $i_d < $max_token_index
3032             && $rtoken_type->[ $i_d + 1 ] ne '.'
3033             && $rtoken_type->[ $i_d + 1 ] ne 'w' )
3034             )
3035             )
3036             {
3037             # Let the full scanner handle multi-digit integers beginning with
3038             # '0' because there could be error messages. For example, '009' is
3039             # not a valid number.
3040              
3041 2286 100 100     6805 if ( $tok_d eq '0' || substr( $tok_d, 0, 1 ) ne '0' ) {
3042 2229         3123 $number = $sign . $tok_d;
3043 2229         2653 $type = 'n';
3044 2229         2718 $i = $i_d;
3045             }
3046             }
3047              
3048             #--------------------------------------
3049             # Verify correctness during development
3050             #--------------------------------------
3051 2906         3118 if ( VERIFY_FASTNUM && defined($number) ) {
3052              
3053             # We will call the full method
3054             my $type_simple = $type;
3055             my $i_simple = $i;
3056             my $number_simple = $number;
3057              
3058             $tok = $tok_begin;
3059             $i = $i_begin;
3060             $number = $self->scan_number();
3061              
3062             if ( $type ne $type_simple
3063             || ( $i != $i_simple && $i <= $max_token_index )
3064             || $number ne $number_simple )
3065             {
3066             print {*STDERR} <<EOM;
3067             scan_number_fast differs from scan_number:
3068             simple: i=$i_simple, type=$type_simple, number=$number_simple
3069             full: i=$i, type=$type, number=$number
3070             EOM
3071             }
3072             }
3073              
3074             #----------------------------------------
3075             # call full scanner if may not be integer
3076             #----------------------------------------
3077 2906 100       4501 if ( !defined($number) ) {
3078 677         1403 $number = $self->scan_number();
3079             }
3080 2906         5420 return $number;
3081             } ## end sub scan_number_fast
3082              
3083             sub error_if_expecting_TERM {
3084 1679     1679 0 2704 my ($self) = @_;
3085              
3086             # Issue a warning if a binary operator is missing a term to operate on
3087              
3088             # This should only be called if a term is expected here
3089 1679 50       3092 if ( $expecting != TERM ) { return }
  0         0  
3090              
3091             # Be sure a TERM is definitely required ..
3092 1679 50 66     10783 if (
      66        
      66        
      33        
3093              
3094             # .. following a binary operator token type, like '='
3095             $is_binary_or_unary_operator_type{$last_nonblank_type}
3096              
3097             # .. or following a binary keyword operator, like 'and'
3098             || ( $last_nonblank_type eq 'k'
3099             && $is_binary_or_unary_keyword{$last_nonblank_token} )
3100              
3101             # .. or for a binary operator following something like a ';'
3102             || ( $is_not_a_TERM_producer_type{$last_nonblank_type}
3103             && $is_binary_operator_type{$tok} )
3104             )
3105             {
3106              
3107             # We must exclude error checking in sub signatures which have some
3108             # unusual syntax. For example the following syntax is okay within
3109             # a signature:
3110             # sub mysub ($=,) {...}
3111             # $ = undef
3112 1         2 my $ct = $rparen_type->[$paren_depth];
3113 1 50 33     9 if ( $ct && $ct =~ /^sub\b/ ) { return }
  1         3  
3114              
3115             $self->report_unexpected(
3116             {
3117 0         0 found => $tok,
3118             expecting => "term",
3119             i_tok => $i_tok,
3120             last_nonblank_i => $last_nonblank_i,
3121             rpretoken_map => $rtoken_map,
3122             rpretoken_type => $rtoken_type,
3123             input_line => $input_line,
3124             }
3125             );
3126 0         0 return 1;
3127             }
3128 1678         2614 return;
3129             } ## end sub error_if_expecting_TERM
3130              
3131             # a sub to warn if token found where operator expected
3132             sub error_if_expecting_OPERATOR {
3133              
3134 821     821 0 1301 my ( $self, ($thing) ) = @_;
3135              
3136             # Issue warning on error if expecting operator
3137             # Given:
3138             # $thing = the unexpected token or issue
3139             # = undef to use current pre-token
3140              
3141 821 50       1478 if ( $expecting == OPERATOR ) {
3142 0 0       0 if ( !defined($thing) ) { $thing = $tok }
  0         0  
3143             $self->report_unexpected(
3144             {
3145 0         0 found => $thing,
3146             expecting => "operator",
3147             i_tok => $i_tok,
3148             last_nonblank_i => $last_nonblank_i,
3149             rpretoken_map => $rtoken_map,
3150             rpretoken_type => $rtoken_type,
3151             input_line => $input_line,
3152             }
3153             );
3154 0 0       0 if ( $i_tok == 0 ) {
3155 0         0 $self->interrupt_logfile();
3156 0         0 $self->warning("Missing ';' or ',' above?\n");
3157 0         0 $self->resume_logfile();
3158             }
3159 0         0 return 1;
3160             }
3161 821         1230 return;
3162             } ## end sub error_if_expecting_OPERATOR
3163              
3164             # ------------------------------------------------------------
3165             # end scanner interfaces
3166             # ------------------------------------------------------------
3167              
3168             #------------------
3169             # Tokenization subs
3170             #------------------
3171             # An identifier in possible indirect object location followed by any of
3172             # these tokens: -> , ; } (plus others) is not an indirect object. Fix c257.
3173             my %Z_test_hash;
3174              
3175             BEGIN {
3176 44     44   437 my @qZ = qw#
3177             -> ; } ) ]
3178             => =~ = == !~ || >= != *= .. && |= .= -= += <= %=
3179             ^= &&= ||= //= <=>
3180             #;
3181 44         121 push @qZ, COMMA;
3182 44         264940 $Z_test_hash{$_} = 1 for @qZ;
3183             }
3184              
3185             sub do_DOLLAR_SIGN {
3186              
3187 4879     4879 0 5665 my $self = shift;
3188              
3189             # '$'
3190             # start looking for a scalar
3191 4879 50       7810 $self->error_if_expecting_OPERATOR("Scalar")
3192             if ( $expecting == OPERATOR );
3193 4879         12436 $self->scan_simple_identifier();
3194              
3195 4879 100       8470 if ( $identifier eq '$^W' ) {
3196 1         2 $self->[_saw_perl_dash_w_] = 1;
3197             }
3198              
3199             # Check for identifier in indirect object slot
3200             # (vorboard.pl, sort.t). Something like:
3201             # /^(print|printf|sort|exec|system)$/
3202 4879 100 66     28135 if (
      100        
      100        
      66        
      66        
3203             $is_indirect_object_taker{$last_nonblank_token}
3204             && $last_nonblank_type eq 'k'
3205             || ( ( $last_nonblank_token eq '(' )
3206             && $is_indirect_object_taker{ $rparen_type->[$paren_depth] } )
3207             || ( $last_nonblank_type eq 'w'
3208             || $last_nonblank_type eq 'U' ) # possible object
3209             )
3210             {
3211              
3212             # An identifier followed by '->' is not indirect object;
3213             # fixes b1175, b1176. Fix c257: Likewise for other tokens like
3214             # comma, semicolon, closing brace, and single space.
3215 108         397 my ( $next_nonblank_token, $i_next_uu ) =
3216             $self->find_next_noncomment_token( $i, $rtokens,
3217             $max_token_index );
3218 108 100       322 $type = 'Z' if ( !$Z_test_hash{$next_nonblank_token} );
3219             }
3220 4879         5955 return;
3221             } ## end sub do_DOLLAR_SIGN
3222              
3223             sub do_LEFT_PARENTHESIS {
3224              
3225 2443     2443 0 3109 my $self = shift;
3226              
3227             # '('
3228 2443         2865 ++$paren_depth;
3229              
3230             # variable to enable check for brace after closing paren (c230)
3231 2443         3253 my $want_brace = EMPTY_STRING;
3232              
3233 2443 100 66     6936 if ($want_paren) {
    100          
3234 295         410 $container_type = $want_paren;
3235 295         413 $want_brace = $want_paren;
3236 295         447 $want_paren = EMPTY_STRING;
3237             }
3238             elsif ( substr( $statement_type, 0, 3 ) eq 'sub'
3239             && $statement_type =~ /^sub\b/ )
3240             {
3241 20         40 $container_type = $statement_type;
3242             }
3243             else {
3244 2128         2587 $container_type = $last_nonblank_token;
3245              
3246             # We can check for a syntax error here of unexpected '(',
3247             # but this is going to get messy...
3248 2128 100 100     6281 if (
3249             $expecting == OPERATOR
3250              
3251             # Be sure this is not a method call of the form
3252             # &method(...), $method->(..), &{method}(...),
3253             # $ref[2](list) is ok & short for $ref[2]->(list)
3254             # NOTE: at present, braces in something like &{ xxx }
3255             # are not marked as a block, we might have a method call.
3256             # Added ')' to fix case c017, something like ()()()
3257             && $last_nonblank_token !~ /^(?:[\]\}\)\&]|\-\>)/
3258             )
3259             {
3260              
3261             # ref: camel 3 p 703.
3262 3 50       8 if ( $last_last_nonblank_token eq 'do' ) {
3263 0         0 $self->complain(
3264             "do SUBROUTINE is deprecated; consider & or -> notation\n"
3265             );
3266             }
3267             else {
3268              
3269             # if this is an empty list, (), then it is not an
3270             # error; for example, we might have a constant pi and
3271             # invoke it with pi() or just pi;
3272 3         8 my ( $next_nonblank_token, $i_next_uu ) =
3273             $self->find_next_nonblank_token( $i, $rtokens,
3274             $max_token_index );
3275              
3276             # Patch for c029: give up error check if
3277             # a side comment follows
3278 3 50 33     29 if ( $next_nonblank_token ne ')'
3279             && $next_nonblank_token ne '#' )
3280             {
3281 0         0 my $hint;
3282              
3283 0         0 $self->error_if_expecting_OPERATOR('(');
3284              
3285 0 0       0 if ( $last_nonblank_type eq 'C' ) {
    0          
3286 0         0 $hint =
3287             "$last_nonblank_token has a void prototype\n";
3288             }
3289             elsif ( $last_nonblank_type eq 'i' ) {
3290 0 0 0     0 if ( $i_tok > 0
3291             && $last_nonblank_token =~ /^\$/ )
3292             {
3293 0         0 $hint =
3294             "Do you mean '$last_nonblank_token->(' ?";
3295 0 0       0 if ( $is_for_foreach{ $rtokens->[0] } ) {
3296 0         0 $hint .= " ... or is a ';' missing above?";
3297             }
3298 0         0 $hint .= "\n";
3299             }
3300             }
3301             else {
3302             ## no hint
3303             }
3304 0 0       0 if ($hint) {
3305 0         0 $self->interrupt_logfile();
3306 0         0 $self->warning($hint);
3307 0         0 $self->resume_logfile();
3308             }
3309             } ## end if ( $next_nonblank_token...
3310             } ## end else [ if ( $last_last_nonblank_token...
3311             } ## end if ( $expecting == OPERATOR...
3312             }
3313              
3314 2443         6624 ( $type_sequence, $indent_flag ) =
3315             $self->increase_nesting_depth( PAREN, $rtoken_map->[$i_tok] );
3316              
3317             # propagate types down through nested parens
3318             # for example: the second paren in 'if ((' would be structural
3319             # since the first is.
3320              
3321 2443 100       4231 if ( $last_nonblank_token eq '(' ) {
3322 61         94 $type = $last_nonblank_type;
3323             }
3324              
3325             # We exclude parens as structural after a ',' because it
3326             # causes subtle problems with continuation indentation for
3327             # something like this, where the first 'or' will not get
3328             # indented.
3329             #
3330             # assert(
3331             # __LINE__,
3332             # ( not defined $check )
3333             # or ref $check
3334             # or $check eq "new"
3335             # or $check eq "old",
3336             # );
3337             #
3338             # Likewise, we exclude parens where a statement can start
3339             # because of problems with continuation indentation, like
3340             # these:
3341             #
3342             # ($firstline =~ /^#\!.*perl/)
3343             # and (print $File::Find::name, "\n")
3344             # and (return 1);
3345             #
3346             # (ref($usage_fref) =~ /CODE/)
3347             # ? &$usage_fref
3348             # : (&blast_usage, &blast_params, &blast_general_params);
3349              
3350             else {
3351 2382         3002 $type = '{';
3352             }
3353              
3354 2443 50       4328 if ( $last_nonblank_type eq ')' ) {
3355 0         0 $self->warning(
3356             "Syntax error? found token '$last_nonblank_type' then '('\n");
3357             }
3358              
3359             # git #105: Copy container type and want-brace flag at ') (';
3360             # propagate the container type onward so that any subsequent brace gets
3361             # correctly marked. I have implemented this as a general rule, which
3362             # should be safe, but if necessary it could be restricted to certain
3363             # container statement types such as 'for'.
3364 2443 100       4027 if ( $last_nonblank_token eq ')' ) {
3365 1         1 my $rvars = $rparen_vars->[$paren_depth];
3366 1 50       3 if ( defined($rvars) ) {
3367 1         2 $container_type = $rparen_type->[$paren_depth];
3368 1         2 ( my $type_lp_uu, $want_brace ) = @{$rvars};
  1         3  
3369             }
3370             }
3371              
3372 2443         4036 $rparen_type->[$paren_depth] = $container_type;
3373 2443         5221 $rparen_vars->[$paren_depth] = [ $type, $want_brace ];
3374 2443         3651 $rparen_semicolon_count->[$paren_depth] = 0;
3375              
3376 2443         3248 return;
3377              
3378             } ## end sub do_LEFT_PARENTHESIS
3379              
3380             sub do_RIGHT_PARENTHESIS {
3381              
3382 2443     2443 0 3218 my $self = shift;
3383              
3384 2443         6617 ( $type_sequence, $indent_flag ) =
3385             $self->decrease_nesting_depth( PAREN, $rtoken_map->[$i_tok] );
3386              
3387             # ')'
3388 2443 100       4380 if ( $expecting == TERM ) {
3389             $self->error_if_expecting_TERM()
3390 361 100       1660 if ( !$self->[_rsaw_unknown_syntax_in_seqno_]->{$type_sequence} );
3391             }
3392              
3393 2443         3620 my $rvars = $rparen_vars->[$paren_depth];
3394 2443 50       4112 if ( defined($rvars) ) {
3395 2443         2820 my ( $type_lp, $want_brace_uu ) = @{$rvars};
  2443         4239  
3396 2443 50 33     7193 if ( $type_lp && $type_lp eq '{' ) {
3397 2443         3347 $type = '}';
3398             }
3399             }
3400              
3401 2443         3290 $container_type = $rparen_type->[$paren_depth];
3402              
3403             # restore statement type as 'sub' at closing paren of a signature
3404             # so that a subsequent ':' is identified as an attribute
3405 2443 100 100     5810 if ( substr( $container_type, 0, 3 ) eq 'sub'
3406             && $container_type =~ /^sub\b/ )
3407             {
3408 30         55 $statement_type = $container_type;
3409             }
3410              
3411 2443 100       5070 if ( $is_for_foreach{ $rparen_type->[$paren_depth] } ) {
3412 79         136 my $num_sc = $rparen_semicolon_count->[$paren_depth];
3413 79 50 66     275 if ( $num_sc > 0 && $num_sc != 2 ) {
3414 0         0 $self->warning("Expected 2 ';' in 'for(;;)' but saw $num_sc\n");
3415             }
3416             }
3417              
3418 2443 50       4021 if ( $paren_depth > 0 ) { $paren_depth-- }
  2443         2957  
3419 2443         3144 return;
3420             } ## end sub do_RIGHT_PARENTHESIS
3421              
3422             sub do_COMMA {
3423              
3424 3712     3712 0 4037 my $self = shift;
3425              
3426             # ','
3427 3712 100 33     9063 if ( $last_nonblank_type eq COMMA ) {
    50          
3428 10         26 $self->complain("Repeated ','s \n");
3429             }
3430              
3431             # Note that we have to check both token and type here because a
3432             # comma following a qw list can have last token='(' but type = 'q'
3433             elsif ( $last_nonblank_token eq '(' && $last_nonblank_type eq '{' ) {
3434 0         0 $self->warning("Unexpected leading ',' after a '('\n");
3435             }
3436             else {
3437             ## Error check added in update c565, moved to end of $code loop.
3438             }
3439              
3440             # patch for operator_expected: note if we are in the list (use.t)
3441 3712 100       5849 if ( $statement_type eq 'use' ) { $statement_type = '_use' }
  6         10  
3442 3712         4313 return;
3443              
3444             } ## end sub do_COMMA
3445              
3446             sub do_SEMICOLON {
3447              
3448 2936     2936 0 3544 my $self = shift;
3449              
3450             # ';'
3451 2936         3638 $context = UNKNOWN_CONTEXT;
3452 2936         3556 $statement_type = EMPTY_STRING;
3453 2936         3686 $want_paren = EMPTY_STRING;
3454              
3455 2936 100       6430 if ( $is_for_foreach{ $rparen_type->[$paren_depth] } )
3456             { # mark ; in for loop
3457              
3458             # Be careful: we do not want a semicolon such as the
3459             # following to be included:
3460             #
3461             # for (sort {strcoll($a,$b);} keys %investments) {
3462              
3463 35 100 66     191 if ( $brace_depth == $rdepth_array->[PAREN]->[BRACE]->[$paren_depth]
3464             && $square_bracket_depth ==
3465             $rdepth_array->[PAREN]->[SQUARE_BRACKET]->[$paren_depth] )
3466             {
3467              
3468 34         53 $type = 'f';
3469 34         52 $rparen_semicolon_count->[$paren_depth]++;
3470             }
3471             }
3472             else {
3473             ## Error check added in update c565, moved to end of $code loop.
3474             }
3475 2936         3622 return;
3476             } ## end sub do_SEMICOLON
3477              
3478             sub do_QUOTATION_MARK {
3479              
3480 1289     1289 0 1721 my $self = shift;
3481              
3482             # '"'
3483 1289 50       2376 $self->error_if_expecting_OPERATOR("String")
3484             if ( $expecting == OPERATOR );
3485 1289         1620 $in_quote = 1;
3486 1289         1608 $type = 'Q';
3487 1289         1603 $allowed_quote_modifiers = EMPTY_STRING;
3488 1289         1521 $quote_starting_tok = $tok;
3489 1289         1649 $quote_here_target_2 = undef;
3490 1289         1633 return;
3491             } ## end sub do_QUOTATION_MARK
3492              
3493             sub do_APOSTROPHE {
3494              
3495 1349     1349 0 1702 my $self = shift;
3496              
3497             # "'"
3498 1349 50       2437 $self->error_if_expecting_OPERATOR("String")
3499             if ( $expecting == OPERATOR );
3500 1349         1663 $in_quote = 1;
3501 1349         1594 $type = 'Q';
3502 1349         1574 $allowed_quote_modifiers = EMPTY_STRING;
3503 1349         1568 $quote_starting_tok = $tok;
3504 1349         1578 $quote_here_target_2 = undef;
3505 1349         1714 return;
3506             } ## end sub do_APOSTROPHE
3507              
3508             sub do_BACKTICK {
3509              
3510 0     0 0 0 my $self = shift;
3511              
3512             # '`'
3513 0 0       0 $self->error_if_expecting_OPERATOR("String")
3514             if ( $expecting == OPERATOR );
3515 0         0 $in_quote = 1;
3516 0         0 $type = 'Q';
3517 0         0 $allowed_quote_modifiers = EMPTY_STRING;
3518 0         0 $quote_starting_tok = $tok;
3519 0         0 $quote_here_target_2 = undef;
3520 0         0 return;
3521             } ## end sub do_BACKTICK
3522              
3523             sub do_SLASH {
3524              
3525 225     225 0 336 my $self = shift;
3526              
3527             # '/'
3528 225         290 my $is_pattern;
3529              
3530             # a pattern cannot follow certain keywords which take optional
3531             # arguments, like 'shift' and 'pop'. See also '?'.
3532 225 50 66     851 if (
    50          
3533             $last_nonblank_type eq 'k'
3534             && $is_keyword_rejecting_slash_as_pattern_delimiter{
3535             $last_nonblank_token}
3536             )
3537             {
3538 0         0 $is_pattern = 0;
3539             }
3540             elsif ( $expecting == UNKNOWN ) { # indeterminate, must guess..
3541             (
3542 0         0 $is_pattern,
3543             my $msg,
3544              
3545             ) = $self->guess_if_pattern_or_division(
3546              
3547             $i,
3548             $rtokens,
3549             $rtoken_type,
3550             $rtoken_map,
3551             $max_token_index,
3552             );
3553              
3554 0 0       0 if ($msg) {
3555 0         0 if ( 0 && DEBUG_GUESS_MODE ) {
3556             $self->warning("DEBUG_GUESS_MODE message:\n$msg\n");
3557             }
3558 0         0 $self->write_diagnostics("DIVIDE:$msg\n");
3559 0         0 $self->write_logfile_entry($msg);
3560             }
3561             }
3562             else {
3563 225         394 $is_pattern = ( $expecting == TERM );
3564             }
3565              
3566 225 100       464 if ($is_pattern) {
3567 88         123 $in_quote = 1;
3568 88         131 $type = 'Q';
3569 88         209 $allowed_quote_modifiers = $quote_modifiers{'m'};
3570 88         126 $quote_starting_tok = 'm';
3571 88         135 $quote_here_target_2 = undef;
3572             }
3573             else { # not a pattern; check for a /= token
3574              
3575 137 100       343 if ( $rtokens->[ $i + 1 ] eq '=' ) { # form token /=
3576 4         11 $i++;
3577 4         9 $tok = '/=';
3578 4         10 $type = $tok;
3579             }
3580              
3581             #DEBUG - collecting info on what tokens follow a divide
3582             # for development of guessing algorithm
3583             ## if (
3584             ## $self->is_possible_numerator( $i, $rtokens,
3585             ## $max_token_index ) < 0
3586             ## )
3587             ## {
3588             ## $self->write_diagnostics("DIVIDE? $input_line\n");
3589             ## }
3590             }
3591 225         335 return;
3592             } ## end sub do_SLASH
3593              
3594             sub do_LEFT_CURLY_BRACKET {
3595              
3596 2076     2076 0 2694 my $self = shift;
3597              
3598             # '{'
3599 2076         2237 if ( 0 && $next_tok eq '%' ) {
3600             ## c583: Spot for possible future check for a '{% ' which starts
3601             ## a simple macro. If there is a matching closing '%}' on this
3602             ## line then mark the whole structure as a quote.
3603             }
3604              
3605             # if we just saw a ')', we will label this block with
3606             # its type. We need to do this to allow sub
3607             # code_block_type to determine if this brace starts a
3608             # code block or anonymous hash. (The type of a paren
3609             # pair is the preceding token, such as 'if', 'else',
3610             # etc).
3611 2076         2759 $container_type = EMPTY_STRING;
3612              
3613             # ATTRS: for a '{' following an attribute list, reset
3614             # things to look like we just saw a sub name
3615             # Added 'package' (can be 'class') for --use-feature=class (rt145706)
3616 2076 100 100     13930 if ( substr( $statement_type, 0, 3 ) eq 'sub' ) {
    100 66        
    50 33        
    100          
    50          
3617 36         54 $last_nonblank_token = $statement_type;
3618 36         52 $last_nonblank_type = 'S'; # c250 change
3619 36         60 $statement_type = EMPTY_STRING;
3620             }
3621             elsif ( substr( $statement_type, 0, 7 ) eq 'package' ) {
3622 10         15 $last_nonblank_token = $statement_type;
3623 10         12 $last_nonblank_type = 'P'; # c250 change
3624 10         15 $statement_type = EMPTY_STRING;
3625             }
3626              
3627             # patch for SWITCH/CASE: hide these keywords from an immediately
3628             # following opening brace
3629             elsif ( ( $statement_type eq 'case' || $statement_type eq 'when' )
3630             && $statement_type eq $last_nonblank_token )
3631             {
3632 0         0 $last_nonblank_token = ";";
3633             }
3634              
3635             elsif ( $last_nonblank_token eq ')' ) {
3636 301         519 $last_nonblank_token = $rparen_type->[ $paren_depth + 1 ];
3637              
3638             # defensive move in case of a nesting error (pbug.t)
3639             # in which this ')' had no previous '('
3640             # this nesting error will have been caught
3641 301 50       659 if ( !defined($last_nonblank_token) ) {
3642 0         0 $last_nonblank_token = 'if';
3643             }
3644              
3645             # Syntax check at '){'
3646 301 100       757 if ( $is_blocktype_with_paren{$last_nonblank_token} ) {
3647              
3648 285         485 my $rvars = $rparen_vars->[ $paren_depth + 1 ];
3649 285 50       613 if ( defined($rvars) ) {
3650 285         381 my ( $type_lp_uu, $want_brace ) = @{$rvars};
  285         551  
3651              
3652             # OLD: Now verify that this is not a trailing form
3653             # FIX for git #124: we have to skip this check because
3654             # the 'gather' keyword of List::Gather can operate on
3655             # a full statement, so it isn't possible to be sure
3656             # this is a trailing form.
3657 285         449 if ( 0 && !$want_brace ) {
3658             $self->warning(
3659             "syntax error at ') {', unexpected '{' after closing ')' of a trailing '$last_nonblank_token'\n"
3660             );
3661             }
3662             }
3663             }
3664             else {
3665 16 50       40 if ($rOpts_extended_syntax) {
3666              
3667             # we append a trailing () to mark this as an unknown
3668             # block type. This allows perltidy to format some
3669             # common extensions of perl syntax.
3670             # This is used by sub code_block_type
3671 16         32 $last_nonblank_token .= '()';
3672             }
3673             else {
3674 0         0 my $list =
3675             join( SPACE, sort keys %is_blocktype_with_paren );
3676 0         0 $self->warning(
3677             "syntax error at ') {', didn't see one of: <<$list>>; If this code is okay try using the -xs flag\n"
3678             );
3679             }
3680             }
3681             }
3682              
3683             # patch for paren-less for/foreach glitch, part 2.
3684             # see note below under 'qw'
3685             elsif ($last_nonblank_token eq 'qw'
3686             && $is_for_foreach{$want_paren} )
3687             {
3688 0         0 $last_nonblank_token = $want_paren;
3689 0 0       0 if ( $last_last_nonblank_token eq $want_paren ) {
3690 0         0 $self->warning(
3691             "syntax error at '$want_paren .. {' -- missing \$ loop variable\n"
3692             );
3693              
3694             }
3695 0         0 $want_paren = EMPTY_STRING;
3696             }
3697             else {
3698             ## not special
3699             }
3700              
3701             # now identify which of the three possible types of
3702             # curly braces we have: hash index container, anonymous
3703             # hash reference, or code block.
3704              
3705             # Patch for Object::Pad "field $var BLOCK"
3706 2076 100 66     7641 if ( $statement_type eq 'field'
    100 66        
      33        
3707             && $last_last_nonblank_token eq 'field'
3708             && $last_nonblank_type eq 'i'
3709             && $last_last_nonblank_type eq 'k' )
3710             {
3711 8         12 $type = '{';
3712 8         13 $block_type = $statement_type;
3713             }
3714              
3715             # non-structural (hash index) curly brace pair
3716             # get marked 'L' and 'R'
3717             elsif ( is_non_structural_brace() ) {
3718 588         876 $type = 'L';
3719              
3720             # patch for SWITCH/CASE:
3721             # allow paren-less identifier after 'when'
3722             # if the brace is preceded by a space
3723 588 0 33     1514 if ( $statement_type eq 'when'
      33        
      0        
      0        
3724             && $last_nonblank_type eq 'i'
3725             && $last_last_nonblank_type eq 'k'
3726             && ( $i_tok == 0 || $rtoken_type->[ $i_tok - 1 ] eq 'b' ) )
3727             {
3728 0         0 $type = '{';
3729 0         0 $block_type = $statement_type;
3730             }
3731             }
3732              
3733             # code and anonymous hash have the same type, '{', but are
3734             # distinguished by 'block_type',
3735             # which will be blank for an anonymous hash
3736             else {
3737 1480         3950 $block_type =
3738             $self->code_block_type( $i_tok, $rtokens, $rtoken_type,
3739             $max_token_index );
3740              
3741             # Is a new lexical sub looking for its block sequence number?
3742             # This is indicated with a special '911' signal.
3743 1480 0 66     5232 if ( $block_type
      33        
      33        
3744             && $ris_lexical_sub->{911}
3745             && $last_nonblank_type eq 'S'
3746             && substr( $block_type, 0, 3 ) eq 'sub' )
3747             {
3748 0         0 my ( $subname, $package ) = @{ $ris_lexical_sub->{911} };
  0         0  
3749 0 0 0     0 if ( $block_type =~ /^sub $subname/
3750             && $is_my_our_state{$last_last_nonblank_token} )
3751             {
3752 0         0 $ris_lexical_sub->{$subname}->{$package} =
3753             $next_sequence_number;
3754             }
3755              
3756             # Turn the signal off, even if we did not find the block being
3757             # sought - it may not exist if the sub statement was a simple
3758             # declaration without a block definition.
3759 0         0 $ris_lexical_sub->{911} = undef;
3760             }
3761              
3762             # patch to promote bareword type to function taking block
3763 1480 100 100     4760 if ( $block_type
      66        
3764             && $last_nonblank_type eq 'w'
3765             && $last_nonblank_i >= 0 )
3766             {
3767 36 50       98 if ( $routput_token_type->[$last_nonblank_i] eq 'w' ) {
3768             $routput_token_type->[$last_nonblank_i] =
3769 36 100       150 $is_grep_alias{$block_type} ? 'k' : 'G';
3770             }
3771             }
3772              
3773             # patch for SWITCH/CASE: if we find a stray opening block brace
3774             # where we might accept a 'case' or 'when' block, then take it
3775 1480 100 100     4576 if ( $statement_type eq 'case'
3776             || $statement_type eq 'when' )
3777             {
3778 48 100 66     191 if ( !$block_type || $block_type eq '}' ) {
3779 4         5 $block_type = $statement_type;
3780             }
3781             }
3782             }
3783              
3784 2076         3739 $rbrace_type->[ ++$brace_depth ] = $block_type;
3785              
3786             # Patch for CLASS BLOCK definitions: do not update the package for the
3787             # current depth if this is a BLOCK type definition.
3788             # TODO: should make 'class' separate from 'package' and only do
3789             # this for 'class'
3790 2076 100       5172 $rbrace_package->[$brace_depth] = $current_package
3791             if ( substr( $block_type, 0, 8 ) ne 'package ' );
3792              
3793 2076         3194 $rbrace_structural_type->[$brace_depth] = $type;
3794 2076         3061 $rbrace_context->[$brace_depth] = $context;
3795 2076         4700 ( $type_sequence, $indent_flag ) =
3796             $self->increase_nesting_depth( BRACE, $rtoken_map->[$i_tok] );
3797              
3798 2076         3078 return;
3799             } ## end sub do_LEFT_CURLY_BRACKET
3800              
3801             sub do_RIGHT_CURLY_BRACKET {
3802              
3803 2076     2076 0 2720 my $self = shift;
3804              
3805             # '}'
3806 2076         3247 $block_type = $rbrace_type->[$brace_depth];
3807 2076 100       3804 if ($block_type) { $statement_type = EMPTY_STRING }
  1151         1614  
3808 2076 100       3616 if ( defined( $rbrace_package->[$brace_depth] ) ) {
3809 2066         3160 $current_package = $rbrace_package->[$brace_depth];
3810             }
3811             else {
3812             ## can happen on brace error (caught elsewhere)
3813             }
3814 2076         5366 ( $type_sequence, $indent_flag ) =
3815             $self->decrease_nesting_depth( BRACE, $rtoken_map->[$i_tok] );
3816              
3817 2076 100       3880 if ( $expecting == TERM ) {
3818             $self->error_if_expecting_TERM()
3819             if (
3820 946 100 66     4840 !$self->[_rsaw_unknown_syntax_in_seqno_]->{$type_sequence}
3821              
3822             # c583: no error check at a possible end-of-macro combo '%}'
3823             && $last_nonblank_type ne '%'
3824             );
3825             }
3826              
3827 2076 100       4052 if ( $rbrace_structural_type->[$brace_depth] eq 'L' ) {
3828 588         756 $type = 'R';
3829             }
3830              
3831             # propagate type information for 'do' and 'eval' blocks, and also
3832             # for smartmatch operator. This is necessary to enable us to know
3833             # if an operator or term is expected next.
3834 2076 100       4330 if ( $is_block_operator{$block_type} ) {
3835 85         132 $tok = $block_type;
3836             }
3837              
3838             # pop non-indenting brace stack if sequence number matches
3839 2076 100 100     2279 if ( @{ $self->[_rnon_indenting_brace_stack_] }
  2076         4489  
3840             && $self->[_rnon_indenting_brace_stack_]->[-1] eq $type_sequence )
3841             {
3842 6         8 pop @{ $self->[_rnon_indenting_brace_stack_] };
  6         11  
3843             }
3844              
3845 2076         2808 $context = $rbrace_context->[$brace_depth];
3846 2076 50       3565 if ( $brace_depth > 0 ) { $brace_depth--; }
  2076         2317  
3847 2076         2580 return;
3848             } ## end sub do_RIGHT_CURLY_BRACKET
3849              
3850             sub do_AMPERSAND {
3851              
3852 126     126 0 194 my $self = shift;
3853              
3854             # '&' = maybe sub call? start looking
3855             # We have to check for sub call unless we are sure we
3856             # are expecting an operator. This example from s2p
3857             # got mistaken as a q operator in an early version:
3858             # print BODY &q(<<'EOT');
3859 126 100       300 if ( $expecting != OPERATOR ) {
3860              
3861             # But only look for a sub call if we are expecting a term or
3862             # if there is no existing space after the &.
3863             # For example we probably don't want & as sub call here:
3864             # Fcntl::S_IRUSR & $mode;
3865 106 100 66     313 if ( $expecting == TERM || $next_type ne 'b' ) {
3866 103         280 $self->scan_simple_identifier();
3867             }
3868             }
3869             else {
3870             ## '&' is an operator
3871             }
3872 126         181 return;
3873             } ## end sub do_AMPERSAND
3874              
3875             sub do_LESS_THAN_SIGN {
3876              
3877 33     33 0 82 my $self = shift;
3878              
3879             # '<' - angle operator or less than?
3880 33 100       215 if ( $expecting != OPERATOR ) {
3881 8         38 ( $i, $type ) = $self->find_angle_operator_termination(
3882              
3883             $input_line,
3884             $i,
3885             $rtoken_map,
3886             $expecting,
3887             $max_token_index,
3888             );
3889 8         18 if ( DEBUG_GUESS_MODE && $expecting == UNKNOWN ) {
3890             my $msg = "guessing that '<' is ";
3891             $msg .=
3892             $type eq 'Q' ? "an angle operator" : "a less than symbol";
3893             if ( $type eq 'Q' ) {
3894             $self->warning("DEBUG_GUESS_MODE message:\n$msg\n");
3895             }
3896             }
3897             }
3898             else {
3899             ## ok: '<' is less than
3900             }
3901 33         55 return;
3902             } ## end sub do_LESS_THAN_SIGN
3903              
3904             sub do_QUESTION_MARK {
3905              
3906 193     193 0 281 my $self = shift;
3907              
3908             # '?' = conditional or starting pattern?
3909 193         285 my $is_pattern;
3910              
3911             # Patch for rt #126965
3912             # a pattern cannot follow certain keywords which take optional
3913             # arguments, like 'shift' and 'pop'. See also '/'.
3914 193 100 66     1248 if (
    100          
    100          
3915             $last_nonblank_type eq 'k'
3916             && $is_keyword_rejecting_question_as_pattern_delimiter{
3917             $last_nonblank_token}
3918             )
3919             {
3920 1         2 $is_pattern = 0;
3921             }
3922              
3923             # patch for RT#131288, user constant function without prototype
3924             # last type is 'U' followed by ?.
3925             elsif ( $last_nonblank_type =~ /^[FUY]$/ ) {
3926 1         2 $is_pattern = 0;
3927             }
3928             elsif ( $expecting == UNKNOWN ) {
3929              
3930             # In older versions of Perl, a bare ? can be a pattern
3931             # delimiter. In perl version 5.22 this was
3932             # dropped, but we have to support it in order to format
3933             # older programs. See:
3934             ## https://perl.developpez.com/documentations/en/5.22.0/perl5211delta.html
3935             # For example, the following line worked
3936             # at one time:
3937             # ?(.*)? && (print $1,"\n");
3938             # In current versions it would have to be written with slashes:
3939             # /(.*)/ && (print $1,"\n");
3940             (
3941 12         60 $is_pattern,
3942             my $msg,
3943              
3944             ) = $self->guess_if_pattern_or_conditional(
3945              
3946             $i,
3947             $rtokens,
3948             $rtoken_type,
3949             $rtoken_map,
3950             $max_token_index,
3951             );
3952              
3953 12 50       36 if ($msg) {
3954 12         48 $self->write_logfile_entry($msg);
3955 12         24 if ( DEBUG_GUESS_MODE && $is_pattern ) {
3956             $self->warning("DEBUG_GUESS_MODE message:\n$msg\n");
3957             }
3958             }
3959             }
3960             else {
3961 179         1604 $is_pattern = ( $expecting == TERM );
3962             }
3963              
3964 193 50       428 if ($is_pattern) {
3965 0         0 $in_quote = 1;
3966 0         0 $type = 'Q';
3967 0         0 $allowed_quote_modifiers = $quote_modifiers{'m'};
3968 0         0 $quote_starting_tok = 'm';
3969 0         0 $quote_here_target_2 = undef;
3970             }
3971             else {
3972 193         601 ( $type_sequence, $indent_flag ) =
3973             $self->increase_nesting_depth( QUESTION_COLON,
3974             $rtoken_map->[$i_tok] );
3975             }
3976 193         332 return;
3977             } ## end sub do_QUESTION_MARK
3978              
3979             sub do_STAR {
3980              
3981 254     254 0 361 my $self = shift;
3982              
3983             # '*' = typeglob, or multiply?
3984              
3985             # Guess based on next token. See also c036, and versions before 2026-
3986 254 100 100     730 if ( $expecting == UNKNOWN && $next_type ne 'b' ) {
3987              
3988             # Check for a normal glob, like *OUT:
3989 6 50       29 if ( $next_tok =~ /^[_A-Za-z]/ ) {
3990 0         0 $expecting = TERM;
3991             }
3992             else {
3993             ## Could check for glob of a simple punctuation variable here
3994             ## by looking ahead one more character
3995             }
3996             }
3997              
3998 254 100       545 if ( $expecting == TERM ) {
3999 21         82 $self->scan_simple_identifier();
4000             }
4001             else {
4002              
4003 233 100       867 if ( $rtokens->[ $i + 1 ] eq '=' ) {
    100          
4004 2         5 $tok = '*=';
4005 2         4 $type = $tok;
4006 2         3 $i++;
4007             }
4008             elsif ( $rtokens->[ $i + 1 ] eq '*' ) {
4009 42         69 $tok = '**';
4010 42         1245 $type = $tok;
4011 42         62 $i++;
4012 42 100       123 if ( $rtokens->[ $i + 1 ] eq '=' ) {
4013 2         4 $tok = '**=';
4014 2         4 $type = $tok;
4015 2         3 $i++;
4016             }
4017             }
4018             else {
4019             ## not multiple characters
4020             }
4021             }
4022 254         399 return;
4023             } ## end sub do_STAR
4024              
4025             sub do_DOT {
4026              
4027 176     176 0 248 my $self = shift;
4028              
4029             # '.' = what kind of . ?
4030 176 100       398 if ( $expecting != OPERATOR ) {
4031 10         24 $self->scan_number();
4032             }
4033 176         246 return;
4034             } ## end sub do_DOT
4035              
4036             sub do_COLON {
4037              
4038 285     285 0 430 my $self = shift;
4039              
4040             # ':' = label, ternary, attribute, ?
4041              
4042             # if this is the first nonblank character, call it a label
4043             # since perl seems to just swallow it
4044 285 50 66     3066 if ( $input_line_number == 1 && $last_nonblank_i == -1 ) {
    100 66        
    100 66        
    100 66        
    100          
    100          
4045 0         0 $type = 'J';
4046             }
4047              
4048             # ATTRS: check for a ':' which introduces an attribute list
4049             # either after a 'sub' keyword or within a paren list
4050             # Added 'package' (can be 'class') for --use-feature=class (rt145706)
4051             elsif ( $statement_type =~ /^(sub|package)\b/ ) {
4052 22         35 $type = 'A';
4053 22         39 $self->[_in_attribute_list_] = 1;
4054             }
4055              
4056             # Within a signature, unless we are in a ternary. For example,
4057             # from 't/filter_example.t':
4058             # method foo4 ( $class: $bar ) { $class->bar($bar) }
4059             elsif ( $rparen_type->[$paren_depth] =~ /^sub\b/
4060             && !is_balanced_closing_container(QUESTION_COLON) )
4061             {
4062 1         2 $type = 'A';
4063 1         2 $self->[_in_attribute_list_] = 1;
4064             }
4065              
4066             # check for scalar attribute, such as
4067             # my $foo : shared = 1;
4068             elsif ($is_my_our_state{$statement_type}
4069             && $rcurrent_depth->[QUESTION_COLON] == 0 )
4070             {
4071 17         35 $type = 'A';
4072 17         48 $self->[_in_attribute_list_] = 1;
4073             }
4074              
4075             # Look for Switch::Plain syntax if an error would otherwise occur
4076             # here. Note that we do not need to check if the extended syntax
4077             # flag is set because otherwise an error would occur, and we would
4078             # then have to output a message telling the user to set the
4079             # extended syntax flag to avoid the error.
4080             # case 1: {
4081             # default: {
4082             # default:
4083             # Note that the line 'default:' will be parsed as a label elsewhere.
4084             elsif ( $is_case_default{$statement_type}
4085             && !is_balanced_closing_container(QUESTION_COLON) )
4086             {
4087             # mark it as a perltidy label type
4088 46         62 $type = 'J';
4089             }
4090              
4091             # mark colon as attribute if an error would occur otherwise; git #162
4092             elsif ( !$rcurrent_depth->[QUESTION_COLON] ) {
4093 6         9 $type = 'A';
4094 6         9 $self->[_in_attribute_list_] = 1;
4095              
4096             # and set a flag to skip error messages
4097 6         12 my $seqno = $self->[_rseqno_at_depth_]->[$total_depth];
4098 6 50       19 $self->[_rsaw_unknown_syntax_in_seqno_]->{$seqno} = 1 if ($seqno);
4099             }
4100              
4101             # otherwise, it should be part of a ?/: operator
4102             else {
4103 193         611 ( $type_sequence, $indent_flag ) =
4104             $self->decrease_nesting_depth( QUESTION_COLON,
4105             $rtoken_map->[$i_tok] );
4106 193 50       486 if ( $last_nonblank_token eq '?' ) {
4107 0         0 $self->warning("Syntax error near ? :\n");
4108             }
4109             }
4110 285         446 return;
4111             } ## end sub do_COLON
4112              
4113             sub do_PLUS_SIGN {
4114              
4115 240     240 0 344 my $self = shift;
4116              
4117             # '+' = what kind of plus?
4118 240 100       675 if ( $expecting == TERM ) {
    100          
4119 14         42 my $number = $self->scan_number_fast();
4120              
4121             # unary plus is safest assumption if not a number
4122 14 50       32 if ( !defined($number) ) { $type = 'p'; }
  14         23  
4123             }
4124             elsif ( $expecting == OPERATOR ) {
4125             }
4126             else {
4127 2 50 33     7 if ( $next_type eq 'w' || $next_type eq '{' ) { $type = 'p' }
  2         4  
4128             }
4129 240         344 return;
4130             } ## end sub do_PLUS_SIGN
4131              
4132             sub do_AT_SIGN {
4133              
4134 524     524 0 742 my $self = shift;
4135              
4136             # '@' = sigil for array?
4137 524 50       1173 $self->error_if_expecting_OPERATOR("Array")
4138             if ( $expecting == OPERATOR );
4139 524         1635 $self->scan_simple_identifier();
4140 524         721 return;
4141             } ## end sub do_AT_SIGN
4142              
4143             sub do_PERCENT_SIGN {
4144              
4145 218     218 0 340 my $self = shift;
4146              
4147             # '%' = hash or modulo?
4148             # first guess is hash if no following blank or paren
4149 218 50       531 if ( $expecting == UNKNOWN ) {
4150 0 0 0     0 if ( $next_type ne 'b' && $next_type ne '(' ) {
4151 0         0 $expecting = TERM;
4152             }
4153             }
4154 218 100       528 if ( $expecting == TERM ) {
4155 208         614 $self->scan_simple_identifier();
4156             }
4157 218         334 return;
4158             } ## end sub do_PERCENT_SIGN
4159              
4160             sub do_LEFT_SQUARE_BRACKET {
4161              
4162 814     814 0 1044 my $self = shift;
4163              
4164             # '['
4165 814         2646 $rsquare_bracket_type->[ ++$square_bracket_depth ] =
4166             $last_nonblank_token;
4167 814         2013 ( $type_sequence, $indent_flag ) =
4168             $self->increase_nesting_depth( SQUARE_BRACKET,
4169             $rtoken_map->[$i_tok] );
4170              
4171             # It may seem odd, but structural square brackets have
4172             # type '{' and '}'. This simplifies the indentation logic.
4173 814 100       1688 if ( !is_non_structural_brace() ) {
4174 374         532 $type = '{';
4175             }
4176 814         1361 $rsquare_bracket_structural_type->[$square_bracket_depth] = $type;
4177 814         1112 return;
4178             } ## end sub do_LEFT_SQUARE_BRACKET
4179              
4180             sub do_RIGHT_SQUARE_BRACKET {
4181              
4182 814     814 0 1066 my $self = shift;
4183              
4184             # ']'
4185 814         2224 ( $type_sequence, $indent_flag ) =
4186             $self->decrease_nesting_depth( SQUARE_BRACKET,
4187             $rtoken_map->[$i_tok] );
4188              
4189 814 100       1642 if ( $expecting == TERM ) {
4190             $self->error_if_expecting_TERM()
4191 91 50       394 if ( !$self->[_rsaw_unknown_syntax_in_seqno_]->{$type_sequence} );
4192             }
4193              
4194 814 100       1609 if ( $rsquare_bracket_structural_type->[$square_bracket_depth] eq '{' )
4195             {
4196 374         504 $type = '}';
4197             }
4198              
4199             # propagate type information for smartmatch operator. This is
4200             # necessary to enable us to know if an operator or term is expected
4201             # next.
4202 814 100       1660 if ( $rsquare_bracket_type->[$square_bracket_depth] eq '~~' ) {
4203 20         26 $tok = $rsquare_bracket_type->[$square_bracket_depth];
4204             }
4205              
4206 814 50       1608 if ( $square_bracket_depth > 0 ) { $square_bracket_depth--; }
  814         958  
4207 814         1011 return;
4208             } ## end sub do_RIGHT_SQUARE_BRACKET
4209              
4210             sub do_MINUS_SIGN {
4211              
4212 491     491 0 697 my $self = shift;
4213              
4214             # '-' = what kind of minus?
4215 491 100 100     2303 if ( ( $expecting != OPERATOR )
    100          
    100          
4216             && $is_file_test_operator{$next_tok} )
4217             {
4218 12         76 my ( $next_nonblank_token, $i_next_uu ) =
4219             $self->find_next_nonblank_token( $i + 1, $rtokens,
4220             $max_token_index );
4221              
4222             # check for a quoted word like "-w=>xx";
4223             # it is sufficient to just check for a following '='
4224 12 50       41 if ( $next_nonblank_token eq '=' ) {
4225 0         0 $type = 'm';
4226             }
4227             else {
4228 12         22 $i++;
4229 12         22 $tok .= $next_tok;
4230 12         25 $type = 'F';
4231             }
4232             }
4233             elsif ( $expecting == TERM ) {
4234 378         915 my $number = $self->scan_number_fast();
4235              
4236             # maybe part of bareword token? unary is safest
4237 378 100       835 if ( !defined($number) ) { $type = 'm'; }
  288         394  
4238              
4239             }
4240             elsif ( $expecting == OPERATOR ) {
4241             }
4242             else {
4243 4 50       12 if ( $next_type eq 'w' ) {
4244 4         9 $type = 'm';
4245             }
4246             }
4247 491         650 return;
4248             } ## end sub do_MINUS_SIGN
4249              
4250             sub do_CARAT_SIGN {
4251              
4252 12     12 0 18 my $self = shift;
4253              
4254             # '^'
4255             # check for special variables like ${^WARNING_BITS}
4256 12 100       23 if ( $expecting == TERM ) {
4257              
4258 5 50 33     44 if ( $last_nonblank_token eq '{'
      33        
4259             && ( $next_tok !~ /^\d/ )
4260             && ( $next_tok =~ /^\w/ ) )
4261             {
4262              
4263 5 100       14 if ( $next_tok eq 'W' ) {
4264 1         3 $self->[_saw_perl_dash_w_] = 1;
4265             }
4266 5         9 $tok = $tok . $next_tok;
4267 5         7 $i = $i + 1;
4268 5         7 $type = 'w';
4269              
4270             # Optional coding to try to catch syntax errors. This can
4271             # be removed if it ever causes incorrect warning messages.
4272             # The '{^' should be preceded by either by a type or '$#'
4273             # Examples:
4274             # $#{^CAPTURE} ok
4275             # *${^LAST_FH}{NAME} ok
4276             # @{^HOWDY} ok
4277             # $hash{^HOWDY} error
4278              
4279             # Note that a type sigil '$' may be tokenized as 'Z'
4280             # after something like 'print', so allow type 'Z'
4281 5 0 33     16 if ( $last_last_nonblank_type ne 't'
      33        
4282             && $last_last_nonblank_type ne 'Z'
4283             && $last_last_nonblank_token ne '$#' )
4284             {
4285 0         0 $self->warning("Possible syntax error near '{^'\n");
4286             }
4287             }
4288             }
4289 12         16 return;
4290             } ## end sub do_CARAT_SIGN
4291              
4292             sub do_DOUBLE_COLON {
4293              
4294 9     9 0 15 my $self = shift;
4295              
4296             # '::' = probably a sub call
4297 9         21 $self->scan_bare_identifier();
4298 9         13 return;
4299             } ## end sub do_DOUBLE_COLON
4300              
4301             sub do_LEFT_SHIFT {
4302              
4303 19     19 0 34 my $self = shift;
4304              
4305             # '<<' = maybe a here-doc?
4306 19 50       55 if ( $expecting != OPERATOR ) {
4307             my (
4308 19         75 $found_target,
4309             $here_doc_target,
4310             $here_quote_character,
4311             $i_return,
4312             $saw_error,
4313              
4314             ) = $self->find_here_doc(
4315              
4316             $expecting,
4317             $i,
4318             $rtokens,
4319             $rtoken_type,
4320             $rtoken_map,
4321             $max_token_index,
4322             );
4323 19         32 $i = $i_return;
4324              
4325 19 50       39 if ($found_target) {
    0          
4326 19         29 push @{$rhere_target_list},
  19         51  
4327             [ $here_doc_target, $here_quote_character ];
4328 19         31 $type = 'h';
4329 19 50       116 if ( length($here_doc_target) > 80 ) {
    50          
    100          
4330 0         0 my $truncated = substr( $here_doc_target, 0, 80 );
4331 0         0 $self->complain("Long here-target: '$truncated' ...\n");
4332             }
4333             elsif ( !$here_doc_target ) {
4334 0 0       0 $self->warning(
4335             'Use of bare << to mean <<"" is deprecated' . "\n" )
4336             if ( !$here_quote_character );
4337             }
4338             elsif ( $here_doc_target !~ /^[A-Z_]\w+$/ ) {
4339 2         9 $self->complain(
4340             "Unconventional here-target: '$here_doc_target'\n");
4341             }
4342             else {
4343             ## nothing to complain about
4344             }
4345             }
4346             elsif ( $expecting == TERM ) {
4347 0 0       0 if ( !$saw_error ) {
4348              
4349             # shouldn't happen..arriving here implies an error in
4350             # the logic in sub 'find_here_doc'
4351 0         0 if (DEVEL_MODE) {
4352             Fault(<<EOM);
4353             Program bug; didn't find here doc target
4354             EOM
4355             }
4356             $self->warning(
4357 0         0 "Possible program error: didn't find here doc target\n"
4358             );
4359 0         0 $self->report_definite_bug();
4360             }
4361             }
4362              
4363             # target not found, expecting == UNKNOWN
4364             else {
4365             ## assume it is a shift
4366             }
4367             }
4368             else {
4369             ## '<<' is shift
4370             }
4371 19         28 return;
4372             } ## end sub do_LEFT_SHIFT
4373              
4374             sub do_NEW_HERE_DOC {
4375              
4376             # '<<~' = a here-doc, new type added in v26
4377              
4378 14     14 0 19 my $self = shift;
4379              
4380             return
4381 14 50       37 if ( $i >= $max_token_index ); # here-doc not possible if end of line
4382 14 50       30 if ( $expecting != OPERATOR ) {
4383             my (
4384 14         49 $found_target,
4385             $here_doc_target,
4386             $here_quote_character,
4387             $i_return,
4388             $saw_error,
4389              
4390             ) = $self->find_here_doc(
4391              
4392             $expecting,
4393             $i,
4394             $rtokens,
4395             $rtoken_type,
4396             $rtoken_map,
4397             $max_token_index,
4398             );
4399 14         24 $i = $i_return;
4400              
4401 14 50       25 if ($found_target) {
    0          
4402              
4403 14 50       80 if ( length($here_doc_target) > 80 ) {
    50          
4404 0         0 my $truncated = substr( $here_doc_target, 0, 80 );
4405 0         0 $self->complain("Long here-target: '$truncated' ...\n");
4406             }
4407             elsif ( $here_doc_target !~ /^[A-Z_]\w+$/ ) {
4408 0         0 $self->complain(
4409             "Unconventional here-target: '$here_doc_target'\n");
4410             }
4411             else {
4412             ## nothing to complain about
4413             }
4414              
4415             # Note that we put a leading space on the here quote
4416             # character indicate that it may be preceded by spaces
4417 14         27 $here_quote_character = SPACE . $here_quote_character;
4418 14         19 push @{$rhere_target_list},
  14         42  
4419             [ $here_doc_target, $here_quote_character ];
4420 14         25 $type = 'h';
4421             }
4422              
4423             # target not found ..
4424             elsif ( $expecting == TERM ) {
4425 0 0       0 if ( !$saw_error ) {
4426              
4427             # shouldn't happen..arriving here implies an error in
4428             # the logic in sub 'find_here_doc'
4429 0         0 if (DEVEL_MODE) {
4430             Fault(<<EOM);
4431             Program bug; didn't find here doc target
4432             EOM
4433             }
4434             $self->warning(
4435 0         0 "Possible program error: didn't find here doc target\n"
4436             );
4437 0         0 $self->report_definite_bug();
4438             }
4439             }
4440              
4441             # Target not found, expecting==UNKNOWN
4442             else {
4443 0         0 $self->warning("didn't find here doc target after '<<~'\n");
4444             }
4445             }
4446             else {
4447 0         0 $self->error_if_expecting_OPERATOR();
4448             }
4449 14         23 return;
4450             } ## end sub do_NEW_HERE_DOC
4451              
4452             sub do_POINTER {
4453              
4454             # '->'
4455 1197     1197 0 1564 return;
4456             }
4457              
4458             sub do_PLUS_PLUS {
4459              
4460 50     50 0 90 my $self = shift;
4461              
4462             # '++'
4463             # type = 'pp' for pre-increment, '++' for post-increment
4464 50 100       196 if ( $expecting == OPERATOR ) { $type = '++' }
  41 100       92  
4465 7         14 elsif ( $expecting == TERM ) { $type = 'pp' }
4466              
4467             # handle ( $expecting == UNKNOWN )
4468             else {
4469              
4470             # look ahead ..
4471 2         7 my ( $next_nonblank_token, $i_next ) =
4472             $self->find_next_nonblank_token( $i, $rtokens, $max_token_index );
4473              
4474             # Fix for c042: look past a side comment
4475 2 50       6 if ( $next_nonblank_token eq '#' ) {
4476 0         0 ( $next_nonblank_token, $i_next ) =
4477             $self->find_next_nonblank_token( $max_token_index,
4478             $rtokens, $max_token_index );
4479             }
4480              
4481 2 50       8 if ( $next_nonblank_token eq '$' ) { $type = 'pp' }
  0         0  
4482             }
4483 50         76 return;
4484             } ## end sub do_PLUS_PLUS
4485              
4486             sub do_FAT_COMMA {
4487              
4488 1115     1115 0 1398 my $self = shift;
4489              
4490             # '=>'
4491 1115 50       2201 if ( $last_nonblank_type eq $tok ) {
4492 0         0 $self->complain("Repeated '=>'s \n");
4493             }
4494              
4495             # patch for operator_expected: note if we are in the list (use.t)
4496             # TODO: make version numbers a new token type
4497 1115 100       2041 if ( $statement_type eq 'use' ) { $statement_type = '_use' }
  18         28  
4498 1115         1426 return;
4499             } ## end sub do_FAT_COMMA
4500              
4501             sub do_MINUS_MINUS {
4502              
4503 2     2 0 5 my $self = shift;
4504              
4505             # '--'
4506             # type = 'mm' for pre-decrement, '--' for post-decrement
4507              
4508 2 50       7 if ( $expecting == OPERATOR ) { $type = '--' }
  0 50       0  
4509 2         4 elsif ( $expecting == TERM ) { $type = 'mm' }
4510              
4511             # handle ( $expecting == UNKNOWN )
4512             else {
4513              
4514             # look ahead ..
4515 0         0 my ( $next_nonblank_token, $i_next ) =
4516             $self->find_next_nonblank_token( $i, $rtokens, $max_token_index );
4517              
4518             # Fix for c042: look past a side comment
4519 0 0       0 if ( $next_nonblank_token eq '#' ) {
4520 0         0 ( $next_nonblank_token, $i_next ) =
4521             $self->find_next_nonblank_token( $max_token_index,
4522             $rtokens, $max_token_index );
4523             }
4524              
4525 0 0       0 if ( $next_nonblank_token eq '$' ) { $type = 'mm' }
  0         0  
4526             }
4527              
4528 2         2 return;
4529             } ## end sub do_MINUS_MINUS
4530              
4531             sub do_DIGITS {
4532              
4533 2514     2514 0 3039 my $self = shift;
4534              
4535             # 'd' = string of digits
4536 2514 50       4030 $self->error_if_expecting_OPERATOR("Number")
4537             if ( $expecting == OPERATOR );
4538              
4539 2514         4992 my $number = $self->scan_number_fast();
4540 2514 50       4471 if ( !defined($number) ) {
4541              
4542             # shouldn't happen - we should always get a number
4543 0         0 if (DEVEL_MODE) {
4544             Fault(<<EOM);
4545             non-number beginning with digit--program bug
4546             EOM
4547             }
4548             $self->warning(
4549 0         0 "Unexpected error condition: non-number beginning with digit\n"
4550             );
4551 0         0 $self->report_definite_bug();
4552             }
4553 2514         3138 return;
4554             } ## end sub do_DIGITS
4555              
4556             sub do_ATTRIBUTE_LIST {
4557              
4558 45     45 0 121 my ( $self, $next_nonblank_token ) = @_;
4559              
4560             # Called at a bareword encountered while in an attribute list
4561             # returns 'is_attribute':
4562             # true if attribute found
4563             # false if an attribute (continue parsing bareword)
4564              
4565             # treat bare word followed by open paren like qw(
4566 45 100       108 if ( $next_nonblank_token eq '(' ) {
4567              
4568             # For something like:
4569             # : prototype($$)
4570             # we should let do_scan_sub see it so that it can see
4571             # the prototype. All other attributes get parsed as a
4572             # quoted string.
4573 20 100       52 if ( $tok eq 'prototype' ) {
4574 2         4 $id_scan_state = 'prototype';
4575              
4576             # start just after the word 'prototype'
4577 2         5 my $i_beg = $i + 1;
4578 2         20 ( $i, $tok, $type, $id_scan_state ) = $self->do_scan_sub(
4579             {
4580             input_line => $input_line,
4581             i => $i,
4582             i_beg => $i_beg,
4583             tok => $tok,
4584             type => $type,
4585             rtokens => $rtokens,
4586             rtoken_map => $rtoken_map,
4587             id_scan_state => $id_scan_state,
4588             max_token_index => $max_token_index,
4589             }
4590             );
4591              
4592             # If successful, mark as type 'q' to be consistent
4593             # with other attributes. Type 'w' would also work.
4594 2 50       11 if ( $i > $i_beg ) {
4595 2         4 $type = 'q';
4596 2         5 return 1;
4597             }
4598              
4599             # If not successful, continue and parse as a quote.
4600             }
4601              
4602             # All other attribute lists must be parsed as quotes
4603             # (see 'signatures.t' for good examples)
4604 18         37 $in_quote = $quote_items{'q'};
4605 18         38 $allowed_quote_modifiers = $quote_modifiers{'q'};
4606 18         28 $quote_starting_tok = 'q';
4607 18         26 $type = 'q';
4608 18         27 $quote_type = 'q';
4609 18         24 $quote_here_target_2 = undef;
4610 18         34 return 1;
4611             }
4612              
4613             # handle bareword not followed by open paren
4614             else {
4615 25         41 $type = 'w';
4616 25         50 return 1;
4617             }
4618              
4619             # attribute not found
4620 0         0 return;
4621             } ## end sub do_ATTRIBUTE_LIST
4622              
4623             sub do_X_OPERATOR {
4624              
4625 17     17 0 28 my $self = shift;
4626              
4627             # We are at a pretoken starting with 'x' where an operator is expected
4628              
4629 17 100       51 if ( $tok eq 'x' ) {
4630 15 50       49 if ( $rtokens->[ $i + 1 ] eq '=' ) { # x=
4631 0         0 $tok = 'x=';
4632 0         0 $type = $tok;
4633 0         0 $i++;
4634             }
4635             else {
4636 15         28 $type = 'x';
4637             }
4638             }
4639             else {
4640              
4641             # Split a pretoken like 'x10' into 'x' and '10'.
4642             # Note: In previous versions of perltidy it was marked
4643             # as a number, $type = 'n', and fixed downstream by the
4644             # Formatter.
4645 2         3 $type = 'n';
4646 2 50       14 if ( $self->split_pretoken(1) ) {
4647 2         2 $type = 'x';
4648 2         3 $tok = 'x';
4649             }
4650             }
4651 17         29 return;
4652             } ## end sub do_X_OPERATOR
4653              
4654             sub do_USE_CONSTANT {
4655              
4656 16     16 0 28 my $self = shift;
4657              
4658             # We just saw 'use constant' and must look ahead
4659              
4660 16         53 $self->scan_bare_identifier();
4661 16         60 my ( $next_nonblank_tok2, $i_next2_uu ) =
4662             $self->find_next_nonblank_token( $i, $rtokens, $max_token_index );
4663              
4664 16 50       46 if ($next_nonblank_tok2) {
4665              
4666 16 100       43 if ( $is_keyword{$next_nonblank_tok2} ) {
4667              
4668             # Assume qw is used as a quote and okay, as in:
4669             # use constant qw{ DEBUG 0 };
4670             # Not worth trying to parse for just a warning
4671              
4672             # NOTE: This warning is deactivated because recent
4673             # versions of perl do not complain here, but
4674             # the coding is retained for reference.
4675 1         2 if ( 0 && $next_nonblank_tok2 ne 'qw' ) {
4676             $self->warning(
4677             "Attempting to define constant '$next_nonblank_tok2' which is a perl keyword\n"
4678             );
4679             }
4680             }
4681              
4682             else {
4683 15         41 $ris_constant->{$current_package}->{$next_nonblank_tok2} = 1;
4684             }
4685             }
4686 16         27 return;
4687             } ## end sub do_USE_CONSTANT
4688              
4689             sub do_KEYWORD {
4690              
4691 3114     3114 0 4099 my $self = shift;
4692              
4693             # found a keyword - set any associated flags
4694 3114         4163 $type = 'k';
4695              
4696             # Since for and foreach may not be followed immediately
4697             # by an opening paren, we have to remember which keyword
4698             # is associated with the next '('
4699             # Previously, before update c230 : if ( $is_for_foreach{$tok} ) {
4700             ##(if elsif unless while until for foreach switch case given when catch)
4701 3114 100       6281 if ( $is_blocktype_with_paren{$tok} ) {
4702 501 100       1359 if ( new_statement_ok() ) {
4703 362         612 $want_paren = $tok;
4704             }
4705             }
4706              
4707             # Catch some unexpected keyword errors; c517.
4708             # Note that we only check keywords for OPERATOR expected, not TERM.
4709             # This is because a large number of keywords which normally expect
4710             # a TERM will also take an OPERATOR.
4711 3114 50 66     6304 if ( $expecting == OPERATOR && $is_TERM_keyword{$tok} ) {
4712 0         0 $self->error_if_expecting_OPERATOR();
4713             }
4714              
4715             # recognize 'use' statements, which are special
4716 3114 100 100     16630 if ( $is_use_require{$tok} ) {
    100 100        
    100          
    100          
    100          
    100          
4717 178         263 $statement_type = $tok;
4718             }
4719              
4720             # remember my and our to check for trailing ": shared"
4721             elsif ( $is_my_our_state{$tok} ) {
4722 763         1180 $statement_type = $tok;
4723             }
4724              
4725             # Check for unexpected 'elsif'
4726             elsif ( $tok eq 'elsif' ) {
4727 35 0 0     100 if (
      33        
4728              
4729             !$is_if_elsif_unless{$last_nonblank_block_type}
4730              
4731             # Allow isolated blocks of any kind during editing
4732             # by checking for a last noblank token of ';' and no
4733             # sequence numbers having been issued (c272). The check
4734             # on sequence number is not perfect but good enough.
4735             && !(
4736             $last_nonblank_token eq ';'
4737             && $next_sequence_number == SEQ_ROOT + 1
4738             )
4739              
4740             )
4741             {
4742             ## prevent formatting and avoid instability (b1553)
4743 0         0 $self->warning_do_not_format(
4744             "expecting '$tok' to follow one of 'if|elsif|unless'\n");
4745             }
4746             }
4747              
4748             # Check for unexpected 'else'
4749             elsif ( $tok eq 'else' ) {
4750              
4751             # patched for SWITCH/CASE
4752 53 0 66     201 if (
      0        
      33        
4753              
4754             !$is_if_elsif_unless_case_when{$last_nonblank_block_type}
4755              
4756             # patch to avoid an unwanted error message for
4757             # the case of a parenless 'case' (RT 105484):
4758             # switch ( 1 ) { case x { 2 } else { } }
4759             && !$is_if_elsif_unless_case_when{$statement_type}
4760              
4761             # Allow isolated blocks of any kind during editing (c272)
4762             && !(
4763             $last_nonblank_token eq ';'
4764             && $next_sequence_number == SEQ_ROOT + 1
4765             )
4766              
4767             )
4768             {
4769             ## prevent formatting and avoid instability (b1553)
4770 0         0 $self->warning_do_not_format(
4771             "expecting '$tok' to follow one of 'if|elsif|unless|case|when'\n"
4772             );
4773             }
4774             }
4775              
4776             # patch for SWITCH/CASE if 'case' and 'when are
4777             # treated as keywords. Also 'default' for Switch::Plain
4778             elsif ($tok eq 'when'
4779             || $tok eq 'case'
4780             || $tok eq 'default' )
4781             {
4782 70         112 $statement_type = $tok; # next '{' is block
4783             }
4784              
4785             # feature 'err' was removed in Perl 5.10. So mark this as
4786             # a bareword unless an operator is expected (see c158).
4787             elsif ( $tok eq 'err' ) {
4788 1 50       4 if ( $expecting != OPERATOR ) { $type = 'w' }
  1         1  
4789             }
4790             else {
4791             ## no special treatment needed
4792             }
4793              
4794 3114         4666 return;
4795             } ## end sub do_KEYWORD
4796              
4797             sub do_QUOTE_OPERATOR {
4798              
4799 234     234 0 361 my $self = shift;
4800              
4801             # We have arrived at a quote operator: q, qq, qw, qx, qr, s, y, tr, m
4802              
4803 234 50       648 if ( $expecting == OPERATOR ) {
4804              
4805             # Be careful not to call an error for a qw quote
4806             # where a parenthesized list is allowed. For example,
4807             # it could also be a for/foreach construct such as
4808             #
4809             # foreach my $key qw\Uno Due Tres Quadro\ {
4810             # print "Set $key\n";
4811             # }
4812             #
4813              
4814             # Or it could be a function call.
4815             # NOTE: Braces in something like &{ xxx } are not
4816             # marked as a block, we might have a method call.
4817             # &method(...), $method->(..), &{method}(...),
4818             # $ref[2](list) is ok & short for $ref[2]->(list)
4819             #
4820             # See notes in 'sub code_block_type' and
4821             # 'sub is_non_structural_brace'
4822              
4823             my $paren_list_possible = $tok eq 'qw'
4824             && ( $last_nonblank_token =~ /^([\]\}\&]|\-\>)/
4825 0   0     0 || $is_for_foreach{$want_paren} );
4826              
4827 0 0       0 if ( !$paren_list_possible ) {
4828 0         0 $self->error_if_expecting_OPERATOR();
4829             }
4830             }
4831 234         479 $in_quote = $quote_items{$tok};
4832 234         404 $allowed_quote_modifiers = $quote_modifiers{$tok};
4833 234         361 $quote_starting_tok = $tok;
4834 234         335 $quote_here_target_2 = undef;
4835              
4836             # All quote types are 'Q' except possibly qw quotes.
4837             # qw quotes are special in that they may generally be trimmed
4838             # of leading and trailing whitespace. So they are given a
4839             # separate type, 'q', unless requested otherwise.
4840 234 100 66     888 $type =
4841             ( $tok eq 'qw' && $rOpts_trim_qw )
4842             ? 'q'
4843             : 'Q';
4844 234         358 $quote_type = $type;
4845 234         343 return;
4846             } ## end sub do_QUOTE_OPERATOR
4847              
4848             sub do_UNKNOWN_BAREWORD {
4849              
4850 1034     1034 0 1748 my ( $self, $next_nonblank_token ) = @_;
4851              
4852             # We have encountered a bareword which needs more work to classify
4853              
4854 1034         2673 $self->scan_bare_identifier();
4855              
4856 1034 100 100     2695 if ( $statement_type eq 'use'
4857             && $last_nonblank_token eq 'use' )
4858             {
4859 111         332 $rsaw_use_module->{$current_package}->{$tok} = 1;
4860             }
4861              
4862 1034 100       1993 if ( $type eq 'w' ) {
4863              
4864 1009 100       1931 if ( $expecting == OPERATOR ) {
4865              
4866             # Patch to avoid error message for RPerl overloaded
4867             # operator functions: use overload
4868             # '+' => \&sse_add,
4869             # '-' => \&sse_sub,
4870             # '*' => \&sse_mul,
4871             # '/' => \&sse_div;
4872             # TODO: this could eventually be generalized
4873 2 50 33     18 if ( $rsaw_use_module->{$current_package}->{'RPerl'}
    50 33        
    0          
    0          
4874             && $tok =~ /^sse_(mul|div|add|sub)$/ )
4875             {
4876              
4877             }
4878              
4879             # patch for Syntax::Operator::In, git #162
4880             elsif ( $tok eq 'in' && $next_nonblank_token eq ':' ) {
4881              
4882             }
4883              
4884             # Fix part 1 for git #63 in which a comment falls
4885             # between an -> and the following word. An
4886             # alternate fix would be to change operator_expected
4887             # to return an UNKNOWN for this type.
4888             elsif ( $last_nonblank_type eq '->' ) {
4889              
4890             }
4891              
4892             # don't complain about possible indirect object
4893             # notation.
4894             # For example:
4895             # package main;
4896             # sub new($) { ... }
4897             # $b = new A::; # calls A::new
4898             # $c = new A; # same thing but suspicious
4899             # This will call A::new but we have a 'new' in
4900             # main:: which looks like a constant.
4901             #
4902             elsif ( $last_nonblank_type eq 'C' ) {
4903 0 0       0 if ( $tok !~ /::$/ ) {
4904 0         0 $self->complain(<<EOM);
4905             Expecting operator after '$last_nonblank_token' but found bare word '$tok'
4906             Maybe indirect object notation?
4907             EOM
4908             }
4909             }
4910             else {
4911 0         0 $self->error_if_expecting_OPERATOR("bareword");
4912             }
4913             }
4914              
4915             # mark bare words immediately followed by a paren as
4916             # functions
4917 1009         1632 $next_tok = $rtokens->[ $i + 1 ];
4918 1009 100       1867 if ( $next_tok eq '(' ) {
4919              
4920             # Patch for issue c151, where we are processing a snippet and
4921             # have not seen that SPACE is a constant. In this case 'x' is
4922             # probably an operator. The only disadvantage with an incorrect
4923             # guess is that the space after it may be incorrect. For example
4924             # $str .= SPACE x ( 16 - length($str) ); See also b1410.
4925 298 50 33     1037 if ( $tok eq 'x' && $last_nonblank_type eq 'w' ) { $type = 'x' }
  0 50       0  
4926              
4927             # Fix part 2 for git #63. Leave type as 'w' to keep
4928             # the type the same as if the -> were not separated
4929 298         485 elsif ( $last_nonblank_type ne '->' ) { $type = 'U' }
4930              
4931             # not a special case
4932             else { }
4933              
4934             }
4935              
4936             # underscore after file test operator is file handle
4937 1009 50 66     2263 if ( $tok eq '_' && $last_nonblank_type eq 'F' ) {
4938 0         0 $type = 'Z';
4939             }
4940              
4941             # patch for SWITCH/CASE if 'case' and 'when are
4942             # not treated as keywords:
4943 1009 50 33     3794 if (
      33        
      33        
4944             ( $tok eq 'case' && $rbrace_type->[$brace_depth] eq 'switch' )
4945             || ( $tok eq 'when'
4946             && $rbrace_type->[$brace_depth] eq 'given' )
4947             )
4948             {
4949 0         0 $statement_type = $tok; # next '{' is block
4950 0         0 $type = 'k'; # for keyword syntax coloring
4951             }
4952 1009 100       1910 if ( $next_nonblank_token eq '(' ) {
4953              
4954             # patch for SWITCH/CASE if switch and given not keywords
4955             # Switch is not a perl 5 keyword, but we will gamble
4956             # and mark switch followed by paren as a keyword. This
4957             # is only necessary to get html syntax coloring nice,
4958             # and does not commit this as being a switch/case.
4959 263 50 33     1412 if ( $tok eq 'switch' || $tok eq 'given' ) {
    50 33        
4960 0         0 $type = 'k'; # for keyword syntax coloring
4961             }
4962              
4963             # mark 'x' as operator for something like this (see b1410)
4964             # my $line = join( LD_X, map { LD_H x ( $_ + 2 ) } @$widths );
4965             elsif ( $tok eq 'x' && $last_nonblank_type eq 'w' ) {
4966 0         0 $type = 'x';
4967             }
4968             else {
4969             ## not a special case
4970             }
4971             }
4972             }
4973 1034         1512 return;
4974             } ## end sub do_UNKNOWN_BAREWORD
4975              
4976             sub sub_attribute_ok_here {
4977              
4978 37     37 0 101 my ( $self, $tok_kw, $next_nonblank_token, $i_next ) = @_;
4979              
4980             # Decide if a ':' can introduce an attribute. For example,
4981             # something like 'sub :'
4982              
4983             # Given:
4984             # $tok_kw = a bareword token
4985             # $next_nonblank_token = a following ':' being examined
4986             # $i_next = the index of the following ':'
4987              
4988             # We will decide based on if the colon is followed by a bareword
4989             # which is not a keyword. Changed inext+1 to inext to fixed case
4990             # b1190.
4991 37         58 my $sub_attribute_ok_here;
4992 37 50 66     148 if ( $is_sub{$tok_kw}
      66        
4993             && $expecting != OPERATOR
4994             && $next_nonblank_token eq ':' )
4995             {
4996 3         12 my ( $nn_nonblank_token, $i_nn_uu ) =
4997             $self->find_next_nonblank_token( $i_next, $rtokens,
4998             $max_token_index );
4999             $sub_attribute_ok_here =
5000             $nn_nonblank_token =~ /^\w/
5001             && $nn_nonblank_token !~ /^\d/
5002 3   66     22 && !$is_keyword{$nn_nonblank_token};
5003             }
5004 37         190 return $sub_attribute_ok_here;
5005             } ## end sub sub_attribute_ok_here
5006              
5007 44     44   351 use constant DEBUG_BAREWORD => 0;
  44         80  
  44         16086  
5008              
5009             sub saw_bareword_function {
5010 961     961 0 1643 my ( $self, $bareword ) = @_;
5011             $self->[_rbareword_info_]->{$current_package}->{$bareword}
5012 961         3401 ->{function_count}++;
5013 961         1458 return;
5014             } ## end sub saw_bareword_function
5015              
5016             sub saw_bareword_constant {
5017 180     180 0 362 my ( $self, $bareword ) = @_;
5018             $self->[_rbareword_info_]->{$current_package}->{$bareword}
5019 180         587 ->{constant_count}++;
5020 180         324 return;
5021             } ## end sub saw_bareword_constant
5022              
5023             sub get_bareword_counts {
5024 0     0 0 0 my ( $self, $bareword ) = @_;
5025              
5026             # Given:
5027             # $bareword = a bareword
5028             # Return:
5029             # $function_count = number of times seen as function taking >0 args
5030             # $constant_count = number of times seen as function taking 0 args
5031             # Note:
5032             # $function_count > 0 implies that a TERM should come next
5033             # $constant_count > 0 implies that an OPERATOR **may** come next,
5034             # but this can be incorrect if $bareword can take 0 or more args.
5035             # This is used to help guess tokenization around unknown barewords.
5036 0         0 my $function_count;
5037             my $constant_count;
5038 0         0 my $rbareword_info_tok = $self->[_rbareword_info_]->{$current_package};
5039 0 0       0 if ($rbareword_info_tok) {
5040 0         0 $rbareword_info_tok = $rbareword_info_tok->{$bareword};
5041 0 0       0 if ($rbareword_info_tok) {
5042 0         0 $function_count = $rbareword_info_tok->{function_count};
5043 0         0 $constant_count = $rbareword_info_tok->{constant_count};
5044              
5045             # a positive function count overrides a constant count
5046 0 0       0 if ($function_count) { $constant_count = 0 }
  0         0  
5047             }
5048             }
5049 0 0       0 if ( !defined($function_count) ) { $function_count = 0 }
  0         0  
5050 0 0       0 if ( !defined($constant_count) ) { $constant_count = 0 }
  0         0  
5051 0         0 return ( $function_count, $constant_count );
5052             } ## end sub get_bareword_counts
5053              
5054             # hashes used to help determine a bareword type
5055             my %is_wiUC;
5056             my %is_function_follower;
5057             my %is_constant_follower;
5058             my %is_use_require_no;
5059              
5060             BEGIN {
5061 44     44   234 my @qz = qw( w i U C );
5062 44         285 $is_wiUC{$_} = 1 for @qz;
5063              
5064 44         109 @qz = qw( use require no );
5065 44         170 $is_use_require_no{$_} = 1 for @qz;
5066              
5067             # These pre-token types after a bareword imply that it
5068             # is not a constant, except when '(' is followed by ')'.
5069 44         147 @qz = qw# ( [ { $ @ " ' m #;
5070 44         294 $is_function_follower{$_} = 1 for @qz;
5071              
5072             # These pre-token types after a bareword imply that it
5073             # MIGHT be a constant, but it also might be a function taking
5074             # 0 or more call args.
5075 44         102 @qz = qw# ; ) ] } if unless #;
5076 44         91 push @qz, COMMA;
5077 44         112739 $is_constant_follower{$_} = 1 for @qz;
5078             }
5079              
5080             sub do_BAREWORD {
5081              
5082 6708     6708 0 9445 my ($self) = @_;
5083              
5084             # handle a bareword token:
5085             # returns
5086             # true if this token ends the current line
5087             # false otherwise
5088              
5089 6708         7186 my $next_nonblank_token;
5090 6708         7684 my $i_next = $i + 1;
5091 6708 100 100     18864 if ( $i_next <= $max_token_index && $rtoken_type->[$i_next] eq 'b' ) {
5092 4081         5252 $i_next++;
5093             }
5094 6708 100       9753 if ( $i_next <= $max_token_index ) {
5095 6624         9306 $next_nonblank_token = $rtokens->[$i_next];
5096             }
5097             else {
5098 84         335 ( $next_nonblank_token, $i_next ) =
5099             $self->find_next_nonblank_token( $i, $rtokens, $max_token_index );
5100             }
5101              
5102             # Fix for git #182: If --use-feature=class is set, then
5103             # a colon between words 'ADJUST' and 'params', and on the same line,
5104             # does not form the label 'ADJUST:'. It will get marked as type 'A'.
5105 6708         7262 my $is_not_label;
5106 6708 100 66     10656 if ( $tok eq 'ADJUST'
      66        
      66        
5107             && $is_code_block_token{$tok}
5108             && $rtokens->[$i_next] eq ':'
5109             && $i_next < $max_token_index )
5110             {
5111 2 50       6 my $i_next2 =
5112             $rtoken_type->[ $i_next + 1 ] eq 'b' ? $i_next + 2 : $i_next + 1;
5113 2   33     12 $is_not_label =
5114             ( $i_next2 <= $max_token_index
5115             && $rtoken_type->[$i_next2] eq 'w'
5116             && $rtokens->[$i_next2] eq 'params' );
5117             }
5118              
5119             # a bare word immediately followed by :: is not a keyword;
5120             # use $tok_kw when testing for keywords to avoid a mistake
5121 6708         8054 my $tok_kw = $tok;
5122 6708 100 100     14164 if ( $rtokens->[ $i + 1 ] eq ':'
5123             && $rtokens->[ $i + 2 ] eq ':' )
5124             {
5125 272         476 $tok_kw .= '::';
5126             }
5127              
5128 6708 100       12091 if ( $self->[_in_attribute_list_] ) {
5129 45         131 my $is_attribute = $self->do_ATTRIBUTE_LIST($next_nonblank_token);
5130 45 50       134 return if ($is_attribute);
5131             }
5132              
5133             #-----------------------------------------
5134             # Preliminary check for a lexical sub name
5135             #-----------------------------------------
5136 6663         7620 my $is_lexical_sub_type;
5137              
5138             # Has this name been seen as a lexical sub?
5139 6663 50       12551 if ( my $rseqno_hash = $ris_lexical_sub->{$tok_kw} ) {
5140              
5141             # Look back up the stack to see if it is still in scope.
5142             # Use the deepest we find if there are multiple versions.
5143 0         0 my @seqno_tested;
5144 0         0 my $cd_aa = $rcurrent_depth->[BRACE];
5145 0         0 foreach my $cd ( reverse( 0 .. $cd_aa ) ) {
5146 0 0       0 my $p_seqno =
5147             $cd
5148             ? $rcurrent_sequence_number->[BRACE]->[$cd]
5149             : SEQ_ROOT;
5150              
5151 0         0 push @seqno_tested, $p_seqno;
5152              
5153             # Lexical subs use their containing sequence number as package
5154 0 0       0 if ( my $seqno_brace = $rseqno_hash->{$p_seqno} ) {
5155              
5156             # This sub is in scope .. lookup its type
5157             $is_lexical_sub_type =
5158             $ris_constant->{$p_seqno}->{$tok_kw} ? 'C'
5159             : $ris_block_function->{$p_seqno}->{$tok_kw} ? 'G'
5160             : $ris_block_list_function->{$p_seqno}->{$tok_kw} ? 'G'
5161 0 0       0 : $ris_user_function->{$p_seqno}->{$tok_kw} ? 'U'
    0          
    0          
    0          
5162             : 'U';
5163              
5164             # But lexical subs do not apply within their defining code
5165 0         0 foreach (@seqno_tested) {
5166 0 0       0 next if ( $_ != $seqno_brace );
5167 0         0 $is_lexical_sub_type = undef;
5168 0         0 last;
5169             }
5170              
5171 0         0 last;
5172             }
5173             }
5174             }
5175              
5176             #----------------------------------------
5177             # Starting final if-elsif- chain of tests
5178             #----------------------------------------
5179              
5180             # This is the return flag:
5181             # true => this is the last token on the line
5182             # false => keep tokenizing the line
5183 6663         7399 my $is_last;
5184              
5185             # The following blocks of code must update these vars:
5186             # $type - the final token type, must always be set
5187              
5188             # In addition, if additional pretokens are added:
5189             # $tok - the final token
5190             # $i - the index of the last pretoken
5191              
5192             # They may also need to check and set various flags
5193              
5194             # Scan a bare word following a -> as an identifier; it could
5195             # have a long package name. Fixes c037, c041.
5196 6663 100 100     81054 if ( $last_nonblank_token eq '->' ) {
    100 66        
    100 100        
    100 66        
    100 66        
    100 100        
    100 66        
    50 66        
    50 100        
    100 100        
    50 33        
    100 0        
    100 0        
    100 33        
    100 0        
    100 0        
    100 66        
    100 100        
    100 100        
      100        
      100        
      100        
      66        
      66        
5197 786         1890 $self->scan_bare_identifier();
5198              
5199             # a bareward after '->' gets type 'i'
5200 786         1067 $type = 'i';
5201             }
5202              
5203             # Quote a word followed by => operator
5204             elsif (
5205             ( $next_nonblank_token eq '=' && $rtokens->[ $i_next + 1 ] eq '>' )
5206              
5207             # unless the word is __END__ or __DATA__ and is the only word on
5208             # the line.
5209             && ( !defined( $is_END_DATA{$tok_kw} )
5210             || $input_line !~ /^\s*__(?:END|DATA)__\s*$/ )
5211             )
5212             {
5213             # Bareword followed by a fat comma - see 'git18.in'
5214             # This code was previously sub do_QUOTED_BAREWORD: see c316, c317
5215              
5216             # Older perl:
5217             # 'v25=>1' is a v-string key!
5218             # '-v25=>1' is also a v-string key!
5219             # Deactivated: this is no longer true; see git #165
5220 824 100       2434 if ( 0 && $tok =~ /^v\d+$/ ) {
5221             $type = 'v';
5222             $self->complain("v-string used as hash key\n");
5223             $self->report_v_string($tok);
5224             }
5225              
5226             # If tok is something like 'x17' then it could
5227             # actually be operator x followed by number 17.
5228             # For example, here:
5229             # 123x17 => [ 792, 1224 ],
5230             # (a key of 123 repeated 17 times, perhaps not
5231             # what was intended). We will mark x17 as type
5232             # 'n' and it will be split. If the previous token
5233             # was also a bareword then it is not very clear is
5234             # going on. In this case we will not be sure that
5235             # an operator is expected, so we just mark it as a
5236             # bareword. Perl is a little murky in what it does
5237             # with stuff like this, and its behavior can change
5238             # over time. Something like
5239             # a x18 => [792, 1224], will compile as
5240             # a key with 18 a's. But something like
5241             # push @array, a x18;
5242             # is a syntax error.
5243 0 100 33     0 elsif (
      66        
5244             $expecting == OPERATOR
5245             && substr( $tok, 0, 1 ) eq 'x'
5246             && ( length($tok) == 1
5247             || substr( $tok, 1, 1 ) =~ /^\d/ )
5248             )
5249             {
5250 3         5 $type = 'n';
5251 3 50       7 if ( $self->split_pretoken(1) ) {
5252 3         4 $type = 'x';
5253 3         4 $tok = 'x';
5254             }
5255 3         8 $self->complain("x operator in hash key\n");
5256             }
5257             else {
5258              
5259             # git #18
5260 821         1063 $type = 'w';
5261 821         1728 $self->error_if_expecting_OPERATOR();
5262             }
5263             }
5264              
5265             # quote a bare word within braces..like xxx->{s}; note that we
5266             # must be sure this is not a structural brace, to avoid
5267             # mistaking {s} in the following for a quoted bare word:
5268             # for(@[){s}bla}BLA}
5269             # Also treat q in something like var{-q} as a bare word, not
5270             # a quote operator
5271             elsif (
5272             $next_nonblank_token eq '}'
5273             && (
5274             $last_nonblank_type eq 'L'
5275             || ( $last_nonblank_type eq 'm'
5276             && $last_last_nonblank_type eq 'L' )
5277             )
5278             )
5279             {
5280 138         237 $type = 'w';
5281             }
5282              
5283             # handle operator x (now we know it isn't $x=)
5284             elsif (
5285             $expecting == OPERATOR
5286             && substr( $tok, 0, 1 ) eq 'x'
5287             && ( length($tok) == 1
5288             || substr( $tok, 1, 1 ) =~ /^\d/ )
5289             )
5290             {
5291 17         99 $self->do_X_OPERATOR();
5292             }
5293             elsif ( $tok_kw eq 'CORE::' ) {
5294 3         5 $type = $tok = $tok_kw;
5295 3         5 $i += 2;
5296             }
5297             elsif ( ( $tok eq 'strict' )
5298             and ( $last_nonblank_token eq 'use' ) )
5299             {
5300 14         40 $self->[_saw_use_strict_] = 1;
5301 14         55 $self->scan_bare_identifier();
5302             }
5303              
5304             elsif ( ( $tok eq 'warnings' )
5305             and ( $last_nonblank_token eq 'use' ) )
5306             {
5307 7         16 $self->[_saw_perl_dash_w_] = 1;
5308              
5309             # scan as identifier, so that we pick up something like:
5310             # use warnings::register
5311 7         16 $self->scan_bare_identifier();
5312             }
5313              
5314             elsif (
5315             $tok eq 'AutoLoader'
5316             && $self->[_look_for_autoloader_]
5317             && (
5318             $last_nonblank_token eq 'use'
5319              
5320             # these regexes are from AutoSplit.pm, which we want
5321             # to mimic
5322             || $input_line =~ /^\s*(use|require)\s+AutoLoader\b/
5323             || $input_line =~ /\bISA\s*=.*\bAutoLoader\b/
5324             )
5325             )
5326             {
5327 0         0 $self->write_logfile_entry("AutoLoader seen, -nlal deactivates\n");
5328 0         0 $self->[_saw_autoloader_] = 1;
5329 0         0 $self->[_look_for_autoloader_] = 0;
5330 0         0 $self->scan_bare_identifier();
5331             }
5332              
5333             elsif (
5334             $tok eq 'SelfLoader'
5335             && $self->[_look_for_selfloader_]
5336             && ( $last_nonblank_token eq 'use'
5337             || $input_line =~ /^\s*(use|require)\s+SelfLoader\b/
5338             || $input_line =~ /\bISA\s*=.*\bSelfLoader\b/ )
5339             )
5340             {
5341 0         0 $self->write_logfile_entry("SelfLoader seen, -nlsl deactivates\n");
5342 0         0 $self->[_saw_selfloader_] = 1;
5343 0         0 $self->[_look_for_selfloader_] = 0;
5344 0         0 $self->scan_bare_identifier();
5345             }
5346              
5347             elsif ( ( $tok eq 'constant' )
5348             and ( $last_nonblank_token eq 'use' ) )
5349             {
5350 16         45 $self->do_USE_CONSTANT();
5351             }
5352              
5353             # Lexical sub names override keywords, labels. Based on testing,
5354             # this seems to be the correct location for this check.
5355             elsif ($is_lexical_sub_type) {
5356 0         0 $type = $is_lexical_sub_type;
5357             }
5358              
5359             # various quote operators
5360             elsif ( $is_q_qq_qw_qx_qr_s_y_tr_m{$tok} ) {
5361 234         671 $self->do_QUOTE_OPERATOR();
5362             }
5363              
5364             # check for a statement label
5365             elsif (
5366             ( $next_nonblank_token eq ':' )
5367             && !$is_not_label
5368             && ( $rtokens->[ $i_next + 1 ] ne ':' )
5369             && ( $i_next <= $max_token_index ) # colon on same line
5370              
5371             # like 'sub : lvalue' ?
5372             && !$self->sub_attribute_ok_here( $tok_kw, $next_nonblank_token,
5373             $i_next )
5374             && new_statement_ok()
5375             )
5376             {
5377 33 100       133 if ( $tok !~ /[A-Z]/ ) {
5378 15         32 push @{ $self->[_rlower_case_labels_at_] }, $input_line_number;
  15         55  
5379             }
5380 33         1198 $type = 'J';
5381 33         81 $tok .= ':';
5382 33         65 $i = $i_next;
5383             }
5384              
5385             # 'sub' or other sub alias
5386             elsif ( $is_sub{$tok_kw} ) {
5387              
5388             # Guess what to do for unknown word 'method':
5389             # Updated for --use-feature=class (rt145706):
5390 372 100 100     1446 if ( $tok_kw eq 'method'
      100        
5391             && $guess_if_method
5392             && !$self->method_ok_here($next_nonblank_token) )
5393             {
5394 7         23 $self->do_UNKNOWN_BAREWORD($next_nonblank_token);
5395             }
5396             else {
5397 365 50       835 $self->error_if_expecting_OPERATOR()
5398             if ( $expecting == OPERATOR );
5399 365         1175 initialize_subname();
5400 365         1095 $self->scan_id();
5401             }
5402             }
5403              
5404             # 'package'
5405             elsif ( $is_package{$tok_kw} ) {
5406              
5407             # Update for --use-feature=class (rt145706):
5408             # We have to be extra careful because 'class' may be used for other
5409             # purposes on older code; i.e.
5410             # class($x) - valid sub call
5411             # package($x) - error
5412 54 100       150 if ( $tok_kw eq 'class' ) {
5413 14 100 66     121 if ( $expecting == OPERATOR
      100        
5414             || $next_nonblank_token !~ /^[\w\:]/
5415             || !$self->class_ok_here() )
5416             {
5417 4         12 $self->do_UNKNOWN_BAREWORD($next_nonblank_token);
5418             }
5419 10         25 else { $self->scan_id() }
5420             }
5421             else {
5422 40 50       100 $self->error_if_expecting_OPERATOR()
5423             if ( $expecting == OPERATOR );
5424 40         123 $self->scan_id();
5425             }
5426             }
5427              
5428             # Fix for c035: split 'format' from 'is_format_END_DATA' to be
5429             # more restrictive. Require a new statement to be ok here.
5430             elsif ( $tok_kw eq 'format' && new_statement_ok() ) {
5431 1         3 $type = ';'; # make tokenizer look for TERM next
5432 1         2 $self->[_in_format_] = 1;
5433 1         3 $is_last = 1; ## is last token on this line
5434             }
5435              
5436             # Note on token types for format, __DATA__, __END__:
5437             # It simplifies things to give these type ';', so that when we
5438             # start rescanning we will be expecting a token of type TERM.
5439             # We will switch to type 'k' before outputting the tokens.
5440             elsif ( defined( $is_END_DATA{$tok_kw} ) ) {
5441              
5442             # Warn if this follows an operator expecting a term (c565)
5443 8 50       47 $self->error_if_expecting_TERM()
5444             if ( $expecting == TERM );
5445              
5446 8         11 $type = ';'; # make tokenizer look for TERM next
5447              
5448             # Remember that we are in one of these three sections
5449 8         20 $self->[ $is_END_DATA{$tok_kw} ] = 1;
5450 8         12 $is_last = 1; ## is last token on this line
5451             }
5452             elsif ( $is_keyword{$tok_kw} ) {
5453 3114         7995 $self->do_KEYWORD();
5454             }
5455              
5456             # check for inline label following
5457             # /^(redo|last|next|goto)$/
5458             elsif (( $last_nonblank_type eq 'k' )
5459             && ( $is_redo_last_next_goto{$last_nonblank_token} ) )
5460             {
5461 19         32 $type = 'j';
5462             }
5463              
5464             # something else --
5465             else {
5466 1023         2809 $self->do_UNKNOWN_BAREWORD($next_nonblank_token);
5467             }
5468              
5469             #----------------------------------------------------------------
5470             # Save info for use in later guessing. Even for types 'i' and 'U'
5471             # because those may be marked as type 'w' (barewords) elsewhere.
5472             #----------------------------------------------------------------
5473 6663 100 100     20507 if ( $is_wiUC{$type}
      100        
5474             && $statement_type ne 'use'
5475             && $statement_type ne '_use' )
5476             {
5477 2642         3555 my $result = "unknown";
5478              
5479             # Words are marked 'function' if they appear in a role which
5480             # is not consistent with a constant value. Typically they are
5481             # function calls.
5482 2642 100 100     11247 if ( $type eq 'U'
    100 66        
5483             || $is_function_follower{$next_nonblank_token} )
5484             {
5485              
5486 1019         1465 my $empty_parens = 0;
5487 1019 100 100     3234 if ( $next_nonblank_token eq '(' && $i_next < $max_token_index )
5488             {
5489 594         1057 my $tok_next_p1 = $rtokens->[ $i_next + 1 ];
5490 594 100 100     2060 if ( substr( $tok_next_p1, 0, 1 ) eq SPACE
5491             && $i_next + 2 <= $max_token_index )
5492             {
5493 284         459 $tok_next_p1 = $rtokens->[ $i_next + 2 ];
5494             }
5495 594         993 $empty_parens = $tok_next_p1 eq ')';
5496             }
5497              
5498 1019 100       1926 if ( !$empty_parens ) {
5499              
5500             # not a constant term - probably a function
5501 961         1245 $result = "function";
5502 961         2122 $self->saw_bareword_function($tok);
5503             }
5504             }
5505              
5506             # Words are marked 'constant' if they appear in a role
5507             # consistent with a constant value. However, they may simply
5508             # be functions which optionally take zero args. So if a word
5509             # appears as both constant and function, it is not a constant.
5510             elsif ($type eq 'C'
5511             || $is_constant_follower{$next_nonblank_token} )
5512             {
5513              
5514 443   100     1612 my $is_hash_key = $next_nonblank_token eq '}'
5515             && (
5516             $last_nonblank_type eq 'L'
5517             || ( $last_nonblank_type eq 'm'
5518             && $last_last_nonblank_type eq 'L' )
5519             );
5520              
5521 443 100 100     2242 if (
      100        
      100        
5522              
5523             # not a hash key like {bareword} or {-bareword}
5524             !$is_hash_key
5525              
5526             # not a package name, etc
5527             && ( $last_nonblank_type ne 'k'
5528             || !$is_use_require_no{$last_nonblank_token} )
5529              
5530             # skip arrow calls, which can go either way
5531             && $last_nonblank_token ne '->'
5532             )
5533             {
5534             # possibly a constant or constant function
5535 180         248 $result = "constant";
5536 180         546 $self->saw_bareword_constant($tok);
5537             }
5538             else {
5539 263         459 $result = "other bareword";
5540             }
5541             }
5542             else {
5543             ## something else
5544             }
5545              
5546 2642         3173 if ( DEBUG_BAREWORD && $result ne 'other bareword' ) {
5547             print
5548             "$input_line_number: $result: $tok: type=$type : last_tok=$last_nonblank_token : next_tok='$next_nonblank_token'\n";
5549             }
5550             }
5551 6663         10934 return $is_last;
5552              
5553             } ## end sub do_BAREWORD
5554              
5555             # Table of quote types checked for interpolated here targets.
5556             # Issue 310 has extensive test cases.
5557             my %is_interpolated_quote = (
5558             q{'} => 0,
5559             q{`} => 1,
5560             q{"} => 1,
5561             qq => 1,
5562             qx => 1,
5563             m => 1,
5564             qr => 1,
5565             q => 0,
5566             qw => 0,
5567             s => 1,
5568             y => 0,
5569             tr => 0,
5570             );
5571              
5572             sub push_here_targets {
5573 2     2 0 4 my ($rht) = @_;
5574              
5575             # Push here targets found in a quote onto the here target list
5576 2         3 push @{$rhere_target_list}, @{$rht};
  2         5  
  2         6  
5577              
5578             # Change type from 'Q' to 'h' for quotes with here-doc targets so that
5579             # the formatter (see sub process_line_of_CODE) will not make any line
5580             # breaks after this point.
5581 2         5 $type = 'h';
5582 2 100       7 if ( $i_tok < 0 ) {
5583 1         3 my $ilast = $routput_token_list->[-1];
5584 1         3 $routput_token_type->[$ilast] = $type;
5585             }
5586 2         3 return;
5587             } ## end sub push_here_targets
5588              
5589             sub do_FOLLOW_QUOTE {
5590              
5591 3222     3222 0 3758 my $self = shift;
5592              
5593             # Continue following a quote on a new line
5594 3222         4006 $type = $quote_type;
5595              
5596             # initialize if continuation line
5597 3222 100       3371 if ( !@{$routput_token_list} ) {
  3222         5535  
5598 245         354 push( @{$routput_token_list}, $i );
  245         361  
5599 245         405 $routput_token_type->[$i] = $type;
5600             }
5601              
5602             # Save starting lengths for here target search
5603 3222         4070 my $len_qs1 = length($quoted_string_1);
5604 3222         3679 my $len_qs2 = length($quoted_string_2);
5605 3222         3715 my $in_quote_start = $in_quote;
5606              
5607             # scan for the end of the quote or pattern
5608             (
5609 3222         7857 $i,
5610             $in_quote,
5611             $quote_character,
5612             $quote_pos,
5613             $quote_depth,
5614             $quoted_string_1,
5615             $quoted_string_2,
5616              
5617             ) = $self->do_quote(
5618              
5619             $i,
5620             $in_quote,
5621             $quote_character,
5622             $quote_pos,
5623             $quote_depth,
5624             $quoted_string_1,
5625             $quoted_string_2,
5626             $rtokens,
5627             $rtoken_type,
5628             $rtoken_map,
5629             $max_token_index,
5630              
5631             );
5632              
5633             # Save pattern and replacement text for rescanning for /e
5634 3222         5141 my $qs1_for_e_scan = $quoted_string_1;
5635              
5636             # Check for possible here targets in an interpolated quote
5637 3222 100 100     8778 if ( $is_interpolated_quote{$quote_starting_tok}
5638             && $in_quote < $in_quote_start )
5639             {
5640              
5641             # post any saved target of a 2-part quote if the end is reached
5642 1467 100 100     4219 if ( !$in_quote && defined($quote_here_target_2) ) {
5643              
5644             # Safety check
5645 1 50       5 if ( $quote_items{$quote_starting_tok} == 2 ) {
5646 1         5 push_here_targets($quote_here_target_2);
5647             }
5648             else {
5649 0         0 DEVEL_MODE
5650             && Fault(
5651             "unexpected saved here target near line $input_line_number\n"
5652             );
5653             }
5654 1         3 $quote_here_target_2 = undef;
5655             }
5656              
5657             # Single part quotes: use $quoted_string_1, and
5658             # $in_quote drops from 1 to 0 when the end is found
5659             # Dual part quotes ('s'): first part is in $quoted_string_2, and
5660             # $in_quote:
5661             # drops from 2 to 1 when the the first part is found
5662             # drops 1 to 0 when the the second part is found
5663             # drops from 2 to 0 if both parts are found in this call
5664             # The tricky part is that we must search for here targets whenever
5665             # $in_quote drops, but we can only post here targets after the end
5666             # of the last part is found (in_quote==0). See test 'here4.in'.
5667             # Update c310 added interpolated here docs and has many test cases.
5668              
5669             # Initialize for the normal case of a single quote
5670 1467         1927 my $qs = $quoted_string_1;
5671 1467         1795 my $len_qs = $len_qs1;
5672 1467         2036 my $num_quotes = $in_quote_start - $in_quote;
5673              
5674             # Dual part quotes (type 's') have first part in $quoted_string_2
5675 1467 100       2505 if ( $in_quote_start == 2 ) {
5676 31         44 $qs = $quoted_string_2;
5677 31         47 $len_qs = $len_qs2;
5678             }
5679              
5680             # Loop to search 1 or 2 quotes for here targets
5681 1467         3059 foreach ( 1 .. $num_quotes ) {
5682              
5683             # Perform quick tests to avoid a sub call:
5684 1496         2625 my $pos_shift = rindex( $qs, '<<' );
5685 1496 50 100     3171 if (
      33        
      66        
5686              
5687             # a '<<' in the last line
5688             $pos_shift >= $len_qs
5689              
5690             # and a '}' in the last line (c598: updated to allow
5691             # for the possibility of an extra '<<' after a here doc)
5692             && rindex( $qs, '}' ) >= $len_qs
5693              
5694             # and a '<<' preceded by '$' or '@'
5695             && ( rindex( $qs, '$', $pos_shift ) >= 0
5696             || rindex( $qs, '@', $pos_shift ) >= 0 )
5697             )
5698             {
5699              
5700             # scan the quote for here targets
5701 2         9 my ( $rht, $qs_mod ) =
5702             $self->find_interpolated_here_targets( $qs, $len_qs );
5703 2 50       7 if ($rht) {
5704              
5705             # only post here targets when end of quote is found
5706 2 100       6 if ($in_quote) {
5707 1         3 $quote_here_target_2 = $rht;
5708             }
5709             else {
5710 1         3 push_here_targets($rht);
5711              
5712             # Replace the string with the modified version
5713             # in case it is re-scanned due to a /e modifier
5714 1         2 $qs1_for_e_scan = $qs_mod;
5715             }
5716             }
5717             }
5718              
5719             # re-initialize for next pass
5720 1496         1824 $qs = $quoted_string_1;
5721 1496         2436 $len_qs = $len_qs1;
5722             } ## end while ( $num_quotes-- > 0)
5723             }
5724              
5725 3222 100       5003 if ($in_quote) { return }
  244         402  
5726              
5727             # All done with this quote...
5728              
5729             # re-initialize for next search
5730 2978         3418 $quote_character = EMPTY_STRING;
5731 2978         3194 $quote_pos = 0;
5732 2978         3386 $quote_type = 'Q';
5733 2978         3273 $quoted_string_1 = EMPTY_STRING;
5734 2978         3249 $quoted_string_2 = EMPTY_STRING;
5735 2978 100       4790 if ( ++$i > $max_token_index ) { return }
  126         215  
5736              
5737             # look for any modifiers
5738 2852 100       4465 if ($allowed_quote_modifiers) {
5739              
5740             # check for exact quote modifiers
5741 162 100       636 if ( $rtokens->[$i] =~ /^[A-Za-z_]/ ) {
5742 31         47 my $str = $rtokens->[$i];
5743 31         47 my $saw_modifier_e;
5744 31         621 while ( $str =~ /\G$allowed_quote_modifiers/gc ) {
5745 49         101 my $pos = pos($str);
5746 49         97 my $char = substr( $str, $pos - 1, 1 );
5747 49   100     242 $saw_modifier_e ||= ( $char eq 'e' );
5748             }
5749              
5750             # For an 'e' quote modifier we must scan the replacement
5751             # text for here-doc targets...
5752             # but if the modifier starts a new line we must skip
5753             # this because either the here doc will be fully
5754             # contained in the replacement text (so we can
5755             # ignore it) or Perl will not find it. The modifier will have a
5756             # pretoken index $i=1 if it starts a new line, so we only look
5757             # for a here doc if $i>1. See test 'here2.in'.
5758 31 50 66     97 if ( $saw_modifier_e && $i > 1 ) {
5759 0         0 my $rht = $self->scan_replacement_text($qs1_for_e_scan);
5760 0 0       0 if ($rht) {
5761 0         0 push_here_targets($rht);
5762             }
5763             }
5764              
5765 31 50       92 if ( defined( pos($str) ) ) {
5766              
5767             # matched
5768 31 50       73 if ( pos($str) == length($str) ) {
5769 31 50       86 if ( ++$i > $max_token_index ) { return }
  0         0  
5770             }
5771              
5772             # Looks like a joined quote modifier
5773             # and keyword, maybe something like
5774             # s/xxx/yyy/gefor @k=...
5775             # Example is "galgen.pl". Would have to split
5776             # the word and insert a new token in the
5777             # pre-token list. This is so rare that I haven't
5778             # done it. Will just issue a warning citation.
5779              
5780             # This error might also be triggered if my quote
5781             # modifier characters are incomplete
5782             else {
5783 0         0 $self->warning(<<EOM);
5784              
5785             Partial match to quote modifier $allowed_quote_modifiers at word: '$str'
5786             Please put a space between quote modifiers and trailing keywords.
5787             EOM
5788              
5789             # print "token $rtokens->[$i]\n";
5790             # my $num = length($str) - pos($str);
5791             # $rtokens->[$i]=substr($rtokens->[$i],pos($str),$num);
5792             # print "continuing with new token $rtokens->[$i]\n";
5793              
5794             # skipping past this token does least damage
5795 0 0       0 if ( ++$i > $max_token_index ) { return }
  0         0  
5796             }
5797             }
5798             else {
5799              
5800             # example file: rokicki4.pl
5801             # This error might also be triggered if my quote
5802             # modifier characters are incomplete
5803 0         0 $self->write_logfile_entry(
5804             "Note: found word $str at quote modifier location\n");
5805             }
5806             }
5807              
5808             # re-initialize
5809 162         236 $allowed_quote_modifiers = EMPTY_STRING;
5810             }
5811 2852         3878 return;
5812             } ## end sub do_FOLLOW_QUOTE
5813              
5814             # ------------------------------------------------------------
5815             # begin hash of code for handling most token types
5816             # ------------------------------------------------------------
5817             my $tokenization_code = {
5818              
5819             '$' => \&do_DOLLAR_SIGN,
5820             '(' => \&do_LEFT_PARENTHESIS,
5821             ')' => \&do_RIGHT_PARENTHESIS,
5822             ',' => \&do_COMMA,
5823             ';' => \&do_SEMICOLON,
5824             '"' => \&do_QUOTATION_MARK,
5825             "'" => \&do_APOSTROPHE,
5826             '`' => \&do_BACKTICK,
5827             '/' => \&do_SLASH,
5828             '{' => \&do_LEFT_CURLY_BRACKET,
5829             '}' => \&do_RIGHT_CURLY_BRACKET,
5830             '&' => \&do_AMPERSAND,
5831             '<' => \&do_LESS_THAN_SIGN,
5832             '?' => \&do_QUESTION_MARK,
5833             '*' => \&do_STAR,
5834             '.' => \&do_DOT,
5835             ':' => \&do_COLON,
5836             '+' => \&do_PLUS_SIGN,
5837             '@' => \&do_AT_SIGN,
5838             '%' => \&do_PERCENT_SIGN,
5839             '[' => \&do_LEFT_SQUARE_BRACKET,
5840             ']' => \&do_RIGHT_SQUARE_BRACKET,
5841             '-' => \&do_MINUS_SIGN,
5842             '^' => \&do_CARAT_SIGN,
5843             '::' => \&do_DOUBLE_COLON,
5844             '<<' => \&do_LEFT_SHIFT,
5845             '<<~' => \&do_NEW_HERE_DOC,
5846             '->' => \&do_POINTER,
5847             '++' => \&do_PLUS_PLUS,
5848             '=>' => \&do_FAT_COMMA,
5849             '--' => \&do_MINUS_MINUS,
5850              
5851             # No special code for these types yet, but syntax checks
5852             # could be added.
5853             ## '&&' => \&do_LOGICAL_AND,
5854             ## '||' => \&do_LOGICAL_OR,
5855             ## '>' => \&do_GREATER_THAN_SIGN,
5856             ## '|' => \&do_VERTICAL_LINE,
5857             ## '//' => \&do_SLASH_SLASH,
5858             ## '!' => undef,
5859             ## '!=' => undef,
5860             ## '!~' => undef,
5861             ## '%=' => undef,
5862             ## '&&=' => undef,
5863             ## '&=' => undef,
5864             ## '+=' => undef,
5865             ## '-=' => undef,
5866             ## '..' => undef,
5867             ## '..' => undef,
5868             ## '...' => undef,
5869             ## '.=' => undef,
5870             ## '<<=' => undef,
5871             ## '<=' => undef,
5872             ## '<=>' => undef,
5873             ## '<>' => undef,
5874             ## '=' => undef,
5875             ## '==' => undef,
5876             ## '=~' => undef,
5877             ## '>=' => undef,
5878             ## '>>' => undef,
5879             ## '>>=' => undef,
5880             ## '\\' => undef,
5881             ## '^=' => undef,
5882             ## '|=' => undef,
5883             ## '||=' => undef,
5884             ## '//=' => undef,
5885             ## '~' => undef,
5886             ## '~~' => undef,
5887             ## '!~~' => undef,
5888              
5889             };
5890              
5891             # ------------------------------------------------------------
5892             # end hash of code for handling individual token types
5893             # ------------------------------------------------------------
5894              
5895 44     44   386 use constant DEBUG_TOKENIZE => 0;
  44         98  
  44         4360  
5896              
5897             my %is_arrow_or_Z;
5898              
5899             BEGIN {
5900 44     44   197 my @qZ = qw( -> Z );
5901 44         164142 $is_arrow_or_Z{$_} = 1 for @qZ;
5902             }
5903              
5904             sub tokenize_this_line {
5905              
5906 8920     8920 0 13865 my ( $self, $line_of_tokens, $trimmed_input_line ) = @_;
5907              
5908             # This routine tokenizes one line. The results are stored in
5909             # the hash ref '$line_of_tokens'.
5910              
5911             # Given:
5912             # $line_of_tokens = ref to hash of values being filled for this line
5913             # $trimmed_input_line
5914             # = the input line without leading whitespace, OR
5915             # = undef if not available
5916             # Returns:
5917             # nothing
5918              
5919 8920         12654 my $untrimmed_input_line = $line_of_tokens->{_line_text};
5920              
5921             # Extract line number for use in error messages
5922 8920         11367 $input_line_number = $line_of_tokens->{_line_number};
5923              
5924             #-------------------------------------
5925             # Check for start of pod documentation
5926             #-------------------------------------
5927 8920 100 100     26171 if ( !$in_quote
      66        
5928             && substr( $untrimmed_input_line, 0, 1 ) eq '='
5929             && $untrimmed_input_line =~ /^=[A-Za-z_]/ )
5930             {
5931              
5932             # Must not be in an equation where an '=' could be expected.
5933             # Perl has additional restrictions which are not checked here.
5934 15         27 my $blank_after_Z = 1;
5935 15         48 $expecting = $self->operator_expected( '=', 'b', $blank_after_Z );
5936 15 50       59 if ( $expecting == TERM ) {
5937 15         25 $self->[_in_pod_] = 1;
5938 15         34 return;
5939             }
5940             }
5941              
5942             #--------------------------
5943             # Trim leading whitespace ?
5944             #--------------------------
5945             # Use untrimmed line if we are continuing in a type 'Q' quote
5946 8905 100 100     16806 if ( $in_quote && $quote_type eq 'Q' ) {
5947 58         90 $line_of_tokens->{_starting_in_quote} = 1;
5948 58         87 $input_line = $untrimmed_input_line;
5949 58         103 chomp $input_line;
5950             }
5951              
5952             # Trim start of this line if we are not continuing a quoted line.
5953             # Do not trim end because we might end in a quote (test: deken4.pl)
5954             # Perl::Tidy::Formatter will delete needless trailing blanks
5955             else {
5956 8847         13387 $line_of_tokens->{_starting_in_quote} = 0;
5957              
5958             # Use the pre-computed trimmed line if defined (most efficient)
5959 8847         10869 $input_line = $trimmed_input_line;
5960              
5961             # otherwise trim the raw input line (much less efficient)
5962 8847 50       13130 if ( !defined($input_line) ) {
5963 0         0 $input_line = $untrimmed_input_line;
5964 0         0 $input_line =~ s/^\s+//;
5965             }
5966              
5967 8847         11173 chomp $input_line;
5968              
5969             # define 'guessed_indentation_level' if logfile will be saved
5970 8847 100 100     16874 if ( $self->[_save_logfile_] && length($input_line) ) {
5971 3         5 my $guess =
5972             $self->guess_old_indentation_level($untrimmed_input_line);
5973 3         8 $line_of_tokens->{_guessed_indentation_level} = $guess;
5974             }
5975             }
5976              
5977             #------------
5978             # Blank lines
5979             #------------
5980 8905 100       14233 if ( !length($input_line) ) {
5981 1053         1716 $line_of_tokens->{_line_type} = 'CODE';
5982 1053         1729 $line_of_tokens->{_rtokens} = [];
5983 1053         1710 $line_of_tokens->{_rtoken_type} = [];
5984 1053         1763 $line_of_tokens->{_rlevels} = [];
5985 1053         1823 $line_of_tokens->{_rblock_type} = [];
5986 1053         2087 $line_of_tokens->{_nesting_tokens_0} = $nesting_token_string;
5987 1053         1660 $line_of_tokens->{_nesting_blocks_0} = $nesting_block_string;
5988 1053         1685 return;
5989             }
5990              
5991             #---------
5992             # Comments
5993             #---------
5994 7852 100 100     20701 if ( !$in_quote && substr( $input_line, 0, 1 ) eq '#' ) {
5995              
5996             # and check for skipped section
5997 890 50 66     4105 if (
      66        
      66        
5998             (
5999             substr( $input_line, 0, 4 ) eq '#<<V'
6000             || $rOpts_code_skipping_begin
6001             )
6002             && $rOpts_code_skipping
6003              
6004             # note that the code_skipping_patterns require a newline
6005             && ( $input_line . SPACE ) =~ /$code_skipping_pattern_begin/
6006             )
6007             {
6008 2         7 $self->[_in_code_skipping_] = $self->[_last_line_number_];
6009 2         5 return;
6010             }
6011              
6012             # Look for format skipping tags, but just normal mode.
6013             # It will be used for these purposes:
6014             # - to inform the formatter of an end token with no begin token
6015             # - for making a hint when a brace error is detected
6016 888 100 100     8276 if (
    100 100        
      100        
      33        
      66        
      100        
      100        
      100        
6017             (
6018             substr( $input_line, 0, 4 ) eq '#<<<'
6019             || $rOpts_format_skipping_begin
6020             )
6021             && $rOpts_format_skipping
6022              
6023             # note that the format_skipping_patterns require a space
6024             && ( $input_line . SPACE ) =~ /$format_skipping_pattern_begin/
6025              
6026             # allow same token for begin and end
6027             && (
6028             !$self->[_in_format_skipping_]
6029             || ( $format_skipping_pattern_begin ne
6030             $format_skipping_pattern_end )
6031             )
6032             )
6033             {
6034 17         39 my $on_off = 1;
6035 17         35 my $lno = $self->[_last_line_number_];
6036 17         29 my $rformat_skipping_list = $self->[_rformat_skipping_list_];
6037              
6038             # format markers must alternate between on and off
6039 17 50 66     26 if ( @{$rformat_skipping_list}
  17         77  
6040             && $rformat_skipping_list->[-1]->[0] == $on_off )
6041             {
6042 0         0 my $lno_last = $rformat_skipping_list->[-1]->[1];
6043 0         0 $self->warning_do_not_format(
6044             "consecutive format-skipping start markers - see line $lno_last\n"
6045             );
6046             }
6047 17         28 push @{$rformat_skipping_list}, [ $on_off, $lno, $input_line ];
  17         44  
6048 17         34 $self->[_in_format_skipping_] = $lno;
6049             }
6050             elsif (
6051             (
6052             substr( $input_line, 0, 4 ) eq '#>>>'
6053             || $rOpts_format_skipping_end
6054             )
6055             && $rOpts_format_skipping
6056              
6057             # note that the format_skipping_patterns require a newline
6058             && ( $input_line . SPACE ) =~ /$format_skipping_pattern_end/
6059             )
6060             {
6061 20         48 my $lno = $self->[_last_line_number_];
6062 20         33 my $rformat_skipping_list = $self->[_rformat_skipping_list_];
6063 20         33 my $on_off = -1;
6064              
6065             # markers must alternate between on and off
6066 20 50 66     35 if ( @{$rformat_skipping_list}
  20         101  
6067             && $rformat_skipping_list->[-1]->[0] == $on_off )
6068             {
6069 0         0 my $lno_last = $rformat_skipping_list->[-1]->[1];
6070 0         0 $self->warning_do_not_format(
6071             "consecutive format-skipping end markers - see line $lno_last\n"
6072             );
6073             }
6074              
6075 20         40 push @{$rformat_skipping_list}, [ $on_off, $lno, $input_line ];
  20         52  
6076 20         42 $self->[_in_format_skipping_] = 0;
6077             }
6078             else {
6079             ## not a format skipping comment
6080             }
6081              
6082             # Optional fast processing of a block comment
6083 888         1519 $line_of_tokens->{_line_type} = 'CODE';
6084 888         1879 $line_of_tokens->{_rtokens} = [$input_line];
6085 888         1761 $line_of_tokens->{_rtoken_type} = ['#'];
6086 888         2025 $line_of_tokens->{_rlevels} = [$level_in_tokenizer];
6087 888         1915 $line_of_tokens->{_rblock_type} = [EMPTY_STRING];
6088 888         1716 $line_of_tokens->{_nesting_tokens_0} = $nesting_token_string;
6089 888         1496 $line_of_tokens->{_nesting_blocks_0} = $nesting_block_string;
6090 888         1524 return;
6091             }
6092              
6093             #-------------------------------------
6094             # Loop to find all tokens on this line
6095             #-------------------------------------
6096              
6097             # Update the copy of the line for use in error messages
6098             # This must be exactly what we give the pre_tokenizer
6099 6962         9257 $self->[_line_of_text_] = $input_line;
6100              
6101             # re-initialize for the main loop
6102 6962         9393 $routput_token_list = []; # stack of output token indexes
6103 6962         11221 $routput_token_type = []; # token types
6104 6962         16466 $routput_block_type = []; # types of code block
6105 6962         15176 $routput_type_sequence = []; # nesting sequential number
6106              
6107 6962         15348 $rhere_target_list = [];
6108              
6109 6962         9224 $tok = $last_nonblank_token;
6110 6962         8114 $type = $last_nonblank_type;
6111 6962         8313 $prototype = $last_nonblank_prototype;
6112 6962         7800 $last_nonblank_i = -1;
6113 6962         8112 $block_type = $last_nonblank_block_type;
6114 6962         7923 $container_type = $last_nonblank_container_type;
6115 6962         7700 $type_sequence = $last_nonblank_type_sequence;
6116 6962         7123 $indent_flag = 0;
6117 6962         6908 $peeked_ahead = 0;
6118              
6119 6962         15561 $self->tokenizer_main_loop();
6120              
6121             #-------------------------------------------------
6122             # Done tokenizing this line ... package the result
6123             #-------------------------------------------------
6124 6962         17082 $self->tokenizer_wrapup_line($line_of_tokens);
6125              
6126 6962         10427 return;
6127             } ## end sub tokenize_this_line
6128              
6129             sub tokenizer_main_loop {
6130              
6131 6962     6962 0 9475 my ($self) = @_;
6132              
6133             # Break one input line into tokens
6134             # We are working on closure variables.
6135              
6136             # Start by breaking the line into pre-tokens
6137 6962         15447 ( $rtokens, $rtoken_map, $rtoken_type ) = pre_tokenize($input_line);
6138              
6139             # Verify that all leading whitespace has been trimmed
6140             # except for quotes of type 'Q' (c273).
6141 6962 50 66     24265 if ( @{$rtokens}
  6962   33     24772  
      66        
6142             && $rtoken_type->[0] eq 'b'
6143             && !( $in_quote && $quote_type eq 'Q' ) )
6144             {
6145              
6146             # Shouldn't happen if calling sub did trim operation correctly.
6147 0         0 DEVEL_MODE && Fault(<<EOM);
6148             leading blank at line
6149             $input_line
6150             EOM
6151              
6152             # Fix by removing the leading blank token. This fix has been
6153             # tested and works correctly even if no whitespaces was trimmed.
6154             # But it is an inefficient way to do things because, for example,
6155             # it forces all comments to be processed by sub pre_tokenize.
6156             # And it may cause indented code-skipping comments to be missed.
6157 0         0 shift @{$rtokens};
  0         0  
6158 0         0 shift @{$rtoken_map};
  0         0  
6159 0         0 shift @{$rtoken_type};
  0         0  
6160             }
6161              
6162 6962         7939 $max_token_index = scalar( @{$rtokens} ) - 1;
  6962         8942  
6163 6962         7662 push( @{$rtokens}, SPACE, SPACE, SPACE )
  6962         13063  
6164             ; # extra whitespace simplifies logic
6165 6962         7657 push( @{$rtoken_map}, 0, 0, 0 ); # shouldn't be referenced
  6962         11058  
6166 6962         7500 push( @{$rtoken_type}, 'b', 'b', 'b' );
  6962         11357  
6167              
6168             # initialize for main loop
6169 6962         7302 if (0) { #<<< this is not necessary
6170             foreach my $ii ( 0 .. $max_token_index + 3 ) {
6171             $routput_token_type->[$ii] = EMPTY_STRING;
6172             $routput_block_type->[$ii] = EMPTY_STRING;
6173             $routput_type_sequence->[$ii] = EMPTY_STRING;
6174             $routput_indent_flag->[$ii] = 0;
6175             }
6176             }
6177              
6178 6962         8214 $i = -1;
6179 6962         7813 $i_tok = -1;
6180              
6181             #-----------------------
6182             # main tokenization loop
6183             #-----------------------
6184              
6185             # we are looking at each pre-token of one line and combining them
6186             # into tokens
6187 6962         11623 while ( ++$i <= $max_token_index ) {
6188              
6189             # continue looking for the end of a quote
6190 60334 100       78671 if ($in_quote) {
6191 3222         7468 $self->do_FOLLOW_QUOTE();
6192 3222 100 100     8564 last if ( $in_quote || $i > $max_token_index );
6193             }
6194              
6195 59964 100 100     115380 if ( $type ne 'b' && $type ne 'CORE::' ) {
6196              
6197             # try to catch some common errors
6198 42019 100 100     67322 if ( ( $type eq 'n' ) && ( $tok ne '0' ) ) {
6199              
6200 2071 100       4265 if ( $last_nonblank_token eq 'eq' ) {
    50          
6201 9         34 $self->complain("Should 'eq' be '==' here ?\n");
6202             }
6203             elsif ( $last_nonblank_token eq 'ne' ) {
6204 0         0 $self->complain("Should 'ne' be '!=' here ?\n");
6205             }
6206             else {
6207             ## that's all
6208             }
6209             }
6210              
6211             # fix c090, only rotate vars if a new token will be stored
6212 42019 100       56975 if ( $i_tok >= 0 ) {
6213              
6214 35246         37372 $last_last_nonblank_token = $last_nonblank_token;
6215 35246         35194 $last_last_nonblank_type = $last_nonblank_type;
6216              
6217 35246         36406 $last_nonblank_prototype = $prototype;
6218 35246         35246 $last_nonblank_block_type = $block_type;
6219 35246         34411 $last_nonblank_container_type = $container_type;
6220 35246         35905 $last_nonblank_type_sequence = $type_sequence;
6221 35246         33366 $last_nonblank_i = $i_tok;
6222 35246         34489 $last_nonblank_token = $tok;
6223 35246         35645 $last_nonblank_type = $type;
6224             }
6225              
6226             # Check for patches
6227 42019 100       64571 if ( $is_arrow_or_Z{$last_last_nonblank_type} ) {
6228              
6229             # Patch for c030: Fix things in case a '->' got separated
6230             # from the subsequent identifier by a side comment. We
6231             # need the last_nonblank_token to have a leading -> to
6232             # avoid triggering an operator expected error message at
6233             # the next '('. See also fix for git #63.
6234 1242 100       2395 if ( $last_last_nonblank_type eq '->' ) {
    50          
6235 1196 100 66     3882 if ( $last_nonblank_type eq 'w'
6236             || $last_nonblank_type eq 'i' )
6237             {
6238 793         1297 $last_nonblank_token = '->' . $last_nonblank_token;
6239 793         1108 $last_nonblank_type = 'i';
6240             }
6241             }
6242              
6243             # Fix part #3 for git82: propagate type 'Z' though L-R pair
6244             elsif ( $last_last_nonblank_type eq 'Z' ) {
6245 46 100       125 if ( $last_nonblank_type eq 'R' ) {
6246 1         3 $last_nonblank_type = $last_last_nonblank_type;
6247 1         2 $last_nonblank_token = $last_last_nonblank_token;
6248             }
6249             }
6250             else {
6251             ## No other patches
6252             }
6253             }
6254             }
6255              
6256             # store previous token type
6257 59964 100       76428 if ( $i_tok >= 0 ) {
6258 53191         76836 $routput_token_type->[$i_tok] = $type;
6259 53191         69678 $routput_block_type->[$i_tok] = $block_type;
6260 53191         68390 $routput_type_sequence->[$i_tok] = $type_sequence;
6261 53191         59229 $routput_indent_flag->[$i_tok] = $indent_flag;
6262             }
6263              
6264             # get the next pre-token and type
6265             # $tok and $type will be modified to make the output token
6266 59964         72458 my $pre_tok = $tok = $rtokens->[$i]; # get the next pre-token
6267 59964         70090 my $pre_type = $type = $rtoken_type->[$i]; # and type
6268              
6269             # re-initialize various flags for the next output token
6270             (
6271              
6272             # remember the starting index of this token; we will update $i
6273 59964         83449 $i_tok,
6274             $block_type,
6275             $container_type,
6276             $type_sequence,
6277             $indent_flag,
6278             $prototype,
6279             )
6280             = (
6281              
6282             $i,
6283             EMPTY_STRING,
6284             EMPTY_STRING,
6285             EMPTY_STRING,
6286             0,
6287             EMPTY_STRING,
6288             );
6289              
6290             # this pre-token will start an output token
6291 59964         56639 push( @{$routput_token_list}, $i_tok );
  59964         72608  
6292              
6293             #---------------------------------------------------
6294             # The token search leads to one of 5 main END NODES:
6295             #---------------------------------------------------
6296              
6297             #-----------------------
6298             # END NODE 1: whitespace
6299             #-----------------------
6300 59964 100       88038 next if ( $pre_type eq 'b' );
6301              
6302             #----------------------
6303             # END NODE 2: a comment
6304             #----------------------
6305 41874 100       55870 if ( $pre_type eq '#' ) {
6306              
6307             # push non-indenting brace stack Look for a possible
6308             # non-indenting brace. This is only used to give a hint in
6309             # case the file is unbalanced.
6310             # Hardwired to '#<<<' for efficiency. We will not use the
6311             # result later if the pattern has been changed (very unusual).
6312 363 100 66     1277 if ( $last_nonblank_token eq '{'
      66        
      33        
      66        
6313             && $last_nonblank_block_type
6314             && $last_nonblank_type_sequence
6315             && !$self->[_in_format_skipping_]
6316             && $rOpts_non_indenting_braces )
6317             {
6318 46         71 my $offset = $rtoken_map->[$i_tok];
6319 46         95 my $text = substr( $input_line, $offset, 5 );
6320 46         91 my $len = length($text);
6321 46 100 66     272 if ( $len == 4 && $text eq '#<<<'
      66        
      66        
6322             || $len > 4 && $text eq '#<<< ' )
6323             {
6324 6         10 push @{ $self->[_rnon_indenting_brace_stack_] },
  6         11  
6325             $last_nonblank_type_sequence;
6326             }
6327             }
6328 363         616 last;
6329             }
6330              
6331             # continue gathering identifier if necessary
6332 41511 100       56635 if ($id_scan_state) {
6333              
6334 17 100 66     75 if ( $is_sub{$id_scan_state} || $is_package{$id_scan_state} ) {
6335 10         31 $self->scan_id();
6336             }
6337             else {
6338 7         22 $self->scan_identifier();
6339             }
6340              
6341 17 100       40 if ($id_scan_state) {
6342              
6343             # Still scanning ...
6344             # Check for side comment between sub and prototype (c061)
6345              
6346             # done if nothing left to scan on this line
6347 1 50       2 last if ( $i > $max_token_index );
6348              
6349 1         3 my ( $next_nonblank_token_uu, $i_next ) =
6350             find_next_nonblank_token_on_this_line( $i, $rtokens,
6351             $max_token_index );
6352              
6353             # done if it was just some trailing space
6354 1 50       3 last if ( $i_next > $max_token_index );
6355              
6356             # something remains on the line ... must be a side comment
6357 1         3 next;
6358             }
6359              
6360 16 100 100     74 next if ( ( $i > 0 ) || $type );
6361              
6362             # didn't find any token; start over
6363 7         11 $type = $pre_type;
6364 7         12 $tok = $pre_tok;
6365             }
6366              
6367             #-----------------------------------------------------------
6368             # Combine pre-tokens into digraphs and trigraphs if possible
6369             #-----------------------------------------------------------
6370              
6371             # See if we can make a digraph...
6372             # The following tokens are excluded and handled specially:
6373             # '/=' is excluded because the / might start a pattern.
6374             # 'x=' is excluded since it might be $x=, with $ on previous line
6375             # '**' and *= might be typeglobs of punctuation variables
6376             # I have allowed tokens starting with <, such as <=,
6377             # because I don't think these could be valid angle operators.
6378             # test file: storrs4.pl
6379 41501 100 100     99245 if ( $can_start_digraph{$tok}
      100        
6380             && $i < $max_token_index
6381             && $is_digraph{ $tok . $rtokens->[ $i + 1 ] } )
6382             {
6383              
6384 3113         4064 my $combine_ok = 1;
6385 3113         4964 my $test_tok = $tok . $rtokens->[ $i + 1 ];
6386              
6387             # check for special cases which cannot be combined
6388              
6389             # Smartmatch is being deprecated, but may exist in older
6390             # scripts.
6391 3113 100       8524 if ( $test_tok eq '~~' ) {
    100          
    100          
6392              
6393             # Do not combine if a TERM is required
6394 111 100       242 if ( $self->operator_expected( $tok, '~', undef ) == TERM )
6395             {
6396              
6397             # block types ';' may actually be hash refs, c567
6398 1 50       3 if ( $last_nonblank_type eq '}' ) {
6399 1         3 my $blk = $rbrace_type->[ $brace_depth + 1 ];
6400 1 50 33     6 if ( !$blk || $blk ne ';' ) { $combine_ok = 0 }
  0         0  
6401             }
6402             else {
6403 0         0 $combine_ok = 0;
6404             }
6405             }
6406             }
6407              
6408             # '//' must be defined_or operator if an operator is expected.
6409             # TODO: Code for other ambiguous digraphs (/=, x=, **, *=)
6410             # could be migrated here for clarity
6411              
6412             # Patch for RT#102371, misparsing a // in the following snippet:
6413             # state $b //= ccc();
6414             # The solution is to always accept the digraph (or trigraph)
6415             # after type 'Z' (possible file handle). The reason is that
6416             # sub operator_expected gives TERM expected here, which is
6417             # wrong in this case.
6418             elsif ( $test_tok eq '//' ) {
6419 16 50       37 if ( $last_nonblank_type ne 'Z' ) {
6420              
6421             # note that here $tok = '/' and the next tok and type
6422             # is '/'
6423 16         21 my $blank_after_Z;
6424 16         41 $expecting =
6425             $self->operator_expected( $tok, '/', $blank_after_Z );
6426              
6427             # Patched for RT#101547, was
6428             # 'unless ($expecting==OPERATOR)'
6429 16 100       37 $combine_ok = 0 if ( $expecting == TERM );
6430             }
6431             }
6432              
6433             # Patch for RT #114359: mis-parsing of "print $x ** 0.5;
6434             # Accept the digraphs '**' only after type 'Z'
6435             # Otherwise postpone the decision.
6436             elsif ( $test_tok eq '**' ) {
6437 45 100       141 if ( $last_nonblank_type ne 'Z' ) { $combine_ok = 0 }
  43         82  
6438             }
6439             else {
6440             ## no other special cases
6441             }
6442              
6443 3113 100 100     15247 if (
      66        
      100        
6444              
6445             # still ok to combine?
6446             $combine_ok
6447              
6448             && ( $test_tok ne '/=' ) # might be pattern
6449             && ( $test_tok ne 'x=' ) # might be $x
6450             && ( $test_tok ne '*=' ) # typeglob?
6451              
6452             # Moved above as part of fix for
6453             # RT #114359: Missparsing of "print $x ** 0.5;
6454             # && ( $test_tok ne '**' ) # typeglob?
6455             )
6456             {
6457 3060         3770 $tok = $test_tok;
6458 3060         3374 $i++;
6459              
6460             # Now try to assemble trigraphs. Note that all possible
6461             # perl trigraphs can be constructed by appending a character
6462             # to a digraph.
6463 3060         4302 $test_tok = $tok . $rtokens->[ $i + 1 ];
6464              
6465 3060 100       5427 if ( $is_trigraph{$test_tok} ) {
6466 105         160 $tok = $test_tok;
6467 105         172 $i++;
6468             }
6469              
6470             # The only current tetragraph is the double diamond operator
6471             # and its first three characters are NOT a trigraph, so
6472             # we do can do a special test for it
6473             else {
6474 2955 100       5558 if ( $test_tok eq '<<>' ) {
6475 1         3 $test_tok .= $rtokens->[ $i + 2 ];
6476 1 50       3 if ( $is_tetragraph{$test_tok} ) {
6477 1         2 $tok = $test_tok;
6478 1         3 $i += 2;
6479             }
6480             }
6481             }
6482             }
6483             }
6484              
6485 41501         43283 $type = $tok;
6486 41501         51040 $next_tok = $rtokens->[ $i + 1 ];
6487 41501         48525 $next_type = $rtoken_type->[ $i + 1 ];
6488              
6489             # expecting an operator here? first try table lookup, then function
6490 41501         52286 $expecting = $op_expected_table{$last_nonblank_type};
6491 41501 100       55427 if ( !defined($expecting) ) {
6492 11826   100     19572 my $blank_after_Z = $last_nonblank_type eq 'Z'
6493             && ( $i == 0 || $rtoken_type->[ $i - 1 ] eq 'b' );
6494 11826         23973 $expecting =
6495             $self->operator_expected( $tok, $next_type, $blank_after_Z );
6496             }
6497              
6498 41501         38919 DEBUG_TOKENIZE && do {
6499             local $LIST_SEPARATOR = ')(';
6500             my @debug_list = (
6501             $last_nonblank_token, $tok,
6502             $next_tok, $brace_depth,
6503             $rbrace_type->[$brace_depth], $paren_depth,
6504             $rparen_type->[$paren_depth],
6505             );
6506             print {*STDOUT} "TOKENIZE:(@debug_list)\n";
6507             };
6508              
6509             # The next token is '$tok'.
6510             # Now we have to define its '$type'
6511              
6512             #------------------------
6513             # END NODE 3: a bare word
6514             #------------------------
6515 41501 100       53814 if ( $pre_type eq 'w' ) {
6516 6708         15008 my $is_last = $self->do_BAREWORD();
6517 6708 100       10807 last if ($is_last);
6518 6699         13676 next;
6519             }
6520              
6521             # Turn off attribute list on first non-blank, non-bareword,
6522             # and non-comment (added to fix c038)
6523 34793         39127 $self->[_in_attribute_list_] = 0;
6524              
6525             #-------------------------------
6526             # END NODE 4: a string of digits
6527             #-------------------------------
6528 34793 100       43931 if ( $pre_type eq 'd' ) {
6529 2514         6033 $self->do_DIGITS();
6530 2514         4332 next;
6531             }
6532              
6533             #------------------------------------------
6534             # END NODE 5: everything else (punctuation)
6535             #------------------------------------------
6536 32279         45073 my $code = $tokenization_code->{$tok};
6537 32279 100       42959 if ($code) {
6538 30014         60482 $code->($self);
6539 30014 100       43043 redo if ($in_quote);
6540             }
6541              
6542             # Check for a non-TERM where a TERM is expected. Note that this
6543             # checks all symbols, even those without a $code (update c566)
6544 29553 100       50925 if ( $expecting == TERM ) {
6545             my $is_not_term =
6546             $type eq ';'
6547             || $type eq ','
6548 11866   100     38281 || $is_binary_operator_type{$type};
6549 11866 100       24769 if ($is_not_term) {
6550 277         732 $self->error_if_expecting_TERM();
6551             }
6552             }
6553             } ## End main tokenizer loop
6554              
6555             # Store the final token
6556 6962 100       10794 if ( $i_tok >= 0 ) {
6557 6773         11163 $routput_token_type->[$i_tok] = $type;
6558 6773         9877 $routput_block_type->[$i_tok] = $block_type;
6559 6773         9819 $routput_type_sequence->[$i_tok] = $type_sequence;
6560 6773         8878 $routput_indent_flag->[$i_tok] = $indent_flag;
6561             }
6562              
6563             # Remember last nonblank values
6564 6962 100 100     17746 if ( $type ne 'b' && $type ne '#' ) {
6565              
6566 6451         7545 $last_last_nonblank_token = $last_nonblank_token;
6567 6451         7203 $last_last_nonblank_type = $last_nonblank_type;
6568              
6569 6451         6991 $last_nonblank_prototype = $prototype;
6570 6451         6955 $last_nonblank_block_type = $block_type;
6571 6451         6957 $last_nonblank_container_type = $container_type;
6572 6451         7240 $last_nonblank_type_sequence = $type_sequence;
6573 6451         6682 $last_nonblank_token = $tok;
6574 6451         7063 $last_nonblank_type = $type;
6575             }
6576              
6577             # reset indentation level if necessary at a sub or package
6578             # in an attempt to recover from a nesting error
6579 6962 50       11151 if ( $level_in_tokenizer < 0 ) {
6580 0 0       0 if ( $input_line =~ /^\s*(sub|package)\s+(\w+)/ ) {
6581 0         0 reset_indentation_level(0);
6582 0         0 $self->brace_warning("resetting level to 0 at $1 $2\n");
6583             }
6584             }
6585              
6586 6962         8952 $self->[_in_quote_] = $in_quote;
6587             $self->[_quote_target_] =
6588             $in_quote
6589             ? (
6590             $matching_end_token{$quote_character}
6591 6962 100       11857 ? $matching_end_token{$quote_character}
    100          
6592             : $quote_character
6593             )
6594             : EMPTY_STRING;
6595 6962         10390 $self->[_rhere_target_list_] = $rhere_target_list;
6596              
6597 6962         8820 return;
6598             } ## end sub tokenizer_main_loop
6599              
6600             sub tokenizer_wrapup_line {
6601 6962     6962 0 10257 my ( $self, $line_of_tokens ) = @_;
6602              
6603             #---------------------------------------------------------
6604             # Package a line of tokens for shipping back to the caller
6605             #---------------------------------------------------------
6606              
6607             # Arrays to hold token values for this line:
6608             my (
6609 6962         9291 @output_levels, @output_block_type, @output_type_sequence,
6610             @output_token_type, @output_tokens,
6611             );
6612              
6613 6962         13382 $line_of_tokens->{_nesting_tokens_0} = $nesting_token_string;
6614              
6615             # Remember starting nesting block string
6616 6962         9228 my $nesting_block_string_0 = $nesting_block_string;
6617              
6618             #-----------------
6619             # Loop over tokens
6620             #-----------------
6621             # $i is the index of the pretoken which starts this full token
6622 6962         7680 foreach my $ii ( @{$routput_token_list} ) {
  6962         10915  
6623              
6624 60209         64541 my $type_i = $routput_token_type->[$ii];
6625              
6626             #----------------------------------------
6627             # Section 1. Handle a non-sequenced token
6628             #----------------------------------------
6629 60209 100       70693 if ( !$routput_type_sequence->[$ii] ) {
6630              
6631             #-------------------------------
6632             # Section 1.1. types ';' and 't'
6633             #-------------------------------
6634             # - output anonymous 'sub' as keyword (type 'k')
6635             # - output __END__, __DATA__, and format as type 'k' instead
6636             # of ';' to make html colors correct, etc.
6637 49157 100       77975 if ( $is_semicolon_or_t{$type_i} ) {
    50          
6638 3201         4093 my $tok_i = $rtokens->[$ii];
6639 3201 100       5978 if ( $is_END_DATA_format_sub{$tok_i} ) {
6640 189         329 $type_i = 'k';
6641             }
6642             }
6643              
6644             #----------------------------------------------
6645             # Section 1.2. Check for an invalid token type.
6646             #----------------------------------------------
6647             # This can happen by running perltidy on non-scripts although
6648             # it could also be bug introduced by programming change. Perl
6649             # silently accepts a 032 (^Z) and takes it as the end
6650             elsif ( !$is_valid_token_type{$type_i} ) {
6651 0 0       0 if ( !$self->[_in_error_] ) {
6652 0         0 my $val = ord($type_i);
6653 0         0 $self->warning(
6654             "unexpected character decimal $val ($type_i) in script\n"
6655             );
6656 0         0 $self->[_in_error_] = 1;
6657             }
6658             }
6659             else {
6660             ## valid token type other than ; and t
6661             }
6662              
6663             #----------------------------------------------------
6664             # Section 1.3. Store values for a non-sequenced token
6665             #----------------------------------------------------
6666 49157         58225 push( @output_levels, $level_in_tokenizer );
6667 49157         55570 push( @output_block_type, EMPTY_STRING );
6668 49157         54120 push( @output_type_sequence, EMPTY_STRING );
6669 49157         69519 push( @output_token_type, $type_i );
6670              
6671             }
6672              
6673             #------------------------------------
6674             # Section 2. Handle a sequenced token
6675             # One of { [ ( ? : ) ] }
6676             #------------------------------------
6677             else {
6678              
6679             # $level_i is the level we will store. Levels of braces are
6680             # set so that the leading braces have a HIGHER level than their
6681             # CONTENTS, which is convenient for indentation.
6682 11052         11753 my $level_i = $level_in_tokenizer;
6683              
6684             # $tok_i is the PRE-token. It only equals the token for symbols
6685 11052         12583 my $tok_i = $rtokens->[$ii];
6686              
6687             # $routput_indent_flag->[$ii] indicates that we need a change
6688             # in level at a nested ternary, as follows
6689             # 1 => at a nested ternary ?
6690             # -1 => at a nested ternary :
6691             # 0 => otherwise
6692              
6693             #--------------------------------------------
6694             # Section 2.1 Handle a level-increasing token
6695             #--------------------------------------------
6696 11052 100       20195 if ( $is_opening_or_ternary_type{$type_i} ) {
    50          
6697              
6698 5526 100       8133 if ( $type_i eq '?' ) {
6699              
6700 193 100       533 if ( $routput_indent_flag->[$ii] > 0 ) {
6701 8         12 $level_in_tokenizer++;
6702              
6703             # break BEFORE '?' in a nested ternary
6704 8         14 $level_i = $level_in_tokenizer;
6705 8         19 $nesting_block_string .= "$nesting_block_flag";
6706              
6707             }
6708             }
6709             else {
6710              
6711 5333         6451 $nesting_token_string .= $tok_i;
6712              
6713 5333 100 100     10958 if ( $type_i eq '{' || $type_i eq 'L' ) {
6714              
6715 4893         5226 $level_in_tokenizer++;
6716              
6717 4893 100       7112 if ( $routput_block_type->[$ii] ) {
6718 1151         1573 $nesting_block_flag = 1;
6719 1151         1713 $nesting_block_string .= '1';
6720             }
6721             else {
6722 3742         4375 $nesting_block_flag = 0;
6723 3742         4983 $nesting_block_string .= '0';
6724             }
6725             }
6726             }
6727             }
6728              
6729             #---------------------------------------------
6730             # Section 2.2. Handle a level-decreasing token
6731             #---------------------------------------------
6732             elsif ( $is_closing_or_ternary_type{$type_i} ) {
6733              
6734 5526 100       8767 if ( $type_i ne ':' ) {
6735 5333         7790 my $char = chop $nesting_token_string;
6736 5333 50       10438 if ( $char ne $matching_start_token{$tok_i} ) {
6737 0         0 $nesting_token_string .= $char . $tok_i;
6738             }
6739             }
6740              
6741 5526 100 100     13152 if (
      100        
      100        
6742             $type_i eq '}'
6743             || $type_i eq 'R'
6744              
6745             # only the second and higher ? : have levels
6746             || $type_i eq ':' && $routput_indent_flag->[$ii] < 0
6747             )
6748             {
6749              
6750 4901         5631 $level_i = --$level_in_tokenizer;
6751              
6752 4901 50       7332 if ( $level_in_tokenizer < 0 ) {
6753 0 0       0 if ( !$self->[_saw_negative_indentation_] ) {
6754 0         0 $self->[_saw_negative_indentation_] = 1;
6755 0         0 $self->warning(
6756             "Starting negative indentation\n");
6757             }
6758             }
6759              
6760             # restore previous level values
6761 4901 50       7406 if ( length($nesting_block_string) > 1 )
6762             { # true for valid script
6763 4901         5393 chop $nesting_block_string;
6764 4901         7863 $nesting_block_flag =
6765             substr( $nesting_block_string, -1 ) eq '1';
6766             }
6767              
6768             }
6769             }
6770              
6771             #-----------------------------------------------------
6772             # Section 2.3. Unexpected sequenced token type - error
6773             #-----------------------------------------------------
6774             else {
6775              
6776             # The tokenizer should only be assigning sequence numbers
6777             # to types { [ ( ? ) ] } :
6778 0         0 DEVEL_MODE && Fault(<<EOM);
6779             unexpected sequence number on token type $type_i with pre-tok=$tok_i
6780             EOM
6781             }
6782              
6783             #------------------------------------------------
6784             # Section 2.4. Store values for a sequenced token
6785             #------------------------------------------------
6786              
6787             # The starting nesting block string, which is used in any .LOG
6788             # output, should include the first token of the line
6789 11052 100       15528 if ( !@output_levels ) {
6790 1804         2386 $nesting_block_string_0 = $nesting_block_string;
6791             }
6792              
6793             # Store values for a sequenced token
6794 11052         14255 push( @output_levels, $level_i );
6795 11052         16186 push( @output_block_type, $routput_block_type->[$ii] );
6796 11052         14237 push( @output_type_sequence, $routput_type_sequence->[$ii] );
6797 11052         18007 push( @output_token_type, $type_i );
6798              
6799             }
6800             } ## End loop to over tokens
6801              
6802             #---------------------
6803             # Post-loop operations
6804             #---------------------
6805              
6806 6962         13120 $line_of_tokens->{_nesting_blocks_0} = $nesting_block_string_0;
6807              
6808             # Form and store the tokens
6809 6962 50       10776 if (@output_levels) {
6810              
6811 6962         7006 my $im = shift @{$routput_token_list};
  6962         9456  
6812 6962         9414 my $offset = $rtoken_map->[$im];
6813 6962         7353 foreach my $ii ( @{$routput_token_list} ) {
  6962         8917  
6814 53247         52494 my $numc = $rtoken_map->[$ii] - $offset;
6815 53247         70998 push( @output_tokens, substr( $input_line, $offset, $numc ) );
6816 53247         49170 $offset += $numc;
6817              
6818             # programming note: it seems most efficient to 'next' out of
6819             # a critical loop like this as early as possible. So instead
6820             # of 'if ( DEVEL_MODE && $numc < 0 )' we write:
6821 53247         52867 next unless (DEVEL_MODE);
6822 0 0       0 next if ( $numc > 0 );
6823              
6824             # Should not happen unless @{$rtoken_map} is corrupted
6825 0         0 Fault("number of characters is '$numc' but should be >0\n");
6826             }
6827              
6828             # Form and store the final token of this line
6829 6962         8810 my $numc = length($input_line) - $offset;
6830 6962         11488 push( @output_tokens, substr( $input_line, $offset, $numc ) );
6831              
6832 6962         8124 if (DEVEL_MODE) {
6833             if ( $numc <= 0 ) {
6834              
6835             # check '$rtoken_map' and '$routput_token_list'
6836             Fault("Number of Characters is '$numc' but should be >0\n");
6837             }
6838              
6839             # Make sure we didn't gain or lose any characters
6840             my $test_line = join EMPTY_STRING, @output_tokens;
6841             if ( $test_line ne $input_line ) {
6842             my $len_input = length($input_line);
6843             my $len_test = length($test_line);
6844              
6845             # check '$rtoken_map' and '$routput_token_list'
6846             Fault(<<EOM);
6847             Reconstructed line difers from input; input_length=$len_input test_length=$len_test
6848             input:'$input_line'
6849             test :'$test_line'
6850             EOM
6851             }
6852             }
6853             }
6854              
6855             # Wrap up this line of tokens for shipping to the Formatter
6856 6962         15763 $line_of_tokens->{_rtoken_type} = \@output_token_type;
6857 6962         13927 $line_of_tokens->{_rtokens} = \@output_tokens;
6858 6962         12071 $line_of_tokens->{_rblock_type} = \@output_block_type;
6859 6962         10501 $line_of_tokens->{_rtype_sequence} = \@output_type_sequence;
6860 6962         12083 $line_of_tokens->{_rlevels} = \@output_levels;
6861              
6862             #-----------------------------------------------------------------
6863             # Compare input indentation with computed levels at closing braces
6864             #-----------------------------------------------------------------
6865             # This may provide a useful hint for error location if the file
6866             # is not balanced in braces. Closing braces are used because they
6867             # have a well-defined indentation and can be processed efficiently.
6868 6962 100       11565 if ( $output_tokens[0] eq '}' ) {
6869              
6870 757         1163 my $blk = $output_block_type[0];
6871 757 100 100     3772 if (
      66        
6872             (
6873             # builtin block types without continuation indentation
6874             $is_zero_continuation_block_type{$blk}
6875              
6876             # or a named sub, but skip sub aliases for efficiency,
6877             # since this is just for diagnostic info
6878             || substr( $blk, 0, 4 ) eq 'sub '
6879             )
6880              
6881             # and we are not in format skipping
6882             && !$self->[_in_format_skipping_]
6883             )
6884             {
6885              
6886             # subtract 1 space for newline in untrimmed line
6887 415         686 my $untrimmed_input_line = $line_of_tokens->{_line_text};
6888 415         786 my $space_count =
6889             length($untrimmed_input_line) - length($input_line) - 1;
6890              
6891             # check for tabs
6892 415 100 100     1362 if ( $space_count
6893             && ord( substr( $untrimmed_input_line, 0, 1 ) ) == ORD_TAB )
6894             {
6895 15 50       107 if ( $untrimmed_input_line =~ /^(\t+)?(\s+)?/ ) {
6896 15 50       51 if ($1) { $space_count += length($1) * $tabsize }
  15         45  
6897 15 100       45 if ($2) { $space_count += length($2) }
  1         2  
6898             }
6899             }
6900              
6901             # '$guess' = the level according to indentation
6902 415         892 my $guess = int( $space_count / $rOpts_indent_columns );
6903              
6904             # subtract 1 level from guess for --indent-closing-brace
6905 415 100       872 $guess -= 1 if ($rOpts_indent_closing_brace);
6906              
6907             # subtract 1 from $level for each non-indenting brace level
6908 415         529 my $adjust = @{ $self->[_rnon_indenting_brace_stack_] };
  415         674  
6909              
6910 415         589 my $level = $output_levels[0];
6911              
6912             # find the difference between expected and indentation guess
6913 415         664 my $level_diff = $level - $adjust - $guess;
6914              
6915 415         594 my $rhash = $self->[_rclosing_brace_indentation_hash_];
6916              
6917             # results are only valid if we guess correctly at the
6918             # first spaced brace
6919 415 100 100     1304 if ( $space_count && !defined( $rhash->{valid} ) ) {
6920 83         175 $rhash->{valid} = !$level_diff;
6921             }
6922              
6923             # save the result
6924 415         685 my $rhistory_line_number = $rhash->{rhistory_line_number};
6925 415         638 my $rhistory_level_diff = $rhash->{rhistory_level_diff};
6926 415         640 my $rhistory_anchor_point = $rhash->{rhistory_anchor_point};
6927              
6928 415 100       794 if ( $rhistory_level_diff->[-1] != $level_diff ) {
6929              
6930             # Patch for non-indenting-braces: if we guess zero and
6931             # match before all non-indenting braces have been found,
6932             # it means that we would need negative indentation to
6933             # match if/when the brace is found. So we have a problem
6934             # from here on. We indicate this with a value 2 instead
6935             # of 1 as a signal to stop outputting the table here.
6936 55         92 my $anchor = 1;
6937 55 50 66     269 if ( $guess == 0 && $adjust > 0 ) { $anchor = 2 }
  0         0  
6938              
6939             # add an anchor point
6940 55         90 push @{$rhistory_level_diff}, $level_diff;
  55         92  
6941 55         83 push @{$rhistory_line_number}, $input_line_number;
  55         106  
6942 55         97 push @{$rhistory_anchor_point}, $anchor;
  55         131  
6943             }
6944             else {
6945              
6946             # add a movable point following an anchor point
6947 360 100       775 if ( $rhistory_anchor_point->[-1] ) {
6948 162         260 push @{$rhistory_level_diff}, $level_diff;
  162         311  
6949 162         248 push @{$rhistory_line_number}, $input_line_number;
  162         293  
6950 162         248 push @{$rhistory_anchor_point}, 0;
  162         377  
6951             }
6952              
6953             # extend a movable point
6954             else {
6955 198         403 $rhistory_line_number->[-1] = $input_line_number;
6956             }
6957             }
6958             }
6959             }
6960              
6961 6962         12671 return;
6962             } ## end sub tokenizer_wrapup_line
6963              
6964             } ## end tokenize_this_line
6965              
6966             #######################################################################
6967             # Tokenizer routines which assist in identifying token types
6968             #######################################################################
6969              
6970             # Define Global '%op_expected_table'
6971             # = hash table of operator expected values based on last nonblank token
6972              
6973             # exceptions to perl's weird parsing rules after type 'Z'
6974             my %is_weird_parsing_rule_exception;
6975              
6976             my %is_paren_dollar;
6977              
6978             my %is_n_v;
6979              
6980             BEGIN {
6981              
6982             # Always expecting TERM following these types:
6983             # note: this is identical to '@value_requestor_type' defined later.
6984             # Fix for c250: add new type 'P' for package (expecting VERSION or {}
6985             # after package NAMESPACE, so expecting TERM)
6986             # Fix for c250: add new type 'S' for sub (not expecting operator)
6987 44     44   673 my @q = qw#
6988             ; ! + x & ? F J - p / Y : % f U ~ A G j L P S * . | ^ < = [ m { > t
6989             || >= != mm *= => .. !~ == && |= .= pp -= =~ += <= %= ^= x= ~~ ** << /=
6990             &= // >> ~. &. |. ^.
6991             ... **= <<= >>= &&= ||= //= <=> !~~ &.= |.= ^.= <<~
6992             #;
6993 44         188 push @q, BACKSLASH;
6994 44         118 push @q, COMMA;
6995 44         102 push @q, '('; # for completeness, not currently a token type
6996 44         106 push @q, '->'; # was previously in UNKNOWN
6997 44         2355 $op_expected_table{$_} = TERM for @q;
6998              
6999             # No UNKNOWN table types:
7000             # removed '->' for c030, now always TERM
7001             # removed 'w' for c392 to allow use of 'function_count' info in the sub
7002              
7003             # Always expecting OPERATOR ...
7004             # 'n' and 'v' are currently excluded because they might be VERSION numbers
7005             # 'i' is currently excluded because it might be a package
7006             # 'q' is currently excluded because it might be a prototype
7007             # Fix for c030: removed '->' from this list:
7008             # Fix for c250: added 'i' because new type 'P' was added
7009 44         250 @q = qw( -- C h R ++ ] Q <> i );
7010 44         85 push @q, ')';
7011 44         541 $op_expected_table{$_} = OPERATOR for @q;
7012              
7013             # Fix for git #62: added '*' and '%'
7014 44         135 @q = qw( < ? * % );
7015 44         125 $is_weird_parsing_rule_exception{$_} = 1 for @q;
7016              
7017 44         93 @q = qw<) $>;
7018 44         102 $is_paren_dollar{$_} = 1 for @q;
7019              
7020 44         104 @q = qw( n v );
7021 44         1416 $is_n_v{$_} = 1 for @q;
7022              
7023             } ## end BEGIN
7024              
7025 44     44   341 use constant DEBUG_OPERATOR_EXPECTED => 0;
  44         78  
  44         96456  
7026              
7027             sub operator_expected {
7028              
7029 11968     11968 0 19531 my ( $self, $tok, $next_type, $blank_after_Z ) = @_;
7030              
7031             # Returns a parameter indicating what types of tokens can occur next
7032              
7033             # Call format:
7034             # $op_expected =
7035             # $self->operator_expected( $tok, $next_type, $blank_after_Z );
7036             # where
7037             # $tok is the current token
7038             # $next_type is the type of the next token (blank or not)
7039             # $blank_after_Z = flag for guessing after a type 'Z':
7040             # true if $tok follows type 'Z' with intermediate blank
7041             # false if $tok follows type 'Z' with no intermediate blank
7042             # ignored if $tok does not follow type 'Z'
7043              
7044             # Many perl symbols have two or more meanings. For example, '<<'
7045             # can be a shift operator or a here-doc operator. The
7046             # interpretation of these symbols depends on the current state of
7047             # the tokenizer, which may either be expecting a term or an
7048             # operator. For this example, a << would be a shift if an OPERATOR
7049             # is expected, and a here-doc if a TERM is expected. This routine
7050             # is called to make this decision for any current token. It returns
7051             # one of three possible values:
7052             #
7053             # OPERATOR - operator expected (or at least, not a term)
7054             # UNKNOWN - can't tell
7055             # TERM - a term is expected (or at least, not an operator)
7056             #
7057             # The decision is based on what has been seen so far. This
7058             # information is stored in the "$last_nonblank_type" and
7059             # "$last_nonblank_token" variables. For example, if the
7060             # $last_nonblank_type is '=~', then we are expecting a TERM, whereas
7061             # if $last_nonblank_type is 'n' (numeric), we are expecting an
7062             # OPERATOR.
7063             #
7064             # If a UNKNOWN is returned, the calling routine must guess. A major
7065             # goal of this tokenizer is to minimize the possibility of returning
7066             # UNKNOWN, because a wrong guess can spoil the formatting of a
7067             # script.
7068             #
7069             # Adding NEW_TOKENS: it is critically important that this routine be
7070             # updated to allow it to determine if an operator or term is to be
7071             # expected after the new token. Doing this simply involves adding
7072             # the new token character to one of the regexes in this routine or
7073             # to one of the hash lists
7074             # that it uses, which are initialized in the BEGIN section.
7075             # USES GLOBAL VARIABLES: $last_nonblank_type, $last_nonblank_token,
7076             # $statement_type
7077              
7078             # When possible, token types should be selected such that we can determine
7079             # the 'operator_expected' value by a simple hash lookup. If there are
7080             # exceptions, that is an indication that a new type is needed.
7081              
7082             #--------------------------------------------
7083             # Section 1: Table lookup will get most cases
7084             #--------------------------------------------
7085              
7086             # Many types are can be obtained by a table lookup. This typically handles
7087             # more than half of the calls. For speed, the caller may try table lookup
7088             # first before calling this sub.
7089 11968         14647 my $op_expected = $op_expected_table{$last_nonblank_type};
7090 11968 100       16835 if ( defined($op_expected) ) {
7091             DEBUG_OPERATOR_EXPECTED
7092 78         99 && print {*STDOUT}
7093             "OPERATOR_EXPECTED: Table Lookup; returns $op_expected for last type $last_nonblank_type token $last_nonblank_token\n";
7094 78         175 return $op_expected;
7095             }
7096              
7097             DEBUG_OPERATOR_EXPECTED
7098 11890         11940 && print {*STDOUT}
7099             "OPERATOR_EXPECTED: in hardwired table for last type $last_nonblank_type token $last_nonblank_token\n";
7100              
7101             #---------------------------------------------
7102             # Section 2: Handle special cases if necessary
7103             #---------------------------------------------
7104              
7105             # Types 'k', '}' and 'Z' depend on context
7106             # Types 'n', 'v', 'q' also depend on context.
7107              
7108             # identifier...
7109             # Fix for c250: removed coding for type 'i' because 'i' and new type 'P'
7110             # are now done by hash table lookup
7111              
7112             #--------------------
7113             # Section 2A: keyword
7114             #--------------------
7115 11890 100       17913 if ( $last_nonblank_type eq 'k' ) {
7116              
7117             # keywords expecting TERM:
7118 3117 100       6914 if ( $expecting_term_token{$last_nonblank_token} ) {
7119              
7120             # Exceptions from TERM:
7121              
7122             # // may follow perl functions which may be unary operators
7123             # see test file dor.t (defined or);
7124 2997 100 100     5427 if (
      100        
7125             $tok eq '/'
7126             && $next_type eq '/'
7127             && $is_keyword_rejecting_slash_as_pattern_delimiter{
7128             $last_nonblank_token}
7129             )
7130             {
7131 1         2 return OPERATOR;
7132             }
7133              
7134             # Patch to allow a ? following 'split' to be a deprecated pattern
7135             # delimiter. This patch is coordinated with the omission of split
7136             # from the list
7137             # %is_keyword_rejecting_question_as_pattern_delimiter. This patch
7138             # will force perltidy to guess.
7139 2996 50 66     5703 if ( $tok eq '?'
7140             && $last_nonblank_token eq 'split' )
7141             {
7142 0         0 return UNKNOWN;
7143             }
7144              
7145 2996         5401 return TERM;
7146             }
7147              
7148             # keywords expecting OPERATOR:
7149 120 100       365 if ( $expecting_operator_token{$last_nonblank_token} ) {
7150 7         11 return OPERATOR;
7151             }
7152              
7153 113         251 return TERM;
7154              
7155             } ## end type 'k'
7156              
7157             #------------------------------------
7158             # Section 2B: Closing container token
7159             #------------------------------------
7160              
7161             # Note that the actual token for type '}' may also be a ')'.
7162              
7163             # Also note that $last_nonblank_token is not the token corresponding to
7164             # $last_nonblank_type when the type is a closing container. In that
7165             # case it is the token before the corresponding opening container token.
7166             # So for example, for this snippet
7167             # $a = do { BLOCK } / 2;
7168             # the $last_nonblank_token is 'do' when $last_nonblank_type eq '}'.
7169              
7170 8773 100       13940 if ( $last_nonblank_type eq '}' ) {
7171              
7172             #-------------------------------------------
7173             # Section 2B1: Closing structural ')' or ']'
7174             #-------------------------------------------
7175 4187 100 100     9981 if ( $last_nonblank_token eq ')' || $last_nonblank_token eq ']' ) {
7176 2814         4977 return OPERATOR;
7177             }
7178              
7179             #-------------------------------------
7180             # Section 2B2: Closing block brace '}'
7181             #-------------------------------------
7182 1373         2327 my $blk = $rbrace_type->[ $brace_depth + 1 ];
7183              
7184             # Non-blocks
7185 1373 100       2412 if ( !defined($blk) ) {
7186 2         5 return OPERATOR;
7187             }
7188              
7189             # Unidentified block type
7190 1371 100       2508 if ( !$blk ) {
7191 367         707 return UNKNOWN;
7192             }
7193              
7194             # Blocks followed by a TERM
7195 1004 100 100     7830 if ( $is_zero_continuation_block_type{$blk}
      100        
      100        
      100        
      100        
      100        
      66        
      100        
7196             || $is_sort_map_grep{$blk}
7197             || $is_grep_alias{$blk}
7198             || substr( $blk, -1, 1 ) eq ':' && $blk =~ /^\w+:$/
7199             || substr( $blk, 0, 3 ) eq 'sub' && $blk =~ /^sub\s/
7200             || substr( $blk, 0, 7 ) eq 'package' && $blk =~ /^package\s/ )
7201             {
7202 660         1480 return TERM;
7203             }
7204              
7205             # Blocks followed by an OPERATOR
7206             # do eval sub
7207 344 100 100     1371 if ( $is_block_operator{$blk}
7208             || $is_sub{$blk} )
7209             {
7210 276         593 return OPERATOR;
7211             }
7212              
7213             # Any other block type is marked UNKNOWN to be safe (c566).
7214             # For example, a block type marked ';' could be a hash ref:
7215             # { map { $_ => 'x' } keys %main:: } ~~ \%main::;
7216             # The tokenizer would have to analyze the contents to distinguish
7217             # between a block closure and a hash ref brace in this case. So mark
7218             # this as UNKNOWN and let the lower level routines figure it out.
7219 68         150 return UNKNOWN;
7220             }
7221              
7222             #-------------------------------
7223             # Section 2C: number or v-string
7224             #-------------------------------
7225             # An exception is for VERSION numbers a 'use' statement. It has the format
7226             # use Module VERSION LIST
7227             # We could avoid this exception by writing a special sub to parse 'use'
7228             # statements and perhaps mark these numbers with a new type V (for VERSION)
7229 4586 100       8427 if ( $is_n_v{$last_nonblank_type} ) {
7230 2627 100       4276 if ( $statement_type eq 'use' ) {
7231 11         27 return UNKNOWN;
7232             }
7233 2616         4227 return OPERATOR;
7234             }
7235              
7236             #---------------------
7237             # Section 2D: qw quote
7238             #---------------------
7239             # TODO: labeled prototype words would better be given type 'A' or maybe
7240             # 'J'; not 'q'; or maybe mark as type 'Y'?
7241 1959 100       3675 if ( $last_nonblank_type eq 'q' ) {
7242 160 50       471 if ( $last_nonblank_token eq 'prototype' ) {
7243 0         0 return TERM;
7244             }
7245              
7246             # update for --use-feature=class (rt145706):
7247             # Look for class VERSION after possible attribute, as in
7248             # class Example::Subclass : isa(Example::Base) 1.345 { ... }
7249 160 100       391 if ( $statement_type =~ /^package\b/ ) {
7250 3         8 return TERM;
7251             }
7252              
7253             # everything else
7254 157         316 return OPERATOR;
7255             }
7256              
7257             #---------------------
7258             # Section 2E: bareword
7259             #---------------------
7260 1799 100       3171 if ( $last_nonblank_type eq 'w' ) {
7261              
7262             # It is safest to return UNKNOWN if a possible ? pattern delimiter may
7263             # follow (git #32, c469) and let the guess algorithm handle it.
7264 1750 100       3021 if ( $tok eq '?' ) { return UNKNOWN }
  7         16  
7265              
7266             # see if this has been seen in the role of a function taking args
7267 1743         2881 my $rinfo = $self->[_rbareword_info_]->{$current_package};
7268 1743 100       2950 if ($rinfo) {
7269 1228         1818 $rinfo = $rinfo->{$last_nonblank_token};
7270 1228 100       2184 if ($rinfo) {
7271 317         502 my $function_count = $rinfo->{function_count};
7272 317 100 66     1051 if ( $function_count && $function_count > 0 ) { return TERM }
  135         336  
7273             }
7274             }
7275 1608         2995 return UNKNOWN;
7276             }
7277              
7278             #-----------------------------------
7279             # Section 2F: file handle or similar
7280             #-----------------------------------
7281 49 100       131 if ( $last_nonblank_type eq 'Z' ) {
7282              
7283             # angle.t
7284 45 100       170 if ( $last_nonblank_token =~ /^\w/ ) {
7285 2         4 return UNKNOWN;
7286             }
7287              
7288             # Exception to weird parsing rules for 'x(' ... see case b1205:
7289             # In something like 'print $vv x(...' the x is an operator;
7290             # Likewise in 'print $vv x$ww' the x is an operator (case b1207)
7291             # otherwise x follows the weird parsing rules.
7292 43 50 33     151 if ( $tok eq 'x' && $next_type =~ /^[\(\$\@\%]$/ ) {
7293 0         0 return OPERATOR;
7294             }
7295              
7296             # The 'weird parsing rules' of next section do not work for '<' and '?'
7297             # It is best to mark them as unknown. Test case:
7298             # print $fh <DATA>;
7299 43 100       132 if ( $is_weird_parsing_rule_exception{$tok} ) {
7300 4         8 return UNKNOWN;
7301             }
7302              
7303             # For possible file handle like "$a", Perl uses weird parsing rules.
7304             # For example:
7305             # print $a/2,"/hi"; - division
7306             # print $a / 2,"/hi"; - division
7307             # print $a/ 2,"/hi"; - division
7308             # print $a /2,"/hi"; - pattern (and error)!
7309             # Some examples where this logic works okay, for '&','*','+':
7310             # print $fh &xsi_protos(@mods);
7311             # my $x = new $CompressClass *FH;
7312             # print $OUT +( $count % 15 ? ", " : "\n\t" );
7313 39 50 66     127 if ( $blank_after_Z
7314             && $next_type ne 'b' )
7315             {
7316 0         0 return TERM;
7317             }
7318              
7319             # Note that '?' and '<' have been moved above
7320             # ( $tok =~ /^([x\/\+\-\*\%\&\.\?\<]|\>\>)$/ ) {
7321 39 100       165 if ( $tok =~ /^([x\/\+\-\*\%\&\.]|\>\>)$/ ) {
7322              
7323             # Do not complain in 'use' statements, which have special syntax.
7324             # For example, from RT#130344:
7325             # use lib $FindBin::Bin . '/lib';
7326 9 50       26 if ( $statement_type ne 'use' ) {
7327 9         31 $self->complain(
7328             "operator in possible indirect object location not recommended\n"
7329             );
7330             }
7331 9         17 return OPERATOR;
7332             }
7333              
7334             # all other cases
7335              
7336 30         72 return UNKNOWN;
7337             }
7338              
7339             #--------------------------
7340             # Section 2F: anything else
7341             #--------------------------
7342 4         9 return UNKNOWN;
7343              
7344             } ## end sub operator_expected
7345              
7346             sub new_statement_ok {
7347              
7348             # Returns:
7349             # true if a new statement can begin here
7350             # false otherwise
7351              
7352             # USES GLOBAL VARIABLES: $last_nonblank_token, $last_nonblank_type,
7353             # $brace_depth, $rbrace_type
7354              
7355             # Uses:
7356             # - See if a 'class' statement can occur here
7357             # - See if a keyword begins at a new statement; i.e. is an 'if' a
7358             # block if or a trailing if? Also see if 'format' starts a statement.
7359             # - Decide if a ':' is part of a statement label (not a ternary)
7360              
7361             # Curly braces are tricky because some small blocks do not get marked as
7362             # blocks..
7363              
7364             # if it follows an opening curly brace..
7365 551 100 100 551 0 1945 if ( $last_nonblank_token eq '{' ) {
    100          
7366              
7367             # The safe thing is to return true in all cases because:
7368             # - a ternary ':' cannot occur here
7369             # - an 'if' here, for example, cannot be a trailing if
7370             # See test case c231 for an example.
7371             # This works but could be improved, if necessary, by returning
7372             # 'false' at obvious non-blocks.
7373 70         198 return 1;
7374             }
7375              
7376             # if it follows a closing code block curly brace..
7377             elsif ($last_nonblank_token eq '}'
7378             && $last_nonblank_type eq $last_nonblank_token )
7379             {
7380              
7381             # A new statement can follow certain closing block braces ...
7382             # Previously, a true was always returned, and this worked ok.
7383             # Update c443: now we return false for certain blocks which must be
7384             # followed by a ';'. See comments elsewhere on
7385             # '%is_zero_continuation_block_type'. The value of $brace_depth has
7386             # also been corrected, it was off by 1.
7387 117         241 my $block_type = $rbrace_type->[ $brace_depth + 1 ];
7388             return $block_type
7389 117   66     576 && !$is_sort_map_grep_eval_do_sub{$block_type};
7390             }
7391              
7392             # otherwise, it is a label if and only if it follows a ';' (real or fake)
7393             # or another label
7394             else {
7395 364   100     1652 return ( $last_nonblank_type eq ';' || $last_nonblank_type eq 'J' );
7396             }
7397             } ## end sub new_statement_ok
7398              
7399             sub code_block_type {
7400              
7401 1480     1480 0 3015 my ( $self, $i, $rtokens, $rtoken_type, $max_token_index ) = @_;
7402              
7403             # Decide if this is a block of code, and its type.
7404             # Must be called only when $type = $token = '{'
7405             # The problem is to distinguish between the start of a block of code
7406             # and the start of an anonymous hash reference
7407             # Returns "" if not code block, otherwise returns 'last_nonblank_token'
7408             # to indicate the type of code block. (For example, 'last_nonblank_token'
7409             # might be 'if' for an if block, 'else' for an else block, etc).
7410             # USES GLOBAL VARIABLES: $last_nonblank_token, $last_nonblank_type,
7411             # $last_nonblank_block_type, $brace_depth, $rbrace_type
7412              
7413             # handle case of multiple '{'s
7414              
7415             #print "BLOCK_TYPE EXAMINING: type=$last_nonblank_type tok=$last_nonblank_token\n";
7416              
7417 1480 100 66     13948 if ( $last_nonblank_token eq '{'
    100 66        
    100 66        
    100 100        
    100 66        
    100 66        
    50          
    50          
    100          
    100          
    100          
7418             && $last_nonblank_type eq $last_nonblank_token )
7419             {
7420              
7421             # opening brace where a statement may appear is probably
7422             # a code block but might be and anonymous hash reference
7423 98 50       223 if ( $rbrace_type->[$brace_depth] ) {
7424 98         227 return $self->decide_if_code_block( $i, $rtokens, $rtoken_type,
7425             $max_token_index );
7426             }
7427              
7428             # cannot start a code block within an anonymous hash
7429             else {
7430 0         0 return EMPTY_STRING;
7431             }
7432             }
7433              
7434             elsif ( $last_nonblank_token eq ';' ) {
7435              
7436             # an opening brace where a statement may appear is probably
7437             # a code block but might be and anonymous hash reference
7438 55         191 return $self->decide_if_code_block( $i, $rtokens, $rtoken_type,
7439             $max_token_index );
7440             }
7441              
7442             # handle case of '}{'
7443             elsif ($last_nonblank_token eq '}'
7444             && $last_nonblank_type eq $last_nonblank_token )
7445             {
7446              
7447             # a } { situation ...
7448             # could be hash reference after code block..(blktype1.t)
7449 10 50       26 if ($last_nonblank_block_type) {
7450 10         27 return $self->decide_if_code_block( $i, $rtokens, $rtoken_type,
7451             $max_token_index );
7452             }
7453              
7454             # must be a block if it follows a closing hash reference
7455             else {
7456 0         0 return $last_nonblank_token;
7457             }
7458             }
7459              
7460             #--------------------------------------------------------------
7461             # NOTE: braces after type characters start code blocks, but for
7462             # simplicity these are not identified as such. See also
7463             # sub is_non_structural_brace.
7464             #--------------------------------------------------------------
7465              
7466             ## elsif ( $last_nonblank_type eq 't' ) {
7467             ## return $last_nonblank_token;
7468             ## }
7469              
7470             # brace after label:
7471             elsif ( $last_nonblank_type eq 'J' ) {
7472 34         88 return $last_nonblank_token;
7473             }
7474              
7475             # otherwise, see if a block must follow the previous token (such as 'if'):
7476             elsif ($is_code_block_token{$last_nonblank_token}
7477             || $is_grep_alias{$last_nonblank_token} )
7478             {
7479              
7480             # Bug Patch: Note that the opening brace after the 'if' in the following
7481             # snippet is an anonymous hash ref and not a code block!
7482             # print 'hi' if { x => 1, }->{x};
7483             # We can identify this situation because the last nonblank type
7484             # will be a keyword (instead of a closing paren)
7485 559 50 33     1982 if (
      66        
7486             $last_nonblank_type eq 'k'
7487             && ( $last_nonblank_token eq 'if'
7488             || $last_nonblank_token eq 'unless' )
7489             )
7490             {
7491 0         0 return EMPTY_STRING;
7492             }
7493             else {
7494 559         1358 return $last_nonblank_token;
7495             }
7496             }
7497              
7498             # or a sub or package BLOCK
7499             # Fixed for c250 to include new package type 'P', and change 'i' to 'S'
7500             elsif (
7501             $last_nonblank_type eq 'P'
7502             || $last_nonblank_type eq 'S'
7503             || ( $last_nonblank_type eq 't'
7504             && substr( $last_nonblank_token, 0, 3 ) eq 'sub' )
7505             )
7506             {
7507 366         975 return $last_nonblank_token;
7508             }
7509              
7510             elsif ( $statement_type =~ /^(sub|package)\b/ ) {
7511 0         0 return $statement_type;
7512             }
7513              
7514             # user-defined subs with block parameters (like grep/map/eval)
7515             elsif ( $last_nonblank_type eq 'G' ) {
7516 0         0 return $last_nonblank_token;
7517             }
7518              
7519             # check bareword
7520             elsif ( $last_nonblank_type eq 'w' ) {
7521              
7522             # check for syntax 'use MODULE LIST'
7523             # This fixes b1022 b1025 b1027 b1028 b1029 b1030 b1031
7524 24 100       67 return EMPTY_STRING if ( $statement_type eq 'use' );
7525              
7526 23         82 return $self->decide_if_code_block( $i, $rtokens, $rtoken_type,
7527             $max_token_index );
7528             }
7529              
7530             # Patch for bug # RT #94338 reported by Daniel Trizen
7531             # for-loop in a parenthesized block-map triggering an error message:
7532             # map( { foreach my $item ( '0', '1' ) { print $item} } qw(a b c) );
7533             # Check for a code block within a parenthesized function call
7534             elsif ( $last_nonblank_token eq '(' ) {
7535 87         167 my $paren_type = $rparen_type->[$paren_depth];
7536              
7537             # /^(map|grep|sort)$/
7538 87 100 66     343 if ( $paren_type && $is_sort_map_grep{$paren_type} ) {
7539              
7540             # We will mark this as a code block but use type 't' instead
7541             # of the name of the containing function. This will allow for
7542             # correct parsing but will usually produce better formatting.
7543             # Braces with block type 't' are not broken open automatically
7544             # in the formatter as are other code block types, and this usually
7545             # works best.
7546 1         2 return 't'; # (Not $paren_type)
7547             }
7548             else {
7549 86         203 return EMPTY_STRING;
7550             }
7551             }
7552              
7553             # handle unknown syntax ') {'
7554             # we previously appended a '()' to mark this case
7555             elsif ( $last_nonblank_token =~ /\(\)$/ ) {
7556 16         57 return $last_nonblank_token;
7557             }
7558              
7559             # anything else must be anonymous hash reference
7560             else {
7561 231         490 return EMPTY_STRING;
7562             }
7563             } ## end sub code_block_type
7564              
7565             sub decide_if_code_block {
7566              
7567             # USES GLOBAL VARIABLES: $last_nonblank_token
7568 186     186 0 379 my ( $self, $i, $rtokens, $rtoken_type, $max_token_index ) = @_;
7569              
7570 186         583 my ( $next_nonblank_token, $i_next_uu ) =
7571             $self->find_next_nonblank_token( $i, $rtokens, $max_token_index );
7572              
7573             # we are at a '{' where a statement may appear.
7574             # We must decide if this brace starts an anonymous hash or a code
7575             # block.
7576             # return "" if anonymous hash, and $last_nonblank_token otherwise
7577              
7578             # initialize to be code BLOCK
7579 186         325 my $code_block_type = $last_nonblank_token;
7580              
7581             # Check for the common case of an empty anonymous hash reference:
7582             # Maybe something like sub { { } }
7583 186 100       364 if ( $next_nonblank_token eq '}' ) {
7584 5         9 $code_block_type = EMPTY_STRING;
7585             }
7586              
7587             else {
7588              
7589             # To guess if this '{' is an anonymous hash reference, look ahead
7590             # and test as follows:
7591             #
7592             # it is a hash reference if next come:
7593             # - a string or digit followed by a comma or =>
7594             # - bareword followed by =>
7595             # otherwise it is a code block
7596             #
7597             # Examples of anonymous hash ref:
7598             # {'aa',};
7599             # {1,2}
7600             #
7601             # Examples of code blocks:
7602             # {1; print "hello\n", 1;}
7603             # {$a,1};
7604              
7605             # We are only going to look ahead one more (nonblank/comment) line.
7606             # Strange formatting could cause a bad guess, but that's unlikely.
7607 181         300 my @pre_types;
7608             my @pre_tokens;
7609              
7610             # Ignore the rest of this line if it is a side comment
7611 181 100       404 if ( $next_nonblank_token ne '#' ) {
7612 156         442 @pre_types = @{$rtoken_type}[ $i + 1 .. $max_token_index ];
  156         696  
7613 156         353 @pre_tokens = @{$rtokens}[ $i + 1 .. $max_token_index ];
  156         766  
7614             }
7615              
7616             # Here 20 is arbitrary but generous, and prevents wasting lots of time
7617             # in mangled files
7618 181         600 my ( $rpre_tokens, $rpre_types ) =
7619             $self->peek_ahead_for_n_nonblank_pre_tokens(20);
7620 181 100 66     463 if ( defined($rpre_types) && @{$rpre_types} ) {
  173         445  
7621 173         250 push @pre_types, @{$rpre_types};
  173         556  
7622 173         248 push @pre_tokens, @{$rpre_tokens};
  173         694  
7623             }
7624              
7625             # put a sentinel token to simplify stopping the search
7626 181         296 push @pre_types, '}';
7627 181         258 push @pre_types, '}';
7628              
7629 181         245 my $jbeg = 0;
7630 181 100       422 $jbeg = 1 if ( $pre_types[0] eq 'b' );
7631              
7632             # first look for one of these
7633             # - bareword
7634             # - bareword with leading -
7635             # - digit
7636             # - quoted string
7637 181         293 my $j = $jbeg;
7638 181 100 33     1087 if ( $pre_types[$j] =~ /^[\'\"]/ ) {
    100          
    100          
    50          
7639              
7640             # find the closing quote; don't worry about escapes
7641 1         2 my $quote_mark = $pre_types[$j];
7642 1         4 foreach my $k ( $j + 1 .. @pre_types - 2 ) {
7643 1 50       3 if ( $pre_types[$k] eq $quote_mark ) {
7644 1         1 $j = $k + 1;
7645 1         3 last;
7646             }
7647             }
7648             }
7649             elsif ( $pre_types[$j] eq 'd' ) {
7650 8         12 $j++;
7651             }
7652             elsif ( $pre_types[$j] eq 'w' ) {
7653 78         160 $j++;
7654             }
7655             elsif ( $pre_types[$j] eq '-' && $pre_types[ ++$j ] eq 'w' ) {
7656 0         0 $j++;
7657             }
7658             else {
7659             ## none of the above
7660             }
7661 181 100       387 if ( $j > $jbeg ) {
7662              
7663 87 100       232 $j++ if ( $pre_types[$j] eq 'b' );
7664              
7665             # Patched for RT #95708
7666 87 100 33     541 if (
      66        
      66        
7667              
7668             # it is a comma which is not a pattern delimiter except for qw
7669             (
7670             $pre_types[$j] eq COMMA
7671             && !$is_q_qq_qx_qr_s_y_tr_m{ $pre_tokens[$jbeg] }
7672             )
7673              
7674             # or a =>
7675             || ( $pre_types[$j] eq '=' && $pre_types[ ++$j ] eq '>' )
7676             )
7677             {
7678 18         30 $code_block_type = EMPTY_STRING;
7679             }
7680             }
7681              
7682 181 100       496 if ($code_block_type) {
7683              
7684             # Patch for cases b1085 b1128: It is uncertain if this is a block.
7685             # If this brace follows a bareword, then append a space as a signal
7686             # to the formatter that this may not be a block brace. To find the
7687             # corresponding code in Formatter.pm search for 'b1085'.
7688             # But not for the word 'method': fixes c534; this will cause the
7689             # formatter to mark an asub block instead of a sub block.
7690 163 100 66     1158 if ( $code_block_type =~ /^\w/ && $code_block_type ne 'method' ) {
7691 20         130 $code_block_type .= SPACE;
7692             }
7693             }
7694             }
7695              
7696 186         534 return $code_block_type;
7697             } ## end sub decide_if_code_block
7698              
7699             sub report_unexpected {
7700              
7701             # report unexpected token type and show where it is
7702             # USES GLOBAL VARIABLES: (none)
7703 0     0 0 0 my ( $self, $rcall_hash ) = @_;
7704              
7705 0         0 my $found = $rcall_hash->{found};
7706 0         0 my $expecting = $rcall_hash->{expecting};
7707 0         0 my $i_tok = $rcall_hash->{i_tok};
7708 0         0 my $last_nonblank_i = $rcall_hash->{last_nonblank_i};
7709 0         0 my $rpretoken_map = $rcall_hash->{rpretoken_map};
7710 0         0 my $rpretoken_type = $rcall_hash->{rpretoken_type};
7711 0         0 my $input_line = $rcall_hash->{input_line};
7712              
7713 0 0       0 if ( ++$self->[_unexpected_error_count_] <= MAX_NAG_MESSAGES ) {
7714 0         0 my $msg = "found $found where $expecting expected";
7715 0         0 my $pos = $rpretoken_map->[$i_tok];
7716 0         0 $self->interrupt_logfile();
7717 0         0 my $input_line_number = $self->[_last_line_number_];
7718 0         0 my ( $offset, $numbered_line, $underline ) =
7719             make_numbered_line( $input_line_number, $input_line, $pos );
7720 0         0 $underline = write_on_underline( $underline, $pos - $offset, '^' );
7721              
7722 0         0 my $trailer = EMPTY_STRING;
7723 0 0 0     0 if ( ( $i_tok > 0 ) && ( $last_nonblank_i >= 0 ) ) {
7724 0         0 my $pos_prev = $rpretoken_map->[$last_nonblank_i];
7725 0         0 my $num;
7726 0 0       0 if ( $rpretoken_type->[ $i_tok - 1 ] eq 'b' ) {
7727 0         0 $num = $rpretoken_map->[ $i_tok - 1 ] - $pos_prev;
7728             }
7729             else {
7730 0         0 $num = $pos - $pos_prev;
7731             }
7732 0 0       0 if ( $num > 40 ) { $num = 40; $pos_prev = $pos - 40; }
  0         0  
  0         0  
7733              
7734             $underline =
7735 0         0 write_on_underline( $underline, $pos_prev - $offset, '-' x $num );
7736 0         0 $trailer = " (previous token underlined)";
7737             }
7738 0         0 $underline =~ s/\s+$//;
7739 0         0 $self->warning( $numbered_line . "\n" );
7740 0         0 $self->warning( $underline . "\n" );
7741 0         0 $self->warning( $msg . $trailer . "\n" );
7742 0         0 $self->resume_logfile();
7743             }
7744 0         0 return;
7745             } ## end sub report_unexpected
7746              
7747             my %is_sigil_or_paren;
7748             my %is_R_closing_sb;
7749              
7750             BEGIN {
7751              
7752 44     44   276 my @q = qw< $ & % * @ ) >;
7753 44         320 $is_sigil_or_paren{$_} = 1 for @q;
7754              
7755 44         115 @q = qw( R ] );
7756 44         71847 $is_R_closing_sb{$_} = 1 for @q;
7757             } ## end BEGIN
7758              
7759             sub is_non_structural_brace {
7760              
7761             # Decide if a brace or bracket is structural or non-structural
7762             # by looking at the previous token and type
7763             # USES GLOBAL VARIABLES: $last_nonblank_type, $last_nonblank_token
7764              
7765             # EXPERIMENTAL: Mark slices as structural; idea was to improve formatting.
7766             # Tentatively deactivated because it caused the wrong operator expectation
7767             # for this code:
7768             # $user = @vars[1] / 100;
7769             # Must update sub operator_expected before re-implementing.
7770             # if ( $last_nonblank_type eq 'i' && $last_nonblank_token =~ /^@/ ) {
7771             # return 0;
7772             # }
7773              
7774             #--------------------------------------------------------------
7775             # NOTE: braces after type characters start code blocks, but for
7776             # simplicity these are not identified as such. See also
7777             # sub code_block_type
7778             #--------------------------------------------------------------
7779              
7780             ##if ($last_nonblank_type eq 't') {return 0}
7781              
7782             # otherwise, it is non-structural if it is decorated
7783             # by type information.
7784             # For example, the '{' here is non-structural: ${xxx}
7785             # Removed '::' to fix c074
7786             ## $last_nonblank_token =~ /^([\$\@\*\&\%\)]|->|::)/
7787             return (
7788             ## $last_nonblank_token =~ /^([\$\@\*\&\%\)]|->)/
7789             $is_sigil_or_paren{ substr( $last_nonblank_token, 0, 1 ) }
7790             || substr( $last_nonblank_token, 0, 2 ) eq '->'
7791              
7792             # or if we follow a hash or array closing curly brace or bracket
7793             # For example, the second '{' in this is non-structural: $a{'x'}{'y'}
7794             # because the first '}' would have been given type 'R'
7795             ##|| $last_nonblank_type =~ /^([R\]])$/
7796 2882   66 2882 0 13396 || $is_R_closing_sb{$last_nonblank_type}
7797             );
7798             } ## end sub is_non_structural_brace
7799              
7800             #######################################################################
7801             # Tokenizer routines for tracking container nesting depths
7802             #######################################################################
7803              
7804             # The following routines keep track of nesting depths of the nesting
7805             # types, ( [ { and ?. This is necessary for determining the indentation
7806             # level, and also for debugging programs. Not only do they keep track of
7807             # nesting depths of the individual brace types, but they check that each
7808             # of the other brace types is balanced within matching pairs. For
7809             # example, if the program sees this sequence:
7810             #
7811             # { ( ( ) }
7812             #
7813             # then it can determine that there is an extra left paren somewhere
7814             # between the { and the }. And so on with every other possible
7815             # combination of outer and inner brace types. For another
7816             # example:
7817             #
7818             # ( [ ..... ] ] )
7819             #
7820             # which has an extra ] within the parens.
7821             #
7822             # The brace types have indexes 0 .. 3 which are indexes into
7823             # the matrices.
7824             #
7825             # The pair ? : are treated as just another nesting type, with ? acting
7826             # as the opening brace and : acting as the closing brace.
7827             #
7828             # The matrix
7829             #
7830             # $rdepth_array->[$a][$b][ $rcurrent_depth->[$a] ] = $rcurrent_depth->[$b];
7831             #
7832             # saves the nesting depth of brace type $b (where $b is either of the other
7833             # nesting types) when brace type $a enters a new depth. When this depth
7834             # decreases, a check is made that the current depth of brace types $b is
7835             # unchanged, or otherwise there must have been an error. This can
7836             # be very useful for localizing errors, particularly when perl runs to
7837             # the end of a large file (such as this one) and announces that there
7838             # is a problem somewhere.
7839             #
7840             # A numerical sequence number is maintained for every nesting type,
7841             # so that each matching pair can be uniquely identified in a simple
7842             # way.
7843              
7844             sub increase_nesting_depth {
7845 5526     5526 0 8526 my ( $self, $aa, $pos ) = @_;
7846              
7847             # Given:
7848             # $aa = integer code of container type, 0-3
7849             # $pos = position of character, for error message
7850              
7851             # USES GLOBAL VARIABLES: $rcurrent_depth,
7852             # $rcurrent_sequence_number, $rdepth_array,
7853             # $rstarting_line_of_current_depth, $statement_type
7854 5526         7773 my $cd_aa = ++$rcurrent_depth->[$aa];
7855 5526         6075 $total_depth++;
7856 5526         8768 $rtotal_depth->[$aa]->[$cd_aa] = $total_depth;
7857 5526         6924 my $input_line_number = $self->[_last_line_number_];
7858 5526         6917 my $input_line = $self->[_line_of_text_];
7859              
7860             # Sequence numbers increment by number of items. This keeps
7861             # a unique set of numbers but still allows the relative location
7862             # of any type to be determined.
7863              
7864             # make a new unique sequence number
7865 5526         6604 my $seqno = $next_sequence_number++;
7866              
7867             # Remember the type sequence number at the current depth,
7868             # but do not overwrite the root sequence number.
7869 5526 50       8835 if ( $total_depth > 0 ) {
7870 5526         8310 $self->[_rseqno_at_depth_]->[$total_depth] = $seqno;
7871             }
7872              
7873 5526         8180 $rcurrent_sequence_number->[$aa]->[$cd_aa] = $seqno;
7874              
7875 5526         14097 $rstarting_line_of_current_depth->[$aa]->[$cd_aa] =
7876             [ $input_line_number, $input_line, $pos ];
7877              
7878 5526         12459 for my $bb ( 0 .. @closing_brace_names - 1 ) {
7879 22104 100       28359 next if ( $bb == $aa );
7880 16578         25372 $rdepth_array->[$aa]->[$bb]->[$cd_aa] = $rcurrent_depth->[$bb];
7881             }
7882              
7883             # set a flag for indenting a nested ternary statement
7884 5526         6926 my $indent = 0;
7885 5526 100       8604 if ( $aa == QUESTION_COLON ) {
7886 193         336 $rnested_ternary_flag->[$cd_aa] = 0;
7887 193 100       489 if ( $cd_aa > 1 ) {
7888 17 100       51 if ( $rnested_ternary_flag->[ $cd_aa - 1 ] == 0 ) {
7889 16         32 my $pdepth = $rtotal_depth->[$aa]->[ $cd_aa - 1 ];
7890 16 100       46 if ( $pdepth == $total_depth - 1 ) {
7891 8         13 $indent = 1;
7892 8         17 $rnested_ternary_flag->[ $cd_aa - 1 ] = -1;
7893             }
7894             }
7895             }
7896             }
7897              
7898             # Fix part #1 for git82: save last token type for propagation of type 'Z'
7899 5526         21355 $rnested_statement_type->[$aa]->[$cd_aa] =
7900             [ $statement_type, $last_nonblank_type, $last_nonblank_token ];
7901 5526         6832 $statement_type = EMPTY_STRING;
7902 5526         10646 return ( $seqno, $indent );
7903             } ## end sub increase_nesting_depth
7904              
7905             sub is_balanced_closing_container {
7906              
7907 47     47 0 77 my ($aa) = @_;
7908              
7909             # Return true if a closing container can go here without error
7910             # Return false if not
7911             # Given:
7912             # $aa = integer code of container type, 0-3
7913              
7914             # cannot close if there was no opening
7915 47         69 my $cd_aa = $rcurrent_depth->[$aa];
7916 47 100       157 return if ( $cd_aa <= 0 );
7917              
7918             # check that any other brace types $bb contained within would be balanced
7919 8         13 for my $bb ( 0 .. @closing_brace_names - 1 ) {
7920 8 50       28 next if ( $bb == $aa );
7921             return
7922             if (
7923 8 50       34 $rdepth_array->[$aa]->[$bb]->[$cd_aa] != $rcurrent_depth->[$bb] );
7924             }
7925              
7926             # OK, everything will be balanced
7927 0         0 return 1;
7928             } ## end sub is_balanced_closing_container
7929              
7930             sub decrease_nesting_depth {
7931              
7932 5526     5526 0 8298 my ( $self, $aa, $pos ) = @_;
7933              
7934             # Given:
7935             # $aa = integer code of container type, 0-3
7936             # $pos = position of character, for error message
7937              
7938             # USES GLOBAL VARIABLES: $rcurrent_depth,
7939             # $rcurrent_sequence_number, $rdepth_array, $rstarting_line_of_current_depth
7940             # $statement_type
7941 5526         6048 my $seqno = 0;
7942 5526         7385 my $input_line_number = $self->[_last_line_number_];
7943 5526         7067 my $input_line = $self->[_line_of_text_];
7944              
7945 5526         6041 my $outdent = 0;
7946 5526         6336 $total_depth--;
7947 5526         7164 my $cd_aa = $rcurrent_depth->[$aa];
7948 5526 50       8661 if ( $cd_aa > 0 ) {
7949              
7950             # set a flag for un-indenting after seeing a nested ternary statement
7951 5526         8040 $seqno = $rcurrent_sequence_number->[$aa]->[$cd_aa];
7952 5526 100       8784 if ( $aa == QUESTION_COLON ) {
7953 193         322 $outdent = $rnested_ternary_flag->[$cd_aa];
7954             }
7955              
7956             # Fix part #2 for git82: use saved type for propagation of type 'Z'
7957             # through type L-R braces. Perl seems to allow ${bareword}
7958             # as an indirect object, but nothing much more complex than that.
7959             ( $statement_type, my $saved_type, my $saved_token_uu ) =
7960 5526         6027 @{ $rnested_statement_type->[$aa]->[ $rcurrent_depth->[$aa] ] };
  5526         12841  
7961 5526 50 100     13901 if ( $aa == BRACE
      66        
      66        
7962             && $saved_type eq 'Z'
7963             && $last_nonblank_type eq 'w'
7964             && $rbrace_structural_type->[$brace_depth] eq 'L' )
7965             {
7966 1         2 $last_nonblank_type = $saved_type;
7967             }
7968              
7969             # check that any brace types $bb contained within are balanced
7970 5526         11060 for my $bb ( 0 .. @closing_brace_names - 1 ) {
7971 22104 100       28636 next if ( $bb == $aa );
7972              
7973 16578 50       29988 if ( $rdepth_array->[$aa]->[$bb]->[$cd_aa] !=
7974             $rcurrent_depth->[$bb] )
7975             {
7976 0         0 my $diff =
7977             $rcurrent_depth->[$bb] -
7978             $rdepth_array->[$aa]->[$bb]->[$cd_aa];
7979              
7980             # don't whine too many times
7981 0         0 my $saw_brace_error = $self->get_saw_brace_error();
7982 0 0 0     0 if (
      0        
7983             $saw_brace_error <= MAX_NAG_MESSAGES
7984              
7985             # if too many closing types have occurred, we probably
7986             # already caught this error
7987             && ( ( $diff > 0 ) || ( $saw_brace_error <= 0 ) )
7988             )
7989             {
7990 0         0 $self->interrupt_logfile();
7991 0         0 my $rsl = $rstarting_line_of_current_depth->[$aa]->[$cd_aa];
7992 0         0 my $sl = $rsl->[0];
7993 0         0 my $rel = [ $input_line_number, $input_line, $pos ];
7994 0         0 my $el = $rel->[0];
7995 0         0 my ($ess);
7996              
7997 0 0 0     0 if ( $diff == 1 || $diff == -1 ) {
7998 0         0 $ess = EMPTY_STRING;
7999             }
8000             else {
8001 0         0 $ess = 's';
8002             }
8003 0 0       0 my $bname =
8004             ( $diff > 0 )
8005             ? $opening_brace_names[$bb]
8006             : $closing_brace_names[$bb];
8007 0         0 $self->write_error_indicator_pair( @{$rsl}, '^' );
  0         0  
8008 0         0 my $msg = <<"EOM";
8009             Found $diff extra $bname$ess between $opening_brace_names[$aa] on line $sl and $closing_brace_names[$aa] on line $el
8010             EOM
8011              
8012 0 0       0 if ( $diff > 0 ) {
8013 0         0 my $rml =
8014             $rstarting_line_of_current_depth->[$bb]
8015             ->[ $rcurrent_depth->[$bb] ];
8016 0         0 my $ml = $rml->[0];
8017 0         0 $msg .=
8018             " The most recent un-matched $bname is on line $ml\n";
8019 0         0 $self->write_error_indicator_pair( @{$rml}, '^' );
  0         0  
8020             }
8021 0         0 $self->write_error_indicator_pair( @{$rel}, '^' );
  0         0  
8022 0         0 $self->warning($msg);
8023 0         0 $self->resume_logfile();
8024             }
8025 0         0 $self->increment_brace_error();
8026 0 0       0 if ( $bb eq BRACE ) { $self->[_show_indentation_table_] = 1 }
  0         0  
8027             }
8028             }
8029 5526         7281 $rcurrent_depth->[$aa]--;
8030             }
8031             else {
8032              
8033 0         0 my $saw_brace_error = $self->get_saw_brace_error();
8034 0 0       0 if ( $saw_brace_error <= MAX_NAG_MESSAGES ) {
8035 0         0 my $msg = <<"EOM";
8036             There is no previous $opening_brace_names[$aa] to match a $closing_brace_names[$aa] on line $input_line_number
8037             EOM
8038 0         0 $self->indicate_error( $msg, $input_line_number, $input_line, $pos,
8039             '^' );
8040             }
8041 0         0 $self->increment_brace_error();
8042 0 0       0 if ( $aa eq BRACE ) { $self->[_show_indentation_table_] = 1 }
  0         0  
8043              
8044             # keep track of errors in braces alone (ignoring ternary nesting errors)
8045 0 0       0 $self->[_true_brace_error_count_]++
8046             if ( $closing_brace_names[$aa] ne "':'" );
8047             }
8048 5526         10218 return ( $seqno, $outdent );
8049             } ## end sub decrease_nesting_depth
8050              
8051             sub check_final_nesting_depths {
8052              
8053             # USES GLOBAL VARIABLES: $rcurrent_depth, $rstarting_line_of_current_depth
8054 659     659 0 1129 my $self = shift;
8055              
8056 659         2063 for my $aa ( 0 .. @closing_brace_names - 1 ) {
8057              
8058 2636         3271 my $cd_aa = $rcurrent_depth->[$aa];
8059 2636 50       4158 if ($cd_aa) {
8060 0         0 my $rsl = $rstarting_line_of_current_depth->[$aa]->[$cd_aa];
8061 0         0 my $sl = $rsl->[0];
8062              
8063             # Add hint for something like a missing terminal ':' of a ternary
8064 0         0 my $hint = EMPTY_STRING;
8065 0 0       0 if ( $cd_aa == 1 ) {
8066 0         0 $hint =
8067             " .. did not find its closing $closing_brace_names[$aa]";
8068             }
8069 0         0 my $msg = <<"EOM";
8070             Final nesting depth of $opening_brace_names[$aa]s is $cd_aa
8071             The most recent un-matched $opening_brace_names[$aa] is on line $sl$hint
8072             EOM
8073 0         0 $self->indicate_error( $msg, @{$rsl}, '^' );
  0         0  
8074 0         0 $self->increment_brace_error();
8075 0 0       0 if ( $aa eq BRACE ) { $self->[_show_indentation_table_] = 1 }
  0         0  
8076             }
8077             }
8078 659         1031 return;
8079             } ## end sub check_final_nesting_depths
8080              
8081             #######################################################################
8082             # Tokenizer routines for looking ahead in input stream
8083             #######################################################################
8084              
8085             sub peek_ahead_for_n_nonblank_pre_tokens {
8086              
8087 188     188 0 348 my ( $self, $max_pretokens ) = @_;
8088              
8089             # Given:
8090             # $max_pretokens = number of pretokens wanted
8091             # Return:
8092             # next $max_pretokens pretokens if they exist
8093             # undef's if hits eof without seeing any pretokens
8094              
8095             # USES GLOBAL VARIABLES: (none)
8096 188         227 my $line;
8097 188         266 my $i = 0;
8098 188         262 my ( $rpre_tokens, $rmap, $rpre_types );
8099              
8100 188         465 while ( defined( $line = $self->peek_ahead( $i++ ) ) ) {
8101 206         695 $line =~ s/^\s+//; # trim leading blanks
8102 206 100       422 next if ( length($line) <= 0 ); # skip blank
8103 200 100       476 next if ( $line =~ /^#/ ); # skip comment
8104 180         418 ( $rpre_tokens, $rmap, $rpre_types ) =
8105             pre_tokenize( $line, $max_pretokens );
8106 180         287 last;
8107             } ## end while ( defined( $line = ...))
8108 188         483 return ( $rpre_tokens, $rpre_types );
8109             } ## end sub peek_ahead_for_n_nonblank_pre_tokens
8110              
8111             # look ahead for next non-blank, non-comment line of code
8112             sub peek_ahead_for_nonblank_token {
8113              
8114 143     143 0 294 my ( $self, $rtokens, $max_token_index ) = @_;
8115              
8116             # Given:
8117             # $rtokens = ref to token array
8118             # $max_token_index = index of last token in $rtokens
8119             # Task:
8120             # Update $rtokens with next nonblank token
8121              
8122             # USES GLOBAL VARIABLES: (none)
8123 143         211 my $line;
8124 143         212 my $i = 0;
8125              
8126 143         563 while ( defined( $line = $self->peek_ahead( $i++ ) ) ) {
8127 194         723 $line =~ s/^\s+//; # trim leading blanks
8128 194 100       474 next if ( length($line) <= 0 ); # skip blank
8129 165 100       471 next if ( $line =~ /^#/ ); # skip comment
8130              
8131             # Updated from 2 to 3 to get trigraphs, added for case b1175
8132 141         402 my ( $rtok, $rmap_uu, $rtype_uu ) = pre_tokenize( $line, 3 );
8133 141         258 my $j = $max_token_index + 1;
8134              
8135 141         208 foreach my $tok ( @{$rtok} ) {
  141         282  
8136 406 100       745 last if ( $tok =~ "\n" );
8137 363         648 $rtokens->[ ++$j ] = $tok;
8138             }
8139 141         377 last;
8140             } ## end while ( defined( $line = ...))
8141 143         269 return;
8142             } ## end sub peek_ahead_for_nonblank_token
8143              
8144             #######################################################################
8145             # Tokenizer guessing routines for ambiguous situations
8146             #######################################################################
8147              
8148             my %is_non_ternary_pretok;
8149              
8150             BEGIN {
8151              
8152             # Some pre-tokens which cannot immediately follow a ternary '?'
8153 44     44   306 my @q = qw# ; ? : ) } ] = > #;
8154 44         138 push @q, COMMA;
8155 44         158 %is_non_ternary_pretok = map { $_ => 1 } @q;
  396         20709  
8156             }
8157              
8158             sub guess_if_pattern_or_conditional {
8159              
8160 12     12 0 33 my ( $self, $i, $rtokens, $rtoken_type, $rtoken_map_uu, $max_token_index )
8161             = @_;
8162              
8163             # This routine is called when we have encountered a ? following an
8164             # unknown bareword, and we must decide if it starts a pattern or not
8165             # Given:
8166             # $i - token index of the ? starting possible pattern
8167             # $rtokens ... = the token arrays
8168             # Return:
8169             # $is_pattern = 0 if probably not pattern, =1 if probably a pattern
8170             # msg = a warning or diagnostic message
8171              
8172             # USES GLOBAL VARIABLES: $last_nonblank_token
8173              
8174 12         17 my $is_pattern = 0;
8175 12         28 my $msg =
8176             "guessing that ? after type='$last_nonblank_type' token='$last_nonblank_token' starts a ";
8177              
8178 12 50       39 if ( $i >= $max_token_index ) {
8179 0         0 $msg .= "conditional (no end to pattern found on the line)\n";
8180 0         0 $is_pattern = 0;
8181 0         0 return ( $is_pattern, $msg );
8182             }
8183              
8184             # See if we can rule out a ternary operator here before proceeding. c547.
8185 12         39 my ( $next_nonblank_token, $i_next_uu ) =
8186             find_next_nonblank_token_on_this_line( $i, $rtokens, $max_token_index );
8187 12 50 33     75 if (
      33        
8188             !(
8189             $is_non_ternary_pretok{$next_nonblank_token}
8190             || ( $last_nonblank_type eq 'k' && $last_nonblank_token eq 'split' )
8191             )
8192             )
8193             {
8194             # A ternary cannot be ruled out here. We will assume this is a ternary
8195             # operator since '?' as pattern delimiter is deprecated.
8196 12         21 $is_pattern = 0;
8197 12         26 $msg .= "conditional (cannot rule it out)";
8198 12         35 return ( $is_pattern, $msg );
8199             }
8200              
8201             # If we get here, then we either have a ternary with a syntax error or some
8202             # ancient code which uses ? as a pattern delimiter. We will only select the
8203             # pattern delimiter if we can find its matching closing delimiter.
8204              
8205 0         0 my $ibeg = $i;
8206 0         0 $i = $ibeg + 1;
8207             ##my $next_token = $rtokens->[$i]; # first token after ?
8208              
8209             # look for a possible ending ? on this line..
8210 0         0 my $in_quote = 1;
8211 0         0 my $quote_depth = 0;
8212 0         0 my $quote_character = EMPTY_STRING;
8213 0         0 my $quote_pos = 0;
8214 0         0 my $quoted_string;
8215             (
8216              
8217 0         0 $i,
8218             $in_quote,
8219             $quote_character,
8220             $quote_pos,
8221             $quote_depth,
8222             $quoted_string,
8223              
8224             ) = $self->follow_quoted_string(
8225              
8226             $ibeg,
8227             $in_quote,
8228             $rtokens,
8229             $rtoken_type,
8230             $quote_character,
8231             $quote_pos,
8232             $quote_depth,
8233             $max_token_index,
8234              
8235             );
8236              
8237 0 0       0 if ($in_quote) {
8238              
8239             # we didn't find an ending ? on this line,
8240             # so we bias towards conditional
8241 0         0 $is_pattern = 0;
8242 0         0 $msg .= "conditional (no ending ? on this line)\n";
8243 0         0 return ( $is_pattern, $msg );
8244             }
8245              
8246             # we found an ending ?, so we bias towards a pattern
8247              
8248             # Watch out for an ending ? in quotes, like this
8249             # my $case_flag = File::Spec->case_tolerant ? '(?i)' : '';
8250 0         0 my $s_quote = 0;
8251 0         0 my $d_quote = 0;
8252 0         0 my $colons = 0;
8253 0         0 foreach my $ii ( $ibeg + 1 .. $i - 1 ) {
8254 0         0 my $tok = $rtokens->[$ii];
8255 0 0       0 if ( $tok eq ":" ) { $colons++ }
  0         0  
8256 0 0       0 if ( $tok eq "'" ) { $s_quote++ }
  0         0  
8257 0 0       0 if ( $tok eq '"' ) { $d_quote++ }
  0         0  
8258             }
8259 0 0 0     0 if ( $s_quote % 2 || $d_quote % 2 || $colons ) {
      0        
8260 0         0 $is_pattern = 0;
8261 0         0 $msg .= "conditional: found ending ? but unbalanced quote chars\n";
8262 0         0 return ( $is_pattern, $msg );
8263             }
8264 0 0       0 if ( $self->pattern_expected( $i, $rtokens, $max_token_index ) >= 0 ) {
8265 0         0 $is_pattern = 1;
8266 0         0 $msg .= "pattern (found ending ? and pattern expected)\n";
8267 0         0 return ( $is_pattern, $msg );
8268             }
8269              
8270             # NOTE: An ultimate decision could be made on version, since ? is a ternary
8271             # after version 5.22. But we may be formatting an ancient script with a
8272             # newer perl, and it might run on an older perl, so we cannot be certain.
8273             # if ($] >=5.022) {$is_pattern=0} else { ... not sure
8274              
8275 0         0 $msg .= "conditional (but uncertain)\n";
8276 0         0 return ( $is_pattern, $msg );
8277             } ## end sub guess_if_pattern_or_conditional
8278              
8279             my %is_known_constant;
8280             my %is_known_function;
8281              
8282             BEGIN {
8283              
8284             # Constants like 'pi' in Trig.pm are common
8285 44     44   249 my @q = qw( pi pi2 pi4 pip2 pip4 );
8286 44         321 $is_known_constant{$_} = 1 for @q;
8287              
8288             # parenless calls of 'ok' are common
8289 44         103 @q = qw( ok );
8290 44         70885 $is_known_function{$_} = 1 for @q;
8291             } ## end BEGIN
8292              
8293             sub guess_if_pattern_or_division {
8294              
8295 0     0 0 0 my ( $self, $i, $rtokens, $rtoken_type, $rtoken_map, $max_token_index ) =
8296             @_;
8297              
8298             # This routine is called when we have encountered a / following an
8299             # unknown bareword, and we must decide if it starts a pattern or is a
8300             # division.
8301             # Given:
8302             # $i - token index of the / starting possible pattern
8303             # $rtokens ... = the token arrays
8304             # Return:
8305             # $is_pattern = 0 if probably division, =1 if probably a pattern
8306             # msg = a warning or diagnostic message
8307             # USES GLOBAL VARIABLES: $last_nonblank_token
8308 0         0 my $msg = "guessing that / after '$last_nonblank_token' starts a ";
8309 0         0 my $ibeg = $i;
8310 0         0 my $is_pattern = 0;
8311              
8312 0         0 my $divide_possible =
8313             $self->is_possible_numerator( $i, $rtokens, $max_token_index );
8314              
8315 0 0       0 if ( $divide_possible < 0 ) {
8316 0         0 $msg .= "pattern (division not possible here)\n";
8317 0         0 $is_pattern = 1;
8318 0         0 $self->saw_bareword_function($last_nonblank_token);
8319 0         0 return ( $is_pattern, $msg );
8320             }
8321 0 0       0 if ( $divide_possible == 4 ) {
8322 0         0 $msg .= "division (pattern not possible here)\n";
8323 0         0 $is_pattern = 0;
8324 0         0 return ( $is_pattern, $msg );
8325             }
8326              
8327             # anything left on line?
8328 0 0       0 if ( $i >= $max_token_index ) {
8329 0         0 $msg .= "division (line ends with this /)\n";
8330 0         0 $is_pattern = 0;
8331 0         0 return ( $is_pattern, $msg );
8332             }
8333              
8334             # quick check for no pattern-ending slash on this line
8335 0         0 my $pos_beg = $rtoken_map->[$ibeg];
8336 0         0 my $input_line = $self->[_line_of_text_];
8337 0 0       0 if ( index( $input_line, '/', $pos_beg + 1 ) < 0 ) {
8338 0         0 $msg .= "division (no ending / on this line)\n";
8339 0         0 $is_pattern = 0;
8340 0         0 return ( $is_pattern, $msg );
8341             }
8342              
8343             # Setup spacing rule before we change $i below..
8344 0         0 $i = $ibeg + 1;
8345 0         0 my $next_token = $rtokens->[$i]; # first token after slash
8346              
8347             # There are four possible spacings around the first slash:
8348             #
8349             # return pi/two;#/; -/-
8350             # return pi/ two;#/; -/+
8351             # return pi / two;#/; +/+
8352             # return pi /two;#/; +/- <-- possible pattern
8353             #
8354             # Spacing rule: a space before the slash but not after the slash
8355             # usually indicates a pattern. We can use this to break ties.
8356             # Note: perl seems to take a newline as a space in this rule (c243)
8357 0   0     0 my $space_before = $i < 2 || $rtokens->[ $i - 2 ] =~ m/^\s/;
8358 0         0 my $space_after = $next_token =~ m/^\s/;
8359 0   0     0 my $is_pattern_by_spacing = $space_before && !$space_after;
8360              
8361             # Make an accurate search for a possible terminating / on this line..
8362 0         0 my $in_quote = 1;
8363 0         0 my $quote_depth = 0;
8364 0         0 my $quote_character = EMPTY_STRING;
8365 0         0 my $quote_pos = 0;
8366 0         0 my $quoted_string;
8367             (
8368              
8369 0         0 $i,
8370             $in_quote,
8371             $quote_character,
8372             $quote_pos,
8373             $quote_depth,
8374             $quoted_string,
8375             )
8376             = $self->follow_quoted_string(
8377              
8378             $ibeg,
8379             $in_quote,
8380             $rtokens,
8381             $rtoken_type,
8382             $quote_character,
8383             $quote_pos,
8384             $quote_depth,
8385             $max_token_index,
8386             );
8387              
8388             # if we didn't find an ending / on this line ..
8389 0 0       0 if ($in_quote) {
8390 0         0 $is_pattern = 0;
8391 0         0 $msg .= "division (no ending / on this line)\n";
8392 0         0 return ( $is_pattern, $msg );
8393             }
8394              
8395             # we found an ending /, see if it might terminate a pattern
8396 0         0 my $pattern_expected =
8397             $self->pattern_expected( $i, $rtokens, $max_token_index );
8398              
8399 0 0       0 if ( $pattern_expected < 0 ) {
8400 0         0 $is_pattern = 0;
8401 0         0 $msg .= "division (pattern not possible)\n";
8402 0         0 return ( $is_pattern, $msg );
8403             }
8404              
8405             # Both pattern and divide can work here...
8406             # Check for known constants in the numerator, like 'pi'
8407 0 0       0 if ( $is_known_constant{$last_nonblank_token} ) {
8408 0         0 $msg .=
8409             "division (pattern works too but saw known constant '$last_nonblank_token')\n";
8410 0         0 $is_pattern = 0;
8411 0         0 return ( $is_pattern, $msg );
8412             }
8413              
8414             # Check for known functions like 'ok'
8415 0 0       0 if ( $is_known_function{$last_nonblank_token} ) {
8416 0         0 $msg .= "pattern (division works too but saw '$last_nonblank_token')\n";
8417 0         0 $is_pattern = 1;
8418 0         0 return ( $is_pattern, $msg );
8419             }
8420              
8421             # If one rule is more probable, use it
8422 0 0       0 if ( $divide_possible > $pattern_expected ) {
8423 0         0 $msg .= "division (more likely based on following tokens)\n";
8424 0         0 $is_pattern = 0;
8425 0         0 return ( $is_pattern, $msg );
8426             }
8427              
8428             # finally, we have to use the spacing rule
8429 0 0       0 if ($is_pattern_by_spacing) {
8430 0         0 $msg .= "pattern (guess on spacing, but division possible too)\n";
8431 0         0 $is_pattern = 1;
8432             }
8433             else {
8434 0         0 $msg .= "division (guess on spacing, but pattern is possible too)\n";
8435 0         0 $is_pattern = 0;
8436             }
8437              
8438 0         0 return ( $is_pattern, $msg );
8439             } ## end sub guess_if_pattern_or_division
8440              
8441             sub guess_if_here_doc {
8442              
8443 0     0 0 0 my ( $self, $next_token ) = @_;
8444              
8445             # Try to resolve here-doc vs. shift by looking ahead for
8446             # non-code or the end token (currently only looks for end token)
8447              
8448             # Given:
8449             # $next_token = the next token after '<<'
8450              
8451             # Return:
8452             # 1 if it is probably a here doc
8453             # 0 if not
8454              
8455             # USES GLOBAL VARIABLES: $current_package $ris_constant,
8456              
8457             # This is how many lines we will search for a target as part of the
8458             # guessing strategy. There is probably little reason to change it.
8459 0         0 my $HERE_DOC_WINDOW = 40;
8460              
8461 0         0 my $here_doc_expected = 0;
8462 0         0 my $line;
8463 0         0 my $k = 0;
8464 0         0 my $msg = "checking <<";
8465              
8466 0         0 while ( defined( $line = $self->peek_ahead( $k++ ) ) ) {
8467 0         0 chomp $line;
8468 0 0       0 if ( $line eq $next_token ) {
8469 0         0 $msg .= " -- found target $next_token ahead $k lines\n";
8470 0         0 $here_doc_expected = 1; # got it
8471 0         0 last;
8472             }
8473 0 0       0 last if ( $k >= $HERE_DOC_WINDOW );
8474             } ## end while ( defined( $line = ...))
8475              
8476 0 0       0 if ( !$here_doc_expected ) {
8477              
8478 0 0       0 if ( !defined($line) ) {
8479 0         0 $here_doc_expected = -1; # hit eof without seeing target
8480 0         0 $msg .= " -- must be shift; target $next_token not in file\n";
8481             }
8482             else { # still unsure..taking a wild guess
8483              
8484 0 0       0 if ( !$ris_constant->{$current_package}->{$next_token} ) {
8485 0         0 $here_doc_expected = 1;
8486 0         0 $msg .=
8487             " -- guessing it's a here-doc ($next_token not a constant)\n";
8488             }
8489             else {
8490 0         0 $msg .=
8491             " -- guessing it's a shift ($next_token is a constant)\n";
8492             }
8493 0         0 if (DEBUG_GUESS_MODE) {
8494             $self->warning("DEBUG_GUESS_MODE message:\n$msg\n");
8495             }
8496             }
8497             }
8498 0         0 $self->write_logfile_entry($msg);
8499 0         0 return $here_doc_expected;
8500             } ## end sub guess_if_here_doc
8501              
8502             #######################################################################
8503             # Tokenizer Routines for scanning identifiers and related items
8504             #######################################################################
8505              
8506             sub scan_bare_identifier_do {
8507              
8508             my (
8509              
8510 1866     1866 0 4357 $self,
8511              
8512             $input_line,
8513             $i,
8514             $tok,
8515             $type,
8516             $prototype,
8517             $rtoken_map,
8518             $max_token_index,
8519              
8520             ) = @_;
8521              
8522             # This routine is called to scan a token starting with an alphanumeric
8523             # variable or package separator, :: or '.
8524              
8525             # Given:
8526             # current scan state variables
8527              
8528             # USES GLOBAL VARIABLES: $current_package, $last_nonblank_token,
8529             # $last_nonblank_type, $rparen_type, $paren_depth
8530              
8531 1866         2539 my $package = undef;
8532              
8533 1866         2222 my $i_beg = $i;
8534              
8535             # we have to back up one pretoken at a :: since each : is one pretoken
8536 1866 100       3360 if ( $tok eq '::' ) { $i_beg-- }
  9         16  
8537 1866         2704 my $pos_beg = $rtoken_map->[$i_beg];
8538 1866         4972 pos($input_line) = $pos_beg;
8539              
8540             # Examples:
8541             # A::B::C
8542             # A::
8543             # ::A
8544             # A'B
8545 1866 50       10397 if (
8546             $input_line =~ m{
8547             \G\s* # start at pos
8548             ( (?:\w*(?:'|::))* ) # $1 = maybe package name like A:: A::B:: or A'
8549             (\w+)? # $2 = maybe followed by sub name
8550             }gcx
8551             )
8552             {
8553 1866         2601 my $pos = pos($input_line);
8554 1866         2475 my $numc = $pos - $pos_beg;
8555 1866         3420 $tok = substr( $input_line, $pos_beg, $numc );
8556              
8557             # type 'w' includes anything without leading type info
8558             # ($,%,@,*) including something like abc::def::ghi
8559 1866         2331 $type = 'w';
8560              
8561 1866         2289 my $sub_name = EMPTY_STRING;
8562 1866 100       4193 if ( defined($2) ) { $sub_name = $2; }
  1861         2896  
8563 1866 100 66     6190 if ( defined($1) && length($1) ) {
8564 280         482 $package = $1;
8565              
8566             # patch: check for package call A::B::C->
8567             # in this case, C is part of the package name
8568 280 100       584 if ($sub_name) {
8569 275 100       1053 if ( $input_line =~ m{ \G\s*(?:->) }gcx ) {
8570 117         198 $package .= $sub_name;
8571 117         172 $sub_name = EMPTY_STRING;
8572             }
8573 275         523 pos($input_line) = $pos;
8574             }
8575              
8576             # patch: don't allow isolated package name which just ends
8577             # in the old style package separator (single quote). Example:
8578             # use CGI':all';
8579 280 50 66     1023 if ( !($sub_name) && substr( $package, -1, 1 ) eq '\'' ) {
8580 0         0 $pos--;
8581             }
8582              
8583 280         565 $package =~ s/\'/::/g;
8584 280 100       655 if ( $package =~ /^\:/ ) { $package = 'main' . $package }
  9         15  
8585 280         822 $package =~ s/::$//;
8586             }
8587             else {
8588 1586         2265 $package = $current_package;
8589              
8590             # patched for c043, part 1: keyword does not follow '->'
8591 1586 50 66     4477 if ( $is_keyword{$tok} && $last_nonblank_type ne '->' ) {
8592 0         0 $type = 'k';
8593             }
8594             }
8595              
8596             # if it is a bareword.. patched for c043, part 2: not following '->'
8597 1866 100 66     5835 if ( $type eq 'w' && $last_nonblank_type ne '->' ) {
8598              
8599             # check for v-string with leading 'v' type character
8600             # (This seems to have precedence over filehandle, type 'Y')
8601 1080 100 100     13057 if ( substr( $tok, 0, 1 ) eq 'v' && $tok =~ /^v\d[_\d]*$/ ) {
    100 66        
    100 66        
    50 66        
    50          
    100          
    100          
8602              
8603             # we only have the first part - something like 'v101' -
8604             # look for more
8605 2 50       10 if ( $input_line =~ m/\G(\.\d[_\d]*)+/gc ) {
8606 2         4 $pos = pos($input_line);
8607 2         4 $numc = $pos - $pos_beg;
8608 2         4 $tok = substr( $input_line, $pos_beg, $numc );
8609             }
8610 2         4 $type = 'v';
8611 2         8 $self->report_v_string($tok);
8612             }
8613              
8614             # bareword after sort has implied empty prototype; for example:
8615             # @sorted = sort numerically ( 53, 29, 11, 32, 7 );
8616             # This has priority over whatever the user has specified.
8617             elsif ($last_nonblank_token eq 'sort'
8618             && $last_nonblank_type eq 'k' )
8619             {
8620 1         1 $type = 'Z';
8621             }
8622              
8623             # issue c382: this elsif statement moved from above because
8624             # previous check for type 'Z' after sort has priority.
8625             elsif ( $ris_constant->{$package}->{$sub_name} ) {
8626 12         23 $type = 'C';
8627             }
8628              
8629             # Note: strangely, perl does not seem to really let you create
8630             # functions which act like eval and do, in the sense that eval
8631             # and do may have operators following the final }, but any operators
8632             # that you create with prototype (&) apparently do not allow
8633             # trailing operators, only terms. This seems strange.
8634             # If this ever changes, here is the update
8635             # to make perltidy behave accordingly:
8636              
8637             # elsif ( $ris_block_function->{$package}{$tok} ) {
8638             # $tok='eval'; # patch to do braces like eval - doesn't work
8639             # $type = 'k';
8640             #}
8641             # TODO: This could become a separate type to allow for different
8642             # future behavior:
8643             elsif ( $ris_block_function->{$package}->{$sub_name} ) {
8644 0         0 $type = 'G';
8645             }
8646             elsif ( $ris_block_list_function->{$package}->{$sub_name} ) {
8647 0         0 $type = 'G';
8648             }
8649             elsif ( $ris_user_function->{$package}->{$sub_name} ) {
8650 6         12 $type = 'U';
8651 6         15 $prototype = $ruser_function_prototype->{$package}->{$sub_name};
8652             }
8653              
8654             # check for indirect object
8655             elsif (
8656              
8657             # added 2001-03-27: must not be followed immediately by '('
8658             # see fhandle.t
8659             ( $input_line !~ m/\G\(/gc )
8660              
8661             # and
8662             && (
8663              
8664             # preceded by keyword like 'print', 'printf' and friends
8665             $is_indirect_object_taker{$last_nonblank_token}
8666              
8667             # or preceded by something like 'print(' or 'printf('
8668             || (
8669             ( $last_nonblank_token eq '(' )
8670             && $is_indirect_object_taker{
8671             $rparen_type->[$paren_depth]
8672             }
8673              
8674             )
8675             )
8676             )
8677             {
8678              
8679             # may not be indirect object unless followed by a space;
8680             # updated 2021-01-16 to consider newline to be a space.
8681             # updated for case b990 to look for either ';' or space
8682 4 50 33     30 if ( pos($input_line) == length($input_line)
8683             || $input_line =~ m/\G[;\s]/gc )
8684             {
8685 4         7 $type = 'Y';
8686              
8687             # Abandon Hope ...
8688             # Perl's indirect object notation is a very bad
8689             # thing and can cause subtle bugs, especially for
8690             # beginning programmers. And I haven't even been
8691             # able to figure out a sane warning scheme which
8692             # doesn't get in the way of good scripts.
8693              
8694             # Complain if a filehandle has any lower case
8695             # letters. This is suggested good practice.
8696             # Use 'sub_name' because something like
8697             # main::MYHANDLE is ok for filehandle
8698 4 100       16 if ( $sub_name =~ /[a-z]/ ) {
8699              
8700             # could be bug caused by older perltidy if
8701             # followed by '('
8702 1 50       5 if ( $input_line =~ m/\G\s*\(/gc ) {
8703 1         5 $self->complain(
8704             "Caution: unknown word '$tok' in indirect object slot\n"
8705             );
8706             }
8707             }
8708             }
8709              
8710             # bareword not followed by a space -- may not be filehandle
8711             # (may be function call defined in a 'use' statement)
8712             else {
8713 0         0 $type = 'Z';
8714             }
8715             }
8716             else {
8717             ## none of the above special types
8718             }
8719             }
8720              
8721             # Now we must convert back from character position
8722             # to pre_token index.
8723             # I don't think an error flag can occur here ..but who knows
8724 1866         2289 my $error;
8725 1866         4183 ( $i, $error ) =
8726             inverse_pretoken_map( $i, $pos, $rtoken_map, $max_token_index );
8727 1866 50       3635 if ($error) {
8728 0         0 $self->warning(
8729             "scan_bare_identifier: Possibly invalid tokenization\n");
8730             }
8731             }
8732              
8733             # no match but line not blank - could be syntax error
8734             # perl will take '::' alone without complaint
8735             else {
8736 0         0 $type = 'w';
8737              
8738             # change this warning to log message if it becomes annoying
8739 0         0 $self->warning("didn't find identifier after leading ::\n");
8740             }
8741 1866         6547 return ( $i, $tok, $type, $prototype );
8742             } ## end sub scan_bare_identifier_do
8743              
8744             sub scan_id_do {
8745              
8746             my (
8747              
8748 425     425 0 1237 $self,
8749              
8750             $input_line,
8751             $i,
8752             $tok,
8753             $rtokens,
8754             $rtoken_map,
8755             $id_scan_state,
8756             $max_token_index,
8757              
8758             ) = @_;
8759              
8760             # Scan identifier following a type token.
8761             # Given:
8762             # current scan state variables
8763              
8764             # This is the new scanner and may eventually replace scan_identifier.
8765             # Only type 'sub' and 'package' are implemented.
8766             # Token types $ * % @ & -> are not yet implemented.
8767             #
8768             # The type of call depends on $id_scan_state: $id_scan_state = ''
8769             # for starting call, in which case $tok must be the token defining
8770             # the type.
8771             #
8772             # If the type token is the last nonblank token on the line, a value
8773             # of $id_scan_state = $tok is returned, indicating that further
8774             # calls must be made to get the identifier. If the type token is
8775             # not the last nonblank token on the line, the identifier is
8776             # scanned and handled and a value of '' is returned.
8777              
8778 44     44   345 use constant DEBUG_NSCAN => 0;
  44         80  
  44         57454  
8779 425         705 my $type = EMPTY_STRING;
8780 425         532 my $i_beg;
8781              
8782             #print "NSCAN:entering i=$i, tok=$tok, type=$type, state=$id_scan_state\n";
8783             #my ($a,$b,$c) = caller;
8784             #print "NSCAN: scan_id called with tok=$tok $a $b $c\n";
8785              
8786             # on re-entry, start scanning at first token on the line
8787 425 100       907 if ($id_scan_state) {
8788 10         16 $i_beg = $i;
8789 10         17 $type = EMPTY_STRING;
8790             }
8791              
8792             # on initial entry, start scanning just after type token
8793             else {
8794 415         632 $i_beg = $i + 1;
8795 415         578 $id_scan_state = $tok;
8796 415         711 $type = 't';
8797             }
8798              
8799             # find $i_beg = index of next nonblank token,
8800             # and handle empty lines
8801 425         576 my $blank_line = 0;
8802 425         613 my $is_lexical_method = 0;
8803 425         831 my $next_nonblank_token = $rtokens->[$i_beg];
8804 425 100       895 if ( $i_beg > $max_token_index ) {
8805 2         3 $blank_line = 1;
8806             }
8807             else {
8808              
8809             # only a '#' immediately after a '$' is not a comment
8810 423 50       949 if ( $next_nonblank_token eq '#' ) {
8811 0 0       0 if ( $tok ne '$' ) {
8812 0         0 $blank_line = 1;
8813             }
8814             }
8815              
8816 423 100       1445 if ( $next_nonblank_token =~ /^\s/ ) {
8817 403         1128 ( $next_nonblank_token, $i_beg ) =
8818             find_next_nonblank_token_on_this_line( $i_beg, $rtokens,
8819             $max_token_index );
8820 403 100       1804 if ( $next_nonblank_token =~ /(^#|^\s*$)/ ) {
8821 4         8 $blank_line = 1;
8822             }
8823             }
8824              
8825             # Patch for Object::Pad lexical method like 'method $var {':
8826             # Skip past a '$'
8827 423 100 100     1909 if ( !$blank_line
      66        
8828             && $next_nonblank_token eq '$'
8829             && $id_scan_state eq 'method' )
8830             {
8831 2         5 ( $next_nonblank_token, $i_beg ) =
8832             find_next_nonblank_token_on_this_line( $i_beg, $rtokens,
8833             $max_token_index );
8834 2         4 $is_lexical_method = 1;
8835             }
8836             }
8837              
8838             # handle non-blank line; identifier, if any, must follow
8839 425 100       880 if ( !$blank_line ) {
8840              
8841 419 100       930 if ( $is_sub{$id_scan_state} ) {
    50          
8842 369         3890 ( $i, $tok, $type, $id_scan_state ) = $self->do_scan_sub(
8843             {
8844             input_line => $input_line,
8845             i => $i,
8846             i_beg => $i_beg,
8847             tok => $tok,
8848             type => $type,
8849             rtokens => $rtokens,
8850             rtoken_map => $rtoken_map,
8851             id_scan_state => $id_scan_state,
8852             max_token_index => $max_token_index,
8853             is_lexical_method => $is_lexical_method,
8854             }
8855             );
8856             }
8857              
8858             elsif ( $is_package{$id_scan_state} ) {
8859 50         427 ( $i, $tok, $type ) = $self->do_scan_package(
8860             {
8861             input_line => $input_line,
8862             i => $i,
8863             i_beg => $i_beg,
8864             tok => $tok,
8865             type => $type,
8866             rtokens => $rtokens,
8867             rtoken_map => $rtoken_map,
8868             max_token_index => $max_token_index,
8869             }
8870             );
8871 50         184 $id_scan_state = EMPTY_STRING;
8872             }
8873              
8874             else {
8875 0         0 $self->warning("invalid token in scan_id: $tok\n");
8876 0         0 $id_scan_state = EMPTY_STRING;
8877             }
8878             }
8879              
8880 425 50 33     2044 if ( $id_scan_state && ( !defined($type) || !$type ) ) {
      66        
8881              
8882             # shouldn't happen:
8883 0         0 if (DEVEL_MODE) {
8884             Fault(<<EOM);
8885             Program bug in scan_id: undefined type but scan_state=$id_scan_state
8886             EOM
8887             }
8888             $self->warning(
8889 0         0 "Possible program bug in sub scan_id: undefined type but scan_state=$id_scan_state\n"
8890             );
8891 0         0 $self->report_definite_bug();
8892             }
8893              
8894 425         511 DEBUG_NSCAN && do {
8895             print {*STDOUT}
8896             "NSCAN: returns i=$i, tok=$tok, type=$type, state=$id_scan_state\n";
8897             };
8898 425         1327 return ( $i, $tok, $type, $id_scan_state );
8899             } ## end sub scan_id_do
8900              
8901             sub check_prototype {
8902 191     191 0 415 my ( $proto, $package, $subname ) = @_;
8903              
8904             # Classify a sub based on its prototype
8905 191 50       420 return if ( !defined($package) );
8906 191 50       459 return if ( !defined($subname) );
8907 191 100       526 if ( defined($proto) ) {
8908 34         160 $proto =~ s/^\s*\(\s*//;
8909 34         119 $proto =~ s/\s*\)$//;
8910 34 100       88 if ($proto) {
8911 5         15 $ris_user_function->{$package}->{$subname} = 1;
8912 5         15 $ruser_function_prototype->{$package}->{$subname} = "($proto)";
8913              
8914             # prototypes containing '&' must be treated specially..
8915 5 100       18 if ( $proto =~ /\&/ ) {
8916              
8917             # right curly braces of prototypes ending in
8918             # '&' may be followed by an operator
8919 1 50       4 if ( $proto =~ /\&$/ ) {
8920 0         0 $ris_block_function->{$package}->{$subname} = 1;
8921             }
8922              
8923             # right curly braces of prototypes NOT ending in
8924             # '&' may NOT be followed by an operator
8925             else {
8926 1         4 $ris_block_list_function->{$package}->{$subname} = 1;
8927             }
8928             }
8929             }
8930             else {
8931 29         80 $ris_constant->{$package}->{$subname} = 1;
8932             }
8933             }
8934             else {
8935 157         463 $ris_user_function->{$package}->{$subname} = 1;
8936             }
8937 191         368 return;
8938             } ## end sub check_prototype
8939              
8940             sub do_scan_package {
8941              
8942 50     50 0 104 my ( $self, $rcall_hash ) = @_;
8943              
8944             # Parse a package name.
8945              
8946 50         80 my $input_line = $rcall_hash->{input_line};
8947 50         77 my $i = $rcall_hash->{i};
8948 50         70 my $i_beg = $rcall_hash->{i_beg};
8949 50         94 my $tok = $rcall_hash->{tok};
8950 50         82 my $type = $rcall_hash->{type};
8951 50         75 my $rtokens = $rcall_hash->{rtokens};
8952 50         100 my $rtoken_map = $rcall_hash->{rtoken_map};
8953 50         69 my $max_token_index = $rcall_hash->{max_token_index};
8954              
8955             # This is called with $i_beg equal to the index of the first nonblank
8956             # token following a 'package' token.
8957             # USES GLOBAL VARIABLES: $current_package,
8958              
8959             # package NAMESPACE
8960             # package NAMESPACE VERSION
8961             # package NAMESPACE BLOCK
8962             # package NAMESPACE VERSION BLOCK
8963             #
8964             # If VERSION is provided, package sets the $VERSION variable in the given
8965             # namespace to a version object with the VERSION provided. VERSION must be
8966             # a "strict" style version number as defined by the version module: a
8967             # positive decimal number (integer or decimal-fraction) without
8968             # exponentiation or else a dotted-decimal v-string with a leading 'v'
8969             # character and at least three components.
8970             # reference http://perldoc.perl.org/functions/package.html
8971              
8972 50         95 my $package = undef;
8973 50         74 my $pos_beg = $rtoken_map->[$i_beg];
8974 50         185 pos($input_line) = $pos_beg;
8975              
8976             # handle non-blank line; package name, if any, must follow
8977 50 50       267 if ( $input_line =~ m/\G\s*((?:\w*(?:'|::))*\w*)/gc ) {
8978 50         113 $package = $1;
8979 50 50 33     256 $package = ( defined($1) && $1 ) ? $1 : 'main';
8980 50         112 $package =~ s/\'/::/g;
8981 50 50       132 if ( $package =~ /^\:/ ) { $package = 'main' . $package }
  0         0  
8982 50         79 $package =~ s/::$//;
8983 50         72 my $pos = pos($input_line);
8984 50         76 my $numc = $pos - $pos_beg;
8985 50         116 $tok = 'package ' . substr( $input_line, $pos_beg, $numc );
8986 50         70 $type = 'P'; # Fix for c250, previously 'i'
8987              
8988             # Now we must convert back from character position
8989             # to pre_token index.
8990             # I don't think an error flag can occur here ..but ?
8991 50         55 my $error;
8992 50         182 ( $i, $error ) =
8993             inverse_pretoken_map( $i, $pos, $rtoken_map, $max_token_index );
8994 50 50       116 if ($error) { $self->warning("Possibly invalid package\n") }
  0         0  
8995 50         79 $current_package = $package;
8996              
8997             # we should now have package NAMESPACE
8998             # now expecting VERSION, BLOCK, or ; to follow ...
8999             # package NAMESPACE VERSION
9000             # package NAMESPACE BLOCK
9001             # package NAMESPACE VERSION BLOCK
9002 50         183 my ( $next_nonblank_token, $i_next_uu ) =
9003             $self->find_next_nonblank_token( $i, $rtokens, $max_token_index );
9004              
9005             # check that something recognizable follows, but do not parse.
9006             # A VERSION number will be parsed later as a number or v-string in the
9007             # normal way. What is important is to set the statement type if
9008             # everything looks okay so that the operator_expected() routine
9009             # knows that the number is in a package statement.
9010             # Examples of valid primitive tokens that might follow are:
9011             # 1235 . ; { } v3 v
9012             # FIX: added a '#' since a side comment may also follow
9013             # Added ':' for class attributes (for --use-feature=class, rt145706)
9014 50 50       174 if ( $next_nonblank_token =~ /^([v\.\d;\{\}\#\:])|v\d|\d+$/ ) {
9015 50         119 $statement_type = $tok;
9016             }
9017             else {
9018 0         0 $self->warning(
9019             "Unexpected '$next_nonblank_token' after package name '$tok'\n"
9020             );
9021             }
9022             }
9023              
9024             # no match but line not blank --
9025             # could be a label with name package, like package: , for example.
9026             else {
9027 0         0 $type = 'k';
9028             }
9029              
9030 50         169 return ( $i, $tok, $type );
9031             } ## end sub do_scan_package
9032              
9033             { ## begin closure for sub scan_complex_identifier
9034              
9035 44     44   350 use constant DEBUG_SCAN_ID => 0;
  44         68  
  44         4552  
9036              
9037             # Constant hash:
9038             my %is_special_variable_char;
9039              
9040             BEGIN {
9041              
9042             # These are the only characters which can (currently) form special
9043             # variables, like $^W: (issue c066).
9044 44     44   271 my @q = qw{
9045             ? A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ ] ^ _
9046             };
9047 44         110 push @q, BACKSLASH;
9048 44         149922 $is_special_variable_char{$_} = 1 for @q;
9049             } ## end BEGIN
9050              
9051             # These are the possible states for this scanner:
9052             my $scan_state_SIGIL = '$';
9053             my $scan_state_ALPHA = 'A';
9054             my $scan_state_COLON = ':';
9055             my $scan_state_LPAREN = '(';
9056             my $scan_state_RPAREN = ')';
9057             my $scan_state_AMPERSAND = '&';
9058             my $scan_state_SPLIT = '^';
9059              
9060             # Only these non-blank states may be returned to caller:
9061             my %is_returnable_scan_state = (
9062             $scan_state_SIGIL => 1,
9063             $scan_state_AMPERSAND => 1,
9064             );
9065              
9066             # USES GLOBAL VARIABLES:
9067             # $context, $last_nonblank_token, $last_nonblank_type
9068              
9069             #-----------
9070             # call args:
9071             #-----------
9072             my ( $i, $id_scan_state, $identifier, $rtokens, $max_token_index,
9073             $expecting, $container_type );
9074              
9075             #-------------------------------------------
9076             # my variables, re-initialized on each call:
9077             #-------------------------------------------
9078             my $i_begin; # starting index $i
9079             my $type; # returned identifier type
9080             my $tok_begin; # starting token
9081             my $tok; # returned token
9082             my $id_scan_state_begin; # starting scan state
9083             my $identifier_begin; # starting identifier
9084             my $i_save; # a last good index, in case of error
9085             my $message; # hold error message for log file
9086             my $tok_is_blank;
9087             my $last_tok_is_blank;
9088             my $in_prototype_or_signature;
9089             my $saw_alpha;
9090             my $saw_type;
9091             my $allow_tick;
9092              
9093             sub initialize_my_scan_id_vars {
9094              
9095             # Initialize all 'my' vars on entry
9096 551     551 0 766 $i_begin = $i;
9097 551         785 $type = EMPTY_STRING;
9098 551         841 $tok_begin = $rtokens->[$i_begin];
9099 551         780 $tok = $tok_begin;
9100 551 50       1096 if ( $tok_begin eq ':' ) { $tok_begin = '::' }
  0         0  
9101 551         781 $id_scan_state_begin = $id_scan_state;
9102 551         693 $identifier_begin = $identifier;
9103 551         707 $i_save = undef;
9104              
9105 551         1960 $message = EMPTY_STRING;
9106 551         756 $tok_is_blank = undef; # a flag to speed things up
9107 551         640 $last_tok_is_blank = undef;
9108              
9109 551   100     1465 $in_prototype_or_signature =
9110             $container_type && $container_type =~ /^sub\b/;
9111              
9112             # these flags will be used to help figure out the type:
9113 551         665 $saw_alpha = undef;
9114 551         674 $saw_type = undef;
9115              
9116             # allow old package separator (') except in 'use' statement
9117 551         809 $allow_tick = ( $last_nonblank_token ne 'use' );
9118 551         766 return;
9119             } ## end sub initialize_my_scan_id_vars
9120              
9121             #----------------------------------
9122             # Routines for handling scan states
9123             #----------------------------------
9124             sub do_id_scan_state_dollar {
9125              
9126 609     609 0 790 my $self = shift;
9127              
9128             # We saw a sigil, now looking to start a variable name
9129 609 100 66     3516 if ( $tok eq '$' ) {
    100 33        
    100          
    50          
    50          
    100          
    100          
    100          
    100          
9130              
9131 59         97 $identifier .= $tok;
9132              
9133             # we've got a punctuation variable if end of line (punct.t)
9134 59 50       154 if ( $i == $max_token_index ) {
9135 0         0 $type = 'i';
9136 0         0 $id_scan_state = EMPTY_STRING;
9137             }
9138             }
9139             elsif ( $tok =~ /^\w/ ) { # alphanumeric ..
9140 310         433 $saw_alpha = 1;
9141 310         431 $identifier .= $tok;
9142              
9143             # now need :: except for special digit vars like '$1' (c208)
9144 310 100       822 $id_scan_state = $tok =~ /^\d/ ? EMPTY_STRING : $scan_state_COLON;
9145             }
9146             elsif ( $tok eq '::' ) {
9147 16         30 $id_scan_state = $scan_state_ALPHA;
9148 16         26 $identifier .= $tok;
9149             }
9150              
9151             # POSTDEFREF ->@ ->% ->& ->*
9152             elsif ( ( $tok =~ /^[\@\%\&\*]$/ ) && $identifier =~ /\-\>$/ ) {
9153 0         0 $identifier .= $tok;
9154             }
9155             elsif ( $tok eq "'" && $allow_tick ) { # alphanumeric ..
9156 0         0 $saw_alpha = 1;
9157 0         0 $id_scan_state = $scan_state_COLON; # now need ::
9158 0         0 $identifier .= $tok;
9159              
9160             # Perl will accept leading digits in identifiers,
9161             # although they may not always produce useful results.
9162             # Something like $main::0 is ok. But this also works:
9163             #
9164             # sub howdy::123::bubba{ print "bubba $54321!\n" }
9165             # howdy::123::bubba();
9166             #
9167             }
9168             elsif ( $tok eq '#' ) {
9169              
9170 100         168 my $is_punct_var = $identifier eq '$$';
9171              
9172             # side comment or identifier?
9173 100 100 66     899 if (
      66        
      66        
      33        
9174              
9175             # A '#' starts a comment if it follows a space. For example,
9176             # the following is equivalent to $ans=40.
9177             # my $ #
9178             # ans = 40;
9179             !$last_tok_is_blank
9180              
9181             # a # inside a prototype or signature can only start a
9182             # comment
9183             && !$in_prototype_or_signature
9184              
9185             # these are valid punctuation vars: *# %# @# $#
9186             # May also be '$#array' or POSTDEFREF ->$#
9187             && ( $identifier =~ /^[\%\@\$\*]$/
9188             || $identifier =~ /\$$/ )
9189              
9190             # but a '#' after '$$' is a side comment; see c147
9191             && !$is_punct_var
9192              
9193             )
9194             {
9195 96         197 $identifier .= $tok; # keep same state, a $ could follow
9196             }
9197             else {
9198              
9199             # otherwise it is a side comment
9200 4 50       15 if ( $identifier eq '->' ) { }
    50          
    50          
9201 0         0 elsif ($is_punct_var) { $type = 'i' }
9202 4         5 elsif ( $id_scan_state eq $scan_state_SIGIL ) { $type = 't' }
9203 0         0 else { $type = 'i' }
9204 4         5 $i = $i_save;
9205 4         5 $id_scan_state = EMPTY_STRING;
9206             }
9207             }
9208              
9209             elsif ( $tok eq '{' ) {
9210              
9211             # check for something like ${#} or ${?}, where ? is a special char
9212 47 100 100     440 if (
      66        
      100        
      100        
9213             (
9214             $identifier eq '$'
9215             || $identifier eq '@'
9216             || $identifier eq '$#'
9217             )
9218             && $i + 2 <= $max_token_index
9219             && $rtokens->[ $i + 2 ] eq '}'
9220             && $rtokens->[ $i + 1 ] !~ /[\s\w]/
9221             )
9222             {
9223 1         2 my $next2 = $rtokens->[ $i + 2 ];
9224 1         2 my $next1 = $rtokens->[ $i + 1 ];
9225 1         2 $identifier .= $tok . $next1 . $next2;
9226 1         2 $i += 2;
9227 1         2 $id_scan_state = EMPTY_STRING;
9228             }
9229             else {
9230              
9231             # skip something like ${xxx} or ->{
9232 46         73 $id_scan_state = EMPTY_STRING;
9233              
9234             # if this is the first token of a line, any tokens for this
9235             # identifier have already been accumulated
9236 46 100 66     159 if ( $identifier eq '$' || $i == 0 ) {
9237 31         54 $identifier = EMPTY_STRING;
9238             }
9239 46         91 $i = $i_save;
9240             }
9241             }
9242              
9243             # space ok after leading $ % * & @
9244             elsif ( $tok =~ /^\s*$/ ) {
9245              
9246 20         36 $tok_is_blank = 1;
9247              
9248             # note: an id with a leading '&' does not actually come this way
9249 20 50       71 if ( $identifier =~ /^[\$\%\*\&\@]/ ) {
    0          
9250              
9251 20 100       55 if ( length($identifier) > 1 ) {
9252 8         12 $id_scan_state = EMPTY_STRING;
9253 8         9 $i = $i_save;
9254 8         15 $type = 'i'; # probably punctuation variable
9255             }
9256             else {
9257              
9258             # fix c139: trim line-ending type 't'
9259 12 100       47 if ( $i == $max_token_index ) {
    100          
9260 1         3 $i = $i_save;
9261 1         2 $type = 't';
9262             }
9263              
9264             # spaces after $'s are common, and space after @
9265             # is harmless, so only complain about space
9266             # after other type characters. Space after $ and
9267             # @ will be removed in formatting. Report space
9268             # after % and * because they might indicate a
9269             # parsing error. In other words '% ' might be a
9270             # modulo operator. Delete this warning if it
9271             # gets annoying.
9272             elsif ( $identifier !~ /^[\@\$]$/ ) {
9273 1         3 $message =
9274             "Space in identifier, following $identifier\n";
9275             }
9276             else {
9277             ## silently accept space after '$' and '@' sigils
9278             }
9279             }
9280             }
9281              
9282             elsif ( $identifier eq '->' ) {
9283              
9284             # space after '->' is ok except at line end ..
9285             # so trim line-ending in type '->' (fixes c139)
9286 0 0       0 if ( $i == $max_token_index ) {
9287 0         0 $i = $i_save;
9288 0         0 $type = '->';
9289             }
9290             }
9291              
9292             # stop at space after something other than -> or sigil
9293             # Example of what can arrive here:
9294             # eval { $MyClass->$$ };
9295             else {
9296 0         0 $id_scan_state = EMPTY_STRING;
9297 0         0 $i = $i_save;
9298 0         0 $type = 'i';
9299             }
9300             }
9301             elsif ( $tok eq '^' ) {
9302              
9303             # check for some special variables like $^ $^W
9304 11 50       33 if ( $identifier =~ /^[\$\*\@\%]$/ ) {
9305 11         23 $identifier .= $tok;
9306 11         16 $type = 'i';
9307              
9308             # There may be one more character, not a space, after the ^
9309 11         19 my $next1 = $rtokens->[ $i + 1 ];
9310 11         23 my $chr = substr( $next1, 0, 1 );
9311 11 100       33 if ( $is_special_variable_char{$chr} ) {
9312              
9313             # It is something like $^W
9314             # Test case (c066) : $^Oeq'linux'
9315 9         14 $i++;
9316 9         13 $identifier .= $next1;
9317              
9318             # If pretoken $next1 is more than one character long,
9319             # set a flag indicating that it needs to be split.
9320 9 100       30 $id_scan_state =
9321             ( length($next1) > 1 ) ? $scan_state_SPLIT : EMPTY_STRING;
9322             }
9323             else {
9324              
9325             # it is just $^
9326             # Simple test case (c065): '$aa=$^if($bb)';
9327 2         3 $id_scan_state = EMPTY_STRING;
9328             }
9329             }
9330             else {
9331 0         0 $id_scan_state = EMPTY_STRING;
9332 0         0 $i = $i_save;
9333             }
9334             }
9335             else { # something else
9336              
9337 46 100 66     411 if ( $in_prototype_or_signature && $tok =~ /^[\),=#]/ ) {
    100 66        
    100          
    50          
    0          
    0          
9338              
9339             # We might be in an extrusion of
9340             # sub foo2 ( $first, $, $third ) {
9341             # looking at a line starting with a comma, like
9342             # $
9343             # ,
9344             # in this case the comma ends the signature variable
9345             # '$' which will have been previously marked type 't'
9346             # rather than 'i'.
9347 3 100       7 if ( $i == $i_begin ) {
9348 1         1 $identifier = EMPTY_STRING;
9349 1         4 $type = EMPTY_STRING;
9350             }
9351              
9352             # at a # we have to mark as type 't' because more may
9353             # follow, otherwise, in a signature we can let '$' be an
9354             # identifier here for better formatting.
9355             # See 'mangle4.in' for a test case.
9356             else {
9357 2         5 $type = 'i';
9358 2 50 33     12 if ( $id_scan_state eq $scan_state_SIGIL && $tok eq '#' ) {
9359 0         0 $type = 't';
9360             }
9361 2         2 $i = $i_save;
9362             }
9363 3         5 $id_scan_state = EMPTY_STRING;
9364             }
9365              
9366             # check for various punctuation variables
9367             elsif ( $identifier =~ /^[\$\*\@\%]$/ ) {
9368 35         89 $identifier .= $tok;
9369             }
9370              
9371             # POSTDEFREF: Postfix reference ->$* ->%* ->@* ->** ->&* ->$#*
9372             elsif ($tok eq '*'
9373             && $identifier =~ /\-\>([\@\%\$\*\&]|\$\#)$/ )
9374             {
9375 6         14 $identifier .= $tok;
9376             }
9377              
9378             elsif ( $identifier eq '$#' ) {
9379              
9380 2 50       9 if ( $tok eq '{' ) { $type = 'i'; $i = $i_save }
  0 50       0  
  0         0  
9381              
9382             # perl seems to allow just these: $#: $#- $#+
9383             elsif ( $tok =~ /^[\:\-\+]$/ ) {
9384 0         0 $type = 'i';
9385 0         0 $identifier .= $tok;
9386             }
9387             else {
9388 2         4 $i = $i_save;
9389 2         8 $self->write_logfile_entry(
9390             'Use of $# is deprecated' . "\n" );
9391             }
9392             }
9393             elsif ( $identifier eq '$$' ) {
9394              
9395             # perl does not allow references to punctuation
9396             # variables without braces. For example, this
9397             # won't work:
9398             # $:=\4;
9399             # $a = $$:;
9400             # You would have to use
9401             # $a = ${$:};
9402              
9403             # '$$' alone is punctuation variable for PID
9404 0         0 $i = $i_save;
9405 0 0       0 if ( $tok eq '{' ) { $type = 't' }
  0         0  
9406 0         0 else { $type = 'i' }
9407             }
9408             elsif ( $identifier eq '->' ) {
9409 0         0 $i = $i_save;
9410             }
9411             else {
9412 0         0 $i = $i_save;
9413 0 0       0 if ( length($identifier) == 1 ) {
9414 0         0 $identifier = EMPTY_STRING;
9415             }
9416             }
9417 46         1257 $id_scan_state = EMPTY_STRING;
9418             }
9419 609         848 return;
9420             } ## end sub do_id_scan_state_dollar
9421              
9422             sub do_id_scan_state_alpha {
9423              
9424 119     119 0 147 my $self = shift;
9425              
9426             # looking for alphanumeric after ::
9427 119         238 $tok_is_blank = $tok =~ /^\s*$/;
9428              
9429 119 100 33     332 if ( $tok =~ /^\w/ ) { # found it
    50 66        
    50 33        
    50          
9430 106         158 $identifier .= $tok;
9431 106         134 $id_scan_state = $scan_state_COLON; # now need ::
9432 106         138 $saw_alpha = 1;
9433             }
9434             elsif ( $tok eq "'" && $allow_tick ) {
9435 0         0 $identifier .= $tok;
9436 0         0 $id_scan_state = $scan_state_COLON; # now need ::
9437 0         0 $saw_alpha = 1;
9438             }
9439             elsif ( $tok_is_blank && $identifier =~ /^sub / ) {
9440 0         0 $id_scan_state = $scan_state_LPAREN;
9441 0         0 $identifier .= $tok;
9442             }
9443             elsif ( $tok eq '(' && $identifier =~ /^sub / ) {
9444 0         0 $id_scan_state = $scan_state_RPAREN;
9445 0         0 $identifier .= $tok;
9446             }
9447             else {
9448 13         20 $id_scan_state = EMPTY_STRING;
9449 13         15 $i = $i_save;
9450             }
9451 119         159 return;
9452             } ## end sub do_id_scan_state_alpha
9453              
9454             sub do_id_scan_state_colon {
9455              
9456 470     470 0 574 my $self = shift;
9457              
9458             # looking for possible :: after alphanumeric
9459              
9460 470         1165 $tok_is_blank = $tok =~ /^\s*$/;
9461              
9462 470 100 66     2845 if ( $tok eq '::' ) { # got it
    100 66        
    100 66        
    50          
    50          
9463 103         147 $identifier .= $tok;
9464 103         123 $id_scan_state = $scan_state_ALPHA; # now require alpha
9465             }
9466             elsif ( $tok =~ /^\w/ ) { # more alphanumeric is ok here
9467 20         30 $identifier .= $tok;
9468 20         25 $id_scan_state = $scan_state_COLON; # now need ::
9469 20         24 $saw_alpha = 1;
9470             }
9471             elsif ( $tok eq "'" && $allow_tick ) { # tick
9472              
9473 12 50       21 if ( $is_keyword{$identifier} ) {
9474 0         0 $id_scan_state = EMPTY_STRING; # that's all
9475 0         0 $i = $i_save;
9476             }
9477             else {
9478 12         13 $identifier .= $tok;
9479             }
9480             }
9481             elsif ( $tok_is_blank && $identifier =~ /^sub / ) {
9482 0         0 $id_scan_state = $scan_state_LPAREN;
9483 0         0 $identifier .= $tok;
9484             }
9485             elsif ( $tok eq '(' && $identifier =~ /^sub / ) {
9486 0         0 $id_scan_state = $scan_state_RPAREN;
9487 0         0 $identifier .= $tok;
9488             }
9489             else {
9490 335         474 $id_scan_state = EMPTY_STRING; # that's all
9491 335         435 $i = $i_save;
9492             }
9493 470         597 return;
9494             } ## end sub do_id_scan_state_colon
9495              
9496             sub do_id_scan_state_left_paren {
9497              
9498 0     0 0 0 my $self = shift;
9499              
9500             # looking for possible '(' of a prototype
9501              
9502 0 0       0 if ( $tok eq '(' ) { # got it
    0          
9503 0         0 $identifier .= $tok;
9504 0         0 $id_scan_state = $scan_state_RPAREN; # now find the end of it
9505             }
9506             elsif ( $tok =~ /^\s*$/ ) { # blank - keep going
9507 0         0 $identifier .= $tok;
9508 0         0 $tok_is_blank = 1;
9509             }
9510             else {
9511 0         0 $id_scan_state = EMPTY_STRING; # that's all - no prototype
9512 0         0 $i = $i_save;
9513             }
9514 0         0 return;
9515             } ## end sub do_id_scan_state_left_paren
9516              
9517             sub do_id_scan_state_right_paren {
9518              
9519 0     0 0 0 my $self = shift;
9520              
9521             # looking for a ')' of prototype to close a '('
9522              
9523 0         0 $tok_is_blank = $tok =~ /^\s*$/;
9524              
9525 0 0       0 if ( $tok eq ')' ) { # got it
    0          
9526 0         0 $identifier .= $tok;
9527 0         0 $id_scan_state = EMPTY_STRING; # all done
9528             }
9529             elsif ( $tok =~ /^[\s\$\%\\\*\@\&\;]/ ) {
9530 0         0 $identifier .= $tok;
9531             }
9532             else { # probable error in script, but keep going
9533 0         0 $self->warning(
9534             "Unexpected '$tok' while seeking end of prototype\n");
9535 0         0 $identifier .= $tok;
9536             }
9537 0         0 return;
9538             } ## end sub do_id_scan_state_right_paren
9539              
9540             sub do_id_scan_state_ampersand {
9541              
9542 104     104 0 156 my $self = shift;
9543              
9544             # Starting sub call after seeing an '&'
9545 104 100 33     523 if ( $tok =~ /^[\$\w]/ ) { # alphanumeric ..
    50          
    100          
    50          
    50          
    0          
9546 87         142 $id_scan_state = $scan_state_COLON; # now need ::
9547 87         114 $saw_alpha = 1;
9548 87         145 $identifier .= $tok;
9549             }
9550             elsif ( $tok eq "'" && $allow_tick ) { # alphanumeric ..
9551 0         0 $id_scan_state = $scan_state_COLON; # now need ::
9552 0         0 $saw_alpha = 1;
9553 0         0 $identifier .= $tok;
9554             }
9555             elsif ( $tok =~ /^\s*$/ ) { # allow space
9556 2         3 $tok_is_blank = 1;
9557              
9558             # fix c139: trim line-ending type 't'
9559 2 50 33     7 if ( length($identifier) == 1 && $i == $max_token_index ) {
9560 2         3 $i = $i_save;
9561 2         20 $type = 't';
9562             }
9563             }
9564             elsif ( $tok eq '::' ) { # leading ::
9565 0         0 $id_scan_state = $scan_state_ALPHA; # accept alpha next
9566 0         0 $identifier .= $tok;
9567             }
9568             elsif ( $tok eq '{' ) {
9569 15 50 33     53 if ( $identifier eq '&' || $i == 0 ) {
9570 15         45 $identifier = EMPTY_STRING;
9571             }
9572 15         27 $i = $i_save;
9573 15         22 $id_scan_state = EMPTY_STRING;
9574             }
9575             elsif ( $tok eq '^' ) {
9576 0 0       0 if ( $identifier eq '&' ) {
9577              
9578             # Special variable (c066)
9579 0         0 $identifier .= $tok;
9580 0         0 $type = 'i';
9581              
9582             # To be a special $^ variable, there may be one more character,
9583             # not a space, after the ^
9584 0         0 my $next1 = $rtokens->[ $i + 1 ];
9585 0         0 my $chr = substr( $next1, 0, 1 );
9586 0 0       0 if ( $is_special_variable_char{$chr} ) {
9587              
9588             # It is something like &^O
9589 0         0 $i++;
9590 0         0 $identifier .= $next1;
9591              
9592             # If pretoken $next1 is more than one character long,
9593             # set a flag indicating that it needs to be split.
9594 0 0       0 $id_scan_state =
9595             ( length($next1) > 1 ) ? $scan_state_SPLIT : EMPTY_STRING;
9596             }
9597             else {
9598              
9599             # It is &^. This is parsed by perl as a call to sub '^',
9600             # even though it would be difficult to create a sub '^'.
9601             # So we mark it as an identifier (c068).
9602 0         0 $id_scan_state = EMPTY_STRING;
9603             }
9604             }
9605             else {
9606 0         0 $identifier = EMPTY_STRING;
9607 0         0 $i = $i_save;
9608             }
9609             }
9610             else {
9611              
9612             # punctuation variable?
9613             # testfile: cunningham4.pl
9614             #
9615             # We have to be careful here. If we are in an unknown state,
9616             # we will reject the punctuation variable. In the following
9617             # example the '&' is a binary operator but we are in an unknown
9618             # state because there is no sigil on 'Prima', so we don't
9619             # know what it is. But it is a bad guess that
9620             # '&~' is a function variable.
9621             # $self->{text}->{colorMap}->[
9622             # Prima::PodView::COLOR_CODE_FOREGROUND
9623             # & ~tb::COLOR_INDEX ] =
9624             # $sec->{ColorCode}
9625              
9626             # Fix for case c033: a '#' here starts a side comment
9627 0 0 0     0 if ( $identifier eq '&' && $expecting && $tok ne '#' ) {
      0        
9628 0         0 $identifier .= $tok;
9629             }
9630             else {
9631 0         0 $identifier = EMPTY_STRING;
9632 0         0 $i = $i_save;
9633 0         0 $type = '&';
9634             }
9635 0         0 $id_scan_state = EMPTY_STRING;
9636             }
9637 104         178 return;
9638             } ## end sub do_id_scan_state_ampersand
9639              
9640             #-------------------
9641             # hash of scanner subs
9642             #-------------------
9643             my $scan_identifier_code = {
9644             $scan_state_SIGIL => \&do_id_scan_state_dollar,
9645             $scan_state_ALPHA => \&do_id_scan_state_alpha,
9646             $scan_state_COLON => \&do_id_scan_state_colon,
9647             $scan_state_LPAREN => \&do_id_scan_state_left_paren,
9648             $scan_state_RPAREN => \&do_id_scan_state_right_paren,
9649             $scan_state_AMPERSAND => \&do_id_scan_state_ampersand,
9650             };
9651              
9652             sub scan_complex_identifier {
9653              
9654             (
9655 551     551 0 1570 my $self,
9656              
9657             $i,
9658             $id_scan_state,
9659             $identifier,
9660             $rtokens,
9661             $max_token_index,
9662             $expecting,
9663             $container_type,
9664              
9665             ) = @_;
9666              
9667             # This routine assembles tokens into identifiers. It maintains a
9668             # scan state, id_scan_state. It updates id_scan_state based upon
9669             # current id_scan_state and token, and returns an updated
9670             # id_scan_state and the next index after the identifier.
9671              
9672             # This routine now serves a backup for sub scan_simple_identifier
9673             # which handles most identifiers.
9674              
9675             # Note that $self must be a 'my' variable and not be a closure
9676             # variables like the other args. Otherwise it will not get
9677             # deleted by a DESTROY call at the end of a file. Then an
9678             # attempt to create multiple tokenizers can occur when multiple
9679             # files are processed, causing an error.
9680              
9681             # return flag telling caller to split the pretoken
9682 551         2474 my $split_pretoken_flag;
9683              
9684             #-------------------
9685             # Initialize my vars
9686             #-------------------
9687              
9688 551         1419 initialize_my_scan_id_vars();
9689              
9690             #--------------------------------------------------------
9691             # get started by defining a type and a state if necessary
9692             #--------------------------------------------------------
9693              
9694 551 100       1041 if ( !$id_scan_state ) {
9695 544         703 $context = UNKNOWN_CONTEXT;
9696              
9697             # fixup for digraph
9698 544 50       1043 if ( $tok eq '>' ) {
9699 0         0 $tok = '->';
9700 0         0 $tok_begin = $tok;
9701             }
9702 544         782 $identifier = $tok;
9703              
9704 544 100 100     2589 if ( $last_nonblank_token eq '->' ) {
    100 100        
    100 0        
    50          
    0          
    0          
    0          
    0          
9705 8         15 $identifier = '->' . $identifier;
9706 8         13 $id_scan_state = $scan_state_SIGIL;
9707             }
9708             elsif ( $tok eq '$' || $tok eq '*' ) {
9709 355         541 $id_scan_state = $scan_state_SIGIL;
9710 355         501 $context = SCALAR_CONTEXT;
9711             }
9712             elsif ( $tok eq '%' || $tok eq '@' ) {
9713 79         129 $id_scan_state = $scan_state_SIGIL;
9714 79         111 $context = LIST_CONTEXT;
9715             }
9716             elsif ( $tok eq '&' ) {
9717 102         162 $id_scan_state = $scan_state_AMPERSAND;
9718             }
9719             elsif ( $tok eq 'sub' or $tok eq 'package' ) {
9720 0         0 $saw_alpha = 0; # 'sub' is considered type info here
9721 0         0 $id_scan_state = $scan_state_SIGIL;
9722 0         0 $identifier .=
9723             SPACE; # need a space to separate sub from sub name
9724             }
9725             elsif ( $tok eq '::' ) {
9726 0         0 $id_scan_state = $scan_state_ALPHA;
9727             }
9728             elsif ( $tok =~ /^\w/ ) {
9729 0         0 $id_scan_state = $scan_state_COLON;
9730 0         0 $saw_alpha = 1;
9731             }
9732             elsif ( $tok eq '->' ) {
9733 0         0 $id_scan_state = $scan_state_SIGIL;
9734             }
9735             else {
9736              
9737             # shouldn't happen: bad call parameter
9738 0         0 my $msg =
9739             "Program bug detected: scan_complex_identifier received bad starting token = '$tok'\n";
9740 0         0 if (DEVEL_MODE) { Fault($msg) }
9741 0 0       0 if ( !$self->[_in_error_] ) {
9742 0         0 $self->warning($msg);
9743 0         0 $self->[_in_error_] = 1;
9744             }
9745 0         0 $id_scan_state = EMPTY_STRING;
9746              
9747             # emergency return
9748 0         0 goto SCAN_ID_EMERGENCY_RETURN;
9749             }
9750 544         758 $saw_type = !$saw_alpha;
9751             }
9752             else {
9753 7         11 $i--;
9754 7         19 $saw_alpha = ( $tok =~ /^\w/ );
9755 7         16 $saw_type = ( $tok =~ /([\$\%\@\*\&])/ );
9756              
9757             # check for a valid starting state
9758 7         8 if ( DEVEL_MODE && !$is_returnable_scan_state{$id_scan_state} ) {
9759             Fault(<<EOM);
9760             Unexpected starting scan state in sub scan_complex_identifier: '$id_scan_state'
9761             EOM
9762             }
9763             }
9764              
9765             #------------------------------
9766             # loop to gather the identifier
9767             #------------------------------
9768              
9769 551         741 $i_save = $i;
9770              
9771 551   100     1819 while ( $i < $max_token_index && $id_scan_state ) {
9772              
9773             # Be sure we have code to handle this state before we proceed
9774 1305         1982 my $code = $scan_identifier_code->{$id_scan_state};
9775 1305 100       1948 if ( !$code ) {
9776              
9777 3 50       7 if ( $id_scan_state eq $scan_state_SPLIT ) {
9778             ## OK: this is the signal to exit and split the pretoken
9779             }
9780              
9781             # unknown state - should not happen
9782             else {
9783 0         0 if (DEVEL_MODE) {
9784             Fault(<<EOM);
9785             Unknown scan state in sub scan_complex_identifier: '$id_scan_state'
9786             Scan state at sub entry was '$id_scan_state_begin'
9787             EOM
9788             }
9789 0         0 $id_scan_state = EMPTY_STRING;
9790 0         0 $i = $i_save;
9791             }
9792 3         5 last;
9793             }
9794              
9795             # Remember the starting index for progress check below
9796 1302         1476 my $i_start_loop = $i;
9797              
9798 1302         1447 $last_tok_is_blank = $tok_is_blank;
9799 1302 100       1704 if ($tok_is_blank) { $tok_is_blank = undef }
  11         16  
9800 1291         1391 else { $i_save = $i }
9801              
9802 1302         1728 $tok = $rtokens->[ ++$i ];
9803              
9804             # patch to make digraph :: if necessary
9805 1302 100 100     2525 if ( ( $tok eq ':' ) && ( $rtokens->[ $i + 1 ] eq ':' ) ) {
9806 119         150 $tok = '::';
9807 119         138 $i++;
9808             }
9809              
9810 1302         2587 $code->($self);
9811              
9812             # check for forward progress: a decrease in the index $i
9813             # implies that scanning has finished
9814 1302 100       3245 last if ( $i <= $i_start_loop );
9815              
9816             } ## end while ( $i < $max_token_index...)
9817              
9818             #-------------
9819             # Check result
9820             #-------------
9821              
9822             # Be sure a valid state is returned
9823 551 100       1037 if ($id_scan_state) {
9824              
9825 24 100       75 if ( !$is_returnable_scan_state{$id_scan_state} ) {
9826              
9827 17 100       45 if ( $id_scan_state eq $scan_state_SPLIT ) {
9828 3         5 $split_pretoken_flag = 1;
9829             }
9830              
9831 17 50       55 if ( $id_scan_state eq $scan_state_RPAREN ) {
9832 0         0 $self->warning(
9833             "Hit end of line while seeking ) to end prototype\n");
9834             }
9835              
9836 17         31 $id_scan_state = EMPTY_STRING;
9837             }
9838              
9839             # Patch: the deprecated variable $# does not combine with anything
9840             # on the next line.
9841 24 50       60 if ( $identifier eq '$#' ) { $id_scan_state = EMPTY_STRING }
  0         0  
9842             }
9843              
9844             # Be sure the token index is valid
9845 551 50       1082 if ( $i < 0 ) { $i = 0 }
  0         0  
9846              
9847             # Be sure a token type is defined
9848 551 100       1004 if ( !$type ) {
9849              
9850 523 100       939 if ($saw_type) {
    100          
9851              
9852 517 100 66     1701 if ($saw_alpha) {
    50 100        
    100 66        
      66        
9853              
9854             # The type without the -> should be the same as with the -> so
9855             # that if they get separated we get the same bond strengths,
9856             # etc. See b1234
9857 404 50 66     1274 if ( $identifier =~ /^->/
      33        
9858             && $last_nonblank_type eq 'w'
9859             && substr( $identifier, 2, 1 ) =~ /^\w/ )
9860             {
9861 0         0 $type = 'w';
9862             }
9863 404         649 else { $type = 'i' }
9864             }
9865             elsif ( $identifier eq '->' ) {
9866 0         0 $type = '->';
9867             }
9868             elsif (
9869             ( length($identifier) > 1 )
9870              
9871             # In something like '@$=' we have an identifier '@$'
9872             # In something like '$${' we have type '$$' (and only
9873             # part of an identifier)
9874             && !( $identifier =~ /\$$/ && $tok eq '{' )
9875             && $identifier ne 'sub '
9876             && $identifier ne 'package '
9877             )
9878             {
9879 53         110 $type = 'i';
9880             }
9881 60         117 else { $type = 't' }
9882             }
9883             elsif ($saw_alpha) {
9884              
9885             # type 'w' includes anything without leading type info
9886             # ($,%,@,*) including something like abc::def::ghi
9887 5         5 $type = 'w';
9888              
9889             # Fix for b1337, if restarting scan after line break between
9890             # '->' or sigil and identifier name, use type 'i'
9891 5 50 33     22 if ( $id_scan_state_begin
9892             && $identifier =~ /^([\$\%\@\*\&]|->)/ )
9893             {
9894 5         8 $type = 'i';
9895             }
9896             }
9897             else {
9898 1         2 $type = EMPTY_STRING;
9899             } # this can happen on a restart
9900             }
9901              
9902             # See if we formed an identifier...
9903 551 100       900 if ($identifier) {
9904 504         673 $tok = $identifier;
9905 504 100       976 if ($message) { $self->write_logfile_entry($message) }
  1         6  
9906             }
9907              
9908             # did not find an identifier, back up
9909             else {
9910 47         63 $tok = $tok_begin;
9911 47         67 $i = $i_begin;
9912             }
9913              
9914             SCAN_ID_EMERGENCY_RETURN:
9915              
9916 551         611 DEBUG_SCAN_ID && do {
9917             my ( $a, $b, $c ) = caller();
9918             print {*STDOUT}
9919             "SCANID: called from $a $b $c with tok, i, state, identifier =$tok_begin, $i_begin, $id_scan_state_begin, $identifier_begin\n";
9920             print {*STDOUT}
9921             "SCANID: returned with tok, i, state, identifier =$tok, $i, $id_scan_state, $identifier\n";
9922             };
9923              
9924             return (
9925              
9926 551         2067 $i,
9927             $tok,
9928             $type,
9929             $id_scan_state,
9930             $identifier,
9931             $split_pretoken_flag,
9932             );
9933             } ## end sub scan_complex_identifier
9934             } ## end closure for sub scan_complex_identifier
9935              
9936             { ## closure for sub do_scan_sub
9937              
9938             # saved package and subnames in case prototype is on separate line
9939             my ( $package_saved, $subname_saved );
9940              
9941             # initialize subname each time a new 'sub' keyword is encountered
9942             sub initialize_subname {
9943 365     365 0 621 $package_saved = EMPTY_STRING;
9944 365         544 $subname_saved = EMPTY_STRING;
9945 365         512 return;
9946             }
9947              
9948             use constant {
9949 44         99543 SUB_CALL => 1,
9950             PAREN_CALL => 2,
9951             PROTOTYPE_CALL => 3,
9952 44     44   375 };
  44         83  
9953              
9954             sub do_scan_sub {
9955              
9956 371     371 0 756 my ( $self, $rcall_hash ) = @_;
9957              
9958             # Parse a sub name and prototype.
9959              
9960 371         699 my $input_line = $rcall_hash->{input_line};
9961 371         577 my $i = $rcall_hash->{i};
9962 371         588 my $i_beg = $rcall_hash->{i_beg};
9963 371         663 my $tok = $rcall_hash->{tok};
9964 371         537 my $type = $rcall_hash->{type};
9965 371         585 my $rtokens = $rcall_hash->{rtokens};
9966 371         555 my $rtoken_map = $rcall_hash->{rtoken_map};
9967 371         574 my $id_scan_state = $rcall_hash->{id_scan_state};
9968 371         504 my $max_token_index = $rcall_hash->{max_token_index};
9969              
9970 371 100       857 my $id_prefix = $rcall_hash->{is_lexical_method} ? '$' : EMPTY_STRING;
9971              
9972             # At present there are three basic CALL TYPES which are
9973             # distinguished by the starting value of '$tok':
9974             # 1. $tok='sub', id_scan_state='sub'
9975             # it is called with $i_beg equal to the index of the first nonblank
9976             # token following a 'sub' token.
9977             # 2. $tok='(', id_scan_state='sub',
9978             # it is called with $i_beg equal to the index of a '(' which may
9979             # start a prototype.
9980             # 3. $tok='prototype', id_scan_state='prototype'
9981             # it is called with $i_beg equal to the index of a '(' which is
9982             # preceded by ': prototype' and has $id_scan_state eq 'prototype'
9983              
9984             # Examples:
9985              
9986             # A single type 1 call will get both the sub and prototype
9987             # sub foo1 ( $$ ) { }
9988             # ^
9989              
9990             # The subname will be obtained with a 'sub' call
9991             # The prototype on line 2 will be obtained with a '(' call
9992             # sub foo1
9993             # ^ <---call type 1
9994             # ( $$ ) { }
9995             # ^ <---call type 2
9996              
9997             # The subname will be obtained with a 'sub' call
9998             # The prototype will be obtained with a 'prototype' call
9999             # sub foo1 ( $x, $y ) : prototype ( $$ ) { }
10000             # ^ <---type 1 ^ <---type 3
10001              
10002             # TODO: add future error checks to be sure we have a valid
10003             # sub name. For example, 'sub &doit' is wrong. Also, be sure
10004             # a name is given if and only if a non-anonymous sub is
10005             # appropriate.
10006             # USES GLOBAL VARS: $current_package, $last_nonblank_token,
10007             # $rsaw_function_definition,
10008             # $statement_type
10009              
10010 371         512 my $i_entry = $i;
10011              
10012             # Determine the CALL TYPE
10013             # 1=sub
10014             # 2=(
10015             # 3=prototype
10016 371 100       1076 my $call_type =
    100          
10017             $tok eq 'prototype' ? PROTOTYPE_CALL
10018             : $tok eq '(' ? PAREN_CALL
10019             : SUB_CALL;
10020              
10021 371         515 $id_scan_state = EMPTY_STRING; # normally we get everything in one call
10022 371         511 my $subname = $subname_saved;
10023 371         496 my $package = $package_saved;
10024 371         536 my $proto = undef;
10025 371         535 my $attrs = undef;
10026 371         445 my $match;
10027              
10028 371         617 my $pos_beg = $rtoken_map->[$i_beg];
10029 371         1144 pos($input_line) = $pos_beg;
10030              
10031             # Look for the sub NAME if this is a SUB call
10032 371 100 100     2664 if (
10033             $call_type == SUB_CALL
10034             && $input_line =~ m{\G\s*
10035             ((?:\w*(?:'|::))*) # package - something that ends in :: or '
10036             (\w+) # NAME - required
10037             }gcx
10038             )
10039             {
10040 176         303 $match = 1;
10041 176         403 $subname = $2;
10042             my $is_lexical_sub = $last_nonblank_type eq 'k'
10043 176   33     499 && $is_my_our_state{$last_nonblank_token};
10044 176 0 33     423 if ( $is_lexical_sub && $1 ) {
10045 0         0 $self->warning(
10046             "'$last_nonblank_token' sub $subname cannot be in package '$1'\n"
10047             );
10048 0         0 $is_lexical_sub = 0;
10049             }
10050              
10051 176 50       500 if ($is_lexical_sub) {
10052              
10053             # Lexical subs use the containing block sequence number as a
10054             # package name.
10055 0         0 my $seqno =
10056             $rcurrent_sequence_number->[BRACE]
10057             ->[ $rcurrent_depth->[BRACE] ];
10058 0 0       0 $seqno = SEQ_ROOT if ( !defined($seqno) );
10059 0         0 $package = $seqno;
10060              
10061             # The value will eventually be the sequence number of the
10062             # opening curly brace of the definition (if any). We use -1
10063             # until we find it.
10064 0         0 $ris_lexical_sub->{$subname}->{$package} = -1;
10065              
10066             # Set a special signal to tell sub do_LEFT_CURLY_BRACKET to
10067             # update this value if the next opening sub block brace is for
10068             # this sub. The reason we need this value is to avoid applying
10069             # this new sub in its own definition block. Note that '911' is
10070             # not a possible sub name. Search for '911' for related code.
10071 0         0 $ris_lexical_sub->{911} = [ $subname, $package ];
10072              
10073             # Complain if lexical sub name hides a quote operator
10074 0 0       0 if ( $is_q_qq_qw_qx_qr_s_y_tr_m{$subname} ) {
10075 0         0 $self->complain(
10076             "'my' sub '$subname' matches a builtin quote operator\n"
10077             );
10078             ## OLD CODING, before improved handling of lexical subs:
10079             ## This may end badly, it is safest to avoid formatting.
10080             ## For an example, see perl527/lexsub.t (issue c203)
10081             ## $self->[_do_not_format_] = 1;
10082             }
10083             }
10084             else {
10085 176 100 66     921 $package = ( defined($1) && $1 ) ? $1 : $current_package;
10086 176         436 $package =~ s/\'/::/g;
10087 176 50       488 if ( $package =~ /^\:/ ) { $package = 'main' . $package }
  0         0  
10088 176         336 $package =~ s/::$//;
10089             }
10090              
10091 176         277 my $pos = pos($input_line);
10092 176         301 my $numc = $pos - $pos_beg;
10093 176         431 $tok = 'sub ' . $id_prefix . substr( $input_line, $pos_beg, $numc );
10094 176         251 $type = 'S'; ## Fix for c250, was 'i';
10095              
10096             # remember the sub name in case another call is needed to
10097             # get the prototype
10098 176         245 $package_saved = $package;
10099 176         359 $subname_saved = $subname;
10100             }
10101              
10102             # Now look for PROTO ATTRS for all call types
10103             # Look for prototype/attributes which are usually on the same
10104             # line as the sub name but which might be on a separate line.
10105             # For example, we might have an anonymous sub with attributes,
10106             # or a prototype on a separate line from its sub name
10107              
10108             # NOTE: We only want to parse PROTOTYPES here. If we see anything that
10109             # does not look like a prototype, we assume it is a SIGNATURE and we
10110             # will stop and let the standard tokenizer handle it. In
10111             # particular, we stop if we see any nested parens, braces, or commas.
10112             # Also note, a valid prototype cannot contain any alphabetic character
10113             # -- see https://perldoc.perl.org/perlsub
10114             # But it appears that an underscore is valid in a prototype, so the
10115             # regex below uses [A-Za-z] rather than \w
10116             # This is the old regex which has been replaced:
10117             # $input_line =~ m/\G(\s*\([^\)\(\}\{\,#]*\))? # PROTO
10118             # Added '=' for issue c362
10119 371         1005 my $saw_opening_paren = $input_line =~ /\G\s*\(/;
10120 371 100 100     2820 if (
      66        
10121             $input_line =~ m{\G(\s*\([^\)\(\}\{\,#A-Za-z=]*\))? # PROTO
10122             (\s*:)? # ATTRS leading ':'
10123             }gcx
10124             && ( $1 || $2 )
10125             )
10126             {
10127 45         168 $proto = $1;
10128 45         101 $attrs = $2;
10129              
10130             # Append the prototype to the starting token if it is 'sub' or
10131             # 'prototype'. This is not necessary but for compatibility with
10132             # previous versions when the -csc flag is used:
10133 45 100 100     276 if ( $proto && ( $match || $call_type == PROTOTYPE_CALL ) ) {
    100 100        
10134 24         46 $tok .= $proto;
10135             }
10136              
10137             # If we just entered the sub at an opening paren on this call, not
10138             # a following :prototype, label it with the previous token. This is
10139             # necessary to propagate the sub name to its opening block.
10140             elsif ( $call_type == PAREN_CALL ) {
10141 2         3 $tok = $last_nonblank_token;
10142             }
10143             else {
10144             ##
10145             }
10146              
10147 45   100     142 $match ||= 1;
10148              
10149             # Patch part #1 to fixes cases b994 and b1053:
10150             # Mark an anonymous sub keyword without prototype as type 'k', i.e.
10151             # 'sub : lvalue { ...'
10152 45         71 $type = 'S'; ## C250, was 'i';
10153 45 100 100     191 if ( $tok eq 'sub' && !$proto ) { $type = 'k' }
  2         3  
10154             }
10155              
10156 371 100       824 if ($match) {
10157              
10158             # ATTRS: if there are attributes, back up and let the ':' be
10159             # found later by the scanner.
10160 191         289 my $pos = pos($input_line);
10161 191 100       439 if ($attrs) {
10162 15         37 $pos -= length($attrs);
10163             }
10164              
10165 191         382 my $next_nonblank_token = $tok;
10166              
10167             # catch case of line with leading ATTR ':' after anonymous sub
10168 191 100 100     583 if ( $pos == $pos_beg && $tok eq ':' ) {
10169 1         2 $type = 'A';
10170 1         2 $self->[_in_attribute_list_] = 1;
10171             }
10172              
10173             # Otherwise, if we found a match we must convert back from
10174             # string position to the pre_token index for continued parsing.
10175             else {
10176              
10177             # I don't think an error flag can occur here ..but ?
10178 190         294 my $error;
10179 190         597 ( $i, $error ) = inverse_pretoken_map( $i, $pos, $rtoken_map,
10180             $max_token_index );
10181 190 50       463 if ($error) { $self->warning("Possibly invalid sub\n") }
  0         0  
10182              
10183             # Patch part #2 to fixes cases b994 and b1053:
10184             # Do not let spaces be part of the token of an anonymous sub
10185             # keyword which we marked as type 'k' above...i.e. for
10186             # something like:
10187             # 'sub : lvalue { ...'
10188             # Back up and let it be parsed as a blank
10189 190 50 66     581 if ( $type eq 'k'
      66        
      33        
10190             && $attrs
10191             && $i > $i_entry
10192             && substr( $rtokens->[$i], 0, 1 ) =~ m/\s/ )
10193             {
10194 2         3 $i--;
10195             }
10196              
10197             # check for multiple definitions of a sub
10198 190         461 ( $next_nonblank_token, my $i_next_uu ) =
10199             find_next_nonblank_token_on_this_line( $i, $rtokens,
10200             $max_token_index );
10201             }
10202              
10203 191 100       735 if ( $next_nonblank_token =~ /^(\s*|#)$/ )
10204             { # skip blank or side comment
10205 7         30 my ( $rpre_tokens, $rpre_types_uu ) =
10206             $self->peek_ahead_for_n_nonblank_pre_tokens(1);
10207 7 50 33     24 if ( defined($rpre_tokens) && @{$rpre_tokens} ) {
  7         21  
10208 7         32 $next_nonblank_token = $rpre_tokens->[0];
10209             }
10210             else {
10211 0         0 $next_nonblank_token = '}';
10212             }
10213             }
10214              
10215             # See what's next...
10216 191 100       553 if ( $next_nonblank_token eq '{' ) {
    100          
    50          
    100          
    50          
    0          
10217 153 100       406 if ($subname) {
10218              
10219             # Check for multiple definitions of a sub, but
10220             # it is ok to have multiple sub BEGIN, etc,
10221             # so we do not complain if name is all caps
10222 143 50 33     601 if ( $rsaw_function_definition->{$subname}->{$package}
10223             && $subname !~ /^[A-Z]+$/ )
10224             {
10225             my $lno =
10226 0         0 $rsaw_function_definition->{$subname}->{$package};
10227 0 0       0 if ( $package =~ /^\d/ ) {
10228 0         0 $self->warning(
10229             "already saw definition of lexical 'sub $subname' at line $lno\n"
10230             );
10231              
10232             }
10233             else {
10234 0         0 if ( !DEVEL_MODE ) {
10235 0         0 $self->warning(
10236             "already saw definition of 'sub $subname' in package '$package' at line $lno\n"
10237             );
10238             }
10239             }
10240             }
10241 143         415 $rsaw_function_definition->{$subname}->{$package} =
10242             $self->[_last_line_number_];
10243             }
10244             }
10245             elsif ( $next_nonblank_token eq ';' ) {
10246             }
10247             elsif ( $next_nonblank_token eq '}' ) {
10248             }
10249              
10250             # ATTRS - if an attribute list follows, remember the name
10251             # of the sub so the next opening brace can be labeled.
10252             # Setting 'statement_type' causes any ':'s to introduce
10253             # attributes.
10254             elsif ( $next_nonblank_token eq ':' ) {
10255 16 100       37 if ( $call_type == SUB_CALL ) {
10256 14 100       42 $statement_type =
10257             substr( $tok, 0, 3 ) eq 'sub' ? $tok : 'sub';
10258             }
10259             }
10260              
10261             # if we stopped before an open paren ...
10262             elsif ( $next_nonblank_token eq '(' ) {
10263              
10264             # If we DID NOT see this paren above then it must be on the
10265             # next line so we will set a flag to come back here and see if
10266             # it is a PROTOTYPE
10267              
10268             # Otherwise, we assume it is a SIGNATURE rather than a
10269             # PROTOTYPE and let the normal tokenizer handle it as a list
10270 21 100       61 if ( !$saw_opening_paren ) {
10271 4         6 $id_scan_state = 'sub'; # we must come back to get proto
10272             }
10273 21 50       51 if ( $call_type == SUB_CALL ) {
10274 21 50       63 $statement_type =
10275             substr( $tok, 0, 3 ) eq 'sub' ? $tok : 'sub';
10276             }
10277             }
10278              
10279             # something else..
10280             elsif ($next_nonblank_token) {
10281              
10282 0 0 0     0 if ( $rcall_hash->{tok} eq 'method' && $call_type == SUB_CALL )
10283             {
10284             # For a method call, silently ignore this error (rt145706)
10285             # to avoid needless warnings. Example which can produce it:
10286             # test(method Pack (), "method");
10287              
10288             # TODO: scan for use feature 'class' and:
10289             # - if we saw 'use feature 'class' then issue the warning.
10290             # - if we did not see use feature 'class' then issue the
10291             # warning and suggest turning off --use-feature=class
10292             }
10293             else {
10294 0 0       0 $subname = EMPTY_STRING unless ( defined($subname) );
10295 0         0 $self->warning(
10296             "expecting ':' or ';' or '{' after definition or declaration of sub '$subname' but saw '$next_nonblank_token'\n"
10297             );
10298             }
10299             }
10300             else {
10301             ## EOF technically ok
10302             }
10303              
10304 191         594 check_prototype( $proto, $package, $subname );
10305             }
10306              
10307             # no match to either sub name or prototype, but line not blank
10308             else {
10309             ##
10310             }
10311 371         1675 return ( $i, $tok, $type, $id_scan_state );
10312             } ## end sub do_scan_sub
10313             }
10314              
10315             #########################################################################
10316             # Tokenizer utility routines which may use CONSTANTS but no other GLOBALS
10317             #########################################################################
10318              
10319             sub find_next_nonblank_token {
10320 466     466 0 1034 my ( $self, $i, $rtokens, $max_token_index ) = @_;
10321              
10322             # Returns the next nonblank token after the token at index $i
10323             # To skip past a side comment, and any subsequent block comments
10324             # and blank lines, call with i=$max_token_index
10325              
10326             # Skip any ending blank (fix c258). It would be cleaner if caller passed
10327             # $rtoken_map, so we could check for type 'b', and avoid a regex test, but
10328             # benchmarking shows that this test does not take significant time. So
10329             # that would be a nice update but not essential. Also note that ending
10330             # blanks will not occur for text previously processed by perltidy.
10331 466 100 100     1618 if ( $i == $max_token_index - 1
10332             && $rtokens->[$max_token_index] =~ /^\s+$/ )
10333             {
10334 9         17 $i++;
10335             }
10336              
10337 466 100       1029 if ( $i >= $max_token_index ) {
10338 145 100       426 if ( !peeked_ahead() ) {
10339 143         332 peeked_ahead(1);
10340 143         568 $self->peek_ahead_for_nonblank_token( $rtokens, $max_token_index );
10341             }
10342             }
10343              
10344 466         832 my $next_nonblank_token = $rtokens->[ ++$i ];
10345              
10346             # Any more tokens?
10347 466 50 33     1648 return ( SPACE, $i )
10348             if ( !defined($next_nonblank_token) || !length($next_nonblank_token) );
10349              
10350             # Skip over whitespace
10351 466         885 my $ord = ord( substr( $next_nonblank_token, 0, 1 ) );
10352 466 0 66     2211 if (
      33        
      66        
10353              
10354             ( $ord <= ORD_PRINTABLE_MIN || $ord >= ORD_PRINTABLE_MAX )
10355              
10356             # Quick test for ascii space or tab
10357             && (
10358             ( $ord == ORD_SPACE || $ord == ORD_TAB )
10359              
10360             # Slow test to for something else identified as whitespace
10361             || $next_nonblank_token =~ /^\s+$/
10362             )
10363             )
10364             {
10365 305         497 $next_nonblank_token = $rtokens->[ ++$i ];
10366 305 50       741 return ( SPACE, $i ) unless ( defined($next_nonblank_token) );
10367             }
10368              
10369             # We should be at a nonblank now
10370 466         1194 return ( $next_nonblank_token, $i );
10371              
10372             } ## end sub find_next_nonblank_token
10373              
10374             sub find_next_noncomment_token {
10375 108     108 0 248 my ( $self, $i, $rtokens, $max_token_index ) = @_;
10376              
10377             # Given the current character position, look ahead past any comments
10378             # and blank lines and return the next token, including digraphs and
10379             # trigraphs.
10380              
10381 108         392 my ( $next_nonblank_token, $i_next ) =
10382             $self->find_next_nonblank_token( $i, $rtokens, $max_token_index );
10383              
10384             # skip past any side comment
10385 108 50       334 if ( $next_nonblank_token eq '#' ) {
10386 0         0 ( $next_nonblank_token, $i_next ) =
10387             $self->find_next_nonblank_token( $i_next, $rtokens,
10388             $max_token_index );
10389             }
10390              
10391             # check for a digraph
10392 108 50 33     677 if ( $next_nonblank_token
      33        
10393             && $next_nonblank_token ne SPACE
10394             && defined( $rtokens->[ $i_next + 1 ] ) )
10395             {
10396 108         256 my $test2 = $next_nonblank_token . $rtokens->[ $i_next + 1 ];
10397 108 100       306 if ( $is_digraph{$test2} ) {
10398 15         28 $next_nonblank_token = $test2;
10399 15         23 $i_next = $i_next + 1;
10400              
10401             # check for a trigraph
10402 15 50       47 if ( defined( $rtokens->[ $i_next + 1 ] ) ) {
10403 15         27 my $test3 = $next_nonblank_token . $rtokens->[ $i_next + 1 ];
10404 15 50       51 if ( $is_trigraph{$test3} ) {
10405 0         0 $next_nonblank_token = $test3;
10406 0         0 $i_next = $i_next + 1;
10407             }
10408             }
10409             }
10410             }
10411              
10412 108         253 return ( $next_nonblank_token, $i_next );
10413             } ## end sub find_next_noncomment_token
10414              
10415             sub is_possible_numerator {
10416              
10417 0     0 0 0 my ( $self, $i, $rtokens, $max_token_index ) = @_;
10418              
10419             # Look at the next non-comment character and decide if it could be a
10420             # numerator. Returns the following code:
10421             # -1 - division not possible
10422             # 0 - can't tell if division possible
10423             # 1 - division possible
10424             # 2 - division probable: number follows
10425             # 3 - division very probable: number and one of ; ] } follow
10426             # 4 - is division, not pattern: number and ) follow
10427              
10428 0         0 my $divide_possible_code = 0;
10429              
10430 0         0 my $next_token = $rtokens->[ $i + 1 ];
10431 0 0       0 if ( $next_token eq '=' ) { $i++; } # handle /=
  0         0  
10432 0         0 my ( $next_nonblank_token, $i_next ) =
10433             $self->find_next_nonblank_token( $i, $rtokens, $max_token_index );
10434              
10435 0 0       0 if ( $next_nonblank_token eq '#' ) {
10436 0         0 ( $next_nonblank_token, $i_next ) =
10437             $self->find_next_nonblank_token( $max_token_index, $rtokens,
10438             $max_token_index );
10439             }
10440              
10441 0 0       0 if ( $next_nonblank_token =~ / [ \( \$ \w \. \@ ] /x ) {
    0          
10442 0         0 $divide_possible_code = 1;
10443              
10444             # look ahead one more token for some common patterns, such as
10445             # pi/2) pi/2; pi/2}
10446 0 0       0 if ( $next_nonblank_token =~ /^\d/ ) {
10447 0         0 my ( $next_next_nonblank_token, $i_next_next_uu ) =
10448             $self->find_next_nonblank_token( $i_next, $rtokens,
10449             $max_token_index );
10450 0 0 0     0 if ( $next_next_nonblank_token eq ')' ) {
    0 0        
10451 0         0 $divide_possible_code = 4;
10452             }
10453             elsif ($next_next_nonblank_token eq ';'
10454             || $next_next_nonblank_token eq ']'
10455             || $next_next_nonblank_token eq '}' )
10456             {
10457 0         0 $divide_possible_code = 3;
10458             }
10459             else {
10460 0         0 $divide_possible_code = 2;
10461             }
10462             }
10463             }
10464             elsif ( $next_nonblank_token =~ /^\s*$/ ) {
10465 0         0 $divide_possible_code = 0;
10466             }
10467             else {
10468 0         0 $divide_possible_code = -1;
10469             }
10470              
10471 0         0 return $divide_possible_code;
10472             } ## end sub is_possible_numerator
10473              
10474             { ## closure for sub pattern_expected
10475             my %pattern_test;
10476              
10477             BEGIN {
10478              
10479             # List of tokens which may follow a pattern. Note that we will not
10480             # have formed digraphs at this point, so we will see '&' instead of
10481             # '&&' and '|' instead of '||'
10482              
10483             # /(\)|\}|\;|\&\&|\|\||and|or|while|if|unless)/
10484 44     44   301 my @q = qw( & && | || ? : + - * and or while if unless );
10485 44         164 push @q, ')', '}', ']', '>', COMMA, ';';
10486 44         118527 $pattern_test{$_} = 1 for @q;
10487             } ## end BEGIN
10488              
10489             sub pattern_expected {
10490              
10491 0     0 0 0 my ( $self, $i, $rtokens, $max_token_index ) = @_;
10492              
10493             # This a filter for a possible pattern.
10494             # It looks at the token after a possible pattern and tries to
10495             # determine if that token could end a pattern.
10496             # returns -
10497             # 1 - yes
10498             # 0 - can't tell
10499             # -1 - no
10500 0         0 my $is_pattern = 0;
10501              
10502 0         0 my $next_token = $rtokens->[ $i + 1 ];
10503              
10504             # skip a possible quote modifier
10505 0         0 my $possible_modifiers = $quote_modifiers{'m'};
10506 0 0       0 if ( $next_token =~ /^$possible_modifiers/ ) {
10507 0         0 $i++;
10508             }
10509              
10510 0         0 my ( $next_nonblank_token, $i_next_uu ) =
10511             $self->find_next_nonblank_token( $i, $rtokens, $max_token_index );
10512              
10513 0 0       0 if ( $pattern_test{$next_nonblank_token} ) {
10514 0         0 $is_pattern = 1;
10515             }
10516             else {
10517              
10518             # Added '#' to fix issue c044
10519 0 0 0     0 if ( $next_nonblank_token =~ /^\s*$/
10520             || $next_nonblank_token eq '#' )
10521             {
10522 0         0 $is_pattern = 0;
10523             }
10524             else {
10525 0         0 $is_pattern = -1;
10526             }
10527             }
10528 0         0 return $is_pattern;
10529             } ## end sub pattern_expected
10530             }
10531              
10532             sub find_next_nonblank_token_on_this_line {
10533 641     641 0 1120 my ( $i, $rtokens, $max_token_index ) = @_;
10534 641         824 my $next_nonblank_token;
10535              
10536 641 100       1332 if ( $i < $max_token_index ) {
10537 633         970 $next_nonblank_token = $rtokens->[ ++$i ];
10538              
10539 633 100       2360 if ( $next_nonblank_token =~ /^\s*$/ ) {
10540              
10541 182 100       440 if ( $i < $max_token_index ) {
10542 180         346 $next_nonblank_token = $rtokens->[ ++$i ];
10543             }
10544             }
10545             }
10546             else {
10547 8         13 $next_nonblank_token = EMPTY_STRING;
10548             }
10549 641         1636 return ( $next_nonblank_token, $i );
10550             } ## end sub find_next_nonblank_token_on_this_line
10551              
10552             sub find_angle_operator_termination {
10553              
10554 8     8 0 23 my ( $self, $input_line, $i_beg, $rtoken_map, $expecting, $max_token_index )
10555             = @_;
10556              
10557             # We are looking at a '<' and want to know if it is an angle operator.
10558             # Return:
10559             # $i = pretoken index of ending '>' if found, current $i otherwise
10560             # $type = 'Q' if found, '>' otherwise
10561              
10562 8         13 my $i = $i_beg;
10563 8         17 my $type = '<';
10564 8         34 pos($input_line) = 1 + $rtoken_map->[$i];
10565              
10566             # The token sequence '><' implies a markup language
10567 8 50       27 if ( $last_nonblank_token eq '>' ) {
10568 0         0 $self->[_html_tag_count_]++;
10569             }
10570              
10571 8         10 my $filter;
10572              
10573 8         15 my $expecting_TERM = $expecting == TERM;
10574              
10575             # we just have to find the next '>' if a term is expected
10576 8 100       33 if ($expecting_TERM) { $filter = '[\>]' }
  6 50       12  
10577              
10578             # we have to guess if we don't know what is expected
10579 2         4 elsif ( $expecting == UNKNOWN ) { $filter = '[\>\;\=\#\|\<]' }
10580              
10581             # shouldn't happen - we shouldn't be here if operator is expected
10582             else {
10583 0         0 if (DEVEL_MODE) {
10584             Fault(<<EOM);
10585             Bad call to find_angle_operator_termination
10586             EOM
10587             }
10588 0         0 return ( $i, $type );
10589             }
10590              
10591             # To illustrate what we might be looking at, in case we are
10592             # guessing, here are some examples of valid angle operators
10593             # (or file globs):
10594             # <tmp_imp/*>
10595             # <FH>
10596             # <$fh>
10597             # <*.c *.h>
10598             # <_>
10599             # <jskdfjskdfj* op/* jskdjfjkosvk*> ( glob.t)
10600             # <${PREFIX}*img*.$IMAGE_TYPE>
10601             # <img*.$IMAGE_TYPE>
10602             # <Timg*.$IMAGE_TYPE>
10603             # <$LATEX2HTMLVERSIONS${dd}html[1-9].[0-9].pl>
10604             #
10605             # Here are some examples of lines which do not have angle operators:
10606             # return unless $self->[2]++ < $#{$self->[1]};
10607             # < 2 || @$t >
10608             #
10609             # the following line from dlister.pl caused trouble:
10610             # print'~'x79,"\n",$D<1024?"0.$D":$D>>10,"K, $C files\n\n\n";
10611             #
10612             # If the '<' starts an angle operator, it must end on this line and
10613             # it must not have certain characters like ';' and '=' in it. I use
10614             # this to limit the testing. This filter should be improved if
10615             # possible.
10616              
10617 8 50       148 if ( $input_line =~ /($filter)/g ) {
10618              
10619 8 50       29 if ( $1 eq '>' ) {
10620              
10621             # We MAY have found an angle operator termination if we get
10622             # here, but we need to do more to be sure we haven't been
10623             # fooled.
10624 8         13 my $pos = pos($input_line);
10625              
10626 8         14 my $pos_beg = $rtoken_map->[$i];
10627 8         24 my $str = substr( $input_line, $pos_beg, ( $pos - $pos_beg ) );
10628              
10629             # Test for '<' after possible filehandle, issue c103
10630             # print $fh <>; # syntax error
10631             # print $fh <DATA>; # ok
10632             # print $fh < DATA>; # syntax error at '>'
10633             # print STDERR < DATA>; # ok, prints word 'DATA'
10634             # print BLABLA <DATA>; # ok; does nothing unless BLABLA is defined
10635 8 100       19 if ( $last_nonblank_type eq 'Z' ) {
10636              
10637             # $str includes brackets; something like '<DATA>'
10638 1 0 33     5 if ( substr( $last_nonblank_token, 0, 1 ) !~ /[A-Za-z_]/
10639             && substr( $str, 1, 1 ) !~ /[A-Za-z_]/ )
10640             {
10641 0         0 return ( $i, $type );
10642             }
10643             }
10644              
10645             # Reject if the closing '>' follows a '-' as in:
10646             # if ( VERSION < 5.009 && $op-> name eq 'assign' ) { }
10647 8 100       24 if ( $expecting eq UNKNOWN ) {
10648 2         12 my $check = substr( $input_line, $pos - 2, 1 );
10649 2 100       5 if ( $check eq '-' ) {
10650 1         3 return ( $i, $type );
10651             }
10652             }
10653              
10654             ######################################debug#####
10655             #$self->write_diagnostics( "ANGLE? :$str\n");
10656             #print "ANGLE: found $1 at pos=$pos str=$str check=$check\n";
10657             ######################################debug#####
10658 7         9 $type = 'Q';
10659 7         14 my $error;
10660 7         24 ( $i, $error ) =
10661             inverse_pretoken_map( $i, $pos, $rtoken_map, $max_token_index );
10662              
10663             # It may be possible that a quote ends midway in a pretoken.
10664             # If this happens, it may be necessary to split the pretoken.
10665 7 50       20 if ($error) {
10666 0         0 if (DEVEL_MODE) {
10667             Fault(<<EOM);
10668             unexpected error condition returned by inverse_pretoken_map
10669             EOM
10670             }
10671             $self->warning(
10672 0         0 "Possible tokenization error..please check this line\n");
10673             }
10674              
10675             # Check for accidental formatting of a markup language doc...
10676             # Formatting will be skipped if we set _html_tag_count_ and
10677             # also set a warning of any kind.
10678 7         10 my $is_html_tag;
10679 7   33     27 my $is_first_string =
10680             $i_beg == 0 && $self->[_last_line_number_] == 1;
10681              
10682             # html comment '<!...' of any type
10683 7 50 33     69 if ( $str =~ /^<\s*!/ ) {
    50          
    50          
10684 0         0 $is_html_tag = 1;
10685 0 0       0 if ($is_first_string) {
10686 0         0 $self->warning(
10687             "looks like a markup language, continuing error checks\n"
10688             );
10689             }
10690             }
10691              
10692             # html end tag, something like </h1>
10693             elsif ( $str =~ /^<\s*\/\w+\s*>$/ ) {
10694 0         0 $is_html_tag = 1;
10695             }
10696              
10697             # xml prolog?
10698             elsif ( $str =~ /^<\?xml\s.*\?>$/i && $is_first_string ) {
10699 0         0 $is_html_tag = 1;
10700 0         0 $self->warning(
10701             "looks like a markup language, continuing error checks\n");
10702             }
10703             else {
10704             ## doesn't look like a markup tag
10705             }
10706              
10707 7 50       19 if ($is_html_tag) {
10708 0         0 $self->[_html_tag_count_]++;
10709             }
10710              
10711             # count blanks on inside of brackets
10712 7         13 my $blank_count = 0;
10713 7 100       27 $blank_count++ if ( $str =~ /<\s+/ );
10714 7 100       26 $blank_count++ if ( $str =~ /\s+>/ );
10715              
10716             # Now let's see where we stand....
10717             # OK if math op not possible
10718 7 100       24 if ($expecting_TERM) {
    50          
    50          
    0          
10719             }
10720              
10721             elsif ($is_html_tag) {
10722             }
10723              
10724             # OK if there are no more than 2 non-blank pre-tokens inside
10725             # (not possible to write 2 token math between < and >)
10726             # This catches most common cases
10727             elsif ( $i <= $i_beg + 3 + $blank_count ) {
10728              
10729             # No longer any need to document this common case
10730             ## $self->write_diagnostics("ANGLE(1 or 2 tokens): $str\n");
10731             }
10732              
10733             # OK if there is some kind of identifier inside
10734             # print $fh <tvg::INPUT>;
10735             elsif ( $str =~ /^<\s*\$?(\w|::|\s)+\s*>$/ ) {
10736 0         0 $self->write_diagnostics("ANGLE (contains identifier): $str\n");
10737             }
10738              
10739             # Not sure..
10740             else {
10741              
10742             # Let's try a Brace Test: any braces inside must balance
10743 0         0 my $br = $str =~ tr/\{/{/ - $str =~ tr/\}/}/;
10744 0         0 my $sb = $str =~ tr/\[/[/ - $str =~ tr/\]/]/;
10745 0         0 my $pr = $str =~ tr/\(/(/ - $str =~ tr/\)/)/;
10746              
10747             # if braces do not balance - not angle operator
10748 0 0 0     0 if ( $br || $sb || $pr ) {
      0        
10749 0         0 $i = $i_beg;
10750 0         0 $type = '<';
10751 0         0 $self->write_diagnostics(
10752             "NOT ANGLE (BRACE={$br ($pr [$sb ):$str\n");
10753             }
10754              
10755             # we should keep doing more checks here...to be continued
10756             # Tentatively accepting this as a valid angle operator.
10757             # There are lots more things that can be checked.
10758             else {
10759 0         0 $self->write_diagnostics(
10760             "ANGLE-Guessing yes: $str expecting=$expecting\n");
10761 0         0 $self->write_logfile_entry(
10762             "Guessing angle operator here: $str\n");
10763             }
10764             }
10765             }
10766              
10767             # didn't find ending >
10768             else {
10769 0 0       0 if ($expecting_TERM) {
10770 0         0 $self->warning("No ending > for angle operator\n");
10771             }
10772             }
10773             }
10774 7         24 return ( $i, $type );
10775             } ## end sub find_angle_operator_termination
10776              
10777             sub scan_number_do {
10778              
10779 687     687 0 1389 my ( $self, $input_line, $i, $rtoken_map, $input_type, $max_token_index ) =
10780             @_;
10781              
10782             # Scan a number in any of the formats that Perl accepts
10783             # Underbars (_) are allowed in decimal numbers.
10784             # Given:
10785             # $input_line - the string to scan
10786             # $i - pre_token index to start scanning
10787             # $rtoken_map - reference to the pre_token map giving starting
10788             # character position in $input_line of token $i
10789             # Return:
10790             # $i - last pre_token index of the number just scanned
10791             # $type - the token type ('v' or 'n')
10792             # number - the number (characters); or undef if not a number
10793              
10794 687         967 my $pos_beg = $rtoken_map->[$i];
10795 687         810 my $pos;
10796             ##my $i_begin = $i;
10797 687         883 my $number = undef;
10798 687         873 my $type = $input_type;
10799              
10800 687         1310 my $first_char = substr( $input_line, $pos_beg, 1 );
10801              
10802             # Look for bad starting characters; Shouldn't happen..
10803 687 50       2454 if ( $first_char !~ /[\d\.\+\-Ee]/ ) {
10804 0         0 if (DEVEL_MODE) {
10805             Fault(<<EOM);
10806             Program bug - scan_number given bad first character = '$first_char'
10807             EOM
10808             }
10809 0         0 return ( $i, $type, $number );
10810             }
10811              
10812             # handle v-string without leading 'v' character ('Two Dot' rule)
10813             # (vstring.t)
10814             # Here is the format prior to including underscores:
10815             ## if ( $input_line =~ /\G((\d+)?\.\d+(\.\d+)+)/g ) {
10816 687         1662 pos($input_line) = $pos_beg;
10817 687 50       2691 if ( $input_line =~ /\G((\d[_\d]*)?\.[\d_]+(\.[\d_]+)+)/g ) {
10818 0         0 $pos = pos($input_line);
10819 0         0 my $numc = $pos - $pos_beg;
10820 0         0 $number = substr( $input_line, $pos_beg, $numc );
10821 0         0 $type = 'v';
10822             }
10823              
10824             # handle octal, hex, binary
10825 687 50       1229 if ( !defined($number) ) {
10826 687         1006 pos($input_line) = $pos_beg;
10827              
10828             # Perl 5.22 added floating point literals, like '0x0.b17217f7d1cf78p0'
10829             # For reference, the format prior to hex floating point is:
10830             # /\G[+-]?0(([xX][0-9a-fA-F_]+)|([0-7_]+)|([bB][01_]+))/g )
10831             # (hex) (octal) (binary)
10832 687 100       1940 if (
10833             $input_line =~ m{
10834              
10835             \G[+-]?0( # leading [signed] 0
10836              
10837             # a hex float, i.e. '0x0.b17217f7d1cf78p0'
10838             ([xX][0-9a-fA-F_]* # X and optional leading digits
10839             (\.([0-9a-fA-F][0-9a-fA-F_]*)?)? # optional decimal and fraction
10840             [Pp][+-]?[0-9a-fA-F] # REQUIRED exponent with digit
10841             [0-9a-fA-F_]*) # optional Additional exponent digits
10842              
10843             # or hex integer
10844             |([xX][0-9a-fA-F_]+)
10845              
10846             # or octal fraction
10847             |([oO]?[0-7_]+ # string of octal digits
10848             (\.([0-7][0-7_]*)?)? # optional decimal and fraction
10849             [Pp][+-]?[0-7] # REQUIRED exponent, no underscore
10850             [0-7_]*) # Additional exponent digits with underscores
10851              
10852             # or octal integer
10853             |([oO]?[0-7_]+) # string of octal digits
10854              
10855             # or a binary float
10856             |([bB][01_]* # 'b' with string of binary digits
10857             (\.([01][01_]*)?)? # optional decimal and fraction
10858             [Pp][+-]?[01] # Required exponent indicator, no underscore
10859             [01_]*) # additional exponent bits
10860              
10861             # or binary integer
10862             |([bB][01_]+) # 'b' with string of binary digits
10863              
10864             )}gx
10865             )
10866             {
10867 72         97 $pos = pos($input_line);
10868 72         90 my $numc = $pos - $pos_beg;
10869 72         102 $number = substr( $input_line, $pos_beg, $numc );
10870 72         119 $type = 'n';
10871             }
10872             }
10873              
10874             # handle decimal
10875 687 100       1171 if ( !defined($number) ) {
10876 615         916 pos($input_line) = $pos_beg;
10877              
10878 615 50       2426 if ( $input_line =~ /\G([+-]?[\d_]*(\.[\d_]*)?([Ee][+-]?(\d+))?)/g ) {
10879 615         845 $pos = pos($input_line);
10880              
10881             # watch out for things like 0..40 which would give 0. by this;
10882 615 100 100     1677 if ( ( substr( $input_line, $pos - 1, 1 ) eq '.' )
10883             && ( substr( $input_line, $pos, 1 ) eq '.' ) )
10884             {
10885 38         67 $pos--;
10886             }
10887 615         819 my $numc = $pos - $pos_beg;
10888 615         945 $number = substr( $input_line, $pos_beg, $numc );
10889 615         837 $type = 'n';
10890             }
10891             }
10892              
10893             # filter out non-numbers like e + - . e2 .e3 +e6
10894             # the rule: at least one digit, and any 'e' must be preceded by a digit
10895 687 100 66     3344 if (
      66        
10896             $number !~ /\d/ # no digits
10897             || ( $number =~ /^(.*)[eE]/
10898             && $1 !~ /\d/ ) # or no digits before the 'e'
10899             )
10900             {
10901 304         344 $number = undef;
10902 304         353 $type = $input_type;
10903 304         1059 return ( $i, $type, $number );
10904             }
10905              
10906             # Found a number; now we must convert back from character position
10907             # to pre_token index. An error here implies user syntax error.
10908             # An example would be an invalid octal number like '009'.
10909 383         513 my $error;
10910 383         754 ( $i, $error ) =
10911             inverse_pretoken_map( $i, $pos, $rtoken_map, $max_token_index );
10912 383 50       700 if ($error) { $self->warning("Possibly invalid number\n") }
  0         0  
10913              
10914 383         1105 return ( $i, $type, $number );
10915             } ## end sub scan_number_do
10916              
10917             sub inverse_pretoken_map {
10918              
10919             # Starting with the current pre_token index $i, scan forward until
10920             # finding the index of the next pre_token whose position is $pos.
10921 2496     2496 0 4380 my ( $i, $pos, $rtoken_map, $max_token_index ) = @_;
10922 2496         2936 my $error = 0;
10923              
10924 2496         4846 while ( ++$i <= $max_token_index ) {
10925              
10926 4701 100       8201 if ( $pos <= $rtoken_map->[$i] ) {
10927              
10928             # Let the calling routine handle errors in which we do not
10929             # land on a pre-token boundary. It can happen by running
10930             # perltidy on some non-perl scripts, for example.
10931 2452 50       4458 if ( $pos < $rtoken_map->[$i] ) { $error = 1 }
  0         0  
10932 2452         2879 $i--;
10933 2452         3372 last;
10934             }
10935             } ## end while ( ++$i <= $max_token_index)
10936 2496         4834 return ( $i, $error );
10937             } ## end sub inverse_pretoken_map
10938              
10939             sub find_here_doc {
10940              
10941             my (
10942              
10943 33     33 0 70 $self,
10944              
10945             $expecting,
10946             $i,
10947             $rtokens,
10948             $rtoken_type,
10949             $rtoken_map_uu,
10950             $max_token_index,
10951              
10952             ) = @_;
10953              
10954             # Find the target of a here document, if any
10955             # Given:
10956             # $i - token index of the second < of <<
10957             # ($i must be less than the last token index if this is called)
10958             # Return:
10959             # $found_target = 0 didn't find target; =1 found target
10960             # HERE_TARGET - the target string (may be empty string)
10961             # $i - unchanged if not here doc,
10962             # or index of the last token of the here target
10963             # $saw_error - flag noting unbalanced quote on here target
10964 33         50 my $ibeg = $i;
10965 33         44 my $found_target = 0;
10966 33         46 my $here_doc_target = EMPTY_STRING;
10967 33         48 my $here_quote_character = EMPTY_STRING;
10968 33         44 my $saw_error = 0;
10969 33         46 my ( $next_nonblank_token, $i_next_nonblank, $next_token );
10970 33         73 $next_token = $rtokens->[ $i + 1 ];
10971              
10972             # perl allows a backslash before the target string (heredoc.t)
10973 33         44 my $backslash = 0;
10974 33 50       81 if ( $next_token eq BACKSLASH ) {
10975 0         0 $backslash = 1;
10976 0         0 $next_token = $rtokens->[ $i + 2 ];
10977             }
10978              
10979 33         90 ( $next_nonblank_token, $i_next_nonblank ) =
10980             find_next_nonblank_token_on_this_line( $i, $rtokens, $max_token_index );
10981              
10982 33 100 33     163 if ( $next_nonblank_token =~ /[\'\"\`]/ ) {
    50          
    50          
10983              
10984 18         25 my $in_quote = 1;
10985 18         22 my $quote_depth = 0;
10986 18         38 my $quote_pos = 0;
10987 18         26 my $quoted_string;
10988              
10989             (
10990              
10991 18         55 $i,
10992             $in_quote,
10993             $here_quote_character,
10994             $quote_pos,
10995             $quote_depth,
10996             $quoted_string,
10997             )
10998             = $self->follow_quoted_string(
10999              
11000             $i_next_nonblank,
11001             $in_quote,
11002             $rtokens,
11003             $rtoken_type,
11004             $here_quote_character,
11005             $quote_pos,
11006             $quote_depth,
11007             $max_token_index,
11008             );
11009              
11010 18 50       45 if ($in_quote) { # didn't find end of quote, so no target found
11011 0         0 $i = $ibeg;
11012 0 0       0 if ( $expecting == TERM ) {
11013 0         0 $self->warning(
11014             "Did not find here-doc string terminator ($here_quote_character) before end of line \n"
11015             );
11016 0         0 $saw_error = 1;
11017             }
11018             }
11019             else { # found ending quote
11020 18         50 $found_target = 1;
11021              
11022 18         27 my $tokj;
11023 18         57 foreach my $j ( $i_next_nonblank + 1 .. $i - 1 ) {
11024 18         23 $tokj = $rtokens->[$j];
11025              
11026             # we have to remove any backslash before the quote character
11027             # so that the here-doc-target exactly matches this string
11028             next
11029 18 0 33     55 if ( $tokj eq BACKSLASH
      33        
11030             && $j < $i - 1
11031             && $rtokens->[ $j + 1 ] eq $here_quote_character );
11032 18         43 $here_doc_target .= $tokj;
11033             }
11034             }
11035             }
11036              
11037             elsif ( ( $next_token =~ /^\s*$/ ) and ( $expecting == TERM ) ) {
11038 0         0 $found_target = 1;
11039 0         0 $self->write_logfile_entry(
11040             "found blank here-target after <<; suggest using \"\"\n");
11041 0         0 $i = $ibeg;
11042             }
11043             elsif ( $next_token =~ /^\w/ ) { # simple bareword or integer after <<
11044              
11045 15         26 my $here_doc_expected;
11046 15 50       30 if ( $expecting == UNKNOWN ) {
11047 0         0 $here_doc_expected = $self->guess_if_here_doc($next_token);
11048             }
11049             else {
11050 15         20 $here_doc_expected = 1;
11051             }
11052              
11053 15 50       37 if ($here_doc_expected) {
11054 15         20 $found_target = 1;
11055 15         22 $here_doc_target = $next_token;
11056 15         46 $i = $ibeg + 1;
11057             }
11058              
11059             }
11060             else {
11061              
11062 0 0       0 if ( $expecting == TERM ) {
11063 0         0 $found_target = 1;
11064 0         0 $self->write_logfile_entry("Note: bare here-doc operator <<\n");
11065             }
11066             else {
11067 0         0 $i = $ibeg;
11068             }
11069             }
11070              
11071             # patch to neglect any prepended backslash
11072 33 50 33     268 if ( $found_target && $backslash ) { $i++ }
  0         0  
11073              
11074 33         133 return ( $found_target, $here_doc_target, $here_quote_character, $i,
11075             $saw_error );
11076             } ## end sub find_here_doc
11077              
11078             sub do_quote {
11079              
11080             my (
11081              
11082 3222     3222 0 8053 $self,
11083              
11084             $i,
11085             $in_quote,
11086             $quote_character,
11087             $quote_pos,
11088             $quote_depth,
11089             $quoted_string_1,
11090             $quoted_string_2,
11091             $rtokens,
11092             $rtoken_type,
11093             $rtoken_map_uu,
11094             $max_token_index,
11095              
11096             ) = @_;
11097              
11098             # Follow (or continue following) quoted string(s)
11099             # $in_quote = return code:
11100             # 0 - ok, found end
11101             # 1 - still must find end of quote whose target is $quote_character
11102             # 2 - still looking for end of first of two quotes
11103             #
11104             # Returns updated strings:
11105             # $quoted_string_1 = quoted string seen while in_quote=1
11106             # $quoted_string_2 = quoted string seen while in_quote=2
11107              
11108 3222         3849 my $quoted_string;
11109 3222 100       5604 if ( $in_quote == 2 ) { # two quotes/quoted_string_1s to follow
11110 31         44 my $ibeg = $i;
11111             (
11112              
11113 31         113 $i,
11114             $in_quote,
11115             $quote_character,
11116             $quote_pos,
11117             $quote_depth,
11118             $quoted_string,
11119             )
11120             = $self->follow_quoted_string(
11121              
11122             $ibeg,
11123             $in_quote,
11124             $rtokens,
11125             $rtoken_type,
11126             $quote_character,
11127             $quote_pos,
11128             $quote_depth,
11129             $max_token_index,
11130             );
11131 31         65 $quoted_string_2 .= $quoted_string;
11132 31 50       78 if ( $in_quote == 1 ) {
11133 31 100       122 if ( $quote_character =~ /[\{\[\<\(]/ ) { $i++; }
  1         2  
11134 31         55 $quote_character = EMPTY_STRING;
11135             }
11136             else {
11137 0         0 $quoted_string_2 .= "\n";
11138             }
11139             }
11140              
11141 3222 50       5223 if ( $in_quote == 1 ) { # one (more) quote to follow
11142 3222         3747 my $ibeg = $i;
11143             (
11144              
11145 3222         7723 $i,
11146             $in_quote,
11147             $quote_character,
11148             $quote_pos,
11149             $quote_depth,
11150             $quoted_string,
11151             )
11152             = $self->follow_quoted_string(
11153              
11154             $ibeg,
11155             $in_quote,
11156             $rtokens,
11157             $rtoken_type,
11158             $quote_character,
11159             $quote_pos,
11160             $quote_depth,
11161             $max_token_index,
11162             );
11163 3222         5386 $quoted_string_1 .= $quoted_string;
11164 3222 100       5337 if ( $in_quote == 1 ) {
11165 244         345 $quoted_string_1 .= "\n";
11166             }
11167             }
11168             return (
11169              
11170 3222         8974 $i,
11171             $in_quote,
11172             $quote_character,
11173             $quote_pos,
11174             $quote_depth,
11175             $quoted_string_1,
11176             $quoted_string_2,
11177              
11178             );
11179             } ## end sub do_quote
11180              
11181 44     44   377 use constant DEBUG_FIND_INTERPOLATED_HERE_TARGETS => 0;
  44         82  
  44         27119  
11182              
11183             sub find_interpolated_here_targets {
11184 2     2 0 6 my ( $self, $quoted_string, $len_starting_lines ) = @_;
11185              
11186             # Search for here targets in a quoted string
11187             # Given:
11188             # $quoted_string = the complete string of an interpolated quote
11189             # $len_starting_lines = number of characters of the first n-1 lines
11190             # (=0 if this is a single-line quote)
11191             # Task:
11192             # Find and return a list of all here targets on the last line;
11193             # i.e., if here target is index ii, we only return the
11194             # target if $rmap->[$ii]>=$len_starting_lines
11195              
11196             # The items returned are the format needed for @{$rhere_target_list};
11197             # [ $here_doc_target, $here_quote_character ]
11198             # there can be multiple here targets.
11199              
11200 2         4 my $rht;
11201              
11202             # Break the entire quote into pre-tokens, even if multi-line, because we
11203             # have to determine which parts are in single quotes
11204 2         7 my ( $rtokens, $rmap, $rtoken_type ) = pre_tokenize($quoted_string);
11205 2         4 my $max_ii = @{$rtokens} - 1;
  2         6  
11206              
11207             # Depth of braces controlled by a sigil
11208 2         3 my $code_depth = 0;
11209              
11210             # Loop over pre-tokens
11211 2         4 my $ii = -1;
11212 2         8 while ( ++$ii <= $max_ii ) {
11213 21         23 my $token = $rtokens->[$ii];
11214 21         21 if (DEBUG_FIND_INTERPOLATED_HERE_TARGETS) {
11215             print "i=$ii tok=$token block=$code_depth\n";
11216             }
11217              
11218 21 100       31 if ( $token eq BACKSLASH ) {
11219 4 50       8 if ( !$code_depth ) { $ii++ }
  0         0  
11220 4         6 next;
11221             }
11222              
11223             # Look for start of interpolation code block, '${', '@{', '$var{', etc
11224 17 100       25 if ( !$code_depth ) {
11225 4 50 33     12 if ( $token eq '$' || $token eq '@' ) {
11226              
11227 4 100 66     19 $ii++
11228             if ( $ii < $max_ii && $rtoken_type->[ $ii + 1 ] eq 'b' );
11229              
11230 4   33     22 while (
      33        
11231             $ii < $max_ii
11232             && ( $rtoken_type->[ $ii + 1 ] eq 'w'
11233             || $rtoken_type->[ $ii + 1 ] eq '::' )
11234             )
11235             {
11236 0         0 $ii++;
11237             } ## end while ( $ii < $max_ii && ...)
11238              
11239 4 50 33     18 $ii++
11240             if ( $ii < $max_ii && $rtoken_type->[ $ii + 1 ] eq 'b' );
11241              
11242 4 50 33     16 if ( $ii < $max_ii && $rtokens->[ $ii + 1 ] eq '{' ) {
11243 4         7 $ii++;
11244 4         5 $code_depth++;
11245             }
11246             }
11247 4         7 next;
11248             }
11249              
11250             # Continue interpolating while $code_depth > 0..
11251 13 50       20 if ( $token eq '{' ) {
11252 0         0 $code_depth++;
11253 0         0 next;
11254             }
11255 13 100       20 if ( $token eq '}' ) {
11256 4         8 $code_depth--;
11257 4         6 next;
11258             }
11259              
11260             # Look for '<<'
11261 9 50 66     29 if ( $token ne '<'
      66        
11262             || $ii >= $max_ii - 1
11263             || $rtokens->[ $ii + 1 ] ne '<' )
11264             {
11265 5         7 next;
11266             }
11267              
11268             # Remember the location of the first '<' so it can be modified
11269 4         6 my $ii_left_shift = $ii;
11270              
11271 4         4 $ii++;
11272              
11273             # or '<<~'
11274 4 50 33     11 if ( $rtoken_type->[ $ii + 1 ] eq '~' && $ii < $max_ii - 2 ) {
11275 0         0 $ii++;
11276             }
11277              
11278             # blanks ok before targets in quotes
11279 4         5 my $saw_blank;
11280 4 100 66     14 if ( $rtoken_type->[ $ii + 1 ] eq 'b' && $ii < $max_ii - 2 ) {
11281 2         3 $saw_blank = 1;
11282 2         14 $ii++;
11283             }
11284              
11285 4         7 my $next_type = $rtoken_type->[ $ii + 1 ];
11286              
11287             # Look for unquoted targets like "${ \<<END1 }"
11288 4 100 66     14 if ( $next_type eq 'w' ) {
    50 33        
11289 2 50       5 if ($saw_blank) {
11290             ## error: blank target is deprecated
11291             }
11292             else {
11293 2         2 $ii++;
11294 2 50       7 if ( $rmap->[$ii] >= $len_starting_lines ) {
11295 2         4 push @{$rht}, [ $rtokens->[$ii], EMPTY_STRING ];
  2         9  
11296              
11297             # Modify the string so the target is not found again
11298 2         5 my $pos_left_shift = $rmap->[$ii_left_shift];
11299 2         6 substr( $quoted_string, $pos_left_shift, 1, SPACE );
11300 2         5 substr( $quoted_string, $pos_left_shift + 1, 1, SPACE );
11301             }
11302             }
11303             }
11304              
11305             # Look for quoted targets like "${ \<< 'END1' }${ \<<\"END2\" }";
11306             elsif ( $next_type eq "'" || $next_type eq '"' || $next_type eq '`' ) {
11307 2         3 my $quote_char = $next_type;
11308 2         4 $ii++;
11309 2         3 my $here_target = EMPTY_STRING;
11310 2   66     8 while ( ++$ii <= $max_ii && $rtokens->[$ii] ne $quote_char ) {
11311             next
11312 2 50 66     8 if ( $quote_char ne "'" && $rtokens->[$ii] eq BACKSLASH );
11313 2         6 $here_target .= $rtokens->[$ii];
11314             }
11315 2 50       5 if ( $rmap->[$ii] >= $len_starting_lines ) {
11316 2         3 push @{$rht}, [ $here_target, $quote_char ];
  2         5  
11317             }
11318             }
11319             else {
11320             ## no here target found
11321             }
11322 4         8 next;
11323             } ## end while ( ++$ii <= $max_ii )
11324 2         15 return ( $rht, $quoted_string );
11325             } ## end sub find_interpolated_here_targets
11326              
11327             # Some possible non-word quote delimiters, for preliminary checking
11328             my %is_punct_char;
11329              
11330             BEGIN {
11331              
11332 44     44   421 my @q = qw# / " ' { } ( ) [ ] < > ; + - * | % ! x ~ = ? : . ^ & #;
11333 44         136 push @q, '#';
11334 44         105 push @q, COMMA;
11335 44         126345 $is_punct_char{$_} = 1 for @q;
11336             }
11337              
11338             sub follow_quoted_string {
11339              
11340             my (
11341              
11342 3271     3271 0 6350 $self,
11343              
11344             $i_beg,
11345             $in_quote,
11346             $rtokens,
11347             $rtoken_type,
11348             $beginning_tok,
11349             $quote_pos,
11350             $quote_depth,
11351             $max_token_index,
11352              
11353             ) = @_;
11354              
11355             # Scan for a specific token, skipping escaped characters.
11356             # If the quote character is blank, use the first non-blank character.
11357             # Given:
11358             # $rtokens = reference to the array of tokens
11359             # $i = the token index of the first character to search
11360             # $in_quote = number of quoted strings being followed
11361             # $beginning_tok = the starting quote character
11362             # $quote_pos = index to check next for alphanumeric delimiter
11363             # Return:
11364             # $i = the token index of the ending quote character
11365             # $in_quote = decremented if found end, unchanged if not
11366             # $beginning_tok = the starting quote character
11367             # $quote_pos = index to check next for alphanumeric delimiter
11368             # $quote_depth = nesting depth, since delimiters '{ ( [ <' can be nested.
11369             # $quoted_string = the text of the quote (without quotation tokens)
11370 3271         4024 my ( $tok, $end_tok );
11371 3271         3836 my $i = $i_beg - 1;
11372 3271         3835 my $quoted_string = EMPTY_STRING;
11373              
11374 3271         3628 0 && do {
11375             print {*STDOUT}
11376             "QUOTE entering with quote_pos = $quote_pos i=$i beginning_tok =$beginning_tok\n";
11377             };
11378              
11379             # for a non-blank token, get the corresponding end token
11380 3271 100 33     10662 if (
      66        
11381             $is_punct_char{$beginning_tok}
11382             || ( length($beginning_tok)
11383             && $beginning_tok !~ /^\s+$/ )
11384             )
11385             {
11386             $end_tok =
11387             $matching_end_token{$beginning_tok}
11388 244 100       621 ? $matching_end_token{$beginning_tok}
11389             : $beginning_tok;
11390             }
11391              
11392             # for a blank token, find and use the first non-blank one
11393             else {
11394 3027 100       5003 my $allow_quote_comments = ( $i < 0 ) ? 1 : 0; # i<0 means we saw a <cr>
11395              
11396 3027         5040 while ( $i < $max_token_index ) {
11397 3029         4104 $tok = $rtokens->[ ++$i ];
11398              
11399 3029 100       5228 if ( $rtoken_type->[$i] ne 'b' ) {
11400              
11401 3027 50 66     6094 if ( ( $tok eq '#' ) && ($allow_quote_comments) ) {
11402 0         0 $i = $max_token_index;
11403             }
11404             else {
11405              
11406 3027 100       4668 if ( length($tok) > 1 ) {
11407 1 50       3 if ( $quote_pos <= 0 ) { $quote_pos = 1 }
  1         1  
11408 1         3 $beginning_tok = substr( $tok, $quote_pos - 1, 1 );
11409             }
11410             else {
11411 3026         3437 $beginning_tok = $tok;
11412 3026         3514 $quote_pos = 0;
11413             }
11414             $end_tok =
11415             $matching_end_token{$beginning_tok}
11416 3027 100       5330 ? $matching_end_token{$beginning_tok}
11417             : $beginning_tok;
11418 3027         3436 $quote_depth = 1;
11419 3027         4032 last;
11420             }
11421             }
11422             else {
11423 2         5 $allow_quote_comments = 1;
11424             }
11425             } ## end while ( $i < $max_token_index)
11426             }
11427              
11428             # There are two different loops which search for the ending quote
11429             # character. In the rare case of an alphanumeric quote delimiter, we
11430             # have to look through alphanumeric tokens character-by-character, since
11431             # the pre-tokenization process combines multiple alphanumeric
11432             # characters, whereas for a non-alphanumeric delimiter, only tokens of
11433             # length 1 can match.
11434              
11435             #----------------------------------------------------------------
11436             # Case 1 (rare): loop for case of alphanumeric quote delimiter..
11437             # "quote_pos" is the position the current word to begin searching
11438             #----------------------------------------------------------------
11439 3271 100 100     7140 if ( !$is_punct_char{$beginning_tok} && $beginning_tok =~ /\w/ ) {
11440              
11441             # Note this because it is not recommended practice except
11442             # for obfuscated perl contests
11443 1 50       3 if ( $in_quote == 1 ) {
11444 1         5 $self->write_logfile_entry(
11445             "Note: alphanumeric quote delimiter ($beginning_tok) \n");
11446             }
11447              
11448             # Note: changed < to <= here to fix c109. Relying on extra end blanks.
11449 1         4 while ( $i <= $max_token_index ) {
11450              
11451 4 100 66     9 if ( $quote_pos == 0 || ( $i < 0 ) ) {
11452 3         5 $tok = $rtokens->[ ++$i ];
11453              
11454 3 100       7 if ( $tok eq BACKSLASH ) {
11455              
11456             # retain backslash unless it hides the end token
11457 1 50       4 $quoted_string .= $tok
11458             unless ( $rtokens->[ $i + 1 ] eq $end_tok );
11459 1         1 $quote_pos++;
11460 1 50       4 last if ( $i >= $max_token_index );
11461 1         2 $tok = $rtokens->[ ++$i ];
11462             }
11463             }
11464 4         4 my $old_pos = $quote_pos;
11465              
11466 4         6 $quote_pos = 1 + index( $tok, $end_tok, $quote_pos );
11467              
11468 4 100       6 if ( $quote_pos > 0 ) {
11469              
11470 1         3 $quoted_string .=
11471             substr( $tok, $old_pos, $quote_pos - $old_pos - 1 );
11472              
11473             # NOTE: any quote modifiers will be at the end of '$tok'. If we
11474             # wanted to check them, this is the place to get them. But
11475             # this quote form is rarely used in practice, so it isn't
11476             # worthwhile.
11477              
11478 1         2 $quote_depth--;
11479              
11480 1 50       4 if ( $quote_depth == 0 ) {
11481 1         2 $in_quote--;
11482 1         2 last;
11483             }
11484             }
11485             else {
11486 3 50       6 if ( $old_pos <= length($tok) ) {
11487 3         6 $quoted_string .= substr( $tok, $old_pos );
11488             }
11489             }
11490             } ## end while ( $i <= $max_token_index)
11491             }
11492              
11493             #-----------------------------------------------------------------------
11494             # Case 2 (normal): loop for case of a non-alphanumeric quote delimiter..
11495             #-----------------------------------------------------------------------
11496             else {
11497              
11498 3270         5585 while ( $i < $max_token_index ) {
11499 12532         13941 $tok = $rtokens->[ ++$i ];
11500              
11501 12532 100       20510 if ( $tok eq $end_tok ) {
    100          
    100          
11502 3027         3374 $quote_depth--;
11503              
11504 3027 100       4561 if ( $quote_depth == 0 ) {
11505 3026         3258 $in_quote--;
11506 3026         3580 last;
11507             }
11508             }
11509             elsif ( $tok eq $beginning_tok ) {
11510 1         1 $quote_depth++;
11511             }
11512             elsif ( $tok eq BACKSLASH ) {
11513              
11514             # retain backslash unless it hides the beginning or end token
11515 459         705 $tok = $rtokens->[ ++$i ];
11516 459 100 100     1677 $quoted_string .= BACKSLASH
11517             if ( $tok ne $end_tok && $tok ne $beginning_tok );
11518             }
11519             else {
11520             ## nothing special
11521             }
11522 9506         13224 $quoted_string .= $tok;
11523             } ## end while ( $i < $max_token_index)
11524             }
11525 3271 100       5360 if ( $i > $max_token_index ) { $i = $max_token_index }
  10         13  
11526             return (
11527              
11528 3271         10655 $i,
11529             $in_quote,
11530             $beginning_tok,
11531             $quote_pos,
11532             $quote_depth,
11533             $quoted_string,
11534              
11535             );
11536             } ## end sub follow_quoted_string
11537              
11538             sub indicate_error {
11539 0     0 0 0 my ( $self, $msg, $line_number, $input_line, $pos, $caret ) = @_;
11540              
11541             # write input line and line with carat's showing where error was detected
11542 0         0 $self->interrupt_logfile();
11543 0         0 $self->warning($msg);
11544 0         0 $self->write_error_indicator_pair( $line_number, $input_line, $pos,
11545             $caret );
11546 0         0 $self->resume_logfile();
11547 0         0 return;
11548             } ## end sub indicate_error
11549              
11550             sub write_error_indicator_pair {
11551 0     0 0 0 my ( $self, $line_number, $input_line, $pos, $caret ) = @_;
11552 0         0 my ( $offset, $numbered_line, $underline ) =
11553             make_numbered_line( $line_number, $input_line, $pos );
11554 0         0 $underline = write_on_underline( $underline, $pos - $offset, $caret );
11555 0         0 $self->warning( $numbered_line . "\n" );
11556 0         0 $underline =~ s/\s+$//;
11557 0         0 $self->warning( $underline . "\n" );
11558 0         0 return;
11559             } ## end sub write_error_indicator_pair
11560              
11561             sub make_numbered_line {
11562              
11563 0     0 0 0 my ( $lineno, $str, $pos ) = @_;
11564              
11565             # Given:
11566             # $lineno=line number
11567             # $str = an input line
11568             # $pos = character position of interest
11569             # Create a string not longer than 80 characters of the form:
11570             # $lineno: sub_string
11571             # such that the sub_string of $str contains the position of interest
11572             #
11573             # Here is an example of what we want, in this case we add trailing
11574             # '...' because the line is long.
11575             #
11576             # 2: (One of QAML 2.0's authors is a member of the World Wide Web Con ...
11577             #
11578             # Here is another example, this time in which we used leading '...'
11579             # because of excessive length:
11580             #
11581             # 2: ... er of the World Wide Web Consortium's
11582             #
11583             # input parameters are:
11584             # $lineno = line number
11585             # $str = the text of the line
11586             # $pos = position of interest (the error) : 0 = first character
11587             #
11588             # We return :
11589             # - $offset = an offset which corrects the position in case we only
11590             # display part of a line, such that $pos-$offset is the effective
11591             # position from the start of the displayed line.
11592             # - $numbered_line = the numbered line as above,
11593             # - $underline = a blank 'underline' which is all spaces with the same
11594             # number of characters as the numbered line.
11595              
11596 0 0       0 my $offset = ( $pos < 60 ) ? 0 : $pos - 40;
11597 0         0 my $excess = length($str) - $offset - 68;
11598 0 0       0 my $numc = ( $excess > 0 ) ? 68 : undef;
11599              
11600 0 0       0 if ( defined($numc) ) {
11601 0 0       0 if ( $offset == 0 ) {
11602 0         0 $str = substr( $str, $offset, $numc - 4 ) . " ...";
11603             }
11604             else {
11605 0         0 $str = "... " . substr( $str, $offset + 4, $numc - 4 ) . " ...";
11606             }
11607             }
11608             else {
11609              
11610 0 0       0 if ( $offset == 0 ) {
11611             }
11612             else {
11613 0         0 $str = "... " . substr( $str, $offset + 4 );
11614             }
11615             }
11616              
11617 0         0 my $numbered_line = sprintf( "%d: ", $lineno );
11618 0         0 $offset -= length($numbered_line);
11619 0         0 $numbered_line .= $str;
11620 0         0 my $underline = SPACE x length($numbered_line);
11621 0         0 return ( $offset, $numbered_line, $underline );
11622             } ## end sub make_numbered_line
11623              
11624             sub write_on_underline {
11625              
11626 0     0 0 0 my ( $underline, $pos, $pos_chr ) = @_;
11627              
11628             # The "underline" is a string that shows where an error is; it starts
11629             # out as a string of blanks with the same length as the numbered line of
11630             # code above it, and we have to add marking to show where an error is.
11631             # In the example below, we want to write the string '--^' just below
11632             # the line of bad code:
11633             #
11634             # 2: (One of QAML 2.0's authors is a member of the World Wide Web Con ...
11635             # ---^
11636             # We are given the current underline string, plus a position and a
11637             # string to write on it.
11638             #
11639             # In the above example, there will be 2 calls to do this:
11640             # First call: $pos=19, pos_chr=^
11641             # Second call: $pos=16, pos_chr=---
11642             #
11643             # This is a trivial thing to do with substr, but there is some
11644             # checking to do.
11645              
11646             # check for error..shouldn't happen
11647 0 0 0     0 if ( $pos < 0 || $pos > length($underline) ) {
11648 0         0 return $underline;
11649             }
11650 0         0 my $excess = length($pos_chr) + $pos - length($underline);
11651 0 0       0 if ( $excess > 0 ) {
11652 0         0 $pos_chr = substr( $pos_chr, 0, length($pos_chr) - $excess );
11653             }
11654 0         0 substr( $underline, $pos, length($pos_chr), $pos_chr );
11655 0         0 return ($underline);
11656             } ## end sub write_on_underline
11657              
11658             sub pre_tokenize {
11659              
11660 7285     7285 0 11732 my ( $str, ($max_tokens_wanted) ) = @_;
11661              
11662             # Input parameters:
11663             # $str = string to be parsed
11664             # $max_tokens_wanted > 0 to stop on reaching this many tokens.
11665             # = undef or 0 means get all tokens
11666              
11667             # Break a string, $str, into a sequence of preliminary tokens (pre-tokens).
11668             # We look for these types of tokens:
11669             # words (type='w'), example: 'max_tokens_wanted'
11670             # digits (type = 'd'), example: '0755'
11671             # whitespace (type = 'b'), example: ' '
11672             # single character punct (type = char) example: '='
11673              
11674             # Later operations will combine one or more of these pre-tokens into final
11675             # tokens. We cannot do better than this yet because we might be in a
11676             # quoted string or pattern.
11677              
11678             # An advantage of doing this pre-tokenization step is that it keeps almost
11679             # all of the regex parsing very simple and localized right here. A
11680             # disadvantage is that in some extremely rare instances we will have to go
11681             # back and split a pre-token.
11682              
11683             # Return parameters:
11684 7285         9891 my @tokens = (); # array of the tokens themselves
11685 7285         11638 my @token_map = (0); # string position of start of each token
11686 7285         8534 my @type = (); # 'b'=whitespace, 'd'=digits, 'w'=alpha, or punct
11687              
11688 7285 100       11621 if ( !$max_tokens_wanted ) { $max_tokens_wanted = -1 }
  6964         8057  
11689              
11690 7285         12362 while ( $max_tokens_wanted-- ) {
11691              
11692 97377 100       186870 if (
11693             $str =~ m{
11694             \G(
11695             (\s+) # type 'b' = whitespace - this must come before \W
11696             | (\W) # or type=char = single-character, non-whitespace punct
11697             | (\d+) # or type 'd' = sequence of digits - must come before \w
11698             | (\w+) # or type 'w' = words not starting with a digit
11699             )
11700             }gcx
11701             )
11702             {
11703 90254         128364 push @tokens, $1;
11704 90254 100       168512 push @type,
    100          
    100          
11705             defined($2) ? 'b' : defined($3) ? $1 : defined($4) ? 'd' : 'w';
11706 90254         129215 push @token_map, pos($str);
11707             }
11708              
11709             # that's all..
11710             else {
11711 7123         36263 return ( \@tokens, \@token_map, \@type );
11712             }
11713             } ## end while ( $max_tokens_wanted...)
11714              
11715 162         488 return ( \@tokens, \@token_map, \@type );
11716             } ## end sub pre_tokenize
11717              
11718             sub show_tokens {
11719              
11720             # This is an uncalled debug routine, saved for reference
11721 0     0 0   my ( $rtokens, $rtoken_map ) = @_;
11722 0           my $num = scalar( @{$rtokens} );
  0            
11723              
11724 0           foreach my $i ( 0 .. $num - 1 ) {
11725 0           my $len = length( $rtokens->[$i] );
11726 0           print {*STDOUT} "$i:$len:$rtoken_map->[$i]:$rtokens->[$i]:\n";
  0            
11727             }
11728 0           return;
11729             } ## end sub show_tokens
11730              
11731             sub dump_token_types {
11732 0     0 0   my ( $class, $fh ) = @_;
11733              
11734             # This should be the latest list of token types in use
11735             # adding NEW_TOKENS: add a comment here
11736 0           $fh->print(<<'END_OF_LIST');
11737              
11738             Here is a list of the token types currently used for lines of type 'CODE'.
11739             For the following tokens, the "type" of a token is just the token itself.
11740              
11741             .. :: << >> ** && .. || // -> => += -= .= %= &= |= ^= *= <>
11742             ( ) <= >= == =~ !~ != ++ -- /= x=
11743             ... **= <<= >>= &&= ||= //= <=>
11744             , + - / * | % ! x ~ = \ ? : . < > ^ & ^^
11745              
11746             The following additional token types are defined:
11747              
11748             type meaning
11749             b blank (white space)
11750             { indent: opening structural curly brace or square bracket or paren
11751             (code block, anonymous hash reference, or anonymous array reference)
11752             } outdent: right structural curly brace or square bracket or paren
11753             [ left non-structural square bracket (enclosing an array index)
11754             ] right non-structural square bracket
11755             ( left non-structural paren (all but a list right of an =)
11756             ) right non-structural paren
11757             L left non-structural curly brace (enclosing a key)
11758             R right non-structural curly brace
11759             ; terminal semicolon
11760             f indicates a semicolon in a "for" statement
11761             h here_doc operator <<
11762             # a comment
11763             Q indicates a quote or pattern
11764             q indicates a qw quote block
11765             k a perl keyword
11766             C user-defined constant or constant function (with void prototype = ())
11767             U user-defined function taking parameters
11768             G user-defined function taking block parameter (like grep/map/eval)
11769             S sub definition (reported as type 'i' in older versions)
11770             P package definition (reported as type 'i' in older versions)
11771             t type indicator such as %,$,@,*,&,sub
11772             w bare word (perhaps a subroutine call)
11773             i identifier of some type (with leading %, $, @, *, &, sub, -> )
11774             n a number
11775             v a v-string
11776             F a file test operator (like -e)
11777             Y File handle
11778             Z identifier in indirect object slot: may be file handle, object
11779             J LABEL: code block label
11780             j LABEL after next, last, redo, goto
11781             p unary +
11782             m unary -
11783             pp pre-increment operator ++
11784             mm pre-decrement operator --
11785             A : used as attribute separator
11786              
11787             Here are the '_line_type' codes used internally:
11788             SYSTEM - system-specific code before hash-bang line
11789             CODE - line of perl code (including comments)
11790             POD_START - line starting pod, such as '=head'
11791             POD - pod documentation text
11792             POD_END - last line of pod section, '=cut'
11793             HERE - text of here-document
11794             HERE_END - last line of here-doc (target word)
11795             FORMAT - format section
11796             FORMAT_END - last line of format section, '.'
11797             SKIP - code skipping section
11798             SKIP_END - last line of code skipping section, '#>>V'
11799             DATA_START - __DATA__ line
11800             DATA - unidentified text following __DATA__
11801             END_START - __END__ line
11802             END - unidentified text following __END__
11803             ERROR - we are in big trouble, probably not a perl script
11804             END_OF_LIST
11805              
11806 0           return;
11807             } ## end sub dump_token_types
11808              
11809             #------------------
11810             # About Token Types
11811             #------------------
11812              
11813             # The array "valid_token_types" in the BEGIN section has an up-to-date list
11814             # of token types. Sub 'dump_token_types' should be kept up to date with
11815             # token types.
11816              
11817             # Ideally, tokens are the smallest pieces of text
11818             # such that a newline may be inserted between any pair of tokens without
11819             # changing or invalidating the program. This version comes close to this,
11820             # although there are necessarily a few exceptions which must be caught by
11821             # the formatter. Many of these involve the treatment of bare words.
11822             #
11823             # To simplify things, token types are either a single character, or they
11824             # are identical to the tokens themselves.
11825             #
11826             # As a debugging aid, the -D flag creates a file containing a side-by-side
11827             # comparison of the input string and its tokenization for each line of a file.
11828             # This is an invaluable debugging aid.
11829             #
11830             # In addition to tokens, and some associated quantities, the tokenizer
11831             # also returns flags indication any special line types. These include
11832             # quotes, here_docs, formats.
11833             #
11834             #------------------
11835             # Adding NEW_TOKENS
11836             #------------------
11837             #
11838             # Here are some notes on the minimal steps. I wrote these notes while
11839             # adding the 'v' token type for v-strings, which are things like version
11840             # numbers 5.6.0, and ip addresses, and will use that as an example. ( You
11841             # can use your editor to search for the string "NEW_TOKENS" to find the
11842             # appropriate sections to change):
11843              
11844             # *. For another example, search for the smartmatch operator '~~'
11845             # with your editor to see where updates were made for it.
11846              
11847             # *. For another example, search for the string 'c250', which shows
11848             # locations where changes for new types 'P' and 'S' were made.
11849              
11850             # *. Think of a new, unused character for the token type, and add to
11851             # the array @valid_token_types in the BEGIN section of this package.
11852             # For example, I used 'v' for v-strings.
11853             #
11854             # *. Implement coding to recognize the $type of the token in this routine.
11855             # This is the hardest part, and is best done by imitating or modifying
11856             # some of the existing coding. For example, to recognize v-strings, I
11857             # patched 'sub scan_bare_identifier' to recognize v-strings beginning with
11858             # 'v' and 'sub scan_number' to recognize v-strings without the leading 'v'.
11859             #
11860             # *. Update sub operator_expected. This update is critically important but
11861             # the coding is trivial. Look at the comments in that routine for help.
11862             # For v-strings, which should behave like numbers, I just added 'v' to the
11863             # regex used to handle numbers and strings (types 'n' and 'Q').
11864             #
11865             # *. Implement a 'bond strength' rule in sub set_bond_strengths in
11866             # Perl::Tidy::Formatter for breaking lines around this token type. You can
11867             # skip this step and take the default at first, then adjust later to get
11868             # desired results. For adding type 'v', I looked at sub bond_strength and
11869             # saw that number type 'n' was using default strengths, so I didn't do
11870             # anything. I may tune it up someday if I don't like the way line
11871             # breaks with v-strings look.
11872             #
11873             # *. Implement a 'whitespace' rule in sub set_whitespace_flags in
11874             # Perl::Tidy::Formatter. For adding type 'v', I looked at this routine
11875             # and saw that type 'n' used spaces on both sides, so I just added 'v'
11876             # to the array @spaces_both_sides.
11877             #
11878             # *. Update HtmlWriter package so that users can colorize the token as
11879             # desired. This is quite easy; see comments identified by 'NEW_TOKENS' in
11880             # that package. For v-strings, I initially chose to use a default color
11881             # equal to the default for numbers, but it might be nice to change that
11882             # eventually.
11883             #
11884             # *. Update comments in Perl::Tidy::Tokenizer::dump_token_types.
11885             #
11886             # *. Run lots and lots of debug tests. Start with special files designed
11887             # to test the new token type. Run with the -D flag to create a .DEBUG
11888             # file which shows the tokenization. When these work ok, test as many old
11889             # scripts as possible. Start with all of the '.t' files in the 'test'
11890             # directory of the distribution file. Compare .tdy output with previous
11891             # version and updated version to see the differences. Then include as
11892             # many more files as possible. My own technique has been to collect a huge
11893             # number of perl scripts (thousands!) into one directory and run perltidy
11894             # *, then run diff between the output of the previous version and the
11895             # current version.
11896              
11897             BEGIN {
11898              
11899             # These names are used in error messages
11900 44     44   280 @opening_brace_names = qw# '{' '[' '(' '?' #;
11901 44         128 @closing_brace_names = qw# '}' ']' ')' ':' #;
11902              
11903 44         95 my @q;
11904              
11905 44         461 my @digraphs = qw#
11906             .. :: << >> ** && || // -> => += -= .= %= &= |= ^= *= <>
11907             <= >= == =~ !~ != ++ -- /= x= ~~ ~. |. &. ^. ^^
11908             #;
11909 44         1098 $is_digraph{$_} = 1 for @digraphs;
11910              
11911 44         205 @q = qw(
11912             . : < > * & | / - = + - % ^ ! x ~
11913             );
11914 44         372 $can_start_digraph{$_} = 1 for @q;
11915              
11916 44         157 my @trigraphs =
11917             qw( ... **= <<= >>= &&= ||= //= <=> !~~ &.= |.= ^.= <<~ ^^= );
11918 44         868 $is_trigraph{$_} = 1 for @trigraphs;
11919              
11920 44         111 my @tetragraphs = qw( <<>> );
11921 44         115 $is_tetragraph{$_} = 1 for @tetragraphs;
11922              
11923             # make a hash of all valid token types for self-checking the tokenizer
11924             # (adding NEW_TOKENS : select a new character and add to this list)
11925             # fix for c250: added new token type 'P' and 'S'
11926 44         501 my @valid_token_types = qw#
11927             A b C G L R f h Q k t w i q n p m F pp mm U j J Y Z v P S
11928             { } ( ) [ ] ; + - / * | % ! x ~ = ? : . < > ^ &
11929             #;
11930 44         171 push @valid_token_types, BACKSLASH;
11931 44         322 push( @valid_token_types, @digraphs );
11932 44         140 push( @valid_token_types, @trigraphs );
11933 44         76 push( @valid_token_types, @tetragraphs );
11934 44         81 push( @valid_token_types, ( '#', COMMA, 'CORE::' ) );
11935 44         2285 $is_valid_token_type{$_} = 1 for @valid_token_types;
11936              
11937             # a list of file test letters, as in -e (Table 3-4 of 'camel 3')
11938 44         230 my @file_test_operators =
11939             qw( A B C M O R S T W X b c d e f g k l o p r s t u w x z );
11940 44         622 $is_file_test_operator{$_} = 1 for @file_test_operators;
11941              
11942             # these functions have prototypes of the form (&), so when they are
11943             # followed by a block, that block MAY BE followed by an operator.
11944             # Smartmatch operator ~~ may be followed by anonymous hash or array ref
11945 44         133 @q = qw( do eval );
11946 44         133 $is_block_operator{$_} = 1 for @q;
11947              
11948             # these functions allow an identifier in the indirect object slot
11949 44         94 @q = qw( print printf sort exec system say );
11950 44         265 $is_indirect_object_taker{$_} = 1 for @q;
11951              
11952             # Keywords which definitely produce error if an OPERATOR is expected
11953 44         98 @q = qw( my our state local use require );
11954 44         241 $is_TERM_keyword{$_} = 1 for @q;
11955              
11956             # Note: 'field' will be added by sub check_options if --use-feature=class
11957 44         87 @q = qw( my our state );
11958 44         124 $is_my_our_state{$_} = 1 for @q;
11959              
11960             # These tokens may precede a code block
11961             # patched for SWITCH/CASE/CATCH. Actually these could be removed
11962             # now and we could let the extended-syntax coding handle them.
11963             # Added 'default' for Switch::Plain.
11964             # Note: 'ADJUST' will be added by sub check_options if --use-feature=class
11965 44         215 @q = qw(
11966             BEGIN END CHECK INIT AUTOLOAD DESTROY
11967             UNITCHECK continue if elsif else unless
11968             do while until eval for foreach
11969             map grep sort switch case given
11970             when default catch try finally
11971             );
11972 44         894 $is_code_block_token{$_} = 1 for @q;
11973              
11974             # These block types terminate statements and do not need a trailing
11975             # semicolon; patched for SWITCH/CASE/; This may be updated in sub
11976             # check_options.
11977 44         285 @q = qw( } { BEGIN END CHECK INIT AUTOLOAD DESTROY UNITCHECK continue ;
11978             if elsif else unless while until for foreach switch case given when );
11979 44         479 $is_zero_continuation_block_type{$_} = 1 for @q;
11980              
11981             # Note: this hash was formerly named '%is_not_zero_continuation_block_type'
11982             # to contrast it with the block types in '%is_zero_continuation_block_type'
11983             # Note: added 'sub' for anonymous sub blocks (c443)
11984 44         154 @q = qw( sort map grep eval do sub );
11985 44         191 $is_sort_map_grep_eval_do_sub{$_} = 1 for @q;
11986              
11987 44         103 @q = qw( sort map grep );
11988 44         109 $is_sort_map_grep{$_} = 1 for @q;
11989              
11990 44         89 %is_grep_alias = ();
11991              
11992             # I'll build the list of keywords incrementally
11993 44         72 my @Keywords = ();
11994              
11995             # keywords and tokens after which a value or pattern is expected,
11996             # but not an operator. In other words, these should consume terms
11997             # to their right, or at least they are not expected to be followed
11998             # immediately by operators.
11999 44         1234 my @value_requestor = qw(
12000             AUTOLOAD BEGIN CHECK DESTROY
12001             END EQ GE GT
12002             INIT LE LT NE
12003             UNITCHECK abs accept alarm
12004             and atan2 bind binmode
12005             bless break caller chdir
12006             chmod chomp chop chown
12007             chr chroot close closedir
12008             cmp connect continue cos
12009             crypt dbmclose dbmopen defined
12010             delete die dump each
12011             else elsif eof eq
12012             evalbytes exec exists exit
12013             exp fc fcntl fileno
12014             flock for foreach formline
12015             ge getc getgrgid getgrnam
12016             gethostbyaddr gethostbyname getnetbyaddr getnetbyname
12017             getpeername getpgrp getpriority getprotobyname
12018             getprotobynumber getpwnam getpwuid getservbyname
12019             getservbyport getsockname getsockopt glob
12020             gmtime goto grep gt
12021             hex if index int
12022             ioctl join keys kill
12023             last lc lcfirst le
12024             length link listen local
12025             localtime lock log lstat
12026             lt map mkdir msgctl
12027             msgget msgrcv msgsnd my
12028             ne next no not
12029             oct open opendir or
12030             ord our pack pipe
12031             pop pos print printf
12032             prototype push quotemeta rand
12033             read readdir readlink readline
12034             readpipe recv redo ref
12035             rename require reset return
12036             reverse rewinddir rindex rmdir
12037             scalar seek seekdir select
12038             semctl semget semop send
12039             sethostent setnetent setpgrp setpriority
12040             setprotoent setservent setsockopt shift
12041             shmctl shmget shmread shmwrite
12042             shutdown sin sleep socket
12043             socketpair sort splice split
12044             sprintf sqrt srand stat
12045             state study substr symlink
12046             syscall sysopen sysread sysseek
12047             system syswrite tell telldir
12048             tie tied truncate uc
12049             ucfirst umask undef unless
12050             unlink unpack unshift untie
12051             until use utime values
12052             vec waitpid warn while
12053             write xor case catch
12054             default err given isa
12055             say switch when
12056             );
12057              
12058             # Note: 'ADJUST', 'field' are added by sub check_options
12059             # if --use-feature=class
12060              
12061             # patched above for SWITCH/CASE given/when err say
12062             # 'err' is a fairly safe addition.
12063             # Added 'default' for Switch::Plain. Note that we could also have
12064             # a separate set of keywords to include if we see 'use Switch::Plain'
12065 44         1392 push( @Keywords, @value_requestor );
12066              
12067             # These are treated the same but are not keywords:
12068 44         107 my @extra_vr = qw( constant vars );
12069 44         194 push( @value_requestor, @extra_vr );
12070              
12071 44         6455 $expecting_term_token{$_} = 1 for @value_requestor;
12072              
12073             # this list contains keywords which do not look for arguments,
12074             # so that they might be followed by an operator, or at least
12075             # not a term.
12076 44         239 my @operator_requestor = qw(
12077             endgrent endhostent endnetent endprotoent
12078             endpwent endservent fork getgrent
12079             gethostent getlogin getnetent getppid
12080             getprotoent getpwent getservent setgrent
12081             setpwent time times wait
12082             wantarray
12083             );
12084              
12085 44         150 push( @Keywords, @operator_requestor );
12086              
12087             # These are treated the same but are not considered keywords:
12088 44         95 my @extra_or = qw( STDERR STDIN STDOUT );
12089              
12090 44         96 push( @operator_requestor, @extra_or );
12091              
12092 44         849 $expecting_operator_token{$_} = 1 for @operator_requestor;
12093              
12094             # these token TYPES expect trailing operator but not a term
12095             # note: ++ and -- are post-increment and decrement, 'C' = constant
12096 44         96 my @operator_requestor_types = qw( ++ -- C <> q );
12097              
12098             # NOTE: This hash is available but not currently used
12099 44         185 $expecting_operator_types{$_} = 1 for @operator_requestor_types;
12100              
12101             # these token TYPES consume values (terms)
12102             # note: pp and mm are pre-increment and decrement
12103             # f=semicolon in for, F=file test operator
12104 44         529 my @value_requestor_type = qw#
12105             L { ( [ ~ !~ =~ ; . .. ... A : && ! || // = + - x
12106             **= += -= .= /= *= %= x= &= |= ^= <<= >>= &&= ||= //=
12107             <= >= == != => > < % * / ? & | ** <=> ~~ !~~ <<~
12108             f F pp mm Y p m U J G j >> << ^ t
12109             ~. ^. |. &. ^.= |.= &.= ^^
12110             #;
12111 44         92 push @value_requestor_type, BACKSLASH;
12112 44         77 push @value_requestor_type, COMMA;
12113              
12114             # NOTE: This hash is available but not currently used
12115 44         1367 $expecting_term_types{$_} = 1 for @value_requestor_type;
12116              
12117             # Note: the following valid token types are not assigned here to
12118             # hashes requesting to be followed by values or terms, but are
12119             # instead currently hard-coded into sub operator_expected:
12120             # ) -> :: Q R Z ] b h i k n v w } #
12121              
12122             # A syntax error will occur if following operators are not followed by a
12123             # TERM (with an exception made for tokens in sub signatures).
12124             # NOTE: this list does not include unary operator '!'
12125              
12126             # Note the following omissions from the syntax checking operators below
12127             # 'U' = user sub, depends on prototype
12128             # 'F' = file test works on $_ if no following term
12129             # 'Y' = indirect object, too risky to check syntax
12130              
12131 44         494 my @binary_ops = qw#
12132             !~ =~ . .. : && || // = + - x
12133             **= += -= .= /= *= %= x= &= |= ^= <<= >>= &&= ||= //=
12134             <= >= == != > < % * / ? & | ** <=> ~~ !~~ <<~
12135             >> << ^
12136             ^. |. &. ^.= |.= &.= ^^
12137             #;
12138 44         881 $is_binary_operator_type{$_} = 1 for @binary_ops;
12139              
12140             # Note: omitting unary file test type 'F' here because it assumes $_
12141 44         124 my @unary_ops = qw# ! ~ ~. m p mm pp #;
12142 44         473 $is_binary_operator_type{$_} = 1 for @binary_ops;
12143 44         121 push @unary_ops, BACKSLASH;
12144 44         1192 $is_binary_or_unary_operator_type{$_} = 1 for ( @binary_ops, @unary_ops );
12145              
12146             # added xor ge gt le lt ( git #206 )
12147 44         134 my @binary_keywords = qw( and or err eq ne cmp xor ge gt le lt );
12148 44         245 $is_binary_keyword{$_} = 1 for @binary_keywords;
12149              
12150 44         320 $is_binary_or_unary_keyword{$_} = 1 for ( @binary_keywords, 'not' );
12151              
12152             # A syntax error occurs if a binary operator follows any of these types:
12153             # NOTE: a ',' cannot be included because of parenless calls (c015).
12154             # For example this is valid: print "hello\n", && print "goodbye\n";
12155             # NOTE: the 'not' keyword could be added to a corresponding _keyword list
12156             # NOTE: label 'j' omitted, for example: -f $file ? redo BLOCK : last BLOCK;
12157             # NOTE: Removed 'A': fixes git162.t
12158 44         169 @q = qw< L { [ ( ; f J t >;
12159 44         328 $is_not_a_TERM_producer_type{$_} = 1 for ( @q, @unary_ops );
12160              
12161 44         133 @q = qw( q qq qx qr s y tr m );
12162 44         284 $is_q_qq_qx_qr_s_y_tr_m{$_} = 1 for @q;
12163              
12164             # Note added 'qw' here
12165 44         121 @q = qw( q qq qw qx qr s y tr m );
12166 44         219 $is_q_qq_qw_qx_qr_s_y_tr_m{$_} = 1 for @q;
12167              
12168             # Quote modifiers:
12169             # original ref: camel 3 p 147,
12170             # but perl may accept undocumented flags
12171             # perl 5.10 adds 'p' (preserve)
12172             # Perl version 5.22 added 'n'
12173             # From http://perldoc.perl.org/perlop.html we have
12174             # /PATTERN/msixpodualngc or m?PATTERN?msixpodualngc
12175             # s/PATTERN/REPLACEMENT/msixpodualngcer
12176             # y/SEARCHLIST/REPLACEMENTLIST/cdsr
12177             # tr/SEARCHLIST/REPLACEMENTLIST/cdsr
12178             # qr/STRING/msixpodualn
12179 44         224 %quote_modifiers = (
12180             's' => '[msixpodualngcer]',
12181             'y' => '[cdsr]',
12182             'tr' => '[cdsr]',
12183             'm' => '[msixpodualngc]',
12184             'qr' => '[msixpodualn]',
12185             'q' => EMPTY_STRING,
12186             'qq' => EMPTY_STRING,
12187             'qw' => EMPTY_STRING,
12188             'qx' => EMPTY_STRING,
12189             );
12190              
12191             # Note: 'class' will be added by sub check_options if -use-feature=class
12192 44         83 @q = qw( package );
12193 44         124 $is_package{$_} = 1 for @q;
12194              
12195 44         128 @q = qw( if elsif unless );
12196 44         128 $is_if_elsif_unless{$_} = 1 for @q;
12197              
12198 44         89 @q = qw( ; t );
12199 44         124 $is_semicolon_or_t{$_} = 1 for @q;
12200              
12201 44         82 @q = qw( if elsif unless case when );
12202 44         144 $is_if_elsif_unless_case_when{$_} = 1 for @q;
12203              
12204             # Hash of other possible line endings which may occur.
12205             # Keep these coordinated with the regex where this is used.
12206             # Note: chr(13) = chr(015)="\r".
12207 44         99 @q = ( chr(13), chr(29), chr(26) );
12208 44         192 $other_line_endings{$_} = 1 for @q;
12209              
12210             # These keywords are handled specially in the tokenizer code:
12211 44         148 my @special_keywords =
12212             qw( do eval format m package q qq qr qw qx s sub tr y );
12213 44         237 push( @Keywords, @special_keywords );
12214              
12215             # Keywords after which list formatting may be used
12216             # WARNING: do not include |map|grep|eval or perl may die on
12217             # syntax errors (map1.t).
12218 44         525 my @keyword_taking_list = qw(
12219             and chmod chomp chop
12220             chown dbmopen die elsif
12221             exec fcntl for foreach
12222             formline getsockopt given if
12223             index ioctl join kill
12224             local msgctl msgrcv msgsnd
12225             my open or our
12226             pack print printf push
12227             read readpipe recv return
12228             reverse rindex seek select
12229             semctl semget send setpriority
12230             setsockopt shmctl shmget shmread
12231             shmwrite socket socketpair sort
12232             splice split sprintf state
12233             substr syscall sysopen sysread
12234             sysseek system syswrite tie
12235             unless unlink unpack unshift
12236             until vec warn when
12237             while
12238             );
12239              
12240             # NOTE: This hash is available but not currently used
12241 44         1269 $is_keyword_taking_list{$_} = 1 for @keyword_taking_list;
12242              
12243             # perl functions which may be unary operators.
12244              
12245             # This list is used to decide if a pattern delimited by slashes, /pattern/,
12246             # can follow one of these keywords.
12247 44         115 @q = qw( chomp eof eval fc lc pop shift uc undef );
12248              
12249 44         228 $is_keyword_rejecting_slash_as_pattern_delimiter{$_} = 1 for @q;
12250              
12251             # These are keywords for which an arg may optionally be omitted. They are
12252             # currently only used to disambiguate a ? used as a ternary from one used
12253             # as a (deprecated) pattern delimiter. In the future, they might be used
12254             # to give a warning about ambiguous syntax before a /.
12255             # Note: split has been omitted (see note below).
12256 44         676 my @keywords_taking_optional_arg = qw(
12257             abs alarm caller chdir chomp chop
12258             chr chroot close cos defined die
12259             eof eval evalbytes exit exp fc
12260             getc glob gmtime hex int last
12261             lc lcfirst length localtime log lstat
12262             mkdir next oct ord pop pos
12263             print printf prototype quotemeta rand readline
12264             readlink readpipe redo ref require reset
12265             reverse rmdir say select shift sin
12266             sleep sqrt srand stat study tell
12267             uc ucfirst umask undef unlink warn
12268             write
12269             );
12270 44         1087 $is_keyword_taking_optional_arg{$_} = 1 for @keywords_taking_optional_arg;
12271              
12272             # This list is used to decide if a pattern delimited by question marks,
12273             # ?pattern?, can follow one of these keywords. Note that from perl 5.22
12274             # on, a ?pattern? is not recognized, so we can be much more strict than
12275             # with a /pattern/. Note that 'split' is not in this list. In current
12276             # versions of perl a question following split must be a ternary, but
12277             # in older versions it could be a pattern. The guessing algorithm will
12278             # decide. We are combining two lists here to simplify the test.
12279 44         671 @q = ( @keywords_taking_optional_arg, @operator_requestor );
12280 44         1565 $is_keyword_rejecting_question_as_pattern_delimiter{$_} = 1 for @q;
12281              
12282             # These are not used in any way yet
12283             # my @unused_keywords = qw(
12284             # __FILE__
12285             # __LINE__
12286             # __PACKAGE__
12287             # );
12288              
12289             # The list of keywords was originally extracted from function 'keyword' in
12290             # perl file toke.c version 5.005.03, using this utility, plus a
12291             # little editing: (file getkwd.pl):
12292             # while (<>) { while (/\"(.*)\"/g) { print "$1\n"; } }
12293             # Add 'get' prefix where necessary, then split into the above lists.
12294             # This list should be updated as necessary.
12295             # The list should not contain these special variables:
12296             # ARGV DATA ENV SIG STDERR STDIN STDOUT
12297             # __DATA__ __END__
12298              
12299 44         4216 $is_keyword{$_} = 1 for @Keywords;
12300              
12301 44         7409 %matching_end_token = (
12302             '{' => '}',
12303             '(' => ')',
12304             '[' => ']',
12305             '<' => '>',
12306             );
12307             } ## end BEGIN
12308              
12309             } ## end package Perl::Tidy::Tokenizer
12310             1;