#!/perl -w
# NAME: cmpini.pl
# AIM: Compare 2 INI files, showing same, different and missing items ...
# 30/12/2009 - minor update
# 19/02/2008 geoff mclane http://geoffair.net/mperl 
use strict;
use warnings;
unshift(@INC, 'C:/GTools/perl');
require 'logfile.pl' or die "Unable to load logfile.pl ...\n";
# log file stuff
my ($LF);
my $pgmname = $0;
if ($pgmname =~ /(\\|\/)/) {
	my @tmpsp = split(/(\\|\/)/,$pgmname);
	$pgmname = $tmpsp[-1];
}
my $perl_root = 'C:\GTools\perl';
my $outfile = $perl_root."\\temp.$pgmname.txt";
open_log($outfile);

# features
my $load_log = 0;
my $ignore_comments = 1;

# debug
my $dbg0 = 1;  # use DEFAULT
my $dbg1 = 0;	# show 	prt( "$tag1=$item1 - DUE SECTION NOT IN 2\n" ) if ($dbg1);

#my $def_file1 = "C:\\HOMEPAGE\\HOMnew\\php5-new.ini";
my $def_file1 = "C:\\HOMEPAGE\\HOMnew\\shop\\php.ini.sample";
my $def_file2 = "C:\\HOMEPAGE\\HOMnew\\shop\\php5.ini.sample";

#my $def_file1 = "C:\\GTools\\tools\\BglView2\\Bv2-200.ini";
#my $def_file2 = "C:\\GTools\\tools\\BglView2\\BglView2.ini";

my $in_file1 = "";
my $in_file2 = "";
my @lines11 = ();
my @lines22 = ();

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

sub give_help($) {
   my ($arg) = @_;
   prt("$pgmname: Version 0.0.1 2009/12/30\n" );
   prt("Will compare two INI type files, and show the different\n");
   prt("parameters in each.\n");
   prt("Usage: in_file_1 in_file_2 [Options]\n");
   prt("Options:\n");
   prt(" -? -h -v - This output, and exit.\n");
   prt(" -l       - Set to load log at end.\n");
   pgm_exit(0,"Exit on arg [$arg]");
}

sub sectionin2($) {
	my ($s) = shift;
	my $sz = scalar @lines22;
	for (my $i = 0; $i < $sz; $i++) {
		my $itm = $lines22[$i][0];
		if ($itm =~ /^\[(.+)\]$/) {
			my $sec = $1;
			if ($sec eq $s) {
				return $i;
			}
		}
	}
	return -1;
}

sub itemin2($$) {
	my ($t, $s) = @_;
	my $sz = scalar @lines22;
   my ($insect,$foundsect,$itm,$sec2,$tag2,$item2);
	$insect = 1;   # assume in default section [PHP]
   $foundsect = 0;
	for (my $i = 0; $i < $sz; $i++) {
		$itm = $lines22[$i][0];
		if ($itm =~ /^\[(.+)\]$/) {
         $foundsect = 1;
			my $sec2 = $1;
			if ($sec2 eq $s) {
				$insect = 1;
			} else {
				$insect = 0;
			}
		#} elsif ($itm =~ /^(.+)=(.+)$/) {
		} elsif ($itm =~ /^\s*(\S+)\s*=\s*(\S+)\s*$/) {
			$tag2 = $1;
			$item2 = $2;
			if ($tag2 eq $t) {
				if ($insect || ($foundsect == 0)) {
					return $i;
				}
			}
		}
	}
	return -1;
}

sub item3in2($$$) {
	my ($p, $t, $s) = @_;
	my $sz = scalar @lines22;
   my ($insect,$foundsect,$itm,$sec2,$tag2,$item2,$pre);
	$insect = 1;   # assume in default section [PHP]
   $foundsect = 0;
	for (my $i = 0; $i < $sz; $i++) {
		$itm = $lines22[$i][0];
		if ($itm =~ /^\[(.+)\]$/) {
         $foundsect = 1;
			my $sec2 = $1;
			if ($sec2 eq $s) {
				$insect = 1;
			} else {
				$insect = 0;
			}
      } elsif ($itm =~ /^\s*(\S+)\s+(\S+)\s*=\s*(\S+)\s*$/) {
         $pre   = trim_all($1);
			$tag2  = trim_all($2);
			$item2 = trim_all($3);
			if (($pre eq $p) && ($tag2 eq $t)) {
				if ($insect || ($foundsect == 0)) {
					return $i;
				}
			}
		}
	}
	return -1;
}

sub process_files($$) {
   my ($inf1,$inf2) = @_;
   my ($line1, $line2, $sec1, $sec2, $tag1, $item1, $i1, $i2, $fnd1, $fnd2, $tag2, $item2);
   my ($lnnum1, $lnnum2);
   my ($hadsec1,@lines1,@lines2,$fcnt1,$fcnt2);
   my ($pre1,$pre2);
   if (open INF1, "<$inf1") {
      @lines1 = <INF1>;
      close INF1;
      if (open INF2, "<$inf2") {
         @lines2 = <INF2>;
         close INF2;
         $fcnt1 = scalar @lines1;
         $fcnt2 = scalar @lines2;
         prt( "$inf1 had $fcnt1 lines ...\n" );
         prt( "$inf2 had $fcnt2 lines ...\n" );
         # Tidy up the LISTS - remove blanks, and comments
         # =======================================================
         $lnnum1 = 0;
         foreach $line1 (@lines1) {
            $lnnum1++;
            chomp $line1;
            $line1 = trim_all($line1);
            next if (length($line1) == 0);
            next if ($ignore_comments && ($line1 =~ /^\s*;/));
            push(@lines11,[$line1, 0, $lnnum1, 0]);
         }
         $lnnum2 = 0;
         foreach $line2 (@lines2) {
            $lnnum2++;
            chomp $line2;
            $line2 = trim_all($line2);
            next if (length($line2) == 0);
            next if ($ignore_comments && ($line2 =~ /^\s*;/));
            push(@lines22,[$line2, 0, $lnnum2, 0]);
         }
         $fcnt1 = scalar @lines11;
         $fcnt2 = scalar @lines22;
         prt( "Adjusted to $fcnt1, $fcnt2 resp...\n" );
         # =======================================================

         $fnd1 = -1;
         $lnnum1 = 0;
         prt( "\nProcessing LIST 1 for non-matched items ...\n" );
         $sec1 = 'PHP'; # default SECTION, until another encountered
         $hadsec1 = 0;
         for ($i1 = 0; $i1 < $fcnt1; $i1++) {
            $lnnum1 = $lines11[$i1][2];
            $line1 = $lines11[$i1][0];
            if ($line1 =~ /^\[(.+)\]$/) {
               $sec1 = $1;
               $hadsec1 = 1;  # mark HAD a section
               prt( "Section [$sec1] ... " );
               $fnd1 = sectionin2($sec1);
               if ($fnd1 == -1) {
                  prt( "SECTION [$sec1] NOT FOUND in 2!" );
               } else {
                  $lines22[$fnd1][1] = 1;	# show as FOUND
                  $lnnum2 = $lines22[$fnd1][2];
               }
               prt("\n");
            } elsif ($line1 =~ /^\s*(\S+)\s*=\s*(\S+)\s*$/) {
               $tag1  = trim_all($1);
               $item1 = trim_all($2);
               $fnd2 = itemin2( $tag1, $sec1 );
               if ($hadsec1 && ($fnd1 == -1)) {
                  if ($fnd2 == -1) {
                     prt( "$tag1=$item1 - DUE SECTION [$sec1] NOT IN 2\n" ) if ($dbg1);
                  } else {
                     $line2 = $lines22[$fnd2][0];
                     if ($line2 =~ /^\s*(\S+)\s*=\s*(\S+)\s*$/) {
                        $tag2  = trim_all($1);
                        $item2 = trim_all($2);
                        if (($tag1 eq $tag2)&&($tag1 eq $tag2)) {
                           prt( "Found: [$tag1] = [$item1] - SECTION [$sec1] NOT IN 2\n" );
                        } else {
                           prt( "[$tag1] = [$item1] - DUE SECTION [$sec1] NOT IN 2, but FOUND [$tag2] = [$item2]\n" );
                        }
                     } else {
                        prt( "[$tag1] = [$item1] - DUE SECTION [$sec1] NOT IN 2, but FOUND line[$line2]\n" );
                     }
                     $lines22[$fnd2][1] = 2;	# mark item matched
                  }
               } else {
                  if ($fnd2 == -1) {
                     prt( "$tag1=$item1 - ITEM NOT FOUND IN 2\n" );
                  } else {
                     $line2 = $lines22[$fnd2][0];
                     $lnnum2 = $lines22[$fnd2][2];
                     $lines22[$fnd2][1] = 3;	# mark as matched
                     #if ($line2 =~ /^(.+)=(.+)$/) {
                     if ($line2 =~ /^\s*(\S+)\s*=\s*(\S+)\s*$/) {
                        $tag2  = trim_all($1);
                        $item2 = trim_all($2);
                        if ($tag1 ne $tag2) {
                           prt( "ERROR: FAILED TO GET TAG $tag1 vs $tag2!!!\n" );
                        } else {
                           if ($item1 eq $item2) {
                              $lines22[$fnd2][1] = 2;	# mark SAME
                           } else {
                              prt( "DIFF: $tag1 = $item1 vs $item2 ... ($lnnum1/$lnnum2)\n" );
                              $lines22[$fnd2][1] = 4;	# mark DIFFERENT
                           }
                        }
                     } else {
                        prt( "ERROR: $line2 - WHAT IS THIS!\n" );
                     }
                  }
               }
            } elsif ($line1 =~ /^\s*(\S+)\s+(\S+)\s*=\s*(\S+)\s*$/) {
               $pre1  = trim_all($1);
               $tag1  = trim_all($2);
               $item1 = trim_all($3);
               $fnd2 = item3in2( $pre1, $tag1, $sec1 );
               if ($hadsec1 && ($fnd1 == -1)) {
                  if ($fnd2 == -1) {
                     prt( "$pre1 $tag1=$item1 - DUE SECTION [$sec1] NOT IN 2\n" ) if ($dbg1);
                  } else {
                     $line2 = $lines22[$fnd2][0];
                     if ($line2 =~ /^\s*(\S+)\s+(\S+)\s*=\s*(\S+)\s*$/) {
                        $pre2  = trim_all($1);
                        $tag2  = trim_all($2);
                        $item2 = trim_all($3);
                        if (($pre1 eq $pre2)&&($tag1 eq $tag2)&&($tag1 eq $tag2)) {
                           prt( "Found: [$pre1] [$tag1] = [$item1] - SECTION [$sec1] NOT IN 2\n" );
                        } else {
                           prt( "[$pre1] [$tag1] = [$item1] - DUE SECTION [$sec1] NOT IN 2, but FOUND [$pre2] [$tag2] = [$item2]\n" );
                        }
                     } else {
                        prt( "[$pre1] [$tag1] = [$item1] - DUE SECTION [$sec1] NOT IN 2, but FOUND line[$line2]\n" );
                     }
                     $lines22[$fnd2][1] = 2;	# mark item matched
                  }
               } else {
                  if ($fnd2 == -1) {
                     prt( "$pre1 $tag1 = $item1 - ITEM NOT FOUND IN 2\n" );
                  } else {
                     $line2 = $lines22[$fnd2][0];
                     $lnnum2 = $lines22[$fnd2][2];
                     $lines22[$fnd2][1] = 3;	# mark as matched
                     #if ($line2 =~ /^(.+)=(.+)$/) {
                     if ($line2 =~ /^\s*(\S+)\s+(\S+)\s*=\s*(\S+)\s*$/) {
                        $pre2  = trim_all($1);
                        $tag2  = trim_all($2);
                        $item2 = trim_all($3);
                        if (($pre1 ne $pre2)||($tag1 ne $tag2)) {
                           prt( "ERROR: FAILED TO GET TAG $tag1 vs $tag2!!! $pre1 vs $pre2\n" );
                        } else {
                           if ($item1 eq $item2) {
                              $lines22[$fnd2][1] = 2;	# mark SAME
                           } else {
                              prt( "DIFF: $pre1 $tag1 = $item1 vs $item2 ... ($lnnum1/$lnnum2)\n" );
                              $lines22[$fnd2][1] = 4;	# mark DIFFERENT
                           }
                        }
                     } else {
                        prt( "ERROR: $line2 - WHAT IS THIS!\n" );
                     }
                  }
               }
            } else {
               prt( "$line1 - WHAT IS THIS?\n" );
            }
         }
         prt( "\nProcessing LIST 2 for non-matched items ...\n" );
         for ($i2 = 0; $i2 < $fcnt2; $i2++) {
            $line2 = $lines22[$i2][0];
            if ($lines22[$i2][1] == 0) {
               $lnnum2 = $lines22[$i2][2];
               prt( "$line2 - NOT FOUND IN 1! ($lnnum2)\n" );
            }
         }
      } else {
         prt( "ERROR: Unable to open $inf2 ... $! ...\n" );
         pgm_exit(1,"No input file 2\n");
      }
   } else {
      prt( "ERROR: Unable to open [$inf1] ... $! ...\n" );
      pgm_exit(1,"No input file 1\n");
   }
}

# ############################
# MAIN #

parse_args(@ARGV);

process_files($in_file1,$in_file2);

pgm_exit(0,"Normal exit");

# ############################
# =====================
sub parse_args {
   my (@av) = @_;
   my ($arg,$cnt);
   $cnt = 0;
   while (@av) {
      $arg = $av[0];
      if ($arg =~ /^-/) {
         if ($arg =~ /^-l/) {
            $load_log = 1;
            prt("Setting load log at end...\n");
         } elsif (($arg =~ /^-?/) || ($arg =~ /^-h/) || ($arg =~ /^-v/)) {
            give_help($arg);
         } else {
            pgm_exit(1,"ERROR: Unknown options [$arg]\n");
         }
      } else {
         if ($cnt == 0) {
            $in_file1 = $arg;
            prt("Setting in file 1 to [$in_file1]\n");
         } elsif ($cnt == 1) {
            $in_file2 = $arg;
            prt("Setting in file 2 to [$in_file2]\n");
         } else {
            pgm_exit(1,"ERROR: Already have 1[$in_file1], and 2[$in_file2]! WHAT IS THIS? [$arg]");
         }
         $cnt++;
      }
      shift @av;
   }
   if ($dbg0) {
      $in_file1 = $def_file1 if (length($in_file1) == 0);
      $in_file2 = $def_file2 if (length($in_file2) == 0);
   }
}

# eof - cmpini.pl
