Patch 9.0.1418
Problem:    The included xdiff code is a bit outdated.
Solution:   Sync with the latest git xdiff code. (Yee Cheng Chin,
            closes #12181)
Files:      src/xdiff/README.txt, src/xdiff/xdiff.h, src/xdiff/xdiffi.c,
            src/xdiff/xdiffi.h, src/xdiff/xemit.c, src/xdiff/xhistogram.c,
            src/xdiff/xmacros.h, src/xdiff/xpatience.c, src/xdiff/xprepare.c,
            src/xdiff/xutils.c, src/xdiff/xutils.h


*** ../vim-9.0.1417/src/xdiff/README.txt        2021-09-01 10:08:10.000000000 
+0100
--- src/xdiff/README.txt        2023-03-20 17:20:10.111087422 +0000
***************
*** 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 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
--- 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 March 17, 2023 from git release v.2.40.0
  
  This is originally based on libxdiff, which can be found here:
  http://www.xmailserver.org/xdiff-lib.html
*** ../vim-9.0.1417/src/xdiff/xdiff.h   2021-08-31 19:27:29.000000000 +0100
--- src/xdiff/xdiff.h   2023-03-20 17:20:10.111087422 +0000
***************
*** 66,71 ****
--- 66,72 ----
  
  /* merge output styles */
  #define XDL_MERGE_DIFF3 1
+ #define XDL_MERGE_ZEALOUS_DIFF3 2
  
  typedef struct s_mmfile {
        char *ptr;
***************
*** 126,131 ****
--- 127,133 ----
  #endif
  
  #define xdl_malloc(x) lalloc((x), TRUE)
+ #define xdl_calloc(n, sz) lalloc_clear(n*sz, TRUE)
  #define xdl_free(ptr) vim_free(ptr)
  #define xdl_realloc(ptr,x) vim_realloc((ptr),(x))
  
*** ../vim-9.0.1417/src/xdiff/xdiffi.c  2021-08-31 19:27:29.000000000 +0100
--- src/xdiff/xdiffi.c  2023-03-20 17:20:10.111087422 +0000
***************
*** 315,330 ****
        long *kvd, *kvdf, *kvdb;
        xdalgoenv_t xenv;
        diffdata_t dd1, dd2;
  
!       if (XDF_DIFF_ALG(xpp->flags) == XDF_PATIENCE_DIFF)
!               return xdl_do_patience_diff(mf1, mf2, xpp, xe);
! 
!       if (XDF_DIFF_ALG(xpp->flags) == XDF_HISTOGRAM_DIFF)
!               return xdl_do_histogram_diff(mf1, mf2, xpp, xe);
  
!       if (xdl_prepare_env(mf1, mf2, xpp, xe) < 0) {
  
!               return -1;
        }
  
        /*
--- 315,333 ----
        long *kvd, *kvdf, *kvdb;
        xdalgoenv_t xenv;
        diffdata_t dd1, dd2;
+       int res;
  
!       if (xdl_prepare_env(mf1, mf2, xpp, xe) < 0)
!               return -1;
  
!       if (XDF_DIFF_ALG(xpp->flags) == XDF_PATIENCE_DIFF) {
!               res = xdl_do_patience_diff(xpp, xe);
!               goto out;
!       }
  
!       if (XDF_DIFF_ALG(xpp->flags) == XDF_HISTOGRAM_DIFF) {
!               res = xdl_do_histogram_diff(xpp, xe);
!               goto out;
        }
  
        /*
***************
*** 334,340 ****
         * One is to store the forward path and one to store the backward path.
         */
        ndiags = xe->xdf1.nreff + xe->xdf2.nreff + 3;
!       if (!(kvd = (long *) xdl_malloc((2 * ndiags + 2) * sizeof(long)))) {
  
                xdl_free_env(xe);
                return -1;
--- 337,343 ----
         * One is to store the forward path and one to store the backward path.
         */
        ndiags = xe->xdf1.nreff + xe->xdf2.nreff + 3;
!       if (!XDL_ALLOC_ARRAY(kvd, 2 * ndiags + 2)) {
  
                xdl_free_env(xe);
                return -1;
***************
*** 359,375 ****
        dd2.rchg = xe->xdf2.rchg;
        dd2.rindex = xe->xdf2.rindex;
  
!       if (xdl_recs_cmp(&dd1, 0, dd1.nrec, &dd2, 0, dd2.nrec,
!                        kvdf, kvdb, (xpp->flags & XDF_NEED_MINIMAL) != 0, 
&xenv) < 0) {
! 
!               xdl_free(kvd);
!               xdl_free_env(xe);
!               return -1;
!       }
! 
        xdl_free(kvd);
  
!       return 0;
  }
  
  
--- 362,376 ----
        dd2.rchg = xe->xdf2.rchg;
        dd2.rindex = xe->xdf2.rindex;
  
!       res = xdl_recs_cmp(&dd1, 0, dd1.nrec, &dd2, 0, dd2.nrec,
!                          kvdf, kvdb, (xpp->flags & XDF_NEED_MINIMAL) != 0,
!                          &xenv);
        xdl_free(kvd);
+  out:
+       if (res < 0)
+               xdl_free_env(xe);
  
!       return res;
  }
  
  
***************
*** 390,401 ****
  }
  
  
! static int recs_match(xrecord_t *rec1, xrecord_t *rec2, long flags)
  {
!       return (rec1->ha == rec2->ha &&
!               xdl_recmatch(rec1->ptr, rec1->size,
!                            rec2->ptr, rec2->size,
!                            flags));
  }
  
  /*
--- 391,399 ----
  }
  
  
! static int recs_match(xrecord_t *rec1, xrecord_t *rec2)
  {
!       return (rec1->ha == rec2->ha);
  }
  
  /*
***************
*** 759,768 ****
   * following group, expand this group to include it. Return 0 on success or -1
   * if g cannot be slid down.
   */
! static int group_slide_down(xdfile_t *xdf, struct xdlgroup *g, long flags)
  {
        if (g->end < xdf->nrec &&
!           recs_match(xdf->recs[g->start], xdf->recs[g->end], flags)) {
                xdf->rchg[g->start++] = 0;
                xdf->rchg[g->end++] = 1;
  
--- 757,766 ----
   * following group, expand this group to include it. Return 0 on success or -1
   * if g cannot be slid down.
   */
! static int group_slide_down(xdfile_t *xdf, struct xdlgroup *g)
  {
        if (g->end < xdf->nrec &&
!           recs_match(xdf->recs[g->start], xdf->recs[g->end])) {
                xdf->rchg[g->start++] = 0;
                xdf->rchg[g->end++] = 1;
  
***************
*** 780,789 ****
   * into a previous group, expand this group to include it. Return 0 on success
   * or -1 if g cannot be slid up.
   */
! static int group_slide_up(xdfile_t *xdf, struct xdlgroup *g, long flags)
  {
        if (g->start > 0 &&
!           recs_match(xdf->recs[g->start - 1], xdf->recs[g->end - 1], flags)) {
                xdf->rchg[--g->start] = 1;
                xdf->rchg[--g->end] = 0;
  
--- 778,787 ----
   * into a previous group, expand this group to include it. Return 0 on success
   * or -1 if g cannot be slid up.
   */
! static int group_slide_up(xdfile_t *xdf, struct xdlgroup *g)
  {
        if (g->start > 0 &&
!           recs_match(xdf->recs[g->start - 1], xdf->recs[g->end - 1])) {
                xdf->rchg[--g->start] = 1;
                xdf->rchg[--g->end] = 0;
  
***************
*** 839,845 ****
                        end_matching_other = -1;
  
                        /* 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");
  
--- 837,843 ----
                        end_matching_other = -1;
  
                        /* Shift the group backward as much as possible: */
!                       while (!group_slide_up(xdf, &g))
                                if (group_previous(xdfo, &go))
                                        xdl_bug("group sync broken sliding up");
  
***************
*** 854,860 ****
  
                        /* Now shift the group forward as far as possible: */
                        while (1) {
!                               if (group_slide_down(xdf, &g, flags))
                                        break;
                                if (group_next(xdfo, &go))
                                        xdl_bug("group sync broken sliding 
down");
--- 852,858 ----
  
                        /* Now shift the group forward as far as possible: */
                        while (1) {
!                               if (group_slide_down(xdf, &g))
                                        break;
                                if (group_next(xdfo, &go))
                                        xdl_bug("group sync broken sliding 
down");
***************
*** 881,887 ****
                         * other file that it can align with.
                         */
                        while (go.end == go.start) {
!                               if (group_slide_up(xdf, &g, flags))
                                        xdl_bug("match disappeared");
                                if (group_previous(xdfo, &go))
                                        xdl_bug("group sync broken sliding to 
match");
--- 879,885 ----
                         * other file that it can align with.
                         */
                        while (go.end == go.start) {
!                               if (group_slide_up(xdf, &g))
                                        xdl_bug("match disappeared");
                                if (group_previous(xdfo, &go))
                                        xdl_bug("group sync broken sliding to 
match");
***************
*** 924,930 ****
                        }
  
                        while (g.end > best_shift) {
!                               if (group_slide_up(xdf, &g, flags))
                                        xdl_bug("best shift unreached");
                                if (group_previous(xdfo, &go))
                                        xdl_bug("group sync broken sliding to 
blank line");
--- 922,928 ----
                        }
  
                        while (g.end > best_shift) {
!                               if (group_slide_up(xdf, &g))
                                        xdl_bug("best shift unreached");
                                if (group_previous(xdfo, &go))
                                        xdl_bug("group sync broken sliding to 
blank line");
*** ../vim-9.0.1417/src/xdiff/xdiffi.h  2021-08-31 19:27:29.000000000 +0100
--- src/xdiff/xdiffi.h  2023-03-20 17:20:10.111087422 +0000
***************
*** 56,64 ****
  void xdl_free_script(xdchange_t *xscr);
  int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
                  xdemitconf_t const *xecfg);
! int xdl_do_patience_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
!               xdfenv_t *env);
! int xdl_do_histogram_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
!               xdfenv_t *env);
  
  #endif /* #if !defined(XDIFFI_H) */
--- 56,62 ----
  void xdl_free_script(xdchange_t *xscr);
  int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
                  xdemitconf_t const *xecfg);
! int xdl_do_patience_diff(xpparam_t const *xpp, xdfenv_t *env);
! int xdl_do_histogram_diff(xpparam_t const *xpp, xdfenv_t *env);
  
  #endif /* #if !defined(XDIFFI_H) */
*** ../vim-9.0.1417/src/xdiff/xemit.c   2021-09-13 21:14:59.000000000 +0100
--- src/xdiff/xemit.c   2023-03-20 17:20:10.111087422 +0000
***************
*** 65,71 ****
                        *xscr = xch;
        }
  
!       if (*xscr == NULL)
                return NULL;
  
        lxch = *xscr;
--- 65,71 ----
                        *xscr = xch;
        }
  
!       if (!*xscr)
                return NULL;
  
        lxch = *xscr;
***************
*** 96,102 ****
  
  
  #if 0
! static long def_ff(const char *rec, long len, char *buf, long sz, void *priv 
UNUSED)
  {
        if (len > 0 &&
                        (isalpha((unsigned char)*rec) || /* identifier? */
--- 96,102 ----
  
  
  #if 0
! static long def_ff(const char *rec, long len, char *buf, long sz)
  {
        if (len > 0 &&
                        (isalpha((unsigned char)*rec) || /* identifier? */
***************
*** 120,126 ****
        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);
  }
  #endif
--- 120,126 ----
        const char *rec;
        long len = xdl_get_rec(xdf, ri, &rec);
        if (!xecfg->find_func)
!               return def_ff(rec, len, buf, sz);
        return xecfg->find_func(rec, len, buf, sz, xecfg->find_func_priv);
  }
  #endif
*** ../vim-9.0.1417/src/xdiff/xhistogram.c      2021-08-31 19:27:29.000000000 
+0100
--- src/xdiff/xhistogram.c      2023-03-20 17:20:10.111087422 +0000
***************
*** 88,106 ****
  #define REC(env, s, l) \
        (env->xdf##s.recs[l - 1])
  
! static int cmp_recs(xpparam_t const *xpp,
!       xrecord_t *r1, xrecord_t *r2)
  {
!       return r1->ha == r2->ha &&
!               xdl_recmatch(r1->ptr, r1->size, r2->ptr, r2->size,
!                           xpp->flags);
! }
  
! #define CMP_ENV(xpp, env, s1, l1, s2, l2) \
!       (cmp_recs(xpp, REC(env, s1, l1), REC(env, s2, l2)))
  
  #define CMP(i, s1, l1, s2, l2) \
!       (cmp_recs(i->xpp, REC(i->env, s1, l1), REC(i->env, s2, l2)))
  
  #define TABLE_HASH(index, side, line) \
        XDL_HASHLONG((REC(index->env, side, line))->ha, index->table_bits)
--- 88,101 ----
  #define REC(env, s, l) \
        (env->xdf##s.recs[l - 1])
  
! static int cmp_recs(xrecord_t *r1, xrecord_t *r2)
  {
!       return r1->ha == r2->ha;
  
! }
  
  #define CMP(i, s1, l1, s2, l2) \
!       (cmp_recs(REC(i->env, s1, l1), REC(i->env, s2, l2)))
  
  #define TABLE_HASH(index, side, line) \
        XDL_HASHLONG((REC(index->env, side, line))->ha, index->table_bits)
***************
*** 256,262 ****
                    int line1, int count1, int line2, int count2)
  {
        int b_ptr;
!       int sz, ret = -1;
        struct histindex index;
  
        memset(&index, 0, sizeof(index));
--- 251,257 ----
                    int line1, int count1, int line2, int count2)
  {
        int b_ptr;
!       int ret = -1;
        struct histindex index;
  
        memset(&index, 0, sizeof(index));
***************
*** 270,292 ****
        index.rcha.head = NULL;
  
        index.table_bits = xdl_hashbits(count1);
!       sz = index.records_size = 1 << index.table_bits;
!       sz *= sizeof(struct record *);
!       if (!(index.records = (struct record **) xdl_malloc(sz)))
                goto cleanup;
-       memset(index.records, 0, sz);
  
!       sz = index.line_map_size = count1;
!       sz *= sizeof(struct record *);
!       if (!(index.line_map = (struct record **) xdl_malloc(sz)))
                goto cleanup;
-       memset(index.line_map, 0, sz);
  
!       sz = index.line_map_size;
!       sz *= sizeof(unsigned int);
!       if (!(index.next_ptrs = (unsigned int *) xdl_malloc(sz)))
                goto cleanup;
-       memset(index.next_ptrs, 0, sz);
  
        /* lines / 4 + 1 comes from xprepare.c:xdl_prepare_ctx() */
        if (xdl_cha_init(&index.rcha, sizeof(struct record), count1 / 4 + 1) < 
0)
--- 265,280 ----
        index.rcha.head = NULL;
  
        index.table_bits = xdl_hashbits(count1);
!       index.records_size = 1 << index.table_bits;
!       if (!XDL_CALLOC_ARRAY(index.records, index.records_size))
                goto cleanup;
  
!       index.line_map_size = count1;
!       if (!XDL_CALLOC_ARRAY(index.line_map, index.line_map_size))
                goto cleanup;
  
!       if (!XDL_CALLOC_ARRAY(index.next_ptrs, index.line_map_size))
                goto cleanup;
  
        /* lines / 4 + 1 comes from xprepare.c:xdl_prepare_ctx() */
        if (xdl_cha_init(&index.rcha, sizeof(struct record), count1 / 4 + 1) < 
0)
***************
*** 374,385 ****
        return result;
  }
  
! int xdl_do_histogram_diff(mmfile_t *file1, mmfile_t *file2,
!       xpparam_t const *xpp, xdfenv_t *env)
  {
-       if (xdl_prepare_env(file1, file2, xpp, env) < 0)
-               return -1;
- 
        return histogram_diff(xpp, env,
                env->xdf1.dstart + 1, env->xdf1.dend - env->xdf1.dstart + 1,
                env->xdf2.dstart + 1, env->xdf2.dend - env->xdf2.dstart + 1);
--- 362,369 ----
        return result;
  }
  
! int xdl_do_histogram_diff(xpparam_t const *xpp, xdfenv_t *env)
  {
        return histogram_diff(xpp, env,
                env->xdf1.dstart + 1, env->xdf1.dend - env->xdf1.dstart + 1,
                env->xdf2.dstart + 1, env->xdf2.dend - env->xdf2.dstart + 1);
*** ../vim-9.0.1417/src/xdiff/xmacros.h 2021-08-31 19:27:29.000000000 +0100
--- src/xdiff/xmacros.h 2023-03-20 17:20:10.111087422 +0000
***************
*** 34,40 ****
  #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))
- #define XDL_PTRFREE(p) do { if (p) { xdl_free(p); (p) = NULL; } } while (0)
  #define XDL_LE32_PUT(p, v) \
  do { \
        unsigned char *__p = (unsigned char *) (p); \
--- 34,39 ----
***************
*** 50,54 ****
--- 49,71 ----
                ((unsigned long) __p[2]) << 16 | ((unsigned long) __p[3]) << 
24; \
  } while (0)
  
+ /* Allocate an array of nr elements, returns NULL on failure */
+ #define XDL_ALLOC_ARRAY(p, nr)                                \
+       ((p) = SIZE_MAX / sizeof(*(p)) >= (size_t)(nr)  \
+               ? xdl_malloc((nr) * sizeof(*(p)))       \
+               : NULL)
+ 
+ /* Allocate an array of nr zeroed out elements, returns NULL on failure */
+ #define XDL_CALLOC_ARRAY(p, nr)       ((p) = xdl_calloc(nr, sizeof(*(p))))
+ 
+ /*
+  * Ensure array p can accommodate at least nr elements, growing the
+  * array and updating alloc (which is the number of allocated
+  * elements) as necessary. Frees p and returns -1 on failure, returns
+  * 0 on success
+  */
+ #define XDL_ALLOC_GROW(p, nr, alloc)  \
+       (-!((nr) <= (alloc) ||          \
+           ((p) = xdl_alloc_grow_helper((p), (nr), &(alloc), sizeof(*(p))))))
  
  #endif /* #if !defined(XMACROS_H) */
*** ../vim-9.0.1417/src/xdiff/xpatience.c       2021-08-31 19:27:29.000000000 
+0100
--- src/xdiff/xpatience.c       2023-03-20 17:20:10.111087422 +0000
***************
*** 69,75 ****
        } *entries, *first, *last;
        /* were common records found? */
        unsigned long has_matches;
-       mmfile_t *file1, *file2;
        xdfenv_t *env;
        xpparam_t const *xpp;
  };
--- 69,74 ----
***************
*** 139,161 ****
   *
   * It is assumed that env has been prepared using xdl_prepare().
   */
! static int fill_hashmap(mmfile_t *file1, mmfile_t *file2,
!               xpparam_t const *xpp, xdfenv_t *env,
                struct hashmap *result,
                int line1, int count1, int line2, int count2)
  {
-       result->file1 = file1;
-       result->file2 = file2;
        result->xpp = xpp;
        result->env = env;
  
        /* 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));
!       if (!result->entries)
                return -1;
-       memset(result->entries, 0, result->alloc * sizeof(struct entry));
  
        /* First, fill with entries from the first file */
        while (count1--)
--- 138,154 ----
   *
   * It is assumed that env has been prepared using xdl_prepare().
   */
! static int fill_hashmap(xpparam_t const *xpp, xdfenv_t *env,
                struct hashmap *result,
                int line1, int count1, int line2, int count2)
  {
        result->xpp = xpp;
        result->env = env;
  
        /* We know exactly how large we want the hash map */
        result->alloc = count1 * 2;
!       if (!XDL_CALLOC_ARRAY(result->entries, result->alloc))
                return -1;
  
        /* First, fill with entries from the first file */
        while (count1--)
***************
*** 198,206 ****
   * item per sequence length: the sequence with the smallest last
   * element (in terms of line2).
   */
! static struct entry *find_longest_common_sequence(struct hashmap *map)
  {
!       struct entry **sequence = xdl_malloc(map->nr * sizeof(struct entry *));
        int longest = 0, i;
        struct entry *entry;
  
--- 191,199 ----
   * item per sequence length: the sequence with the smallest last
   * element (in terms of line2).
   */
! static int find_longest_common_sequence(struct hashmap *map, struct entry 
**res)
  {
!       struct entry **sequence;
        int longest = 0, i;
        struct entry *entry;
  
***************
*** 211,219 ****
         */
        int anchor_i = -1;
  
!       // Added to silence Coverity.
!       if (sequence == NULL)
!               return map->first;
  
        for (entry = map->first; entry; entry = entry->next) {
                if (!entry->line2 || entry->line2 == NON_UNIQUE)
--- 204,211 ----
         */
        int anchor_i = -1;
  
!       if (!XDL_ALLOC_ARRAY(sequence, map->nr))
!               return -1;
  
        for (entry = map->first; entry; entry = entry->next) {
                if (!entry->line2 || entry->line2 == NON_UNIQUE)
***************
*** 234,241 ****
  
        /* No common unique lines were found */
        if (!longest) {
                xdl_free(sequence);
!               return NULL;
        }
  
        /* Iterate starting at the last element, adjusting the "next" members */
--- 226,234 ----
  
        /* No common unique lines were found */
        if (!longest) {
+               *res = NULL;
                xdl_free(sequence);
!               return 0;
        }
  
        /* Iterate starting at the last element, adjusting the "next" members */
***************
*** 245,252 ****
                entry->previous->next = entry;
                entry = entry->previous;
        }
        xdl_free(sequence);
!       return entry;
  }
  
  static int match(struct hashmap *map, int line1, int line2)
--- 238,246 ----
                entry->previous->next = entry;
                entry = entry->previous;
        }
+       *res = entry;
        xdl_free(sequence);
!       return 0;
  }
  
  static int match(struct hashmap *map, int line1, int line2)
***************
*** 256,263 ****
        return record1->ha == record2->ha;
  }
  
! static int patience_diff(mmfile_t *file1, mmfile_t *file2,
!               xpparam_t const *xpp, xdfenv_t *env,
                int line1, int count1, int line2, int count2);
  
  static int walk_common_sequence(struct hashmap *map, struct entry *first,
--- 250,256 ----
        return record1->ha == record2->ha;
  }
  
! static int patience_diff(xpparam_t const *xpp, xdfenv_t *env,
                int line1, int count1, int line2, int count2);
  
  static int walk_common_sequence(struct hashmap *map, struct entry *first,
***************
*** 288,295 ****
  
                /* Recurse */
                if (next1 > line1 || next2 > line2) {
!                       if (patience_diff(map->file1, map->file2,
!                                       map->xpp, map->env,
                                        line1, next1 - line1,
                                        line2, next2 - line2))
                                return -1;
--- 281,287 ----
  
                /* Recurse */
                if (next1 > line1 || next2 > line2) {
!                       if (patience_diff(map->xpp, map->env,
                                        line1, next1 - line1,
                                        line2, next2 - line2))
                                return -1;
***************
*** 328,335 ****
   *
   * This function assumes that env was prepared with xdl_prepare_env().
   */
! static int patience_diff(mmfile_t *file1, mmfile_t *file2,
!               xpparam_t const *xpp, xdfenv_t *env,
                int line1, int count1, int line2, int count2)
  {
        struct hashmap map;
--- 320,326 ----
   *
   * This function assumes that env was prepared with xdl_prepare_env().
   */
! static int patience_diff(xpparam_t const *xpp, xdfenv_t *env,
                int line1, int count1, int line2, int count2)
  {
        struct hashmap map;
***************
*** 348,354 ****
        }
  
        memset(&map, 0, sizeof(map));
!       if (fill_hashmap(file1, file2, xpp, env, &map,
                        line1, count1, line2, count2))
                return -1;
  
--- 339,345 ----
        }
  
        memset(&map, 0, sizeof(map));
!       if (fill_hashmap(xpp, env, &map,
                        line1, count1, line2, count2))
                return -1;
  
***************
*** 362,386 ****
                return 0;
        }
  
!       first = find_longest_common_sequence(&map);
        if (first)
                result = walk_common_sequence(&map, first,
                        line1, count1, line2, count2);
        else
                result = fall_back_to_classic_diff(&map,
                        line1, count1, line2, count2);
! 
        xdl_free(map.entries);
        return result;
  }
  
! int xdl_do_patience_diff(mmfile_t *file1, mmfile_t *file2,
!               xpparam_t const *xpp, xdfenv_t *env)
  {
!       if (xdl_prepare_env(file1, file2, xpp, env) < 0)
!               return -1;
! 
!       /* environment is cleaned up in xdl_diff() */
!       return patience_diff(file1, file2, xpp, env,
!                       1, env->xdf1.nrec, 1, env->xdf2.nrec);
  }
--- 353,373 ----
                return 0;
        }
  
!       result = find_longest_common_sequence(&map, &first);
!       if (result)
!               goto out;
        if (first)
                result = walk_common_sequence(&map, first,
                        line1, count1, line2, count2);
        else
                result = fall_back_to_classic_diff(&map,
                        line1, count1, line2, count2);
!  out:
        xdl_free(map.entries);
        return result;
  }
  
! int xdl_do_patience_diff(xpparam_t const *xpp, xdfenv_t *env)
  {
!       return patience_diff(xpp, env, 1, env->xdf1.nrec, 1, env->xdf2.nrec);
  }
*** ../vim-9.0.1417/src/xdiff/xprepare.c        2018-09-10 16:39:20.000000000 
+0100
--- src/xdiff/xprepare.c        2023-03-20 17:20:10.111087422 +0000
***************
*** 78,92 ****
  
                return -1;
        }
!       if (!(cf->rchash = (xdlclass_t **) xdl_malloc(cf->hsize * 
sizeof(xdlclass_t *)))) {
  
                xdl_cha_free(&cf->ncha);
                return -1;
        }
-       memset(cf->rchash, 0, cf->hsize * sizeof(xdlclass_t *));
  
        cf->alloc = size;
!       if (!(cf->rcrecs = (xdlclass_t **) xdl_malloc(cf->alloc * 
sizeof(xdlclass_t *)))) {
  
                xdl_free(cf->rchash);
                xdl_cha_free(&cf->ncha);
--- 78,91 ----
  
                return -1;
        }
!       if (!XDL_CALLOC_ARRAY(cf->rchash, cf->hsize)) {
  
                xdl_cha_free(&cf->ncha);
                return -1;
        }
  
        cf->alloc = size;
!       if (!XDL_ALLOC_ARRAY(cf->rcrecs, cf->alloc)) {
  
                xdl_free(cf->rchash);
                xdl_cha_free(&cf->ncha);
***************
*** 112,118 ****
        long hi;
        char const *line;
        xdlclass_t *rcrec;
-       xdlclass_t **rcrecs;
  
        line = rec->ptr;
        hi = (long) XDL_HASHLONG(rec->ha, cf->hbits);
--- 111,116 ----
***************
*** 128,141 ****
                        return -1;
                }
                rcrec->idx = cf->count++;
!               if (cf->count > cf->alloc) {
!                       cf->alloc *= 2;
!                       if (!(rcrecs = (xdlclass_t **) xdl_realloc(cf->rcrecs, 
cf->alloc * sizeof(xdlclass_t *)))) {
! 
                                return -1;
-                       }
-                       cf->rcrecs = rcrecs;
-               }
                cf->rcrecs[rcrec->idx] = rcrec;
                rcrec->line = line;
                rcrec->size = rec->size;
--- 126,133 ----
                        return -1;
                }
                rcrec->idx = cf->count++;
!               if (XDL_ALLOC_GROW(cf->rcrecs, cf->count, cf->alloc))
                                return -1;
                cf->rcrecs[rcrec->idx] = rcrec;
                rcrec->line = line;
                rcrec->size = rec->size;
***************
*** 164,170 ****
        unsigned long hav;
        char const *blk, *cur, *top, *prev;
        xrecord_t *crec;
!       xrecord_t **recs, **rrecs;
        xrecord_t **rhash;
        unsigned long *ha;
        char *rchg;
--- 156,162 ----
        unsigned long hav;
        char const *blk, *cur, *top, *prev;
        xrecord_t *crec;
!       xrecord_t **recs;
        xrecord_t **rhash;
        unsigned long *ha;
        char *rchg;
***************
*** 178,228 ****
  
        if (xdl_cha_init(&xdf->rcha, sizeof(xrecord_t), narec / 4 + 1) < 0)
                goto abort;
!       if (!(recs = (xrecord_t **) xdl_malloc(narec * sizeof(xrecord_t *))))
                goto abort;
  
!       if (XDF_DIFF_ALG(xpp->flags) == XDF_HISTOGRAM_DIFF)
!               hbits = hsize = 0;
!       else {
!               hbits = xdl_hashbits((unsigned int) narec);
!               hsize = 1 << hbits;
!               if (!(rhash = (xrecord_t **) xdl_malloc(hsize * 
sizeof(xrecord_t *))))
!                       goto abort;
!               memset(rhash, 0, hsize * sizeof(xrecord_t *));
!       }
  
        nrec = 0;
!       if ((cur = blk = xdl_mmfile_first(mf, &bsize)) != NULL) {
                for (top = blk + bsize; cur < top; ) {
                        prev = cur;
                        hav = xdl_hash_record(&cur, top, xpp->flags);
!                       if (nrec >= narec) {
!                               narec *= 2;
!                               if (!(rrecs = (xrecord_t **) xdl_realloc(recs, 
narec * sizeof(xrecord_t *))))
!                                       goto abort;
!                               recs = rrecs;
!                       }
                        if (!(crec = xdl_cha_alloc(&xdf->rcha)))
                                goto abort;
                        crec->ptr = prev;
                        crec->size = (long) (cur - prev);
                        crec->ha = hav;
                        recs[nrec++] = crec;
! 
!                       if ((XDF_DIFF_ALG(xpp->flags) != XDF_HISTOGRAM_DIFF) &&
!                           xdl_classify_record(pass, cf, rhash, hbits, crec) < 
0)
                                goto abort;
                }
        }
  
!       if (!(rchg = (char *) xdl_malloc((nrec + 2) * sizeof(char))))
                goto abort;
-       memset(rchg, 0, (nrec + 2) * sizeof(char));
  
!       if (!(rindex = (long *) xdl_malloc((nrec + 1) * sizeof(long))))
!               goto abort;
!       if (!(ha = (unsigned long *) xdl_malloc((nrec + 1) * sizeof(unsigned 
long))))
!               goto abort;
  
        xdf->nrec = nrec;
        xdf->recs = recs;
--- 170,211 ----
  
        if (xdl_cha_init(&xdf->rcha, sizeof(xrecord_t), narec / 4 + 1) < 0)
                goto abort;
!       if (!XDL_ALLOC_ARRAY(recs, narec))
                goto abort;
  
!       hbits = xdl_hashbits((unsigned int) narec);
!       hsize = 1 << hbits;
!       if (!XDL_CALLOC_ARRAY(rhash, hsize))
!               goto abort;
  
        nrec = 0;
!       if ((cur = blk = xdl_mmfile_first(mf, &bsize))) {
                for (top = blk + bsize; cur < top; ) {
                        prev = cur;
                        hav = xdl_hash_record(&cur, top, xpp->flags);
!                       if (XDL_ALLOC_GROW(recs, nrec + 1, narec))
!                               goto abort;
                        if (!(crec = xdl_cha_alloc(&xdf->rcha)))
                                goto abort;
                        crec->ptr = prev;
                        crec->size = (long) (cur - prev);
                        crec->ha = hav;
                        recs[nrec++] = crec;
!                       if (xdl_classify_record(pass, cf, rhash, hbits, crec) < 
0)
                                goto abort;
                }
        }
  
!       if (!XDL_CALLOC_ARRAY(rchg, nrec + 2))
                goto abort;
  
!       if ((XDF_DIFF_ALG(xpp->flags) != XDF_PATIENCE_DIFF) &&
!           (XDF_DIFF_ALG(xpp->flags) != XDF_HISTOGRAM_DIFF)) {
!               if (!XDL_ALLOC_ARRAY(rindex, nrec + 1))
!                       goto abort;
!               if (!XDL_ALLOC_ARRAY(ha, nrec + 1))
!                       goto abort;
!       }
  
        xdf->nrec = nrec;
        xdf->recs = recs;
***************
*** 279,286 ****
        enl1 = xdl_guess_lines(mf1, sample) + 1;
        enl2 = xdl_guess_lines(mf2, sample) + 1;
  
!       if (XDF_DIFF_ALG(xpp->flags) != XDF_HISTOGRAM_DIFF &&
!           xdl_init_classifier(&cf, enl1 + enl2 + 1, xpp->flags) < 0)
                return -1;
  
        if (xdl_prepare_ctx(1, mf1, enl1, xpp, &cf, &xe->xdf1) < 0) {
--- 262,268 ----
        enl1 = xdl_guess_lines(mf1, sample) + 1;
        enl2 = xdl_guess_lines(mf2, sample) + 1;
  
!       if (xdl_init_classifier(&cf, enl1 + enl2 + 1, xpp->flags) < 0)
                return -1;
  
        if (xdl_prepare_ctx(1, mf1, enl1, xpp, &cf, &xe->xdf1) < 0) {
***************
*** 305,312 ****
                return -1;
        }
  
!       if (XDF_DIFF_ALG(xpp->flags) != XDF_HISTOGRAM_DIFF)
!               xdl_free_classifier(&cf);
  
        return 0;
  }
--- 287,293 ----
                return -1;
        }
  
!       xdl_free_classifier(&cf);
  
        return 0;
  }
***************
*** 388,398 ****
        xdlclass_t *rcrec;
        char *dis, *dis1, *dis2;
  
!       if (!(dis = (char *) xdl_malloc(xdf1->nrec + xdf2->nrec + 2))) {
! 
                return -1;
-       }
-       memset(dis, 0, xdf1->nrec + xdf2->nrec + 2);
        dis1 = dis;
        dis2 = dis1 + xdf1->nrec + 1;
  
--- 369,376 ----
        xdlclass_t *rcrec;
        char *dis, *dis1, *dis2;
  
!       if (!XDL_CALLOC_ARRAY(dis, xdf1->nrec + xdf2->nrec + 2))
                return -1;
        dis1 = dis;
        dis2 = dis1 + xdf1->nrec + 1;
  
*** ../vim-9.0.1417/src/xdiff/xutils.c  2021-09-13 21:14:59.000000000 +0100
--- src/xdiff/xutils.c  2023-03-20 17:20:10.115087425 +0000
***************
*** 122,128 ****
        long nl = 0, size, tsize = 0;
        char const *data, *cur, *top;
  
!       if ((cur = data = xdl_mmfile_first(mf, &size)) != NULL) {
                for (top = data + size; nl < sample && cur < top; ) {
                        nl++;
                        if (!(cur = memchr(cur, '\n', top - cur)))
--- 122,128 ----
        long nl = 0, size, tsize = 0;
        char const *data, *cur, *top;
  
!       if ((cur = data = xdl_mmfile_first(mf, &size))) {
                for (top = data + size; nl < sample && cur < top; ) {
                        nl++;
                        if (!(cur = memchr(cur, '\n', top - cur)))
***************
*** 432,434 ****
--- 432,451 ----
  
        return 0;
  }
+ 
+ void* xdl_alloc_grow_helper(void *p, long nr, long *alloc, size_t size)
+ {
+       void *tmp = NULL;
+       size_t n = ((LONG_MAX - 16) / 2 >= *alloc) ? 2 * *alloc + 16 : LONG_MAX;
+       if (nr > (long)n)
+               n = nr;
+       if (SIZE_MAX / size >= n)
+               tmp = xdl_realloc(p, n * size);
+       if (tmp) {
+               *alloc = n;
+       } else {
+               xdl_free(p);
+               *alloc = 0;
+       }
+       return tmp;
+ }
*** ../vim-9.0.1417/src/xdiff/xutils.h  2021-08-31 19:27:29.000000000 +0100
--- src/xdiff/xutils.h  2023-03-20 17:20:10.115087425 +0000
***************
*** 42,47 ****
  int xdl_fall_back_diff(xdfenv_t *diff_env, xpparam_t const *xpp,
                       int line1, int count1, int line2, int count2);
  
! 
  
  #endif /* #if !defined(XUTILS_H) */
--- 42,48 ----
  int xdl_fall_back_diff(xdfenv_t *diff_env, xpparam_t const *xpp,
                       int line1, int count1, int line2, int count2);
  
! /* Do not call this function, use XDL_ALLOC_GROW instead */
! void* xdl_alloc_grow_helper(void* p, long nr, long* alloc, size_t size);
  
  #endif /* #if !defined(XUTILS_H) */
*** ../vim-9.0.1417/src/version.c       2023-03-19 21:57:03.665960580 +0000
--- src/version.c       2023-03-20 17:21:51.443107455 +0000
***************
*** 697,698 ****
--- 697,700 ----
  {   /* Add new patch number below this line */
+ /**/
+     1418,
  /**/

-- 
A successful man is one who makes more money than his wife can spend.
A successful woman is one who can find such a man.

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///                                                                      \\\
\\\        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/20230320173118.2F63B1C135C%40moolenaar.net.

Raspunde prin e-mail lui