summaryrefslogtreecommitdiff
path: root/xdiff
diff options
context:
space:
mode:
Diffstat (limited to 'xdiff')
-rw-r--r--xdiff/xdiff.h18
-rw-r--r--xdiff/xemit.c38
-rw-r--r--xdiff/xmacros.h1
-rw-r--r--xdiff/xmerge.c82
-rw-r--r--xdiff/xutils.c22
5 files changed, 88 insertions, 73 deletions
diff --git a/xdiff/xdiff.h b/xdiff/xdiff.h
index 3f6229edbe..711048ea36 100644
--- a/xdiff/xdiff.h
+++ b/xdiff/xdiff.h
@@ -56,17 +56,14 @@ extern "C" {
#define XDL_MERGE_EAGER 1
#define XDL_MERGE_ZEALOUS 2
#define XDL_MERGE_ZEALOUS_ALNUM 3
-#define XDL_MERGE_LEVEL_MASK 0x0f
/* merge favor modes */
#define XDL_MERGE_FAVOR_OURS 1
#define XDL_MERGE_FAVOR_THEIRS 2
-#define XDL_MERGE_FAVOR(flags) (((flags)>>4) & 3)
-#define XDL_MERGE_FLAGS(level, style, favor) ((level)|(style)|((favor)<<4))
+#define XDL_MERGE_FAVOR_UNION 3
/* merge output styles */
-#define XDL_MERGE_DIFF3 0x8000
-#define XDL_MERGE_STYLE_MASK 0x8000
+#define XDL_MERGE_DIFF3 1
typedef struct s_mmfile {
char *ptr;
@@ -117,13 +114,18 @@ int xdl_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
typedef struct s_xmparam {
xpparam_t xpp;
int marker_size;
+ int level;
+ int favor;
+ int style;
+ const char *ancestor; /* label for orig */
+ const char *file1; /* label for mf1 */
+ const char *file2; /* label for mf2 */
} xmparam_t;
#define DEFAULT_CONFLICT_MARKER_SIZE 7
-int xdl_merge(mmfile_t *orig, mmfile_t *mf1, const char *name1,
- mmfile_t *mf2, const char *name2,
- xmparam_t const *xmp, int flags, mmbuffer_t *result);
+int xdl_merge(mmfile_t *orig, mmfile_t *mf1, mmfile_t *mf2,
+ xmparam_t const *xmp, mmbuffer_t *result);
#ifdef __cplusplus
}
diff --git a/xdiff/xemit.c b/xdiff/xemit.c
index c4bedf0d1c..277e2eec5b 100644
--- a/xdiff/xemit.c
+++ b/xdiff/xemit.c
@@ -85,27 +85,6 @@ static long def_ff(const char *rec, long len, char *buf, long sz, void *priv)
return -1;
}
-static void xdl_find_func(xdfile_t *xf, long i, char *buf, long sz, long *ll,
- find_func_t ff, void *ff_priv) {
-
- /*
- * Be quite stupid about this for now. Find a line in the old file
- * before the start of the hunk (and context) which starts with a
- * plausible character.
- */
-
- const char *rec;
- long len;
-
- while (i-- > 0) {
- len = xdl_get_rec(xf, i, &rec);
- if ((*ll = ff(rec, len, buf, sz, ff_priv)) >= 0)
- return;
- }
- *ll = 0;
-}
-
-
static int xdl_emit_common(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
xdemitconf_t const *xecfg) {
xdfile_t *xdf = &xe->xdf1;
@@ -127,6 +106,7 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
xdchange_t *xch, *xche;
char funcbuf[80];
long funclen = 0;
+ long funclineprev = -1;
find_func_t ff = xecfg->find_func ? xecfg->find_func : def_ff;
if (xecfg->flags & XDL_EMIT_COMMON)
@@ -150,9 +130,19 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
*/
if (xecfg->flags & XDL_EMIT_FUNCNAMES) {
- xdl_find_func(&xe->xdf1, s1, funcbuf,
- sizeof(funcbuf), &funclen,
- ff, xecfg->find_func_priv);
+ long l;
+ for (l = s1 - 1; l >= 0 && l > funclineprev; l--) {
+ const char *rec;
+ long reclen = xdl_get_rec(&xe->xdf1, l, &rec);
+ long newfunclen = ff(rec, reclen, funcbuf,
+ sizeof(funcbuf),
+ xecfg->find_func_priv);
+ if (newfunclen >= 0) {
+ funclen = newfunclen;
+ break;
+ }
+ }
+ funclineprev = s1 - 1;
}
if (xdl_emit_hunk_hdr(s1 + 1, e1 - s1, s2 + 1, e2 - s2,
funcbuf, funclen, ecb) < 0)
diff --git a/xdiff/xmacros.h b/xdiff/xmacros.h
index 8ef232cfad..165a895a93 100644
--- a/xdiff/xmacros.h
+++ b/xdiff/xmacros.h
@@ -30,6 +30,7 @@
#define XDL_MAX(a, b) ((a) > (b) ? (a): (b))
#define XDL_ABS(v) ((v) >= 0 ? (v): -(v))
#define XDL_ISDIGIT(c) ((c) >= '0' && (c) <= '9')
+#define XDL_ISSPACE(c) (isspace((unsigned char)(c)))
#define XDL_ADDBITS(v,b) ((v) + ((v) >> (b)))
#define XDL_MASKBITS(b) ((1UL << (b)) - 1)
#define XDL_HASHLONG(v,b) (XDL_ADDBITS((unsigned long)(v), b) & XDL_MASKBITS(b))
diff --git a/xdiff/xmerge.c b/xdiff/xmerge.c
index 8cbe45e675..9e13b25abc 100644
--- a/xdiff/xmerge.c
+++ b/xdiff/xmerge.c
@@ -28,6 +28,7 @@ typedef struct s_xdmerge {
* 0 = conflict,
* 1 = no conflict, take first,
* 2 = no conflict, take second.
+ * 3 = no conflict, take both.
*/
int mode;
/*
@@ -144,12 +145,13 @@ static int xdl_orig_copy(xdfenv_t *xe, int i, int count, int add_nl, char *dest)
static int fill_conflict_hunk(xdfenv_t *xe1, const char *name1,
xdfenv_t *xe2, const char *name2,
+ const char *name3,
int size, int i, int style,
xdmerge_t *m, char *dest, int marker_size)
{
int marker1_size = (name1 ? strlen(name1) + 1 : 0);
int marker2_size = (name2 ? strlen(name2) + 1 : 0);
- int j;
+ int marker3_size = (name3 ? strlen(name3) + 1 : 0);
if (marker_size <= 0)
marker_size = DEFAULT_CONFLICT_MARKER_SIZE;
@@ -161,8 +163,8 @@ static int fill_conflict_hunk(xdfenv_t *xe1, const char *name1,
if (!dest) {
size += marker_size + 1 + marker1_size;
} else {
- for (j = 0; j < marker_size; j++)
- dest[size++] = '<';
+ memset(dest + size, '<', marker_size);
+ size += marker_size;
if (marker1_size) {
dest[size] = ' ';
memcpy(dest + size + 1, name1, marker1_size - 1);
@@ -178,10 +180,15 @@ static int fill_conflict_hunk(xdfenv_t *xe1, const char *name1,
if (style == XDL_MERGE_DIFF3) {
/* Shared preimage */
if (!dest) {
- size += marker_size + 1;
+ size += marker_size + 1 + marker3_size;
} else {
- for (j = 0; j < marker_size; j++)
- dest[size++] = '|';
+ memset(dest + size, '|', marker_size);
+ size += marker_size;
+ if (marker3_size) {
+ dest[size] = ' ';
+ memcpy(dest + size + 1, name3, marker3_size - 1);
+ size += marker3_size;
+ }
dest[size++] = '\n';
}
size += xdl_orig_copy(xe1, m->i0, m->chg0, 1,
@@ -191,8 +198,8 @@ static int fill_conflict_hunk(xdfenv_t *xe1, const char *name1,
if (!dest) {
size += marker_size + 1;
} else {
- for (j = 0; j < marker_size; j++)
- dest[size++] = '=';
+ memset(dest + size, '=', marker_size);
+ size += marker_size;
dest[size++] = '\n';
}
@@ -202,8 +209,8 @@ static int fill_conflict_hunk(xdfenv_t *xe1, const char *name1,
if (!dest) {
size += marker_size + 1 + marker2_size;
} else {
- for (j = 0; j < marker_size; j++)
- dest[size++] = '>';
+ memset(dest + size, '>', marker_size);
+ size += marker_size;
if (marker2_size) {
dest[size] = ' ';
memcpy(dest + size + 1, name2, marker2_size - 1);
@@ -216,6 +223,7 @@ static int fill_conflict_hunk(xdfenv_t *xe1, const char *name1,
static int xdl_fill_merge_buffer(xdfenv_t *xe1, const char *name1,
xdfenv_t *xe2, const char *name2,
+ const char *ancestor_name,
int favor,
xdmerge_t *m, char *dest, int style,
int marker_size)
@@ -228,16 +236,22 @@ static int xdl_fill_merge_buffer(xdfenv_t *xe1, const char *name1,
if (m->mode == 0)
size = fill_conflict_hunk(xe1, name1, xe2, name2,
+ ancestor_name,
size, i, style, m, dest,
marker_size);
- else if (m->mode == 1)
- size += xdl_recs_copy(xe1, i, m->i1 + m->chg1 - i, 0,
- dest ? dest + size : NULL);
- else if (m->mode == 2)
- size += xdl_recs_copy(xe2, m->i2 - m->i1 + i,
- m->i1 + m->chg2 - i, 0,
+ else if (m->mode & 3) {
+ /* Before conflicting part */
+ size += xdl_recs_copy(xe1, i, m->i1 - i, 0,
dest ? dest + size : NULL);
- else
+ /* Postimage from side #1 */
+ if (m->mode & 1)
+ size += xdl_recs_copy(xe1, m->i1, m->chg1, 1,
+ dest ? dest + size : NULL);
+ /* Postimage from side #2 */
+ if (m->mode & 2)
+ size += xdl_recs_copy(xe2, m->i2, m->chg2, 1,
+ dest ? dest + size : NULL);
+ } else
continue;
i = m->i1 + m->chg1;
}
@@ -322,7 +336,7 @@ static int xdl_refine_conflicts(xdfenv_t *xe1, xdfenv_t *xe2, xdmerge_t *m,
static int line_contains_alnum(const char *ptr, long size)
{
while (size--)
- if (isalnum(*(ptr++)))
+ if (isalnum((unsigned char)*(ptr++)))
return 1;
return 0;
}
@@ -392,15 +406,19 @@ static int xdl_simplify_non_conflicts(xdfenv_t *xe1, xdmerge_t *m,
*
* returns < 0 on error, == 0 for no conflicts, else number of conflicts
*/
-static int xdl_do_merge(xdfenv_t *xe1, xdchange_t *xscr1, const char *name1,
- xdfenv_t *xe2, xdchange_t *xscr2, const char *name2,
- int flags, xmparam_t const *xmp, mmbuffer_t *result) {
+static int xdl_do_merge(xdfenv_t *xe1, xdchange_t *xscr1,
+ xdfenv_t *xe2, xdchange_t *xscr2,
+ xmparam_t const *xmp, mmbuffer_t *result)
+{
xdmerge_t *changes, *c;
xpparam_t const *xpp = &xmp->xpp;
+ const char *const ancestor_name = xmp->ancestor;
+ const char *const name1 = xmp->file1;
+ const char *const name2 = xmp->file2;
int i0, i1, i2, chg0, chg1, chg2;
- int level = flags & XDL_MERGE_LEVEL_MASK;
- int style = flags & XDL_MERGE_STYLE_MASK;
- int favor = XDL_MERGE_FAVOR(flags);
+ int level = xmp->level;
+ int style = xmp->style;
+ int favor = xmp->favor;
if (style == XDL_MERGE_DIFF3) {
/*
@@ -534,6 +552,7 @@ static int xdl_do_merge(xdfenv_t *xe1, xdchange_t *xscr1, const char *name1,
if (result) {
int marker_size = xmp->marker_size;
int size = xdl_fill_merge_buffer(xe1, name1, xe2, name2,
+ ancestor_name,
favor, changes, NULL, style,
marker_size);
result->ptr = xdl_malloc(size);
@@ -542,15 +561,16 @@ static int xdl_do_merge(xdfenv_t *xe1, xdchange_t *xscr1, const char *name1,
return -1;
}
result->size = size;
- xdl_fill_merge_buffer(xe1, name1, xe2, name2, favor, changes,
+ xdl_fill_merge_buffer(xe1, name1, xe2, name2,
+ ancestor_name, favor, changes,
result->ptr, style, marker_size);
}
return xdl_cleanup_merge(changes);
}
-int xdl_merge(mmfile_t *orig, mmfile_t *mf1, const char *name1,
- mmfile_t *mf2, const char *name2,
- xmparam_t const *xmp, int flags, mmbuffer_t *result) {
+int xdl_merge(mmfile_t *orig, mmfile_t *mf1, mmfile_t *mf2,
+ xmparam_t const *xmp, mmbuffer_t *result)
+{
xdchange_t *xscr1, *xscr2;
xdfenv_t xe1, xe2;
int status;
@@ -585,9 +605,9 @@ int xdl_merge(mmfile_t *orig, mmfile_t *mf1, const char *name1,
memcpy(result->ptr, mf1->ptr, mf1->size);
result->size = mf1->size;
} else {
- status = xdl_do_merge(&xe1, xscr1, name1,
- &xe2, xscr2, name2,
- flags, xmp, result);
+ status = xdl_do_merge(&xe1, xscr1,
+ &xe2, xscr2,
+ xmp, result);
}
xdl_free_script(xscr1);
xdl_free_script(xscr2);
diff --git a/xdiff/xutils.c b/xdiff/xutils.c
index bc12f29895..ab6503460f 100644
--- a/xdiff/xutils.c
+++ b/xdiff/xutils.c
@@ -190,8 +190,10 @@ int xdl_recmatch(const char *l1, long s1, const char *l2, long s2, long flags)
{
int i1, i2;
+ if (s1 == s2 && !memcmp(l1, l2, s1))
+ return 1;
if (!(flags & XDF_WHITESPACE_FLAGS))
- return s1 == s2 && !memcmp(l1, l2, s1);
+ return 0;
i1 = 0;
i2 = 0;
@@ -209,18 +211,18 @@ int xdl_recmatch(const char *l1, long s1, const char *l2, long s2, long flags)
if (l1[i1++] != l2[i2++])
return 0;
skip_ws:
- while (i1 < s1 && isspace(l1[i1]))
+ while (i1 < s1 && XDL_ISSPACE(l1[i1]))
i1++;
- while (i2 < s2 && isspace(l2[i2]))
+ while (i2 < s2 && XDL_ISSPACE(l2[i2]))
i2++;
}
} else if (flags & XDF_IGNORE_WHITESPACE_CHANGE) {
while (i1 < s1 && i2 < s2) {
- if (isspace(l1[i1]) && isspace(l2[i2])) {
+ if (XDL_ISSPACE(l1[i1]) && XDL_ISSPACE(l2[i2])) {
/* Skip matching spaces and try again */
- while (i1 < s1 && isspace(l1[i1]))
+ while (i1 < s1 && XDL_ISSPACE(l1[i1]))
i1++;
- while (i2 < s2 && isspace(l2[i2]))
+ while (i2 < s2 && XDL_ISSPACE(l2[i2]))
i2++;
continue;
}
@@ -239,13 +241,13 @@ int xdl_recmatch(const char *l1, long s1, const char *l2, long s2, long flags)
* while there still are characters remaining on both lines.
*/
if (i1 < s1) {
- while (i1 < s1 && isspace(l1[i1]))
+ while (i1 < s1 && XDL_ISSPACE(l1[i1]))
i1++;
if (s1 != i1)
return 0;
}
if (i2 < s2) {
- while (i2 < s2 && isspace(l2[i2]))
+ while (i2 < s2 && XDL_ISSPACE(l2[i2]))
i2++;
return (s2 == i2);
}
@@ -258,10 +260,10 @@ static unsigned long xdl_hash_record_with_whitespace(char const **data,
char const *ptr = *data;
for (; ptr < top && *ptr != '\n'; ptr++) {
- if (isspace(*ptr)) {
+ if (XDL_ISSPACE(*ptr)) {
const char *ptr2 = ptr;
int at_eol;
- while (ptr + 1 < top && isspace(ptr[1])
+ while (ptr + 1 < top && XDL_ISSPACE(ptr[1])
&& ptr[1] != '\n')
ptr++;
at_eol = (top <= ptr + 1 || ptr[1] == '\n');