• merge latest version of rannotate code from corecode
[alioth/cvs.git] / contrib / clmerge.in
1 #! @PERL@
2
3 # Copyright (C) 1995-2005 The Free Software Foundation, Inc.
4
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2, or (at your option)
8 # any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14
15 # Merge conflicted ChangeLogs
16 # tromey Mon Aug 15 1994
17
18 # Usage is:
19 #
20 #       cl-merge [-i] file ...
21 #
22 # With -i, it works in place (backups put in a ~ file).  Otherwise the
23 # merged ChangeLog is printed to stdout.
24
25 # Please report any bugs to me.  I wrote this yesterday, so there are no
26 # guarantees about its performance.  I recommend checking its output
27 # carefully.  If you do send a bug report, please include the failing
28 # ChangeLog, so I can include it in my test suite.
29 #
30 # Tom
31 # ---
32 # tromey@busco.lanl.gov             Member, League for Programming Freedom
33 # Sadism and farce are always inexplicably linked.
34 #       -- Alexander Theroux
35
36
37 # Month->number mapping.  Used for sorting.
38 %months = ('Jan', 0,
39            'Feb', 1,
40            'Mar', 2,
41            'Apr', 3,
42            'May', 4,
43            'Jun', 5,
44            'Jul', 6,
45            'Aug', 7,
46            'Sep', 8,
47            'Oct', 9,
48            'Nov', 10,
49            'Dec', 11);
50
51 # If '-i' is given, do it in-place.
52 if ($ARGV[0] eq '-i') {
53     shift (@ARGV);
54     $^I = '~';
55 }
56
57 $lastkey = '';
58 $lastval = '';
59 $conf = 0;
60 %conflist = ();
61
62 $tjd = 0;
63
64 # Simple state machine.  The states:
65 #
66 # 0     Not in conflict.  Just copy input to output.
67 # 1     Beginning an entry.  Next non-blank line is key.
68 # 2     In entry.  Entry beginner transitions to state 1.
69 while (<>) {
70     if (/^<<<</ || /^====/) {
71         # Start of a conflict.
72
73         # Copy last key into array.
74         if ($lastkey ne '') {
75             $conflist{$lastkey} = $lastval;
76
77             $lastkey = '';
78             $lastval = '';
79         }
80
81         $conf = 1;
82     } elsif (/^>>>>/) {
83         # End of conflict.  Output.
84
85         # Copy last key into array.
86         if ($lastkey ne '') {
87             $conflist{$lastkey} = $lastval;
88
89             $lastkey = '';
90             $lastval = '';
91         }
92
93         foreach (reverse sort clcmp keys %conflist) {
94             print STDERR "doing $_" if $tjd;
95             print $_;
96             print $conflist{$_};
97         }
98
99         $lastkey = '';
100         $lastval = '';
101         $conf = 0;
102         %conflist = ();
103     } elsif ($conf == 1) {
104         # Beginning an entry.  Skip empty lines.  Error if not a real
105         # beginner.
106         if (/^$/) {
107             # Empty line; just skip at this point.
108         } elsif (/^[MTWFS]/) {
109             # Looks like the name of a day; assume opener and move to
110             # "in entry" state.
111             $lastkey = $_;
112             $conf = 2;
113             print STDERR "found $_" if $tjd;
114         } else {
115             die ("conflict crosses entry boundaries: $_");
116         }
117     } elsif ($conf == 2) {
118         # In entry.  Copy into variable until we see beginner line.
119         if (/^[MTWFS]/) {
120             # Entry beginner line.
121
122             # Copy last key into array.
123             if ($lastkey ne '') {
124                 $conflist{$lastkey} = $lastval;
125
126                 $lastkey = '';
127                 $lastval = '';
128             }
129
130             $lastkey = $_;
131             print STDERR "found $_" if $tjd;
132             $lastval = '';
133         } else {
134             $lastval .= $_;
135         }
136     } else {
137         # Just copy.
138         print;
139     }
140 }
141
142 # Compare ChangeLog time strings like <=>.
143 #
144 # 0         1         2         3
145 # Thu Aug 11 13:22:42 1994  Tom Tromey  (tromey@creche.colorado.edu)
146 # 0123456789012345678901234567890
147 #
148 sub clcmp {
149     # First check year.
150     $r = substr ($a, 20, 4) <=> substr ($b, 20, 4);
151
152     # Now check month.
153     $r = $months{substr ($a, 4, 3)} <=> $months{substr ($b, 4, 3)} if !$r;
154
155     # Now check day.
156     $r = substr ($a, 8, 2) <=> substr ($b, 8, 2) if !$r;
157
158     # Now check time (3 parts).
159     $r = substr ($a, 11, 2) <=> substr ($b, 11, 2) if !$r;
160     $r = substr ($a, 14, 2) <=> substr ($b, 14, 2) if !$r;
161     $r = substr ($a, 17, 2) <=> substr ($b, 17, 2) if !$r;
162
163     $r;
164 }