xref: /dragonfly/gnu/usr.bin/rcs/lib/merger.c (revision b40e316c)
1 /* three-way file merge internals */
2 
3 /* Copyright 1991, 1992, 1993, 1994, 1995 Paul Eggert
4    Distributed under license by the Free Software Foundation, Inc.
5 
6 This file is part of RCS.
7 
8 RCS is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12 
13 RCS is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with RCS; see the file COPYING.
20 If not, write to the Free Software Foundation,
21 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 
23 Report problems and direct all questions to:
24 
25     rcs-bugs@cs.purdue.edu
26 
27 */
28 /*
29  * $FreeBSD: src/gnu/usr.bin/rcs/lib/merger.c,v 1.5 1999/08/27 23:36:44 peter Exp $
30  * $DragonFly: src/gnu/usr.bin/rcs/lib/merger.c,v 1.2 2003/06/17 04:25:47 dillon Exp $
31  */
32 
33 #include "rcsbase.h"
34 
35 libId(mergerId, "$DragonFly: src/gnu/usr.bin/rcs/lib/merger.c,v 1.2 2003/06/17 04:25:47 dillon Exp $")
36 
37 	static char const *normalize_arg P((char const*,char**));
38 	static char const *
39 normalize_arg(s, b)
40 	char const *s;
41 	char **b;
42 /*
43  * If S looks like an option, prepend ./ to it.  Yield the result.
44  * Set *B to the address of any storage that was allocated.
45  */
46 {
47 	char *t;
48 	if (*s == '-') {
49 		*b = t = testalloc(strlen(s) + 3);
50 		VOID sprintf(t, ".%c%s", SLASH, s);
51 		return t;
52 	} else {
53 		*b = 0;
54 		return s;
55 	}
56 }
57 
58 	int
59 merge(tostdout, edarg, label, argv)
60 	int tostdout;
61 	char const *edarg;
62 	char const *const label[3];
63 	char const *const argv[3];
64 /*
65  * Do `merge [-p] EDARG -L l0 -L l1 -L l2 a0 a1 a2',
66  * where TOSTDOUT specifies whether -p is present,
67  * EDARG gives the editing type (e.g. "-A", or null for the default),
68  * LABEL gives l0, l1 and l2, and ARGV gives a0, a1 and a2.
69  * Yield DIFF_SUCCESS or DIFF_FAILURE.
70  */
71 {
72 	register int i;
73 	FILE *f;
74 	RILE *rt;
75 	char const *a[3], *t;
76 	char *b[3];
77 	int s;
78 #if !DIFF3_BIN
79 	char const *d[2];
80 #endif
81 
82 	for (i=3; 0<=--i; )
83 		a[i] = normalize_arg(argv[i], &b[i]);
84 
85 	if (!edarg)
86 		edarg = "-E";
87 
88 #if DIFF3_BIN
89 	t = 0;
90 	if (!tostdout)
91 		t = maketemp(0);
92 	s = run(
93 		-1, t,
94 		DIFF3, edarg, "-am",
95 		"-L", label[0],
96 		"-L", label[1],
97 		"-L", label[2],
98 		a[0], a[1], a[2], (char*)0
99 	);
100 	switch (s) {
101 		case DIFF_SUCCESS:
102 			break;
103 		case DIFF_FAILURE:
104 			warn("conflicts during merge");
105 			break;
106 		default:
107 			exiterr();
108 	}
109 	if (t) {
110 		if (!(f = fopenSafer(argv[0], "w")))
111 			efaterror(argv[0]);
112 		if (!(rt = Iopen(t, "r", (struct stat*)0)))
113 			efaterror(t);
114 		fastcopy(rt, f);
115 		Ifclose(rt);
116 		Ofclose(f);
117 	}
118 #else
119 	for (i=0; i<2; i++)
120 		switch (run(
121 			-1, d[i]=maketemp(i),
122 			DIFF, a[i], a[2], (char*)0
123 		)) {
124 			case DIFF_FAILURE: case DIFF_SUCCESS: break;
125 			default: faterror("diff failed");
126 		}
127 	t = maketemp(2);
128 	s = run(
129 		-1, t,
130 		DIFF3, edarg, d[0], d[1], a[0], a[1], a[2],
131 		label[0], label[2], (char*)0
132 	);
133 	if (s != DIFF_SUCCESS) {
134 		s = DIFF_FAILURE;
135 		warn("overlaps or other problems during merge");
136 	}
137 	if (!(f = fopenSafer(t, "a+")))
138 		efaterror(t);
139 	aputs(tostdout ? "1,$p\n" : "w\n",  f);
140 	Orewind(f);
141 	aflush(f);
142 	if (run(fileno(f), (char*)0, ED, "-", a[0], (char*)0))
143 		exiterr();
144 	Ofclose(f);
145 #endif
146 
147 	tempunlink();
148 	for (i=3; 0<=--i; )
149 		if (b[i])
150 			tfree(b[i]);
151 	return s;
152 }
153