deprecated/buildtools/buildsystemtools/scanlog/htmlscanlog.pl
changeset 655 3f65fd25dfd4
equal deleted inserted replaced
649:02d78c9f018e 655:3f65fd25dfd4
       
     1 # Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 # All rights reserved.
       
     3 # This component and the accompanying materials are made available
       
     4 # under the terms of "Eclipse Public License v1.0"
       
     5 # which accompanies this distribution, and is available
       
     6 # at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 #
       
     8 # Initial Contributors:
       
     9 # Nokia Corporation - initial contribution.
       
    10 #
       
    11 # Contributors:
       
    12 #
       
    13 # Description:
       
    14 #
       
    15 
       
    16 # summarise an automated build log
       
    17 use strict;
       
    18 use Getopt::Long;
       
    19 use HTML::Entities;
       
    20 use Carp;
       
    21 use FindBin;		# for FindBin::Bin
       
    22 
       
    23 # Add the directory contain this perl script into the path to find modules
       
    24 use lib $FindBin::Bin;
       
    25 use Scanlog;
       
    26 
       
    27 # For Date calculations
       
    28 use lib "$FindBin::Bin/../lib"; # For running in source
       
    29 use lib "$FindBin::Bin/build/lib"; # For running in epoc32\tools
       
    30 use Date::Manip;
       
    31 
       
    32 # Set TimeZone because Date:Manip needs it set and then tell it to IGNORE the TimeZone
       
    33 &Date_Init("TZ=GMT","ConvTZ=IGNORE");
       
    34 
       
    35 # Variables
       
    36 my $line;
       
    37 my $iSlurp;
       
    38 my $PhaseStartTime;
       
    39 my %Phases;
       
    40 my %Components;
       
    41 my %Commands;
       
    42 my $component;
       
    43 my $command;
       
    44 my $phase;
       
    45 my $match_phase='';
       
    46 my %errors;
       
    47 my %warnings;
       
    48 my %remarks;
       
    49 my %migrationNotes;
       
    50 my %AdvisoryNotes;
       
    51 my %CmdErrors;
       
    52 my %CmdWarnings;
       
    53 my %CmdRemarks;
       
    54 my %CmdMigrationNotes;
       
    55 my %CmdAdvisoryNotes;
       
    56 my %missing;
       
    57 my %not_built;
       
    58 my $starttime;
       
    59 my $duration;
       
    60 my $warningcount;
       
    61 my $errorcount;
       
    62 my $remarkcount;
       
    63 my $migrationNoteCount;
       
    64 my $AdvisoryNoteCount;
       
    65 my ($iStatus, $iName);
       
    66 my %htmlColours=(
       
    67 "errors" =>"#ff0000",
       
    68 "warnings" =>"#fff000",
       
    69 "remarks" =>"#ffccff",
       
    70 "migrationNotes" =>"#ffcc99",
       
    71 "AdvisoryNotes" => "#ffa500"
       
    72 );
       
    73 # Hires Timer Variables
       
    74 my %HiResComponents;
       
    75 my %HiResCommands;
       
    76 my $HiResStartTime;
       
    77 my $HiResErrorFlag; #True if one of the Clients has not reported HiRes timing info
       
    78 
       
    79 my $Dsec;
       
    80 
       
    81 # History Variables
       
    82 my ($hostname) = "N/A";
       
    83 my ($EndTime);
       
    84 
       
    85 # Main section
       
    86 
       
    87 my ($iOutput, $iTitle, $iVerbose, $iDiff, $iWhat, $iHistory, $iClass, @iLogs) =&ProcessCommandLine();
       
    88 
       
    89 # Open Output file
       
    90   open (HTML, ">$iOutput") or die "Couldn't open $iOutput for writing: $!\n";
       
    91 
       
    92 # Open Diff file if specified
       
    93 if ($iDiff ne '')
       
    94 {
       
    95   open (DIFF, ">$iDiff") or die "Couldn't open $iDiff for writing: $!\n";
       
    96 }
       
    97 
       
    98 # Print HTML Header
       
    99 &PrintHTMLHeader($iTitle);
       
   100 
       
   101 
       
   102 # Parse each log File
       
   103 foreach my $iLog (@iLogs) # parses through all logs 
       
   104 {
       
   105   # Open the Log file for reading
       
   106   unless (open (LOG, "< $iLog"))
       
   107     {   # On error, warn rather than die. Then record a "pseudo-error", which will appear in summary output file.
       
   108         $line = "Couldn't open $iLog for reading: $!";
       
   109         warn "$line\n";
       
   110         $command = 'HTMLScanLog';
       
   111         $component = 'Log Summaries';
       
   112         $Commands{$command} = 0;            # Need to define these! So assume zero seconds 
       
   113         $HiResCommands{$command} = 0;       # duration for each of four variables.
       
   114         $Components{$component} = 0;        # The fact the relevant time(s) are defined
       
   115         $HiResComponents{$component} = 0;   # triggers inclusion in the applicable table. 
       
   116         do_error($iLog);
       
   117         next;
       
   118     }
       
   119   # Chop $iLog just to the filename
       
   120   $iLog =~ s/^.*\\//;
       
   121 
       
   122   # Process the logs
       
   123   &ProcessLog($iLog);
       
   124   close LOG;
       
   125 }
       
   126 
       
   127 &PrintResults($iTitle);
       
   128 
       
   129 # Print HTML Footer
       
   130 &PrintHTMLFooter();
       
   131 
       
   132 # Handle the History file
       
   133 if (defined $iHistory)
       
   134 {
       
   135   # Work out the class
       
   136   my ($mclass) = "N/A";
       
   137   open (MC, "< $iClass");
       
   138   while (<MC>)
       
   139   {
       
   140     chomp;
       
   141     my (@columns) = split(/,/);
       
   142     $mclass = $columns[0] if ($columns[1] eq $hostname);
       
   143   }
       
   144   close (MC);
       
   145   
       
   146   # Open and Lock the csv file
       
   147   open(FH, "+< $iHistory")                or die "can't open $iHistory: $!";
       
   148   flock(FH, 2)                        or die "can't flock iHistory: $!";
       
   149   # Read the file
       
   150   # Reader the headers
       
   151   my $cline = <FH>;
       
   152   chomp($cline);
       
   153   my (@headers) = split(/,/,$cline);
       
   154   # Read the data
       
   155   my (@csvdata);
       
   156   @csvdata = <FH>;
       
   157   # Return to the begining
       
   158   seek(FH,0,0)                        or die "Seeking: $!";
       
   159   # Print the old and new data
       
   160   # Work if new headers are needed
       
   161   # Use LowRes component names because they are always available
       
   162   foreach my $component (sort {lc $a cmp lc $b} keys %Components)
       
   163 	{
       
   164     my $compexist = 0;
       
   165     # Itterate through the header array to see if it already exists
       
   166     foreach my $header (@headers)
       
   167     {
       
   168       if ($component eq $header)
       
   169       {
       
   170         $compexist = 1;
       
   171       }
       
   172     }
       
   173     # This component not found in the headers
       
   174     # put the new header at the end of the header array
       
   175     push @headers, $component if ($compexist == 0);
       
   176   }
       
   177   # Print the headers back out
       
   178   print FH join(',',@headers)."\n";
       
   179   # Print the original data
       
   180   print FH @csvdata;
       
   181   # Print the new data
       
   182   foreach my $header (@headers)
       
   183   {
       
   184     if ($header eq 'Machine Class')
       
   185     {
       
   186       print FH "$mclass";
       
   187     } elsif ($header eq 'Machine Name') {
       
   188       print FH "$hostname";
       
   189     } elsif ($header eq 'Title') {
       
   190       print FH "$iTitle";
       
   191     } elsif ($header eq 'End Time') {
       
   192       print FH "$EndTime";
       
   193     } elsif ($header eq 'Total Time') {
       
   194       print FH &ConvertSeconds($duration);
       
   195     } else {
       
   196       # If there is a complete set of HiRes data then use that instead of the LowRes data
       
   197       if ((defined %HiResComponents) && !$HiResErrorFlag)
       
   198       {
       
   199         if (exists $HiResComponents{$header})
       
   200         {
       
   201           print FH &ConvertSeconds($HiResComponents{$header});
       
   202         } else {
       
   203           print FH "";
       
   204         }
       
   205       } else {
       
   206         if (exists $Components{$header})
       
   207         {
       
   208           print FH &ConvertSeconds($Components{$header});
       
   209         } else {
       
   210           print FH "";
       
   211         }
       
   212       }
       
   213     }
       
   214     # Print the , for next entry
       
   215     print FH ",";
       
   216   }
       
   217   # End the entry
       
   218   print FH "\n";
       
   219 
       
   220   # truncate just in case the file is shorter
       
   221   truncate(FH,tell(FH))               or die "Truncating: $!";
       
   222   close(FH)                           or die "Closing: $!";
       
   223 }
       
   224 
       
   225 # DiffLog
       
   226 #
       
   227 # Inputs
       
   228 #
       
   229 # Outputs
       
   230 #
       
   231 # Description
       
   232 # This function Outputs lines to the diff log
       
   233 sub DiffLog()
       
   234 {
       
   235     # Write the line to diff file if specified and not a line with Build Time dependent infomation
       
   236     if ($iDiff ne '')
       
   237     {
       
   238        # Check the line for Build Time dependent infomation
       
   239        unless (($line =~ /^=== .+ started/) || ($line =~ /^=== .+ finished/) || ($line =~ /^---/) || ($line =~ /^\+\+/))
       
   240        {
       
   241           print DIFF $line;
       
   242        }
       
   243     }
       
   244 }
       
   245 
       
   246 
       
   247 # ProcessLog
       
   248 #
       
   249 # Inputs
       
   250 # $iLog - Logfile name
       
   251 #
       
   252 # Outputs
       
   253 #
       
   254 # Description
       
   255 # This function processes the commandline
       
   256 sub ProcessLog()
       
   257 {
       
   258   my ($iLog) = @_;
       
   259   print "Processing: $iLog\n";
       
   260 
       
   261   while ($line=<LOG>)
       
   262     {
       
   263     &DiffLog;
       
   264 
       
   265     # Hostname is
       
   266     # capture the hostname if available
       
   267     if ($line =~ /^Hostname is (.*)$/)
       
   268     {
       
   269       $hostname = $1;
       
   270     }
       
   271 
       
   272     # ===-------------------------------------------------
       
   273     # === Stage=1
       
   274     # ===-------------------------------------------------
       
   275     # === Stage=1 started Wed Apr 30 23:09:38 2003
       
   276 
       
   277     if ($line =~ /^===------/)
       
   278     {
       
   279       $line=<LOG>;
       
   280           &DiffLog;
       
   281       $line=<LOG>;
       
   282           &DiffLog;
       
   283       $line = <LOG>;
       
   284           &DiffLog;
       
   285       $line =~ /^=== (.+) started (.*)/;
       
   286       $phase = $1;
       
   287       $PhaseStartTime =$2;
       
   288       $match_phase=$phase;
       
   289       $match_phase=~s-\\-\\\\-go;
       
   290       next;
       
   291     }
       
   292 
       
   293     # === bldfiles finished Sat Jul 24 01:38:56 1999.
       
   294     if ($line =~ /^=== $match_phase finished (.*)/)
       
   295     {
       
   296       my ($TempTime) = $1;
       
   297       # Calculate the difference in Date/Time and Total up for Phase
       
   298       $Phases{$phase} += &DiffDateTime($PhaseStartTime, $TempTime) ;
       
   299       # The check to see if phase end is later than current EndTime
       
   300       my $err;
       
   301       # The first time a phase end is seen set $EndTime
       
   302       if (!defined $EndTime)
       
   303       {
       
   304         $EndTime = $TempTime;
       
   305       } else {
       
   306         # Check the delta to previous EndTime value is positive
       
   307         # Need due to multiple log file processing might not be in time order
       
   308         my ($delta) = &DateCalc($EndTime,$TempTime,\$err);
       
   309         die "Date Manip error" if ($err);
       
   310         # If the delta starts with a + symbol $TempTime is later or the same as the last EndTime so set the new EndTime.
       
   311         if ($delta =~ /^\+/)
       
   312         {
       
   313           $EndTime = $TempTime;
       
   314         }
       
   315       }
       
   316       next;
       
   317     }
       
   318 
       
   319 
       
   320     # === resource == gdtran 036
       
   321 
       
   322     if ($line =~ /=== $match_phase == (.*)$/)
       
   323     {
       
   324       $component = $1;
       
   325       next;
       
   326     }
       
   327 
       
   328     # Find Command
       
   329     # -- bldmake bldfiles -keepgoing
       
   330     if ($line =~ /^-- (.*)/)
       
   331     {
       
   332       $command = $1;
       
   333       next;
       
   334     }
       
   335 
       
   336     # Find the Command's Start time
       
   337     # ++ Started at Sat May 03 21:09:07 2003
       
   338     if ($line =~ /^\+\+ Started at (.*)/)
       
   339     {
       
   340       $starttime = $1;
       
   341       next;
       
   342     }
       
   343 
       
   344     # Find the Command's End time
       
   345     # ++ Started at Sat May 03 21:09:07 2003
       
   346     if ($line =~ /^\+\+ Finished at (.*)/)
       
   347     {
       
   348       # Calculate the difference in Date/Time and Total up for Command
       
   349       $Dsec = &DiffDateTime($starttime, $1);
       
   350       $Commands{$command} += $Dsec;
       
   351       # Calculate the difference in Date/Time and Total up for Component
       
   352       $Components{$component} += $Dsec;
       
   353       next;
       
   354     }
       
   355 
       
   356     # Act on a HiRes Timer unavailable statement in the log
       
   357     # +++ HiRes Time Unavailable
       
   358     if (($line =~ /^\+\+\+ HiRes Time Unavailable/) && !$HiResErrorFlag)
       
   359     {
       
   360       $HiResErrorFlag = 1;
       
   361           print "Warning one of the clients is not sending HiRes timer Data\n";
       
   362           print "No HiRes timings will be available\n";
       
   363           print "Reverting to LowRes timing Data\n";
       
   364       # Clear out Current HiRes Data
       
   365       undef %HiResCommands;
       
   366       undef %HiResComponents;
       
   367       next;
       
   368     }
       
   369 
       
   370 
       
   371     # Find the Command's HiRes Start time
       
   372     # +++ HiRes Start 1051993130.602050
       
   373     if (($line =~ /^\+\+\+ HiRes Start (\S+)/) && !$HiResErrorFlag)
       
   374     {
       
   375       $HiResStartTime = $1;
       
   376       next;
       
   377     }
       
   378 
       
   379     # Find the Command's HiRes End time
       
   380     # +++ HiRes End 1051993193.829650
       
   381     if (($line =~ /^\+\+\+ HiRes End (\S+)/) && !$HiResErrorFlag)
       
   382     {
       
   383       # Calculate the difference in Date/Time and Total up for Command
       
   384       $HiResCommands{$command} += ($1 - $HiResStartTime);
       
   385       # Calculate the difference in Date/Time and Total up for Component
       
   386       $HiResComponents{$component} += ($1 - $HiResStartTime);
       
   387       next;
       
   388     }
       
   389     
       
   390     # Lines to Ignore
       
   391     ($iStatus) =&Scanlog::CheckForIgnore($line);
       
   392     if($iStatus)
       
   393     {
       
   394       next;
       
   395     }
       
   396 
       
   397     # Advisory Notes
       
   398     ($iStatus) =&Scanlog::CheckForAdvisoryNotes($line);
       
   399     if ($iStatus)
       
   400     {
       
   401        do_AdvisoryNotes($iLog);
       
   402        do_slurp($iSlurp);
       
   403       next;
       
   404     }
       
   405 
       
   406     # Migration Notes
       
   407     ($iStatus) = &Scanlog::CheckForMigrationNotes($line);
       
   408     if ($iStatus)
       
   409       {
       
   410       do_migrationNotes($iLog);
       
   411       next;
       
   412       }
       
   413 
       
   414     # Remarks
       
   415     ($iStatus, $iSlurp) =&Scanlog::CheckForRemarks($line);
       
   416     if ($iStatus)
       
   417     {
       
   418       do_remarks($iLog);
       
   419       do_slurp($iSlurp);
       
   420       next;
       
   421     }
       
   422 
       
   423     # Errors
       
   424     ($iStatus) =&Scanlog::CheckForErrors($line);
       
   425     if ($iStatus)
       
   426     {
       
   427       do_error($iLog);
       
   428       next;
       
   429     }
       
   430 
       
   431     
       
   432     # Warnings
       
   433     ($iStatus) =&Scanlog::CheckForWarnings($line);
       
   434     if ($iStatus)
       
   435     {
       
   436       do_warning($iLog);
       
   437       next;
       
   438     }
       
   439     
       
   440 
       
   441     # Things Not Built
       
   442     ($iStatus, $iName) =&Scanlog::CheckForNotBuilt($line);
       
   443     if ($iStatus)
       
   444     {
       
   445       do_error($iLog); # record these along with the errors
       
   446       $not_built{$iName} = "$component";
       
   447       next;
       
   448     }
       
   449 
       
   450     # Things missing
       
   451     ($iStatus, $iName) =&Scanlog::CheckForMissing($line);
       
   452     if ($iStatus)
       
   453     {
       
   454       do_error($iLog);
       
   455       $missing{$iName} += 1;
       
   456       next;
       
   457     }
       
   458 
       
   459 	}
       
   460 }
       
   461 
       
   462 
       
   463 # PrintResults
       
   464 #
       
   465 # Inputs
       
   466 # $iTitle (Title for Log file)
       
   467 #
       
   468 # Outputs
       
   469 #
       
   470 # Description
       
   471 # This function prints all the data as HTML
       
   472 sub PrintResults
       
   473 {
       
   474   my ($iTitle) = @_;
       
   475   
       
   476   my $title;
       
   477 
       
   478   # Print Heading of Log File
       
   479   my $heading ="Overall";
       
   480   print HTML qq{<h1>$iTitle</h1>\n};
       
   481   print HTML qq{<h2>$heading</h2>\n};
       
   482 
       
   483   # Calculate the total number of remarks messages
       
   484 	$remarkcount = 0;
       
   485 	foreach $component (sort {lc $a cmp lc $b} keys %remarks)
       
   486 		{
       
   487 		$remarkcount += scalar(@{$remarks{$component}});
       
   488 		}
       
   489   # Calculate the Total number of errors
       
   490   	$errorcount = 0;
       
   491 	foreach $component (sort {lc $a cmp lc $b} keys %errors)
       
   492 		{
       
   493 		$errorcount += scalar(@{$errors{$component}});
       
   494 		}
       
   495   # Calculate the total number of warnings
       
   496 	$warningcount = 0;
       
   497 	foreach $component (sort {lc $a cmp lc $b} keys %warnings)
       
   498 		{
       
   499 		$warningcount += scalar(@{$warnings{$component}});
       
   500 		}
       
   501   
       
   502   # Calculate the total number of migration notes
       
   503         $migrationNoteCount=0;
       
   504         foreach $component (sort {lc $a cmp lc $b} keys %migrationNotes)
       
   505                 {
       
   506                 $migrationNoteCount += scalar(@{$migrationNotes{$component}});
       
   507                 }
       
   508 
       
   509   # Calculate the total number of Advisory notes
       
   510         $AdvisoryNoteCount=0;
       
   511         foreach $component (sort {lc $a cmp lc $b} keys %AdvisoryNotes)
       
   512                 {
       
   513                 $AdvisoryNoteCount += scalar(@{$AdvisoryNotes{$component}});
       
   514                 }
       
   515 
       
   516   # Calculate the Total Duration from Phase Data
       
   517 	$duration = 0;
       
   518 	foreach $phase (sort {lc $a cmp lc $b} keys %Phases)
       
   519 		{
       
   520 		  $duration += $Phases{$phase};
       
   521 		}
       
   522   # Start the Table
       
   523   &StartHTMLTable();
       
   524 
       
   525   # Print the Totals
       
   526   &HTMLTableRow($heading,"Total", $duration, $errorcount, $warningcount, $AdvisoryNoteCount, $remarkcount, $migrationNoteCount);
       
   527 
       
   528   # End the Table
       
   529   print HTML qq{</table>\n};
       
   530 
       
   531 
       
   532 
       
   533   # By Component
       
   534   print HTML qq{<h2>By Component</h2>\n};
       
   535 
       
   536   # Start the Table
       
   537   $title="Component";
       
   538   &StartHTMLTable($title);
       
   539 
       
   540   # Print the by Component Data
       
   541   # If there is a complete set of HiRes data then use that instead of the LowRes data
       
   542   if ((defined %HiResComponents) && !$HiResErrorFlag)
       
   543   {
       
   544     foreach $component (sort {lc $a cmp lc $b} keys %HiResComponents)
       
   545 	{
       
   546       # Calculate the number errors,warnings,advisory notes and remarks
       
   547       my $totalerrors;
       
   548       my $totalwarnings;
       
   549       my $totalremarks;
       
   550       my $totalMigrationNotes;
       
   551       my $totalAdvisoryNotes;
       
   552       if (!defined $remarks{$component})
       
   553       {
       
   554         # No Remarks were recorded, set total to zero
       
   555         $totalremarks = 0;
       
   556       } else {
       
   557         $totalremarks = scalar(@{$remarks{$component}});
       
   558       }
       
   559       if (!defined $errors{$component})
       
   560       {
       
   561         # No errors were recorded, set total to zero
       
   562         $totalerrors = 0;
       
   563       } else {
       
   564         $totalerrors = scalar(@{$errors{$component}});
       
   565       }
       
   566       if (!defined $warnings{$component})
       
   567       {
       
   568         # No Warnings were recorded, set total to zero
       
   569         $totalwarnings = 0;
       
   570       } else {
       
   571         $totalwarnings = scalar(@{$warnings{$component}});
       
   572       }
       
   573       
       
   574       if (!defined $migrationNotes{$component})
       
   575         {
       
   576         # No MigrationNotes were recorded, set total to zero
       
   577         $totalMigrationNotes=0;
       
   578         }
       
   579       else
       
   580         {
       
   581         $totalMigrationNotes = scalar(@{$migrationNotes{$component}});
       
   582         }
       
   583       if (!defined $AdvisoryNotes{$component})
       
   584         {
       
   585         # No AdvisoryNotes were recorded, set total to zero
       
   586         $totalAdvisoryNotes=0;
       
   587         }
       
   588       else
       
   589         {
       
   590         $totalAdvisoryNotes = scalar(@{$AdvisoryNotes{$component}});
       
   591         }
       
   592 
       
   593 
       
   594       # Print the Table Row      
       
   595       &HTMLTableRow($title,$component, $HiResComponents{$component}, $totalerrors, $totalwarnings, $totalAdvisoryNotes, $totalremarks, $totalMigrationNotes);
       
   596 
       
   597 	}
       
   598   } else {
       
   599     foreach $component (sort {lc $a cmp lc $b} keys %Components)
       
   600 	{
       
   601       # Calculate the number errors,warnings,advisory notes and remarks
       
   602       my $totalerrors;
       
   603       my $totalwarnings;
       
   604       my $totalremarks;
       
   605       my $totalMigrationNotes;
       
   606       my $totalAdvisoryNotes;
       
   607       if (!defined $remarks{$component})
       
   608       {
       
   609         # No Remarks was recorded, set total to zero
       
   610         $totalremarks = 0;
       
   611       } else {
       
   612         $totalremarks = scalar(@{$remarks{$component}});
       
   613       }
       
   614       if (!defined $errors{$component})
       
   615       {
       
   616         # No errors were recorded, set total to zero
       
   617         $totalerrors = 0;
       
   618       } else {
       
   619         $totalerrors = scalar(@{$errors{$component}});
       
   620       }
       
   621       if (!defined $warnings{$component})
       
   622       {
       
   623         # No Warnings were recorded, set total to zero
       
   624         $totalwarnings = 0;
       
   625       } else {
       
   626         $totalwarnings = scalar(@{$warnings{$component}});
       
   627       }
       
   628       
       
   629       if (!defined $migrationNotes{$component})
       
   630         {
       
   631         # No MigrationNotes were recorded, set total to zero
       
   632         $totalMigrationNotes=0;
       
   633         }
       
   634       else
       
   635         {
       
   636         $totalMigrationNotes = scalar(@{$migrationNotes{$component}});
       
   637         }
       
   638 
       
   639       if (!defined $AdvisoryNotes{$component})
       
   640         {
       
   641         # No AdvisoryNotes were recorded, set total to zero
       
   642           $totalAdvisoryNotes=0;
       
   643           }
       
   644        else
       
   645           {
       
   646          $totalAdvisoryNotes = scalar(@{$AdvisoryNotes{$component}});
       
   647           }
       
   648  
       
   649 
       
   650 
       
   651       # Print the Table Row
       
   652 	  &HTMLTableRow($title,$component, $Components{$component}, $totalerrors, $totalwarnings, $totalAdvisoryNotes, $totalremarks, $totalMigrationNotes);
       
   653 	}
       
   654   }
       
   655 
       
   656   # End the Table
       
   657   print HTML qq{</table>\n};
       
   658 
       
   659   # By Command
       
   660   print HTML qq{<h2>By Command</h2>\n};
       
   661 
       
   662   # Start the Table
       
   663   $title="Command";
       
   664   &StartHTMLTable($title);
       
   665 
       
   666   # Print the by Command Data
       
   667   # If there is a complete set of HiRes data then use that instead of the LowRes data
       
   668   if ((defined %HiResCommands) && !$HiResErrorFlag)
       
   669   {
       
   670     foreach $command (sort {lc $a cmp lc $b} keys %HiResCommands)
       
   671 	{
       
   672       # Calculate the number errors, warnings, advisory notes and remarks
       
   673       my $totalerrors;
       
   674       my $totalwarnings;
       
   675       my $totalremarks;
       
   676       my $totalMigrationNotes;
       
   677       my $totalAdvisoryNotes;
       
   678       if (!defined $CmdRemarks{$command})
       
   679       {
       
   680         # No Remarks were recorded, set total to zero
       
   681         $totalremarks = 0;
       
   682       } else {
       
   683         $totalremarks = scalar(@{$CmdRemarks{$command}});
       
   684       }
       
   685       if (!defined $CmdErrors{$command})
       
   686       {
       
   687         # No errors were recorded, set total to zero
       
   688         $totalerrors = 0;
       
   689       } else {
       
   690         $totalerrors = scalar(@{$CmdErrors{$command}});
       
   691       }
       
   692       if (!defined $CmdWarnings{$command})
       
   693       {
       
   694         # No Warnings were recorded, set total to zero
       
   695         $totalwarnings = 0;
       
   696       } else {
       
   697         $totalwarnings = scalar(@{$CmdWarnings{$command}});
       
   698       }
       
   699       
       
   700       if (!defined $CmdMigrationNotes{$command})
       
   701         {
       
   702         # No MigrationNotes were recorded, set total to zero
       
   703         $totalMigrationNotes=0;
       
   704         }
       
   705       else
       
   706         {
       
   707         $totalMigrationNotes = scalar(@{$CmdMigrationNotes{$command}});
       
   708         }
       
   709 
       
   710       if (!defined $CmdAdvisoryNotes{$command})
       
   711         {
       
   712         # No AdvisoryNotes were recorded, set total to zero
       
   713         $totalAdvisoryNotes=0;
       
   714         }
       
   715       else
       
   716         {
       
   717         $totalAdvisoryNotes = scalar(@{$CmdAdvisoryNotes{$command}});
       
   718         }
       
   719 
       
   720 
       
   721       # Print the Table Row
       
   722 	  &HTMLTableRow($title,$command, $HiResCommands{$command}, $totalerrors, $totalwarnings, $totalAdvisoryNotes, $totalremarks, $totalMigrationNotes);
       
   723 	}
       
   724   } else {
       
   725     foreach $command (sort {lc $a cmp lc $b} keys %Commands)
       
   726     {
       
   727       # Calculate the number errors,warnings,advisory notes and remarks
       
   728       my $totalerrors;
       
   729       my $totalwarnings;
       
   730       my $totalremarks;
       
   731       my $totalMigrationNotes;
       
   732       my $totalAdvisoryNotes;
       
   733       
       
   734       if (!defined $CmdRemarks{$command})
       
   735       {
       
   736         # No Remarks were recorded, set total to zero
       
   737         $totalremarks = 0;
       
   738       } else {
       
   739         $totalremarks = scalar(@{$CmdRemarks{$command}});
       
   740       }
       
   741       if (!defined $CmdErrors{$command})
       
   742       {
       
   743         # No errors were recorded, set total to zero
       
   744         $totalerrors = 0;
       
   745       } else {
       
   746         $totalerrors = scalar(@{$CmdErrors{$command}});
       
   747       }
       
   748       if (!defined $CmdWarnings{$command})
       
   749       {
       
   750         # No Warnings were recorded, set total to zero
       
   751         $totalwarnings = 0;
       
   752       } else {
       
   753         $totalwarnings = scalar(@{$CmdWarnings{$command}});
       
   754       }
       
   755       
       
   756       if (!defined $CmdMigrationNotes{$command})
       
   757         {
       
   758         # No MigrationNotes were recorded, set total to zero
       
   759         $totalMigrationNotes=0;
       
   760         }
       
   761       else
       
   762         {
       
   763         $totalMigrationNotes = scalar(@{$CmdMigrationNotes{$command}});
       
   764         }
       
   765 
       
   766       if (!defined $CmdAdvisoryNotes{$command})
       
   767         {
       
   768         # No AdvisoryNotes were recorded, set total to zero
       
   769         $totalAdvisoryNotes=0;
       
   770         }
       
   771       else
       
   772         {
       
   773         $totalAdvisoryNotes = scalar(@{$CmdAdvisoryNotes{$command}});
       
   774         }
       
   775 
       
   776       # Print the Table Row
       
   777       &HTMLTableRow($title,$command, $Commands{$command}, $totalerrors, $totalwarnings, $totalAdvisoryNotes, $totalremarks, $totalMigrationNotes);
       
   778     }
       
   779   }
       
   780 
       
   781   # End the Table
       
   782   print HTML qq{</table>\n};
       
   783 
       
   784   # Print Things Missing
       
   785   if (scalar %missing)
       
   786 	{
       
   787 	my $count = scalar keys %missing;
       
   788 	print HTML qq{<h2>Things Missing ($count)</h2>\n};
       
   789 	print HTML "Don't know how to make...\n";
       
   790 	foreach my $file (sort {lc $a cmp lc $b} keys %missing)
       
   791 		{
       
   792 		printf HTML "%d\t%s</BR>\n", $missing{$file}, $file;
       
   793 		}
       
   794 	}
       
   795   print HTML qq{</BR>\n};
       
   796 
       
   797   # Print Things Not Built
       
   798   if (scalar %not_built)
       
   799 	{
       
   800 	my $count = scalar keys %not_built;
       
   801 	print HTML qq{<h2>Things Not Built ($count)</h2>\n};
       
   802 	foreach my $file (sort {lc $a cmp lc $b} keys %not_built)
       
   803 		{
       
   804 		print HTML "MISSING: $file ($not_built{$file})</BR>\n";
       
   805 		}
       
   806 	}
       
   807 
       
   808 
       
   809   # Print the Actual Errors by Component
       
   810   if ($iVerbose > 0)
       
   811   {
       
   812     # Only Print the header if there are some errors
       
   813     if (scalar(keys %errors))
       
   814     {
       
   815       print HTML qq{<h2><a name="errorsByOverall_Total">Error Details by Component</a></h2>\n};
       
   816 	  foreach $component (sort {lc $a cmp lc $b} keys %errors)
       
   817 		{
       
   818 			my ($HTML) = $component;
       
   819 			$HTML =~ s/\s+$//;
       
   820 			encode_entities($HTML);
       
   821 			my $count = scalar @{$errors{$component}};
       
   822 			print HTML qq{<h3><a name="errorsByComponent_$HTML">$HTML</a> ($count)</h3>\n};
       
   823 			foreach $line (@{$errors{$component}})
       
   824 				{
       
   825 				encode_entities($line);
       
   826 				print HTML $line.qq{</BR>};
       
   827 				}
       
   828 			print HTML qq{</BR>\n};
       
   829 		}
       
   830     }
       
   831   }
       
   832 
       
   833   # Print the Actual Warning by Component
       
   834   if ($iVerbose > 1)
       
   835   {
       
   836     # Only Print the header if there are some warnings
       
   837     if (scalar(keys %warnings))
       
   838     {
       
   839       print HTML qq{<h2><a name="warningsByOverall_Total">Warning Details by Component</a></h2>\n};
       
   840       foreach $component (sort {lc $a cmp lc $b} keys %warnings)
       
   841         {
       
   842           my ($HTML) = $component;
       
   843           $HTML =~ s/\s+$//;
       
   844           encode_entities($HTML);
       
   845 		  my $count = scalar @{$warnings{$component}};
       
   846           print HTML qq{<h3><a name="warningsByComponent_$HTML">$HTML</a> ($count)</h3>\n};
       
   847           foreach $line (@{$warnings{$component}})
       
   848             {
       
   849             encode_entities($line);
       
   850             print HTML $line.qq{</BR>};
       
   851             }
       
   852           print HTML qq{</BR>\n};
       
   853         }
       
   854     }
       
   855   }
       
   856   
       
   857   # Print the Actual Advisory Notes by Component
       
   858   if ($iVerbose > 1)
       
   859   {
       
   860     # Only Print the header if there are some warnings
       
   861     if (scalar(keys %AdvisoryNotes))
       
   862     {
       
   863       print HTML qq{<h2><a name="AdvisoryNotesByOverall_Total">Advisory Note Details by Component</a></h2>\n};
       
   864       foreach $component (sort {lc $a cmp lc $b} keys %AdvisoryNotes)
       
   865         {
       
   866           my ($HTML) = $component;
       
   867           $HTML =~ s/\s+$//;
       
   868           encode_entities($HTML);
       
   869 		     my $count = scalar @{$AdvisoryNotes{$component}};
       
   870           print HTML qq{<h3><a name="AdvisoryNotesByComponent_$HTML">$HTML</a> ($count)</h3>\n};
       
   871           foreach $line (@{$AdvisoryNotes{$component}})
       
   872             {
       
   873             encode_entities($line);
       
   874             print HTML $line.qq{</BR>};
       
   875             }
       
   876           print HTML qq{</BR>\n};
       
   877         }
       
   878     }
       
   879   }  
       
   880 
       
   881   # Print the Actual Remarks by Component
       
   882   if ($iVerbose > 1)
       
   883   {
       
   884     # Only Print the header if there are some errors
       
   885     if (scalar(keys %remarks))
       
   886     {
       
   887       print HTML qq{<h2><a name="remarksByOverall_Total">Remarks Details by Component</a></h2>\n};
       
   888 	  foreach $component (sort {lc $a cmp lc $b} keys %remarks)
       
   889 		{
       
   890 			my ($HTML) = $component;
       
   891 			$HTML =~ s/\s+$//;
       
   892 			encode_entities($HTML);
       
   893 			my $count = scalar @{$remarks{$component}};
       
   894 			print HTML qq{<h3><a name="remarksByComponent_$HTML">$HTML</a> ($count)</h3>\n};
       
   895 			foreach $line (@{$remarks{$component}})
       
   896 				{
       
   897 				encode_entities($line);
       
   898 				print HTML $line.qq{</BR>};
       
   899 				}
       
   900 			print HTML qq{</BR>\n};
       
   901 		}
       
   902     }
       
   903   }
       
   904 
       
   905    # Print the Actual Migration Notes by Component
       
   906 if ($iVerbose > 1)
       
   907   {
       
   908     # Only Print the header if there are some warnings
       
   909     if (scalar(keys %migrationNotes))
       
   910     {
       
   911       print HTML qq{<h2><a name="migrationNotesByOverall_Total">Migration Note Details by Component</a></h2>\n};
       
   912       foreach $component (sort {lc $a cmp lc $b} keys %migrationNotes)
       
   913         {
       
   914           my ($HTML) = $component;
       
   915           $HTML =~ s/\s+$//;
       
   916           encode_entities($HTML);
       
   917 		     my $count = scalar @{$migrationNotes{$component}};
       
   918           print HTML qq{<h3><a name="migrationNotesByComponent_$HTML">$HTML</a> ($count)</h3>\n};
       
   919           foreach $line (@{$migrationNotes{$component}})
       
   920             {
       
   921             encode_entities($line);
       
   922             print HTML $line.qq{</BR>};
       
   923             }
       
   924           print HTML qq{</BR>\n};
       
   925         }
       
   926     }
       
   927   }
       
   928   
       
   929   # Print the Actual Errors by Command
       
   930   if ($iVerbose > 0)
       
   931   {
       
   932     # Only Print the header if there are some errors
       
   933     if (scalar(keys %CmdErrors))
       
   934     {
       
   935       print HTML qq{<h2>Error Details by Command</h2>\n};
       
   936 	  foreach $command (sort {lc $a cmp lc $b} keys %CmdErrors)
       
   937 		{
       
   938 			my ($HTML) = $command;
       
   939 			$HTML =~ s/\s+$//;
       
   940 			encode_entities($HTML);
       
   941 			print HTML qq{<h3><a name="errorsByCommand_$HTML">$HTML</a></h3>\n};
       
   942 			foreach $line (@{$CmdErrors{$command}})
       
   943 				{
       
   944 				encode_entities($line);
       
   945 				print HTML $line.qq{</BR>};
       
   946 				}
       
   947 			print HTML qq{</BR>\n};
       
   948 		}
       
   949     }
       
   950   }
       
   951 
       
   952   # Print the Actual Warning by Command
       
   953   if ($iVerbose > 1)
       
   954   {
       
   955     # Only Print the header if there are some warnings
       
   956     if (scalar(keys %CmdWarnings))
       
   957     {
       
   958       print HTML qq{<h2>Warning Details by Command</h2>\n};
       
   959 	  foreach $command (sort {lc $a cmp lc $b} keys %CmdWarnings)
       
   960 		{
       
   961 			my ($HTML) = $command;
       
   962 			$HTML =~ s/\s+$//;
       
   963 			encode_entities($HTML);
       
   964 			print HTML qq{<h3><a name="warningsByCommand_$HTML">$HTML</a></h3>\n};
       
   965 			foreach $line (@{$CmdWarnings{$command}})
       
   966 				{
       
   967 				encode_entities($line);
       
   968 				print HTML $line.qq{</BR>};
       
   969 				}
       
   970 			print HTML qq{</BR>\n};
       
   971 		}
       
   972     }
       
   973   }
       
   974   
       
   975   # Print the Actual Advisory Notes by Command
       
   976   if ($iVerbose >1)
       
   977   {
       
   978     # Only Print the header if there are some errors
       
   979     if (scalar(keys %CmdAdvisoryNotes))
       
   980       {
       
   981         print HTML qq{<h2>Advisory Note Details by Command</h2>\n};
       
   982             foreach $command (sort {lc $a cmp lc $b} keys %CmdAdvisoryNotes)
       
   983                   {
       
   984      	                  my ($HTML) = $command;
       
   985                           $HTML =~ s/\s+$//;
       
   986                           encode_entities($HTML);
       
   987                           print HTML qq{<h3><a name="AdvisoryNotesByCommand_$HTML">$HTML</a></h3>\n};
       
   988                           foreach $line (@{$CmdAdvisoryNotes{$command}})
       
   989 				  {
       
   990 				  encode_entities($line);
       
   991 		                  print HTML $line.qq{</BR>};
       
   992 	                          }
       
   993                           print HTML qq{</BR>\n}
       
   994                   }
       
   995       }
       
   996     }
       
   997 
       
   998   # Print the Actual Remarks by Command
       
   999   if ($iVerbose > 1)
       
  1000   {
       
  1001     # Only Print the header if there are some errors
       
  1002     if (scalar(keys %CmdRemarks))
       
  1003     {
       
  1004       print HTML qq{<h2>Remarks Details by Command</h2>\n};
       
  1005 	  foreach $command (sort {lc $a cmp lc $b} keys %CmdRemarks)
       
  1006 		{
       
  1007 			my ($HTML) = $command;
       
  1008 			$HTML =~ s/\s+$//;
       
  1009 			encode_entities($HTML);
       
  1010 			print HTML qq{<h3><a name="remarksByCommand_$HTML">$HTML</a></h3>\n};
       
  1011 			foreach $line (@{$CmdRemarks{$command}})
       
  1012 				{
       
  1013 				encode_entities($line);
       
  1014 				print HTML $line.qq{</BR>};
       
  1015 				}
       
  1016 			print HTML qq{</BR>\n};
       
  1017 		}
       
  1018     }
       
  1019   }
       
  1020 
       
  1021   # Print the Actual Migration Notes by Command
       
  1022   if ($iVerbose >1)
       
  1023     {
       
  1024     # Only Print the header if there are some errors
       
  1025     if (scalar(keys %CmdMigrationNotes))
       
  1026       {
       
  1027       print HTML qq{<h2>Migration Note Details by Command</h2>\n};
       
  1028       
       
  1029       foreach $command (sort {lc $a cmp lc $b} keys %CmdMigrationNotes)
       
  1030         {
       
  1031      	  my ($HTML) = $command;
       
  1032         $HTML =~ s/\s+$//;
       
  1033         encode_entities($HTML);
       
  1034         print HTML qq{<h3><a name="migrationNotesByCommand_$HTML">$HTML</a></h3>\n};
       
  1035         foreach $line (@{$CmdMigrationNotes{$command}})
       
  1036 				  {
       
  1037 				  encode_entities($line);
       
  1038 				  print HTML $line.qq{</BR>};
       
  1039 				  }
       
  1040         print HTML qq{</BR>\n}
       
  1041         }
       
  1042       }
       
  1043     }
       
  1044   
       
  1045 }
       
  1046 
       
  1047 
       
  1048 # StartHTMLTable
       
  1049 #
       
  1050 # Inputs
       
  1051 # $iC1Title (Column 1 Title)
       
  1052 #
       
  1053 # Outputs
       
  1054 #
       
  1055 # Description
       
  1056 # This function prints the start of the HTML Table
       
  1057 sub StartHTMLTable
       
  1058 {
       
  1059   my ($iC1Title) = @_;
       
  1060 
       
  1061   if ($iC1Title eq '')
       
  1062   {
       
  1063     $iC1Title = "&nbsp;";
       
  1064   } else {
       
  1065     encode_entities($iC1Title);
       
  1066   }
       
  1067 
       
  1068   # Start the Table
       
  1069   print HTML qq{<table border="1" cellpadding="0" cellspacing="0" width="100%">\n};
       
  1070 
       
  1071   # Print the Header Row
       
  1072   print HTML qq{\t<th width="50%">$iC1Title</th>\n};
       
  1073   print HTML qq{\t<th width="15%">Time</th>\n};
       
  1074   print HTML qq{\t<th width="8%">Errors</th>\n};
       
  1075   print HTML qq{\t<th width="8%">Warnings</th>\n};
       
  1076   print HTML qq{\t<th width="8%">Advisory Notes</th>\n};
       
  1077   print HTML qq{\t<th width="8%">Remarks</th>\n};
       
  1078   print HTML qq{\t<th width="8%">Migration Notes</th>\n};
       
  1079   print HTML qq{</tr>\n};
       
  1080 }
       
  1081 
       
  1082 # HTMLTableCell
       
  1083 #
       
  1084 # Inputs
       
  1085 # $iType	(errors,warnings,remarks,migration_notes)
       
  1086 # $iCount	(number of errors)
       
  1087 # $iLink	(empty string or linktype)
       
  1088 #
       
  1089 # Outputs
       
  1090 # Returns HTML table data element with appropriate link & background color
       
  1091 #
       
  1092 # Description
       
  1093 # Constructs HTML table element - used by HTMLTableRow to handle the formatting
       
  1094 # of the data cells, complete with colouring and links where appropriate.
       
  1095 sub HTMLTableCell
       
  1096 {
       
  1097    my ($iType,$iCount,$iLink)= @_;
       
  1098    my $td = qq{td width="8%" align="center"};	# implied by the TH elements already?
       
  1099    if ($iCount != 0)
       
  1100       {
       
  1101 	  $td = "$td BGCOLOR=$htmlColours{$iType}";
       
  1102       }
       
  1103    if ($iLink eq "" || $iCount == 0)
       
  1104       {
       
  1105       return qq{<$td>$iCount</td>};
       
  1106       }
       
  1107    $iLink = $iType."By".$iLink;
       
  1108    return qq{<$td><a href="#$iLink">$iCount</a></td>};
       
  1109 }
       
  1110 
       
  1111 # HTMLTableRow
       
  1112 #
       
  1113 # Inputs
       
  1114 # $iTitle (Need to differentiate between command and component to provide correct anchors)
       
  1115 # $iC1Data(Column 1 Data)
       
  1116 # $iC2Data(Column 2 Data) (Time in seconds)
       
  1117 # $iC3Data(Column 3 Data) (Number of errors)
       
  1118 # $iC4Data(Column 4 Data) (Number of warnings)
       
  1119 # $iC5Data(Column 5 Data) (Number of Advisory notes )
       
  1120 # $iC6Data(Column 6 Data) (Number of remarks )
       
  1121 # $iC7Data(Column 7 Data) (Number of migration notes )
       
  1122 #
       
  1123 # Outputs
       
  1124 #
       
  1125 # Description
       
  1126 # This function prints a line of the HTML Table
       
  1127 sub HTMLTableRow
       
  1128 {
       
  1129   my ($iTitle,$iC1Data, $iC2Data, $iC3Data, $iC4Data,$iC5Data, $iC6Data, $iC7Data) = @_;
       
  1130 
       
  1131   #print "$iC2Data\n";
       
  1132 
       
  1133   # Convert the seconds in hh:mm:ss format
       
  1134   $iC2Data = &ConvertSeconds($iC2Data);
       
  1135 
       
  1136   # HTML encode the text
       
  1137   encode_entities($iC1Data);
       
  1138   encode_entities($iC2Data);
       
  1139   encode_entities($iC3Data);
       
  1140   encode_entities($iC4Data);
       
  1141   encode_entities($iC5Data);
       
  1142   encode_entities($iC6Data);
       
  1143   encode_entities($iC7Data);
       
  1144 
       
  1145   my $linkname = "$iTitle"."_"."$iC1Data";
       
  1146   
       
  1147   # Print the Row, including summary in a script comment
       
  1148   print HTML qq{<tr>\n};
       
  1149   print HTML qq{<!--\t$linkname\t$iC2Data\t$iC3Data\t$iC4Data\t$iC5Data\t$iC6Data\t$iC7Data\t-->\n};
       
  1150   print HTML qq{\t<td width="50%">$iC1Data</td>\n};
       
  1151   print HTML qq{\t<td width="15%" align="center">$iC2Data</td>\n};
       
  1152 
       
  1153   print HTML "\t",&HTMLTableCell("errors",  $iC3Data,$linkname),"\n";
       
  1154   print HTML "\t",&HTMLTableCell("warnings",$iC4Data,$linkname),"\n";
       
  1155   print HTML "\t",&HTMLTableCell("AdvisoryNotes", $iC5Data,$linkname),"\n";
       
  1156   print HTML "\t",&HTMLTableCell("remarks", $iC6Data,$linkname),"\n";
       
  1157   print HTML "\t",&HTMLTableCell("migrationNotes", $iC7Data,$linkname),"\n";
       
  1158 
       
  1159   print HTML qq{</tr>\n};
       
  1160 }
       
  1161 
       
  1162 # ConvertSeconds
       
  1163 #
       
  1164 # Inputs
       
  1165 # $iSeconds
       
  1166 #
       
  1167 # Outputs
       
  1168 # $iString (seconds in hh:mm:ss)
       
  1169 #
       
  1170 # Description
       
  1171 # This function processes the commandline
       
  1172 sub ConvertSeconds
       
  1173 {
       
  1174   my ($iSeconds) = @_;
       
  1175   
       
  1176   my ($iString);
       
  1177   my ($ih) = int($iSeconds/3600);
       
  1178   my ($im) = int(($iSeconds-($ih*3600))/60);
       
  1179   my ($is) = $iSeconds-($ih*3600)-($im*60);
       
  1180   # Print the correct format if the data is HiRes (has a decimal point in the string)
       
  1181   if ($is =~ /\d+\.\d+/)
       
  1182   {
       
  1183     $iString = sprintf "%d:%02d:%06.3f", $ih, $im, $is;
       
  1184   } else {
       
  1185     $iString = sprintf "%d:%02d:%02d", $ih, $im, $is;
       
  1186   }
       
  1187   return $iString;
       
  1188 }
       
  1189 
       
  1190 # ProcessCommandLine
       
  1191 #
       
  1192 # Inputs
       
  1193 #
       
  1194 # Outputs
       
  1195 # $iOutput (Output filename)
       
  1196 # $iVerbose (Verbose Level)
       
  1197 # $iLogs (Log files to process)
       
  1198 #
       
  1199 # Description
       
  1200 # This function processes the commandline
       
  1201 
       
  1202 sub ProcessCommandLine {
       
  1203   my ($iHelp, @iLogs, $iOutput, $iTitle, $iVerbose, $iDiff, $iHistory, $iClass, $iHistoryHelp);
       
  1204   GetOptions('h' => \$iHelp, 'l=s' =>\@iLogs, 'o=s' => \$iOutput, 't=s' => \$iTitle, 'v+' => \$iVerbose, 'd=s' =>\$iDiff, 'c=s' =>\$iHistory, 'm=s' =>\$iClass, 'hh' => \$iHistoryHelp);
       
  1205 
       
  1206   if ($iHistoryHelp)
       
  1207   {
       
  1208     &HistoryHelp();
       
  1209   }
       
  1210 
       
  1211   if (($iHelp) || (!defined @iLogs) || (!defined $iOutput))
       
  1212   {
       
  1213     Usage();
       
  1214   } elsif (-e $iOutput) {
       
  1215     die "$iOutput already exists";
       
  1216   } elsif (-e $iDiff) {
       
  1217     die "$iDiff already exists";
       
  1218   } elsif (-e $iWhat) {
       
  1219     die "$iWhat already exists";
       
  1220   }
       
  1221   foreach my $iLog (@iLogs)
       
  1222   {
       
  1223     warn "$iLog does not exist" if (! -e $iLog);
       
  1224   }
       
  1225   
       
  1226   # Check the history options
       
  1227   if (defined $iHistory)
       
  1228   {
       
  1229     if (! -e $iHistory)
       
  1230     {
       
  1231 	    warn "$iHistory does not exist";
       
  1232 	    undef $iHistory;
       
  1233     } 
       
  1234     
       
  1235    	elsif (!defined $iClass)
       
  1236    	{
       
  1237 	    warn "No machine name to class csv file specified with -m option";
       
  1238 	    undef $iHistory;
       
  1239    	}
       
  1240   }
       
  1241 
       
  1242   # Set default title
       
  1243   if ($iTitle eq '')
       
  1244   {
       
  1245     $iTitle = "Log File Summary";
       
  1246   }
       
  1247 
       
  1248   return($iOutput, $iTitle, $iVerbose, $iDiff, $iWhat, $iHistory, $iClass, @iLogs);
       
  1249 }
       
  1250 
       
  1251 # Usage
       
  1252 #
       
  1253 # Output Usage Information.
       
  1254 #
       
  1255 
       
  1256 sub Usage {
       
  1257   print <<USAGE_EOF;
       
  1258 
       
  1259     Usage: Scanlog.pl [options]
       
  1260 
       
  1261     options:
       
  1262 
       
  1263     -h  help
       
  1264     -l  Log file to scan [Multiple allowed]
       
  1265     -o  Output file
       
  1266     -v  Increments Verbose level [Maximum Level = 2]
       
  1267     -t  Title to add to the Summary
       
  1268     -d  Filename for Logfile with Time Information removed [Optional]
       
  1269     
       
  1270     History options [Optional]
       
  1271     -hh More help on History options and file formats
       
  1272     -c  History csv to add summary to
       
  1273     -m  Machine name to class csv data file [required if using -c]
       
  1274 
       
  1275 USAGE_EOF
       
  1276 	exit 1;
       
  1277 }
       
  1278 
       
  1279 # HistoryHelp
       
  1280 #
       
  1281 # Output History Help Information.
       
  1282 #
       
  1283 sub HistoryHelp{
       
  1284   print <<HISTORY_EOF;
       
  1285 
       
  1286   History Description:
       
  1287   The History function collates the timing summary information of the
       
  1288   components from multiple builds. As the timing data varies between
       
  1289   machines of different specifications, htmlscanlog tries to identify
       
  1290   the machines hostname from the logs so it can identify which class
       
  1291   of machine it belongs to (the machine class is used to group multiple
       
  1292   machines with identical specifications). If it is not able to identify
       
  1293   a machine name (and class) it uses the first entry in the Machine name
       
  1294   to class csv.
       
  1295   
       
  1296   History csv file format:
       
  1297   The csv format is for easy loading into spreadsheet programs for
       
  1298   generating charts. The first line contains the column headings, the
       
  1299   first column headings is the machine class, machine name, Title,
       
  1300   the last time entry in all the logs processed, then the
       
  1301   component names. Removed components will cause empty entries, new
       
  1302   components will be added at the end.
       
  1303   
       
  1304   Machine name to class csv data file format:
       
  1305   The csv format contains two columns with no headings, first column is
       
  1306   the class name, the second is the machine name.
       
  1307     
       
  1308 HISTORY_EOF
       
  1309 	exit 1;
       
  1310 }
       
  1311 
       
  1312 # PrintHTMLHeader
       
  1313 #
       
  1314 # Inputs
       
  1315 # $iTitle (Title for Log file)
       
  1316 #
       
  1317 # Outputs
       
  1318 #
       
  1319 # Description
       
  1320 # This function print the HTML Header
       
  1321 
       
  1322 sub PrintHTMLHeader {
       
  1323   my ($iTitle) = @_;
       
  1324 
       
  1325    print HTML <<HTML_EOF;
       
  1326 <HTML>
       
  1327 <HEAD>
       
  1328 <TITLE>$iTitle</TITLE>
       
  1329 </HEAD>
       
  1330 <BODY BGCOLOR="FFFFFF">
       
  1331 <FONT FACE="Courier New">
       
  1332 HTML_EOF
       
  1333 }
       
  1334 
       
  1335 # PrintHTMLFooter
       
  1336 #
       
  1337 # Inputs
       
  1338 #
       
  1339 # Outputs
       
  1340 #
       
  1341 # Description
       
  1342 # This function print the HTML Footer
       
  1343 
       
  1344 sub PrintHTMLFooter {
       
  1345    print HTML <<HTML_EOF;
       
  1346 </FONT>
       
  1347 </BODY>
       
  1348 </HTML>
       
  1349 HTML_EOF
       
  1350 }
       
  1351 
       
  1352 #  DiffDateTime
       
  1353 #
       
  1354 # Inputs
       
  1355 # $StartDateTime (Start Date/Time String)
       
  1356 # $EndDateTime (End Date/Time String)
       
  1357 #
       
  1358 # Outputs
       
  1359 # $Duration (Difference in seconds bertween the two dates/Times)
       
  1360 #
       
  1361 # Description
       
  1362 # This function calculate the difference between to dates and times
       
  1363 
       
  1364 sub DiffDateTime {
       
  1365   my ($String1, $String2) = @_;
       
  1366   
       
  1367   my ($err, $delta);
       
  1368 
       
  1369   $delta=&DateCalc($String1,$String2,\$err);
       
  1370   if ($err)
       
  1371   {
       
  1372     print "WARNING: DiffDateTime encountered and error\n";
       
  1373     return "0";
       
  1374   } else { 
       
  1375     # Convert into seconds to aid additions
       
  1376     return &Delta_Format($delta,'0',"%sh");
       
  1377   }
       
  1378 }
       
  1379 
       
  1380 sub do_remarks()
       
  1381 {
       
  1382 	my ($iLog) =@_;
       
  1383 	# Store remarks by Command
       
  1384 	if (!defined $CmdRemarks{$command})
       
  1385 		{
       
  1386 		$CmdRemarks{$command} = ();
       
  1387 		}
       
  1388 	push @{$CmdRemarks{$command}}, "$iLog:"."$.".">$line";
       
  1389 
       
  1390 	# Store remarks by Component
       
  1391 	if (!defined $remarks{$component})
       
  1392 		{
       
  1393 		$remarks{$component} = ();
       
  1394 		}
       
  1395 	push @{$remarks{$component}}, "$iLog:"."$.".">$line";
       
  1396 }
       
  1397 
       
  1398 sub do_warning()
       
  1399 {
       
  1400 	my ($iLog) =@_;
       
  1401 	# Store warning by Command
       
  1402 	if (!defined $CmdWarnings{$command})
       
  1403 		{
       
  1404 		$CmdWarnings{$command} = ();
       
  1405 		}
       
  1406 	push @{$CmdWarnings{$command}}, "$iLog:"."$.".">$line";
       
  1407 
       
  1408 	# Store warning by Component
       
  1409 	if (!defined $warnings{$component})
       
  1410 		{
       
  1411 		$warnings{$component} = ();
       
  1412 		}
       
  1413 	push @{$warnings{$component}}, "$iLog:"."$.".">$line";
       
  1414 }
       
  1415 
       
  1416 
       
  1417 sub do_migrationNotes()
       
  1418   {
       
  1419   my ($iLog)= @_;
       
  1420   # Store Migration Notes by command
       
  1421   if (!defined $CmdMigrationNotes{$command})
       
  1422     {
       
  1423     $CmdMigrationNotes{$command} = ();
       
  1424     }
       
  1425   push @{$CmdMigrationNotes{$command}}, "$iLog:"."$.".">$line";
       
  1426   
       
  1427   # Store Migration Notes by Componen
       
  1428   if (!defined $migrationNotes{$component})
       
  1429     {
       
  1430     $migrationNotes{$component} = ();
       
  1431     }
       
  1432   push @{$migrationNotes{$component}}, "$iLog:"."$.".">$line";
       
  1433   
       
  1434   }
       
  1435 
       
  1436 sub do_AdvisoryNotes()
       
  1437   {
       
  1438   my ($iLog)= @_;
       
  1439   # Store Advisory Notes by command
       
  1440   if (!defined $CmdAdvisoryNotes{$command})
       
  1441     {
       
  1442     $CmdAdvisoryNotes{$command} = ();
       
  1443     }
       
  1444   push @{$CmdAdvisoryNotes{$command}}, "$iLog:"."$.".">$line";
       
  1445   
       
  1446   # Store Advisory Notes by Component
       
  1447   if (!defined $AdvisoryNotes{$component})
       
  1448     {
       
  1449     $AdvisoryNotes{$component} = ();
       
  1450     }
       
  1451   push @{$AdvisoryNotes{$component}}, "$iLog:"."$.".">$line";
       
  1452   
       
  1453 }
       
  1454 
       
  1455 sub do_error()
       
  1456 {
       
  1457   my ($iLog) =@_;
       
  1458 	# Store Errors by Command
       
  1459 	if (!defined $CmdErrors{$command})
       
  1460 		{
       
  1461 		$CmdErrors{$command} = ();
       
  1462 		}
       
  1463 	push @{$CmdErrors{$command}}, "$iLog:"."$.".">$line";
       
  1464 
       
  1465 	# Store Errors by Component
       
  1466 	if (!defined $errors{$component})
       
  1467 		{
       
  1468 		$errors{$component} = ();
       
  1469 		}
       
  1470 	push @{$errors{$component}}, "$iLog:"."$.".">$line";
       
  1471 }
       
  1472 
       
  1473 # Read a number of lines in the log ignoreing the content
       
  1474 sub do_slurp()
       
  1475 {
       
  1476   my ($num_lines) =@_;
       
  1477   for (my $i = 0; $i < $num_lines; $i++)
       
  1478   {
       
  1479     <LOG>;
       
  1480   }
       
  1481 }