"Fossies" - the Fresh Open Source Software Archive 
Member "qdiff-0.9.1/tdiffoutput.cc" (21 Oct 2008, 21837 Bytes) of package /linux/privat/old/qdiff-0.9.1.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
1 /*GPL*START*
2 *
3 * Copyright (C) 1998 by Johannes Overmann <overmann@iname.com>
4 * Copyright (C) 2008 by Tong Sun <suntong001@users.sourceforge.net>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 * *GPL*END*/
20
21 #include <sys/ioctl.h>
22 #include "tdiffoutput.h"
23 #include "ctype.h"
24
25
26 static const char *color_nor = "\033[m";
27 static const char *color_ins = "\033[00;32m";
28 static const char *color_del = "\033[01;31m";
29 static const char *color_sub = "\033[01;33m";
30 static const char *color_mat = "\033[01;37m";
31 static const char *color_sep = "\033[00;34m";
32
33
34 TDiffOutput::~TDiffOutput() {
35 delete[] linebuf1;
36 delete[] linebuf2;
37 }
38
39 TDiffOutput::TDiffOutput(TROTFile& file1, TROTFile& file2,
40 const TAppConfig& appconf):
41 f1(file1), f2(file2), o1(0), o2(0), ac(appconf), mode(VERTICAL),
42 verbose(false),
43 hide_mat(false),
44 hide_ins(false),
45 hide_del(false),
46 hide_sub(false),
47 range_mat(false),
48 range_ins(false),
49 range_del(false),
50 range_sub(false),
51 no_color(false),
52 width(0),
53 bytes_per_line(0),
54 max_bytes_per_line(0),
55 half_line_len(0),
56 linebuf1(0),
57 linebuf2(0),
58 linebuf1p(0),
59 linebuf2p(0),
60 bytesin1(0),
61 bytesin2(0),
62 lastcolor1(NIL),
63 lastcolor2(NIL),
64 needadr1(false),
65 needadr2(false),
66 line1(0),
67 line2(0),
68 tab_size(0),
69 alignment_marks(false),
70 show_lf_and_tab(false),
71 show_space(false),
72 line_numbers(false),
73 no_line_break(false),
74 unprint(0),
75 control_hex(false)
76 {
77 // adjust colors
78 if(ac("alt-colors")) {
79 color_nor = "\033[00m";
80 color_ins = "\033[35m";
81 color_del = "\033[31m";
82 color_sub = "\033[33m";
83 color_mat = "\033[37m";
84 color_sep = "\033[34m";
85 }
86
87 // verbose?
88 verbose = ac("verbose");
89
90 // some format options
91 alignment_marks = ac("alignment-marks");
92 line_numbers = ac("line-numbers");
93 no_line_break = ac("no-line-break");
94 control_hex = ac("control-hex");
95 tstring up = ac.getString("unprintable");
96 if(up.len()==0) unprint = 0;
97 else if(up.len()==1) unprint = up[0];
98 else
99 userError("parameter for --unprintable-char should be a single char! (was '%s')\n", up.data());
100
101 // format?
102 width = ac.getInt("width");
103 if(width == 0) {
104 struct winsize win;
105 if(ioctl(1, TIOCGWINSZ, &win) == 0)
106 width = win.ws_col;
107 else
108 width = 80;
109 }
110 if(width < 42) width = 42;
111 half_line_len = (width-1)/2;
112 tab_size = ac.getInt("tab-size");
113 show_lf_and_tab = ac("show-lf-and-tab");
114 show_space = ac("show-space");
115
116 // which mode?
117 bool hex = ac("hex");
118 bool f_ascii = ac("formatted");
119 bool u_ascii = ac("unformatted");
120 bool vertical = ac("vertical");
121 int i = hex+f_ascii+u_ascii+vertical;
122 switch(i) {
123 case 0: // automatic format
124 mode = autoMode();
125 break;
126 case 1:
127 if(hex) mode = HEX;
128 if(f_ascii) mode = F_ASCII;
129 if(u_ascii) mode = U_ASCII;
130 break;
131 default:
132 userError("specify only one of {--hex, --formatted-ascii, --unformatted-ascii, --vertical}\n");
133 }
134 switch(mode) {
135 case HEX:
136 if(verbose) printf("printing hex dump, block by block (hex mode)\n");
137 max_bytes_per_line = (((width-1)/2)-8)/3;
138 bytes_per_line = ac.getInt("bytes-per-line");
139 if(bytes_per_line<=0) bytes_per_line = max_bytes_per_line;
140 if(unprint)
141 userError("--unprintable-char not useful in hex mode!\n");
142 if(show_space)
143 userError("--show-space not useful in hex mode!\n");
144 if(control_hex)
145 userError("--control-hex not useful in hex mode!\n");
146 break;
147 case F_ASCII:
148 if(line_numbers)
149 max_bytes_per_line = half_line_len-9;
150 else
151 max_bytes_per_line = half_line_len;
152 bytes_per_line = ac.getInt("bytes-per-line");
153 if(bytes_per_line<=0) bytes_per_line = max_bytes_per_line;
154 if(verbose) printf("printing formatted ascii text, line by line (formatted-ascii mode)\n");
155 break;
156 case U_ASCII:
157 max_bytes_per_line = half_line_len-9;
158 bytes_per_line = ac.getInt("bytes-per-line");
159 if(bytes_per_line<=0) bytes_per_line = max_bytes_per_line;
160 if(verbose) printf("printing unformatted ascii text, block by block (unformatted-ascii mode)\n");
161 break;
162 case VERTICAL:
163 if(verbose) printf("printing one byte per line (vertical mode)\n");
164 break;
165 }
166 if(mode!=F_ASCII) {
167 show_lf_and_tab = true;
168 if(line_numbers)
169 userError("--line-numbers make only sense for formatted ascii mode!\n");
170 if(no_line_break)
171 userError("--no-line-break makes only sense for formatted ascii mode!\n");
172 line_numbers = true;
173 }
174
175 // disable color?
176 if(ac("no-color")) {
177 color_sep=color_sub=color_mat=color_del=color_ins=color_nor="";
178 }
179
180 // hide:
181 hide_mat = ac("hide-match");
182 hide_ins = ac("hide-insertion");
183 hide_del = ac("hide-deletion");
184 hide_sub = ac("hide-substitution");
185 if(hide_mat && hide_ins && hide_del && hide_sub)
186 userError("specify not all of {--hide-match, --hide-deletion, --hide-insertion, --hide-substitution}\n");
187
188 // range:
189 range_mat = ac("range-match");
190 range_ins = ac("range-deletion");
191 range_del = ac("range-insertion");
192 range_sub = ac("range-substitution");
193 if(ac("range")) {
194 range_mat = range_sub = range_ins = range_del = true;
195 }
196
197 // alloc some mem:
198 linebuf1 = new char[half_line_len*16];
199 linebuf2 = new char[half_line_len*16];
200 bytesin1 = bytesin2 = 0;
201 lastcolor1 = lastcolor2 = NIL;
202 linebuf1p = linebuf1;
203 linebuf2p = linebuf2;
204 needadr1 = needadr2 = true;
205 line1 = line2 = 1;
206 }
207
208
209 const char *TDiffOutput::printChar(uchar c, char *buf) const {
210 if((c==32)&& show_space) return "SPC";
211 // printable codes
212 if(isprint(c)) {
213 buf[0] = '\'';
214 buf[1] = c;
215 buf[2] = '\'';
216 buf[3] = 0;
217 return buf;
218 }
219 // control codes
220 switch(c) {
221 case 0: return "NUL";
222 case 1: return "SOH";
223 case 2: return "STX";
224 case 3: return "ETX";
225 case 4: return "EOT";
226 case 5: return "ENQ";
227 case 6: return "ACK";
228 case 7: return "BEL";
229 case 8: return "BS ";
230 case 9: return "HT ";
231 case 10: return "LF ";
232 case 11: return "VT ";
233 case 12: return "FF ";
234 case 13: return "CR ";
235 case 14: return "SO ";
236 case 15: return "SI ";
237 case 16: return "DLE";
238 case 17: return "DC1";
239 case 18: return "DC2";
240 case 19: return "DC3";
241 case 20: return "DC4";
242 case 21: return "NAK";
243 case 22: return "SYN";
244 case 23: return "ETB";
245 case 24: return "CAN";
246 case 25: return "EM ";
247 case 26: return "SUB";
248 case 27: return "ESC";
249 case 28: return "FS ";
250 case 29: return "GS ";
251 case 30: return "RS ";
252 case 31: return "US ";
253 case 127:return "DEL";
254 }
255 // all other codes
256 return " ";
257 }
258
259
260 void TDiffOutput::setStrLen(char *str, int len) const {
261 char *p=str;
262 int l=0;
263 bool esc_seq = false;
264 while(*p) {
265 if(l==len) break;
266 if(*p==27) {
267 esc_seq = true;
268 while(*p!='m') p++;
269 p++;
270 } else {
271 p++;
272 l++;
273 }
274 }
275 while(l<len) {
276 *(p++)=' ';
277 l++;
278 }
279 *p=0; // terminate string
280 if(esc_seq) strcpy(p, color_nor); // switch to normal
281 }
282
283
284 void TDiffOutput::flush() {
285 if(bytesin1 || bytesin2)
286 printSplitLine(linebuf1, linebuf2);
287 *linebuf1=0;
288 *linebuf2=0;
289 bytesin1 = bytesin2 = 0;
290 lastcolor1 = lastcolor2 = NIL;
291 linebuf1p = linebuf1;
292 linebuf2p = linebuf2;
293 needadr1 = needadr2 = true;
294 }
295
296
297 void TDiffOutput::putChar(char **p, uchar c, int pos) const {
298 const char *hex="0123456789ABCDEF";
299 if(c>=128) { // 128-255
300 if(unprint) {
301 *((*p)++)=unprint;
302 **p=0;
303 return;
304 }
305 *((*p)++)='<';
306 *((*p)++)='x';
307 *((*p)++)=hex[c>>4];
308 *((*p)++)=hex[c&15];
309 *((*p)++)='>';
310 **p=0;
311 return;
312 }
313 if((c>32)&&(c<=126)) { // 32-126
314 *((*p)++)=c;
315 **p=0;
316 return;
317 }
318 if((c==' ')&&(!show_space)) {
319 *((*p)++)=' ';
320 **p=0;
321 return;
322 }
323 if((c=='\n')&&(!show_lf_and_tab)) {
324 **p=0;
325 return;
326 }
327 if((c=='\t')&&(!show_lf_and_tab)) {
328 do {
329 *((*p)++)=' '; pos++;
330 } while(pos%tab_size);
331 **p=0;
332 return;
333 }
334
335 if(unprint) {
336 *((*p)++)=unprint;
337 **p=0;
338 return;
339 }
340
341 if(control_hex) {
342 *((*p)++)='<';
343 *((*p)++)='x';
344 *((*p)++)=hex[c>>4];
345 *((*p)++)=hex[c&15];
346 *((*p)++)='>';
347 **p=0;
348 return;
349 }
350
351 *((*p)++)='<';
352 const char *q = printChar(c, NULL);
353 *((*p)++)=q[0];
354 *((*p)++)=q[1];
355 if(charLen(c, 0)==5)
356 *((*p)++)=q[2];
357 *((*p)++)='>';
358 **p=0;
359 }
360
361
362 void TDiffOutput::putSpace(char **p, int num) const {
363 while(num--) *((*p)++)=' ';
364 **p=0;
365 }
366
367
368 int TDiffOutput::charLen(uchar c, int pos) const {
369 int four=4;
370 if(control_hex) four = 5; // :)
371 if(unprint) {
372 if(c==9) {
373 if(show_lf_and_tab) return 1;
374 else return tab_size-(pos%tab_size);
375 }
376 return 1;
377 }
378 switch(c) { // 0-31
379 case 0:
380 case 1:
381 case 2:
382 case 3:
383 case 4:
384 case 5:
385 case 6:
386 case 7:
387 case 16:
388 case 17:
389 case 18:
390 case 19:
391 case 20:
392 case 21:
393 case 22:
394 case 23:
395 case 24:
396 case 26:
397 case 27:
398 return 5;
399 case 8:
400 // case 9:
401 // case 10:
402 case 11:
403 case 12:
404 case 13:
405 case 14:
406 case 15:
407 case 25:
408 case 28:
409 case 29:
410 case 30:
411 case 31:
412 return four;
413 case 9:
414 if(show_lf_and_tab) return four;
415 else return tab_size-(pos%tab_size);
416 case 10:
417 if(show_lf_and_tab) return four;
418 else return 1;
419 case 32:
420 if(show_space) return 5;
421 else return 1;
422 default:
423 if(c>=127) return 5; // 127-255
424 if(c>32) return 1; // 33-126
425 }
426 fatalError("internal error: should never get here!\n");
427 }
428
429
430 void TDiffOutput::putAscElem(int off1, uchar b1, int off2, uchar b2, DIFF_T diff,
431 bool formatted) {
432 if((bytesin1+charLen(off1>=0?b1:b2,off1>=0?bytesin1:bytesin2)>bytes_per_line)||
433 (bytesin2+charLen(off2>=0?b2:b1,off2>=0?bytesin2:bytesin1)>bytes_per_line)) {
434 if(!no_line_break) flush();
435 }
436 if((bytesin1 > max_bytes_per_line)||(bytesin2 > max_bytes_per_line)&&0) {
437 bytesin1+=charLen(b1, bytesin1);
438 bytesin2+=charLen(b2, bytesin2);
439 } else {
440 if(off1 >= 0) {
441 if(bytesin1==0 && line_numbers) {
442 if(!formatted) linebuf1p += sprintf(linebuf1, "%08X:", off1);
443 else linebuf1p += sprintf(linebuf1, "% 8d:", line1);
444 needadr1 = false;
445 }
446 if(needadr1 && line_numbers) {
447 char t = linebuf1[9];
448 if(!formatted) sprintf(linebuf1, "%08X:", off1);
449 else sprintf(linebuf1, "% 8d:", line1);
450 linebuf1[9] = t;
451 needadr1 = false;
452 }
453 if(lastcolor1 != diff) {
454 linebuf1p += sprintf(linebuf1p, colorStr(diff));
455 lastcolor1 = diff;
456 }
457 putChar(&linebuf1p, b1, bytesin1);
458 bytesin1+=charLen(b1, bytesin1);
459 if((off2>=0)&&(charLen(b2, bytesin2)>charLen(b1, bytesin1))) {
460 putSpace(&linebuf1p, charLen(b2, bytesin2)-charLen(b1, bytesin1));
461 bytesin1+=charLen(b2, bytesin2)-charLen(b1, bytesin1);
462 }
463 } else {
464 if(bytesin1==0 && line_numbers) linebuf1p += sprintf(linebuf1, " ");
465 putSpace(&linebuf1p, charLen(b2, bytesin2));
466 bytesin1 += charLen(b2, bytesin2);
467 }
468 if(off2 >= 0) {
469 if(bytesin2==0 && line_numbers) {
470 if(!formatted) linebuf2p += sprintf(linebuf2, "%08X:", off2);
471 else linebuf2p += sprintf(linebuf2, "% 8d:", line2);
472 needadr2 = false;
473 }
474 if(needadr2 && line_numbers) {
475 char t = linebuf2[9];
476 if(!formatted) sprintf(linebuf2, "%08X:", off2);
477 else sprintf(linebuf2, "% 8d:", line2);
478 linebuf2[9] = t;
479 needadr2 = false;
480 }
481 if(lastcolor2 != diff) {
482 linebuf2p += sprintf(linebuf2p, colorStr(diff));
483 lastcolor2 = diff;
484 }
485 putChar(&linebuf2p, b2, bytesin2);
486 bytesin2+=charLen(b2, bytesin2);
487 if((off1>=0)&&(charLen(b1, bytesin1)>charLen(b2, bytesin2))) {
488 putSpace(&linebuf2p, charLen(b1, bytesin1)-charLen(b2, bytesin2));
489 bytesin2+=charLen(b1, bytesin1)-charLen(b2, bytesin2);
490 }
491 } else {
492 if(bytesin2==0 && line_numbers) linebuf2p += sprintf(linebuf2, " ");
493 putSpace(&linebuf2p, charLen(b1, bytesin1));
494 bytesin2+=charLen(b1, bytesin1);
495 }
496 }
497 if(formatted) {
498 if(((off1>=0)&&(b1=='\n'))||((off2>=0)&&(b2=='\n'))) {
499 if((off1>=0)&&(b1=='\n')) line1++;
500 if((off2>=0)&&(b2=='\n')) line2++;
501 flush();
502 }
503 }
504 }
505
506
507 void TDiffOutput::putHexElem(int off1, uchar b1, int off2, uchar b2, DIFF_T diff) {
508 if((bytesin1 == bytes_per_line)||(bytesin2 == bytes_per_line)) flush();
509 if((bytesin1 > max_bytes_per_line)||(bytesin2 > max_bytes_per_line)) {
510 bytesin1++;
511 bytesin2++;
512 } else {
513 if(off1 >= 0) {
514 if(bytesin1==0) {
515 linebuf1p += sprintf(linebuf1, "%08X:", off1);
516 needadr1 = false;
517 }
518 if(needadr1) {
519 char t = linebuf1[9];
520 sprintf(linebuf1, "%08X:", off1);
521 linebuf1[9] = t;
522 needadr1 = false;
523 }
524 if(lastcolor1 != diff) {
525 linebuf1p += sprintf(linebuf1p, colorStr(diff));
526 lastcolor1 = diff;
527 }
528 char t1 = ' ';
529 if(alignment_marks) {
530 if((off1&7)==0) t1 = '+';
531 else if((off1&3)==0) t1 = '-';
532 }
533 if(bytesin1) linebuf1p += sprintf(linebuf1p, "%c%02X", t1, b1);
534 else linebuf1p += sprintf(linebuf1p, "%02X", b1);
535 bytesin1++;
536 } else {
537 if(bytesin1==0) linebuf1p += sprintf(linebuf1, " ");
538 else linebuf1p += sprintf(linebuf1p, " ");
539 bytesin1++;
540 }
541 if(off2 >= 0) {
542 if(bytesin2==0) {
543 linebuf2p += sprintf(linebuf2, "%08X:", off2);
544 needadr2 = false;
545 }
546 if(needadr2) {
547 char t = linebuf2[9];
548 sprintf(linebuf2, "%08X:", off2);
549 linebuf2[9] = t;
550 needadr2 = false;
551 }
552 if(lastcolor2 != diff) {
553 linebuf2p += sprintf(linebuf2p, colorStr(diff));
554 lastcolor2 = diff;
555 }
556 char t2 = ' ';
557 if(alignment_marks) {
558 if((off2&7)==0) t2 = '+';
559 else if((off2&3)==0) t2 = '-';
560 }
561 if(bytesin2) linebuf2p += sprintf(linebuf2p, "%c%02X", t2, b2);
562 else linebuf2p += sprintf(linebuf2p, "%02X", b2);
563 bytesin2++;
564 } else {
565 if(bytesin2==0) linebuf2p += sprintf(linebuf2, " ");
566 else linebuf2p += sprintf(linebuf2p, " ");
567 bytesin2++;
568 }
569 }
570 }
571
572
573 const char *TDiffOutput::colorStr(DIFF_T diff) const {
574 switch(diff) {
575 case MAT: return color_mat;
576 case SUB: return color_sub;
577 case INS: return color_ins;
578 case DEL: return color_del;
579 default:
580 fatalError("internal error: diff=%d\n", diff);
581 }
582 }
583
584
585 void TDiffOutput::printSplitLine(char *buf1, char *buf2) const {
586 setStrLen(buf1, half_line_len);
587 setStrLen(buf2, half_line_len);
588 printf("%s%s|%s%s\n", buf1, color_sep, color_nor, buf2);
589 }
590
591
592 void TDiffOutput::mat(int num) {
593 int i;
594 char buf1[10];
595 char buf2[10];
596 switch(mode) {
597 case VERTICAL:
598 if(hide_mat) {
599 o1 += num;
600 o2 += num;
601 return;
602 }
603 if(range_mat) {
604 printf("0x%08X (%10d): %s%10d bytes match %s :(%10d) 0x%08X\n",
605 o1, o1, color_mat, num, color_nor, o2, o2);
606 o1 += num;
607 o2 += num;
608 return;
609 }
610 for(i=0; i<num; i++, o1++, o2++) {
611 printf("0x%08X (%10d): %s%s %3d 0x%02X 0x%02X %3d %s%s :(%10d) 0x%08X\n",
612 o1, o1, color_mat, printChar(f1[o1], buf1), f1[o1], f1[o1],
613 f2[o2], f2[o2], printChar(f2[o2], buf2), color_nor, o2, o2);
614 }
615 break;
616
617 case F_ASCII:
618 case U_ASCII:
619 case HEX:
620 if(hide_mat) {
621 flush();
622 o1 += num;
623 o2 += num;
624 return;
625 }
626 if(range_mat) {
627 flush();
628 sprintf(linebuf1, "%08X: %s%10d bytes match%s", o1, color_mat, num,
629 color_nor);
630 sprintf(linebuf2, "%08X: %s%10d bytes match%s", o2, color_mat, num,
631 color_nor);
632 printSplitLine(linebuf1, linebuf2);
633 o1 += num;
634 o2 += num;
635 return;
636 }
637 for(i=0; i<num; i++, o1++, o2++) {
638 if(mode==HEX) putHexElem(o1, f1[o1], o2, f2[o2], MAT);
639 else putAscElem(o1, f1[o1], o2, f2[o2], MAT, mode==F_ASCII);
640 }
641 break;
642 }
643 }
644
645
646 void TDiffOutput::sub(int num, int ins, int del) {
647 int i;
648 char buf1[10];
649 char buf2[10];
650 switch(mode) {
651 case VERTICAL:
652 if(hide_sub) {
653 o1 += num + del;
654 o2 += num + ins;
655 return;
656 }
657 if(range_sub) {
658 printf("0x%08X (%10d): %s%10d subst %10d%s :(%10d) 0x%08X\n",
659 o1, o1, color_sub, num + del, num + ins, color_nor, o2, o2);
660 o1 += num + del;
661 o2 += num + ins;
662 return;
663 }
664 for(i=0; i<num; i++, o1++, o2++) {
665 printf("0x%08X (%10d): %s%s %3d 0x%02X ! 0x%02X %3d %s%s :(%10d) 0x%08X\n",
666 o1, o1, color_sub, printChar(f1[o1], buf1), f1[o1], f1[o1],
667 f2[o2], f2[o2], printChar(f2[o2], buf2), color_nor, o2, o2);
668 }
669 for(i=0; i<del; i++, o1++) {
670 printf("0x%08X (%10d): %s%s %3d 0x%02X !%s\n",
671 o1, o1, color_sub, printChar(f1[o1], buf1), f1[o1], f1[o1], color_nor);
672 }
673 for(i=0; i<ins; i++, o2++) {
674 printf(" %s! 0x%02X %3d %s%s :(%10d) 0x%08X\n",
675 color_sub, f2[o2], f2[o2], printChar(f2[o2], buf1), color_nor, o2, o2);
676 }
677 break;
678
679 case F_ASCII:
680 case U_ASCII:
681 case HEX:
682 if(hide_sub) {
683 flush();
684 o1 += num + del;
685 o2 += num + ins;
686 return;
687 }
688 if(range_sub) {
689 flush();
690 sprintf(linebuf1, "%08X: %s%10d bytes substituted%s", o1, color_sub,
691 num + del, color_nor);
692 sprintf(linebuf2, "%08X: %s%10d bytes substituted%s", o2, color_sub,
693 num + ins, color_nor);
694 printSplitLine(linebuf1, linebuf2);
695 o1 += num + del;
696 o2 += num + ins;
697 return;
698 }
699 for(i=0; i<num; i++, o1++, o2++) {
700 if(mode==HEX) putHexElem(o1, f1[o1], o2, f2[o2], SUB);
701 else putAscElem(o1, f1[o1], o2, f2[o2], SUB, mode==F_ASCII);
702 }
703 for(i=0; i<del; i++, o1++) {
704 if(mode==HEX) putHexElem(o1, f1[o1], -1, 0, SUB);
705 else putAscElem(o1, f1[o1], -1, 0, SUB, mode==F_ASCII);
706 }
707 for(i=0; i<ins; i++, o2++) {
708 if(mode==HEX) putHexElem(-1, 0, o2, f2[o2], SUB);
709 else putAscElem(-1, 0, o2, f2[o2], SUB, mode==F_ASCII);
710 }
711 break;
712 }
713 }
714
715
716 void TDiffOutput::del(int num) {
717 int i;
718 char buf[10];
719 switch(mode) {
720 case VERTICAL:
721 if(hide_del) {
722 o1 += num;
723 return;
724 }
725 if(range_del) {
726 printf("0x%08X (%10d): %s%10d bytes deleted %s\n",
727 o1, o1, color_del, num, color_nor);
728 o1 += num;
729 return;
730 }
731 for(i=0; i<num; i++, o1++) {
732 printf("0x%08X (%10d): %s%s %3d 0x%02X <%s\n",
733 o1, o1, color_del, printChar(f1[o1], buf), f1[o1], f1[o1], color_nor);
734 }
735 break;
736
737 case F_ASCII:
738 case U_ASCII:
739 case HEX:
740 if(hide_del) {
741 flush();
742 o1 += num;
743 return;
744 }
745 if(range_del) {
746 flush();
747 sprintf(linebuf1, "%08X: %s%10d bytes deleted%s", o1, color_del,
748 num, color_nor);
749 *linebuf2=0;
750 printSplitLine(linebuf1, linebuf2);
751 o1 += num;
752 return;
753 }
754 for(i=0; i<num; i++, o1++) {
755 if(mode==HEX) putHexElem(o1, f1[o1], -1, 0, DEL);
756 else putAscElem(o1, f1[o1], -1, 0, DEL, mode==F_ASCII);
757 }
758 break;
759 }
760 }
761
762
763 void TDiffOutput::ins(int num) {
764 int i;
765 char buf[10];
766 switch(mode) {
767 case VERTICAL:
768 if(hide_ins) {
769 o2 += num;
770 return;
771 }
772 if(range_ins) {
773 printf(" %s%10d bytes inserted %s :(%10d) 0x%08X\n",
774 color_ins, num, color_nor, o2, o2);
775 o2 += num;
776 return;
777 }
778 for(i=0; i<num; i++, o2++) {
779 printf(" %s> 0x%02X %3d %s%s :(%10d) 0x%08X\n",
780 color_ins, f2[o2], f2[o2], printChar(f2[o2], buf), color_nor, o2, o2);
781 }
782 break;
783
784 case F_ASCII:
785 case U_ASCII:
786 case HEX:
787 if(hide_ins) {
788 flush();
789 o2 += num;
790 return;
791 }
792 if(range_ins) {
793 flush();
794 sprintf(linebuf1, "%08X: %s%10d bytes inserted%s", o2, color_ins,
795 num, color_nor);
796 *linebuf2=0;
797 printSplitLine(linebuf2, linebuf1);
798 o2 += num;
799 return;
800 }
801 for(i=0; i<num; i++, o2++) {
802 if(mode==HEX) putHexElem(-1, 0, o2, f2[o2], INS);
803 else putAscElem(-1, 0, o2, f2[o2], INS, mode==F_ASCII);
804 }
805 break;
806 }
807 }
808
809
810 TDiffOutput::MODE_T TDiffOutput::autoMode() {
811 int i;
812 double newline=0;
813 double noascii=0;
814 double num=0;
815 int s1=10000; // chars to read from each file
816 int s2=10000;
817
818 // adjust sizes
819 if(s1 > f1.size()) s1 = f1.size();
820 if(s2 > f2.size()) s2 = f2.size();
821
822 // count chars
823 for(i=0; i<s1; i++, num++) {
824 if(f1[i]=='\n') newline++;
825 if((f1[i]>126)||(f1[i]==0)) noascii++;
826 }
827 for(i=0; i<s1; i++, num++) {
828 if(f1[i]=='\n') newline++;
829 if((f1[i]>126)||(f1[i]==0)) noascii++;
830 }
831
832 // determine mode
833 num /= 100.0; // convert to percent
834 newline /= num;
835 noascii /= num;
836 if(noascii > 10.0) {
837 if(verbose) printf("files contain %.1f%% > 10.0%% non ascii chars ==> hex mode\n", noascii);
838 return HEX;
839 }
840 if(newline < 1.0) {
841 if(verbose) printf("files contain %.1f%% < 1.0%% newline chars ==> unformatted-ascii mode\n", newline);
842 return U_ASCII;
843 }
844 if(verbose) printf("files contain %.1f%% >= 1.0%% newline chars ==> formatted-ascii mode\n", newline);
845 return F_ASCII;
846 }
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866