#!/perl -w
# NAME: amitems.pl
# AIM: Read a Makefile.am files, and hash the contents
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);

my $in_file = '';
my $load_log = 1;
my $skip_missing_cont = 0;

my $def_file = 'C:\FG\27\templist.txt';

my @warnings = ();
# forward
sub show_warnings($);

# debug
my $dbg_a01 = 0; # prt("[dbg_a01] IF:$lnn: [$line] ($inif)\n") if ($dbg_a01);
my $dbg_a02 = 0; # prt("[dbg_a02]$lnn: TARG [$line]\n") if ($dbg_a02); and MORE
my $dbg_a03 = 0; # prt( "[dbg_a03]:$bgnlnn:$lnn: [$line]\n" ) if ($dbg_a03); - show EACH LINE
my $dbg_a04 = 1; # prt("[dbg_a04] Current file [$curfile]\n") if ($dbg_a04);

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

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

sub show_warnings($) {
	my ($dbg) = shift;
    if (@warnings) {
        prt( "\nGot ".scalar @warnings." WARNINGS ...\n" );
        foreach my $line (@warnings) {
            prt("$line\n" );
        }
        prt("\n");
    } elsif ($dbg) {
        prt("\nNo warnings issued.\n\n");
    }
}

if (@ARGV) {
   $in_file = shift @ARGV;
} else {
   $in_file = $def_file;
}

if (! -f $in_file) {
   prt("ERROR: Unable to locate file [$in_file]! Check name, location...\n");
   exit(1);
}

sub is_equal_macro($) {
   my ($ln) = shift;
   return 1 if ($ln =~ /(\w+)\s*\+*=\s*(.*)\s*$/);
   return 0;
}

sub is_target_line($) {
   my ($ln) = shift;
   return 1 if ($ln =~ /^(\w|\.|-|\$|\(|\)|\/|\s)+\s*:/);
   return 0;
}

sub is_if_else_or_endif($) {
   my ($ln) = shift;
   return 1 if ($ln =~ /^if\s+/);
   return 2 if ($ln =~ /^else\s*/);
   return 3 if ($ln =~ /^endif\s*/);
   return 0;
}

sub process_file($) {
   my ($fil) = shift;
   if (!open INF, "<$fil") {
      prt("ERROR: Unable to open file [$fil]!\n");
      exit(1);
   }
   prt("Loading [$fil]...");
   my @lines = <INF>;
   close INF;
   my $lncnt = scalar @lines;
   prt(", got $lncnt lines to process...\n");
   my ($i,$line,$i2,$cont,$tmp,$lnn,$line2,$line3,$prev,$bgnlnn,$plnn,$inif,$liner);
   my ($curfile,$prevlr,$prevln);
   my %hash = ();
   $line = '';
   $inif = 0;
   $curfile = $fil;  # this is the current file
   for ($i = 0; $i < $lncnt; $i++) {
      $i2 = $i + 1;
      $lnn++;
      $prev = $line;
      $plnn = $bgnlnn;
      $prevlr = $liner;
      $prevln = $lnn;
      $liner = $lines[$i];       # get RAW line
      $line = trim_all($liner);  # and trimmed version
      next if (length($line) == 0); # ignore blanks
      $inif = 0 if ($liner =~ /^# EOF ===/);   # restart IF counter, if a NEW file
      if ($line =~ /^# Contents of (.+)\s*$/) {
         $curfile = $1;
         prt("[dbg_a04] Current file [$curfile]\n") if ($dbg_a04);
         $inif = 0 ;   # restart IF counter, if a NEW file
      }
      next if ($line =~ /^#/);   # ignore comments

      $bgnlnn = $lnn;   # keep where line assumed to BEGIN
      # get the FULL continuation lines
      while (($line =~ /\\$/)&&($i2 < $lncnt)) {
         $i++;
         $i2 = $i + 1;
         $lnn++;
         $line =~ s/\\$/ /;
         $liner = $lines[$i];
         $prevlr = $liner;
         $prevln = $lnn;
         $line2 = trim_all($liner);
         # QUESTION: Can continuation lines CROSS an 'if', 'else', 'endif' barrier
         # answer YES
         # last if (is_if_else_or_endif($liner)); # only test on RAW lines
         if ($skip_missing_cont) {
            if ( length($line2) && !($line2 =~ /\\$/) && ($i2 < $lncnt)) {
               # this was a good try, but caused lots of PROBLEMS
               $liner = trim_all($lines[$i2]);
               $line3 = trim_all($liner);
               if (length($line3) && ($line3 =~ /\\$/) && !is_equal_macro($line3)) {
                  prt("$lnn: Adding missing 'cont' [$line]+[$line2]\ since got line3 [$line3]\n");
                  $line2 .= "\\";   # artificially ADD continuation
               }
            }
         } elsif (!($line2 =~ /\\$/)) {
            # Known exception
            # Contents of C:\FG\27\terragear-cs\Makefile.am 
            # EXTRA_DIST = \
            #	README.plib README.SimGear \
            #	TerraGear.dsp TerraGear.dsw
            #	acinclude.m4 \
            if ($line2 =~ /TerraGear\.dsp TerraGear\.dsw/) {
               $line2 .= "\\";   # add it for the EXCEPTION KNOWN ONLY
            } elsif ($line2 =~ /-lsgbucket -lsgmisc -lsgdebug -lsgxml -lz/) {
               # C:\FG\27\terragear-cs\src\Prep\DemChop\Makefile.am
               $line2 .= "\\";   # add it for the EXCEPTIONS KNOWN ONLY
            } elsif ($line2 =~ /-lsgbucket -lsgmath -lsgmisc -lsgdebug -lsgxml -lz/) {
               # C:\FG\27\terragear-cs\src\Prep\DemChop\Makefile.am
               $line2 .= "\\";   # add it for the EXCEPTIONS KNOWN ONLY
            } elsif ($line2 =~ /-lgenpolyclip -lz/) {
               # C:\FG\27\terragear-cs\src\Prep\Photo\Makefile.am
               $line2 .= "\\";   # add it for the EXCEPTIONS KNOWN ONLY
            }
         }
         $line .= $line2;
      }

      prt( "[dbg_a03]:$bgnlnn:$lnn: [$line]\n" ) if ($dbg_a03);
      # now CHECK THE LINE
      if ($line =~ /(\w+)\s*\+*=\s*(.*)\s*$/) {
         # macro EQUALS
         $cont = $1;
         if (defined $hash{$cont}) {
            $hash{$cont}++;
         } else {
            $hash{$cont} = 1;
         }
      } elsif ($line =~ /^(\w|\.|-|\$|\(|\)|\/|\s)+\s*:/) {
         # eat lines until another target line or BLANK found,
         prt("[dbg_a02]$lnn: BEGIN TARG [$line]\n") if ($dbg_a02);
         $i++; # goto NEXT line
         for (; $i < $lncnt; $i++) {
            $i2 = $i + 1;
            $lnn++;
            $liner = $lines[$i];      # get RAW line
            $prevlr = $liner;
            $prevln = $lnn;
            $tmp = trim_all($liner);  # and trimmed version

            if ($liner =~ /^# EOF ===/) { # restart IF counter, if a NEW file
               prt("[dbg_a02]$lnn: END TARG on EOF [$tmp] [$line]\n") if ($dbg_a02);
               $inif = 0;
               # no need to back up - skip this line - but do it anyway
                $i-- if ($i); # back up to collect this line
                $lnn-- if ($lnn);
               last;
            }

            if (length($tmp) == 0) {
               prt("[dbg_a02]$lnn: END TARG on BLANK [$line]\n") if ($dbg_a02);
               # no need to back up - skip this line - but do it anyway
                $i-- if ($i); # back up to collect this line
                $lnn-- if ($lnn);
               last;
            }


            next if ($liner =~ /^#/);  # skip comment lines completely

            if (is_target_line($tmp)) {
                prt("[dbg_a02]$lnn: END TARG on next TARGET [$tmp] [$line]\n") if ($dbg_a02);
                $i-- if ($i); # back up to collect this line
                $lnn-- if ($lnn);
                last;
            }

            if ( !($liner =~ /^\t/) ) {
               # Does NOT commence with a TAB
               if (is_if_else_or_endif($liner)) {
                  # ok, just an 'if', 'else', 'endif'
                  if ($liner =~ /^if\s+/) {
                     $inif++;
                     prt("[dbg_a01] IF:$lnn: [$line] ($inif)\n") if ($dbg_a01);
                  } elsif ($liner =~ /^else\s*/) {
                     # skip else
                  } elsif ($liner =~ /^endif\s*/) {
                     # skip endif
                     $inif-- if ($inif);
                     prt("[dbg_a01] ENDIF:$lnn: [$line] ($inif)\n") if ($dbg_a01);
                  }
                  next;    # skip adding these these

               } else {
                  # NOT if/else/endif
                  if ( !($line =~ /\\$/) ) {
                     # ok, previous line added does NOT have continuation
                     prt("[dbg_a02]$lnn: END TARG on NO TAB [$tmp] [$line]\n") if ($dbg_a02);
                     $i-- if ($i); # back up to collect this line
                     $lnn-- if ($lnn);
                     last;
                  }
               }
            }

            # NO - THIS IS WRONG last if (is_if_else_or_endif($liner)); # only test on RAW lines eg
            # $(top_builddir)/lib/ca-bundle.h: Makefile.in Makefile
            #     @if test -f $@; then \
            #        chmod 0644 $@; \
            #     fi
            #   echo "/* This file is generated automatically */" > $@
            # if CABUNDLE
            #   echo '#define CURL_CA_BUNDLE @CURL_CA_BUNDLE@' >> $@
            # else
            #   echo '#undef CURL_CA_BUNDLE /* unknown */' >> $@
            # endif
            # NO THIS IS WRONG last if ($tmp =~ /^#/);
            $line .= " $tmp";
         }  # get TARGET lines loop
      } elsif ($line =~ /^if\s+(.+)\s*$/) {
         # skip if
         $inif++;
         prt("[dbg_a01] IF:$lnn: [$line] ($inif)\n") if ($dbg_a01);
      } elsif ($line =~ /^else\s*/) {
         # skip else
      } elsif ($line =~ /^endif\s*/) {
         # skip endif
         $inif-- if ($inif);
         prt("[dbg_a01] ENDIF:$lnn: [$line] ($inif)\n") if ($dbg_a01);
      } elsif ($line =~ /^include\s+/) {
         # skip include
      } else {
         prt("\nPREV $plnn:[$prev]\n");
         prt("RAW  $lnn: $prevlr");
         prt("$lnn: WHAT IS THIS? [$line]\n\n");
         pgm_exit(1,"");
      }
   }
   return \%hash;
}

sub show_ref_hash($) {
   my ($rh) = @_;
   my ($key,$val,@arr2,$flg,$wrap,$cnt);
   my @arr = sort keys(%{$rh});
   my $max = scalar @arr;
   my %h = ();
   prt("Got $max keys, as follows...\n");
   #foreach $key (keys %{$rh}) {
   $wrap = 0;
   foreach $key (@arr) {
      $val = ${$rh}{$key};
      prt( "$key $val " );
      @arr2 = split('_',$key);
      $cnt = scalar @arr2;
      if ($cnt > 1) {
         $flg = $arr2[-1];
         if (($key =~ /_$flg$/)&&($flg =~ /^[A-Z]+$/)) {
            $h{$flg} = 1;
         }
      }
      $wrap++;
      if ($wrap == 4) {
         prt("\n");
         $wrap = 0;
      }
   }
   prt("\n") if ($wrap);
   prt("Done $max keys...\n");
   $wrap = 0;
   $cnt = scalar keys(%h);
   prt("Got $cnt '_' items, as follows...\n");
   foreach $key (keys %h) {
      prt("_$key ");
      $wrap++;
      if ($wrap == 6) {
         prt("\n");
         $wrap = 0;
      }
   }
   prt("\n") if ($wrap);
}


if (length($in_file)) {
   my $ref_hash = process_file($in_file);
   show_ref_hash($ref_hash);
} else {
   prt( "$pgmname... Give the Makefile.am to process...\n" );
}

pgm_exit(0,"Normal Exit");

# eof
