#!/usr/bin/perl -w

# find unbalanced hf_ stuff (used but missing from the array)

use strict;

my $debug = 0;
# 0: off
# 1: specific debug
# 2: full debug

my $D;

my %elements;
my $element;
my %skip;

my $state;
my $newstate;
# "s_unknown",
# "s_declared",
# "s_used",
# "s_array",
# "s_usedarray",
# "s_error"

my $type;
# "t_declaration";
# "t_usage";
# "t_array";

my $restofline;
my $currfile = "";

my $comment = 0;

sub printprevfile {
	my $state;

	foreach $element (keys %elements) {
		$state = $elements{$element};
		$debug>=2 && print "$currfile, $element: PRINT $state\n";
		if ($state =~ "s_usedarray") {
			# Everything is fine
		} elsif ($state =~ "s_used") {
			print "NO ARRAY: $currfile, $element\n"
		} elsif ($state =~ "s_array") {
			print "Unused entry: $currfile, $element\n"
		} elsif ($state =~ "s_declared") {
			print "Declared only entry: $currfile, $element\n"
		} elsif ($state =~ "s_unknown") {
			print "UNKNOWN: $currfile, $element\n"
		} else {
			die "Impossible: State $state for $currfile, $element\n";
		}
	}
}

while (<>) {
	if ($currfile !~ /$ARGV/) {
		&printprevfile();
		# New file - reset array and state
		$currfile = $ARGV;
		%elements = ( );
		%skip = ( "hf_register_info" => 1 );
		$state = "s_unknown";
	}
	# opening then closing comment
	if (/(.*?)\/\*.*\*\/(.*)/) {
		$comment = 0;
		$_ = "$1$2";
	# closing then opening comment
	} elsif (/.*?\*\/(.*?)\/\*/) {
		$comment = 1;
		$_ = "$1";
	# opening comment
	} elsif (/(.*?)\/\*/) {
		$comment = 1;
		$_ = "$1";
	# closing comment
	} elsif (/\*\/(.*?)/) {
		$comment = 0;
		$_ = "$1";
	} elsif ($comment == 1) {
		next;
	}
	# unhandled: more than one complete comment per line

	chomp;
	$D = $_;

	# Read input
	if (/static\s+.*int\s+(hf_\w*)\s*=\s*-1\s*;/) {
		$element = $1;
		$type = "t_declaration";
		# ignore: declarations without any use are detected by the compiler
		next;
	# Skip function parameter declarations with hf_ names
	} elsif (/(int\s+?|int\s*?\*\s*?|hf_register_info\s+?|hf_register_info\s*?\*\s*?|->\s*?)(hf_\w*)\W(.*)/) {
		$element = $2;
		$restofline = $3;
		$debug && print "Setting skip for $element\n";
		$skip{$element} = 1;
		# Handle functions with multiple hf_ parameters
		while ($restofline =~ /(int\s+?|int\s*?\*\s*?|->\s*?)(hf_\w*)\W(.*)/) {
			$element = $2;
			$restofline = $3;
			$debug && print "Setting skip for $element\n";
			$skip{$element} = 1;
		}
		next;
	} elsif (/(\{|^)\s*?&\s*?(hf_\w*)\W+/) {
		$element = $2;
		$type = "t_array";
	# Order matters: catch all remaining hf_ lines
	} elsif (/\W(hf_\w*)\W/) {
		$element = $1;
		next if ($skip{$element});
		$type = "t_usage";
	} else {
		# current line is not relevant
		next;
	}

	# Get current state
	if (!defined($elements{$element})) {
		$state= "s_unknown";
	} else {
		$state = $elements{$element};
	}

	# current state + input ==> new state
	# we currently ignore t_declaration
	if ($state =~ "s_unknown" && $type =~ "t_usage") {
			$newstate = "s_used";
	} elsif ($state =~ "s_unknown" && $type =~ "t_array") {
			$newstate = "s_array";
	} elsif ($state =~ "s_used" && $type =~ "t_array") {
			$newstate = "s_usedarray";
	} elsif ($state =~ "s_array" && $type =~ "t_usage") {
			$newstate = "s_usedarray";
	} else {
		$newstate = $state;
	}
	$elements{$element} = $newstate;
	$debug>=2 && print "$currfile, $element: SET $state + $type => $newstate\n";
}
&printprevfile();

exit 0;

__END__
