#! /usr/bin/perl

@findopts = ();
@grepopts = ();
$pattern  = "";
$dryrun   = 0; 
$show_errors  = 0; 

# Any option arguments (e.g. beginning with a '-') are passed to
# grep, except:
#
# * -s is a shorthand for a certain file spec.
# * --, if present, denotes end of grep options.  E.g. this allows
#   the user to search for a string that begins with a '-'.

while (@ARGV > 0) {
	unless ($ARGV[0] =~ m/^-/) {
		last;
	}
	if ($ARGV[0] =~ m/^--$/) {
		shift @ARGV;
		last;
	}
	if ($ARGV[0] =~ m/^-s$/) {
		shift @ARGV;
		push @findopts,
"\\( -name '*.[chsS]' -o -name '*.cpp' -o -name '*.cc' -o -name '[Mm]akefile' -o -name '*.mki'";
	}
	elsif ($ARGV[0] =~ m/^-X$/) {
		shift @ARGV;
		$dryrun = 1;
	}
	elsif ($ARGV[0] =~ m/^-E$/) {
		shift @ARGV;
		$show_errors = 1;
	}
	else {
		push @grepopts, shift @ARGV;
	}
}

# There must at least be a search pattern.
if (@ARGV == 0) {
	print "$0:  Requires at least one non-option argument.\n";
	usage();
}
$pattern = shift @ARGV;

# Remaining arguments are filespecs.
while (@ARGV > 0) {
	if (@findopts) {
		push @findopts, "-o";
	}
	else {
		push @findopts, "\\(";
	}
	push @findopts, "-name";
	$arg = shift @ARGV;
	push @findopts, "'$arg'";
}

if (@findopts) {
	push @findopts, "\\)";
}


$cmd = "find . -type f @findopts -exec egrep @grepopts '$pattern' {} /dev/null \\;";
if (!$show_errors) {
	$cmd = $cmd . " 2> /dev/null";
}
if ($dryrun) {
	print "findopts: <<@findopts>>\n";
	print "grepopts: <<@grepopts>>\n";
	print "pattern:  <<$pattern>>\n";
	print "command:\n";
	print "$cmd\n";
}
else {
	system("$cmd");
}

sub usage
{
	print "Usage: $0 [-s | grep options] {search pattern} [filename patterns ...]\n";
	print "  Recursively greps for the specified search pattern in files\n";
	print "  whose names match specified patterns.  Single quotes are required\n";
	print "  around any patterns with '*' or '?' in them.\n";
	print 
	"  The -s argument is simply a shorthand for the filename pattern '*.[chsS]'.\n";
	print "  If the filename patterns are omitted, all files are searched.\n";
	print "  Any argument begins with a '-' is considered to be an argument\n";
	print "  to grep, not a filename pattern.\n";
	print "  Example:  $0 my_function '*.c' '*.h'\n";
	print "  Example:  $0 -s my_function \n";
	print "  Example:  $0 -i -s my_function \n";
	print "  Example:  $0 some_string \n";

	exit(1);
}
