#!/usr/bin/perl -w
# NAME: showdefs.pl
# AIM: Given a C/C++ page, show items like '#define FOO'
# 21/09/2010 geoff mclane http://geoffair.net/mperl
use strict;
use warnings;
use File::Basename;  # split path ($name,$dir,$ext) = fileparse($file [, qr/\.[^.]*/] )
use Cwd;
my $perl_dir = 'C:\GTools\perl';
unshift(@INC, $perl_dir);
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 $outfile = $perl_dir."\\temp.$pgmname.txt";
open_log($outfile);

# user variables
my $load_log = 0;
my $in_file = '';

my $debug_on = 0;
my $def_file = 'def_file';

my $dbg_02 = 0;

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

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

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


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

sub process_in_file($) {
    my ($inf) = @_;
    if (! open INF, "<$inf") {
        pgm_exit(1,"ERROR: Unable to open file [$inf]\n"); 
    }
    my @lines = <INF>;
    close INF;
    my $lncnt = scalar @lines;
    prt("Processing $lncnt lines, from [$inf]...\n");
    my ($line,$def,$lnn,@arr);
    my ($ifitem,$defitem,$impitem,$pragitem,$erritem,$unditem,$useitem);
    my ($i,$key,$cnt,$val,$ra);
    $lnn = 0;
    my %defshash = ();
    my %dvalhash = ();
    foreach $line (@lines) {
        chomp $line;
        $lnn++;
        if ($line =~ /^\s*\#\s*define\s+(.+)$/) {
            $defitem = $1;
    		$defitem =~ s/\/\/.*$//;
    		$defitem =~ s/\/\*.*$//;
            $defitem = trim_all($defitem);
            @arr = split(/\s+/,$defitem);
            $key = $arr[0];
            $val = '';
            $cnt = scalar @arr;
            for ($i = 1; $i < $cnt; $i++) {
                $val .= ' ' if (length($val));
                $val .= $arr[$i];
            }
            $defshash{$key} = $val;
            $dvalhash{$val} = [] if (!defined $dvalhash{$val});
            $ra = $dvalhash{$val};
            push(@{$ra},$key);
            ###prt("$lnn: #define [$defitem]\n");
            prt("$lnn: #define [$key $val]\n");
        } elsif ($line =~ /^\s*\#\s*if\s+(.+)$/) {
            $ifitem = $1;
    		$ifitem =~ s/\/\/.*$//;
    		$ifitem =~ s/\/\*.*$//;
            prt("$lnn: #if [$ifitem]\n") if ($dbg_02);
        } elsif ($line =~ /^\s*\#\s*ifdef\s+(.+)$/) {
            $ifitem = $1;
    		$ifitem =~ s/\/\/.*$//;
    		$ifitem =~ s/\/\*.*$//;
            prt("$lnn: #ifdef [$ifitem]\n") if ($dbg_02);
        } elsif ($line =~ /^\s*\#\s*ifndef\s+(.+)$/) {
            $ifitem = $1;
    		$ifitem =~ s/\/\/.*$//;
    		$ifitem =~ s/\/\*.*$//;
            prt("$lnn: #ifndef [$ifitem]\n") if ($dbg_02);
        } elsif ($line =~ /^\s*\#\s*else\s+(.+)$/) {
            $ifitem = $1;
    		$ifitem =~ s/\/\/.*$//;
    		$ifitem =~ s/\/\*.*$//;
            prt("$lnn: #else [$ifitem]\n") if ($dbg_02);
        } elsif ($line =~ /^\s*\#\s*elif\s+(.+)$/) {
            $ifitem = $1;
    		$ifitem =~ s/\/\/.*$//;
    		$ifitem =~ s/\/\*.*$//;
            prt("$lnn: #elif [$ifitem]\n") if ($dbg_02);
        } elsif ($line =~ /^\s*\#\s*endif\s+(.+)$/) {
            $ifitem = $1;
    		$ifitem =~ s/\/\/.*$//;
    		$ifitem =~ s/\/\*.*$//;
            prt("$lnn: #endif [$ifitem]\n") if ($dbg_02);
        } elsif ($line =~ /^\s*\#\s*import\s+(.+)$/) {
            $impitem = $1;
    		$impitem =~ s/\/\/.*$//;
    		$impitem =~ s/\/\*.*$//;
            prt("$lnn: #import [$impitem]\n") if ($dbg_02);
        } elsif ($line =~ /^\s*\#\s*pragma\s+(.+)$/) {
            $pragitem = $1;
    		$pragitem =~ s/\/\/.*$//;
    		$pragitem =~ s/\/\*.*$//;
            prt("$lnn: #pragma [$ifitem]\n") if ($dbg_02);
        } elsif ($line =~ /^\s*\#\s*error\s+(.+)$/) {
            $erritem = $1;
    		$erritem =~ s/\/\/.*$//;
    		$erritem =~ s/\/\*.*$//;
            prt("$lnn: #error [$erritem]\n") if ($dbg_02);
        } elsif ($line =~ /^\s*\#\s*undef\s+(.+)$/) {
            $unditem = $1;
    		$unditem =~ s/\/\/.*$//;
    		$unditem =~ s/\/\*.*$//;
            prt("$lnn: #undef [$unditem]\n") if ($dbg_02);
        } elsif ($line =~ /^\s*\#\s*use\s+(.+)$/) {
            $useitem = $1;
    		$useitem =~ s/\/\/.*$//;
    		$useitem =~ s/\/\*.*$//;
            prt("$lnn: #use [$useitem]\n") if ($dbg_02);
        }
    }
    #@arr = sort keys %defshash;
    #foreach $key (@arr) {
    #    $val = $defshash{$key};
    #    prt("$key $val\n");
    #}
}

#########################################
### MAIN ###
parse_args(@ARGV);
process_in_file($in_file);
pgm_exit(0,"Normal exit(0)");
########################################
sub give_help {
    prt("$pgmname: version 0.0.1 2010-09-11\n");
    prt("Usage: $pgmname [options] in-file\n");
    prt("Options:\n");
    prt(" --help (-h or -?) = This help, and exit 0.\n");
    prt(" --verbose    (-v) = Show all precompile directives, #if, #ifdef, etc\n");
    prt("Purpose:\n");
    prt(" Given an input of a C/C++ file, output all the '#define FOO' etries.\n");
}
sub need_arg {
    my ($arg,@av) = @_;
    pgm_exit(1,"ERROR: [$arg] must have following argument!\n") if (!@av);
}

sub parse_args {
    my (@av) = @_;
    my ($arg,$sarg);
    while (@av) {
        $arg = $av[0];
        if ($arg =~ /^-/) {
            $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 =~ /^v/i) {
                $dbg_02 = 1;
            } else {
                pgm_exit(1,"ERROR: Invalid argument [$arg]! Try -?\n");
            }
        } else {
            $in_file = $arg;
            prt("Set input to [$in_file]\n");
        }
        shift @av;
    }

    if ((length($in_file) ==  0) && $debug_on) {
        $in_file = $def_file;
    }
    if (length($in_file) ==  0) {
        pgm_exit(1,"ERROR: No input files found in command!\n");
    }
    if (! -f $in_file) {
        pgm_exit(1,"ERROR: Unable to find in file [$in_file]! Check name, location...\n");
    }
}

# eof - template.pl
