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="\&nbsp\;<a href=\"\#WARNINGLINK" . ($htmlwarninglink-2);
192        $t10link="\&nbsp\;<a href=\"\#WARNINGLINK" . ($htmlwarninglink+9);
193        $t_10link="\&nbsp\;<a href=\"\#WARNINGLINK" . ($htmlwarninglink-11);
194        $t100link="\&nbsp\;<a href=\"\#WARNINGLINK" . ($htmlwarninglink+99);
195        $t_100link="\&nbsp\;<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="\&nbsp\;<a href=\"\#WARNINGLINK" . ($htmlwarninglink-1);
260$t_10link="\&nbsp\;<a href=\"\#WARNINGLINK" . ($htmlwarninglink-10);
261$t_100link="\&nbsp\;<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= "&quot;";
467#          }
468        elsif ( $c eq  "&")
469          {
470            $c= "&amp;";
471          }
472        elsif ( $c eq  "<")
473          {
474            $c= "&lt;";
475          }
476        elsif ( $c eq  ">")
477          {
478            $c= "&gt;";
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