"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