view g23m/system/busyb/tools/cmp_objs.pl @ 12:da79bf85bd73

README added
author Space Falcon <falcon@ivan.Harhan.ORG>
date Tue, 02 Jun 2015 00:29:51 +0000
parents 509db1a7b7b8
children
line wrap: on
line source

#!perl -w

# This script compares object files in two directories. Comparisons is done bytewise ignoring
# the first 8 bytes of the file ( COFF magic number and time stamp).
#
# The directories must be specified in a configuration file read by the script. The filename is
# passed as the one and only command line parameter.
#
# The script expects the utility cmp to be in the path.
#
# The syntax of each line in the configuration file is the following (comments start with #)
# <left_directory> <right_directory> <excluded_files> <explicit_files>
# <excluded_files> = [-<filename_without_path>]*
# <explicit_files> = [+<filename_without_path>]*
#
# default behaviour (no excluded or explicit files) is to compare all similar named files
# inthe  two directories
# if <excluded_files> are specified these files are excluded from the comparison
# if <explicit_files> are specified ONY THESE FILES are included in the comparison
#
# Attention: file and directory names MUST NOT contain spaces or other white space

use strict;

use File::Glob ':glob';
use File::Spec;

# define global variables
my $cnfFile=$ARGV[0];
my $logFile="cmp_report.log";
my $firstComment = 1;

# find the config file
@ARGV == 1 || die "Usage:\tcmp_objs.pl config_file\n";

# check for cmp.exe
system("cmp -v > cmp_report.log 2>&1") && die "ERROR: cmp must be in the path \n";

# open the config file
#
open (IN,"<$cnfFile")||die "Can't open $cnfFile !\n";

# parse the config file
#
  my $line;

  while(defined($line = <IN>))
  {
    # reset variable for next loop
    my $leftDir;
    my $rightDir;
    my @files;
    my @excludedFiles;
    my @explicitFiles;

    # ignore comments (starting with #)
    if($line =~ /^\s*\#/) {
      # print out special comments starting with ##
      if ($' =~ /^\s*\#/) {
        if ($firstComment == 1) {
          print "\n";
          $firstComment = 0;
        }
        print "[COMMENT]  $'";
      }
      else {
        $firstComment = 1;
      }
      next;
    }

    # ignore empty lines
    if($line =~ /^\s+$/) {
      next;
    }

    # remove trailing \n
    chomp($line);
    
    # put everything SEPARATED BY WHITESPACE in an array
    @files = split(/\s+/,$line);

    # find the directories (and remove them from the array)
    $leftDir = $files[0]; shift(@files);
    $rightDir = $files[0]; shift(@files);

    # check whether the directories are wildcards
#    if ($leftDir =~ s/(.*?)(\/\*)/$1/ && $rightDir =~ s/(.*?)(\/\*)/$1/ ) {
    if ($leftDir =~ s:(.*?)([/\\]\*):$1: && $rightDir =~ s:(.*?)([/\\]\*):$1: ) {
      my @dirs;
      my @leftDirs;
      my @rightDirs;

      # check whether the parent directories exist
      (-e $leftDir) || die "Directory $leftDir does not exist !\n";
      (-e $rightDir) || die "Directory $rightDir does not exist !\n";

      # find all sub directories left
      @dirs = bsd_glob("$leftDir/*");
      @dirs = sort @dirs;
      foreach (@dirs) {
        my ($drv,$dir);
        ($drv,$dir,$_) = File::Spec->splitpath($_);
        if (-d "$leftDir/$_") {
          push (@leftDirs, "$_");
        }
      }

      # reset variables
      splice (@dirs);

      # find all sub directories right
      @dirs = bsd_glob("$rightDir/*");
      @dirs = sort @dirs;
      foreach (@dirs) {
        my ($drv,$dir);
        ($drv,$dir,$_) = File::Spec->splitpath($_);
        if (-d "$rightDir/$_") {
          push (@rightDirs, "$_");
        }
      }

      # create a hash that uses the filename as the key and an integer as value
      # to find those directories that are found in both directories or only in one
      # of them
      my %count;
      my $element;

      foreach $element (@leftDirs) { $count{$element}++; }
      foreach $element (@rightDirs) { $count{$element}+=2; }
  
      # delete used arrays for later reuse
      splice (@dirs);
      splice (@leftDirs);
      splice (@rightDirs);

      foreach $element (keys %count) { 
          if ($count{$element} == 1) {
            push @leftDirs, $element;
          }
          elsif ($count{$element} == 2) {
            push @rightDirs, $element;
          }
          elsif  ($count{$element} == 3) {
            push @dirs, $element;
          }
      }
      print "[LEFT   ]  $leftDir/*\n";
      print "[RIGHT  ]  $rightDir/*\n";
      foreach $element (sort(@leftDirs)) { 
        print "[WARNING - directory missing right]     $element\n";
      }
      foreach $element (sort(@rightDirs)) { 
        print "[WARNING - directory missing left]     $element\n";
      }
      print "\n";
      foreach $element (sort(@dirs)) {
        # ignore some commonly used version files
        splice (@excludedFiles);
        push (@excludedFiles,"ver.obj");
        push (@excludedFiles,"$element\_version.obj");
        cmp_dirs ("$leftDir/$element", "$rightDir/$element", \@excludedFiles, \@explicitFiles);
      }

    }
    else {
      # check whether the directories exist
      (-e $leftDir) || die "Directory $leftDir does not exist !\n";
      (-e $rightDir) || die "Directory $rightDir does not exist !\n";

      if (defined($files[0])) {
        # some files are are specified or excluded explicitely
        foreach (@files) {
          if (/^-/) {
            push(@excludedFiles,$');
          }
          elsif(/^\+/) {
            (-e "$leftDir/$'") || die "File $rightDir/$' does not exist !\n";
            (-e "$rightDir/$'") || die "File $rightDir/$' does not exist !\n";
            push(@explicitFiles,$');
          }
        }
      }
      cmp_dirs ($leftDir, $rightDir, \@excludedFiles, \@explicitFiles);
    }
 
  }


# close the config file
#
close IN;

# delete the log file
#
#unlink($logFile);

###################
#
sub cmp_dirs {

    my $leftDir = $_[0];
    my $rightDir = $_[1];
    my @excludedFiles = @{$_[2]};
    my @explicitFiles = @{$_[3]};

    my @files;
    my @leftFiles;
    my @rightFiles;
    my $element;

    if (defined($explicitFiles[0])) {
      @files = @explicitFiles;
    }
    else {
      @leftFiles = bsd_glob("$leftDir/*.obj");
      @leftFiles = sort @leftFiles;
      foreach (@leftFiles) {
        my ($drv,$dir);
        ($drv,$dir,$_) = File::Spec->splitpath($_);
      }
  
      @rightFiles = bsd_glob("$rightDir/*.obj");
      @rightFiles = sort @rightFiles;
      foreach (@rightFiles) {
        my ($drv,$dir);
        ($drv,$dir,$_) = File::Spec->splitpath($_);
      }
  
      # create a hash that uses the filename as the key and an integer as value
      # to find those files that are found in both directories or only in one
      # of them
      my %count;

      foreach $element (@leftFiles) { $count{$element}++; }
      foreach $element (@rightFiles) { $count{$element}+=2; }
  
      # delete used arrays for later reuse
      splice (@files);
      splice (@leftFiles);
      splice (@rightFiles);

      # remove all exclude files
      foreach $element (@excludedFiles) { 
        if (exists($count{$element})) {
#          print "Skipping file: $element \n";
          delete($count{$element});
        }
      }

      foreach $element (keys %count) { 
          if ($count{$element} == 1) {
            push @leftFiles, $element;
          }
          elsif ($count{$element} == 2) {
            push @rightFiles, $element;
          }
          elsif  ($count{$element} == 3) {
            push @files, $element;
          }
      }
    }


    print "[LEFT ]  $leftDir/\n";
    print "[RIGHT]  $rightDir/\n";

    if(defined($leftFiles[0]) || defined($rightFiles[0]) ) {
      my %tmp;

      foreach $element (@leftFiles)  { $tmp{$element} = "  [WARNING - file missing right]     $element\n" };
      foreach $element (@rightFiles) { $tmp{$element} = "  [WARNING - file missing left ]     $element\n"; }

      foreach $element (sort(keys %tmp)) { 
        print $tmp{$element};
      }
    }


    foreach (sort(@files)) {
      if (system("cmp -i8 $leftDir/$_ $rightDir/$_ >>$logFile 2>&1")) {
       print "  [ERROR   - files differ]     $_\n";
       cmp_cmdFiles ($leftDir , $rightDir , $_ );
      }
    }

   print "\n";
}




###################
##
sub cmp_cmdFiles {

  my $leftDir = $_[0];
  my $rigthDir = $_[1];
  my $cmdFile = $_[2];

  my @leftDef;
  my @rightDef;

  $cmdFile =~ s/\.obj/\.cl470cmd/;

  my $leftFile = $leftDir . "\\" . $cmdFile;
  my $rightFile = $rigthDir . "\\" . $cmdFile;

  print "    [Checking cmd files  ]     $cmdFile\n";

  if (!(-e $leftFile) || !(-e $rightFile)){
    print "      [Cmdfile(s) missing]\n\n";
    return;
  }

  my @AoA = parse_cmdFile($leftFile);
  push(@leftDef, @{$AoA[0]});

  @AoA = parse_cmdFile($rightFile);
  push(@rightDef, @{$AoA[0]});

  my %defines;
  my $element;
  my %defSorted;

  foreach $element (@leftDef) { $defines{$element}++; }
  foreach $element (@rightDef) { $defines{$element}+=2; }

  foreach $element (keys %defines) { 
      if ($defines{$element} == 1) {
        $defSorted{"      [LEFT ]                  $element\n"} = 0;
      }
      elsif ($defines{$element} == 2) {
        $defSorted{"      [RIGHT]                  $element\n"} = 0;
      }
  }
  foreach $element (sort(keys(%defSorted))) { 
    print $element;
  }

  print "\n";
}

###################
##
sub parse_cmdFile {
  my @defines;
  my %def;
  my $line;
  my $element;

  open (CMD,"<$_[0]")||die "Can't open $_[0] !\n";
  while(defined($line = <CMD>))
  {
    chomp($line);
    my @tmp = split(/\s+/,$line);
    foreach $element (@tmp) {
      if ($element =~ /^-d/i ) {
        if ($' =~ /^$/) {
          #ignore empty defines
        }
        else {
          $def{"-D$'"}++;
        }
      }
      elsif ($element =~ /^-u/i ) {
        if ($' =~ /^$/) {
          #ignore empty defines
        }
        else {
          $def{"-U$'"}++;
        }
      }
    }
  }

# check for double defines
#  foreach $element (keys %def) { 
#    print "$element\n";
#    }

  @defines = sort(keys %def);
  
  close CMD;
  return (\@defines);
}