eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}'
& eval 'exec perl -S $0 $argv:q'
if 0;
# $Id$
# Make the build output prettier.
use Getopt::Std;
use English;
use FileHandle;
use strict;
use vars qw/$opt_b $opt_c $opt_h $opt_i $opt_m $opt_o $opt_p $opt_t/;
if (!getopts ('bc:hi:m:o:pt') || $opt_h) {
print "Output Beautifier\n";
print "\n";
print "make_pretty.pl [-bpthr] [-c compiler] [-m msg] [-i file] [-o file]\n";
print " -b Brief-ify the output (only errors and warnings)\n";
print " -c compiler Specify the compiler type [msvc/makefile]\n";
print " -h Show this help output\n";
print " -i file Use file as input (defaults to stdin)\n";
print " -m Message to attach to the end of the output\n";
print " -o file Use file as output (defaults to stdout)\n";
print " -p Plain text mode (default is html)\n";
print " -t Only give totals for warnings and errors (auto -b)\n";
exit (1);
}
if (!defined $opt_c) {
$opt_c = 'makefile';
$opt_c = 'msvc' if ($OSNAME eq 'Win32');
}
if ($opt_c ne 'makefile' && $opt_c ne 'msvc') {
print STDERR "Error: Must specify msvc or makefile as the compiler type\n";
exit (1);
}
my $input;
my $output;
if (!defined $opt_i) {
$input = *STDIN;
}
else {
$input = new FileHandle ("$opt_i", "r");
if (!defined $input) {
print STDERR "Error: Could not open file <$opt_i> for input\n";
exit 1;
}
}
if (!defined $opt_o) {
$output = *STDOUT;
}
else {
$output = new FileHandle ("$opt_o", "w");
if (!defined $output) {
print STDERR "Error: Could not open file <$opt_o> for output\n";
exit 1;
}
}
$opt_b = 1 if ($opt_t);
my $header;
my $trailer;
my $bookmark_table_header;
my $bookmark_table_config;
my $bookmark_table_cvs;
my $bookmark_table_compiler;
my $bookmark_table_tests;
my $bookmark_table_footer;
my $bookmark_config;
my $bookmark_cvs;
my $bookmark_compiler;
my $bookmark_tests;
my $pre_section_title;
my $post_section_title;
my $pre_error;
my $post_error;
my $pre_warning;
my $post_warning;
my $pre_config;
my $post_config;
my $line_break;
my $separator;
###############################################################################
sub set_html_output ()
{
$header = "".
"
".
"Error/Warning Summary of Daily Build".
"".
"Error/Warning Summary of Daily Build
".
"\n";
$trailer = "";
$bookmark_table_header = "
".
"Quick links
".
"";
$bookmark_table_config = "- Config";
$bookmark_table_cvs = "
- CVS";
$bookmark_table_compiler = "
- Compilation";
$bookmark_table_tests = "
- Tests";
$bookmark_table_footer = "
";
$bookmark_config = "";
$bookmark_cvs = "";
$bookmark_compiler = "";
$bookmark_tests = "";
$pre_section_title = "";
$post_section_title = "
";
$pre_error = "";
$post_error = "";
$pre_warning = "";
$post_warning = "";
$pre_config = "";
$post_config = "";
$line_break = "
";
$separator = "
";
}
sub set_text_output ()
{
$header = "" ;
$trailer = "" ;
$bookmark_table_header = "";
$bookmark_table_config = "";
$bookmark_table_cvs = "";
$bookmark_table_compiler = "";
$bookmark_table_tests = "";
$bookmark_table_footer = "";
$bookmark_cvs = "";
$bookmark_compiler = "";
$bookmark_tests = "";
$pre_section_title = "\n================================================".
"================================\n";
$post_section_title = "\n================================================".
"================================\n";
$pre_error = "";
$post_error = "";
$pre_warning = "";
$post_warning = "";
$pre_config = "";
$post_config = "";
$line_break = "";
$separator = "------------------------------------------------".
"--------------------------------\n";
}
# is_warning checks for warnings. It returns
# 0 = no warning
# 1 = warning line
# 2 = possible warning
# 3 = false warning
sub is_warning ()
{
# Look for any warnings we should ignore
return 3 if (/^LINK : warning LNK4089:/);
# For some reason, there's a false license warning
return 3 if (/\(W\).*Compilation will proceed shortly./);
# AIX reports a bazillion multiple defines when doing templates.
return 3 if (m/^ld: \d+\-\d+ WARNING: Duplicate symbol:/);
# HP-UX uses 'nocompatwarnings' as an option to the compiler.
return 3 if (m/vnocompatwarnings/);
# SUN CC 5.0 defines __pthread_cleanup_push as a macro which causes
# warnings. See /usr/include/pthread.h and
# $ACE_ROOT/examples/Timer_Queue/Thread_Timer_Queue_Test.cpp for more
# information.
return 0 if (m/in call to __pthread_cleanup_push\(extern/);
# Look for lines that also should be color coded, but not counted
# as warnings.
return 2 if (/see declaration of/);
# Look for warnings
return 1 if ((/warning/i && !/ warning\(s\)/ && !/pragma warning\(s\)/)
|| /info: /i
|| /^make.*\*\*\*/
|| /^error \(future\)/i);
if (/^.*\.h: /
|| /^.*\.i: /
|| /^.*\.inl: /
|| /^.*\.cpp: /
|| /^.*\.java: /) {
return 1;
}
# IBM's compilers don't say the word "warning" - check for their code
return 1 if (m/^.*\d+\-\d+:? \(W\)/);
# didn't find anything
return 0;
}
# is_error checks for errors. It returns
# 0 = no error
# 1 = error line
# 2 = possible error
# 3 = false errors
sub is_error ()
{
# Look for any errors we should ignore
# AIX reports a bazillion multiple defines when doing templates; some
# have the word 'error' in the symbol name - ignore those.
return 0 if (m/^ld: \d+\-\d+ WARNING: Duplicate symbol:/);
# Linux has this annoying mktemp, mkstemp stuff. Ignore that
# for the timebeing
return 0 if (/is dangerous, better use/);
# Look for lines that also should be color coded, but not counted
# as errors.
return 2 if (/Types pointed to are unrelated/
|| /while compiling class-template/
|| /requires an explicit cast/);
if (/^.*:[0-9]+: /
&& !/^.*:[0-9]+: warning:/) {
return 1;
}
# AIX linking errors from ld
# But don't report the extra "check the map" message
return 0 if (/^ld: 0711\-345/);
return 1 if (/^ld: \d+\-\d+/);
# Look for linking errors too
return 1 if (/undefined reference to/
|| /: cannot open/
|| /: multiple definition of/
|| /path name does not exist/);
# Look for possible errors
return 1 if ((/error/i && !/ error\(s\), / && !/error \(future\)/i)
|| /^Fatal\:/
|| /: fatal:/);
# Again, IBM's compilers speak in code langauge
if (m/.*\d+\-\d+:? \([SI]\)/) {
# Ignore licensing messages
return 3 if (/.*Compilation will proceed shortly./);
return 1;
}
# didn't find anything
return 0;
}
sub print_build_header ($$)
{
my $directory = shift;
my $config = shift;
print $output "$separator$line_break";
print $output "$pre_config$directory$post_config$line_break\n";
print $output "$pre_config$config$post_config$line_break$line_break";
}
################################################################################
sub config_output (@)
{
if (!$opt_t) {
print $output $separator;
print $output $bookmark_config;
print $output $pre_section_title."Configuration".$post_section_title;
}
foreach (@_) {
s/</g if !$opt_p;
s/>/>/g if !$opt_p;
if (m/^\s*MAKE_PRETTY_COMPILER\:\s*(.*)\s*$/) {
$opt_c = $1;
}
elsif (!$opt_b) {
print $output "$_$line_break";
}
}
}
sub cvs_output (@)
{
my $patched = 0;
my $updated = 0;
my $modified = 0;
my $conflicts = 0;
my $unknown = 0;
if (!$opt_t) {
print $output $separator;
print $output $bookmark_cvs;
print $output $pre_section_title."CVS".$post_section_title;
}
foreach (@_) {
my $error = 0;
++$patched if (/^P /);
++$updated if (/^U /);
++$modified if (/^M /);
++$conflicts if (/^C /);
++$unknown if (/^\? /);
### Isn't really a conflict, but easiest place to put it.
if (/aborted/i || /cannot access/i || /no such file/i) {
$error = 1;
++$conflicts;
}
if ($opt_t) {
}
elsif ($error) {
print $output "$pre_error$_$post_error$line_break";
}
elsif (/^C /) {
print $output "$pre_error$_$post_error$line_break";
}
elsif (/^M /) {
print $output "$pre_warning$_$post_warning$line_break";
}
elsif (!$opt_b) {
print $output "$_$line_break";
}
}
print $output $line_break;
print $output "\nCVS Totals: ";
print $output " Patched: $patched Updated:$updated Modified: $modified ".
" Conflicts: $conflicts Unknown: $unknown\n\n$line_break";
}
sub compiler_output (@)
{
makefile_compiler_output (@_) if ($opt_c eq 'makefile');
msvc_compiler_output (@_) if ($opt_c eq 'msvc');
}
sub msvc_compiler_output (@)
{
my $project = "NULL";
my $configuration = "NULL";
my $dsp = "NULL";
my $first_problem = 1;
my $total_warnings = 0;
my $total_errors = 0;
my $bogus_warnings = 0;
my $bogus_errors = 0;
if (!$opt_t) {
print $output $separator;
print $output $bookmark_compiler;
print $output $pre_section_title."Compilation".$post_section_title;
}
foreach (@_) {
s/</g if !$opt_p;
s/>/>/g if !$opt_p;
my $is_warning = is_warning ();
my $is_error = is_error ();
if (/^Auto_compiling (.*)/) {
print $output $separator, $line_break, $pre_config, $_, $post_config, $line_break
if (!$opt_b && !$opt_t);
$dsp = $1;
$first_problem = 1;
}
elsif (/^--------------------Configuration: (.*) - (.*)--------------------/) {
print $output $pre_config.$_.$post_config.$line_break
if (!$opt_b && !$opt_t);
$project = $1;
$configuration = $2;
$first_problem = 1;
}
elsif (/\- (.*) error\(s\)\, (.*) warning\(s\)/) {
my $errors = $1 - $bogus_errors;
my $warnings = $2 - $bogus_warnings;
print $output "$project - $errors error(s), $warnings warnings(s)$line_break\n"
if (!$opt_b || ($opt_t && ($errors > 0 || $warnings > 0)));
$total_errors = $total_errors + $errors;
$total_warnings = $total_warnings + $warnings;
$bogus_warnings = 0;
$bogus_errors = 0;
}
elsif ($is_error == 3) {
++$bogus_errors;
}
elsif ($is_error == 2 || $is_error == 1) {
if (!$opt_t) {
print_build_header ($dsp, "$project: $configuration")
if ($first_problem && $opt_b);
$first_problem = 0;
print $output $pre_error, $_, $post_error, $line_break;
}
}
elsif ($is_warning == 3) {
++$bogus_warnings;
}
elsif ($is_warning == 2 || $is_warning == 1) {
if (!$opt_t) {
print_build_header ($dsp, "$project: $configuration")
if ($first_problem && $opt_b);
$first_problem = 0;
print $output $pre_warning, $_, $post_warning, $line_break;
}
}
else
{
print $output $_, $line_break
if (!$opt_b && !$opt_t);
}
}
print $output $line_break;
print $output "\nCompiler Totals: ";
print $output " Errors: $total_errors Warnings: $total_warnings\n\n$line_break";
}
sub makefile_compiler_output (@)
{
use vars qw/$directory $total_warnings $total_errors/;
use vars qw/$project_warnings $project_errors/;
local $directory = 'NULL';
my $first_problem = 1;
local $total_warnings = 0;
local $total_errors = 0;
local $project_warnings = 0;
local $project_errors = 0;
if (!$opt_t) {
print $output $separator;
print $output $bookmark_compiler;
print $output $pre_section_title."Compilation".$post_section_title;
}
sub print_summary ()
{
print $output $_.$line_break if (!$opt_b);
$total_errors = $total_errors + $project_errors;
$total_warnings = $total_warnings + $project_warnings;
$project_errors = 0;
$project_warnings = 0;
$directory = 'NULL';
}
sub set_directory ($)
{
my $dir = shift;
# Strip off the ACE_wrappers stuff
if ($dir =~ /ACE_wrappers\/build\/[^\/]*\/(.*)/) {
$dir = $1;
}
elsif ($dir =~ /ACE_wrappers\/(.*)/) {
$dir = $1;
}
# Strip of trailing '
if ($dir =~ /(.*)\'$/) {
$dir = $1;
}
$directory = $dir;
}
foreach (@_) {
s/</g if !$opt_p;
s/>/>/g if !$opt_p;
my $is_warning = is_warning ();
my $is_error = is_error ();
if (/Entering directory (.*)/) {
print_summary () if ($directory ne 'NULL');
print $output $pre_config, $1, $post_config, "\n", $line_break
if (!$opt_b && !$opt_t);
set_directory ($1);
$first_problem = 1;
}
elsif ($is_error == 3) {
# Do Nothing
}
elsif ($is_error == 2 || $is_error == 1) {
if (!$opt_t) {
print_build_header ($directory, "")
if ($first_problem && $opt_b);
$first_problem = 0;
print $output $pre_error, $_, $post_error, $line_break;
}
if ($is_error == 1) {
++$project_errors;
}
}
elsif ($is_warning == 3) {
# Do Nothing
}
elsif ($is_warning == 2 || $is_warning == 1) {
if (!$opt_t) {
print_build_header ($directory, "")
if ($first_problem && $opt_b);
$first_problem = 0;
print $output $pre_warning, $_, $post_warning, $line_break;
}
if ($is_warning == 1) {
++$project_warnings;
}
}
else {
print $output $_, $line_break
if (!$opt_b && !$opt_t);
}
}
print_summary () if ($directory ne 'NULL');
print $output $line_break;
print $output "\nCompiler Totals: ";
print $output " Errors: $total_errors Warnings: $total_warnings\n\n$line_break";
}
sub tests_output (@)
{
use vars qw/$first_problem $run_test $tests_failed/;
local $first_problem = 1;
local $run_test = 'NULL';
local $tests_failed = 0;
sub check_result ()
{
if ($first_problem == 0) {
if ($opt_t) {
print $output $pre_error."Failure in $run_test\n".$post_error.$line_break;
}
++$tests_failed;
}
}
if (!$opt_t) {
print $output $separator;
print $output $bookmark_tests;
print $output $pre_section_title."Tests".$post_section_title;
}
foreach (@_) {
s/</g if !$opt_p;
s/>/>/g if !$opt_p;
if (/auto_run_tests: (.*)/) {
check_result ();
print $output $pre_config.$1.$post_config."\n".$line_break
if (!$opt_b && !$opt_t);
$run_test = $1;
$first_problem = 1;
}
elsif (m/Error/
|| m/ERROR/
|| m/FAILED/
|| m/EXCEPTION/
|| m/pure virtual /i) {
if (!$opt_t) {
print_build_header ($run_test, "") if ($first_problem && $opt_b);
print $output "$pre_error$_$post_error$line_break";
}
$first_problem = 0;
}
else
{
print $output "$_$line_break"
if (!$opt_b && !$opt_t);
}
}
check_result ();
print $output $line_break;
print $output "\nTest Failures: $tests_failed\n\n$line_break";
}
##############################################################################
if ($opt_p) {
set_text_output ();
}
else {
set_html_output ();
}
my @configdata;
my @cvsdata;
my @compiledata;
my @testdata;
my %statemap = (nowhere => -1,
unknown => -2,
cvsdata => 1,
configdata => 2,
compiledata => 3,
testdata => 4);
my $state = 0;
my $endfound = 1;
my $multiplelogs = 0;
# Read in the input
while (<$input>) {
if (m/^#################### CVS/) {
$state = %statemap->{cvsdata};
}
elsif (m/^#################### Config/) {
$state = %statemap->{configdata};
}
elsif (m/^#################### Compile/) {
$state = %statemap->{compiledata};
}
elsif (m/^#################### Tests/) {
$state = %statemap->{testdata};
}
elsif (m/^#################### End/) {
$state = %statemap->{nowhere};
$endfound++;
}
elsif (m/^####################/) {
$state = %statemap->{unknown};
}
# if we find that we are starting a new log in the
# same file, delete the
if ($state != %statemap->{nowhere} && $endfound > 0) {
$endfound = 0;
@cvsdata = ();
@configdata = ();
@compiledata = ();
@testdata = ();
}
next if (m/^####################/);
if ($state == %statemap->{cvsdata}) { #CVS
push @cvsdata, $_;
}
elsif ($state == %statemap->{configdata}) { #Config
push @configdata, $_;
}
elsif ($state == %statemap->{compiledata}) { #Compile
push @compiledata, $_;
}
elsif ($state == %statemap->{testdata}) { #Test
push @testdata, $_;
}
}
print $output $header;
print $output $bookmark_table_header;
print $output $bookmark_table_config if ($#configdata >= 0);
print $output $bookmark_table_cvs if ($#cvsdata >= 0);
print $output $bookmark_table_compiler if ($#compiledata >= 0);
print $output $bookmark_table_tests if ($#testdata >= 0);
print $output $bookmark_table_footer;
config_output (@configdata) if ($#configdata >= 0);
cvs_output (@cvsdata) ; # CVS Section isn't optional
compiler_output (@compiledata) if ($#compiledata >= 0);
tests_output (@testdata) if ($#testdata >= 0);
print $output "$line_break\n\n$opt_m\n\n$line_break" if $opt_m;
print $output $trailer;