/* CP/M BINARY FILE COMPARE UTILITY THIS PROGRAM WAS WRITTEN FOR THE INTEL PL/M-80 CROSS COMPILER 1.0 04/06/2007 UDO MUNK INITIAL VERSION */ 0100H: /* ORIGIN OF THIS PROGRAM FOR CP/M */ DECLARE /* CONSTANTS */ FALSE LITERALLY '0', TRUE LITERALLY '1'; DECLARE /* BDOS FUNCTIONS */ BDOS$EXIT LITERALLY '0', /* EXIT PROGRAM */ BDOS$PRINT LITERALLY '2', /* PRINT CONSOLE CHARACTER */ BDOS$PRINTS LITERALLY '9', /* PRINT CONSOLE STRING */ BDOS$FOPEN LITERALLY '15', /* OPEN FILE */ BDOS$FREAD LITERALLY '20', /* READ FILE */ BDOS$DMA LITERALLY '26'; /* SET DMA ADDRESS */ /* JUST FOR THE FUN OF IT: A DIGITAL RESEARCH LIKE COPYRIGHT */ DECLARE COPYRIGHT DATA (' V1.0, COPYRIGHT (C) 2007, UDO MUNK '); DECLARE /* DEFAULT FILE CONTROL BLOCK */ FCB$A ADDRESS INITIAL(5CH), FCB BASED FCB$A (33) BYTE; DECLARE /* FCB FOR SECOND FILE */ FCB2 (33) BYTE; DECLARE /* DEFAULT BUFFER */ BUFF$A ADDRESS INITIAL(80H), BUFF BASED BUFF$A (128) BYTE; DECLARE /* BUFFER FOR SECOND FILE */ BUFF2 (128) BYTE; DECLARE /* SOME MORE GLOBAL VARIABLES */ EOF1 BYTE INITIAL(FALSE), /* FLAG EOF FILE 1 */ EOF2 BYTE INITIAL(FALSE), /* FLAG EOF FILE 2 */ RECNO ADDRESS INITIAL(0), /* CURRENT RECORD NO. */ I BYTE; /* CALL BDOS FUNCTIONS WITHOUT RETURN CODE */ BDOS1: PROCEDURE(FUNC,PARM); DECLARE FUNC BYTE; DECLARE PARM ADDRESS; DECLARE BDOS$JUMP LITERALLY '05H'; GO TO BDOS$JUMP; END BDOS1; /* CALL BDOS FUNCTIONS WITH BYTE RETURN CODE */ BDOS2: PROCEDURE(FUNC,PARM) BYTE; DECLARE FUNC BYTE; DECLARE PARM ADDRESS; DECLARE BDOS$JUMP LITERALLY '05H'; GO TO BDOS$JUMP; END BDOS2; /* PRINT A STRING TERMINATED WITH $ CHARACTER */ PRINTS: PROCEDURE(S); DECLARE S ADDRESS; CALL BDOS1(BDOS$PRINTS,S); END PRINTS; /* PRINT DECIMAL NUMBER */ PRINTN: PROCEDURE(N); DECLARE N ADDRESS; DECLARE S(5) BYTE INITIAL(' ',' ',' ',' ','0'); DECLARE (I,J) BYTE; I = 4; DO WHILE N > 0; J = N MOD 10 + '0'; N = N / 10; S(I) = J; I = I - 1; END; DO I = 0 TO 4; IF S(I) <> ' ' THEN CALL BDOS1(BDOS$PRINT,S(I)); END; END PRINTN; /* FILE OPEN ERROR, PRINT FILENAME FROM FCB */ FERROR: PROCEDURE(X); DECLARE X ADDRESS; DECLARE F BASED X (33) BYTE; DECLARE (I,C) BYTE; CALL PRINTS(.('FILE NOT FOUND: $')); CALL BDOS1(BDOS$PRINT,F(0) + 'A'); CALL BDOS1(BDOS$PRINT,':'); DO I = 1 TO 8; C = F(I); IF C > ' ' THEN CALL BDOS1(BDOS$PRINT,C); END; CALL BDOS1(BDOS$PRINT,'.'); DO I = 9 TO 11; C = F(I); IF C > ' ' THEN CALL BDOS1(BDOS$PRINT,C); END; END FERROR; /**********************************/ /* MAIN PROGRAM */ /**********************************/ /* BEFORE ANY FILE OPERATIONS THE SECOND FILENAME MUST BE MOVED OUT OF THE DEFAULT FCB! */ DO I = 0 TO 11; FCB2(I) = FCB(I + 16); END; DO; /* GOT TWO FILENAMES AS ARGUMENT? */ IF (FCB(1) = ' ') OR (FCB2(1) = ' ') THEN DO; CALL PRINTS(.('USAGE: CMP FILE1 FILE2$')); GO TO DONE; END; /* TRY TO OPEN FIRST FILE */ IF (BDOS2(BDOS$FOPEN,FCB$A) = 255) THEN DO; CALL FERROR(FCB$A); GO TO DONE; END; /* TRY TO OPEN SECOND FILE */ IF (BDOS2(BDOS$FOPEN,.FCB2) = 255) THEN DO; CALL FERROR(.FCB2); GO TO DONE; END; /* READ FILES AND COMPARE */ DO WHILE TRUE; CALL BDOS1(BDOS$DMA,.BUFF); IF (BDOS2(BDOS$FREAD,FCB$A) <> 0) THEN EOF1 = TRUE; ELSE RECNO = RECNO + 1; CALL BDOS1(BDOS$DMA,.BUFF2); IF (BDOS2(BDOS$FREAD,.FCB2) <> 0) THEN EOF2 = TRUE; IF (EOF1 = TRUE) OR (EOF2 = TRUE) THEN DO; IF (EOF1 = TRUE) AND (EOF2 = TRUE) THEN DO; CALL PRINTS(.('FILES ARE EQUAL$')); GO TO DONE; END; ELSE IF EOF1 = TRUE THEN DO; CALL PRINTS(.('FILE2 IS LARGER$')); GO TO DONE; END; ELSE DO; CALL PRINTS(.('FILE2 IS SMALLER$')); GO TO DONE; END; END; DO I = 0 TO 127; IF BUFF(I) <> BUFF2(I) THEN DO; CALL PRINTS(.('FILES ARE DIFFERENT AT RECORD: $')); CALL PRINTN(RECNO); CALL PRINTS(.(', AND BYTE: $')); CALL PRINTN(I + 1); GO TO DONE; END; END; END; DONE: END; CALL BDOS1(BDOS$EXIT,0); /* DONE, TERMINATE PROGRAM */ EOF