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