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