Merge pull request #15602 from clason/vim-8.2.3390

vim-patch:8.2.3390: included xdiff code is outdated

build: move src/nvim/xdiff to src/xdiff
This commit is contained in:
Christian Clason 2021-09-09 08:43:20 +02:00 committed by GitHub
commit ed0c747788
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 240 additions and 149 deletions

View File

@ -87,8 +87,8 @@ file(MAKE_DIRECTORY ${LINT_SUPPRESSES_ROOT}/src)
file(GLOB NVIM_SOURCES *.c)
file(GLOB NVIM_HEADERS *.h)
file(GLOB XDIFF_SOURCES xdiff/*.c)
file(GLOB XDIFF_HEADERS xdiff/*.h)
file(GLOB XDIFF_SOURCES ../xdiff/*.c)
file(GLOB XDIFF_HEADERS ../xdiff/*.h)
foreach(subdir
os

View File

@ -1059,7 +1059,7 @@ static int diff_file_internal(diffio_T *diffio)
emit_cfg.ctxlen = 0; // don't need any diff_context here
emit_cb.priv = &diffio->dio_diff;
emit_cb.outf = xdiff_out;
emit_cb.out_line = xdiff_out;
if (xdl_diff(&diffio->dio_orig.din_mmfile,
&diffio->dio_new.din_mmfile,
&param, &emit_cfg, &emit_cb) < 0) {

View File

@ -8,7 +8,7 @@
#include <string.h>
#include "nvim/vim.h"
#include "nvim/xdiff/xdiff.h"
#include "xdiff/xdiff.h"
#include "nvim/lua/xdiff.h"
#include "nvim/lua/converter.h"
#include "nvim/lua/executor.h"
@ -294,7 +294,7 @@ int nlua_xdl_diff(lua_State *lstate)
case kNluaXdiffModeUnified:
luaL_buffinit(lstate, &buf);
ecb.priv = &buf;
ecb.outf = write_string;
ecb.out_line = write_string;
break;
case kNluaXdiffModeOnHunkCB:
priv = xmalloc(sizeof(*priv));

View File

@ -1,6 +1,6 @@
The files in this directory come from the xdiff implementation in git.
You can find it here: https://github.com/git/git/tree/master/xdiff
The files were last updated 2018 September 10.
The files were last updated August 31, 2021 from git release v.2.33.0
This is originally based on libxdiff, which can be found here:
http://www.xmailserver.org/xdiff-lib.html

View File

@ -25,9 +25,9 @@
#ifdef __cplusplus
extern "C" {
#endif // #ifdef __cplusplus
#endif /* #ifdef __cplusplus */
// xpparm_t.flags
/* xpparm_t.flags */
#define XDF_NEED_MINIMAL (1 << 0)
#define XDF_IGNORE_WHITESPACE (1 << 1)
@ -48,22 +48,23 @@ extern "C" {
#define XDF_INDENT_HEURISTIC (1 << 23)
// xdemitconf_t.flags
/* xdemitconf_t.flags */
#define XDL_EMIT_FUNCNAMES (1 << 0)
#define XDL_EMIT_NO_HUNK_HDR (1 << 1)
#define XDL_EMIT_FUNCCONTEXT (1 << 2)
// merge simplification levels
/* merge simplification levels */
#define XDL_MERGE_MINIMAL 0
#define XDL_MERGE_EAGER 1
#define XDL_MERGE_ZEALOUS 2
#define XDL_MERGE_ZEALOUS_ALNUM 3
// merge favor modes
/* merge favor modes */
#define XDL_MERGE_FAVOR_OURS 1
#define XDL_MERGE_FAVOR_THEIRS 2
#define XDL_MERGE_FAVOR_UNION 3
// merge output styles
/* merge output styles */
#define XDL_MERGE_DIFF3 1
typedef struct s_mmfile {
@ -79,14 +80,24 @@ typedef struct s_mmbuffer {
typedef struct s_xpparam {
unsigned long flags;
// See Documentation/diff-options.txt.
/* -I<regex> */
#if 0 // unused by Vim
regex_t **ignore_regex;
size_t ignore_regex_nr;
#endif
/* See Documentation/diff-options.txt. */
char **anchors;
size_t anchors_nr;
} xpparam_t;
typedef struct s_xdemitcb {
void *priv;
int (*outf)(void *, mmbuffer_t *, int);
int (*out_hunk)(void *,
long old_begin, long old_nr,
long new_begin, long new_nr,
const char *func, long funclen);
int (*out_line)(void *, mmbuffer_t *, int);
} xdemitcb_t;
typedef long (*find_func_t)(const char *line, long line_len, char *buffer, long buffer_size, void *priv);
@ -108,7 +119,7 @@ typedef struct s_bdiffparam {
long bsize;
} bdiffparam_t;
#include "../memory.h"
#include "../nvim/memory.h"
#define xdl_malloc(x) xmalloc((x))
#define xdl_free(ptr) xfree(ptr)
@ -126,9 +137,9 @@ typedef struct s_xmparam {
int level;
int favor;
int style;
const char *ancestor; // label for orig
const char *file1; // label for mf1
const char *file2; // label for mf2
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
@ -138,6 +149,6 @@ int xdl_merge(mmfile_t *orig, mmfile_t *mf1, mmfile_t *mf2,
#ifdef __cplusplus
}
#endif // #ifdef __cplusplus
#endif /* #ifdef __cplusplus */
#endif // #if !defined(XDIFF_H)
#endif /* #if !defined(XDIFF_H) */

View File

@ -38,9 +38,9 @@ typedef struct s_xdpsplit {
* Basically considers a "box" (off1, off2, lim1, lim2) and scan from both
* the forward diagonal starting from (off1, off2) and the backward diagonal
* starting from (lim1, lim2). If the K values on the same diagonal crosses
* returns the furthest point of reach. We might end up having to expensive
* cases using this algorithm is full, so a little bit of heuristic is needed
* to cut the search and to return a suboptimal point.
* returns the furthest point of reach. We might encounter expensive edge cases
* using this algorithm, so a little bit of heuristic is needed to cut the
* search and to return a suboptimal point.
*/
static long xdl_split(unsigned long const *ha1, long off1, long lim1,
unsigned long const *ha2, long off2, long lim2,
@ -63,11 +63,13 @@ static long xdl_split(unsigned long const *ha1, long off1, long lim1,
int got_snake = 0;
/*
* We need to extent the diagonal "domain" by one. If the next
* We need to extend the diagonal "domain" by one. If the next
* values exits the box boundaries we need to change it in the
* opposite direction because (max - min) must be a power of two.
* opposite direction because (max - min) must be a power of
* two.
*
* Also we initialize the external K value to -1 so that we can
* avoid extra conditions check inside the core loop.
* avoid extra conditions in the check inside the core loop.
*/
if (fmin > dmin)
kvdf[--fmin - 1] = -1;
@ -98,11 +100,13 @@ static long xdl_split(unsigned long const *ha1, long off1, long lim1,
}
/*
* We need to extent the diagonal "domain" by one. If the next
* We need to extend the diagonal "domain" by one. If the next
* values exits the box boundaries we need to change it in the
* opposite direction because (max - min) must be a power of two.
* opposite direction because (max - min) must be a power of
* two.
*
* Also we initialize the external K value to -1 so that we can
* avoid extra conditions check inside the core loop.
* avoid extra conditions in the check inside the core loop.
*/
if (bmin > dmin)
kvdb[--bmin - 1] = XDL_LINE_MAX;
@ -138,7 +142,7 @@ static long xdl_split(unsigned long const *ha1, long off1, long lim1,
/*
* If the edit cost is above the heuristic trigger and if
* we got a good snake, we sample current diagonals to see
* if some of the, have reached an "interesting" path. Our
* if some of them have reached an "interesting" path. Our
* measure is a function of the distance from the diagonal
* corner (i1 + i2) penalized with the distance from the
* mid diagonal itself. If this value is above the current
@ -196,8 +200,9 @@ static long xdl_split(unsigned long const *ha1, long off1, long lim1,
}
/*
* Enough is enough. We spent too much time here and now we collect
* the furthest reaching path using the (i1 + i2) measure.
* Enough is enough. We spent too much time here and now we
* collect the furthest reaching path using the (i1 + i2)
* measure.
*/
if (ec >= xenv->mxcost) {
long fbest, fbest1, bbest, bbest1;
@ -244,9 +249,9 @@ static long xdl_split(unsigned long const *ha1, long off1, long lim1,
/*
* Rule: "Divide et Impera". Recursively split the box in sub-boxes by calling
* the box splitting function. Note that the real job (marking changed lines)
* is done in the two boundary reaching checks.
* Rule: "Divide et Impera" (divide & conquer). Recursively split the box in
* sub-boxes by calling the box splitting function. Note that the real job
* (marking changed lines) is done in the two boundary reaching checks.
*/
int xdl_recs_cmp(diffdata_t *dd1, long off1, long lim1,
diffdata_t *dd2, long off2, long lim2,
@ -323,7 +328,9 @@ int xdl_do_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
}
/*
* Allocate and setup K vectors to be used by the differential algorithm.
* Allocate and setup K vectors to be used by the differential
* algorithm.
*
* One is to store the forward path and one to store the backward path.
*/
ndiags = xe->xdf1.nreff + xe->xdf2.nreff + 3;
@ -418,13 +425,13 @@ static int xget_indent(xrecord_t *rec)
ret += 1;
else if (c == '\t')
ret += 8 - ret % 8;
// ignore other whitespace characters
/* ignore other whitespace characters */
if (ret >= MAX_INDENT)
return MAX_INDENT;
}
// The line contains only whitespace.
/* The line contains only whitespace. */
return -1;
}
@ -435,7 +442,7 @@ static int xget_indent(xrecord_t *rec)
*/
#define MAX_BLANKS 20
// Characteristics measured about a hypothetical split position.
/* Characteristics measured about a hypothetical split position. */
struct split_measurement {
/*
* Is the split at the end of the file (aside from any blank lines)?
@ -443,8 +450,8 @@ struct split_measurement {
int end_of_file;
/*
* How much is the line immediately following the split indented (or -1 if
* the line is blank):
* How much is the line immediately following the split indented (or -1
* if the line is blank):
*/
int indent;
@ -454,8 +461,8 @@ struct split_measurement {
int pre_blank;
/*
* How much is the nearest non-blank line above the split indented (or -1
* if there is no such line)?
* How much is the nearest non-blank line above the split indented (or
* -1 if there is no such line)?
*/
int pre_indent;
@ -472,10 +479,10 @@ struct split_measurement {
};
struct split_score {
// The effective indent of this split (smaller is preferred).
/* The effective indent of this split (smaller is preferred). */
int effective_indent;
// Penalty for this split (smaller is preferred).
/* Penalty for this split (smaller is preferred). */
int penalty;
};
@ -534,16 +541,16 @@ static void measure_split(const xdfile_t *xdf, long split,
* integer math.
*/
// Penalty if there are no non-blank lines before the split
/* Penalty if there are no non-blank lines before the split */
#define START_OF_FILE_PENALTY 1
// Penalty if there are no non-blank lines after the split
/* Penalty if there are no non-blank lines after the split */
#define END_OF_FILE_PENALTY 21
// Multiplier for the number of blank lines around the split
/* Multiplier for the number of blank lines around the split */
#define TOTAL_BLANK_WEIGHT (-30)
// Multiplier for the number of blank lines after the split
/* Multiplier for the number of blank lines after the split */
#define POST_BLANK_WEIGHT 6
/*
@ -581,13 +588,13 @@ static void measure_split(const xdfile_t *xdf, long split,
/*
* Compute a badness score for the hypothetical split whose measurements are
* stored in m. The weight factors were determined empirically using the tools and
* corpus described in
* stored in m. The weight factors were determined empirically using the tools
* and corpus described in
*
* https://github.com/mhagger/diff-slider-tools
*
* Also see that project if you want to improve the weights based on, for example,
* a larger or more diverse corpus.
* Also see that project if you want to improve the weights based on, for
* example, a larger or more diverse corpus.
*/
static void score_add_split(const struct split_measurement *m, struct split_score *s)
{
@ -610,7 +617,7 @@ static void score_add_split(const struct split_measurement *m, struct split_scor
post_blank = (m->indent == -1) ? 1 + m->post_blank : 0;
total_blank = m->pre_blank + post_blank;
// Penalties based on nearby blank lines:
/* Penalties based on nearby blank lines: */
s->penalty += TOTAL_BLANK_WEIGHT * total_blank;
s->penalty += POST_BLANK_WEIGHT * post_blank;
@ -621,13 +628,13 @@ static void score_add_split(const struct split_measurement *m, struct split_scor
any_blanks = (total_blank != 0);
// Note that the effective indent is -1 at the end of the file:
/* Note that the effective indent is -1 at the end of the file: */
s->effective_indent += indent;
if (indent == -1) {
// No additional adjustments needed.
/* No additional adjustments needed. */
} else if (m->pre_indent == -1) {
// No additional adjustments needed.
/* No additional adjustments needed. */
} else if (indent > m->pre_indent) {
/*
* The line is indented more than its predecessor.
@ -669,7 +676,7 @@ static void score_add_split(const struct split_measurement *m, struct split_scor
static int score_cmp(struct split_score *s1, struct split_score *s2)
{
// -1 if s1.effective_indent < s2->effective_indent, etc.
/* -1 if s1.effective_indent < s2->effective_indent, etc. */
int cmp_indents = ((s1->effective_indent > s2->effective_indent) -
(s1->effective_indent < s2->effective_indent));
@ -809,13 +816,16 @@ int xdl_change_compact(xdfile_t *xdf, xdfile_t *xdfo, long flags) {
group_init(xdfo, &go);
while (1) {
// If the group is empty in the to-be-compacted file, skip it:
/*
* If the group is empty in the to-be-compacted file, skip it:
*/
if (g.end == g.start)
goto next;
/*
* Now shift the change up and then down as far as possible in
* each direction. If it bumps into any other changes, merge them.
* each direction. If it bumps into any other changes, merge
* them.
*/
do {
groupsize = g.end - g.start;
@ -828,7 +838,7 @@ int xdl_change_compact(xdfile_t *xdf, xdfile_t *xdfo, long flags) {
*/
end_matching_other = -1;
// Shift the group backward as much as possible:
/* Shift the group backward as much as possible: */
while (!group_slide_up(xdf, &g, flags))
if (group_previous(xdfo, &go))
xdl_bug("group sync broken sliding up");
@ -842,7 +852,7 @@ int xdl_change_compact(xdfile_t *xdf, xdfile_t *xdfo, long flags) {
if (go.end > go.start)
end_matching_other = g.end;
// Now shift the group forward as far as possible:
/* Now shift the group forward as far as possible: */
while (1) {
if (group_slide_down(xdf, &g, flags))
break;
@ -858,17 +868,17 @@ int xdl_change_compact(xdfile_t *xdf, xdfile_t *xdfo, long flags) {
* If the group can be shifted, then we can possibly use this
* freedom to produce a more intuitive diff.
*
* The group is currently shifted as far down as possible, so the
* heuristics below only have to handle upwards shifts.
* The group is currently shifted as far down as possible, so
* the heuristics below only have to handle upwards shifts.
*/
if (g.end == earliest_end) {
// no shifting was possible
/* no shifting was possible */
} else if (end_matching_other != -1) {
/*
* Move the possibly merged group of changes back to line
* up with the last group of changes from the other file
* that it can align with.
* Move the possibly merged group of changes back to
* line up with the last group of changes from the
* other file that it can align with.
*/
while (go.end == go.start) {
if (group_slide_up(xdf, &g, flags))
@ -879,14 +889,15 @@ int xdl_change_compact(xdfile_t *xdf, xdfile_t *xdfo, long flags) {
} else if (flags & XDF_INDENT_HEURISTIC) {
/*
* Indent heuristic: a group of pure add/delete lines
* implies two splits, one between the end of the "before"
* context and the start of the group, and another between
* the end of the group and the beginning of the "after"
* context. Some splits are aesthetically better and some
* are worse. We compute a badness "score" for each split,
* and add the scores for the two splits to define a
* "score" for each position that the group can be shifted
* to. Then we pick the shift with the lowest score.
* implies two splits, one between the end of the
* "before" context and the start of the group, and
* another between the end of the group and the
* beginning of the "after" context. Some splits are
* aesthetically better and some are worse. We compute
* a badness "score" for each split, and add the scores
* for the two splits to define a "score" for each
* position that the group can be shifted to. Then we
* pick the shift with the lowest score.
*/
long shift, best_shift = -1;
struct split_score best_score;
@ -921,7 +932,7 @@ int xdl_change_compact(xdfile_t *xdf, xdfile_t *xdfo, long flags) {
}
next:
// Move past the just-processed group:
/* Move past the just-processed group: */
if (group_next(xdf, &g))
break;
if (group_next(xdfo, &go))
@ -987,7 +998,7 @@ static int xdl_call_hunk_func(xdfenv_t *xe UNUSED, xdchange_t *xscr, xdemitcb_t
return 0;
}
static void xdl_mark_ignorable(xdchange_t *xscr, xdfenv_t *xe, long flags)
static void xdl_mark_ignorable_lines(xdchange_t *xscr, xdfenv_t *xe, long flags)
{
xdchange_t *xch;
@ -1008,6 +1019,48 @@ static void xdl_mark_ignorable(xdchange_t *xscr, xdfenv_t *xe, long flags)
}
}
#if 0 // unused by Vim
static int record_matches_regex(xrecord_t *rec, xpparam_t const *xpp) {
regmatch_t regmatch;
int i;
for (i = 0; i < xpp->ignore_regex_nr; i++)
if (!regexec_buf(xpp->ignore_regex[i], rec->ptr, rec->size, 1,
&regmatch, 0))
return 1;
return 0;
}
static void xdl_mark_ignorable_regex(xdchange_t *xscr, const xdfenv_t *xe,
xpparam_t const *xpp)
{
xdchange_t *xch;
for (xch = xscr; xch; xch = xch->next) {
xrecord_t **rec;
int ignore = 1;
long i;
/*
* Do not override --ignore-blank-lines.
*/
if (xch->ignore)
continue;
rec = &xe->xdf1.recs[xch->i1];
for (i = 0; i < xch->chg1 && ignore; i++)
ignore = record_matches_regex(rec[i], xpp);
rec = &xe->xdf2.recs[xch->i2];
for (i = 0; i < xch->chg2 && ignore; i++)
ignore = record_matches_regex(rec[i], xpp);
xch->ignore = ignore;
}
}
#endif
int xdl_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
xdemitconf_t const *xecfg, xdemitcb_t *ecb) {
xdchange_t *xscr;
@ -1027,7 +1080,12 @@ int xdl_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
}
if (xscr) {
if (xpp->flags & XDF_IGNORE_BLANK_LINES)
xdl_mark_ignorable(xscr, &xe, xpp->flags);
xdl_mark_ignorable_lines(xscr, &xe, xpp->flags);
#if 0
if (xpp->ignore_regex)
xdl_mark_ignorable_regex(xscr, &xe, xpp);
#endif
if (ef(&xe, xscr, ecb, xecfg) < 0) {

View File

@ -61,4 +61,4 @@ int xdl_do_patience_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
int xdl_do_histogram_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
xdfenv_t *env);
#endif // #if !defined(XDIFFI_H)
#endif /* #if !defined(XDIFFI_H) */

View File

@ -31,7 +31,7 @@ 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) {
long size, psize = (long)strlen(pre);
long size, psize = strlen(pre);
char const *rec;
size = xdl_get_rec(xdf, ri, &rec);
@ -54,9 +54,9 @@ xdchange_t *xdl_get_hunk(xdchange_t **xscr, xdemitconf_t const *xecfg)
xdchange_t *xch, *xchp, *lxch;
long max_common = 2 * xecfg->ctxlen + xecfg->interhunkctxlen;
long max_ignorable = xecfg->ctxlen;
unsigned long ignored = 0; // number of ignored blank lines
unsigned long ignored = 0; /* number of ignored blank lines */
// remove ignorable changes that are too far before other changes
/* remove ignorable changes that are too far before other changes */
for (xchp = *xscr; xchp && xchp->ignore; xchp = xchp->next) {
xch = xchp->next;
@ -99,9 +99,9 @@ xdchange_t *xdl_get_hunk(xdchange_t **xscr, xdemitconf_t const *xecfg)
static long def_ff(const char *rec, long len, char *buf, long sz, void *priv UNUSED)
{
if (len > 0 &&
(isalpha((unsigned char)*rec) || // identifier?
*rec == '_' || // also identifier?
*rec == '$')) { // identifiers from VMS and other esoterico
(isalpha((unsigned char)*rec) || /* identifier? */
*rec == '_' || /* also identifier? */
*rec == '$')) { /* identifiers from VMS and other esoterico */
if (len > sz)
len = sz;
while (0 < len && isspace((unsigned char)rec[len - 1]))
@ -197,7 +197,7 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
if (xecfg->flags & XDL_EMIT_FUNCCONTEXT) {
long fs1, i1 = xch->i1;
// Appended chunk?
/* Appended chunk? */
if (i1 >= xe->xdf1.nrec) {
long i2 = xch->i2;
@ -225,8 +225,23 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
if (fs1 < 0)
fs1 = 0;
if (fs1 < s1) {
s2 -= s1 - fs1;
s2 = XDL_MAX(s2 - (s1 - fs1), 0);
s1 = fs1;
/*
* Did we extend context upwards into an
* ignored change?
*/
while (xchp != xch &&
xchp->i1 + xchp->chg1 <= s1 &&
xchp->i2 + xchp->chg2 <= s2)
xchp = xchp->next;
/* If so, show it after all. */
if (xchp != xch) {
xch = xchp;
goto pre_context_calculation;
}
}
}
@ -249,7 +264,7 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
if (fe1 < 0)
fe1 = xe->xdf1.nrec;
if (fe1 > e1) {
e2 += fe1 - e1;
e2 = XDL_MIN(e2 + (fe1 - e1), xe->xdf2.nrec);
e1 = fe1;
}
@ -281,7 +296,8 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
funclineprev = s1 - 1;
}
#endif
if (xdl_emit_hunk_hdr(s1 + 1, e1 - s1, s2 + 1, e2 - s2,
if (!(xecfg->flags & XDL_EMIT_NO_HUNK_HDR) &&
xdl_emit_hunk_hdr(s1 + 1, e1 - s1, s2 + 1, e2 - s2,
func_line.buf, func_line.len, ecb) < 0)
return -1;

View File

@ -33,4 +33,4 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
#endif // #if !defined(XEMIT_H)
#endif /* #if !defined(XEMIT_H) */

View File

@ -42,8 +42,6 @@
*/
#include "xinclude.h"
#include "xtypes.h"
#include "xdiff.h"
#define MAX_PTR INT_MAX
#define MAX_CNT INT_MAX
@ -55,8 +53,8 @@ struct histindex {
struct record {
unsigned int ptr, cnt;
struct record *next;
} **records, // an occurrence
**line_map; // map of line to record chain
} **records, /* an occurrence */
**line_map; /* map of line to record chain */
chastore_t rcha;
unsigned int *next_ptrs;
unsigned int table_bits,
@ -128,7 +126,7 @@ static int scanA(struct histindex *index, int line1, int count1)
*/
NEXT_PTR(index, ptr) = rec->ptr;
rec->ptr = ptr;
// cap rec->cnt at MAX_CNT
/* cap rec->cnt at MAX_CNT */
rec->cnt = XDL_MIN(MAX_CNT, rec->cnt + 1);
LINE_MAP(index, ptr) = rec;
goto continue_scan;
@ -154,7 +152,7 @@ static int scanA(struct histindex *index, int line1, int count1)
LINE_MAP(index, ptr) = rec;
continue_scan:
; // no op
; /* no op */
}
return 0;
@ -237,6 +235,8 @@ static int fall_back_to_classic_diff(xpparam_t const *xpp, xdfenv_t *env,
int line1, int count1, int line2, int count2)
{
xpparam_t xpparam;
memset(&xpparam, 0, sizeof(xpparam));
xpparam.flags = xpp->flags & ~XDF_DIFF_ALGORITHM_MASK;
return xdl_fall_back_diff(env, &xpparam,
@ -266,7 +266,7 @@ static int find_lcs(xpparam_t const *xpp, xdfenv_t *env,
index.records = NULL;
index.line_map = NULL;
// in case of early xdl_cha_free()
/* in case of early xdl_cha_free() */
index.rcha.head = NULL;
index.table_bits = xdl_hashbits(count1);
@ -288,7 +288,7 @@ static int find_lcs(xpparam_t const *xpp, xdfenv_t *env,
goto cleanup;
memset(index.next_ptrs, 0, sz);
// lines / 4 + 1 comes from xprepare.c:xdl_prepare_ctx()
/* lines / 4 + 1 comes from xprepare.c:xdl_prepare_ctx() */
if (xdl_cha_init(&index.rcha, sizeof(struct record), count1 / 4 + 1) < 0)
goto cleanup;

View File

@ -40,6 +40,7 @@
#if !defined(XINCLUDE_H)
#define XINCLUDE_H
// This effectively re-verts b46054b3746271d23feab0 from git
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
@ -48,7 +49,10 @@
#endif
#include <string.h>
#include <limits.h>
// This include comes from git, so uncomment it
#if 0
#include "git-compat-util.h"
#endif
#include "xmacros.h"
#include "xdiff.h"
#include "xtypes.h"
@ -58,4 +62,4 @@
#include "xemit.h"
#endif // #if !defined(XINCLUDE_H)
#endif /* #if !defined(XINCLUDE_H) */

View File

@ -51,4 +51,4 @@ do { \
} while (0)
#endif // #if !defined(XMACROS_H)
#endif /* #if !defined(XMACROS_H) */

View File

@ -20,8 +20,6 @@
*
*/
#include "xinclude.h"
#include "xtypes.h"
#include "xdiff.h"
/*
* The basic idea of patience diff is to find lines that are unique in
@ -69,7 +67,7 @@ struct hashmap {
*/
unsigned anchor : 1;
} *entries, *first, *last;
// were common records found?
/* were common records found? */
unsigned long has_matches;
mmfile_t *file1, *file2;
xdfenv_t *env;
@ -78,21 +76,21 @@ struct hashmap {
static int is_anchor(xpparam_t const *xpp, const char *line)
{
size_t i;
for (i = 0; i < xpp->anchors_nr; i++) {
int i;
for (i = 0; i < (int)xpp->anchors_nr; i++) {
if (!strncmp(line, xpp->anchors[i], strlen(xpp->anchors[i])))
return 1;
}
return 0;
}
// The argument "pass" is 1 for the first file, 2 for the second.
/* The argument "pass" is 1 for the first file, 2 for the second. */
static void insert_record(xpparam_t const *xpp, int line, struct hashmap *map,
int pass)
{
xrecord_t **records = pass == 1 ?
map->env->xdf1.recs : map->env->xdf2.recs;
xrecord_t *record = records[line - 1], *other;
xrecord_t *record = records[line - 1];
/*
* After xdl_prepare_env() (or more precisely, due to
* xdl_classify_record()), the "ha" member of the records (AKA lines)
@ -106,11 +104,7 @@ static void insert_record(xpparam_t const *xpp, int line, struct hashmap *map,
int index = (int)((record->ha << 1) % map->alloc);
while (map->entries[index].line1) {
other = map->env->xdf1.recs[map->entries[index].line1 - 1];
if (map->entries[index].hash != record->ha ||
!xdl_recmatch(record->ptr, record->size,
other->ptr, other->size,
map->xpp->flags)) {
if (map->entries[index].hash != record->ha) {
if (++index >= map->alloc)
index = 0;
continue;
@ -155,7 +149,7 @@ static int fill_hashmap(mmfile_t *file1, mmfile_t *file2,
result->xpp = xpp;
result->env = env;
// We know exactly how large we want the hash map
/* We know exactly how large we want the hash map */
result->alloc = count1 * 2;
result->entries = (struct entry *)
xdl_malloc(result->alloc * sizeof(struct entry));
@ -163,11 +157,11 @@ static int fill_hashmap(mmfile_t *file1, mmfile_t *file2,
return -1;
memset(result->entries, 0, result->alloc * sizeof(struct entry));
// First, fill with entries from the first file
/* First, fill with entries from the first file */
while (count1--)
insert_record(xpp, line1++, result, 1);
// Then search for matches in the second file
/* Then search for matches in the second file */
while (count2--)
insert_record(xpp, line2++, result, 2);
@ -185,13 +179,13 @@ static int binary_search(struct entry **sequence, int longest,
while (left + 1 < right) {
int middle = left + (right - left) / 2;
// by construction, no two entries can be equal
/* by construction, no two entries can be equal */
if (sequence[middle]->line2 > entry->line2)
right = middle;
else
left = middle;
}
// return the index in "sequence", _not_ the sequence length
/* return the index in "sequence", _not_ the sequence length */
return left;
}
@ -206,9 +200,10 @@ static int binary_search(struct entry **sequence, int longest,
*/
static struct entry *find_longest_common_sequence(struct hashmap *map)
{
struct entry **sequence = (struct entry **)xdl_malloc(map->nr * sizeof(struct entry *));
struct entry **sequence = xdl_malloc(map->nr * sizeof(struct entry *));
int longest = 0, i;
struct entry *entry;
/*
* If not -1, this entry in sequence must never be overridden.
* Therefore, overriding entries before this has no effect, so
@ -237,13 +232,13 @@ static struct entry *find_longest_common_sequence(struct hashmap *map)
}
}
// No common unique lines were found
/* No common unique lines were found */
if (!longest) {
xdl_free(sequence);
return NULL;
}
// Iterate starting at the last element, adjusting the "next" members
/* Iterate starting at the last element, adjusting the "next" members */
entry = sequence[longest - 1];
entry->next = NULL;
while (entry->previous) {
@ -258,8 +253,7 @@ static int match(struct hashmap *map, int line1, int line2)
{
xrecord_t *record1 = map->env->xdf1.recs[line1 - 1];
xrecord_t *record2 = map->env->xdf2.recs[line2 - 1];
return xdl_recmatch(record1->ptr, record1->size,
record2->ptr, record2->size, map->xpp->flags);
return record1->ha == record2->ha;
}
static int patience_diff(mmfile_t *file1, mmfile_t *file2,
@ -273,7 +267,7 @@ static int walk_common_sequence(struct hashmap *map, struct entry *first,
int next1, next2;
for (;;) {
// Try to grow the line ranges of common lines
/* Try to grow the line ranges of common lines */
if (first) {
next1 = first->line1;
next2 = first->line2;
@ -292,11 +286,8 @@ static int walk_common_sequence(struct hashmap *map, struct entry *first,
line2++;
}
// Recurse
/* Recurse */
if (next1 > line1 || next2 > line2) {
struct hashmap submap;
memset(&submap, 0, sizeof(submap));
if (patience_diff(map->file1, map->file2,
map->xpp, map->env,
line1, next1 - line1,
@ -323,6 +314,8 @@ static int fall_back_to_classic_diff(struct hashmap *map,
int line1, int count1, int line2, int count2)
{
xpparam_t xpp;
memset(&xpp, 0, sizeof(xpp));
xpp.flags = map->xpp->flags & ~XDF_DIFF_ALGORITHM_MASK;
return xdl_fall_back_diff(map->env, &xpp,
@ -343,7 +336,7 @@ static int patience_diff(mmfile_t *file1, mmfile_t *file2,
struct entry *first;
int result = 0;
// trivial case: one side is empty
/* trivial case: one side is empty */
if (!count1) {
while(count2--)
env->xdf2.rchg[line2++ - 1] = 1;
@ -359,7 +352,7 @@ static int patience_diff(mmfile_t *file1, mmfile_t *file2,
line1, count1, line2, count2))
return -1;
// are there any matching lines at all?
/* are there any matching lines at all? */
if (!map.has_matches) {
while(count1--)
env->xdf1.rchg[line1++ - 1] = 1;
@ -387,7 +380,7 @@ int xdl_do_patience_diff(mmfile_t *file1, mmfile_t *file2,
if (xdl_prepare_env(file1, file2, xpp, env) < 0)
return -1;
// environment is cleaned up in xdl_diff()
/* environment is cleaned up in xdl_diff() */
return patience_diff(file1, file2, xpp, env,
1, env->xdf1.nrec, 1, env->xdf2.nrec);
}

View File

@ -31,4 +31,4 @@ void xdl_free_env(xdfenv_t *xe);
#endif // #if !defined(XPREPARE_H)
#endif /* #if !defined(XPREPARE_H) */

View File

@ -64,4 +64,4 @@ typedef struct s_xdfenv {
#endif // #if !defined(XTYPES_H)
#endif /* #if !defined(XTYPES_H) */

View File

@ -20,13 +20,9 @@
*
*/
#include <limits.h>
#include <assert.h>
#include "xinclude.h"
long xdl_bogosqrt(long n) {
long i;
@ -51,10 +47,10 @@ int xdl_emit_diffrec(char const *rec, long size, char const *pre, long psize,
mb[1].size = size;
if (size > 0 && rec[size - 1] != '\n') {
mb[2].ptr = (char *) "\n\\ No newline at end of file\n";
mb[2].size = (long)strlen(mb[2].ptr);
mb[2].size = strlen(mb[2].ptr);
i++;
}
if (ecb->outf(ecb->priv, mb, i) < 0) {
if (ecb->out_line(ecb->priv, mb, i) < 0) {
return -1;
}
@ -168,7 +164,7 @@ static int ends_with_optional_cr(const char *l, long s, long i)
s--;
if (s == i)
return 1;
// do not ignore CR at the end of an incomplete line
/* do not ignore CR at the end of an incomplete line */
if (complete && s == i + 1 && l[i] == '\r')
return 1;
return 0;
@ -208,7 +204,7 @@ int xdl_recmatch(const char *l1, long s1, const char *l2, long s2, long flags)
} else if (flags & XDF_IGNORE_WHITESPACE_CHANGE) {
while (i1 < s1 && i2 < s2) {
if (XDL_ISSPACE(l1[i1]) && XDL_ISSPACE(l2[i2])) {
// Skip matching spaces and try again
/* Skip matching spaces and try again */
while (i1 < s1 && XDL_ISSPACE(l1[i1]))
i1++;
while (i2 < s2 && XDL_ISSPACE(l2[i2]))
@ -224,7 +220,7 @@ int xdl_recmatch(const char *l1, long s1, const char *l2, long s2, long flags)
i2++;
}
} else if (flags & XDF_IGNORE_CR_AT_EOL) {
// Find the first difference and see how the line ends
/* Find the first difference and see how the line ends */
while (i1 < s1 && i2 < s2 && l1[i1] == l2[i2]) {
i1++;
i2++;
@ -261,7 +257,7 @@ static unsigned long xdl_hash_record_with_whitespace(char const **data,
for (; ptr < top && *ptr != '\n'; ptr++) {
if (cr_at_eol_only) {
// do not ignore CR at the end of an incomplete line
/* do not ignore CR at the end of an incomplete line */
if (*ptr == '\r' &&
(ptr + 1 < top && ptr[1] == '\n'))
continue;
@ -274,7 +270,7 @@ static unsigned long xdl_hash_record_with_whitespace(char const **data,
ptr++;
at_eol = (top <= ptr + 1 || ptr[1] == '\n');
if (flags & XDF_IGNORE_WHITESPACE)
; // already handled
; /* already handled */
else if (flags & XDF_IGNORE_WHITESPACE_CHANGE
&& !at_eol) {
ha += (ha << 5);
@ -344,8 +340,9 @@ int xdl_num_out(char *out, long val) {
return str - out;
}
int xdl_emit_hunk_hdr(long s1, long c1, long s2, long c2,
const char *func, long funclen, xdemitcb_t *ecb) {
static int xdl_format_hunk_hdr(long s1, long c1, long s2, long c2,
const char *func, long funclen,
xdemitcb_t *ecb) {
int nb = 0;
mmbuffer_t mb;
char buf[128];
@ -387,9 +384,21 @@ int xdl_emit_hunk_hdr(long s1, long c1, long s2, long c2,
mb.ptr = buf;
mb.size = nb;
if (ecb->outf(ecb->priv, &mb, 1) < 0)
if (ecb->out_line(ecb->priv, &mb, 1) < 0)
return -1;
return 0;
}
int xdl_emit_hunk_hdr(long s1, long c1, long s2, long c2,
const char *func, long funclen,
xdemitcb_t *ecb) {
if (!ecb->out_hunk)
return xdl_format_hunk_hdr(s1, c1, s2, c2, func, funclen, ecb);
if (ecb->out_hunk(ecb->priv,
c1 ? s1 : s1 - 1, c1,
c2 ? s2 : s2 - 1, c2,
func, funclen) < 0)
return -1;
return 0;
}

View File

@ -44,4 +44,4 @@ int xdl_fall_back_diff(xdfenv_t *diff_env, xpparam_t const *xpp,
#endif // #if !defined(XUTILS_H)
#endif /* #if !defined(XUTILS_H) */