#! /usr/bin/perl

use strict;
use warnings FATAL => 'all';


sub get_range($$) {
	$_ = shift;
	my $file = shift;
	my ($a, $b);

	if (! /^\d/) {
		my $t;
		($t, $_) = /(.)(.*)/;
		$file = ($t eq "a" || $t eq "A") ? 1 : 2;
	}
		
	if (/-/) {
		($a, $b) = split(/-/, $_);
	} else {
		if (/\.$/) {
			($a) = /(.*)./;
			$b = $a - 1;
		} else {
			$a = $b = $_;
		}
	}
	return ($file, $a - 1, $b - 1);
}


if ($#ARGV < 2) {
	print <<EOF;
Usage: copyreplace.pl FILE1 FILE2 RULE ...

RULE can be [a|A|b|B]RANGE_[a|A|b|B]RANGE, where "a" and "b" refer to FILE1 and
FILE2, respectively. Range can be A[_B] or A., where A and B are start and
end line numbers, respectively. "A." can be used to insert text at line A
instead of replacing line A. To insert text at the end of file, A should equal
to "number of lines + 1".

Examples:
	a3-7_b2-3
		Replace lines 2 -- 3 in FILE2 with lines 3 -- 7 from FILE1.

	a1_b9.
		Insert line 1 from FILE1 to line 9 at FILE2. Old line 9 in
		FILE2 will become line 10.
EOF

	exit(0);
}



my $filename1 = shift @ARGV;
my $filename2 = shift @ARGV;
my $file;

open($file, "< $filename1") or die "Cannot read $filename1";
my @o_file1 = <$file>;
close($file);

open($file, "< $filename2") or die "Cannot read $filename2";
my @o_file2 = <$file>;
close($file);

my @file1;
my @file2;
push(@file1, $_) foreach (@o_file1);
push(@file2, $_) foreach (@o_file2);

my (@index1, @index2);
push(@index1, $_) for (0 .. $#o_file1);
push(@index1, $#o_file1 + 1);
push(@index2, $_) for (0 .. $#o_file2);
push(@index2, $#o_file2 + 1);


while ($#ARGV >= 0) {
	my ($from, $to) = split(/_/, $ARGV[0]);
	my $t;
	if ($ENV{'DEBUG'}) { print "$from to $to\n"; }

	my ($from_file, $from_a, $from_b) = &get_range($from, 1);
	my ($to_file, $to_a, $to_b) = &get_range($to, 2);

	if ($ENV{'DEBUG'}) {
		print "from $from_file:$from_a-$from_b -> " .
				"$to_file:$to_a-$to_b\n";
	}

	my @src;
	if ($from_file == 1) {
		push(@src, $o_file1[$_])
			for ($index1[$from_a] .. $index1[$from_b]);
	} else {
		push(@src, $o_file2[$_])
			for ($index2[$from_a] .. $index2[$from_b]);
	}

	if ($ENV{'DEBUG'}) { print "---src---\n"; print foreach (@src); }

	my $to_len = $to_b - $to_a + 1;
	my $offset = $to_len - ($from_b - $from_a + 1);
	if ($to_file == 1) {
		splice(@file1, $index1[$to_a], $to_len, @src);
		$index1[$_] -= $offset for ($to_a + 1 .. $#index1);
	} else {
		splice(@file2, $index2[$to_a], $to_len, @src);
		$index2[$_] -= $offset for ($to_a + 1 .. $#index2);
	}

	shift @ARGV;
	if ($ENV{'DEBUG'}) { print "---\n"; print foreach (@file2); }
}

if ($ENV{'DEBUG'}) {
	print "---final---\n";
	print foreach (@file2);
	exit(0);
}

open($file, "> $filename1.out") or die "Cannot write $filename1.out";
print $file $_ foreach (@file1);
close($file);

open($file, "> $filename2.out") or die "Cannot write $filename2.out";
print $file $_ foreach (@file2);
close($file);
