#!/usr/bin/perl -w
#   rp pat rpl file...
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
# This program takes a perl pattern and scans thru the files for it.  When it
# is  found,  the  file is "edited" so that all instances of the pattern $pat
# are replaced by the string $rpl. The editing is done "in place", by copying
# the  text  over to a /tmp/ file, and if any matches succeed, the /tmp/ file
# is copied back to the original file.  This method is like ed, and works for
# multiply-linked  files.  It also doesn't touch files that don't contain the
# pattern, so make still works properly.  At present, there is  no  provision
# for making a backup copy, but it'd be easy enough to do if needed.
#
# Note some special cases, based on the name that we're called by:
#   frp   matches only function calls, i.e., /\b$pat\s*\(/.
#   vrp   matches "variables", i.e., /\b$pat\b/
# If called by any other name will merely replace $pat with $rpl globally.
#
# We show the file names and the matches.  Perhaps we need a -v option ...
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #

($P = $0) =~ s/.*\///;
$Usage = "Usage: $P pattern replacement [filename]...\n";
#
# Check out the name we were called with:
#
$p1 = $p2 = $r1 = $r2 = '';
if (lc($P) eq 'frp') {	# frp matches function calls.
	$p1 = '\b';
	$p2 = '\s*\(';
	$r2 = '(';
} elsif (lc($P) eq 'vrp') {	# vrp matches variables.
	$p1 = '\b';
	$p2 = '\b';
}
$, = ' ';
defined($pat = shift) || die $Usage;
defined($rpl = shift) || die $Usage;

for $f (@ARGV) {
	if ($f) {
#		print "File : $f\n";
		if (open(F,"<$f")) {
			$t = "/tmp/fr_$$";
			if (open(T,">$t")) {
				$m = 0;		# Number of matches.
				while (<F>) {
					if (s/$p1$pat$p2/$r1$rpl$r2/g) {
						print;
						++$m;
					}
					print T;
				}
				close(F);
				close(T);
				if ($m) {
					print "=====>	$f\n";
					system "cp $t $f"; 
				}
				system "rm $t";
			} else {
				printf STDERR "Can't write \"$t\"\n";
			}
		} else {
			printf STDERR "Can't read \"$f\"\n";
		}
	}
}
