home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 22 gnu / 22-gnu.zip / rcs57pc3.zip / diff16 / merged.c < prev    next >
C/C++ Source or Header  |  1991-09-18  |  5KB  |  193 lines

  1. /*
  2.  * The merged diff format added by Chip Rosenthal <chip@chinacat.unicom.com>
  3.  */
  4.  
  5. #include "diff.h"
  6.  
  7. #define TABSTOP    8    /* must be a power of two (e.g. 4, 8, etc.) */
  8.  
  9. #define Fput3(FP,S1,S2,S3) \
  10.     ( fputs((S1),(FP)), fputs((S2),(FP)), fputs((S3),(FP)), putc('\n',(FP)) )
  11.  
  12. #define Strncpy(OUT,IN,LEN) \
  13.     ( (OUT)[(LEN)] = '\0', strncpy((OUT),(IN),(LEN)) )
  14.  
  15. static int field_width;
  16. static char *field0_buf, *field1_buf, *tmp_buf;
  17.  
  18. static void print_merged_hunk();
  19. static void expand_field();
  20.  
  21. extern struct change *find_change();
  22.  
  23.  
  24. void print_merged_script(script)
  25. struct change *script;
  26. {
  27.  
  28.     /*
  29.      * Figure out how big a field to print the file differences in.
  30.      */
  31.     field_width = ( line_width - (sizeof("-+-")-1) ) / 2;
  32.     if ( field_width < 1 ) {
  33.         fputs("diff: bad field width specified\n",stderr);
  34.         exit(1);
  35.     }
  36.  
  37.     /*
  38.      * Create the space for formatting.
  39.      */
  40.     field0_buf = (char*) xmalloc((unsigned)field_width+1);
  41.     field1_buf = (char*) xmalloc((unsigned)field_width+1);
  42.     tmp_buf = (char*) xmalloc((unsigned)field_width+1);
  43.  
  44.     /*
  45.      * Print the header.
  46.      */
  47.     expand_field(tmp_buf, (char*)NULL, field_width, '-'),
  48.     Fput3(outfile, tmp_buf, "-+-", tmp_buf);
  49.  
  50.     (void) Strncpy(tmp_buf, files[0].name, field_width);
  51.     expand_field(field0_buf, tmp_buf, field_width, ' '),
  52.     (void) Strncpy(tmp_buf, files[1].name, field_width);
  53.     expand_field(field1_buf, tmp_buf, field_width, ' '),
  54.     Fput3(outfile, field0_buf, " | ", field1_buf);
  55.  
  56.     /*
  57.      * Print the hunks.
  58.      */
  59.     print_script(script, find_change, print_merged_hunk);
  60.  
  61.     /*
  62.      * Print the trailer.
  63.      */
  64.     expand_field(tmp_buf, (char*)NULL, field_width, '-'),
  65.     Fput3(outfile, tmp_buf, "-+-", tmp_buf);
  66.  
  67.     free(field0_buf);
  68.     free(field1_buf);
  69.     free(tmp_buf);
  70. }
  71.  
  72.  
  73. static void print_merged_hunk(hunk)
  74. struct change *hunk;
  75. {
  76.     int first0, last0, first1, last1, deletes, inserts, tr_first, tr_last, len;
  77.     char *action;
  78.     register int i0, i1;
  79.  
  80.     /*
  81.      * Determine range of line numbers involved in each file.
  82.      */
  83.     analyze_hunk(hunk, &first0, &last0, &first1, &last1, &deletes, &inserts);
  84.     if ( deletes > 0 && inserts > 0 )
  85.         action = "change";
  86.     else if ( deletes > 0 )
  87.         action = "delete";
  88.     else if ( inserts > 0 )
  89.         action = "insert";
  90.     else
  91.         return;
  92.  
  93.     /*
  94.      * Print the header for this hunk.
  95.      */
  96.     translate_range(&files[0], first0, last0, &tr_first, &tr_last);
  97.     if ( tr_last > tr_first )
  98.         (void) sprintf(tmp_buf, "--- %s at %d-%d ", action, tr_first, tr_last);
  99.     else
  100.         (void) sprintf(tmp_buf, "--- %s at %d ", action, tr_last);
  101.     expand_field(field0_buf, tmp_buf, field_width, '-');
  102.  
  103.     translate_range(&files[1], first1, last1, &tr_first, &tr_last);
  104.     if ( tr_last > tr_first )
  105.         (void) sprintf(tmp_buf, " %d-%d ", tr_first, tr_last);
  106.     else
  107.         (void) sprintf(tmp_buf, " %d ", tr_last);
  108.     expand_field(field1_buf, tmp_buf, field_width, '-');
  109.  
  110.     Fput3(outfile, field0_buf, "-+-", field1_buf);
  111.  
  112.     /*
  113.      * Format and print each line in this hunk.
  114.      */
  115.     for ( i0 = first0, i1 = first1 ; i0 <= last0 || i1 <= last1 ; ++i0, ++i1 ) {
  116.  
  117.         if ( i0 <= last0 ) {
  118.             len = ( files[0].linbuf[i0].length < field_width ?
  119.                 files[0].linbuf[i0].length : field_width );
  120.             Strncpy(tmp_buf, files[0].linbuf[i0].text, len);
  121.             expand_field(field0_buf, tmp_buf, field_width, ' ');
  122.         } else {
  123.             expand_field(field0_buf, (char*)NULL, field_width, ' ');
  124.         }
  125.  
  126.         if ( i1 <= last1 ) {
  127.             len = ( files[1].linbuf[i1].length < field_width ?
  128.                 files[1].linbuf[i1].length : field_width );
  129.             Strncpy(tmp_buf, files[1].linbuf[i1].text, len);
  130.             expand_field(field1_buf, tmp_buf, field_width, ' ');
  131.         } else {
  132.             expand_field(field1_buf, (char*)NULL, field_width, ' ');
  133.         }
  134.  
  135.         Fput3(outfile, field0_buf, " | ", field1_buf);
  136.  
  137.     }
  138.  
  139. }
  140.  
  141.  
  142. /*
  143.  * The expand_field() routine performs two functions.  First, it goes
  144.  * through "inbuf" and reformats the line doing stuff like expanding
  145.  * tabs and stripping out newlines.  Second, it expands the text to
  146.  * "fieldlen" characters, using the "padchar" to fill to this length.
  147.  * If the "inbuf" is NULL, we just generate a string of the "padchar".
  148.  */
  149. static void expand_field(outbuf,inbuf,fieldlen,padchar)
  150. char *outbuf;
  151. char *inbuf;
  152. int fieldlen;
  153. int padchar;
  154. {
  155.     int currcol;
  156.  
  157.     /*
  158.      * If no string was passed to us, make one of the full field length.
  159.      */
  160.     if ( inbuf == NULL ) {
  161.         while ( --fieldlen >= 0 )
  162.             *outbuf++ = padchar;
  163.         *outbuf = '\0';
  164.         return;
  165.     }
  166.  
  167.     /*
  168.      * Go through the string doing translations (tab expansion, etc.).
  169.      */
  170.     currcol = 1;
  171.     while ( *inbuf != '\0' && fieldlen > 0 ) {
  172.         if ( *inbuf == '\t' ) {
  173.             do {
  174.                 *outbuf++ = ' ';
  175.             } while ( --fieldlen >= 0 && !( currcol++ & TABSTOP ) ) ;
  176.             ++inbuf;
  177.         } else if ( isascii(*inbuf) && isprint(*inbuf) ) {
  178.             *outbuf++ = *inbuf++;
  179.             ++currcol;
  180.             --fieldlen;
  181.         } else {
  182.             ++inbuf; /* elide this character */
  183.         }
  184.     }
  185.  
  186.     /*
  187.      * Finally, pad it out to the required length.
  188.      */
  189.     while ( --fieldlen >= 0 )
  190.         *outbuf++ = padchar;
  191.     *outbuf = '\0';
  192. }
  193.