diff.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,393 行 · 第 1/3 页

C
1,393
字号
}

/*
 * Sort hash entries
 */

void sort( vector, vecsize )
     LINE           *vector;     /* What to sort       */
     SLONG             vecsize;    /* How many to sort      */
{
    register SLONG      j;
    register LINE       *aim;
    register LINE       *ai;
    SLONG               mid;
    SLONG               k;
    LINE                work;

    for( j = 1; j <= vecsize; j *= 2 )
        ;
    mid = ( j - 1 );
    while( ( mid /= 2 ) != 0 ) {
        k = vecsize - mid;
        for( j = 1; j <= k; j++ ) {
            for( ai = &vector[j]; ai > vector; ai -= mid ) {
                aim = &ai[mid];
                if( aim < ai )
		    break;      /* ?? Why ??     */
                if( aim->hash > ai->hash ||
                    ( aim->hash == ai->hash &&
                     aim->serial > ai->serial ) ) break;
                work.hash = ai->hash;
                ai->hash = aim->hash;
                aim->hash = work.hash;
                work.serial = ai->serial;
                ai->serial = aim->serial;
                aim->serial = work.serial;
            }
        }
    }
}

/*
 * Build equivalence class vector
 */

void equiv()
{
    register LINE       *ap;
    union {
        LINE    *bp;
        short   *mp;
    }                   r;
    register SLONG      j;
    LINE                *atop;

#ifdef DEBUG
    printf( "equiv entry\n" );
    for( j = 1; j <= slenA; j++ ) {
        printf( "sfileA[%d] = %6d %06o\n",
                j, sfileA[j].serial, sfileA[j].hash );
    }
    for( j = 1; j <= slenB; j++ ) {
        printf( "sfileB[%d] = %6d %06o\n",
                j, sfileB[j].serial, sfileB[j].hash );
    }
#endif
    j = 1;
    ap = &sfileA[1];
    r.bp = &sfileB[1];
    atop = &sfileA[slenA];
    while( ap <= atop && j <= slenB ) {
        if( ap->hash < r.bp->hash ) {
            ap->hash = 0;
            ap++;
        } else if( ap->hash == r.bp->hash ) {
            ap->hash = j;
            ap++;
        } else {
            r.bp++;
            j++;
        }
    }
    while( ap <= atop ) {
        ap->hash = 0;
        ap++;
    }
    sfileB[slenB + 1].hash = 0;
#ifdef DEBUG
    printf( "equiv exit\n" );
    for( j = 1; j <= slenA; j++ ) {
        printf( "sfileA[%d] = %6d %06o\n",
                j, sfileA[j].serial, sfileA[j].hash );
    }
    for( j = 1; j <= slenB; j++ ) {
        printf( "sfileB[%d] = %6d %06o\n",
                j, sfileB[j].serial, sfileB[j].hash );
    }
#endif
    ap = &sfileB[0];
    atop = &sfileB[slenB];
    r.mp = &member[0];
    while( ++ap <= atop ) {
        r.mp++;
        *r.mp = -( ap->serial );
        while( ap[1].hash == ap->hash ) {
            ap++;
            r.mp++;
            *r.mp = ap->serial;
        }
    }
    r.mp[1] = -1;
#ifdef DEBUG
    for( j = 0; j <= slenB; j++ ) {
        printf( "member[%d] = %d\n", j, member[j] );
    }
#endif
}

/*
 * Build class vector
 */

void unsort()
{
    SLONG               *temp;
    register SLONG      *tp;
    union {
        LINE    *ap;
        short   *cp;
    }                   u;
    LINE                *evec;
    short               *eclass;
#ifdef DEBUG
    SLONG               i;
#endif

    temp = ( SLONG * ) myalloc( ( slenA + 1 ) * sizeof( SLONG ), "unsort scratch" );
    u.ap = &sfileA[1];
    evec = &sfileA[slenA];
    while( u.ap <= evec ) {
#ifdef DEBUG
        printf( "temp[%2d] := %06o\n", u.ap->serial, u.ap->hash );
#endif
        temp[u.ap->serial] = u.ap->hash;
        u.ap++;
    }

    /*
     * Copy into class vector and free work space
     */
    u.cp = &class[1];
    eclass = &class[slenA];
    tp = &temp[1];
    while( u.cp <= eclass ) {
        *u.cp++ = *tp++;
    }
    myfree( &temp );
#ifdef DEBUG
    printf( "unsort exit\n" );
    for( i = 1; i <= slenA; i++ ) {
        printf( "class[%d] = %d %06o\n", i, class[i], class[i] );
    }
#endif
}

/*
 * Generate maximum common subsequence chain in clist[]
 */

SLONG newcand();
SLONG subseq()
{
    SLONG               a;
    register ULONG      ktop;
    register SLONG      b;
    register SLONG      s;
    ULONG               r;
    SLONG               i;
    SLONG               cand;

    klist[0] = newcand( 0, 0, -1 );
    klist[1] = newcand( slenA + 1, slenB + 1, -1 );
    ktop = 1;                   /* -> guard entry  */
    for( a = 1; a <= slenA; a++ ) {

        /*
         * For each non-zero element in fileA ...
         */
        if( ( i = class[a] ) == 0 )
	    continue;
        cand = klist[0];        /* No candidate now  */
        r = 0;                  /* Current r-candidate  */
        do {
#ifdef DEBUG
            printf( "a = %d, i = %d, b = %d\n", a, i, member[i] );
#endif

            /*
             * Perform the merge algorithm
             */
            if( ( b = member[i] ) < 0 ) {
                b = -b;
            }
#ifdef DEBUG
            printf( "search(%d, %d, %d) -> %d\n",
                    r, ktop, b, search( r, ktop, b ) );
#endif
            if( ( s = search( r, ktop, b ) ) != 0 ) {
                if( clist[klist[s]].b > b ) {
                    klist[r] = cand;
                    r = s;
                    cand = newcand( a, b, klist[s - 1] );
#ifdef DEBUG
                    dumpklist( ktop, "klist[s-1]->b > b" );
#endif
                }
                if( s >= ktop ) {
                    klist[ktop + 1] = klist[ktop];
                    ktop++;
#ifdef DEBUG
                    klist[r] = cand;
                    dumpklist( ktop, "extend" );
#endif
                    break;
                }
            }
        } while( member[++i] > 0 );
        klist[r] = cand;
    }
#ifdef DEBUG
    printf( "last entry = %d\n", ktop - 1 );
#endif
    return( ktop - 1 );          /* Last entry found  */
}

SLONG
newcand( a, b, pred )
    SLONG             a;          /* Line in fileA      */
    SLONG             b;          /* Line in fileB      */
    SLONG             pred;       /* Link to predecessor, index in cand[]  */
{
    register CANDIDATE  *new;

    clength++;
    if( ++clength >= csize ) {
        csize += CSIZE_INC;
        clist = ( CANDIDATE * ) compact( ( char *) clist,
                                         csize * sizeof( CANDIDATE ),
                                         "extending clist" );
    }
    new = &clist[clength - 1];
    new->a = a;
    new->b = b;
    new->link = pred;
    return( clength - 1 );
}

/*
 * Search klist[low..top] (inclusive) for b.  If klist[low]->b >= b,
 * return zero.  Else return s such that klist[s-1]->b < b and
 * klist[s]->b >= b.  Note that the algorithm presupposes the two
 * preset "fence" elements, (0, 0) and (slenA, slenB).
 */

SLONG search( low, high, b )
     register ULONG    low;
     register ULONG    high;
     register SLONG    b;
{
    register SLONG      temp;
    register ULONG      mid;

    if( clist[klist[low]].b >= b )
        return( 0 );
    while( ( mid = ( low + high ) / 2 ) > low ) {
        if( ( temp = clist[klist[mid]].b ) > b )
            high = mid;
        else if( temp < b )
            low = mid;
        else {
            return( mid );
        }
    }
    return( mid + 1 );
}

void unravel( k )
     register SLONG    k;
{
    register SLONG      i;
    register CANDIDATE  *cp;
    SLONG               first_trailer;
    SLONG               difference;

    first_trailer = lenA - suffix;
    difference = lenB - lenA;
#ifdef DEBUG
    printf( "first trailer = %d, difference = %d\n",
            first_trailer, difference );
#endif
    for( i = 0; i <= lenA; i++ ) {
        match[i] = ( i <= prefix ) ? i
            : ( i > first_trailer ) ? i + difference
            : 0;
    }
#ifdef DEBUG
    printf( "unravel\n" );
#endif
    while( k != -1 ) {
        cp = &clist[k];
#ifdef DEBUG
        if( k < 0 || k >= clength )
            error( "Illegal link -> %d", k );
        printf( "match[%d] := %d\n", cp->a + prefix, cp->b + prefix );
#endif
        match[cp->a + prefix] = cp->b + prefix;
        k = cp->link;
    }
}

/*
 * Check for hash matches (jackpots) and collect random access indices to
 * the two files.
 *
 * It should be possible to avoid doing most of the ftell's by noticing
 * that we are not doing a context diff and noticing that if a line
 * compares equal to the other file, we will not ever need to know its
 * file position.  FIXME.
 */

INT check( char *fileAname, char *fileBname )
{
    SLONG       a;          /* Current line in file A  */
    SLONG       b;          /* Current line in file B  */
    SLONG       jackpot;

    fileAname= fileAname;
    fileBname= fileBname;
    /*
     * The VAX C ftell() returns the address of the CURRENT record, not the
     * next one (as in DECUS C or, effectively, other C's).  Hence, the values
     * are "off by one" in the array.  OFFSET compensates for this.
     */

#define OFFSET 0

    b = 1;
    rewind( infd[0] );
    rewind( infd[1] );
    /*
     * See above; these would be over-written on VMS anyway.
     */

    oldseek[0] = ftell( infd[0] );
    newseek[0] = ftell( infd[1] );

    jackpot = 0;
#ifdef DEBUG
    printf( "match vector\n" );
    for( a = 0; a <= lenA; a++ )
        printf( "match[%d] = %d\n", a, match[a] );
#endif
    for( a = 1; a <= lenA; a++ ) {
        if( match[a] == 0 ) {
            /* Unique line in A */
            oldseek[a + OFFSET] = ftell( infd[0] );
            getline( infd[0], text );
            continue;
        }
        while( b < match[a] ) {
            /* Skip over unique lines in B */
            newseek[b + OFFSET] = ftell( infd[1] );
            getline( infd[1], textb );
            b++;
        }

        /*
         * Compare the two, supposedly matching, lines. Unless we are going
         * to print these lines, don't bother to remember where they are.  We
         * only print matching lines if a context diff is happening, or if a
         * jackpot occurs.
         */
        //      if (cflag) {
        oldseek[a + OFFSET] = ftell( infd[0] );
        newseek[b + OFFSET] = ftell( infd[1] );
        //      }
        getline( infd[0], text );
        getline( infd[1], textb );
        if( !streq( text, textb ) ) {
#ifdef DEBUG
            fprintf( stderr, "Spurious match:\n" );
            fprintf( stderr, "line %d in %s, \"%s\"\n",
                     a, fileAname, text );
            fprintf( stderr, "line %d in %s, \"%s\"\n",
                     b, fileBname, textb );
#endif
            match[a] = 0;
            jackpot++;
        }
        b++;
    }
    for( ; b <= lenB; b++ ) {
        newseek[b + OFFSET] = ftell( infd[1] );
        getline( infd[1], textb );
    }
    /*
     * The logical converse to the code up above, for NON-VMS systems, to
     * store away an fseek() pointer at the beginning of the file.  For VMS,
     * we need one at EOF...
     */

    return( jackpot );
}

void output( char *fileAname, char *fileBname )
{
    SLONG       astart;
    SLONG       aend = 0;
    SLONG       bstart;
    SLONG       bend;

    rewind( infd[0] );
    rewind( infd[1] );
    match[0] = 0;
    match[lenA + 1] = lenB + 1;
    if( !eflag ) {
        if( cflag ) {

            /*
             * Should include ctime style dates after the file names, but
             * this would be non-trivial on OSK.  Perhaps there should be a
             * special case for stdin.
             */
            printf( "*** %s\n--- %s\n", fileAname, fileBname );
        }

        /*
         * Normal printout
         */
        for( astart = 1; astart <= lenA; astart = aend + 1 ) {

            /*
             * New subsequence, skip over matching stuff
             */
            while( astart <= lenA && match[astart] == ( match[astart - 1] + 1 ) ) {
                astart++;
            }

            /*
             * Found a difference, setup range and print it
             */
            bstart = match[astart - 1] + 1;
            aend = astart - 1;
            while( aend < lenA && match[aend + 1] == 0 ) {
                aend++;
            }
            bend = match[aend + 1] - 1;
            match[aend] = bend;
            change( astart, aend, bstart, bend );
        }
    } else {

        /*
         * Edit script output -- differences are output "backwards" for the
         * benefit of a line-oriented editor.

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?