2 * LibXDiff by Davide Libenzi ( File Differential Library )
3 * Copyright (C) 2003 Davide Libenzi
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 * Davide Libenzi <davidel@xmailserver.org>
28 static long xdl_get_rec(xdfile_t
*xdf
, long ri
, char const **rec
);
29 static int xdl_emit_record(xdfile_t
*xdf
, long ri
, char const *pre
, xdemitcb_t
*ecb
);
30 static xdchange_t
*xdl_get_hunk(xdchange_t
*xscr
, xdemitconf_t
const *xecfg
);
35 static long xdl_get_rec(xdfile_t
*xdf
, long ri
, char const **rec
) {
37 *rec
= xdf
->recs
[ri
]->ptr
;
39 return xdf
->recs
[ri
]->size
;
43 static int xdl_emit_record(xdfile_t
*xdf
, long ri
, char const *pre
, xdemitcb_t
*ecb
) {
44 long size
, psize
= strlen(pre
);
47 size
= xdl_get_rec(xdf
, ri
, &rec
);
48 if (xdl_emit_diffrec(rec
, size
, pre
, psize
, ecb
) < 0) {
58 * Starting at the passed change atom, find the latest change atom to be included
59 * inside the differential hunk according to the specified configuration.
61 static xdchange_t
*xdl_get_hunk(xdchange_t
*xscr
, xdemitconf_t
const *xecfg
) {
62 xdchange_t
*xch
, *xchp
;
64 for (xchp
= xscr
, xch
= xscr
->next
; xch
; xchp
= xch
, xch
= xch
->next
)
65 if (xch
->i1
- (xchp
->i1
+ xchp
->chg1
) > 2 * xecfg
->ctxlen
)
72 static void xdl_find_func(xdfile_t
*xf
, long i
, char *buf
, long sz
, long *ll
) {
75 * Be quite stupid about this for now. Find a line in the old file
76 * before the start of the hunk (and context) which starts with a
77 * plausible character.
85 len
= xdl_get_rec(xf
, i
, &rec
);
87 (isalpha((unsigned char)*rec
) || /* identifier? */
88 *rec
== '_' || /* also identifier? */
89 *rec
== '(' || /* lisp defun? */
90 *rec
== '#')) { /* #define? */
93 if (len
&& rec
[len
- 1] == '\n')
95 memcpy(buf
, rec
, len
);
103 int xdl_emit_common(xdfenv_t
*xe
, xdchange_t
*xscr
, xdemitcb_t
*ecb
,
104 xdemitconf_t
const *xecfg
) {
105 xdfile_t
*xdf
= &xe
->xdf1
;
106 const char *rchg
= xdf
->rchg
;
109 for (ix
= 0; ix
< xdf
->nrec
; ix
++) {
112 if (xdl_emit_record(xdf
, ix
, "", ecb
))
118 int xdl_emit_diff(xdfenv_t
*xe
, xdchange_t
*xscr
, xdemitcb_t
*ecb
,
119 xdemitconf_t
const *xecfg
) {
120 long s1
, s2
, e1
, e2
, lctx
;
121 xdchange_t
*xch
, *xche
;
125 if (xecfg
->flags
& XDL_EMIT_COMMON
)
126 return xdl_emit_common(xe
, xscr
, ecb
, xecfg
);
128 for (xch
= xche
= xscr
; xch
; xch
= xche
->next
) {
129 xche
= xdl_get_hunk(xch
, xecfg
);
131 s1
= XDL_MAX(xch
->i1
- xecfg
->ctxlen
, 0);
132 s2
= XDL_MAX(xch
->i2
- xecfg
->ctxlen
, 0);
134 lctx
= xecfg
->ctxlen
;
135 lctx
= XDL_MIN(lctx
, xe
->xdf1
.nrec
- (xche
->i1
+ xche
->chg1
));
136 lctx
= XDL_MIN(lctx
, xe
->xdf2
.nrec
- (xche
->i2
+ xche
->chg2
));
138 e1
= xche
->i1
+ xche
->chg1
+ lctx
;
139 e2
= xche
->i2
+ xche
->chg2
+ lctx
;
142 * Emit current hunk header.
145 if (xecfg
->flags
& XDL_EMIT_FUNCNAMES
) {
146 xdl_find_func(&xe
->xdf1
, s1
, funcbuf
,
147 sizeof(funcbuf
), &funclen
);
149 if (xdl_emit_hunk_hdr(s1
+ 1, e1
- s1
, s2
+ 1, e2
- s2
,
150 funcbuf
, funclen
, ecb
) < 0)
156 for (; s1
< xch
->i1
; s1
++)
157 if (xdl_emit_record(&xe
->xdf1
, s1
, " ", ecb
) < 0)
160 for (s1
= xch
->i1
, s2
= xch
->i2
;; xch
= xch
->next
) {
162 * Merge previous with current change atom.
164 for (; s1
< xch
->i1
&& s2
< xch
->i2
; s1
++, s2
++)
165 if (xdl_emit_record(&xe
->xdf1
, s1
, " ", ecb
) < 0)
169 * Removes lines from the first file.
171 for (s1
= xch
->i1
; s1
< xch
->i1
+ xch
->chg1
; s1
++)
172 if (xdl_emit_record(&xe
->xdf1
, s1
, "-", ecb
) < 0)
176 * Adds lines from the second file.
178 for (s2
= xch
->i2
; s2
< xch
->i2
+ xch
->chg2
; s2
++)
179 if (xdl_emit_record(&xe
->xdf2
, s2
, "+", ecb
) < 0)
184 s1
= xch
->i1
+ xch
->chg1
;
185 s2
= xch
->i2
+ xch
->chg2
;
191 for (s1
= xche
->i1
+ xche
->chg1
; s1
< e1
; s1
++)
192 if (xdl_emit_record(&xe
->xdf1
, s1
, " ", ecb
) < 0)