11 extern struct line *file[2];
13 extern long *ixold, *ixnew;
16 static Biobuf *input[2];
17 static char *file1, *file2;
18 static int firstchange;
20 #define MAXLINELEN 4096
21 #define MIN(x, y) ((x) < (y) ? (x): (y))
24 readline(Biobuf *bp, char *buf)
43 if (c != '\n' && c >= 0) {
45 while (c >= 0 && c != '\n');
51 #define low(x) (x&((1L<<HALFLONG)-1))
52 #define high(x) (x>>HALFLONG)
55 * hashing has the effect of
56 * arranging line in 7-bit bytes and then
57 * summing 1-s complement in 16-bit hunks
60 readhash(Biobuf *bp, char *buf)
69 if ((len = readline(bp, buf)) == -1)
72 switch(bflag) /* various types of white space handling */
76 sum += (long)*p++ << (shift &= (HALFLONG-1));
82 * coalesce multiple white-space
84 for (space = 0; len--; p++) {
93 sum += (long)*p << (shift &= (HALFLONG-1));
99 * strip all white-space
106 sum += (long)*p++ << (shift &= (HALFLONG-1));
111 sum = low(sum) + high(sum);
112 return ((short)low(sum) + (short)high(sum));
116 prepare(int i, char *arg)
121 char *cp, buf[MAXLINELEN];
125 bp = Bopen(arg, OREAD);
127 panic(mflag ? 0: 2, "cannot open %s: %r\n", arg);
132 nbytes = Bread(bp, buf, MIN(1024, MAXLINELEN));
135 while (cp < buf+nbytes-UTFmax) {
137 * heuristic for a binary file in the
138 * brave new UNICODE world
140 cp += chartorune(&r, cp);
141 if (r == 0 || (r > 0x7f && r <= 0xa0)) {
148 p = MALLOC(struct line, 3);
149 for (j = 0; h = readhash(bp, buf); p[j].value = h)
150 p = REALLOC(p, struct line, (++j+3));
153 input[i] = bp; /*fix*/
154 if (i == 0) { /*fix*/
164 squishspace(char *buf)
169 for (space = 0, q = p = buf; *q; q++) {
174 if (space && bflag == 1) {
185 * need to fix up for unexpected EOF's
188 check(Biobuf *bf, Biobuf *bt)
190 int f, t, flen, tlen;
191 char fbuf[MAXLINELEN], tbuf[MAXLINELEN];
193 ixold[0] = ixnew[0] = 0;
194 for (f = t = 1; f < len[0]; f++) {
195 flen = readline(bf, fbuf);
196 ixold[f] = ixold[f-1] + flen + 1; /* ftell(bf) */
200 tlen = readline(bt, tbuf);
201 ixnew[t] = ixnew[t-1] + tlen + 1; /* ftell(bt) */
202 } while (t++ < J[f]);
204 flen = squishspace(fbuf);
205 tlen = squishspace(tbuf);
207 if (flen != tlen || strcmp(fbuf, tbuf))
211 tlen = readline(bt, tbuf);
212 ixnew[t] = ixnew[t-1] + tlen + 1; /* fseek(bt) */
218 range(int a, int b, char *separator)
220 Bprint(&stdout, "%d", a > b ? b: a);
222 Bprint(&stdout, "%s%d", separator, b);
226 fetch(long *f, int a, int b, Biobuf *bp, char *s)
228 char buf[MAXLINELEN];
241 Bseek(bp, f[a-1], 0);
244 Bprint(&stdout, "%s%s\n", s, buf);
248 typedef struct Change Change;
261 change(int a, int b, int c, int d)
270 if (mflag && firstchange == 0) {
279 Bprint(&stdout, "diff %s%s %s\n", buf, file1, file2);
282 verb = a > b ? 'a': c > d ? 'd': 'c';
286 Bputc(&stdout, verb);
290 Bputc(&stdout, verb);
294 Bprint(&stdout, "%s:", file1);
296 Bprint(&stdout, " %c ", verb);
297 Bprint(&stdout, "%s:", file2);
301 Bputc(&stdout, verb);
306 if(nchanges%1024 == 0)
307 changes = erealloc(changes, (nchanges+1024)*sizeof(changes[0]));
308 ch = &changes[nchanges++];
315 Bputc(&stdout, '\n');
316 if (mode == 0 || mode == 'n') {
317 fetch(ixold, a, b, input[0], "< ");
318 if (a <= b && c <= d)
319 Bprint(&stdout, "---\n");
321 fetch(ixnew, c, d, input[1], mode == 0 || mode == 'n' ? "> ": "");
322 if (mode != 0 && mode != 'n' && c <= d)
323 Bprint(&stdout, ".\n");
328 Lines = 3, /* number of lines of context shown */
334 while(i<nchanges && changes[i].b+1+2*Lines > changes[i+1].a)
350 for(i=0; i<nchanges; ){
352 a = changes[i].a-Lines;
353 b = changes[j-1].b+Lines;
354 c = changes[i].c-Lines;
355 d = changes[j-1].d+Lines;
371 Bprint(&stdout, "%s:", file1);
373 Bprint(&stdout, " - ");
374 Bprint(&stdout, "%s:", file2);
376 Bputc(&stdout, '\n');
379 fetch(ixold, at, changes[i].a-1, input[0], " ");
380 fetch(ixold, changes[i].a, changes[i].b, input[0], "< ");
381 fetch(ixnew, changes[i].c, changes[i].d, input[1], "> ");
384 fetch(ixold, at, b, input[0], " ");