1#! /bin/sh 2# -*- perl -*- 3exec perl -I $VXLROOT/core/bin -x $0 ${1+"$@"} 4#!perl 5#line 6 6 7# 8# crossge@crd.ge.com 9# 10# Modifications: 11# 13 May 2001 - Peter Vanroose - several minor fixes: 12# unified search strings for different compilers; 13# consequently removed specific computer names; 14# ad-hoc fix for bug in ParseDate which does not recognise "DST" in date; 15# simplified expressions, e.g. by replacing $currentline with $_; 16# added removal of $IUEROOT absolute path (which is irrelevant). 17# 21 May 2001 - Amitha Perera - fixed to work on FreeBSD (temp 18# filenames should not have $s in them in perl, because interpolation 19# happens in the most awkward places. 20# 17 Jun 2001 - Peter Vanroose - added test failures as errors, 21# but now ignoring "error in subdirs" messages. 22# 18 Jun 2001 - Peter Vanroose - added hyperlinks to warnings. 23# 24 25# global modules from CPAN 26use Date::Manip qw(ParseDate UnixDate); 27use IO::Socket; 28use Time::Local; 29 30# local module 31use FrostAPI; 32 33# see if we have compress 34# if so, we output to a tmpfile first, then compress it, MIME it and then output it 35# otherwise we just output it to STDOUT 36$tmpfilename1= "/tmp/buildlog_parser_${$}_1.tmp"; 37$tmpfilename2= "/tmp/buildlog_parser_${$}_2.tmp.gz"; 38 39if ( -f "/bin/compress" ) 40 { 41 $compress= "/bin/compress -c $tmpfilename1 > $tmpfilename2"; 42 } 43 44if ( -f "/usr/local/bin/gzip" ) 45 { 46 $compress= "/usr/local/bin/gzip -c $tmpfilename1 > $tmpfilename2"; 47 } 48 49if ( -f "/bin/gzip" ) 50 { 51 $compress= "/bin/gzip -c $tmpfilename1 > $tmpfilename2"; 52 } 53 54if ( -f "/freeware/bin/gnu-tools/gzip" ) 55 { 56 $compress= "/freeware/bin/gnu-tools/gzip -c -n -q -9 $tmpfilename1 > $tmpfilename2"; 57 } 58 59if ( -f "/tmp/iup_opt/bin/gzip" ) 60 { 61 $compress= "/tmp/iup_opt/bin/gzip -c $tmpfilename1 > $tmpfilename2"; 62 } 63 64# get current date and time 65$date= localtime; 66# patch for daylight saving time (DST) which is not correctly recognised: 67$date =~ s/( ?DST )/ /; 68if ($1) { 69 $date =~ m/\s(\d\d):/; $hr = $1 - 1; $date =~ s/\s\d\d:/ $hr:/; 70} 71 72############ 73# gmake 3.79 74 75# make[2]: Entering directory `/a/directory/a/directory' 76# make[6]: *** 77$gmake_enteringdirectory= q/^g?make\[\d+\]: Entering directory \`(.+?)\'\s*$/; 78$gmake_leavingdirectory = q/^g?make\[\d+\]: Leaving directory \`(.+?)\'\s*$/; 79$gmake_errorindirectory = q/^g?make(\[\d+\])?: \*\*\* \[(x?all|subdirs|.*recurse-subdirs\])/; 80$gmake_errorintest = q/^g?make(\[\d+\])?: \*\*\* \[.*\.out\]/; 81$gmake_errortestfail = q/Test Summary:.*\*\*\*/; 82$gmake_error_segfault = q/^g?make(\[\d+\])?: \[.*\.out\]\s+Error\s+139/; 83$gmake_error_assert = q/:\d+: failed assertion /; 84$gmake_error = q/^g?make(\[\d+\])?: \*\*\* \[/; 85 86############ 87# gcc-2.95 88 89# g++ ... -o something.o 90# gcc ... -o something.o 91# gcc ... -o something.so 92 93############ 94# FreeBSD 95 96# c++ ... -o something.o 97# gcc ... -o something.o 98# gcc ... -o something.so 99 100############### 101# status flags 102 103open(INFO,"-"); 104 105$starttime=""; 106$endtime=""; 107@current= {}; 108$index= 0; 109$nextindex= 0; 110$htmlerrorlink= 0; 111$htmlwarninglink= 0; 112 113### build stats 114%allbuilds = (); 115@buildname= []; 116@buildfilenumber = []; 117@buildwarnings = []; 118@builderrors = []; 119@buildparent= []; 120@buildchildrenwarnings = []; 121@buildchildrenerrors = []; 122@buildlogs= []; 123$fullbuildlog="<a href=\"\#ERRORLINK$htmlerrorlink\"><font size=-1 color=\"CC3333\">Jump to first error</font></a><br>\n"; 124$fullbuildlog.="<a href=\"\#WARNINGLINK$htmlwarninglink\"><font size=-1 color=\"773333\">Jump to first warning</font></a><br>\n"; 125#%buildtime = (); 126 127######################## 128# get the current machine name ... 129@uname = split(/\s/,<INFO>); 130$machine = $uname[1]; 131$machine =~ s/\..*//; 132 133#print "Machine: $machine\n"; 134#print "Date : $date\n"; 135 136############ 137# main loop 138 139while ( <INFO>) 140 { 141 # patch together multi-lines 142 $_ .= <INFO> while ( s/\\\s*$//); 143 s/$iueroot\/?/\//g if ( $iueroot); 144 145 $currentlineweb= webify_string($_); 146 147 if ( m/$gmake_enteringdirectory/) 148 { 149 $currentlineweb="<font color=\"555500\">$currentlineweb</font>"; 150 151 push( @current, $1); 152 153 if ( !exists( $allbuilds{$1})) 154 { 155 $nextindex=$nextindex+1; 156 $allbuilds{$1}= $nextindex; 157 $index= $nextindex; 158 $buildname[$index]= $1; 159 } 160 else 161 { 162 $index= $allbuilds{$1}; 163 } 164 } 165 elsif ( m/$gmake_leavingdirectory/) 166 { 167 $currentlineweb="<font color=\"555500\">$currentlineweb</font>"; 168 pop( @current); 169 $index= $allbuilds{$current[$#current]}; 170 } 171 elsif ( m/$compilingcpp/) 172 { 173 $buildfilenumber[$index]++; 174 $currentlineweb="<font color=blue>$currentlineweb</font>"; 175 } 176 elsif ( m/$compilingc/) 177 { 178 $buildfilenumber[$index]++; 179 $currentlineweb="<font color=blue>$currentlineweb</font>"; 180 } 181 elsif ( m/$linkingso/) 182 { 183# print "so file: $1\n"; 184 } 185 elsif ( m/$compilewarning/ || m/$linkwarning/) 186 { 187 $buildwarnings[$index]++; 188 $currentlineweb="<a name=\"WARNINGLINK$htmlwarninglink\">" .$currentlineweb; 189 $currentlineweb="<font color=\"AA0000\">$currentlineweb</font>"; 190 $htmlwarninglink++; 191 $t_1link="\ \;<a href=\"\#WARNINGLINK" . ($htmlwarninglink-2); 192 $t10link="\ \;<a href=\"\#WARNINGLINK" . ($htmlwarninglink+9); 193 $t_10link="\ \;<a href=\"\#WARNINGLINK" . ($htmlwarninglink-11); 194 $t100link="\ \;<a href=\"\#WARNINGLINK" . ($htmlwarninglink+99); 195 $t_100link="\ \;<a href=\"\#WARNINGLINK" . ($htmlwarninglink-101); 196 $fnt="<font size=-1 color=\"773333\">"; $efnt="</font></a>\n"; 197 $currentlineweb.="<a href=\"\#WARNINGLINK$htmlwarninglink\">$fnt Jump to next warning$efnt"; 198 $currentlineweb.="$t_1link\">$fnt -1$efnt" if ($htmlwarninglink > 1); 199 $currentlineweb.="$t10link\">+$fnt 10$efnt"; 200 $currentlineweb.="$t_10link\">-$fnt 10$efnt" if ($htmlwarninglink > 10); 201 $currentlineweb.="$t100link\">+$fnt 100$efnt"; 202 $currentlineweb.="$t_100link\">-$fnt 100$efnt" if ($htmlwarninglink > 100); 203 $currentlineweb.="<br>\n"; 204 } 205 elsif ( m/$gmake_errorintest/ || m/$gmake_errortestfail/) 206 { 207 $builderrors[$index]++; 208 $currentlineweb="<a name=\"ERRORLINK$htmlerrorlink\">" .$currentlineweb; 209 $currentlineweb.="<font color=red>$currentlineweb</font>"; 210 $htmlerrorlink++; 211 $currentlineweb.="<a href=\"\#ERRORLINK$htmlerrorlink\"><font size=-1 color=\"CC3333\">Jump to next error</font></a><br>\n"; 212 } 213 elsif ( m/$gmake_errorindirectory/) 214 { 215 $buildwarnings[$index]++; 216 $currentlineweb="<font color=\"AA0000\">$currentlineweb</font>"; 217 } 218 elsif ( m/$gmake_error_segfault/ || m/$gmake_error_assert/ || m/$gmake_error/) 219 { 220 $builderrors[$index]++; 221 $currentlineweb="<a name=\"ERRORLINK$htmlerrorlink\">" .$currentlineweb; 222 $currentlineweb.="<font color=red>$currentlineweb</font>"; 223 $htmlerrorlink++; 224 $currentlineweb.="<a href=\"\#ERRORLINK$htmlerrorlink\"><font size=-1 color=\"CC3333\">Jump to next error</font></a><br>\n"; 225 } 226 elsif ( m/$testsummary/) 227 { 228 $currentlineweb="<font color=\"00AA00\">$currentlineweb</font>"; 229 } 230 elsif ( m/Beginning TargetJr make:\s*(.*)$/) 231 { 232 $f = $1; $f =~ s/( ?DST )/ /; 233 if ($1) { 234 $f =~ m/\s(\d\d):/; $hr = $1 - 1; $f =~ s/\s\d\d:/ $hr:/; 235 $currentlineweb =~ s/ ?DST / /; 236 } 237 @thisdate= ParseDate( $f); 238 $starttime= UnixDate( @thisdate, "%a %b %e %H:%M:%S %z %Y") unless ($starttime); 239 } 240 elsif ( m/Done TargetJr make:\s*(.*)$/) 241 { 242 $f = $1; $f =~ s/( ?DST )/ /; 243 if ($1) { 244 $f =~ m/\s(\d\d):/; $hr = $1 - 1; $f =~ s/\s\d\d:/ $hr:/; 245 $currentlineweb =~ s/ ?DST / /; 246 } 247 @thisdate= ParseDate( $f); 248 $endtime= UnixDate( @thisdate, "%a %b %e %H:%M:%S %z %Y"); 249 } 250 251 if ( $index) 252 { 253 $buildlogs[$index].= $currentlineweb; 254 } 255 256 $fullbuildlog.= $currentlineweb; 257 } 258 259$t_1link="\ \;<a href=\"\#WARNINGLINK" . ($htmlwarninglink-1); 260$t_10link="\ \;<a href=\"\#WARNINGLINK" . ($htmlwarninglink-10); 261$t_100link="\ \;<a href=\"\#WARNINGLINK" . ($htmlwarninglink-100); 262$fnt="<font size=-1 color=\"773333\">"; $efnt="</font></a>\n"; 263$fullbuildlog.="<a name=\"ERRORLINK$htmlerrorlink\"><a href=\"\#ERRORLINK0\">" 264 . "<font size=-1 color=\"CC3333\">No more errors.</font></a><br>\n" 265 . "<a name=\"WARNINGLINK$htmlwarninglink\"><a href=\"\#WARNINGLINK0\">" 266 . "$fnt Jump to first warning$efnt"; 267$fullbuildlog.="$t_1link\">$fnt -1$efnt" if ($htmlwarninglink > 0); 268$fullbuildlog.="$t_10link\">-$fnt 10$efnt" if ($htmlwarninglink > 9); 269$fullbuildlog.="$t_100link\">-$fnt 100$efnt" if ($htmlwarninglink > 99); 270$fullbuildlog.="<br>\n"; 271 272############################################## 273# find the common sub-directory for each build 274 275$subdir=-1; 276 277for $build ( keys %allbuilds ) 278 { 279 if ( $subdir== -1) 280 { 281 $subdir= $build; 282 } 283 else 284 { 285 ($subdir)=(($subdir."_FOO_".$build) =~ /^(.*).*_FOO_\1.*$/); 286 } 287 } 288 289############################################################################# 290# and remove the sub-directory (and leading and following /s) from each build 291 292%allbuildsnew= (); 293 294for $build ( keys %allbuilds ) 295 { 296 $buildold= $build; 297 $build=~ s/^$subdir\/*//; 298 $build=~ s/\/$//; 299 300 $allbuildsnew{$build}= $allbuilds{$buildold}; 301 $buildname[$allbuilds{$buildold}]= $build; 302 } 303 304%allbuilds= %allbuildsnew; 305 306####################### 307# compute the hierarchy 308 309for $buildit1 ( keys %allbuilds ) 310 { 311 # remove the last subdirectory from this build 312 $index = $allbuilds{$buildit1}; 313 $buildit1=~ s/\/*[^\/]+$//; 314 315 for $buildit2 ( keys %allbuilds ) 316 { 317 if ( $buildit1 eq $buildit2) 318 { 319 $buildparent[$index]= $allbuilds{$buildit2}; 320 } 321 } 322 } 323 324######################################## 325# propogate errors from children upwards 326$toterrors= 0; 327$totwarnings= 0; 328$totfiles= 0; 329$totstarttime= $starttime; 330 331for $build ( keys %allbuilds ) 332 { 333 if (( $build!~ /\//) & ( $build!~ /^\s*$/)) 334 { 335 $errors= 0; 336 $warnings= 0; 337 338 for $buildit ( keys %allbuilds ) 339 { 340 if ( $buildit =~ /^$build/) 341 { 342 $errors+= $builderrors[$allbuilds{$buildit}]; 343 $warnings+= $buildwarnings[$allbuilds{$buildit}]; 344 $files+= $buildfilenumber[$allbuilds{$buildit}]; 345 } 346 } 347 348 $builderrors[$allbuilds{$build}]= $errors; 349 $buildwarnings[$allbuilds{$build}]= $warnings; 350 $toterrors+= $errors; 351 $totwarnings+= $warnings; 352 $totfiles+= $files; 353 } 354 } 355 356($ds, $Ms, $ys, $hs,$ms,$ss)= UnixDate( ParseDate( $starttime), "%d", "%m", "%y", "%H", "%M", "%S"); 357($de, $Me, $ye, $he,$me,$se)= UnixDate( ParseDate( $endtime) , "%d", "%m", "%y", "%H", "%M", "%S"); 358 359#print STDERR "Start time = $starttime\n"; 360#print STDERR "End time = $endtime\n"; 361 362$Ms --; $Me --; 363$as= timelocal( $ss, $ms, $hs, $ds, $Ms, $ys); 364$ae= timelocal( $se, $me, $he, $de, $Me, $ye); 365 366$tottime= int(($ae-$as)/60); 367 368################## 369### OUTPUT THE XML 370 371#StartFrost( "icehouse", "vxl", "vxluser", ""); 372 373 374if ( $compress ne "") 375 { 376 FrostAPI::StartFrost( "FILE", $tmpfilename1); 377 } 378 379 380FrostAPI::SetMachine( $machine); 381 382FrostAPI::StartRunTestGroup( "root", $date); 383FrostAPI::StartRunTest( "BuildStats", $date); 384FrostAPI::RunMeasurement( "Errors", $toterrors); 385FrostAPI::RunMeasurement( "Warnings", $totwarnings); 386FrostAPI::RunMeasurement( "FileCount", $totfiles); 387FrostAPI::RunMeasurement( "TimeStarted", $totstarttime); 388FrostAPI::RunMeasurement( "TimeElapsed", $tottime); 389FrostAPI::RunMeasurementBase64( "BuildLog", $fullbuildlog); 390 391if ( $toterrors>0) 392 { 393 FrostAPI::EndRunTest( "f"); 394 } 395else 396 { 397 FrostAPI::EndRunTest( "t"); 398 } 399 400 401FrostAPI::EndRunTestGroup(); 402 403 404$headindex= $allbuilds{""}; 405@roots= get_children( $headindex); 406 407for ( $i=0; $i<= $#roots; $i++) 408 { 409 XMLruntestgroup( $roots[$i]); 410 } 411 412if ( $compress ne "") 413 { 414 FrostAPI::EndFrost(); 415 416 system( $compress); 417 418 open( CP, $tmpfilename2); 419 420 $buffer= ""; 421 422 while ( read( CP, $c, 1)) 423 { 424 $buffer.= $c; 425 } 426 427 print MIME::Base64::encode( $buffer); 428 429 unlink( $tmpfilename1); 430 unlink( $tmpfilename2); 431 } 432 433#print webify_string("hello\nthis is \"a\" test")."\n"; 434 435################### 436#################### 437##################### 438###################### 439######## sub-routines 440###################### 441##################### 442#################### 443################### 444 445sub webify_string 446 { 447 my ($string)= @_; 448 my $i; 449 my $n= ""; 450 my $c; 451 452 for ( $i= 0; $i<= length($string); $i++) 453 { 454 $c= substr($string,$i,1); 455 456 if ( $c eq "\r") 457 { 458 $c= ""; 459 } 460 elsif ( $c eq "\n") 461 { 462 $c= "<br>\n"; 463 } 464# elsif ( $c eq "\"") 465# { 466# $c= """; 467# } 468 elsif ( $c eq "&") 469 { 470 $c= "&"; 471 } 472 elsif ( $c eq "<") 473 { 474 $c= "<"; 475 } 476 elsif ( $c eq ">") 477 { 478 $c= ">"; 479 } 480 481 $n.= $c; 482 } 483 484 return $n; 485 } 486 487 488sub get_depth 489 { 490 my ($index)= @_; 491 my $i= 0; 492 493 494 while ( $buildparent[$index]!= $index) 495 { 496 $i++; 497 $index= $buildparent[$index]; 498 } 499 500 return $i; 501 } 502 503sub get_children 504 { 505 ############################ 506 # return an indexes children 507 my ($index)= @_; 508 my $i; 509 my @children; 510 511 @pr= @buildparent; 512 513 for ( $i= 0; $i<= $#pr; $i++) 514 { 515 if (( $pr[$i]== $index) & 516 ( $i!= $index)) 517 { 518 push( @children, $i); 519 } 520 } 521 522 return @children; 523 } 524 525 526sub display 527 { 528 ###################### 529 # display some results 530 my $i; 531 my $j; 532 533 for $i ( keys %allbuilds ) 534 { 535 print "name = $i ".$allbuilds{$i}." Parent = " 536 .$buildparent[$allbuilds{$i}]." Warnings = " 537 .($buildwarnings[$allbuilds{$i}])." Errors = " 538 .($builderrors[$allbuilds{$i}])." Files = " 539 .($buildfilenumber[$allbuilds{$i}])." "; 540 541 @children= get_children( $allbuilds{$i}); 542 print "Children = "; 543 for ( $j= 0; $j<= $#children; $j++) 544 { 545 print $children[$j]." "; 546 } 547 print "\n"; 548 } 549 } 550 551 552######################################## 553# output the gauges and XML header stuff 554 555sub XMLruntestgroup 556 { 557 my ($index)= @_; 558 my $name= $buildname[$index]; 559 my @children; 560 my $i; 561 562 FrostAPI::StartRunTestGroup( $name, $date); 563 564 { 565 if ( $name=~ /\//) 566 { 567 FrostAPI::StartRunTest( "BuildDirectory", $date); 568 } 569 else 570 { 571 FrostAPI::StartRunTest( "BuildLibrary", $date); 572 } 573 574 # errors 575 FrostAPI::RunMeasurement( "Errors",($builderrors[$index]+0)); 576 577 # warnings 578 FrostAPI::RunMeasurement( "Warnings", ($buildwarnings[$index]+0)); 579 580 # build log 581# if ( $buildlogs[$index] ne "") 582# { 583# FrostAPI::RunMeasurementBase64( "BuildLog", $buildlogs[$index]); 584# } 585 586 # file count 587# RunMeasurement( "BuildFileNumber", ($buildfilenumber[$index]+0)); 588 589 # start time 590# RunMeasurement( "BuildStartTime", $starttime); 591 592 if ( $builderrors[$index]== 0) 593 { 594 FrostAPI::EndRunTest("t"); 595 } 596 else 597 { 598 FrostAPI::EndRunTest("f"); 599 } 600 } 601 602 @children= get_children( $index); 603 604 for ( $i=0; $i<=$#children; $i++) 605 { 606 XMLruntestgroup( $children[$i]); 607 } 608 609 FrostAPI::EndRunTestGroup( $date); 610 } 611