#!/usr/bin/perl -w

use strict;
my $filename;
my @lines;
my $linesinfile=0;

foreach my $file (@ARGV) {
	process ($file)
		or warn "Couldn't check file $file: $!";
}

sub search {
	my $regexp=shift;
	my $text=shift;
	my $hits=0;
	my $linenr=0;

	foreach my $line (@lines) {
		$linenr++;
		if ($line=~$regexp) {
			$hits++;
			if ($hits==1) {
				print $text
			}
			print "$line\n";
		}
	}
	if ($hits!=0) {
	    print ("\n");
	}
}

sub process {
	my $linenr=0;
	my $hits=0;

	$filename=shift;

	print "Checking $filename\n";
	system("cp $filename findbug.$$.c");
	system("indent -kr findbug.$$.c");

	return undef unless $filename;

	open INPUT, "findbug.$$.c"
		or return undef;

	while(!eof INPUT) {
		my $input=<INPUT>;
		chomp $input;
		push @lines, $input;
		$linesinfile++;
	}
	close INPUT;
	system("rm -f findbug.$$.c findbug.$$.c~");

#  TODO
#	if !A && B    should be if (!(A && B))

	# noisy
#	search(qr/strcpy|sprintf/, "Found usage of unsafe string functions:\n");
#	search(qr/\/tmp\/|mktemp/, "Found usage of insecure /tmp files\n");

#search(qr/open.*\(.*,[.*]O_CREAT[[:space:]]\)/, "Found open with O_CREAT and no mode.\n");
#search(qr/open.*,.*O_CREAT\)/, "Found open with O_CREAT and no mode.\n");
	search(qr/open.*\(.*,.*O_CREAT[^,]*\);/, "Found open with O_CREAT and no mode.\n");
	search(qr/memset.*\,(\ |)(0x|)0(\ |0|)\);/, "Found memset with swapped arguments.\n");
#search(qr/memset.*\,(\ |)1(\ |)\);/, "Found suspicious single byte memset.\n");
#	search(qr/![a-zA-Z0-9_ ]+(\|[^|]|\&[^&])|([^|]\||[^&]\&) *!/, "Possible boolean logic bug.\n");
	search(qr/\tif(\ |)\(.*\)(\ |)(\|\&)\ /, "Found an if with suspect looking boolean logic\n");
	search(qr/\tif[[:space:]]*\([^\)]*\)[[:space:]]*\;$/, "if with ; at EOL!\n");
	search(qr/\tfor[[:space:]]*\([^\)]*\)[[:space:]]*\;$/, "for with ; at EOL!\n");
	search(qr/\twhile[[:space:]]*\([^\)]*\)[[:space:]]*\;$/, "while with ; at EOL!\n");

    return 1;
}

