/* * CDI.C - CHARACTER DIFFERENCE DETECTOR * * ÁDRIAN ÐEPPER, 1987 * * DEVELOPED WITH/FOR à ÐÏ×ÅÒ 64 SYSTEM * * ÕPLOADED AS IS, IN RESPONSE TO * PERCEIVED NEED. (ÔHAT'S AN APOLOGY * FOR LACK OF COMMENTS) * * ÕSAGE: * * CDI [-H -O# -L# -M#] FILE1 FILE2 * * -H GIVE OUTPUT IN HEX (ELSE DECIMAL) * * -O SPECIFY AN OFFSET (IN DECIMAL) TO * BE ASSUMED FOR BEGINNING OF FILE * * -L,-M SET VALUES OF VARS MATLEN, * AND MATRAT, WHICH INFLUENCE THE * ALGORITHM FOR DECIDING WHEN FILES * ARE MATCHING AGAIN */ #INCLUDE #DEFINE ÙÅÓ 1 #DEFINE ÎÏ 0 TYPEDEF INT ÂÉÇ; /* USE FLOAT FOR REALLY ÂÉÇ FILES */ INT MATLEN = 20; INT MATRAT = 2; INT HEX = 0; INT OFFSET = 0; MAIN(ARGC,AV) INT ARGC; CHAR **AV; Û AUTO ÆÉÌÅ F1, F2; AUTO CHAR **ARGV; ARGV = AV; ARGC = OPTION(ARGC, &ARGV); IF (ARGC < 2) Û PRINTF("USAGE:CDI [-L# -M# -H -O#] FILE1 FILE2\N"); EXIT(1); Ý IF ((F1 = FOPEN(ARGV[0], "R")) == 0 ßß FERROR()) Û PRINTF("CAN'T OPEN %S\N",ARGV[0]); EXIT(1); Ý IF ((F2 = FOPEN(ARGV[1], "R")) == 0 ßß FERROR()) Û PRINTF("CAN'T OPEN %S\N",ARGV[1]); EXIT(1); Ý CDI(F1, F2, ARGV[0], ARGV[1]); Ý OPTION(ARGC, PARGV) INT ARGC; CHAR ***PARGV; Û AUTO CHAR **ARGV; MATLEN = 20; MATRAT = 2; HEX = 0; OFFSET = 0; ARGV = *PARGV; ++ARGV; --ARGC; WHILE (ARGC > 0 && *ARGV[0] == '-') Û SWITCH ((*ARGV)[1]) Û CASE 'L': IF (--ARGC < 1 ßß (MATLEN = ATOI(*++ARGV)) <= 0) MATLEN = 1; BREAK; CASE 'M': IF (--ARGC < 1 ßß (MATRAT = ATOI(*++ARGV)) <= 0) MATRAT = 1; BREAK; CASE 'O': IF (--ARGC >= 1) OFFSET = ATOI(*++ARGV); BREAK; CASE 'H': HEX = 1; BREAK; DEFAULT: *PARGV = ARGV; RETURN 0; Ý --ARGC; ++ARGV; Ý *PARGV = ARGV; RETURN ARGC; Ý BCMP(B1, B2, LEN) INT B1[], B2[]; INT LEN; Û AUTO INT I; FOR (I = 0; I < LEN; ++I) IF (B1[I] != B2[I]) RETURN ÎÏ; RETURN ÙÅÓ; Ý MATCH(U1, B1, R1, U2, B2, R2, LENGTH) INT U1; INT B1[]; INT R1; INT U2; INT B2[]; INT R2; INT LENGTH; Û AUTO INT I; IF ((R1-U1) < LENGTH ßß (R2-U2) < LENGTH) RETURN R1; FOR (I = U1; I <= (R1-LENGTH) && BCMP(&B1[I], &B2[R2-LENGTH], LENGTH) == ÎÏ; ++I) ; RETURN I; Ý SHUFFLE(BUF, R, U) INT BUF[]; INT R, U; Û AUTO INT I; IF (U == 0) Û PRINTF("ÔOO MANY DIFFERENCES\N"); EXIT(1); Ý FOR (I = U; I < R; ++I) BUF[I-U] = BUF[I]; RETURN R-U; Ý #DEFINE ÍÁØÂÕÆ 1000 INT BUF1[ÍÁØÂÕÆ] = Û0Ý; INT BUF2[ÍÁØÂÕÆ] = Û0Ý; CDI(F1, F2, NAME1, NAME2) ÆÉÌÅ F1, F2; CHAR *NAME1, *NAME2; Û AUTO ÂÉÇ COUNT1, COUNT2; AUTO INT USED1, USED2; /* BUFFERED CHAR "USED" */ AUTO INT READ1, READ2; /* BUFFERED CHAR "READ" */ AUTO INT I1, I2; AUTO INT LEN; AUTO CHAR *FMT; READ1 = READ2 = 0; USED1 = USED2 = 0; COUNT1 = COUNT2 = ((ÂÉÇ)OFFSET); FOR ( ; ; ) Û WHILE (USED1 != READ1 ßß USED2 != READ2) Û IF (USED1 == READ1) Û USED1 = READ1 = 0; BUF1[READ1++] = GETC(F1); Ý IF (USED2 == READ2) Û USED2 = READ2 = 0; BUF2[READ2++] = GETC(F2); Ý LEN = READ1-USED1; IF ((READ2-USED2) > LEN) LEN = READ2-USED2; LEN = (LEN/MATRAT) + 1; IF (LEN > MATLEN) LEN = MATLEN; I1 = MATCH(USED1, BUF1, READ1, USED2, BUF2, READ2, LEN); I2 = MATCH(USED2, BUF2, READ2, USED1, BUF1, READ1, LEN); /* ASSERT USED1 < READ1 && USED2 < READ2 */ IF (BUF1[USED1] == BUF2[USED2]) Û ++USED1; ++USED2; COUNT1 = COUNT1 + ((ÂÉÇ)1); COUNT2 = COUNT2 + ((ÂÉÇ)1); Ý ELSE IF (I1 <= (READ1-LEN) && (I2 > (READ2-LEN) ßß (I1-USED1) <= (I2-USED2))) Û SHOWDIFF(&COUNT1, BUF1, &USED1, I1, &COUNT2, BUF2, &USED2, READ2-LEN, LEN); Ý ELSE IF (I2 <= (READ2-LEN) && (I1 > (READ1-LEN) ßß (I2-USED2) <= (I1-USED1))) Û SHOWDIFF(&COUNT1, BUF1, &USED1, READ1-LEN, &COUNT2, BUF2, &USED2, I2, LEN); Ý ELSE Û IF (READ1 >= ÍÁØÂÕÆ) Û READ1 = SHUFFLE(BUF1, READ1, USED1); USED1 = 0; Ý BUF1[READ1++] = GETC(F1); IF (READ2 >= ÍÁØÂÕÆ) Û READ2 = SHUFFLE(BUF2, READ2, USED2); USED2 = 0; Ý BUF2[READ2++] = GETC(F2); Ý Ý USED1 = READ1 = 0; BUF1[0] = GETC(F1); USED2 = READ2 = 0; BUF2[0] = GETC(F2); IF (BUF1[0] == ÅÏÆ && BUF2[0] == ÅÏÆ) BREAK; IF (BUF1[0] != BUF2[0]) Û ++READ1; ++READ2; Ý ELSE Û COUNT1 = COUNT1 + ((ÂÉÇ)1); COUNT2 = COUNT2 + ((ÂÉÇ)1); Ý Ý FMT = "%D:%S %0.0F(%0.0F BYTES)\N"; IF (SIZEOF(ÂÉÇ) != SIZEOF(FLOAT)) FMT = HEX ? "%D:%S $%04X (%D BYTES)\N" : "%D:%S %D (%D BYTES)\N"; PRINTF(FMT, 1, NAME1, COUNT1, COUNT1-((ÂÉÇ)OFFSET)); PRINTF(FMT, 2, NAME2, COUNT2, COUNT2-((ÂÉÇ)OFFSET)); Ý SHOWDIFF(PC1, B1, PU1, I1, PC2, B2, PU2, I2, LEN) ÂÉÇ *PC1; INT B1[]; INT *PU1; INT I1; ÂÉÇ *PC2; INT B2[]; INT *PU2; INT I2; Û AUTO INT I; AUTO CHAR *FMT; FMT = "%D:(%6.0F):"; IF (SIZEOF(ÂÉÇ) != SIZEOF(FLOAT)) FMT = HEX ? "%D:($%04X):" : "%D:(%6D):"; IF (B1[I1+LEN-1] != B2[I2+LEN-1]) Û PRINTF("SHOULDN'T HAPPEN\N"); Ý PRINTF(FMT, 1, *PC1); FOR (I = *PU1; I <= I1; ++I) PRINTF(" %02X", B1[I]); PRINTF("\N"); PRINTF(FMT, 2, *PC2); FOR (I = *PU2; I <= I2; ++I) PRINTF(" %02X", B2[I]); PRINTF("\N"); *PC1 = *PC1 + ((ÂÉÇ)(I1 - *PU1 + 1)); *PU1 = I1 + 1; *PC2 = *PC2 + ((ÂÉÇ)(I2 - *PU2 + 1)); *PU2 = I2 + 1; Ý