#!/usr/bin/perl

# ----------------------------------------------------------------
# John Kerl
# kerl.john.r@gmail.com
# 2002/12/01
#
# Does a global search and replace for patterns in specified files.
# Useful for heavy-duty reworking of source code.
#
# Example:
#
#   mrepl old_name:new_name YuckyStyle:nice_style Crapoli:marvy */*.[ch]
#
# would replace "old_name" with "new_name", "YuckyStyle" with "nice_style"
# and "Crapoli" with "marvy" in all .c and .h files in all subdirectories
# of the current directory.
# ----------------------------------------------------------------

my @old_new_pairs = ();
my @file_names = ();
my $word_match = 0;

for my $arg (@ARGV) {
	if ($arg eq "-w") {
		$word_match = 1;
	}
	elsif ($arg =~ m/:/) {
		push @old_new_pairs, $arg;
	}
	else {
		push @file_names, $arg;
	}
}

$usage_string = "Usage: $0 {old:new} {old:new} {old:new ...} {file names ... }\n";
die $usage_string unless @file_names;
die $usage_string unless @old_new_pairs;

$num_files = @file_names;


for my $file_name (@file_names) {
	next if -d $file_name;

	print "." if ($num_files > 1);

	$temp_name = $file_name . ".repl";

	if (!open(FILEHANDLE, $file_name)) {
		print "Couldn't open file \"$file_name\"; skipping.\n";
		next;
	}
	$mode = (stat($file_name))[2] & 07777;

	if (!open(TEMPHANDLE, ">$temp_name")) {
		print "Couldn't open file \"$temp_name\"; skipping.\n";
		close FILEHANDLE;
		next;
	}

	while ($line = <FILEHANDLE>) {
		for my $old_new_pair (@old_new_pairs) {
			my ($oldpat, $newpat) = split /:/, $old_new_pair;
			if ($word_match) {
				$line =~ s/\b$oldpat\b/$newpat/g;
			}
			else {
				$line =~ s/$oldpat/$newpat/g;
			}
		}
		print TEMPHANDLE $line;
	}

	close FILEHANDLE;
	close TEMPHANDLE;
	chmod $mode, $temp_name;

	if (!rename($temp_name, $file_name)) {
		warn "Cannot rename $temp_name to $file_name: $!\n";
	}
}
print "\n";
