diff options
Diffstat (limited to 'xdiff/xemit.c')
-rw-r--r-- | xdiff/xemit.c | 88 |
1 files changed, 55 insertions, 33 deletions
diff --git a/xdiff/xemit.c b/xdiff/xemit.c index 4266ada23f..b52b4b9c1e 100644 --- a/xdiff/xemit.c +++ b/xdiff/xemit.c @@ -22,15 +22,6 @@ #include "xinclude.h" - - - -static long xdl_get_rec(xdfile_t *xdf, long ri, char const **rec); -static int xdl_emit_record(xdfile_t *xdf, long ri, char const *pre, xdemitcb_t *ecb); - - - - static long xdl_get_rec(xdfile_t *xdf, long ri, char const **rec) { *rec = xdf->recs[ri]->ptr; @@ -120,19 +111,14 @@ static long def_ff(const char *rec, long len, char *buf, long sz, void *priv) return -1; } -static int xdl_emit_common(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, - xdemitconf_t const *xecfg) { - xdfile_t *xdf = &xe->xdf2; - const char *rchg = xdf->rchg; - long ix; - - for (ix = 0; ix < xdf->nrec; ix++) { - if (rchg[ix]) - continue; - if (xdl_emit_record(xdf, ix, "", ecb)) - return -1; - } - return 0; +static long match_func_rec(xdfile_t *xdf, xdemitconf_t const *xecfg, long ri, + char *buf, long sz) +{ + const char *rec; + long len = xdl_get_rec(xdf, ri, &rec); + if (!xecfg->find_func) + return def_ff(rec, len, buf, sz, xecfg->find_func_priv); + return xecfg->find_func(rec, len, buf, sz, xecfg->find_func_priv); } struct func_line { @@ -143,7 +129,6 @@ struct func_line { static long get_func_line(xdfenv_t *xe, xdemitconf_t const *xecfg, struct func_line *func_line, long start, long limit) { - find_func_t ff = xecfg->find_func ? xecfg->find_func : def_ff; long l, size, step = (start > limit) ? -1 : 1; char *buf, dummy[1]; @@ -151,9 +136,7 @@ static long get_func_line(xdfenv_t *xe, xdemitconf_t const *xecfg, size = func_line ? sizeof(func_line->buf) : sizeof(dummy); for (l = start; l != limit && 0 <= l && l < xe->xdf1.nrec; l += step) { - const char *rec; - long reclen = xdl_get_rec(&xe->xdf1, l, &rec); - long len = ff(rec, reclen, buf, size, xecfg->find_func_priv); + long len = match_func_rec(&xe->xdf1, xecfg, l, buf, size); if (len >= 0) { if (func_line) func_line->len = len; @@ -163,6 +146,18 @@ static long get_func_line(xdfenv_t *xe, xdemitconf_t const *xecfg, return -1; } +static int is_empty_rec(xdfile_t *xdf, long ri) +{ + const char *rec; + long len = xdl_get_rec(xdf, ri, &rec); + + while (len > 0 && XDL_ISSPACE(*rec)) { + rec++; + len--; + } + return !len; +} + int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, xdemitconf_t const *xecfg) { long s1, s2, e1, e2, lctx; @@ -170,9 +165,6 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, long funclineprev = -1; struct func_line func_line = { 0 }; - if (xecfg->flags & XDL_EMIT_COMMON) - return xdl_emit_common(xe, xscr, ecb, xecfg); - for (xch = xscr; xch; xch = xche->next) { xche = xdl_get_hunk(&xch, xecfg); if (!xch) @@ -182,7 +174,34 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, s2 = XDL_MAX(xch->i2 - xecfg->ctxlen, 0); if (xecfg->flags & XDL_EMIT_FUNCCONTEXT) { - long fs1 = get_func_line(xe, xecfg, NULL, xch->i1, -1); + long fs1, i1 = xch->i1; + + /* Appended chunk? */ + if (i1 >= xe->xdf1.nrec) { + char dummy[1]; + long i2 = xch->i2; + + /* + * We don't need additional context if + * a whole function was added, possibly + * starting with empty lines. + */ + while (i2 < xe->xdf2.nrec && + is_empty_rec(&xe->xdf2, i2)) + i2++; + if (i2 < xe->xdf2.nrec && + match_func_rec(&xe->xdf2, xecfg, i2, + dummy, sizeof(dummy)) >= 0) + goto post_context_calculation; + + /* + * Otherwise get more context from the + * pre-image. + */ + i1 = xe->xdf1.nrec - 1; + } + + fs1 = get_func_line(xe, xecfg, NULL, i1, -1); if (fs1 < 0) fs1 = 0; if (fs1 < s1) { @@ -191,7 +210,7 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, } } - again: + post_context_calculation: lctx = xecfg->ctxlen; lctx = XDL_MIN(lctx, xe->xdf1.nrec - (xche->i1 + xche->chg1)); lctx = XDL_MIN(lctx, xe->xdf2.nrec - (xche->i2 + xche->chg2)); @@ -203,6 +222,8 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, long fe1 = get_func_line(xe, xecfg, NULL, xche->i1 + xche->chg1, xe->xdf1.nrec); + while (fe1 > 0 && is_empty_rec(&xe->xdf1, fe1 - 1)) + fe1--; if (fe1 < 0) fe1 = xe->xdf1.nrec; if (fe1 > e1) { @@ -216,11 +237,12 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb, * its new end. */ if (xche->next) { - long l = xche->next->i1; + long l = XDL_MIN(xche->next->i1, + xe->xdf1.nrec - 1); if (l <= e1 || get_func_line(xe, xecfg, NULL, l, e1) < 0) { xche = xche->next; - goto again; + goto post_context_calculation; } } } |