Introduction
Introduction Statistics Contact Development Disclaimer Help
diffio.c - 9base - revived minimalist port of Plan 9 userland to Unix
git clone git://git.suckless.org/9base
Log
Files
Refs
README
LICENSE
---
diffio.c (6620B)
---
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <ctype.h>
5 #include "diff.h"
6
7 struct line {
8 int serial;
9 int value;
10 };
11 extern struct line *file[2];
12 extern int len[2];
13 extern long *ixold, *ixnew;
14 extern int *J;
15
16 static Biobuf *input[2];
17 static char *file1, *file2;
18 static int firstchange;
19
20 #define MAXLINELEN 4096
21 #define MIN(x, y) ((x) < (y) ? (x): (y))
22
23 static int
24 readline(Biobuf *bp, char *buf)
25 {
26 int c;
27 char *p, *e;
28
29 p = buf;
30 e = p + MAXLINELEN-1;
31 do {
32 c = Bgetc(bp);
33 if (c < 0) {
34 if (p == buf)
35 return -1;
36 break;
37 }
38 if (c == '\n')
39 break;
40 *p++ = c;
41 } while (p < e);
42 *p = 0;
43 if (c != '\n' && c >= 0) {
44 do c = Bgetc(bp);
45 while (c >= 0 && c != '\n');
46 }
47 return p - buf;
48 }
49
50 #define HALFLONG 16
51 #define low(x) (x&((1L<<HALFLONG)-1))
52 #define high(x) (x>>HALFLONG)
53
54 /*
55 * hashing has the effect of
56 * arranging line in 7-bit bytes and then
57 * summing 1-s complement in 16-bit hunks
58 */
59 static int
60 readhash(Biobuf *bp, char *buf)
61 {
62 long sum;
63 unsigned shift;
64 char *p;
65 int len, space;
66
67 sum = 1;
68 shift = 0;
69 if ((len = readline(bp, buf)) == -1)
70 return 0;
71 p = buf;
72 switch(bflag) /* various types of white space handling */
73 {
74 case 0:
75 while (len--) {
76 sum += (long)*p++ << (shift &= (HALFLONG-1));
77 shift += 7;
78 }
79 break;
80 case 1:
81 /*
82 * coalesce multiple white-space
83 */
84 for (space = 0; len--; p++) {
85 if (isspace((uchar)*p)) {
86 space++;
87 continue;
88 }
89 if (space) {
90 shift += 7;
91 space = 0;
92 }
93 sum += (long)*p << (shift &= (HALFLONG-1));
94 shift += 7;
95 }
96 break;
97 default:
98 /*
99 * strip all white-space
100 */
101 while (len--) {
102 if (isspace((uchar)*p)) {
103 p++;
104 continue;
105 }
106 sum += (long)*p++ << (shift &= (HALFLONG-1));
107 shift += 7;
108 }
109 break;
110 }
111 sum = low(sum) + high(sum);
112 return ((short)low(sum) + (short)high(sum));
113 }
114
115 Biobuf *
116 prepare(int i, char *arg)
117 {
118 struct line *p;
119 int j, h;
120 Biobuf *bp;
121 char *cp, buf[MAXLINELEN];
122 int nbytes;
123 Rune r;
124
125 bp = Bopen(arg, OREAD);
126 if (!bp) {
127 panic(mflag ? 0: 2, "cannot open %s: %r\n", arg);
128 return 0;
129 }
130 if (binary)
131 return bp;
132 nbytes = Bread(bp, buf, MIN(1024, MAXLINELEN));
133 if (nbytes > 0) {
134 cp = buf;
135 while (cp < buf+nbytes-UTFmax) {
136 /*
137 * heuristic for a binary file in the
138 * brave new UNICODE world
139 */
140 cp += chartorune(&r, cp);
141 if (r == 0 || (r > 0x7f && r <= 0xa0)) {
142 binary++;
143 return bp;
144 }
145 }
146 Bseek(bp, 0, 0);
147 }
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));
151 len[i] = j;
152 file[i] = p;
153 input[i] = bp; /*fix*/
154 if (i == 0) { /*fix*/
155 file1 = arg;
156 firstchange = 0;
157 }
158 else
159 file2 = arg;
160 return bp;
161 }
162
163 static int
164 squishspace(char *buf)
165 {
166 char *p, *q;
167 int space;
168
169 for (space = 0, q = p = buf; *q; q++) {
170 if (isspace((uchar)*q)) {
171 space++;
172 continue;
173 }
174 if (space && bflag == 1) {
175 *p++ = ' ';
176 space = 0;
177 }
178 *p++ = *q;
179 }
180 *p = 0;
181 return p - buf;
182 }
183
184 /*
185 * need to fix up for unexpected EOF's
186 */
187 void
188 check(Biobuf *bf, Biobuf *bt)
189 {
190 int f, t, flen, tlen;
191 char fbuf[MAXLINELEN], tbuf[MAXLINELEN];
192
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; /* ftel…
197 if (J[f] == 0)
198 continue;
199 do {
200 tlen = readline(bt, tbuf);
201 ixnew[t] = ixnew[t-1] + tlen + 1; /* ftel…
202 } while (t++ < J[f]);
203 if (bflag) {
204 flen = squishspace(fbuf);
205 tlen = squishspace(tbuf);
206 }
207 if (flen != tlen || strcmp(fbuf, tbuf))
208 J[f] = 0;
209 }
210 while (t < len[1]) {
211 tlen = readline(bt, tbuf);
212 ixnew[t] = ixnew[t-1] + tlen + 1; /* fseek(bt) */
213 t++;
214 }
215 }
216
217 static void
218 range(int a, int b, char *separator)
219 {
220 Bprint(&stdout, "%d", a > b ? b: a);
221 if (a < b)
222 Bprint(&stdout, "%s%d", separator, b);
223 }
224
225 static void
226 fetch(long *f, int a, int b, Biobuf *bp, char *s)
227 {
228 char buf[MAXLINELEN];
229 int maxb;
230
231 if(a <= 1)
232 a = 1;
233 if(bp == input[0])
234 maxb = len[0];
235 else
236 maxb = len[1];
237 if(b > maxb)
238 b = maxb;
239 if(a > maxb)
240 return;
241 Bseek(bp, f[a-1], 0);
242 while (a++ <= b) {
243 readline(bp, buf);
244 Bprint(&stdout, "%s%s\n", s, buf);
245 }
246 }
247
248 typedef struct Change Change;
249 struct Change
250 {
251 int a;
252 int b;
253 int c;
254 int d;
255 };
256
257 Change *changes;
258 int nchanges;
259
260 void
261 change(int a, int b, int c, int d)
262 {
263 char verb;
264 char buf[4];
265 Change *ch;
266
267 if (a > b && c > d)
268 return;
269 anychange = 1;
270 if (mflag && firstchange == 0) {
271 if(mode) {
272 buf[0] = '-';
273 buf[1] = mode;
274 buf[2] = ' ';
275 buf[3] = '\0';
276 } else {
277 buf[0] = '\0';
278 }
279 Bprint(&stdout, "diff %s%s %s\n", buf, file1, file2);
280 firstchange = 1;
281 }
282 verb = a > b ? 'a': c > d ? 'd': 'c';
283 switch(mode) {
284 case 'e':
285 range(a, b, ",");
286 Bputc(&stdout, verb);
287 break;
288 case 0:
289 range(a, b, ",");
290 Bputc(&stdout, verb);
291 range(c, d, ",");
292 break;
293 case 'n':
294 Bprint(&stdout, "%s:", file1);
295 range(a, b, ",");
296 Bprint(&stdout, " %c ", verb);
297 Bprint(&stdout, "%s:", file2);
298 range(c, d, ",");
299 break;
300 case 'f':
301 Bputc(&stdout, verb);
302 range(a, b, " ");
303 break;
304 case 'c':
305 case 'a':
306 if(nchanges%1024 == 0)
307 changes = erealloc(changes, (nchanges+1024)*size…
308 ch = &changes[nchanges++];
309 ch->a = a;
310 ch->b = b;
311 ch->c = c;
312 ch->d = d;
313 return;
314 }
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");
320 }
321 fetch(ixnew, c, d, input[1], mode == 0 || mode == 'n' ? "> ": ""…
322 if (mode != 0 && mode != 'n' && c <= d)
323 Bprint(&stdout, ".\n");
324 }
325
326 enum
327 {
328 Lines = 3 /* number of lines of context shown */
329 };
330
331 int
332 changeset(int i)
333 {
334 while(i<nchanges && changes[i].b+1+2*Lines > changes[i+1].a)
335 i++;
336 if(i<nchanges)
337 return i+1;
338 return nchanges;
339 }
340
341 void
342 flushchanges(void)
343 {
344 int a, b, c, d, at;
345 int i, j;
346
347 if(nchanges == 0)
348 return;
349
350 for(i=0; i<nchanges; ){
351 j = changeset(i);
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;
356 if(a < 1)
357 a = 1;
358 if(c < 1)
359 c = 1;
360 if(b > len[0])
361 b = len[0];
362 if(d > len[1])
363 d = len[1];
364 if(mode == 'a'){
365 a = 1;
366 b = len[0];
367 c = 1;
368 d = len[1];
369 j = nchanges;
370 }
371 Bprint(&stdout, "%s:", file1);
372 range(a, b, ",");
373 Bprint(&stdout, " - ");
374 Bprint(&stdout, "%s:", file2);
375 range(c, d, ",");
376 Bputc(&stdout, '\n');
377 at = a;
378 for(; i<j; i++){
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…
382 at = changes[i].b+1;
383 }
384 fetch(ixold, at, b, input[0], " ");
385 }
386 nchanges = 0;
387 }
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.