D7net
Home
Console
Upload
information
Create File
Create Folder
About
Tools
:
/
opt
/
cpanel
/
perl5
/
532
/
site_lib
/
Perl
/
Tidy
/
Filename :
Logger.pm
back
Copy
##################################################################### # # The Perl::Tidy::Logger class writes the .LOG and .ERR files # ##################################################################### package Perl::Tidy::Logger; use strict; use warnings; our $VERSION = '20210402'; sub AUTOLOAD { # Catch any undefined sub calls so that we are sure to get # some diagnostic information. This sub should never be called # except for a programming error. our $AUTOLOAD; return if ( $AUTOLOAD =~ /\bDESTROY$/ ); my ( $pkg, $fname, $lno ) = caller(); my $my_package = __PACKAGE__; print STDERR <<EOM; ====================================================================== Error detected in package '$my_package', version $VERSION Received unexpected AUTOLOAD call for sub '$AUTOLOAD' Called from package: '$pkg' Called from File '$fname' at line '$lno' This error is probably due to a recent programming change ====================================================================== EOM exit 1; } sub DESTROY { # required to avoid call to AUTOLOAD in some versions of perl } sub new { my ( $class, @args ) = @_; my %defaults = ( rOpts => undef, log_file => undef, warning_file => undef, fh_stderr => undef, saw_extruce => undef, display_name => undef, is_encoded_data => undef, ); my %args = ( %defaults, @args ); my $rOpts = $args{rOpts}; my $log_file = $args{log_file}; my $warning_file = $args{warning_file}; my $fh_stderr = $args{fh_stderr}; my $saw_extrude = $args{saw_extrude}; my $display_name = $args{display_name}; my $is_encoded_data = $args{is_encoded_data}; my $fh_warnings = $rOpts->{'standard-error-output'} ? $fh_stderr : undef; # remove any old error output file if we might write a new one unless ( $fh_warnings || ref($warning_file) ) { if ( -e $warning_file ) { unlink($warning_file) or Perl::Tidy::Die( "couldn't unlink warning file $warning_file: $!\n"); } } my $logfile_gap = defined( $rOpts->{'logfile-gap'} ) ? $rOpts->{'logfile-gap'} : 50; if ( $logfile_gap == 0 ) { $logfile_gap = 1 } my $filename_stamp = $display_name ? $display_name . ':' : "??"; my $input_stream_name = $display_name ? $display_name : "??"; return bless { _log_file => $log_file, _logfile_gap => $logfile_gap, _rOpts => $rOpts, _fh_warnings => $fh_warnings, _last_input_line_written => 0, _at_end_of_file => 0, _use_prefix => 1, _block_log_output => 0, _line_of_tokens => undef, _output_line_number => undef, _wrote_line_information_string => 0, _wrote_column_headings => 0, _warning_file => $warning_file, _warning_count => 0, _complaint_count => 0, _is_encoded_data => $is_encoded_data, _saw_code_bug => -1, # -1=no 0=maybe 1=for sure _saw_brace_error => 0, _saw_extrude => $saw_extrude, _output_array => [], _input_stream_name => $input_stream_name, _filename_stamp => $filename_stamp, }, $class; } sub get_input_stream_name { my $self = shift; return $self->{_input_stream_name}; } sub get_warning_count { my $self = shift; return $self->{_warning_count}; } sub get_use_prefix { my $self = shift; return $self->{_use_prefix}; } sub block_log_output { my $self = shift; $self->{_block_log_output} = 1; return; } sub unblock_log_output { my $self = shift; $self->{_block_log_output} = 0; return; } sub interrupt_logfile { my $self = shift; $self->{_use_prefix} = 0; $self->warning("\n"); $self->write_logfile_entry( '#' x 24 . " WARNING " . '#' x 25 . "\n" ); return; } sub resume_logfile { my $self = shift; $self->write_logfile_entry( '#' x 60 . "\n" ); $self->{_use_prefix} = 1; return; } sub we_are_at_the_last_line { my $self = shift; unless ( $self->{_wrote_line_information_string} ) { $self->write_logfile_entry("Last line\n\n"); } $self->{_at_end_of_file} = 1; return; } # record some stuff in case we go down in flames sub black_box { my ( $self, $line_of_tokens, $output_line_number ) = @_; my $input_line = $line_of_tokens->{_line_text}; my $input_line_number = $line_of_tokens->{_line_number}; # save line information in case we have to write a logfile message $self->{_line_of_tokens} = $line_of_tokens; $self->{_output_line_number} = $output_line_number; $self->{_wrote_line_information_string} = 0; my $last_input_line_written = $self->{_last_input_line_written}; if ( ( ( $input_line_number - $last_input_line_written ) >= $self->{_logfile_gap} ) || ( $input_line =~ /^\s*(sub|package)\s+(\w+)/ ) ) { my $structural_indentation_level = $line_of_tokens->{_level_0}; $structural_indentation_level = 0 if ( $structural_indentation_level < 0 ); $self->{_last_input_line_written} = $input_line_number; ( my $out_str = $input_line ) =~ s/^\s*//; chomp $out_str; $out_str = ( '.' x $structural_indentation_level ) . $out_str; if ( length($out_str) > 35 ) { $out_str = substr( $out_str, 0, 35 ) . " ...."; } $self->logfile_output( "", "$out_str\n" ); } return; } sub write_logfile_entry { my ( $self, @msg ) = @_; # add leading >>> to avoid confusing error messages and code $self->logfile_output( ">>>", "@msg" ); return; } sub write_column_headings { my $self = shift; $self->{_wrote_column_headings} = 1; my $routput_array = $self->{_output_array}; push @{$routput_array}, <<EOM; The nesting depths in the table below are at the start of the lines. The indicated output line numbers are not always exact. ci = levels of continuation indentation; bk = 1 if in BLOCK, 0 if not. in:out indent c b nesting code + messages; (messages begin with >>>) lines levels i k (code begins with one '.' per indent level) ------ ----- - - -------- ------------------------------------------- EOM return; } sub make_line_information_string { # make columns of information when a logfile message needs to go out my $self = shift; my $line_of_tokens = $self->{_line_of_tokens}; my $input_line_number = $line_of_tokens->{_line_number}; my $line_information_string = ""; if ($input_line_number) { my $output_line_number = $self->{_output_line_number}; my $brace_depth = $line_of_tokens->{_curly_brace_depth}; my $paren_depth = $line_of_tokens->{_paren_depth}; my $square_bracket_depth = $line_of_tokens->{_square_bracket_depth}; my $guessed_indentation_level = $line_of_tokens->{_guessed_indentation_level}; my $structural_indentation_level = $line_of_tokens->{_level_0}; $self->write_column_headings() unless $self->{_wrote_column_headings}; # keep logfile columns aligned for scripts up to 999 lines; # for longer scripts it doesn't really matter my $extra_space = ""; $extra_space .= ( $input_line_number < 10 ) ? " " : ( $input_line_number < 100 ) ? " " : ""; $extra_space .= ( $output_line_number < 10 ) ? " " : ( $output_line_number < 100 ) ? " " : ""; # there are 2 possible nesting strings: # the original which looks like this: (0 [1 {2 # the new one, which looks like this: {{[ # the new one is easier to read, and shows the order, but # could be arbitrarily long, so we use it unless it is too long my $nesting_string = "($paren_depth [$square_bracket_depth {$brace_depth"; my $nesting_string_new = $line_of_tokens->{_nesting_tokens_0}; my $ci_level = $line_of_tokens->{_ci_level_0}; if ( $ci_level > 9 ) { $ci_level = '*' } my $bk = ( $line_of_tokens->{_nesting_blocks_0} =~ /1$/ ) ? '1' : '0'; if ( length($nesting_string_new) <= 8 ) { $nesting_string = $nesting_string_new . " " x ( 8 - length($nesting_string_new) ); } $line_information_string = "L$input_line_number:$output_line_number$extra_space i$guessed_indentation_level:$structural_indentation_level $ci_level $bk $nesting_string"; } return $line_information_string; } sub logfile_output { my ( $self, $prompt, $msg ) = @_; return if ( $self->{_block_log_output} ); my $routput_array = $self->{_output_array}; if ( $self->{_at_end_of_file} || !$self->{_use_prefix} ) { push @{$routput_array}, "$msg"; } else { my $line_information_string = $self->make_line_information_string(); $self->{_wrote_line_information_string} = 1; if ($line_information_string) { push @{$routput_array}, "$line_information_string $prompt$msg"; } else { push @{$routput_array}, "$msg"; } } return; } sub get_saw_brace_error { my $self = shift; return $self->{_saw_brace_error}; } sub increment_brace_error { my $self = shift; $self->{_saw_brace_error}++; return; } sub brace_warning { my ( $self, $msg ) = @_; #use constant BRACE_WARNING_LIMIT => 10; my $BRACE_WARNING_LIMIT = 10; my $saw_brace_error = $self->{_saw_brace_error}; if ( $saw_brace_error < $BRACE_WARNING_LIMIT ) { $self->warning($msg); } $saw_brace_error++; $self->{_saw_brace_error} = $saw_brace_error; if ( $saw_brace_error == $BRACE_WARNING_LIMIT ) { $self->warning("No further warnings of this type will be given\n"); } return; } sub complain { # handle non-critical warning messages based on input flag my ( $self, $msg ) = @_; my $rOpts = $self->{_rOpts}; # these appear in .ERR output only if -w flag is used if ( $rOpts->{'warning-output'} ) { $self->warning($msg); } # otherwise, they go to the .LOG file else { $self->{_complaint_count}++; $self->write_logfile_entry($msg); } return; } sub warning { # report errors to .ERR file (or stdout) my ( $self, $msg ) = @_; #use constant WARNING_LIMIT => 50; my $WARNING_LIMIT = 50; # Always bump the warn count, even if no message goes out Perl::Tidy::Warn_count_bump(); my $rOpts = $self->{_rOpts}; unless ( $rOpts->{'quiet'} ) { my $warning_count = $self->{_warning_count}; my $fh_warnings = $self->{_fh_warnings}; my $is_encoded_data = $self->{_is_encoded_data}; if ( !$fh_warnings ) { my $warning_file = $self->{_warning_file}; ( $fh_warnings, my $filename ) = Perl::Tidy::streamhandle( $warning_file, 'w', $is_encoded_data ); $fh_warnings or Perl::Tidy::Die("couldn't open $filename $!\n"); Perl::Tidy::Warn_msg("## Please see file $filename\n") unless ref($warning_file); $self->{_fh_warnings} = $fh_warnings; $fh_warnings->print("Perltidy version is $Perl::Tidy::VERSION\n"); } my $filename_stamp = $self->{_filename_stamp}; if ( $warning_count < $WARNING_LIMIT ) { if ( !$warning_count ) { # On first error always write a line with the filename. Note # that the filename will be 'perltidy' if input is from stdin # or from a data structure. if ($filename_stamp) { $fh_warnings->print( "\n$filename_stamp Begin Error Output Stream\n"); } # Turn off filename stamping unless error output is directed # to the standard error output (with -se flag) if ( !$rOpts->{'standard-error-output'} ) { $filename_stamp = ""; $self->{_filename_stamp} = $filename_stamp; } } if ( $self->get_use_prefix() > 0 ) { $self->write_logfile_entry("WARNING: $msg"); # add prefix 'filename:line_no: ' to message lines my $input_line_number = Perl::Tidy::Tokenizer::get_input_line_number(); if ( !defined($input_line_number) ) { $input_line_number = -1 } my $pre_string = $filename_stamp . $input_line_number . ': '; chomp $msg; $msg =~ s/\n/\n$pre_string/g; $msg = $pre_string . $msg . "\n"; $fh_warnings->print($msg); } else { $self->write_logfile_entry($msg); # add prefix 'filename: ' to message lines if ($filename_stamp) { my $pre_string = $filename_stamp . " "; chomp $msg; $msg =~ s/\n/\n$pre_string/g; $msg = $pre_string . $msg . "\n"; } $fh_warnings->print($msg); } } $warning_count++; $self->{_warning_count} = $warning_count; if ( $warning_count == $WARNING_LIMIT ) { $fh_warnings->print( $filename_stamp . "No further warnings will be given\n" ); } } return; } # programming bug codes: # -1 = no bug # 0 = maybe, not sure. # 1 = definitely sub report_possible_bug { my $self = shift; my $saw_code_bug = $self->{_saw_code_bug}; $self->{_saw_code_bug} = ( $saw_code_bug < 0 ) ? 0 : $saw_code_bug; return; } sub report_definite_bug { my $self = shift; $self->{_saw_code_bug} = 1; return; } sub ask_user_for_bug_report { my ( $self, $infile_syntax_ok, $formatter ) = @_; my $saw_code_bug = $self->{_saw_code_bug}; if ( ( $saw_code_bug == 0 ) && ( $infile_syntax_ok == 1 ) ) { $self->warning(<<EOM); You may have encountered a code bug in perltidy. If you think so, and the problem is not listed in the BUGS file at http://perltidy.sourceforge.net, please report it so that it can be corrected. Include the smallest possible script which has the problem, along with the .LOG file. See the manual pages for contact information. Thank you! EOM } elsif ( $saw_code_bug == 1 ) { if ( $self->{_saw_extrude} ) { $self->warning(<<EOM); You may have encountered a bug in perltidy. However, since you are using the -extrude option, the problem may be with perl or one of its modules, which have occasional problems with this type of file. If you believe that the problem is with perltidy, and the problem is not listed in the BUGS file at http://perltidy.sourceforge.net, please report it so that it can be corrected. Include the smallest possible script which has the problem, along with the .LOG file. See the manual pages for contact information. Thank you! EOM } else { $self->warning(<<EOM); Oops, you seem to have encountered a bug in perltidy. Please check the BUGS file at http://perltidy.sourceforge.net. If the problem is not listed there, please report it so that it can be corrected. Include the smallest possible script which produces this message, along with the .LOG file if appropriate. See the manual pages for contact information. Your efforts are appreciated. Thank you! EOM my $added_semicolon_count = 0; eval { $added_semicolon_count = $formatter->get_added_semicolon_count(); }; if ( $added_semicolon_count > 0 ) { $self->warning(<<EOM); The log file shows that perltidy added $added_semicolon_count semicolons. Please rerun with -nasc to see if that is the cause of the syntax error. Even if that is the problem, please report it so that it can be fixed. EOM } } } return; } sub get_save_logfile { # To be called after tokenizer has finished to make formatting more # efficient. This is not precisely the same as the check used below # because we don't yet have the syntax check result, but since syntax # checking is off by default it will be the same except in debug runs with # syntax checking activated. In that case it will tell the formatter to # save the logfile even if it may actually be deleted based on the syntax # check. my $self = shift; my $saw_code_bug = $self->{_saw_code_bug}; my $rOpts = $self->{_rOpts}; return $saw_code_bug == 1 || $rOpts->{'logfile'} || $rOpts->{'check-syntax'}; } sub finish { # called after all formatting to summarize errors my ( $self, $infile_syntax_ok, $formatter ) = @_; my $rOpts = $self->{_rOpts}; my $warning_count = $self->{_warning_count}; my $saw_code_bug = $self->{_saw_code_bug}; my $save_logfile = ( $saw_code_bug == 0 && $infile_syntax_ok == 1 ) || $saw_code_bug == 1 || $rOpts->{'logfile'}; my $log_file = $self->{_log_file}; if ($warning_count) { if ($save_logfile) { $self->block_log_output(); # avoid echoing this to the logfile $self->warning( "The logfile $log_file may contain useful information\n"); $self->unblock_log_output(); } if ( $self->{_complaint_count} > 0 ) { $self->warning( "To see $self->{_complaint_count} non-critical warnings rerun with -w\n" ); } if ( $self->{_saw_brace_error} && ( $self->{_logfile_gap} > 1 || !$save_logfile ) ) { $self->warning("To save a full .LOG file rerun with -g\n"); } } $self->ask_user_for_bug_report( $infile_syntax_ok, $formatter ); if ($save_logfile) { my $log_file = $self->{_log_file}; my $is_encoded_data = $self->{_is_encoded_data}; my ( $fh, $filename ) = Perl::Tidy::streamhandle( $log_file, 'w', $is_encoded_data ); if ($fh) { my $routput_array = $self->{_output_array}; foreach ( @{$routput_array} ) { $fh->print($_) } if ( $log_file ne '-' && !ref $log_file ) { eval { $fh->close() }; } } } return; } 1;