Line Flow Count Block(s) Source
1 - /*
2 - * LibXDiff by Davide Libenzi ( File Differential Library )
3 - * Copyright (C) 2003-2006 Davide Libenzi, Johannes E. Schindelin
4 - *
5 - * This library is free software; you can redistribute it and/or
6 - * modify it under the terms of the GNU Lesser General Public
7 - * License as published by the Free Software Foundation; either
8 - * version 2.1 of the License, or (at your option) any later version.
9 - *
10 - * This library 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 GNU
13 - * Lesser General Public License for more details.
14 - *
15 - * You should have received a copy of the GNU Lesser General Public
16 - * License along with this library; if not, see
17 - * <http://www.gnu.org/licenses/>.
18 - *
19 - * Davide Libenzi <davidel@xmailserver.org>
20 - *
21 - */
22 -
23 - #include "xinclude.h"
24 -
25 - typedef struct s_xdmerge {
26 - struct s_xdmerge *next;
27 - /*
28 - * 0 = conflict,
29 - * 1 = no conflict, take first,
30 - * 2 = no conflict, take second.
31 - * 3 = no conflict, take both.
32 - */
33 - int mode;
34 - /*
35 - * These point at the respective postimages. E.g. <i1,chg1> is
36 - * how side #1 wants to change the common ancestor; if there is no
37 - * overlap, lines before i1 in the postimage of side #1 appear
38 - * in the merge result as a region touched by neither side.
39 - */
40 - long i1, i2;
41 - long chg1, chg2;
42 - /*
43 - * These point at the preimage; of course there is just one
44 - * preimage, that is from the shared common ancestor.
45 - */
46 - long i0;
47 - long chg0;
48 - } xdmerge_t;
49 -
50 675 2 static int xdl_append_merge(xdmerge_t **merge, int mode,
51 - long i0, long chg0,
52 - long i1, long chg1,
53 - long i2, long chg2)
54 - {
55 675 2 xdmerge_t *m = *merge;
56 675 2-4 if (m && (i1 <= m->i1 + m->chg1 || i2 <= m->i2 + m->chg2)) {
57 36 5 if (mode != m->mode)
58 33 6 m->mode = 0;
59 36 7 m->chg0 = i0 + chg0 - m->i0;
60 36 7 m->chg1 = i1 + chg1 - m->i1;
61 36 7 m->chg2 = i2 + chg2 - m->i2;
62 - } else {
63 639 8 m = xdl_malloc(sizeof(xdmerge_t));
64 639 9 if (!m)
65 ##### 10 return -1;
66 639 11 m->next = NULL;
67 639 11 m->mode = mode;
68 639 11 m->i0 = i0;
69 639 11 m->chg0 = chg0;
70 639 11 m->i1 = i1;
71 639 11 m->chg1 = chg1;
72 639 11 m->i2 = i2;
73 639 11 m->chg2 = chg2;
74 639 11 if (*merge)
75 233 12 (*merge)->next = m;
76 639 13 *merge = m;
77 - }
78 675 14 return 0;
79 - }
80 -
81 406 2 static int xdl_cleanup_merge(xdmerge_t *c)
82 - {
83 406 2 int count = 0;
84 - xdmerge_t *next_c;
85 -
86 - /* were there conflicts? */
87 1044 2,5,6 for (; c; c = next_c) {
88 638 3 if (c->mode == 0)
89 255 4 count++;
90 638 5 next_c = c->next;
91 638 5 free(c);
92 - }
93 406 7 return count;
94 - }
95 -
96 212 2 static int xdl_merge_cmp_lines(xdfenv_t *xe1, int i1, xdfenv_t *xe2, int i2,
97 - int line_count, long flags)
98 - {
99 - int i;
100 212 2 xrecord_t **rec1 = xe1->xdf2.recs + i1;
101 212 2 xrecord_t **rec2 = xe2->xdf2.recs + i2;
102 -
103 263 2,6,7 for (i = 0; i < line_count; i++) {
104 257 3,3 int result = xdl_recmatch(rec1[i]->ptr, rec1[i]->size,
105 257 3,3 rec2[i]->ptr, rec2[i]->size, flags);
106 257 4 if (!result)
107 206 5 return -1;
108 - }
109 6 8 return 0;
110 - }
111 -
112 3894 2 static int xdl_recs_copy_0(size_t *out, int use_orig, xdfenv_t *xe, int i, int count, int needs_cr, int add_nl, char *dest)
113 - {
114 - xrecord_t **recs;
115 3894 2 size_t size = 0;
116 -
117 3894 2 *out = 0;
118 -
119 3894 2-4 recs = (use_orig ? xe->xdf1.recs : xe->xdf2.recs) + i;
120 -
121 3894 5 if (count < 1)
122 1502 6 return 0;
123 -
124 9450 7,17 for (i = 0; i < count; ) {
125 7058 8 if (dest)
126 3529 9 memcpy(dest + size, recs[i]->ptr, recs[i]->size);
127 -
128 7058 10-16 GIT_ERROR_CHECK_ALLOC_ADD(&size, size, recs[i++]->size);
129 - }
130 -
131 2392 18 if (add_nl) {
132 1024 19 i = recs[count - 1]->size;
133 1024 19,20 if (i == 0 || recs[count - 1]->ptr[i - 1] != '\n') {
134 ##### 21 if (needs_cr) {
135 ##### 22 if (dest)
136 ##### 23 dest[size] = '\r';
137 ##### 24-30 GIT_ERROR_CHECK_ALLOC_ADD(&size, size, 1);
138 - }
139 -
140 ##### 31 if (dest)
141 ##### 32 dest[size] = '\n';
142 -
143 ##### 33-39 GIT_ERROR_CHECK_ALLOC_ADD(&size, size, 1);
144 - }
145 - }
146 -
147 2392 40 *out = size;
148 2392 40 return 0;
149 - }
150 -
151 3878 2 static int xdl_recs_copy(size_t *out, xdfenv_t *xe, int i, int count, int needs_cr, int add_nl, char *dest)
152 - {
153 3878 2 return xdl_recs_copy_0(out, 0, xe, i, count, needs_cr, add_nl, dest);
154 - }
155 -
156 16 2 static int xdl_orig_copy(size_t *out, xdfenv_t *xe, int i, int count, int needs_cr, int add_nl, char *dest)
157 - {
158 16 2 return xdl_recs_copy_0(out, 1, xe, i, count, needs_cr, add_nl, dest);
159 - }
160 -
161 - /*
162 - * Returns 1 if the i'th line ends in CR/LF (if it is the last line and
163 - * has no eol, the preceding line, if any), 0 if it ends in LF-only, and
164 - * -1 if the line ending cannot be determined.
165 - */
166 966 2 static int is_eol_crlf(xdfile_t *file, int i)
167 - {
168 - long size;
169 -
170 966 2 if (i < file->nrec - 1)
171 - /* All lines before the last *must* end in LF */
172 572 3-7 return (size = file->recs[i]->size) > 1 &&
173 456 4 file->recs[i]->ptr[size - 2] == '\r';
174 394 8 if (!file->nrec)
175 - /* Cannot determine eol style from empty file */
176 ##### 9 return -1;
177 394 10,11 if ((size = file->recs[i]->size) &&
178 394 11 file->recs[i]->ptr[size - 1] == '\n')
179 - /* Last line; ends in LF; Is it CR/LF? */
180 394 12-16 return size > 1 &&
181 394 13 file->recs[i]->ptr[size - 2] == '\r';
182 ##### 17 if (!i)
183 - /* The only line has no eol */
184 ##### 18 return -1;
185 - /* Determine eol from second-to-last line */
186 ##### 19,20 return (size = file->recs[i - 1]->size) > 1 &&
187 ##### 20 file->recs[i - 1]->ptr[size - 2] == '\r';
188 - }
189 -
190 926 2 static int is_cr_needed(xdfenv_t *xe1, xdfenv_t *xe2, xdmerge_t *m)
191 - {
192 - int needs_cr;
193 -
194 - /* Match post-images' preceding, or first, lines' end-of-line style */
195 926 2-5 needs_cr = is_eol_crlf(&xe1->xdf2, m->i1 ? m->i1 - 1 : 0);
196 926 6 if (needs_cr)
197 20 7-10 needs_cr = is_eol_crlf(&xe2->xdf2, m->i2 ? m->i2 - 1 : 0);
198 - /* Look at pre-image's first line, unless we already settled on LF */
199 926 11 if (needs_cr)
200 20 12 needs_cr = is_eol_crlf(&xe1->xdf1, 0);
201 - /* If still undecided, use LF-only */
202 926 13 return needs_cr < 0 ? 0 : needs_cr;
203 - }
204 -
205 510 2 static int fill_conflict_hunk(size_t *out, xdfenv_t *xe1, const char *name1,
206 - xdfenv_t *xe2, const char *name2,
207 - const char *name3,
208 - size_t size, int i, int style,
209 - xdmerge_t *m, char *dest, int marker_size)
210 - {
211 510 2-4 int marker1_size = (name1 ? (int)strlen(name1) + 1 : 0);
212 510 5-7 int marker2_size = (name2 ? (int)strlen(name2) + 1 : 0);
213 510 8-10 int marker3_size = (name3 ? (int)strlen(name3) + 1 : 0);
214 510 11 int needs_cr = is_cr_needed(xe1, xe2, m);
215 - size_t copied;
216 -
217 510 12 *out = 0;
218 -
219 510 12 if (marker_size <= 0)
220 488 13 marker_size = DEFAULT_CONFLICT_MARKER_SIZE;
221 -
222 - /* Before conflicting part */
223 510 14-18 if (xdl_recs_copy(&copied, xe1, i, m->i1 - i, 0, 0,
224 255 15 dest ? dest + size : NULL) < 0)
225 ##### 19 return -1;
226 -
227 510 20-26 GIT_ERROR_CHECK_ALLOC_ADD(&size, size, copied);
228 -
229 510 27 if (!dest) {
230 255 28-40 GIT_ERROR_CHECK_ALLOC_ADD5(&size, size, marker_size, 1, needs_cr, marker1_size);
231 - } else {
232 255 41 memset(dest + size, '<', marker_size);
233 255 41 size += marker_size;
234 255 41 if (marker1_size) {
235 255 42 dest[size] = ' ';
236 255 42 memcpy(dest + size + 1, name1, marker1_size - 1);
237 255 42 size += marker1_size;
238 - }
239 255 43 if (needs_cr)
240 10 44 dest[size++] = '\r';
241 255 45 dest[size++] = '\n';
242 - }
243 -
244 - /* Postimage from side #1 */
245 510 46-50 if (xdl_recs_copy(&copied, xe1, m->i1, m->chg1, needs_cr, 1,
246 255 47 dest ? dest + size : NULL) < 0)
247 ##### 51 return -1;
248 -
249 510 52-58 GIT_ERROR_CHECK_ALLOC_ADD(&size, size, copied);
250 -
251 510 59 if (style == XDL_MERGE_DIFF3) {
252 - /* Shared preimage */
253 16 60 if (!dest) {
254 8 61-73 GIT_ERROR_CHECK_ALLOC_ADD5(&size, size, marker_size, 1, needs_cr, marker3_size);
255 - } else {
256 8 74 memset(dest + size, '|', marker_size);
257 8 74 size += marker_size;
258 8 74 if (marker3_size) {
259 8 75 dest[size] = ' ';
260 8 75 memcpy(dest + size + 1, name3, marker3_size - 1);
261 8 75 size += marker3_size;
262 - }
263 8 76 if (needs_cr)
264 1 77 dest[size++] = '\r';
265 8 78 dest[size++] = '\n';
266 - }
267 -
268 16 79-83 if (xdl_orig_copy(&copied, xe1, m->i0, m->chg0, needs_cr, 1,
269 8 80 dest ? dest + size : NULL) < 0)
270 ##### 84 return -1;
271 16 85-91 GIT_ERROR_CHECK_ALLOC_ADD(&size, size, copied);
272 - }
273 -
274 510 92 if (!dest) {
275 255 93-102 GIT_ERROR_CHECK_ALLOC_ADD4(&size, size, marker_size, 1, needs_cr);
276 - } else {
277 255 103 memset(dest + size, '=', marker_size);
278 255 103 size += marker_size;
279 255 103 if (needs_cr)
280 10 104 dest[size++] = '\r';
281 255 105 dest[size++] = '\n';
282 - }
283 -
284 - /* Postimage from side #2 */
285 -
286 510 106-110 if (xdl_recs_copy(&copied, xe2, m->i2, m->chg2, needs_cr, 1,
287 255 107 dest ? dest + size : NULL) < 0)
288 ##### 111 return -1;
289 510 112-118 GIT_ERROR_CHECK_ALLOC_ADD(&size, size, copied);
290 -
291 510 119 if (!dest) {
292 255 120-132 GIT_ERROR_CHECK_ALLOC_ADD5(&size, size, marker_size, 1, needs_cr, marker2_size);
293 - } else {
294 255 133 memset(dest + size, '>', marker_size);
295 255 133 size += marker_size;
296 255 133 if (marker2_size) {
297 255 134 dest[size] = ' ';
298 255 134 memcpy(dest + size + 1, name2, marker2_size - 1);
299 255 134 size += marker2_size;
300 - }
301 255 135 if (needs_cr)
302 10 136 dest[size++] = '\r';
303 255 137 dest[size++] = '\n';
304 - }
305 -
306 510 138 *out = size;
307 510 138 return 0;
308 - }
309 -
310 812 2 static int xdl_fill_merge_buffer(size_t *out,
311 - xdfenv_t *xe1, const char *name1,
312 - xdfenv_t *xe2, const char *name2,
313 - const char *ancestor_name,
314 - int favor,
315 - xdmerge_t *m, char *dest, int style,
316 - int marker_size)
317 - {
318 - size_t size, copied;
319 - int i;
320 -
321 812 2 *out = 0;
322 -
323 2088 2,55,56 for (size = i = 0; m; m = m->next) {
324 1276 3,4 if (favor && !m->mode)
325 8 5 m->mode = favor;
326 -
327 1276 6 if (m->mode == 0) {
328 510 7,8 if (fill_conflict_hunk(&size, xe1, name1, xe2, name2,
329 - ancestor_name,
330 - size, i, style, m, dest,
331 - marker_size) < 0)
332 ##### 9 return -1;
333 - }
334 766 10 else if (m->mode & 3) {
335 - /* Before conflicting part */
336 766 11-15 if (xdl_recs_copy(&copied, xe1, i, m->i1 - i, 0, 0,
337 383 12 dest ? dest + size : NULL) < 0)
338 ##### 16 return -1;
339 766 17-23 GIT_ERROR_CHECK_ALLOC_ADD(&size, size, copied);
340 -
341 - /* Postimage from side #1 */
342 766 24 if (m->mode & 1) {
343 416 25 int needs_cr = is_cr_needed(xe1, xe2, m);
344 -
345 416 26-30 if (xdl_recs_copy(&copied, xe1, m->i1, m->chg1, needs_cr, (m->mode & 2),
346 208 27 dest ? dest + size : NULL) < 0)
347 ##### 31 return -1;
348 416 32-38 GIT_ERROR_CHECK_ALLOC_ADD(&size, size, copied);
349 - }
350 -
351 - /* Postimage from side #2 */
352 766 39 if (m->mode & 2) {
353 354 40-44 if (xdl_recs_copy(&copied, xe2, m->i2, m->chg2, 0, 0,
354 177 41 dest ? dest + size : NULL) < 0)
355 ##### 45 return -1;
356 354 46-52 GIT_ERROR_CHECK_ALLOC_ADD(&size, size, copied);
357 - }
358 - } else
359 ##### 53 continue;
360 1276 54 i = m->i1 + m->chg1;
361 - }
362 -
363 812 57-61 if (xdl_recs_copy(&copied, xe1, i, xe1->xdf2.nrec - i, 0, 0,
364 406 58 dest ? dest + size : NULL) < 0)
365 ##### 62 return -1;
366 812 63-69 GIT_ERROR_CHECK_ALLOC_ADD(&size, size, copied);
367 -
368 812 70 *out = size;
369 812 70 return 0;
370 - }
371 -
372 - /*
373 - * Sometimes, changes are not quite identical, but differ in only a few
374 - * lines. Try hard to show only these few lines as conflicting.
375 - */
376 398 2 static int xdl_refine_conflicts(xdfenv_t *xe1, xdfenv_t *xe2, xdmerge_t *m,
377 - xpparam_t const *xpp)
378 - {
379 1029 2,35,36 for (; m; m = m->next) {
380 - mmfile_t t1, t2;
381 - xdfenv_t xe;
382 - xdchange_t *xscr, *x;
383 631 3 int i1 = m->i1, i2 = m->i2;
384 -
385 - /* let's handle just the conflicts */
386 631 3 if (m->mode)
387 384 4,33 continue;
388 -
389 - /* no sense refining a conflict when one side is empty */
390 256 5,6 if (m->chg1 == 0 || m->chg2 == 0)
391 9 7 continue;
392 -
393 - /*
394 - * This probably does not work outside git, since
395 - * we have a very simple mmfile structure.
396 - */
397 247 8 t1.ptr = (char *)xe1->xdf2.recs[m->i1]->ptr;
398 247 8,8 t1.size = xe1->xdf2.recs[m->i1 + m->chg1 - 1]->ptr
399 247 8 + xe1->xdf2.recs[m->i1 + m->chg1 - 1]->size - t1.ptr;
400 247 8 t2.ptr = (char *)xe2->xdf2.recs[m->i2]->ptr;
401 247 8,8 t2.size = xe2->xdf2.recs[m->i2 + m->chg2 - 1]->ptr
402 247 8 + xe2->xdf2.recs[m->i2 + m->chg2 - 1]->size - t2.ptr;
403 247 8,9 if (xdl_do_diff(&t1, &t2, xpp, &xe) < 0)
404 ##### 10,34 return -1;
405 247 11,12,14 if (xdl_change_compact(&xe.xdf1, &xe.xdf2, xpp->flags) < 0 ||
406 247 13,16 xdl_change_compact(&xe.xdf2, &xe.xdf1, xpp->flags) < 0 ||
407 247 15 xdl_build_script(&xe, &xscr) < 0) {
408 ##### 17 xdl_free_env(&xe);
409 ##### 18 return -1;
410 - }
411 247 19 if (!xscr) {
412 - /* If this happens, the changes are identical. */
413 ##### 20 xdl_free_env(&xe);
414 ##### 21 m->mode = 4;
415 ##### 21 continue;
416 - }
417 247 22 x = xscr;
418 247 22 m->i1 = xscr->i1 + i1;
419 247 22 m->chg1 = xscr->chg1;
420 247 22 m->i2 = xscr->i2 + i2;
421 247 22 m->chg2 = xscr->chg2;
422 267 22,29 while (xscr->next) {
423 20 23 xdmerge_t *m2 = xdl_malloc(sizeof(xdmerge_t));
424 20 24 if (!m2) {
425 ##### 25 xdl_free_env(&xe);
426 ##### 26 xdl_free_script(x);
427 ##### 27 return -1;
428 - }
429 20 28 xscr = xscr->next;
430 20 28 m2->next = m->next;
431 20 28 m->next = m2;
432 20 28 m = m2;
433 20 28 m->mode = 0;
434 20 28 m->i1 = xscr->i1 + i1;
435 20 28 m->chg1 = xscr->chg1;
436 20 28 m->i2 = xscr->i2 + i2;
437 20 28 m->chg2 = xscr->chg2;
438 - }
439 247 30 xdl_free_env(&xe);
440 247 31,32 xdl_free_script(x);
441 - }
442 398 37 return 0;
443 - }
444 -
445 ##### 2 static int line_contains_alnum(const char *ptr, long size)
446 - {
447 ##### 2,6 while (size--)
448 ##### 3,4 if (isalnum((unsigned char)*(ptr++)))
449 ##### 5 return 1;
450 ##### 7 return 0;
451 - }
452 -
453 ##### 2 static int lines_contain_alnum(xdfenv_t *xe, int i, int chg)
454 - {
455 ##### 2,6,7 for (; chg; chg--, i++)
456 ##### 3,4 if (line_contains_alnum(xe->xdf2.recs[i]->ptr,
457 ##### 3 xe->xdf2.recs[i]->size))
458 ##### 5 return 1;
459 ##### 8 return 0;
460 - }
461 -
462 - /*
463 - * This function merges m and m->next, marking everything between those hunks
464 - * as conflicting, too.
465 - */
466 21 2 static void xdl_merge_two_conflicts(xdmerge_t *m)
467 - {
468 21 2 xdmerge_t *next_m = m->next;
469 21 2 m->chg1 = next_m->i1 + next_m->chg1 - m->i1;
470 21 2 m->chg2 = next_m->i2 + next_m->chg2 - m->i2;
471 21 2 m->next = next_m->next;
472 21 2 free(next_m);
473 21 2 }
474 -
475 - /*
476 - * If there are less than 3 non-conflicting lines between conflicts,
477 - * it appears simpler -- because it takes up less (or as many) lines --
478 - * if the lines are moved into the conflicts.
479 - */
480 398 2 static int xdl_simplify_non_conflicts(xdfenv_t *xe1, xdmerge_t *m,
481 - int simplify_if_no_alnum)
482 - {
483 398 2 int result = 0;
484 -
485 398 2 if (!m)
486 ##### 3 return result;
487 - for (;;) {
488 651 4 xdmerge_t *next_m = m->next;
489 - int begin, end;
490 -
491 651 4 if (!next_m)
492 398 5 return result;
493 -
494 253 6 begin = m->i1 + m->chg1;
495 253 6 end = next_m->i1;
496 -
497 253 6-8 if (m->mode != 0 || next_m->mode != 0 ||
498 25 8,9 (end - begin > 3 &&
499 ##### 11 (!simplify_if_no_alnum ||
500 ##### 10 lines_contain_alnum(xe1, begin, end - begin)))) {
501 232 12 m = next_m;
502 - } else {
503 21 13 result++;
504 21 13 xdl_merge_two_conflicts(m);
505 - }
506 253 14 }
507 - }
508 -
509 - /*
510 - * level == 0: mark all overlapping changes as conflict
511 - * level == 1: mark overlapping changes as conflict only if not identical
512 - * level == 2: analyze non-identical changes for minimal conflict set
513 - * level == 3: analyze non-identical changes for minimal conflict set, but
514 - * treat hunks not containing any letter or number as conflicting
515 - *
516 - * returns < 0 on error, == 0 for no conflicts, else number of conflicts
517 - */
518 406 2 static int xdl_do_merge(xdfenv_t *xe1, xdchange_t *xscr1,
519 - xdfenv_t *xe2, xdchange_t *xscr2,
520 - xmparam_t const *xmp, mmbuffer_t *result)
521 - {
522 - xdmerge_t *changes, *c;
523 406 2 xpparam_t const *xpp = &xmp->xpp;
524 406 2 const char *const ancestor_name = xmp->ancestor;
525 406 2 const char *const name1 = xmp->file1;
526 406 2 const char *const name2 = xmp->file2;
527 - int i0, i1, i2, chg0, chg1, chg2;
528 406 2 int level = xmp->level;
529 406 2 int style = xmp->style;
530 406 2 int favor = xmp->favor;
531 -
532 406 2 if (style == XDL_MERGE_DIFF3) {
533 - /*
534 - * "diff3 -m" output does not make sense for anything
535 - * more aggressive than XDL_MERGE_EAGER.
536 - */
537 8 3 if (XDL_MERGE_EAGER < level)
538 8 4 level = XDL_MERGE_EAGER;
539 - }
540 -
541 406 5 c = changes = NULL;
542 -
543 878 5,40,41 while (xscr1 && xscr2) {
544 472 6 if (!changes)
545 457 7 changes = c;
546 472 8 if (xscr1->i1 + xscr1->chg1 < xscr2->i1) {
547 165 9 i0 = xscr1->i1;
548 165 9 i1 = xscr1->i2;
549 165 9 i2 = xscr2->i2 - xscr2->i1 + xscr1->i1;
550 165 9 chg0 = xscr1->chg1;
551 165 9 chg1 = xscr1->chg2;
552 165 9 chg2 = xscr1->chg1;
553 165 9,10 if (xdl_append_merge(&c, 1,
554 - i0, chg0, i1, chg1, i2, chg2)) {
555 ##### 11 xdl_cleanup_merge(changes);
556 ##### 12 return -1;
557 - }
558 165 13 xscr1 = xscr1->next;
559 165 13 continue;
560 - }
561 307 14 if (xscr2->i1 + xscr2->chg1 < xscr1->i1) {
562 34 15 i0 = xscr2->i1;
563 34 15 i1 = xscr1->i2 - xscr1->i1 + xscr2->i1;
564 34 15 i2 = xscr2->i2;
565 34 15 chg0 = xscr2->chg1;
566 34 15 chg1 = xscr2->chg1;
567 34 15 chg2 = xscr2->chg2;
568 34 15,16 if (xdl_append_merge(&c, 2,
569 - i0, chg0, i1, chg1, i2, chg2)) {
570 ##### 17 xdl_cleanup_merge(changes);
571 ##### 18 return -1;
572 - }
573 34 19 xscr2 = xscr2->next;
574 34 19 continue;
575 - }
576 273 20-22 if (level == XDL_MERGE_MINIMAL || xscr1->i1 != xscr2->i1 ||
577 257 22,23 xscr1->chg1 != xscr2->chg1 ||
578 228 23,25 xscr1->chg2 != xscr2->chg2 ||
579 212 24,24,24 xdl_merge_cmp_lines(xe1, xscr1->i2,
580 212 24 xe2, xscr2->i2,
581 212 24,24 xscr1->chg2, xpp->flags)) {
582 - /* conflict */
583 267 26 int off = xscr1->i1 - xscr2->i1;
584 267 26 int ffo = off + xscr1->chg1 - xscr2->chg1;
585 -
586 267 26 i0 = xscr1->i1;
587 267 26 i1 = xscr1->i2;
588 267 26 i2 = xscr2->i2;
589 267 26 if (off > 0) {
590 15 27 i0 -= off;
591 15 27 i1 -= off;
592 - }
593 - else
594 252 28 i2 += off;
595 267 29 chg0 = xscr1->i1 + xscr1->chg1 - i0;
596 267 29 chg1 = xscr1->i2 + xscr1->chg2 - i1;
597 267 29 chg2 = xscr2->i2 + xscr2->chg2 - i2;
598 267 29 if (ffo < 0) {
599 11 30 chg0 -= ffo;
600 11 30 chg1 -= ffo;
601 - } else
602 256 31 chg2 += ffo;
603 267 32,33 if (xdl_append_merge(&c, 0,
604 - i0, chg0, i1, chg1, i2, chg2)) {
605 ##### 34 xdl_cleanup_merge(changes);
606 ##### 35 return -1;
607 - }
608 - }
609 -
610 273 36 i1 = xscr1->i1 + xscr1->chg1;
611 273 36 i2 = xscr2->i1 + xscr2->chg1;
612 -
613 273 36 if (i1 >= i2)
614 262 37 xscr2 = xscr2->next;
615 273 38 if (i2 >= i1)
616 248 39 xscr1 = xscr1->next;
617 - }
618 467 42,50 while (xscr1) {
619 61 43 if (!changes)
620 29 44 changes = c;
621 61 45 i0 = xscr1->i1;
622 61 45 i1 = xscr1->i2;
623 61 45 i2 = xscr1->i1 + xe2->xdf2.nrec - xe2->xdf1.nrec;
624 61 45 chg0 = xscr1->chg1;
625 61 45 chg1 = xscr1->chg2;
626 61 45 chg2 = xscr1->chg1;
627 61 45,46 if (xdl_append_merge(&c, 1,
628 - i0, chg0, i1, chg1, i2, chg2)) {
629 ##### 47 xdl_cleanup_merge(changes);
630 ##### 48 return -1;
631 - }
632 61 49 xscr1 = xscr1->next;
633 - }
634 554 51,59 while (xscr2) {
635 148 52 if (!changes)
636 117 53 changes = c;
637 148 54 i0 = xscr2->i1;
638 148 54 i1 = xscr2->i1 + xe1->xdf2.nrec - xe1->xdf1.nrec;
639 148 54 i2 = xscr2->i2;
640 148 54 chg0 = xscr2->chg1;
641 148 54 chg1 = xscr2->chg1;
642 148 54 chg2 = xscr2->chg2;
643 148 54,55 if (xdl_append_merge(&c, 2,
644 - i0, chg0, i1, chg1, i2, chg2)) {
645 ##### 56 xdl_cleanup_merge(changes);
646 ##### 57 return -1;
647 - }
648 148 58 xscr2 = xscr2->next;
649 - }
650 406 60 if (!changes)
651 211 61 changes = c;
652 - /* refine conflicts */
653 406 62,64 if (XDL_MERGE_ZEALOUS <= level &&
654 398 63,66 (xdl_refine_conflicts(xe1, xe2, changes, xpp) < 0 ||
655 398 65 xdl_simplify_non_conflicts(xe1, changes,
656 - XDL_MERGE_ZEALOUS < level) < 0)) {
657 ##### 67 xdl_cleanup_merge(changes);
658 ##### 68 return -1;
659 - }
660 - /* output */
661 406 69 if (result) {
662 406 70 int marker_size = xmp->marker_size;
663 - size_t size;
664 -
665 406 70,71 if (xdl_fill_merge_buffer(&size, xe1, name1, xe2, name2,
666 - ancestor_name,
667 - favor, changes, NULL, style,
668 - marker_size) < 0)
669 ##### 72,81 return -1;
670 -
671 406 73 result->ptr = xdl_malloc(size);
672 406 74 if (!result->ptr) {
673 ##### 75 xdl_cleanup_merge(changes);
674 ##### 76 return -1;
675 - }
676 406 77 result->size = size;
677 406 77,78 if (xdl_fill_merge_buffer(&size, xe1, name1, xe2, name2,
678 - ancestor_name, favor, changes,
679 - result->ptr, style, marker_size) < 0)
680 406 79,80 return -1;
681 - }
682 406 82 return xdl_cleanup_merge(changes);
683 - }
684 -
685 428 2 int xdl_merge(mmfile_t *orig, mmfile_t *mf1, mmfile_t *mf2,
686 - xmparam_t const *xmp, mmbuffer_t *result)
687 - {
688 - xdchange_t *xscr1, *xscr2;
689 - xdfenv_t xe1, xe2;
690 - int status;
691 428 2 xpparam_t const *xpp = &xmp->xpp;
692 -
693 428 2 result->ptr = NULL;
694 428 2 result->size = 0;
695 -
696 428 2,3 if (xdl_do_diff(orig, mf1, xpp, &xe1) < 0) {
697 ##### 4 return -1;
698 - }
699 428 5,6 if (xdl_do_diff(orig, mf2, xpp, &xe2) < 0) {
700 ##### 7 xdl_free_env(&xe1);
701 ##### 8 return -1;
702 - }
703 428 9,10,12 if (xdl_change_compact(&xe1.xdf1, &xe1.xdf2, xpp->flags) < 0 ||
704 428 11,14 xdl_change_compact(&xe1.xdf2, &xe1.xdf1, xpp->flags) < 0 ||
705 428 13 xdl_build_script(&xe1, &xscr1) < 0) {
706 ##### 15 xdl_free_env(&xe1);
707 ##### 16 return -1;
708 - }
709 428 17,18,20 if (xdl_change_compact(&xe2.xdf1, &xe2.xdf2, xpp->flags) < 0 ||
710 428 19,22 xdl_change_compact(&xe2.xdf2, &xe2.xdf1, xpp->flags) < 0 ||
711 428 21 xdl_build_script(&xe2, &xscr2) < 0) {
712 ##### 23 xdl_free_script(xscr1);
713 ##### 24 xdl_free_env(&xe1);
714 ##### 25 xdl_free_env(&xe2);
715 ##### 26 return -1;
716 - }
717 428 27 status = 0;
718 428 27 if (!xscr1) {
719 20 28 result->ptr = xdl_malloc(mf2->size);
720 20 29 if (!result->ptr) {
721 ##### 30 xdl_free_script(xscr2);
722 ##### 31 xdl_free_env(&xe1);
723 ##### 32 xdl_free_env(&xe2);
724 ##### 33 return -1;
725 - }
726 20 34 memcpy(result->ptr, mf2->ptr, mf2->size);
727 20 34 result->size = mf2->size;
728 408 35 } else if (!xscr2) {
729 2 36 result->ptr = xdl_malloc(mf1->size);
730 2 37 if (!result->ptr) {
731 ##### 38 xdl_free_script(xscr1);
732 ##### 39 xdl_free_env(&xe1);
733 ##### 40 xdl_free_env(&xe2);
734 ##### 41 return -1;
735 - }
736 2 42 memcpy(result->ptr, mf1->ptr, mf1->size);
737 2 42 result->size = mf1->size;
738 - } else {
739 406 43 status = xdl_do_merge(&xe1, xscr1,
740 - &xe2, xscr2,
741 - xmp, result);
742 - }
743 428 44 xdl_free_script(xscr1);
744 428 45 xdl_free_script(xscr2);
745 -
746 428 46 xdl_free_env(&xe1);
747 428 47 xdl_free_env(&xe2);
748 -
749 428 48 return status;
750 - }