xdiff: delete chastore from xdfile_t

xdfile_t currently uses chastore_t which is an arena allocator. I think that xrecord_t used to be a linked list and recs didn't exist originally. When recs was added I think they forgot to remove xdfile_t.next, but was overlooked. This dual data structure setup makes the code somewhat confusing. Additionally the C type chastore_t isn't FFI friendly, and provides little to no performance benefit over using realloc to grow an array. Performance impact of deleting fields from xdfile_t: Deleting ha is about 5% slower. Deleting cha is about 5% faster. Delete ha, but keep cha time hyperfine --warmup 3 -L exe build_v2.51.0/git,build_delete_ha/git '{exe} log --oneline --shortstat --diff-algorithm=myers -3000 v2.39.1 >/dev/null' Benchmark 1: build_v2.51.0/git log --oneline --shortstat --diff-algorithm=myers -3000 v2.39.1 >/dev/null Time (mean ± σ): 1.269 s ± 0.017 s [User: 1.135 s, System: 0.128 s] Range (min … max): 1.249 s … 1.286 s 10 runs Benchmark 2: build_delete_ha/git log --oneline --shortstat --diff-algorithm=myers -3000 v2.39.1 >/dev/null Time (mean ± σ): 1.339 s ± 0.017 s [User: 1.234 s, System: 0.099 s] Range (min … max): 1.320 s … 1.358 s 10 runs Summary build_v2.51.0/git log --oneline --shortstat --diff-algorithm=myers -3000 v2.39.1 >/dev/null ran 1.06 ± 0.02 times faster than build_delete_ha/git log --oneline --shortstat --diff-algorithm=myers -3000 v2.39.1 >/dev/null Delete cha, but keep ha time hyperfine --warmup 3 -L exe build_v2.51.0/git,build_delete_chastore/git '{exe} log --oneline --shortstat --diff-algorithm=myers -3000 v2.39.1 >/dev/null' Benchmark 1: build_v2.51.0/git log --oneline --shortstat --diff-algorithm=myers -3000 v2.39.1 >/dev/null Time (mean ± σ): 1.290 s ± 0.001 s [User: 1.154 s, System: 0.130 s] Range (min … max): 1.288 s … 1.292 s 10 runs Benchmark 2: build_delete_chastore/git log --oneline --shortstat --diff-algorithm=myers -3000 v2.39.1 >/dev/null Time (mean ± σ): 1.232 s ± 0.017 s [User: 1.105 s, System: 0.121 s] Range (min … max): 1.205 s … 1.249 s 10 runs Summary build_delete_chastore/git log --oneline --shortstat --diff-algorithm=myers -3000 v2.39.1 >/dev/null ran 1.05 ± 0.01 times faster than build_v2.51.0/git log --oneline --shortstat --diff-algorithm=myers -3000 v2.39.1 >/dev/null Delete ha AND chastore time hyperfine --warmup 3 -L exe build_v2.51.0/git,build_delete_ha_and_chastore/git '{exe} log --oneline --shortstat --diff-algorithm=myers -3000 v2.39.1 >/dev/null' Benchmark 1: build_v2.51.0/git log --oneline --shortstat --diff-algorithm=myers -3000 v2.39.1 >/dev/null Time (mean ± σ): 1.291 s ± 0.002 s [User: 1.156 s, System: 0.129 s] Range (min … max): 1.287 s … 1.295 s 10 runs Benchmark 2: build_delete_ha_and_chastore/git log --oneline --shortstat --diff-algorithm=myers -3000 v2.39.1 >/dev/null Time (mean ± σ): 1.306 s ± 0.001 s [User: 1.195 s, System: 0.105 s] Range (min … max): 1.305 s … 1.308 s 10 runs Summary build_v2.51.0/git log --oneline --shortstat --diff-algorithm=myers -3000 v2.39.1 >/dev/null ran 1.01 ± 0.00 times faster than build_delete_ha_and_chastore/git log --oneline --shortstat --diff-algorithm=myers -3000 v2.39.1 >/dev/null Best-viewed-with: --color-words Signed-off-by: Ezekiel Newren <ezekielnewren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Ezekiel Newren committed Sep 26, 2025 at 22:41 UTC d43d591252cfac10433aac01cc3d9d906c2f72c3
8 files changed +63 -69
xdiff/xdiffi.c
+12 -12
@@ -24,7 +24,7 @@
24
25 static unsigned long get_hash(xdfile_t *xdf, long index)
26 {
27 - return xdf->recs[xdf->rindex[index]]->ha;
27 + return xdf->recs[xdf->rindex[index]].ha;
28 }
29
30 #define XDL_MAX_COST_MIN 256
@@ -489,13 +489,13 @@ static void measure_split(const xdfile_t *xdf, long split,
489 m->indent = -1;
490 } else {
491 m->end_of_file = 0;
492 - m->indent = get_indent(xdf->recs[split]);
492 + m->indent = get_indent(&xdf->recs[split]);
493 }
494
495 m->pre_blank = 0;
496 m->pre_indent = -1;
497 for (i = split - 1; i >= 0; i--) {
498 - m->pre_indent = get_indent(xdf->recs[i]);
498 + m->pre_indent = get_indent(&xdf->recs[i]);
499 if (m->pre_indent != -1)
500 break;
501 m->pre_blank += 1;
@@ -508,7 +508,7 @@ static void measure_split(const xdfile_t *xdf, long split,
508 m->post_blank = 0;
509 m->post_indent = -1;
510 for (i = split + 1; i < xdf->nrec; i++) {
511 - m->post_indent = get_indent(xdf->recs[i]);
511 + m->post_indent = get_indent(&xdf->recs[i]);
512 if (m->post_indent != -1)
513 break;
514 m->post_blank += 1;
@@ -752,7 +752,7 @@ static inline int group_previous(xdfile_t *xdf, struct xdlgroup *g)
752 static int group_slide_down(xdfile_t *xdf, struct xdlgroup *g)
753 {
754 if (g->end < xdf->nrec &&
755 - recs_match(xdf->recs[g->start], xdf->recs[g->end])) {
755 + recs_match(&xdf->recs[g->start], &xdf->recs[g->end])) {
756 xdf->rchg[g->start++] = 0;
757 xdf->rchg[g->end++] = 1;
758
@@ -773,7 +773,7 @@ static int group_slide_down(xdfile_t *xdf, struct xdlgroup *g)
773 static int group_slide_up(xdfile_t *xdf, struct xdlgroup *g)
774 {
775 if (g->start > 0 &&
776 - recs_match(xdf->recs[g->start - 1], xdf->recs[g->end - 1])) {
776 + recs_match(&xdf->recs[g->start - 1], &xdf->recs[g->end - 1])) {
777 xdf->rchg[--g->start] = 1;
778 xdf->rchg[--g->end] = 0;
779
@@ -988,16 +988,16 @@ static void xdl_mark_ignorable_lines(xdchange_t *xscr, xdfenv_t *xe, long flags)
988
989 for (xch = xscr; xch; xch = xch->next) {
990 int ignore = 1;
991 - xrecord_t **rec;
991 + xrecord_t *rec;
992 long i;
993
994 rec = &xe->xdf1.recs[xch->i1];
995 for (i = 0; i < xch->chg1 && ignore; i++)
996 - ignore = xdl_blankline(rec[i]->ptr, rec[i]->size, flags);
996 + ignore = xdl_blankline(rec[i].ptr, rec[i].size, flags);
997
998 rec = &xe->xdf2.recs[xch->i2];
999 for (i = 0; i < xch->chg2 && ignore; i++)
1000 - ignore = xdl_blankline(rec[i]->ptr, rec[i]->size, flags);
1000 + ignore = xdl_blankline(rec[i].ptr, rec[i].size, flags);
1001
1002 xch->ignore = ignore;
1003 }
@@ -1021,7 +1021,7 @@ static void xdl_mark_ignorable_regex(xdchange_t *xscr, const xdfenv_t *xe,
1021 xdchange_t *xch;
1022
1023 for (xch = xscr; xch; xch = xch->next) {
1024 - xrecord_t **rec;
1024 + xrecord_t *rec;
1025 int ignore = 1;
1026 long i;
1027
@@ -1033,11 +1033,11 @@ static void xdl_mark_ignorable_regex(xdchange_t *xscr, const xdfenv_t *xe,
1033
1034 rec = &xe->xdf1.recs[xch->i1];
1035 for (i = 0; i < xch->chg1 && ignore; i++)
1036 - ignore = record_matches_regex(rec[i], xpp);
1036 + ignore = record_matches_regex(&rec[i], xpp);
1037
1038 rec = &xe->xdf2.recs[xch->i2];
1039 for (i = 0; i < xch->chg2 && ignore; i++)
1040 - ignore = record_matches_regex(rec[i], xpp);
1040 + ignore = record_matches_regex(&rec[i], xpp);
1041
1042 xch->ignore = ignore;
1043 }
xdiff/xemit.c
+3 -3
@@ -25,7 +25,7 @@
25
26 static int xdl_emit_record(xdfile_t *xdf, long ri, char const *pre, xdemitcb_t *ecb)
27 {
28 - xrecord_t *rec = xdf->recs[ri];
28 + xrecord_t *rec = &xdf->recs[ri];
29
30 if (xdl_emit_diffrec(rec->ptr, rec->size, pre, strlen(pre), ecb) < 0)
31 return -1;
@@ -110,7 +110,7 @@ static long def_ff(const char *rec, long len, char *buf, long sz)
110 static long match_func_rec(xdfile_t *xdf, xdemitconf_t const *xecfg, long ri,
111 char *buf, long sz)
112 {
113 - xrecord_t *rec = xdf->recs[ri];
113 + xrecord_t *rec = &xdf->recs[ri];
114
115 if (!xecfg->find_func)
116 return def_ff(rec->ptr, rec->size, buf, sz);
@@ -150,7 +150,7 @@ static long get_func_line(xdfenv_t *xe, xdemitconf_t const *xecfg,
150
151 static int is_empty_rec(xdfile_t *xdf, long ri)
152 {
153 - xrecord_t *rec = xdf->recs[ri];
153 + xrecord_t *rec = &xdf->recs[ri];
154 long i = 0;
155
156 for (; i < rec->size && XDL_ISSPACE(rec->ptr[i]); i++);
xdiff/xhistogram.c
+1 -1
@@ -86,7 +86,7 @@ struct region {
86 ((LINE_MAP(index, ptr))->cnt)
87
88 #define REC(env, s, l) \
89 - (env->xdf##s.recs[l - 1])
89 + (&env->xdf##s.recs[l - 1])
90
91 static int cmp_recs(xrecord_t *r1, xrecord_t *r2)
92 {
xdiff/xmerge.c
+28 -28
@@ -97,12 +97,12 @@ 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 - xrecord_t **rec1 = xe1->xdf2.recs + i1;
101 - xrecord_t **rec2 = xe2->xdf2.recs + i2;
100 + xrecord_t *rec1 = xe1->xdf2.recs + i1;
101 + xrecord_t *rec2 = xe2->xdf2.recs + i2;
102
103 for (i = 0; i < line_count; i++) {
104 - int result = xdl_recmatch(rec1[i]->ptr, rec1[i]->size,
105 - rec2[i]->ptr, rec2[i]->size, flags);
104 + int result = xdl_recmatch(rec1[i].ptr, rec1[i].size,
105 + rec2[i].ptr, rec2[i].size, flags);
106 if (!result)
107 return -1;
108 }
@@ -111,7 +111,7 @@ static int xdl_merge_cmp_lines(xdfenv_t *xe1, int i1, xdfenv_t *xe2, int i2,
111
112 static int xdl_recs_copy_0(int use_orig, xdfenv_t *xe, int i, int count, int needs_cr, int add_nl, char *dest)
113 {
114 - xrecord_t **recs;
114 + xrecord_t *recs;
115 int size = 0;
116
117 recs = (use_orig ? xe->xdf1.recs : xe->xdf2.recs) + i;
@@ -119,12 +119,12 @@ static int xdl_recs_copy_0(int use_orig, xdfenv_t *xe, int i, int count, int nee
119 if (count < 1)
120 return 0;
121
122 - for (i = 0; i < count; size += recs[i++]->size)
122 + for (i = 0; i < count; size += recs[i++].size)
123 if (dest)
124 - memcpy(dest + size, recs[i]->ptr, recs[i]->size);
124 + memcpy(dest + size, recs[i].ptr, recs[i].size);
125 if (add_nl) {
126 - i = recs[count - 1]->size;
127 - if (i == 0 || recs[count - 1]->ptr[i - 1] != '\n') {
126 + i = recs[count - 1].size;
127 + if (i == 0 || recs[count - 1].ptr[i - 1] != '\n') {
128 if (needs_cr) {
129 if (dest)
130 dest[size] = '\r';
@@ -160,22 +160,22 @@ static int is_eol_crlf(xdfile_t *file, int i)
160
161 if (i < file->nrec - 1)
162 /* All lines before the last *must* end in LF */
163 - return (size = file->recs[i]->size) > 1 &&
164 - file->recs[i]->ptr[size - 2] == '\r';
163 + return (size = file->recs[i].size) > 1 &&
164 + file->recs[i].ptr[size - 2] == '\r';
165 if (!file->nrec)
166 /* Cannot determine eol style from empty file */
167 return -1;
168 - if ((size = file->recs[i]->size) &&
169 - file->recs[i]->ptr[size - 1] == '\n')
168 + if ((size = file->recs[i].size) &&
169 + file->recs[i].ptr[size - 1] == '\n')
170 /* Last line; ends in LF; Is it CR/LF? */
171 return size > 1 &&
172 - file->recs[i]->ptr[size - 2] == '\r';
172 + file->recs[i].ptr[size - 2] == '\r';
173 if (!i)
174 /* The only line has no eol */
175 return -1;
176 /* Determine eol from second-to-last line */
177 - return (size = file->recs[i - 1]->size) > 1 &&
178 - file->recs[i - 1]->ptr[size - 2] == '\r';
177 + return (size = file->recs[i - 1].size) > 1 &&
178 + file->recs[i - 1].ptr[size - 2] == '\r';
179 }
180
181 static int is_cr_needed(xdfenv_t *xe1, xdfenv_t *xe2, xdmerge_t *m)
@@ -334,22 +334,22 @@ static int recmatch(xrecord_t *rec1, xrecord_t *rec2, unsigned long flags)
334 static void xdl_refine_zdiff3_conflicts(xdfenv_t *xe1, xdfenv_t *xe2, xdmerge_t *m,
335 xpparam_t const *xpp)
336 {
337 - xrecord_t **rec1 = xe1->xdf2.recs, **rec2 = xe2->xdf2.recs;
337 + xrecord_t *rec1 = xe1->xdf2.recs, *rec2 = xe2->xdf2.recs;
338 for (; m; m = m->next) {
339 /* let's handle just the conflicts */
340 if (m->mode)
341 continue;
342
343 while(m->chg1 && m->chg2 &&
344 - recmatch(rec1[m->i1], rec2[m->i2], xpp->flags)) {
344 + recmatch(&rec1[m->i1], &rec2[m->i2], xpp->flags)) {
345 m->chg1--;
346 m->chg2--;
347 m->i1++;
348 m->i2++;
349 }
350 while (m->chg1 && m->chg2 &&
351 - recmatch(rec1[m->i1 + m->chg1 - 1],
352 - rec2[m->i2 + m->chg2 - 1], xpp->flags)) {
351 + recmatch(&rec1[m->i1 + m->chg1 - 1],
352 + &rec2[m->i2 + m->chg2 - 1], xpp->flags)) {
353 m->chg1--;
354 m->chg2--;
355 }
@@ -381,12 +381,12 @@ static int xdl_refine_conflicts(xdfenv_t *xe1, xdfenv_t *xe2, xdmerge_t *m,
381 * This probably does not work outside git, since
382 * we have a very simple mmfile structure.
383 */
384 - t1.ptr = (char *)xe1->xdf2.recs[m->i1]->ptr;
385 - t1.size = xe1->xdf2.recs[m->i1 + m->chg1 - 1]->ptr
386 - + xe1->xdf2.recs[m->i1 + m->chg1 - 1]->size - t1.ptr;
387 - t2.ptr = (char *)xe2->xdf2.recs[m->i2]->ptr;
388 - t2.size = xe2->xdf2.recs[m->i2 + m->chg2 - 1]->ptr
389 - + xe2->xdf2.recs[m->i2 + m->chg2 - 1]->size - t2.ptr;
384 + t1.ptr = (char *)xe1->xdf2.recs[m->i1].ptr;
385 + t1.size = xe1->xdf2.recs[m->i1 + m->chg1 - 1].ptr
386 + + xe1->xdf2.recs[m->i1 + m->chg1 - 1].size - t1.ptr;
387 + t2.ptr = (char *)xe2->xdf2.recs[m->i2].ptr;
388 + t2.size = xe2->xdf2.recs[m->i2 + m->chg2 - 1].ptr
389 + + xe2->xdf2.recs[m->i2 + m->chg2 - 1].size - t2.ptr;
390 if (xdl_do_diff(&t1, &t2, xpp, &xe) < 0)
391 return -1;
392 if (xdl_change_compact(&xe.xdf1, &xe.xdf2, xpp->flags) < 0 ||
@@ -440,8 +440,8 @@ static int line_contains_alnum(const char *ptr, long size)
440 static int lines_contain_alnum(xdfenv_t *xe, int i, int chg)
441 {
442 for (; chg; chg--, i++)
443 - if (line_contains_alnum(xe->xdf2.recs[i]->ptr,
444 - xe->xdf2.recs[i]->size))
443 + if (line_contains_alnum(xe->xdf2.recs[i].ptr,
444 + xe->xdf2.recs[i].size))
445 return 1;
446 return 0;
447 }
xdiff/xpatience.c
+5 -5
@@ -88,9 +88,9 @@ static int is_anchor(xpparam_t const *xpp, const char *line)
88 static void insert_record(xpparam_t const *xpp, int line, struct hashmap *map,
89 int pass)
90 {
91 - xrecord_t **records = pass == 1 ?
91 + xrecord_t *records = pass == 1 ?
92 map->env->xdf1.recs : map->env->xdf2.recs;
93 - xrecord_t *record = records[line - 1];
93 + xrecord_t *record = &records[line - 1];
94 /*
95 * After xdl_prepare_env() (or more precisely, due to
96 * xdl_classify_record()), the "ha" member of the records (AKA lines)
@@ -121,7 +121,7 @@ static void insert_record(xpparam_t const *xpp, int line, struct hashmap *map,
121 return;
122 map->entries[index].line1 = line;
123 map->entries[index].hash = record->ha;
124 - map->entries[index].anchor = is_anchor(xpp, map->env->xdf1.recs[line - 1]->ptr);
124 + map->entries[index].anchor = is_anchor(xpp, map->env->xdf1.recs[line - 1].ptr);
125 if (!map->first)
126 map->first = map->entries + index;
127 if (map->last) {
@@ -246,8 +246,8 @@ static int find_longest_common_sequence(struct hashmap *map, struct entry **res)
246
247 static int match(struct hashmap *map, int line1, int line2)
248 {
249 - xrecord_t *record1 = map->env->xdf1.recs[line1 - 1];
250 - xrecord_t *record2 = map->env->xdf2.recs[line2 - 1];
249 + xrecord_t *record1 = &map->env->xdf1.recs[line1 - 1];
250 + xrecord_t *record2 = &map->env->xdf2.recs[line2 - 1];
251 return record1->ha == record2->ha;
252 }
253
xdiff/xprepare.c
+7 -12
@@ -128,7 +128,6 @@ static void xdl_free_ctx(xdfile_t *xdf)
128 xdl_free(xdf->rindex);
129 xdl_free(xdf->rchg - 1);
130 xdl_free(xdf->recs);
131 - xdl_cha_free(&xdf->rcha);
131 }
132
133
@@ -143,8 +142,6 @@ static int xdl_prepare_ctx(unsigned int pass, mmfile_t *mf, long narec, xpparam_
142 xdf->rchg = NULL;
143 xdf->recs = NULL;
144
146 - if (xdl_cha_init(&xdf->rcha, sizeof(xrecord_t), narec / 4 + 1) < 0)
147 - goto abort;
145 if (!XDL_ALLOC_ARRAY(xdf->recs, narec))
146 goto abort;
147
@@ -155,12 +152,10 @@ static int xdl_prepare_ctx(unsigned int pass, mmfile_t *mf, long narec, xpparam_
152 hav = xdl_hash_record(&cur, top, xpp->flags);
153 if (XDL_ALLOC_GROW(xdf->recs, xdf->nrec + 1, narec))
154 goto abort;
158 - if (!(crec = xdl_cha_alloc(&xdf->rcha)))
159 - goto abort;
155 + crec = &xdf->recs[xdf->nrec++];
156 crec->ptr = prev;
157 crec->size = (long) (cur - prev);
158 crec->ha = hav;
163 - xdf->recs[xdf->nrec++] = crec;
159 if (xdl_classify_record(pass, cf, crec) < 0)
160 goto abort;
161 }
@@ -260,7 +255,7 @@ static int xdl_clean_mmatch(char const *dis, long i, long s, long e) {
255 */
256 static int xdl_cleanup_records(xdlclassifier_t *cf, xdfile_t *xdf1, xdfile_t *xdf2) {
257 long i, nm, nreff, mlim;
263 - xrecord_t **recs;
258 + xrecord_t *recs;
259 xdlclass_t *rcrec;
260 char *dis, *dis1, *dis2;
261 int need_min = !!(cf->flags & XDF_NEED_MINIMAL);
@@ -273,7 +268,7 @@ static int xdl_cleanup_records(xdlclassifier_t *cf, xdfile_t *xdf1, xdfile_t *xd
268 if ((mlim = xdl_bogosqrt(xdf1->nrec)) > XDL_MAX_EQLIMIT)
269 mlim = XDL_MAX_EQLIMIT;
270 for (i = xdf1->dstart, recs = &xdf1->recs[xdf1->dstart]; i <= xdf1->dend; i++, recs++) {
276 - rcrec = cf->rcrecs[(*recs)->ha];
271 + rcrec = cf->rcrecs[recs->ha];
272 nm = rcrec ? rcrec->len2 : 0;
273 dis1[i] = (nm == 0) ? 0: (nm >= mlim && !need_min) ? 2: 1;
274 }
@@ -281,7 +276,7 @@ static int xdl_cleanup_records(xdlclassifier_t *cf, xdfile_t *xdf1, xdfile_t *xd
276 if ((mlim = xdl_bogosqrt(xdf2->nrec)) > XDL_MAX_EQLIMIT)
277 mlim = XDL_MAX_EQLIMIT;
278 for (i = xdf2->dstart, recs = &xdf2->recs[xdf2->dstart]; i <= xdf2->dend; i++, recs++) {
284 - rcrec = cf->rcrecs[(*recs)->ha];
279 + rcrec = cf->rcrecs[recs->ha];
280 nm = rcrec ? rcrec->len1 : 0;
281 dis2[i] = (nm == 0) ? 0: (nm >= mlim && !need_min) ? 2: 1;
282 }
@@ -317,13 +312,13 @@ static int xdl_cleanup_records(xdlclassifier_t *cf, xdfile_t *xdf1, xdfile_t *xd
312 */
313 static int xdl_trim_ends(xdfile_t *xdf1, xdfile_t *xdf2) {
314 long i, lim;
320 - xrecord_t **recs1, **recs2;
315 + xrecord_t *recs1, *recs2;
316
317 recs1 = xdf1->recs;
318 recs2 = xdf2->recs;
319 for (i = 0, lim = XDL_MIN(xdf1->nrec, xdf2->nrec); i < lim;
320 i++, recs1++, recs2++)
326 - if ((*recs1)->ha != (*recs2)->ha)
321 + if (recs1->ha != recs2->ha)
322 break;
323
324 xdf1->dstart = xdf2->dstart = i;
@@ -331,7 +326,7 @@ static int xdl_trim_ends(xdfile_t *xdf1, xdfile_t *xdf2) {
326 recs1 = xdf1->recs + xdf1->nrec - 1;
327 recs2 = xdf2->recs + xdf2->nrec - 1;
328 for (lim -= i, i = 0; i < lim; i++, recs1--, recs2--)
334 - if ((*recs1)->ha != (*recs2)->ha)
329 + if (recs1->ha != recs2->ha)
330 break;
331
332 xdf1->dend = xdf1->nrec - i - 1;
xdiff/xtypes.h
+1 -2
@@ -45,10 +45,9 @@ typedef struct s_xrecord {
45 } xrecord_t;
46
47 typedef struct s_xdfile {
48 - chastore_t rcha;
48 + xrecord_t *recs;
49 long nrec;
50 long dstart, dend;
51 - xrecord_t **recs;
51 char *rchg;
52 long *rindex;
53 long nreff;
xdiff/xutils.c
+6 -6
@@ -416,12 +416,12 @@ int xdl_fall_back_diff(xdfenv_t *diff_env, xpparam_t const *xpp,
416 mmfile_t subfile1, subfile2;
417 xdfenv_t env;
418
419 - subfile1.ptr = (char *)diff_env->xdf1.recs[line1 - 1]->ptr;
420 - subfile1.size = diff_env->xdf1.recs[line1 + count1 - 2]->ptr +
421 - diff_env->xdf1.recs[line1 + count1 - 2]->size - subfile1.ptr;
422 - subfile2.ptr = (char *)diff_env->xdf2.recs[line2 - 1]->ptr;
423 - subfile2.size = diff_env->xdf2.recs[line2 + count2 - 2]->ptr +
424 - diff_env->xdf2.recs[line2 + count2 - 2]->size - subfile2.ptr;
419 + subfile1.ptr = (char *)diff_env->xdf1.recs[line1 - 1].ptr;
420 + subfile1.size = diff_env->xdf1.recs[line1 + count1 - 2].ptr +
421 + diff_env->xdf1.recs[line1 + count1 - 2].size - subfile1.ptr;
422 + subfile2.ptr = (char *)diff_env->xdf2.recs[line2 - 1].ptr;
423 + subfile2.size = diff_env->xdf2.recs[line2 + count2 - 2].ptr +
424 + diff_env->xdf2.recs[line2 + count2 - 2].size - subfile2.ptr;
425 if (xdl_do_diff(&subfile1, &subfile2, xpp, &env) < 0)
426 return -1;
427