181404Speter#! @PERL@
281404Speter
3175261Sobrien# Copyright (C) 1995-2005 The Free Software Foundation, Inc.
4175261Sobrien
5175261Sobrien# This program is free software; you can redistribute it and/or modify
6175261Sobrien# it under the terms of the GNU General Public License as published by
7175261Sobrien# the Free Software Foundation; either version 2, or (at your option)
8175261Sobrien# any later version.
9175261Sobrien#
10175261Sobrien# This program is distributed in the hope that it will be useful,
11175261Sobrien# but WITHOUT ANY WARRANTY; without even the implied warranty of
12175261Sobrien# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13175261Sobrien# GNU General Public License for more details.
14175261Sobrien
1581404Speter# Merge conflicted ChangeLogs
1681404Speter# tromey Mon Aug 15 1994
1781404Speter
1881404Speter# Usage is:
1981404Speter#
2081404Speter#	cl-merge [-i] file ...
2181404Speter#
2281404Speter# With -i, it works in place (backups put in a ~ file).  Otherwise the
2381404Speter# merged ChangeLog is printed to stdout.
2481404Speter
2581404Speter# Please report any bugs to me.  I wrote this yesterday, so there are no
2681404Speter# guarantees about its performance.  I recommend checking its output
2781404Speter# carefully.  If you do send a bug report, please include the failing
2881404Speter# ChangeLog, so I can include it in my test suite.
2981404Speter#
3081404Speter# Tom
3181404Speter# ---
3281404Speter# tromey@busco.lanl.gov             Member, League for Programming Freedom
3381404Speter# Sadism and farce are always inexplicably linked.
3481404Speter#	-- Alexander Theroux
3581404Speter
3681404Speter
3781404Speter# Month->number mapping.  Used for sorting.
3881404Speter%months = ('Jan', 0,
3981404Speter	   'Feb', 1,
4081404Speter	   'Mar', 2,
4181404Speter	   'Apr', 3,
4281404Speter	   'May', 4,
4381404Speter	   'Jun', 5,
4481404Speter	   'Jul', 6,
4581404Speter	   'Aug', 7,
4681404Speter	   'Sep', 8,
4781404Speter	   'Oct', 9,
4881404Speter	   'Nov', 10,
4981404Speter	   'Dec', 11);
5081404Speter
5181404Speter# If '-i' is given, do it in-place.
5281404Speterif ($ARGV[0] eq '-i') {
5381404Speter    shift (@ARGV);
5481404Speter    $^I = '~';
5581404Speter}
5681404Speter
5781404Speter$lastkey = '';
5881404Speter$lastval = '';
5981404Speter$conf = 0;
6081404Speter%conflist = ();
6181404Speter
6281404Speter$tjd = 0;
6381404Speter
6481404Speter# Simple state machine.  The states:
6581404Speter#
6681404Speter# 0	Not in conflict.  Just copy input to output.
6781404Speter# 1	Beginning an entry.  Next non-blank line is key.
6881404Speter# 2	In entry.  Entry beginner transitions to state 1.
6981404Speterwhile (<>) {
7081404Speter    if (/^<<<</ || /^====/) {
7181404Speter	# Start of a conflict.
7281404Speter
7381404Speter	# Copy last key into array.
7481404Speter	if ($lastkey ne '') {
7581404Speter	    $conflist{$lastkey} = $lastval;
7681404Speter
7781404Speter	    $lastkey = '';
7881404Speter	    $lastval = '';
7981404Speter	}
8081404Speter
8181404Speter	$conf = 1;
8281404Speter    } elsif (/^>>>>/) {
8381404Speter	# End of conflict.  Output.
8481404Speter
8581404Speter	# Copy last key into array.
8681404Speter	if ($lastkey ne '') {
8781404Speter	    $conflist{$lastkey} = $lastval;
8881404Speter
8981404Speter	    $lastkey = '';
9081404Speter	    $lastval = '';
9181404Speter	}
9281404Speter
9381404Speter	foreach (reverse sort clcmp keys %conflist) {
9481404Speter	    print STDERR "doing $_" if $tjd;
9581404Speter	    print $_;
9681404Speter	    print $conflist{$_};
9781404Speter	}
9881404Speter
9981404Speter	$lastkey = '';
10081404Speter	$lastval = '';
10181404Speter	$conf = 0;
10281404Speter	%conflist = ();
10381404Speter    } elsif ($conf == 1) {
10481404Speter	# Beginning an entry.  Skip empty lines.  Error if not a real
10581404Speter	# beginner.
10681404Speter	if (/^$/) {
10781404Speter	    # Empty line; just skip at this point.
10881404Speter	} elsif (/^[MTWFS]/) {
10981404Speter	    # Looks like the name of a day; assume opener and move to
11081404Speter	    # "in entry" state.
11181404Speter	    $lastkey = $_;
11281404Speter	    $conf = 2;
11381404Speter	    print STDERR "found $_" if $tjd;
11481404Speter	} else {
11581404Speter	    die ("conflict crosses entry boundaries: $_");
11681404Speter	}
11781404Speter    } elsif ($conf == 2) {
11881404Speter	# In entry.  Copy into variable until we see beginner line.
11981404Speter	if (/^[MTWFS]/) {
12081404Speter	    # Entry beginner line.
12181404Speter
12281404Speter	    # Copy last key into array.
12381404Speter	    if ($lastkey ne '') {
12481404Speter		$conflist{$lastkey} = $lastval;
12581404Speter
12681404Speter		$lastkey = '';
12781404Speter		$lastval = '';
12881404Speter	    }
12981404Speter
13081404Speter	    $lastkey = $_;
13181404Speter	    print STDERR "found $_" if $tjd;
13281404Speter	    $lastval = '';
13381404Speter	} else {
13481404Speter	    $lastval .= $_;
13581404Speter	}
13681404Speter    } else {
13781404Speter	# Just copy.
13881404Speter	print;
13981404Speter    }
14081404Speter}
14181404Speter
14281404Speter# Compare ChangeLog time strings like <=>.
14381404Speter#
14481404Speter# 0         1         2         3
14581404Speter# Thu Aug 11 13:22:42 1994  Tom Tromey  (tromey@creche.colorado.edu)
14681404Speter# 0123456789012345678901234567890
14781404Speter#
14881404Spetersub clcmp {
14981404Speter    # First check year.
15081404Speter    $r = substr ($a, 20, 4) <=> substr ($b, 20, 4);
15181404Speter
15281404Speter    # Now check month.
15381404Speter    $r = $months{substr ($a, 4, 3)} <=> $months{substr ($b, 4, 3)} if !$r;
15481404Speter
15581404Speter    # Now check day.
15681404Speter    $r = substr ($a, 8, 2) <=> substr ($b, 8, 2) if !$r;
15781404Speter
15881404Speter    # Now check time (3 parts).
15981404Speter    $r = substr ($a, 11, 2) <=> substr ($b, 11, 2) if !$r;
16081404Speter    $r = substr ($a, 14, 2) <=> substr ($b, 14, 2) if !$r;
16181404Speter    $r = substr ($a, 17, 2) <=> substr ($b, 17, 2) if !$r;
16281404Speter
16381404Speter    $r;
16481404Speter}
165