#!/perl -w
# NAME: vc_cmp.pl
# AIM: Compare 2 vcproj files
use strict;
use warnings;
use File::Basename;  # split path ($name,$dir,$ext) = fileparse($file [, qr/\.[.]*/] )
use Cwd;
unshift(@INC, 'C:\GTools\perl');
require 'fgutils02.pl' or die "Unable to load fgutils02.pl ...\n";
require 'fgdsphdrs03.pl' or die "Unable to load fgdsphdrs03.pl ...\n";
require 'scanvc.pl' or die "Unable to load scanvc.pl ...\n";
# log file stuff
my ($LF);
my $pgmname = $0;
if ($pgmname =~ /\w{1}:\\.*/) {
    my @tmpsp = split(/\\/,$pgmname);
    $pgmname = $tmpsp[-1];
}
my $perl_dir = 'C:\GTools\perl';
my $outfile = $perl_dir."\\temp.$pgmname.txt";
open_log($outfile);

# user variables
my $debug_on = 0;   # OFF for release
my $def_file1 = 'C:\FG\Atlas\Atlas-0.4.8\projects\msvc\Atlas.vcproj';
my $def_file2 = 'C:\FG\Atlas\Atlas-0.4.8\projects\msvc\Map.vcproj';

my $load_log = 0;
my $in_file1 = '';
my $in_file2 = '';
my $show_cfgs = 0;
my $show_all = 0;

### program variables
my @warnings = ();
my $cwd = cwd();
my $os = $^O;

sub pgm_exit($$) {
    my ($val,$msg) = @_;
    if (length($msg)) {
        $msg .= "\n" if (!($msg =~ /\n$/));
        prt($msg)
    }
    close_log($outfile,$load_log);
    exit($val);
}


sub prtw($) {
   my ($tx) = shift;
   $tx =~ s/\n$//;
   prt("$tx\n");
   push(@warnings,$tx);
}

sub show_warnings() {
   if (@warnings) {
      prt( "\nGot ".scalar @warnings." WARNINGS...\n" );
      foreach my $itm (@warnings) {
         prt("$itm\n");
      }
      prt("\n");
   } else {
      prt( "\nNo warnings issued.\n\n" );
   }
}

sub compare_source_arrays($$$$) {
    my ($rh1,$rh2,$val1,$val2) = @_;
    my ($key,$src,$grp,$flt,$ff,$ok,$i);
    my $acnt1 = scalar @{$val1};
    my $acnt2 = scalar @{$val2};
    $key = 'PROJECT_FDIR';
    my $sdir1 = ((defined ${$rh1}{$key}) ? ${$rh1}{$key} : "Undefined1/");
    my $sdir2 = ((defined ${$rh2}{$key}) ? ${$rh2}{$key} : "Undefined2/");
    my %srcs1 = ();
    my %srcs2 = ();
    my $min1 = 0;
    my $min2 = 0;
    my $cnt1 = 0;
    my $cnt2 = 0;
    my $scnt = 0;
    my ($len,$msg,$ra1,$ra2);
    for ($i = 0; $i < $acnt1; $i++) {
        $src = ${$val1}[$i][0];
        $grp = ${$val1}[$i][1];
        $flt = ${$val1}[$i][2];
        $ff = fix_rel_path($sdir1.$src); # in fgutils02.pl
        $ok = (-f $ff) ? 'ok' : 'NF';
        $srcs1{$src} = [ $i, $ok, $ff, $val1 ];
        $len = length($src);
        $min1 = $len if ($len > $min1);
        $len = length($grp);
        $min2 = $len if ($len > $min2);
        $cnt1++;
    }
    for ($i = 0; $i < $acnt2; $i++) {
        $src = ${$val2}[$i][0];
        $grp = ${$val2}[$i][1];
        $flt = ${$val2}[$i][2];
        $ff = fix_rel_path($sdir2.$src); # in fgutils02.pl
        $ok = (-f $ff) ? 'ok' : 'NF';
        $srcs2{$src} = [ $i, $ok, $ff, $val2 ];
        $len = length($src);
        $min1 = $len if ($len > $min1);
        $len = length($grp);
        $min2 = $len if ($len > $min2);
        $cnt2++;
    }
    # count any SHARED sources, if any... not a FULL check
    foreach $key (keys %srcs1) {
            $scnt++ if (defined $srcs2{$key});
    }
    prt(" Compare of sources F1=$cnt1, F2=$cnt2, SHARED=$scnt\n");
    if ($show_all) {
        $cnt1 = 0;
        foreach $key (keys %srcs1) {
            $cnt1++ if (!defined $srcs2{$key});
        }
        prt(" List $cnt1, only in F1...\n");
        foreach $key (keys %srcs1) {
            $ra1 = $srcs1{$key};
            $i    = ${$ra1}[0];
            $ok   = ${$ra1}[1];
            $ff   = ${$ra1}[2];
            $val1 = ${$ra1}[3];
            $src = ${$val1}[$i][0];
            $grp = ${$val1}[$i][1];
            $flt = ${$val1}[$i][2];
            $msg = $key;
            $msg .= ' ' while (length($msg) < $min1);
            if (defined $srcs2{$key}) {
                # prt(" $msg - SHARED SOURCE\n");
            } else {
                prt(" $msg - ONLY IN F1 $ok $grp $flt\n");
            }
        }
        $cnt2 = 0;
        foreach $key (keys %srcs2) {
            $cnt2++ if (!defined $srcs1{$key});
        }
        prt(" List $cnt2, only in F2...\n");
        foreach $key (keys %srcs2) {
            $ra2 = $srcs2{$key};
            $i    = ${$ra2}[0];
            $ok   = ${$ra2}[1];
            $ff   = ${$ra2}[2];
            $val2 = ${$ra2}[3];
            $src = ${$val2}[$i][0];
            $grp = ${$val2}[$i][1];
            $flt = ${$val2}[$i][2];
            $msg = $key;
            $msg .= ' ' while (length($msg) < $min1);
            if (defined $srcs1{$key}) {
                # prt(" $msg - SHARED SOURCE\n");
            } else {
                prt(" $msg - ONLY IN F2 $ok $grp $flt\n");
            }
        }
    }
    if ($scnt) {
        prt(" List of $scnt SHARED F1 and F2...\n");
        foreach $key (keys %srcs1) {
            $ra1 = $srcs1{$key};
            $i    = ${$ra1}[0];
            $ok   = ${$ra1}[1];
            $ff   = ${$ra1}[2];
            $val1 = ${$ra1}[3];
            $src = ${$val1}[$i][0];
            $grp = ${$val1}[$i][1];
            $flt = ${$val1}[$i][2];
            $msg = $key;
            $msg .= ' ' while (length($msg) < $min1);
            if (defined $srcs2{$key}) {
                prt(" $msg - SHARED SOURCE $ok $grp $flt\n");
            }
        }
    } elsif (!$show_all) {
        prt(" There appears NO shared sources. Use -show-all to see source lists.\n");
    }
}

sub compare_config_arrays($$$$) {
    my ($rh1,$rh2,$val1,$val2) = @_;
    my $acnt1 = scalar @{$val1};
    my $acnt2 = scalar @{$val2};
    my ($i,$i2,$src,$grp,$flt,$rsb,@karr,$scnt,$msg,$ky,$v2);
    my %cfgs1 = ();
    my %cfgs2 = ();
    my ($ckey);
    # my $rcfgs = ${$rh}{'PROJECT_CFGS'};
    #                   0       1      2      3
    # push(@{$rcfgs}, [ $pname, $var1, $conf, $dsp_sub_sub ]);
    for ($i = 0; $i < $acnt1; $i++) {
        $src = ${$val1}[$i][0];
        $flt = ${$val1}[$i][2];
        $ckey = $src.'+'.$flt;
        $cfgs1{$ckey} = $i;
    }
    for ($i = 0; $i < $acnt2; $i++) {
        $i2 = $i + 1;
        $src = ${$val2}[$i][0];
        $flt = ${$val2}[$i][2];
        $ckey = $src.'+'.$flt;
        $cfgs2{$ckey} = $i;
    }

    prt(" List of $acnt1 CONFIGS in F1\n");
    for ($i = 0; $i < $acnt1; $i++) {
        $i2 = $i + 1;
        $src = ${$val1}[$i][0];
        #$grp = ${$val1}[$i][1];
        $flt = ${$val1}[$i][2];
        $rsb = ${$val1}[$i][3];
        @karr = keys(%{$rsb});
        $scnt = scalar @karr;
        $msg = sprintf("%3d:",$i2);
        #prt( "  $msg [$src] [$grp] [$flt] $scnt\n" );
        prt( "  $msg [$src] [$flt] $scnt\n" );
        foreach $ky (@karr) {
            $v2 = ${$rsb}{$ky};
            prt("   $ky = [$v2]\n" );
        }
    }
    prt(" List of $acnt2 CONFIGS in F1\n");
    for ($i = 0; $i < $acnt2; $i++) {
        $i2 = $i + 1;
        $src = ${$val2}[$i][0];
        #$grp = ${$val2}[$i][1];
        $flt = ${$val2}[$i][2];
        $rsb = ${$val2}[$i][3];
        @karr = keys(%{$rsb});
        $scnt = scalar @karr;
        $msg = sprintf("%3d:",$i2);
        #prt( "  $msg [$src] [$grp] [$flt] $scnt\n" );
        prt( "  $msg [$src] [$flt] $scnt\n" );
        foreach $ky (@karr) {
            $v2 = ${$rsb}{$ky};
            prt("   $ky = [$v2]\n" );
        }
    }
    # attempt to compare ***TBD***
}

sub compare_hash_results($$) {
    my ($rh1,$rh2) = @_;
    my ($key,$val1,$val2,$cnt,$fil1,$fil2);
    my ($acnt1,$acnt2,$typ);
    my %done = ();
    $key = 'PROJECT_FILE';
    $fil1 = ((defined ${$rh1}{$key}) ? ${$rh1}{$key} : "Unknown1");
    $fil2 = ((defined ${$rh2}{$key}) ? ${$rh2}{$key} : "Unknown2");
    my $hrki = get_prj_key_info_ref();
    prt("Comparing [$fil1], with [$fil2]\n");
    foreach $key (keys %{$rh1}) {
        $val1 = ${$rh1}{$key};
        if (defined ${$rh2}{$key}) {
            $val2 = ${$rh2}{$key};
        } else {
            prt("Key [$key] NOT available in 2\n");
        }
        $done{$key} = 1;
    }
    foreach $key (keys %{$rh2}) {
        $val2 = ${$rh2}{$key};
        if (!defined $done{$key}) {
            prt("Key [$key] NOT available in 1\n");
        }
    }
    foreach $key (keys %{$rh1}) {
        $val1 = ${$rh1}{$key};
        if (defined ${$rh2}{$key}) {
            $val2 = ${$rh2}{$key};
            if ( $key =~ /^CURR_/ ) {
                # ignore current items
            } else {
                if (defined ${$hrki}{$key}) {
                    $typ = ${$hrki}{$key};
                    if ($typ =~ /^<S>/) {
                        if ($val1 eq $val2) {
                            prt("$key:$typ [$val1] SAME\n");
                        } else {
                            prt("$key:$typ [$val1] vs [$val2] DIFFERENT\n");
                        }
                    } elsif ($typ =~ /^<N>/) {
                        if ($val1 == $val2) {
                            prt("$key:$typ [$val1] SAME\n");
                        } else {
                            prt("$key:$typ [$val1] vs [$val2] DIFFERENT\n");
                        }
                    } else {
                        # it is an ARRAY
                        $acnt1 = scalar @{$val1};
                        $acnt2 = scalar @{$val2};
                        prt( "$key:$typ F1=[$fil1]=$acnt1, F2=[$fil2]=$acnt2\n" );
                        if ($key eq 'PROJECT_SRCS') {
                            # compare the SOURCES
                            # compare_source_arrays($rh1,$rh2,$val1,$val2);
                        } elsif ($key eq 'PROJECT_CFGS') {
                            # compare the CONFIGS
                            compare_config_arrays($rh1,$rh2,$val1,$val2) if ($show_cfgs);
                        }
                    }
                } else {
                    prtw("WARNING: $key NOT in info hash!\n");
                }
            }
        }
    }
    # Now show the SOURCES
    # ====================
    foreach $key (keys %{$rh1}) {
        $val1 = ${$rh1}{$key};
        if (defined ${$rh2}{$key}) {
            $val2 = ${$rh2}{$key};
            if ( $key =~ /^CURR_/ ) {
                # ignore current items
            } else {
                if (defined ${$hrki}{$key}) {
                    $typ = ${$hrki}{$key};
                    if ($typ =~ /^<S>/) {
                        # done
                    } elsif ($typ =~ /^<N>/) {
                        # done
                    } else {
                        # it is an ARRAY
                        $acnt1 = scalar @{$val1};
                        $acnt2 = scalar @{$val2};
                        if ($key eq 'PROJECT_SRCS') {
                            # compare the SOURCES
                            prt( "$key:$typ F1=[$fil1]=$acnt1, F2=[$fil2]=$acnt2\n" );
                            compare_source_arrays($rh1,$rh2,$val1,$val2);
                        }
                    }
                }
            }
        }
    }
    prt("Done [$fil1], with [$fil2]\n");
}

sub compare_files($$) {
    my ($inf1,$inf2) = @_;
    if (!open INF, "<$inf1") {
        pgm_exit(1,"ERROR: Failed to OPEN fine [$inf1]!\n");
    }
    close INF;
    if (!open INF, "<$inf2") {
        pgm_exit(1,"ERROR: Failed to OPEN fine [$inf2]!\n");
    }
    close INF;
    my $rh1 = process_VCPROJ3($inf1);
    my $rh2 = process_VCPROJ3($inf2);
    prt( "Loaded the two files, now to compare...\n");
    compare_hash_results($rh1,$rh2);
}


#########################################
### MAIN ###
parse_args(@ARGV);
prt( "$pgmname: in [$cwd]: Comparing\n[$in_file1] with\n[$in_file2]...\n" );
compare_files($in_file1,$in_file2);
pgm_exit(0,"Normal exit(0)");
########################################
sub give_help {
    prt("$pgmname: version 0.0.1 2010-05-05\n");
    prt("Usage: $pgmname [options] in_file1 in_file2\n");
    prt("Options:\n");
    prt(" -h (-?)    = This help and exit 0\n");
    prt(" -l         = Set to load LOG at end.\n");
    prt(" -show=cfgs = Output the CONFIGS of each file.\n");
    prt("Purpose: Given intput of two vcproj files, compare these files,\n");
    prt("         and remprt differences.\n");
}
sub need_arg {
    my ($arg,@av) = @_;
    pgm_exit(1,"ERROR: [$arg] must have follwoing argument!\n")
        if (!@av);
}
sub parse_args {
    my (@av) = @_;
    my $cnt = 0;
    while (@av) {
        my $arg = $av[0];
        if ($arg =~ /-/) {
            my $sarg = substr($arg,1);
            $sarg = substr($sarg,1) while ($sarg =~ /-/);
            if (($sarg =~ /h/i)||($sarg eq '?')) {
                give_help();
                pgm_exit(0,"Help exit(0)");
            } elsif ($sarg =~ /^l/i) {
                $load_log = 1;
                prt("Set to load log at end\n");
            } elsif ($sarg eq 'show-cfgs') {
                $show_cfgs = 1;
                prt("Set to show CONFIGS...\n");
            } elsif ($sarg eq 'show-all') {
                $show_all = 1;
                prt("Set to show all source, not only any shared...\n");
            } else {
                pgm_exit(1,"ERROR: Invalid argument [$arg]! Try -?\n");
            }
        } else {
            if ($cnt == 0) {
                $in_file1 = $arg;
                prt("Set input 1 to [$in_file1]\n");
            } elsif ($cnt == 1) {
                $in_file2 = $arg;
                prt("Set input 2 to [$in_file2]\n");
            } else {
                pgm_exit(1,"ERROR: Only accepts 2 input files [$in_file1] [$in_file2]. Invalid argument additional [$arg]! Try -?\n");
            }
            $cnt++;
        }
        shift @av;
    }
    if (length($in_file1) == 0) {
        if ($debug_on && (-f $def_file1)) {
            $in_file1 = $def_file1;
            prt("Set input 1 to DEFAULT [$in_file1]\n");
        } else {
            pgm_exit(1,"ERROR: No input file 1!\n");
        }
    }
    if (length($in_file2) == 0) {
        if ($debug_on && (-f $def_file2)) {
            $in_file2 = $def_file2;
            prt("Set input 2 to DEFAULT [$in_file2]\n");
        } else {
            pgm_exit(1,"ERROR: No input file 2!\n");
        }
    }
    if (! -f $in_file1) {
       pgm_exit(1,"ERROR: Input file 1 NOT found!\n");
    }
    if (! -f $in_file2) {
       pgm_exit(1,"ERROR: Input file 2 NOT found!\n");
    }
    if ($debug_on && !$load_log) {
        $load_log = 1;
        prt("Set DEBUG load log at end\n");
    }
}

# eof - template.pl
