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];
230 Bseek(bp, f[a-1], 0);
233 Bprint(&stdout, "%s%s\n", s, buf);
238 change(int a, int b, int c, int d)
246 if (mflag && firstchange == 0) {
255 Bprint(&stdout, "diff %s%s %s\n", buf, file1, file2);
258 verb = a > b ? 'a': c > d ? 'd': 'c';
262 Bputc(&stdout, verb);
266 Bputc(&stdout, verb);
270 Bprint(&stdout, "%s:", file1);
272 Bprint(&stdout, " %c ", verb);
273 Bprint(&stdout, "%s:", file2);
277 Bputc(&stdout, verb);
281 Bputc(&stdout, '\n');
282 if (mode == 0 || mode == 'n') {
283 fetch(ixold, a, b, input[0], "< ");
284 if (a <= b && c <= d)
285 Bprint(&stdout, "---\n");
287 fetch(ixnew, c, d, input[1], mode == 0 || mode == 'n' ? "> ": "");
288 if (mode != 0 && mode != 'n' && c <= d)
289 Bprint(&stdout, ".\n");