1 package org.catacomb.util;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 import java.io.*;
33 import java.util.Date;
34 import java.util.Vector;
35
36
37
38
39 interface UnaryPredicate {
40 boolean execute(Object obj);
41 }
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64 @SuppressWarnings("all")
65 public class DiffPrint {
66
67
68
69
70
71 public static abstract class Base {
72 protected PrintWriter outfile;
73
74 public void setOutput(Writer wtr) {
75 outfile = new PrintWriter(wtr);
76 }
77 public void setupOutput() {
78 if (outfile == null)
79 outfile = new PrintWriter(new OutputStreamWriter(System.out));
80 }
81 protected Base(Object[] a,Object[] b) {
82 file0 = a;
83 file1 = b;
84 }
85
86
87
88 protected UnaryPredicate ignore = null;
89
90
91
92 protected Object[] file0, file1;
93
94
95
96
97
98
99
100 public void print_script(Diff.change script) {
101 setupOutput();
102 Diff.change next = script;
103
104 while (next != null)
105 {
106 Diff.change t, end;
107
108
109 t = next;
110 end = hunkfun(next);
111
112
113
114 next = end.link;
115 end.link = null;
116
117
118
119
120 print_hunk(t);
121
122
123 end.link = next;
124 }
125 outfile.flush();
126 }
127
128
129
130
131
132 protected Diff.change hunkfun(Diff.change hunk) {
133 return hunk;
134 }
135
136 protected int first0, last0, first1, last1, deletes, inserts;
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151 protected void analyze_hunk(Diff.change hunk) {
152 int f0, l0 = 0, f1, l1 = 0, show_from = 0, show_to = 0;
153 int i;
154 Diff.change next;
155 boolean nontrivial = (ignore == null);
156
157 show_from = show_to = 0;
158
159 f0 = hunk.line0;
160 f1 = hunk.line1;
161
162 for (next = hunk; next != null; next = next.link)
163 {
164 l0 = next.line0 + next.deleted - 1;
165 l1 = next.line1 + next.inserted - 1;
166 show_from += next.deleted;
167 show_to += next.inserted;
168 for (i = next.line0; i <= l0 && ! nontrivial; i++)
169 if (!ignore.execute(file0[i]))
170 nontrivial = true;
171 for (i = next.line1; i <= l1 && ! nontrivial; i++)
172 if (!ignore.execute(file1[i]))
173 nontrivial = true;
174 }
175
176 first0 = f0;
177 last0 = l0;
178 first1 = f1;
179 last1 = l1;
180
181
182
183
184 if (!nontrivial)
185 show_from = show_to = 0;
186
187 deletes = show_from;
188 inserts = show_to;
189 }
190
191
192 protected void print_header(String filea, @SuppressWarnings("unused")
193 String fileb) {
194 setupOutput();
195 }
196
197 protected abstract void print_hunk(Diff.change hunk);
198
199 protected void print_1_line(String pre,Object linbuf) {
200 outfile.println(pre + linbuf.toString());
201 }
202
203
204
205
206
207
208
209 protected void print_number_range(char sepchar, int a, int b) {
210
211
212
213 if (++b > ++a)
214 outfile.print("" + a + sepchar + b);
215 else
216 outfile.print(b);
217 }
218
219 public static char change_letter(int inserts, int deletes) {
220 if (inserts == 0)
221 return 'd';
222 else if (deletes == 0)
223 return 'a';
224 else
225 return 'c';
226 }
227 }
228
229
230
231 public static class NormalPrint extends Base {
232
233 public NormalPrint(Object[] a,Object[] b) {
234 super(a,b);
235 }
236
237
238
239
240
241 protected void print_hunk(Diff.change hunk) {
242
243
244 analyze_hunk(hunk);
245 if (deletes == 0 && inserts == 0)
246 return;
247
248
249 print_number_range(',', first0, last0);
250 outfile.print(change_letter(inserts, deletes));
251 print_number_range(',', first1, last1);
252 outfile.println();
253
254
255 if (deletes != 0)
256 for (int i = first0; i <= last0; i++)
257 print_1_line("< ", file0[i]);
258
259 if (inserts != 0 && deletes != 0)
260 outfile.println("---");
261
262
263 if (inserts != 0)
264 for (int i = first1; i <= last1; i++)
265 print_1_line("> ", file1[i]);
266 }
267 }
268
269
270
271
272
273 public static class EdPrint extends Base {
274
275 public EdPrint(Object[] a,Object[] b) {
276 super(a,b);
277 }
278
279
280 protected void print_hunk(Diff.change hunk) {
281
282
283 analyze_hunk(hunk);
284 if (deletes == 0 && inserts == 0)
285 return;
286
287
288 print_number_range(',', first0, last0);
289 outfile.println(change_letter(inserts, deletes));
290
291
292 if (inserts != 0)
293 {
294 boolean inserting = true;
295 for (int i = first1; i <= last1; i++)
296 {
297
298 if (! inserting)
299 outfile.println(i - first1 + first0 + "a");
300 inserting = true;
301
302
303
304
305
306
307 if (".".equals(file1[i]))
308 {
309 outfile.println("..");
310 outfile.println(".");
311
312 outfile.println(i - first1 + first0 + 1 + "s/^\\.\\././");
313 inserting = false;
314 }
315 else
316
317 print_1_line("", file1[i]);
318 }
319
320
321 if (inserting)
322 outfile.println(".");
323 }
324 }
325 }
326
327
328
329
330 public static class ContextPrint extends Base {
331
332 protected int context = 3;
333
334 public ContextPrint(Object[] a,Object[] b) {
335 super(a,b);
336 }
337
338 protected void print_context_label(String mark, File inf, String label) {
339 setupOutput();
340 if (label != null)
341 outfile.println(mark + ' ' + label);
342 else if (inf.lastModified() > 0)
343
344 outfile.println(
345 mark + ' ' + inf.getPath() + '\t' + new Date(inf.lastModified())
346 );
347 else
348
349 outfile.println(mark + ' ' + inf.getPath());
350 }
351
352 public void print_header(String filea,String fileb) {
353 print_context_label("***", new File(filea), filea);
354 print_context_label("---", new File(fileb), fileb);
355 }
356
357
358 private String find_function(Object[] lines, int start) {
359 return null;
360 }
361
362 protected void print_function(Object[] file,int start) {
363 String function = find_function(file0, first0);
364 if (function != null) {
365 outfile.print(" ");
366 outfile.print(
367 (function.length() < 40) ? function : function.substring(0,40)
368 );
369 }
370 }
371
372 protected void print_hunk(Diff.change hunk) {
373
374
375
376 analyze_hunk(hunk);
377
378 if (deletes == 0 && inserts == 0)
379 return;
380
381
382
383 first0 = Math.max(first0 - context, 0);
384 first1 = Math.max(first1 - context, 0);
385 last0 = Math.min(last0 + context, file0.length - 1);
386 last1 = Math.min(last1 + context, file1.length - 1);
387
388
389 outfile.print("***************");
390
391
392
393 print_function(file0, first0);
394
395 outfile.println();
396 outfile.print("*** ");
397 print_number_range(',', first0, last0);
398 outfile.println(" ****");
399
400 if (deletes != 0) {
401 Diff.change next = hunk;
402
403 for (int i = first0; i <= last0; i++) {
404
405
406
407 while (next != null && next.line0 + next.deleted <= i)
408 next = next.link;
409
410
411
412 String prefix = " ";
413 if (next != null && next.line0 <= i)
414
415
416
417 prefix = (next.inserted > 0) ? "!" : "-";
418
419 print_1_line(prefix, file0[i]);
420 }
421 }
422
423 outfile.print("--- ");
424 print_number_range(',', first1, last1);
425 outfile.println(" ----");
426
427 if (inserts != 0) {
428 Diff.change next = hunk;
429
430 for (int i = first1; i <= last1; i++) {
431
432
433
434 while (next != null && next.line1 + next.inserted <= i)
435 next = next.link;
436
437
438
439 String prefix = " ";
440 if (next != null && next.line1 <= i)
441
442
443
444 prefix = (next.deleted > 0) ? "!" : "+";
445
446 print_1_line(prefix, file1[i]);
447 }
448 }
449 }
450 }
451
452
453
454
455 public static class UnifiedPrint extends ContextPrint {
456
457 public UnifiedPrint(Object[] a,Object[] b) {
458 super(a,b);
459 }
460
461 public void print_header(String filea,String fileb) {
462 print_context_label("---", new File(filea), filea);
463 print_context_label("+++", new File(fileb), fileb);
464 }
465
466 private void print_number_range(int a, int b) {
467
468
469
470
471
472 if (b < a)
473 outfile.print(b + ",0");
474 else
475 super.print_number_range(',',a,b);
476 }
477
478 protected void print_hunk(Diff.change hunk) {
479
480 analyze_hunk(hunk);
481
482 if (deletes == 0 && inserts == 0)
483 return;
484
485
486
487 first0 = Math.max(first0 - context, 0);
488 first1 = Math.max(first1 - context, 0);
489 last0 = Math.min(last0 + context, file0.length - 1);
490 last1 = Math.min(last1 + context, file1.length - 1);
491
492 outfile.print("@@ -");
493 print_number_range(first0, last0);
494 outfile.print(" +");
495 print_number_range(first1, last1);
496 outfile.print(" @@");
497
498
499
500 print_function(file0,first0);
501
502 outfile.println();
503
504 Diff.change next = hunk;
505 int i = first0;
506 int j = first1;
507
508 while (i <= last0 || j <= last1) {
509
510
511
512 if (next == null || i < next.line0) {
513 if (i < file0.length) {
514 outfile.print(' ');
515 print_1_line("", file0[i++]);
516 }
517 j++;
518 }
519 else {
520
521
522 int k = next.deleted;
523 while (k-- > 0) {
524 outfile.print('-');
525 print_1_line("", file0[i++]);
526 }
527
528
529
530 k = next.inserted;
531 while (k-- > 0) {
532 outfile.print('+');
533 print_1_line("", file1[j++]);
534 }
535
536
537
538 next = next.link;
539 }
540 }
541 }
542 }
543
544
545
546
547
548
549
550
551 static String[] slurp(String file) throws IOException {
552 BufferedReader rdr = new BufferedReader(new FileReader(file));
553 Vector<String> s = new Vector<String>();
554 for (;;) {
555 String line = rdr.readLine();
556 if (line == null) break;
557 s.addElement(line);
558 }
559 String[] a = new String[s.size()];
560 s.copyInto(a);
561 return a;
562 }
563
564 public static void main(String[] argv) throws IOException {
565 String filea = argv[argv.length - 2];
566 String fileb = argv[argv.length - 1];
567 String[] a = slurp(filea);
568 String[] b = slurp(fileb);
569 Diff d = new Diff(a,b);
570 char style = 'n';
571 for (int i = 0; i < argv.length - 2; ++i) {
572 String f = argv[i];
573 if (f.startsWith("-")) {
574 for (int j = 1; j < f.length(); ++j) {
575 switch (f.charAt(j)) {
576 case 'e':
577 style = 'e';
578 break;
579 case 'c':
580 style = 'c';
581 break;
582 case 'u':
583 style = 'u';
584 break;
585 }
586 }
587 }
588 }
589 boolean reverse = style == 'e';
590 Diff.change script = d.diff_2(reverse);
591 if (script == null)
592 System.err.println("No differences");
593 else {
594 Base p;
595 switch (style) {
596 case 'e':
597 p = new EdPrint(a,b);
598 break;
599 case 'c':
600 p = new ContextPrint(a,b);
601 break;
602 case 'u':
603 p = new UnifiedPrint(a,b);
604 break;
605 default:
606 p = new NormalPrint(a,b);
607 }
608 p.print_header(filea,fileb);
609 p.print_script(script);
610 }
611 }
612
613 }