.TITLE LOAD MODULE COMPARE ROUTINE .IDENT /SSA001/ ; ; .SBTTL FILE DISCRIPTOR BLOCKS ; ; .MCALL FSRSZ$,FDBDF$,FDAT$A,FDRC$A,FDBK$A,FDOP$A,NMBLK$ ; ; FSRSZ$ 4 ; FOUR R.VAR FILES OPEN AT ONE TIME ; .PSECT DATA RW,D TOFDB: FDBDF$ ; FDB FOR TERMINAL OUTPUT FDAT$A R.VAR,FD.CR,80.,, ; VAR. RECORDS 80 BYTE MAX, INSERT CR FDRC$A FD.PLC,, ; LOCATE MODE FDOP$A 9.,OFDSPT ; LUN = 9, FILE OPEN SECTION AT OFDSPT OFDSPT: .WORD DNAMSZ,DNAM ; DEVICE NAME DISCRIPTOR .WORD 0,0 ; NULL DIRECTORY DISCRIPTOR .WORD 0,0 ; NULL FILENAME DISCRIPTOR DNAM: .ASCII /TI:/ ; DEFINES DEVICE NAME STRING DNAMSZ =.-DNAM ; DEVICE NAME STRING LENGTH .EVEN ; ; LSTFDB: FDBDF$ ; FDB FOR ERROR LIST FILE FDAT$A R.VAR,FD.CR,80.,, ; VAR. RECORDS 80 BYTE MAX, INSERT CR FDRC$A FD.PLC,, ; LOCATE MODE FDOP$A 1,CSIBLK+C.DSDS,LSTNAM ; LUN=1, FILENAME=COMMAND STRING INPUT LSTNAM: NMBLK$ COMPLM,DAT,,SY,0 ; DEFAULT FILENAME=SY0:COMPLM.DAT ; ; F1FDB: FDBDF$ ; FDB FOR INPUT FILE NUMBER 1 FDRC$A FD.RWM ; SET TO BLOCK MODE FDBK$A F1BUFA,512.,,1,F1ERR ; INPUT BUF=F1BUFA, BLOCK=512.BYTES FDOP$A 2,CSIBLK+C.DSDS,FILNAM ; LUN=2, FILENAME=COMMAND STRING INPUT ; ; F2FDB: FDBDF$ ; FDB FOR INPUT FILE NUMBER 2 FDRC$A FD.RWM ; SET TO BLOCK MODE FDBK$A F2BUFA,512.,,2,F2ERR ; INPUT BUF=F3BUFA, BLOCK=512.BYTES FDOP$A 3,CSIBLK+C.DSDS,FILNAM ; LUN=3, FILENAME=COMMAND STRING INPUT ; FILNAM: NMBLK$ ,LDA,,SY,0 ; DEFAULTS FOR INPUT FILES, DEV=SY:0, ; NO DEFAULT FOR FILENAME, EXT=.LDA ; F1ERR: .BLKW 2 ; FILE 1 I/O ERROR STORAGE SPACE F2ERR: .BLKW 2 ; FILE 2 I/O ERROR STORAGE SPACE ; F1BUFA: .BLKW 512. ; FILE 1 INPUT BUFFER - A F1BUFB = F1BUFA+512. ; FILE 1 INPUT BUFFER - B F2BUFA: .BLKW 512. ; FILE 2 INPUT BUFFER - A F2BUFB = F2BUFA+512. ; FILE 2 INPUT BUFFER - B MEMBUF: .BLKW 8. ; INPUT BUFF. MEMORY MANAGEMENT ; F1TEMP: FDBDF$ ; FILE 1 POST-PROCESSING DATA FILE FDAT$A R.FIX,FD.BLK,6.,, ; FIXED LENGTH RECORDS 6 BYTES LONG ; RECORDS WILL NOT CROSS BLK. BOUNDARIES FDRC$A FD.RAN,PPBUFA,6. ; RANDOM ACCESS, I/O BUFFER = PPBUFA FDOP$A 7 ; LUN = 7 ; F2TEMP: FDBDF$ ; FILE 2 POST-PROCESSING DATA FILE FDAT$A R.FIX,FD.BLK,6.,, ; FIXED LENGTH RECORDS 6 BYTES LONG ; RECORDS WILL NOT CROSS BLOCK BOUNDARIES FDRC$A FD.RAN,PPBUFA,6. ; RANDOM ACCESS, I/O BUFFER = PPBUFA FDOP$A 8. ; LUN = 8 ; PPBUFA: .BLKW 3 ; POST-PROCESSING I/O BUFFER A PPBUFB: .BLKW 3 ; POST-PROCESSING I/O BUFFER B PPNULL: .WORD 77777 ; NULL RECORD FOR POST PROCESSING .WORD 77777 ; NULL RECORD FOR POST PROCESSING .WORD 77777 ; NULL RECORD FOR POST PROCESSING .PAGE .SBTTL COMMAND LINE DATA BLOCKS ; ; .MCALL GCMLB$,CSI$,CSI$SW,CSI$SV,CSI$ND ; GCLBLK: GCMLB$ 2,CLM,,5 ; GET COMMAND LINE CONTROL BLK ; CSI$ ; COMMAND INTERPRETER CONTROL BLK CSIBLK: .BLKB C.SIZE .EVEN ; SWTAB: CSI$SW HA,SW.HA,FLAG,SET,NEG ; INPUT FILES ARE H-516 LOAD MODULES CSI$SW SP,SW.SP,FLAG,SET,NEG ; SPOOL OUTPUT FILE CSI$SW O1,SW.OF,FLAG,SET,,O1TAB; PROVIDE FILE OFFSET NUMBER 1 CSI$SW O2,SW.OF,FLAG,SET,,O2TAB; PROVIDE FILE OFFSET NUMBER 2 CSI$SW O3,SW.OF,FLAG,SET,,O3TAB; PROVIDE FILE OFFSET NUMBER 3 CSI$SW O4,SW.OF,FLAG,SET,,O4TAB; PROVIDE FILE OFFSET NUMBER 4 CSI$SW O5,SW.OF,FLAG,SET,,O5TAB; PROVIDE FILE OFFSET NUMBER 5 CSI$SW VI,SW.VI,FLAG,SET,NEG ; OUTPUT VIRTUAL ADDRESSES CSI$SW PP,SW.PP,FLAG,SET,NEG ; PERFORM POST-PROCESSING O1TAB: CSI$SV OCTAL,O1,2 ; OFFSET VALUE DESCRIPTOR NUMBER 1 O2TAB: CSI$SV OCTAL,O2,2 ; OFFSET VALUE DESCRIPTOR NUMBER 2 O3TAB: CSI$SV OCTAL,O3,2 ; OFFSET VALUE DESCRIPTOR NUMBER 3 O4TAB: CSI$SV OCTAL,O4,2 ; OFFSET VALUE DESCRIPTOR NUMBER 4 O5TAB: CSI$SV OCTAL,O5,2 ; OFFSET VALUE DESCRIPTOR NUMBER 5 CSI$ND ; END OF SWITCH TABLE ; SW.HA=1 ; /HA SWITCH MASK SW.SP=2 ; /SP SWITCH MASK SW.OF=4 ; /OFFSET SWITCH MASK SW.VI=10 ; /VI SWITCH MASK SW.PP=20 ; /PP SWITCH MASK ; FLAG: .WORD 0 ; STORAGE FOR SWITCH ENTRIES O1: .WORD 0 ; STORAGE FOR OFFSET VALUE NUMBER 1 O2: .WORD 0 ; STORAGE FOR OFFSET VALUE NUMBER 2 O3: .WORD 0 ; STORAGE FOR OFFSET VALUE NUMBER 3 O4: .WORD 0 ; STORAGE FOR OFFSET VALUE NUMBER 4 O5: .WORD 0 ; STORAGE FOR OFFSET VALUE NUMBER 5 .PAGE .SBTTL FILE PROCESSING BLOCKS ; ; THE FILE PROCESSING BLOCKS CONTAIN THE VARIABLES NEEDED TO ; COMPARE FILE 1 AND FILE 2 ; ; THE FOLLOWING DEFINES THE OFFSETS INTO THE FILE PROCESSING BLOCKS ; ; EACH SYMBOL WILL BE USED TO INDEX A REGISTER SET TO THE BEGINNING ; OF THE FILE PROCESSING BLOCK. THIS WILL ENABLE THE PROGRAM TO ; ACCESS INFORMATION FROM FILES 1 OR 2 BY CHANGING THE POINTER TO ; THE SPECIFIC FILE BLOCK ; S.FDBP = 0 ; POINTER TO FILE FDB S.INBF = 2 ; CURRENT INPUT BUFFER (A OR B) S.BFSW = 4 ; BUFFER STORAGE SWITCH, 0 = A 1 = B S.BUFA = 6 ; ADDRESS OF INPUT BUFFER A S.BUFB = 10 ; ADDRESS OF INPUT BUFFER B S.EOF = 12 ; END OF FILE FLAG S.BTCT = 14 ; CURRENT BYTE COUNT S.BAAD = 16 ; VIRTUAL BASE ADDRESS S.BEND = 20 ; ENDING ADDRESS OF CURRENT BUFFER S.ENDA = 22 ; END OF BUFFER A S.ENDB = 24 ; END OF BUFFER B S.MAXB = 26 ; MAX BYTE COUNT S.FFBT = 30 ; FIRST FREE BYTE OF LAST BLK S.ERCT = 32 ; BYTE COUNT AT ERROR S.ERXB = 34 ; MAX BYTE COUNT AT ERROR S.ERAD = 36 ; BASE ADDRESS AT ERROR S.ERLO = 40 ; LOCATION IN BUFFER AT ERROR S.MALO = 42 ; LOCATION IN BUFFER AT MATCH S.MACT = 44 ; BYTE COUNT AT MATCH S.MXBM = 46 ; MAX BYTE AT MATCH S.MAAD = 50 ; BASE ADDRESS AT MATCH S.OFFS = 52 ; AMOUNT OF OFFSET S.DATA = 54 ; DATA WORD PLUS OFFSET S.VIRT = 56 ; CURRENT VIRTUAL ADDRESS S.NEW0 = 60 ; NEW MEMORY MANAGEMENT REG. 0 S.MMR0 = 62 ; MEMORY MANAGEMENT REG. 0 S.PAF = 64 ; PHYSICAL ADDRESS OFFSET S.SDR0 = 66 ; SUPERVISOR I SPACE ADDRESS REGISTOR 0-8 S.ERM0 = 106 ; MEMORY MANAGEMENT REG. 0 AT ERROR S.EEW0 = 110 ; NEW MEMORY MANAGEMENT REG 0 AT ERROR S.ERAF = 112 ; PHYSICAL ADDRESS OFFSET AT ERROR S.ERR0 = 114 ; SUPER. I SPACE ADDRESS REG. 0-8 AT ERROR S.MAM0 = 134 ; MEMORY MANAGEMENT REG. 0 AT MATCH S.MEW0 = 136 ; NEW MEMORY MANAGEMENT R0 AT MATCH S.MAAF = 140 ; PHYSICAL ADDRESS OFFSET AT MATCH S.MAR0 = 142 ; SUPER. I SPACE ADDRESS REG 0-8 AT MATCH S.OTCT = 162 ; POINTER TO END OF POST-PROCESS DATA ; ; FILE1: .WORD F1FDB ; S.FDBP .WORD F1BUFA ; S.INBF .WORD 0 ; S.BFSW .WORD F1BUFA ; S.BUFA .WORD F1BUFB ; S.BUFB .WORD 0 ; S.EOF .WORD 0 ; S.BTCT .WORD 0 ; S.BAAD .WORD 0 ; S.BEND .WORD F1BUFA+512. ; S.ENDA .WORD F1BUFB+512. ; S.ENDB .WORD 0 ; S.MAXB .WORD 0 ; S.FFBT .WORD 0 ; S.ERCT .WORD 0 ; S.ERXB .WORD 0 ; S.ERAD .WORD 0 ; S.ERLO .WORD 0 ; S.MALO .WORD 0 ; S.MACT .WORD 0 ; S.MXBM .WORD 0 ; S.MAAD .WORD 0 ; S.OFFS .WORD 0 ; S.DATA .WORD 0 ; S.VIRT .WORD 0 ; S.NEW0 .WORD 0 ; S.MMR0 .WORD 0 ; S.PAF .BLKW 8. ; S.SDR0 (SPACE FOR 8 REGISTORS) .WORD 0 ; S.ERM0 .WORD 0 ; S.EEW0 .WORD 0 ; S.ERAF .BLKW 8. ; S.ERR0 (SPACE FOR 8 REGISTORS) .WORD 0 ; S.MAM0 .WORD 0 ; S.MEW0 .WORD 0 ; S.MAAF .BLKW 8. ; S.MAR0 (SPACE FOR 8 REGISTORS) .WORD 0 ; S.OTCT ; ; FILE2: .WORD F2FDB ; S.FDBP .WORD F2BUFA ; S.INBF .WORD 0 ; S.BFSW .WORD F2BUFA ; S.BUFA .WORD F2BUFB ; S.BUFB .WORD 0 ; S.EOF .WORD 0 ; S.BTCT .WORD 0 ; S.BAAD .WORD 0 ; S.BEND .WORD F2BUFA+512. ; S.ENDA .WORD F2BUFB+512. ; S.ENDB .WORD 0 ; S.MAXB .WORD 0 ; S.FFBT .WORD 0 ; S.ERCT .WORD 0 ; S.ERXB .WORD 0 ; S.ERAD .WORD 0 ; S.ERLO .WORD 0 ; S.MALO .WORD 0 ; S.MACT .WORD 0 ; S.MXBM .WORD 0 ; S.MAAD .WORD 0 ; S.OFFS .WORD 0 ; S.DATA .WORD 0 ; S.VIRT .WORD 0 ; S.NEW0 .WORD 0 ; S.MMR0 .WORD 0 ; S.PAF .BLKW 8. ; S.SDR0 (SPACE FOR 8 REGISTORS) .WORD 0 ; S.ERM0 .WORD 0 ; S.EEW0 .WORD 0 ; S.ERAF .BLKW 8. ; S.ERR0 (SPACE FOR 8 REGISTORS) .WORD 0 ; S.MAM0 .WORD 0 ; S.MEW0 .WORD 0 ; S.MAAF .BLKW 8. ; S.MAR0 (SPACE FOR 8 REGISTORS) .WORD 0 ; S.OTCT .PAGE .SBTTL GET COMMAND LINE AND OPEN FILES ; ; .MCALL FINIT$,EXIT$S,GCML$,OPEN$W,OPEN$R,CLOSE$,CSI$1,CSI$2 .MCALL CALL,RETURN,READ$,WAIT$,OPNT$D,GET$,PUT$ ; ; .EVEN .PSECT CODE GO:: FINIT$ ; INITIALIZE FDB'S OPEN$W #TOFDB ; OPEN THE TI: FOR OUTPUT BCC START ; OK TO START PROCESSING JMP EXIT ; CAN'T TALK TO TI:, SO SPLIT START: CLR FLAG ; CLEAR ALL SWITCH ENTRIES MOV #5,R0 ; SET UP LOOP COUNT MOV #O1,R1 ; POINTER TO OFFSETS 1$: CLR (R1)+ ; CLEAR ALL OFFSETS SOB R0,1$ ; LOOP UNTIL ALL ARE DONE GCML$ #GCLBLK ; REQUEST COMMAND LINE BCS CHKZ ; ERROR READING COMMAND LINE CSI$1 #CSIBLK,GCLBLK+G.CMLD+2,GCLBLK+G.CMLD ; COMPRESS AND CHECK SYNTAX BCS ERRSYN ; ERROR IN SYNTAX BITB CSIBLK+C.STAT,#CS.EQU ; INPUT MUST CONTAIN AN "=" SIGN BEQ ERRSYN ; ERROR IN SYNTAX CSI$2 #CSIBLK,OUTPUT,#SWTAB ; GET OUTPUT FILESPEC BCS ERRSYN ; ERROR IN SYNTAX OPEN$W #LSTFDB ; OPEN OUTPUT FILE BCS EROFIL ; ERROR WHEN OPENING FILE CALL OUTCMD ; OUTPUT COMMAND LINE CSI$2 #CSIBLK,INPUT,#SWTAB ; GET INPUT FILE 1 SPEC BCS ERRSYN ; ERROR IN SYNTAX OPEN$R #F1FDB ; OPEN FILE 1 BCS ERFIL1 ; ERROR WHEN OPENING FILE 1 CSI$2 #CSIBLK,INPUT,#SWTAB ; GET INPUT FILE 2 SPEC BCS ERRSYN ; SYNTAX ERROR OPEN$R #F2FDB ; OPEN FILE 2 BCS ERFIL2 ; ERROR WHEN OPENING FILE 2 BIT #20,FLAG ; POST-PROCESSING REQUIRED? BEQ 2$ ; NO - SO DON`T OPEN FILES OPNT$D #F1TEMP ; OPEN POST-PROCESSING FILE 1 BCS ERRTMP ; OUTPUT ERROR MESSAGE OPNT$D #F2TEMP ; OPEN POST-PROCESSING FILE 2 BCS ERRTMP ; OUTPUT ERROR MESSAGE 2$: JMP MAIN ; GO DO IT ; CHKZ: CMPB GCLBLK+G.ERR,#GE.EOF ; WAS INPUT A CONTROL Z ? BEQ EXIT ; Y - NORMAL EXIT JMP ERRSYN ; ERROR IN SYNTAX ; ERRTMP: MOV #ERR12,R5 ; BR CALLO ; CALL OUTPUT ERRSYN: MOV #ERR1,R5 ; BR CALLO ; CALL OUTPUT EROFIL: MOV #ERR2,R5 ; BR CALLO ; CALL OUTPUT ERFIL1: MOV #ERR3,R5 ; BR CALLO ; CALL OUTPUT ERFIL2: MOV #ERR4,R5 ; CALLO: CALL OUTTI ; CALL OUTPUT TO TI: JMP RESTRT ; CLOSE FILES AND START OVER ; OUTCMD: MOV #ASTRI1,R5 ; OUTPUT ASTRICS WITH CR CALL OUT ; OUTPUT TO OUTPUT FILE PUT$ #LSTFDB,GCLBLK+G.CMLD+2,GCLBLK+G.CMLD ; OUTPUT COMMAND LINE MOV #ASTRI2,R5 ; OUTPUT MORE ASTRICS NO CR CALL OUT ; OUTPUT TO OUTPUT FILE RETURN ; EXIT: CALL CLOSE ; CLOSE ALL FILES CLOSE$ #TOFDB ; CLOSE THE TI: FILE EXIT$S ; NORMAL EXIT ; RESTRT: CALL CLOSE ; CLOSE ALL FILES JMP START ; GO BACK FOR MORE INPUT ; CLOSE: CLOSE$ #LSTFDB ; CLOSE OUTPUT FILE CLOSE$ #F1FDB ; CLOSE INPUT FILE 1 CLOSE$ #F2FDB ; CLOSE INPUT FILE 2 CLOSE$ #F1TEMP ; CLOSE TEMPORARY FILE 1 CLOSE$ #F2TEMP ; CLOSE TEMPORARY FILE 2 RETURN .PAGE .SBTTL MAIN COMPARE LOOP ; ; .PSECT DATA ; ERRCND: .WORD 0 ; SET DURING ERROR CONDITION FILSKW: .WORD 0 ; FILE 1 VIRTUAL ADD.+SKEW ERROR: .WORD 0 ; ERROR MESSAGE FLAG ; ; ; ; ; ; THE ROUTINE "MAIN" IS THE MAIN COMPARE LOOP. THE PROGRAM STAYS IN ; THIS LOOP UNTIL A MISSMATCH IS ENCOUNTERED. ; ; .PSECT CODE MAIN: MOV #FILE1,R1 ; USE R1 FOR FILE 1 MOV #FILE2,R2 ; USE R2 FOR FILE 2 CLR S.EOF(R1) ; DO HOUSEKEEPING CLR S.EOF(R2) ; CLEAR END OF FILE FILE 2 CLR S.BFSW(R1) ; CLEAR BUFFER SELECT SWITCH CLR S.BFSW(R2) ; SAME FOR FILE 2 CLR S.MMR0(R1) ; CLEAR MEMORY MANAG. CONTROL CLR S.MMR0(R2) ; SAME FOR FILE 2 CLR S.PAF(R1) ; CLEAR PAGE ADDRESS FIELD CLR S.PAF(R2) ; SAME FOR FILE 2 CLR S.OTCT(R1) ; CLEAR POST-PROCESSING COUNT CLR S.OTCT(R2) ; SAME FOR FILE 2 CLR MATCH5 ; CLEAR NUMBER OF MATCHES CLR ERROR ; CLEAR ERROR MESSAGE FLAG CLR ERRCND ; CLEAR ERROR CONDITION CLR FILSKW ; CLEAR ADDRESS OFFSET CLR LIMIT1 ; CLEAR OUTPUT LIMIT 1 CLR LIMIT2 ; CLEAR OUTPUT LIMIT 2 CLR LIMIT3 ; CLEAR OUTPUT LIMIT 3 MOV R1,R5 ; GET SET TO READ FILE 1 CALL READ ; READ FIRST BLOCK FILE 1 MOV F.FFBY(R0),S.FFBT(R1) ; STORE FIRST FREE BYTE MOV S.BUFA(R1),R3 ; GET ADDRESS OF INPUT BUF ADD (R3),R3 ; THE FIRST LOCATION IS THE ; BYTE COUNT. BY ADDING IT TO ; THE BASE WE STEP OVER THE ; LOAD MODULE HEADER. TST (R3)+ ; BUMP TO NEXT BYTE COUNT MOV R2,R5 ; GET SET TO READ FILE 2 CALL READ ; READ FIRST BLOCK FILE 2 MOV F.FFBY(R0),S.FFBT(R2) ; STORE FIRST FREE BYTE FILE 2 MOV S.BUFA(R2),R4 ; GET ADDRESS OF INPUT BUFFER ADD (R4),R4 ; ADD RECORD BYTE COUNT TO BASE TST (R4)+ ; BUMP POINTER TO NEXT BYTE COUNT CMP S.FFBT(R1),S.FFBT(R2) ; COMPARE FIRST FREE BYTES BEQ 1$ ; IF EQUAL SKIP ERROR MESSAGE CALL ERREOF ; 1$: CALL BTCBA1 ; GET BYTE COUNT AND BASE ADDRESS CALL BTCBA2 ; GET BYTE CT. BASE ADD. FILE 2 COMPAR: CMP S.VIRT(R1),S.VIRT(R2) ; COMPARE VIRTUAL ADDRESSES BEQ 1$ ; IF EQUAL GO COMPARE DATA MOV FILSKW,R5 ; GET OLD FILSKW ADD S.VIRT(R1),R5 ; ADD IN FILE 1 VIRTUAL ADDR. CMP R5,S.VIRT(R2) ; ARE FILES STILL TRACKING? BEQ 1$ ; YES - SO CONTINUE MOV S.VIRT(R2),FILSKW ; CALCULATE NEW FILSKW SUB S.VIRT(R1),FILSKW ; S.VIRT(R1)-S.VIRT(R2)=FILSKW CALL OUT4 ; OUTPUT THE ERROR MESSAGE 1$: CMP (R3),(R4) ; BEGIN COMPARING DATA BEQ 6$ ; EQUAL SO GO ON BIT #4,FLAG ; ANY OFFSETS ENTERED? BEQ 3$ ; NO - SKIP OFFSET CALCULATIONS MOV #5,R5 ; SET UP LOOP COUNT MOV #O1,R0 ; POINTER TO FIRST OFFSET 2$: MOV (R4),S.DATA(R2) ; STORE DATA FILE 2 ADD (R0),S.DATA(R2) ; ADD OFFSET FILE 2 CMP (R3),S.DATA(R2) ; CMP DATA INCLUDING OFFSET BEQ 6$ ; THIS COMPARES SO GO ON MOV (R4),S.DATA(R2) ; STORE DATA FILE 2 SUB (R0)+,S.DATA(R2) ; SUB OFFSET FILE 2 AND BUMP CMP (R3),S.DATA(R2) ; CMP DATA INCLUDING OFFSET BEQ 6$ ; THIS COMPARES SO GO ON SOB R5,2$ ; LOOP TO DO ALL OFFSETS 3$: MOV #FILE1,R5 ; ERROR - SET UP FOR FILE 1 CALL STORIT ; STORE FILE PARAMETERS AT ERROR MOV R3,S.ERLO(R1) ; STORE CURRENT BUF LOCATION INC S.BFSW(R1) ; SET UP TO STORE IN BUF B MOV #FILE2,R5 ; SET UP FOR FILE 2 CALL STORIT ; STORE FILE 2 PARAMETERS MOV R4,S.ERLO(R2) ; STORE FILE 2 BUF LOC. INC S.BFSW(R2) ; STORE NEXT READ IN BUF B INC ERROR ; SET ERROR MESSAGE FLAG INC ERRCND ; SET ERROR CONDITION TST S.EOF(R1) ; FILE 1 AT EOF? BNE 4$ ; YES - SO OUTPUT FILE 2 TST S.EOF(R2) ; FILE 2 AT EOF? BEQ 5$ ; NO - SO TRY TO FIND A MATCH JMP EOFF2 ; YES - OUTPUT 10 LOCS. FILE 1 4$: JMP EOFF1 ; OUTPUT 10 LOCATIONS OF FILE 2 5$: JMP FINDIT ; FINDIT TRIES TO MATCH-UM UP 6$: TST (R3)+ ; ADVANCE TO NEXT DATA WORD TST (R4)+ ; FILE 2 TO NEXT DATA WORD CALL ENDBF1 ; SEE IF WE'RE AT END OF BUF CALL ENDBF2 ; FILE 2 AT END OF BUFFER BIT #1,FLAG ; HONEYWELL ADDRESSING? BNE 7$ ; YES - SO INC S.VIRT ONCE INC S.VIRT(R1) ; STEP VIRTUAL ADDRESS ONCE INC S.VIRT(R2) ; SAME FOR FILE 2 7$: INC S.VIRT(R1) ; STEP VIRTUAL ADDRESS AGAIN INC S.VIRT(R2) ; SAME FOR FILE 2 ADD #2,S.BTCT(R1) ; INC FILE 1 WORD COUNT CMP S.BTCT(R1),S.MAXB(R1) ; DONE ALL THE BYTES THIS REC BLT 8$ ; NO - SO CONTINUE CALL BTCBA1 ; RE-STORE BYTE COUNT & ADDRESS 8$: ADD #2,S.BTCT(R2) ; INCREMENT FILE 2 BYTE COUNT CMP S.BTCT(R2),S.MAXB(R2) ; FINISHED WITH THIS RECORD? BLT 9$ ; NO - SO CONTINUE CALL BTCBA2 ; NEW BYTE CT. AND ADD. FILE 2 9$: TST S.EOF(R1) ; FILE 1 AT EOF? BEQ 10$ ; NOPE TST S.EOF(R2) ; FILE 2 AT EOF? 10$: BEQ COMPAR ; LOOP FOR NEXT DATA WORD JMP DONE ; BOTH AT EOF AND NO ERRORS ; ; ERREOF: MOV #ERR5,R5 ; CALL OUT ; OUTPUT TO OUTPUT FILE RETURN ; DONE: TST ERROR ; ANY ERRORS DURING COMPARE? BNE 1$ ; YES - CHECK FOR POST-PROCESS MOV #NOERR,R5 ; MESSAGE CALL OUT ; OUTPUT MESSAGE BR 2$ ; NO ERRORS SO NO NEED FOR PP 1$: BIT #20,FLAG ; IS POST-PROCESSING REQUIRED? BEQ 2$ ; NO - SO SKIP IT CALL POSTPR ; DO POST-PROCESSING 2$: MOV #DONE1,R5 ; CALL OUT ; OUTPUT TO OUTPUT FILE BIT #2,FLAG ; TEST IF SPOOL IS REQUESTED BEQ 3$ ; NO - SO GO ON MOV #LSTFDB,R0 ; SET UP TO PRINT OUTPUT FILE CALL .PRINT ; SPOOL IT 3$: JMP RESTRT ; SEE IF THERE'S MORE TO DO .PAGE .SBTTL MAIN PROGRAM SUBROUTINES ; ; .PSECT DATA ; MATCH5: .WORD 0 ; NUMBER OF MATCHES AFTER ERROR LIMIT1: .WORD 0 ; OUT1 LIMIT LIMIT2: .WORD 0 ; OUT2 LIMIT LIMIT3: .WORD 0 ; OUT3 LIMIT ; ; ; THE "READ" SUBROUTINE WILL READ A BLOCK OF THE FILE REFERENCED ; BY REGISTER 5 ; ; WHEN NOT IN AN ERROR CONDITION, THE INPUT BUFFER WILL ALWAYS ; BE BUFFER A ; ; WHEN IN AN ERROR CONDITION (SEARCHING FOR A MATCH OR OUTPUTING ; ERRORS) IT WILL READ INTO BUFFER B ; ; ALSO, WHEN IN AN ERROR CONDITION, THE VIRTUAL BLOCK NUMBER (F.BKVB) ; WILL BE DECREMENTED BY ONE EACH TIME A BLOCK IS READ. THIS WILL KEEP ; THE VIRTUAL BLOCK NUMBER THE SAME SO THAT THE SAME BLOCK WILL BE READ ; AS LONG AS THE ERROR CONDITION EXISTS ; ; .PSECT CODE READ: TST S.BFSW(R5) ; WHICH BUFFER SHALL WE FILL BNE 1$ ; FILL BUFFER B MOV S.BUFA(R5),S.INBF(R5) ; SETUP TO FILL BUFFER A MOV S.ENDA(R5),S.BEND(R5) ; STORE END OF BUFFER A BR 2$ ; SKIP OVER BUFF B STUFF 1$: MOV S.BUFB(R5),S.INBF(R5) ; SETUP TO FILL BUFFER B MOV S.ENDB(R5),S.BEND(R5) ; STORE END OF BUFFER B 2$: READ$ S.FDBP(R5),S.INBF(R5),#512. ; READ IN 1 BLOCK OF DATA BCS 4$ ; CHECK THE ERROR WAIT$ S.FDBP(R5) ; WAIT TILL READ IS FINISHED BCS 4$ ; CHECK THE ERROR TST ERRCND ; ARE WE IN ERROR CONDITION? BEQ 3$ ; NO - SO CONTINUE MOV S.FDBP(R5),R5 ; SET UP TO ACCESS PROPER FDB DEC F.BKVB+2(R5) ; DEC. VIRTUAL BLK. NUMBER ; SO THAT THE SAME BLOCK WILL ; BE READ NEXT TIME AROUND. 3$: RETURN ; ALL DONE 4$: CMPB F.ERR(R0),#IE.EOF ; CHECK IF END OF FILE BNE 5$ ; NO - PRINT I/O ERROR MOV #ERR7,R5 ; BR 6$ ; CALL OUTPUT 5$: MOV #ERR8,R5 ; 6$: CALL OUTTI ; OUTPUT TO TI: JMP RESTRT ; ; ; ; ; ; THE RECORDS OF A LOAD MODULE ARE ARRANGED AS FOLLOWS: ; FIRST WORD = LENGTH OF RECORD IN BYTES ; SECOND WORD = BASE ADDRESS OF RECORD ; FOLLOWING BYTES = DATA TO BE STORED ; ; THE "BYTE COUNT AND BASE ADDRESS" SUBROUTINE PERFORMES THE FOLLOWING: ; 1. GETS AND STORES THE LENGTH OF THE RECORD IN BYTES ; 2. CHECKS IF RECORD CONTAINS AN ODD NUMBER OF BYTES ; 3. ZEROS THE "LEFT OVER" BYTE IF RECORD LENGTH IS ODD, THIS ; PREVENTS AN ERRONEOUS ERROR INDICATION IF THE UNUSED ; BYTES HAPPEN TO BE DIFFERENT. ; 4. CHECKS TO SEE IF THE END OF BLOCK (SAME AS END OF BUFFER) ; HAS BEEN REACHED, IF SO A NEW BLOCK WILL BE READ IN ; 5. CHECKS FOR A TRANSFER ADDRESS (A RECORD WITH A BYTE COUNT ; OF 2). A TRANSFER ADDRESS INDICATES EITHER THE END OF FILE ; OR THE END OF ONE OF SEVERAL LOAD MODULES WHICH HAVE BEEN ; CONCATENATED TOGETHER. WITH A BYTE COUNT OF 2, IT CHECKS ; FOR END OF FILE, IF NOT END OF FILE IT SKIPS THE NEXT ; RECORD (THE HEADER FOR THE NEXT LOAD MODULE). THE HEADER ; MUST BE SKIPPED BECAUSE DIFFERENT CREATION DATES AND TIMES ; WILL GIVE EXTRANEOUS ERROR INDICATIONS. ; 6. GET AND STORE THE BASE ADDRESS ; 7. RESET THE BYTE COUNTER (S.BTCT) ; ; BTCBA1: MOV (R3)+,S.MAXB(R1) ; STORE RECORD BYTE COUNT BIT #1,S.MAXB(R1) ; ODD BYTE COUNT? BEQ 1$ ; NO - SO CONTINUE MOV S.MAXB(R1),R5 ; USE R5 FOR INDEX ADD R3,R5 ; ADD IN BUFFER POINTER CLRB (R5) ; CLEAR UNUSED BYTE 1$: CALL ENDBF1 ; CHECK IF END OF BUFFER CMP #2,S.MAXB(R1) ; IS RECORD ONLY 2 BYTES LONG BNE 3$ ; NO - SO CONTINUE TST (R3)+ ; SKIP OVER TRANSFER ADDRESS MOV R3,R5 ; USE R5 FOR CALCULATIONS SUB S.INBF(R1),R5 ; FIND WHERE WE ARE IN BLK. CMP R5,S.FFBT(R1) ; ARE WE AT FIRST FREE BYTE? BEQ 4$ ; YES - SET S.EOF AND RETURN CALL ENDBF1 ; END OF BUF? MOV (R3)+,S.MAXB(R1) ; STORE LENGTH OF LOAD HEADER CALL ENDBF1 ; END OF BUFFER? 2$: TSTB (R3)+ ; THIS WILL STEP PAST THE CALL ENDBF1 ; LOAD MODULE HEADER DEC S.MAXB(R1) ; CK. IF END OF MODULE HEAD. BNE 2$ ; NOT YET, SO LOOP BR BTCBA1 ; START OVER AGAIN 3$: MOV (R3)+,S.BAAD(R1) ; STORE RECORD BASE ADDRESS MOV S.BAAD(R1),S.VIRT(R1) ; STORE NEW VIRTUAL ADDRESS CALL ENDBF1 ; END OF BUFFER? CALL MEMAN1 ; DO MEMORY MANAGEMENT SUBR. MOV #2,S.BTCT(R1) ; STEP THE BYTE COUNT TO DATA BR 5$ ; RETURN 4$: INC S.EOF(R1) ; SET FILE 1 EOF 5$: RETURN ; GO BACK ; ; BTCBA2: MOV (R4)+,S.MAXB(R2) ; STORE RECORD BYTE COUNT BIT #1,S.MAXB(R2) ; ODD BYTE COUNT? BEQ 1$ ; NO - SO CONTINUE MOV S.MAXB(R2),R5 ; USE R5 FOR INDEX ADD R4,R5 ; ADD IN THE BUFFER POINTER CLRB (R5) ; CLEAR UNUSED BYTE 1$: CALL ENDBF2 ; CHECK IF END OF BUFFER CMP #2,S.MAXB(R2) ; RECORD ONLY 2 BYTES LONG? BNE 3$ ; NO - SO CONTINUE TST (R4)+ ; SKIP OVER TRANSFER ADDRESS MOV R4,R5 ; USE R5 FOR CALCULATIONS SUB S.INBF(R2),R5 ; FIND WHERE WE ARE IN BLK. CMP R5,S.FFBT(R2) ; ARE WE AT FIRST FREE BYTE? BEQ 4$ ; YES - SET S.EOF AND RETURN CALL ENDBF2 ; END OF BUFFER? MOV (R4)+,S.MAXB(R2) ; STORE LENGTH OF LOAD HEADER CALL ENDBF2 ; END OF BUFFER? 2$: TSTB (R4)+ ; THIS WILL STEP PAST THE CALL ENDBF2 ; LOAD MODULE HEADER DEC S.MAXB(R2) ; CK. IF END OF MODULE HEADER BNE 2$ ; NOT YET, SO LOOP BR BTCBA2 ; START OVER WITH NEXT RECORD 3$: MOV (R4)+,S.BAAD(R2) ; STORE RECORD BASE COUNT MOV S.BAAD(R2),S.VIRT(R2) ; STORE NEW VIRTUAL ADDRESS CALL ENDBF2 ; END OF BUFFER? CALL MEMAN2 ; DO MEMORY MANAGEMENT SUBR. MOV #2,S.BTCT(R2) ; STEP THE BYTE CT TO DATA BR 5$ ; RETURN 4$: INC S.EOF(R2) ; SET FILE EOF FLAG 5$: RETURN ; GO BACK ; ; ; ; ; ; THE "END BUFFER" SUBROUTINE IS USED TO DETERMINE IF A NEW BLOCK ; OF DATA MUST BE READ INTO MEMORY. IF THE BUFFER POINTER IS AT THE ; END OF THE BUFFER, THE "READ" SUBROUTINE IS CALLED. (THE BUFFER ; LENGTH IS EQUAL TO ONE FILE BLOCK) ; ; IF THE PROGRAM IS NOT SEARCHING FOR A MATCH, (NOT IN AN ERROR CON- ; DITION) THE BUFFER POINTER WILL BE RESET TO THE BEGINING OF THE ; BUFFER INTO WHICH THE BLOCK WAS READ (BUFFER A) ; ; IF THE PROGRAM IS IN AN ERROR CONDITION THE NEW BLOCK WILL BE READ ; INTO BUFFER B AND THE BUFFER POINTER WILL ALREADY BE AT THE BEGINING ; OF BUFFER B SINCE BUFFER A AND BUFFER B ARE CONTIGUOUS ; ; ENDBF1: CMP R3,S.BEND(R1) ; SEE IF WE'RE AT END OF BUF BNE 1$ ; NO - SO RETURN MOV #FILE1,R5 ; SET UP TO READ FILE 1 CALL READ ; READ IN NEW BLOCK TST ERRCND ; ARE WE IN ERROR CONDITION? BNE 1$ ; YES - BUFFER POINTER OK MOV S.BUFA(R5),R3 ; RESET THE BUFFER POINTER 1$: RETURN ; GO BACK ; ; ENDBF2: CMP R4,S.BEND(R2) ; CHECK IF AT END OF BUFFER BNE 1$ ; NO - SO GO AWAY MOV #FILE2,R5 ; SET UP TO READ FILE 2 CALL READ ; READ IN THE NEW BLOCK TST ERRCND ; IN ERROR CONDITION? BNE 1$ ; YES - BUFFER POINTER OK MOV S.BUFA(R5),R4 ; RESET THE BUFFER POINTER 1$: RETURN ; GO BACK ; ; ; ; ; ; THE "MEMORY MANAGEMENT" SUBROUTINE TAKES THE PLACE OF THE MEMORY ; MANAGEMENT HARDWARE IN THE 11/55 COMPUTER. AN UNDERSTANDING OF ; THE PDP MEMORY MANAGEMENT SYSTEM WILL BE HELPFUL IN DECIPHERING ; THE FOLLOWING SUBROUTINE. ; ; THE NEW AND CURRENT (S.NEW0 & S.MMR0) MEMORY MANAGEMENT ON/OFF FLAGS ; ARE NECESSARY BECAUSE IF THERE IS AN ERROR PRINTOUT OF THAT LOCATION ; (177572 OR 777572) THE MEMORY MANAGEMENT ON/OFF CANNOT BE CHANGED ; UNTIL AFTER THE PRINTOUT. IF IT IS CHANGED BEFORE THE PRINTOUT THE ; PHYSICAL ADDRESS WILL BE INCORRECT. ; ; THE DATA MANIPULATION (BIT SHIFTS AND WORD STORAGE) WILL BE UNDER- ; STOOD BEST BY THOSE FAMILIAR WITH MEMORY MANAGEMENT. BASICALLY, ; THIS SUBROUTINE CHECKS THE VIRTUAL ADDRESSES TO SEE IF THEY ARE ; MEMORY MAMAGEMENT HARDWARE ADDRESSES, AND IF THEY ARE, STORES THE ; DATA IN THE FILE PARAMETER BUFFER. THE MEMORY MANAGEMENT INFOR- ; MATION THUS OBTAINED IS USED TO FORM A PHYSICAL ADDRESS FROM A ; VIRTUAL ADDRESS WHEN AN ERROR IS PRINTED. ; ; THE READ 16 BYTES AT THE END OF THE SUBROUTINE IS NECESSARY TO ; OBVIATE THE PROBLEM OF THE MEMORY MANAGEMENT INFORMATION BEING ; CONTAINED IN TWO SEPARATE BLOCKS. A WHOLE NEW BLOCK CANNOT BE READ ; IN BECAUSE THAT WOULD DESTROY FILE INFORMATION NOT YET COMPARED. ; ; THIS SUBROUTINE WILL ONLY CHECK FOR THE "SUPERVISOR INSTRUCTION" PAGE ; ADDRESS REGISTERS. THIS IS SUFFICIENT FOR THE P3C TRAINERS BECAUSE ; THE LOADER ONLY OPERATES IN THAT MODE, AND THE MEMORY MAPS ARE ; WRITTEN TO REFLECT THIS. ; ; MEMAN1: JSR PC,$SAVAL ; SAVE THE REGISTERS BR MEMANG ; BRANCH AROUND FILE 2 SET UP MEMAN2: JSR PC,$SAVAL ; SAVE ALL REGISTERS MOV R2,R1 ; SET UP FOR FILE 2 MOV R4,R3 ; USE FILE 2 POINTER MEMANG: MOV S.BAAD(R1),R4 ; GET BASE ADDRESS MOV S.NEW0(R1),S.MMR0(R1) ; SET MEMORY MANAGEMENT BIT #1,S.MMR0(R1) ; IS MEMORY MANAGEMENT ON? BEQ 1$ ; NO - DON'T CALCULATE S.PAF ASH #-12.,R4 ; SHIFT MM REG SEL BITS TO 1-3 BIC #177761,R4 ; MASK OUT ALL BUT REG SELECT ADD #S.SDR0,R4 ; FORM INDEX FOR CORRECT MM REG ADD R1,R4 ; ADD START OF FILE 1 OR 2 MOV (R4),S.PAF(R1) ; MEMORY MANAGEMENT OFFSET MOV S.BAAD(R1),R4 ; BASE ADDRESS IN R4 ASHC #-6,R4 ; BEGIN TO FORM PHYSICAL ADD. BIC #177600,R4 ; CLEAR UNWANTED BITS ADD S.PAF(R1),R4 ; ADD THE PAGE ADD. FIELD ASHC #-6.,R4 ; 2 MOST SIGNIF. PLACES IN R4 CMP R4,#76 ; IS ADDRESS IN TOP 4K? BLT 5$ ; NO SO DONT CHECK MEM. MANAG. ASHC #12.,R4 ; SHIFT IN ENTIRE ADDRESS 1$: CMP R4,#177572 ; MEMORY MANAGEMENT REG. 0? BNE 2$ ; NO - TRY ANOTHER MOV (R3),S.NEW0(R1) ; YES - STORE DATA BR 5$ ; ALL DONE 2$: CMP R4,#172240 ; SUPER I SPACE ADDRESS REG. 0? BLT 5$ ; NO - SO RETURN CMP R4,#172256 ; SUPER I SPACE ADDRESS REG. 8? BGT 5$ ; NO - SO RETURN SUB #172240,R4 ; GET OFFSET FROM 172240 ADD #S.SDR0,R4 ; FORM INDEX FOR STORAGE ADD R1,R4 ; ADD START OF FILE 1 OR 2 MOV R1,R2 ; START OF FILE DATA BUFFER ADD #S.SDR0+20,R2 ; CALC. END OF PAF STORAGE MOV S.MAXB(R1),R0 ; GET BYTE COUNT SUB #2,R0 ; DON'T COUNT BASE ADDRESS 3$: MOVB (R3)+,(R4)+ ; STORE ADDRESS OFFSETS CMP R3,S.BEND(R1) ; AT END OF BUFFER? BNE 4$ ; NO - SO CONTINUE READ$ S.FDBP(R1),#MEMBUF,#16. ; READ REST OF MEM MAN INFO. BCS 6$ ; OUTPUT ERROR MESSAGE WAIT$ S.FDBP(R1) ; WAIT FOR READ TO FINISH BCS 6$ ; OUT PUT ERROR MESSAGE MOV S.FDBP(R1),R5 ; GET POINTER TO FILE FDB DEC F.BKVB+2(R5) ; SET BACK VIRTUAL BLK. NUM. MOV #MEMBUF,R3 ; POINT R3 TO NEW DATA 4$: CMP R4,R2 ; HAVE WE GOT ALL WE WANT? BGE 5$ ; YES - SO GO ON SOB R0,3$ ; LOOP TILL DONE 5$: RETURN 6$: MOV #ERR8,R5 ; JMP RESTRT ; START OVER AGAIN ; ; ; ; ; ; THE "STORIT" SUBROUTINE STORES THE FILE PARAMETERS IN EFFECT WHEN ; AN ERROR IS FOUND. THE POINTER TO EITHER FILE 1 OR FILE 2 PARAMETERS ; BUFFER WILL BE IN R5 AT ENTRY. ; ; STORIT: MOV S.BTCT(R5),S.ERCT(R5) ; STORE CURRENT BYTE COUNT MOV S.MAXB(R5),S.ERXB(R5) ; STORE CURRENT BYTE COUNT MOV S.BAAD(R5),S.ERAD(R5) ; STORE CURRENT BASE ADD. MOV S.MMR0(R5),S.ERM0(R5) ; STORE MEM. MANAG. R0 MOV S.NEW0(R5),S.EEW0(R5) ; STORE NEW MEM. MANAG. R0 MOV S.PAF(R5),S.ERAF(R5) ; STORE CURRENT PAGE ADD. FIELD MOV #8.,R0 ; SET UP INDEX OF 8 1$: MOV S.SDR0(R5),S.ERR0(R5) ; STORE CURRENT ADDRESS REGS TST (R5)+ ; INCREMENT R5 SOB R0,1$ ; LOOP TILL ALL 8 ARE DONE RETURN ; GO BACK ; ; ; ; ; ; THE "GETIT" SUBROUTINE IS USED TO GO BACK TO WHERE THE ORIGINAL ERROR ; OCCURED. THIS ROUTINE RETRIEVES THE DATA STORED BY THE "STORIT" ; SUBROUTINE. ; ; GETIT: MOV S.ERCT(R5),S.BTCT(R5) ; RESTORE BYTE COUNT MOV S.ERXB(R5),S.MAXB(R5) ; RESTORE MAX BYTE COUNT MOV S.ERAD(R5),S.BAAD(R5) ; RESTORE BASE ADDRESS MOV S.ERM0(R5),S.MMR0(R5) ; RESTORE MEM. MANAG. R0 MOV S.EEW0(R5),S.NEW0(R5) ; RESTORE NEW MEM. MANAG. R0 MOV S.ERAF(R5),S.PAF(R5) ; RESTORE PAGE ADD. FIELD MOV #8.,R0 ; SET UP LOOP COUNT 1$: MOV S.ERR0(R5),S.SDR0(R5) ; RESTORE THE ADDRESS REGS. TST (R5)+ ; INCREMAENT R5 SOB R0,1$ ; LOOP TILL DONE RETURN ; GO BACK ; ; ; ; ; ; THE "MATCIT" SUBROUTINE STORES THE FILE PARAMETERS IN EFFECT WHEN ; A MATCH IS FOUND. THE POINTER TO EITHER FILE 1 OR FILE 2 PARAMETERS ; BUFFER WILL BE IN R5 AT ENTRY. ; ; MATCIT: MOV S.BTCT(R5),S.MACT(R5) ; STORE BYTE COUNT AT MATCH MOV S.MAXB(R5),S.MXBM(R5) ; STORE MAX BYTE AT MATCH MOV S.BAAD(R5),S.MAAD(R5) ; STORE BASE ADDRESS AT MATCH MOV S.MMR0(R5),S.MAM0(R5) ; STORE MEM. MANAG. R0 MOV S.NEW0(R5),S.MEW0(R5) ; STORE NEW MEM.MANAG. R0 MOV S.PAF(R5),S.MAAF(R5) ; STORE CURRENT PAGE ADD FIELD MOV #8.,R0 ; SET UP LOOP COUNT 1$: MOV S.SDR0(R5),S.MAR0(R5) ; STORE ADDRESS REGISTERS TST (R5)+ ; INCREMENT R5 SOB R0,1$ ; LOOP TILL DONE RETURN ; GO BACK ; ; ; ; ; ; THE "MATCNO" SUBROUTINE IS USED TO GO BACK TO WHERE THE ORIGINAL MATCH ; OCCURED. THIS ROUTINE RETRIEVES THE DATA STORED BY THE "MATCIT", AND ; IS USED WHEN ANOTHER ERROR IS FOUND WITHIN 5 LOCATIONS OF A MATCH. ; ; MATCNO: MOV S.MACT(R5),S.BTCT(R5) ; RESTORE BYTE COUNT MOV S.MXBM(R5),S.MAXB(R5) ; RESTORE MAX BYTE MOV S.MAAD(R5),S.BAAD(R5) ; RESTORE BASE ADDRESS MOV S.MAM0(R5),S.MMR0(R5) ; RESTORE MEM. MANAG. R0 MOV S.MEW0(R5),S.NEW0(R5) ; RESTORE NEW MEM. MANAG. R0 MOV S.MAAF(R5),S.PAF(R5) ; RESTORE PAGE ADDRESS FIELD MOV #8.,R0 ; SET UP LOOP COUNT 1$: MOV S.MAR0(R5),S.SDR0(R5) ; RESTORE ADDRESS REGISTERS TST (R5)+ ; INCREMENT R5 SOB R0,1$ ; LOOP TILL DONE RETURN ; GO BACK ; ; ; ; ; ; THE "FINDIT" SUBROUTINE IS USED TO TRY TO MATCH UP THE TWO FILES ; AFTER AN ERROR IS ENCOUNTERED. STARTING FROM THE LOCATION WHERE THE ; MISMATCH OCCURED, THE FIRST ERROR LOCATION OF FILE 1 IS COMPARED TO ; EACH LOCATION OF FILE 2 UNTIL THE END OF BUFFER A OR END OF FILE 2 IS ; REACHED. WHEN FILE 2 REACHES THE END OF BUFFER A ANOTHER BLOCK OF DATA ; FROM FILE 2 IS READ INTO BUFFER B AND THE FIRST ERROR LOCATION OF FILE ; 1 IS COMPARED TO EVERY LOCATION IN FILE 2'S BUFFER B. IF NO MATCH HAS ; BEEN FOUND BEFORE THE END OF BUFFER B (OR EOF) FILE 2 IS RESET BACK TO ; WHERE THE FIRST ERROR OCCURED (GETIT) AND FILE 1 IS ADVANCED ONE ; LOCATION. THIS NEW LOCATION IS COMPARED TO FILE 2 (BUFFER A AND B) AND ; IF NO MATCH IS FOUND FILE 1 IS ADVANCED AGAIN. THIS CONTINUES UNTIL ; FILE 1 REACHES THE END OF BUFFER A, AT WHICH TIME ANOTHER BLOCK OF ; FILE 1 IS READ INTO BUFFER B. IF NO MATCH IS FOUND BY THE TIME FILE 1 ; REACHES THE END OF BUFFER B (OR EOF) THE PROGRAM GIVES UP. AT THIS ; TIME FOUR EXITS ARE PROVIDED DEPENDING ON WHICH FILE IS AT EOF, OR IF ; BOTH OR NONE ARE AT EOF. ; ; IF "FINDIT" FINDS A MATCH BETWEEN FILE 1 AND 2 BOTH FILES ARE STEPPED ; TO THE NEXT LOCATION AND THEY ARE COMPARED. IF 5 CONSECUTIVE LOCATIONS ; MATCH, THIS SUBROUTINE EXITS TO "FOUND". IF AN ERROR IS ENCOUNTERED ; BEFORE THE 5TH MATCH, THEN BOTH FILES ARE RESET (MATCNO), FILE 2 IS ; ADVANCED ONE LOCATION, AND THE SEARCH IS ON AGAIN. ; ; FINDIT: TST (R4)+ ; ADVANCE R4 CMP R4,S.ENDB(R2) ; AND CK. END BUF B BGE 2$ ; YES - SO ADVANCE R3 CALL ENDBF2 ; CK. IF END BUF A ADD #2,S.BTCT(R2) ; ADVANCE BYTE COUNT CMP S.BTCT(R2),S.MAXB(R2) ; AT END OF RECORD? BLT 1$ ; NO - SO CONTINUE CALL BTCBA2 ; GET NEW BYTE COUNT AND ADD. TST S.EOF(R2) ; AT END OF FILE? BNE 2$ ; YES - SO ADVANCE FILE 1 1$: TST MATCH5 ; IN A MATCH SEQUENCE? BEQ 7$ ; NO - GO COMPARE DATA 2$: TST (R3)+ ; ADVANCE R3 CMP R3,S.ENDB(R1) ; & CK. IF END OF BUF B BLT 4$ ; NO - SO CONTINUE TST S.EOF(R2) ; IS FILE 2 AT EOF? BNE 3$ ; YES - FILE IS AT EOF JMP NOEOF ; NO - NO MATCH, NO EOF 3$: JMP EOFF2 ; LIMIT FILE 1 OUTPUT 4$: CALL ENDBF1 ; CHECK FOR END OF BUFFER A ADD #2,S.BTCT(R1) ; ADVANCE BYTE COUNT CMP S.BTCT(R1),S.MAXB(R1) ; AT END OF RECORD? BLT 6$ ; RESET FILE 2 & COMPARE AGAIN CALL BTCBA1 ; GET NEW BYTE CT. & BASE ADD. TST S.EOF(R1) ; AT END OF FILE? BEQ 6$ ; NO - SO GO ON TST S.EOF(R2) ; DID FILE 2 GET TO EOF? BNE 5$ ; YES - BOTH AT EOF, DO F12EOF JMP EOFF1 ; NO, JUST FILE 1, LIMIT FILE 2 5$: JMP F12EOF ; PRINT OUT REST OF FILES 6$: TST MATCH5 ; ARE WE IN MATCH SEQUENCE? BNE 7$ ; YES - SEE IF WE CAN GET 5 MOV #FILE2,R5 ; NO - SO MOVE FILE 2 BACK CALL GETIT ; GO BACK TO ERROR MOV S.ERLO(R2),R4 ; MOVE BUFFER POINTER BACK CLR S.EOF(R2) ; FILE 2 NO LONGER AT EOF 7$: CMP (R3),(R4) ; COMPARE DATA BEQ 10$ ; DO THE MATCH5 STUFF BIT #4,FLAG ; ANY OFFSETS ENTERED? BEQ 9$ ; NO - SKIP OFFSET CALCULATIONS MOV #5,R5 ; SET UP LOOP COUNT MOV #O1,R0 ; POINTER TO FIRST OFFSET 8$: MOV (R4),S.DATA(R2) ; STORE DATA FILE 2 ADD (R0),S.DATA(R2) ; ADD OFFSET FILE 2 CMP (R3),S.DATA(R2) ; CMP DATA INCLUDING OFFSET BEQ 10$ ; THIS COMPARES SO GO ON MOV (R4),S.DATA(R2) ; STORE DATA FILE 2 SUB (R0)+,S.DATA(R2) ; SUB OFFSET FILE 2 AND BUMP CMP (R3),S.DATA(R2) ; CMP DATA INCLUDING OFFSET BEQ 10$ ; THIS COMPARES SO GO ON SOB R5,8$ ; LOOP TO DO ALL OFFSETS 9$: TST MATCH5 ; ARE WE IN A MATCH SEQUENCE? BEQ FINDIT ; NO - SO GO BACK TO BEGINING MOV #FILE1,R5 ; SET UP FOR FILE 1 CALL MATCNO ; RESTORE THE POSITION MOV S.MALO(R1),R3 ; RESTORE BUFFER POSITION CLR MATCH5 ; SET NUMBER OF MATCHES TO 0 BR FINDIT ; LOOP TO TRY AGAIN 10$: TST MATCH5 ; ARE WE IN A MATCH SEQUENCE? BNE 11$ ; YES - SO DON'T STORE AGAIN MOV #FILE1,R5 ; STORE FILE 1 CALL MATCIT ; STORE POSITION AT MATCH MOV #FILE2,R5 ; SET UP FOR FILE 2 CALL MATCIT ; STORE FILE 2 DATA MOV R3,S.MALO(R1) ; STORE BUFFER LOC AT MATCH MOV R4,S.MALO(R2) ; SAME FOR FILE 2 11$: INC MATCH5 ; BUMP THE NUMBER OF MATCHES CMP #5,MATCH5 ; DO WE HAVE 5 MATCHES? BEQ FOUND ; YES - OUTPUT ERRORS & RETURN BR FINDIT ; LOOP TILL WE GET FIVE ; ; ; ; ; ; THE FOLLOWING SUBROUTINES ARE USED TO LIMIT THE NUMBER OF ERRORS ; THAT WILL BE PRINTED WHEN THE FILES CANNOT BE MATCHED. THE ; LIMITS ARE AS FOLLOWS: ; ; FILE AT EOF - PRINT TO THE END OF FILE ; FILE NOT AT EOF - LIMIT THE OUTPUT TO 10 LOCATIONS ; ; THE PARAMETER S.MALO (LOCATION WHERE FILES MATCHED) IS USED BY THE ; OUTPUT ROUTINES TO STOP THE OUTPUT. ; ; EOFF1: MOV #10.,LIMIT2 ; LIMIT OUTPUT OF FILE 2 TO 10 MOV #512.,S.FFBT(R2) ; GET FILE 2 EOF OUT OF THE WAY BR F12EOF ; CONTINUE ON EOFF2: MOV #10.,LIMIT1 ; LIMIT OUTPUT FILE 1 TO 10 MOV #512.,S.FFBT(R1) ; GET FILE 1 EOF OUT OF THE WAY F12EOF: MOV S.FFBT(R1),R5 ; USE R5 FOR ADDITION ADD S.INBF(R1),R5 ; POINTER END OF DATA FILE 1 MOV R5,S.MALO(R1) ; LIMIT OUTPUT TO END OF FILE MOV S.FFBT(R2),R5 ; USE R5 FOR ADDITION ADD S.INBF(R2),R5 ; POINTER END OF DATA FILE 2 MOV R5,S.MALO(R2) ; LIMIT OUTPUT TO END OF FILE BR CALLO3 ; GO CALL OUTPUT NOEOF: MOV #10.,LIMIT3 ; SET BOTH FILES OUTPUT LIMIT MOV S.BUFB(R1),S.MALO(R1) ; SET MATCH LOC. TO MAX MOV S.BUFB(R2),S.MALO(R2) ; SAME FOR FILE 2 CALLO3: CALL OUT3 ; GO DO THE OUTPUT JMP DONE ; FINISHED ; ; ; ; ; ; THE "FOUND" ROUTINE IS USED TO DETERMINE WHICH OF THE THREE OUTPUT ; ROUTINES SHOULD BE USED. S.ERLO IS THE LOCATION OF THE ERROR, AND ; S.MALO IS THE LOCATION OF THE MATCH, THUS A DIFFERENCE BETWEEN ; THE TWO INDICATES ERRORS WHICH MUST BE PRINTED. ; ; FOUND: CMP S.ERLO(R1),S.MALO(R1) ; ANY MISMATCHES IN FILE 1? BNE 1$ ; YES - CHECK FILE 2 CALL OUT2 ; NO - SO OUTPUT JUST FILE 2 BR 3$ ; GOBACK TO MAIN COMPARE 1$: CMP S.ERLO(R2),S.MALO(R2) ; ANY BAD ONES IN FILE 2? BNE 2$ ; YES - OUTPUT BOTH FILES 1 & 2 CALL OUT1 ; NO - OUTPUT JUST FILE 1 BR 3$ ; GO TO GOBACK 2$: CALL OUT3 ; OUTPUT FILES 1 & 2 3$: JMP GOBACK ; SET UP FOR RETURN TO MAIN LOOP ; ; ; ; ; THE "GOBACK" ROUTINE RESETS THE FILE PARAMETERS TO GO BACK TO THE ; MAIN COMPARE PROGRAM LOOP. IF THE MATCH OCCURRED IN BUFFER B, THE ; SAME BLOCK THAT WAS READ INTO BUFFER B WILL BE READ INTO BUFFER A ; AND THE BUFFER POINTER RESET BACK TO BUFFER A. THE MAIN COMPARE LOOP ; MUST OPERATE IN BUFFER A BECAUSE, IN THE EVENT OF ANOTHER ERROR, ; BUFFER B MUST BE FREE FOR THE "FINDIT" ROUTINE. ; ; GOBACK: MOV #FILE1,R5 ; SET UP FOR FILE 1 CALL MATCNO ; GO BACK TO MATCH LOCATION MOV #FILE2,R5 ; SET UP FOR FILE 2 CALL MATCNO ; SET FILE 2 PARAMETERS MOV S.MALO(R1),R3 ; SET FILE 1 BUFFER POINTER MOV S.MALO(R2),R4 ; SET FILE 2 BUFFER POINTER CALL F1VIRT ; GET CURRENT VIRTUAL ADDRESS CALL F2VIRT ; SAME FOR FILE 2 CLR MATCH5 ; CLEAR MATCH CONDITION CLR ERRCND ; CLEAR ERROR CONDITION MOV S.ENDA(R1),S.BEND(R1) ; RESET END OF BUFFER FILE 1 MOV S.ENDA(R2),S.BEND(R2) ; RESET END OF BUFFER FILE 2 CLR S.BFSW(R1) ; FILE 1 TO READ INTO BUFF A CLR S.BFSW(R2) ; FILE 2 TO READ INTO BUFF A CMP R3,S.BUFB(R1) ; CHECK IF IN BUF A OR B BLT 1$ ; IN BUF A, SO NO PROBLEM MOV #FILE1,R5 ; SET UP FOR READ CALL READ ; READ SAME BLOCK INTO BUF A SUB #512.,R3 ; MOVE POINTER DOWN TO BUF A 1$: CMP R4,S.BUFB(R2) ; CHECK FILE 2 BUF A OR BUF B BLT 2$ ; BUFFER A SO GO AWAY MOV #FILE2,R5 ; SET UP FOR FILE 2 CALL READ ; READ BLOCK INTO BUFFER A SUB #512.,R4 ; RESET THE BUFFER POINTER 2$: JMP COMPAR ; GO BACK TO MAIN COMPARE LOOP ; ; ; ; ; ; THE "F1VIRT" AND "F2VIRT" SUBROUTINES ARE USED TO DETERMINE THE ; FILES VIRTUAL ADDRESS. SINCE THE CURRENT BYTE COUNT (S.BTCT) ; INCLUDES THE BASE ADDRESS, THOSE TWO BYTES MUST BE SUBTRACTED. ; IF HONEYWELL ADDRESSING IS SELECTED, THE BYTE COUNT MUST BE DIVIDED ; BY TWO (BYTE ADDRESSING VS. WORD ADDRESSING). ; ; F1VIRT: MOV S.BTCT(R1),S.VIRT(R1) ; GET CURRENT BYTE COUNT SUB #2,S.VIRT(R1) ; SUB. 2 FOR BASE ADDRESS BIT #1,FLAG ; HONEYWELL ADDRESSING? BEQ 1$ ; NO - SO CONTINUE ASR S.VIRT(R1) ; YES - DIVIDE BY TWO 1$: ADD S.BAAD(R1),S.VIRT(R1) ; FILE 1 VIRTUAL ADDRESS RETURN ; GO BACK ; ; ; F2VIRT: MOV S.BTCT(R2),S.VIRT(R2) ; GET CURRENT BYTE COUNT SUB #2,S.VIRT(R2) ; SUB. 2 FOR BASE ADDRESS BIT #1,FLAG ; HONEYWELL ADDRESSING? BEQ 1$ ; NO - SO CONTINUE ASR S.VIRT(R2) ; YES - DIVIDE BY TWO 1$: ADD S.BAAD(R2),S.VIRT(R2) ; FILE 2 VIRTUAL ADDRESS RETURN ; GO BACK .PAGE .SBTTL OUTPUT ROUTINES ; ; .PSECT DATA ; ARG: .BLKW 6 ; ARGUMENT STORAGE FOR $EDMSG ASCII: .BLKW 6 ; ASCII CHARACTERS FOR $EDMSG OUTBLK: .BLKW 50. ; OUTPUT BLOCK FOR $EDMSG PASS2: .WORD 0 ; ONE OR TWO PASSES THRU ADRES1 ; ; ; ; EDIT MESSAGE ($EDMSG) INPUT STRINGS FOR ERROR AND ADVISORY MESSAGES ; AND MISMATCH PRINTOUTS. SEE THE RSX-11 SYSTEM LIBRARY ROUTINES ; REFERENCE MANUAL FOR INFORMATION CONCERNING EDIT MESSAGE ($EDMSG) ; INPUT STRING FORMAT. ; .NLIST BIN ; F01: .ASCIZ /%N FILE 1 %6A - %P/ F02: .ASCIZ /%N FILE 2 %6A - %P/ F03: .ASCIZ /%N FILE 1 %6A - %P FILE 2 %6A - %P %O/ F04: .ASCIZ /%N FILE 1 %2R - %P/ F05: .ASCIZ /%N FILE 2 %2R - %P/ F06: .ASCIZ /%N FILE 1 %2R - %P FILE 2 %2R - %P/ F07: .ASCIZ /%N****** FILE 1 AT ADDRESS - %6A FILE 2 AT ADDRESS - %6A/ ERR1: .ASCIZ /CLM -- COMMAND LINE SYNTAX ERROR/ ERR2: .ASCIZ /CLM -- UNABLE TO OPEN OUTPUT FILE/ ERR3: .ASCIZ /CLM -- UNABLE TO OPEN INPUT FILE 1/ ERR4: .ASCIZ /CLM -- UNABLE TO OPEN INPUT FILE 2/ ERR5: .ASCIZ /%NCLM -- FILE 1 AND FILE 2 ARE DIFFERENT SIZE/ ERR7: .ASCIZ /%NCLM -- TRIED TO READ PAST EOF/ ERR8: .ASCIZ \%NCLM -- INPUT FILE I/O ERROR ON READ\ ERR9: .ASCIZ \%NCLM -- OUTPUT FILE I/O ERROR\ ERR10: .ASCIZ \%NCLM -- I/O ERROR TO TI:\ ERR11: .ASCIZ \%NCLM -- I/O ERROR TO TEMP FILE\ ERR12: .ASCIZ /%NCLM -- UNABLE TO OPEN POST-PROCESSING FILE/ ERR13: .ASCIZ \%NCLM -- POST-PROCESS FILE I/O ERROR\ ASTRI1: .ASCIZ /%N******************************************/ ASTRI2: .ASCIZ /******************************************/ F1EOF: .ASCIZ / FILE 1 AT EOF/ F2EOF: .ASCIZ / FILE 2 AT EOF/ POINT1: .ASCIZ / POINTLESS TO CONTINUE/ POINT2: .ASCIZ / POINTLESS TO CONTINUE/ PLESS2: .ASCIZ / POINTLESS TO CONTINUE POINTLESS TO CONTINUE/ POST: .ASCIZ /CLM -- BEGIN POST-PROCESSING OUTPUT/ POST1: .ASCIZ /%NCLM -- BEGIN POST-PROCESSING "PATIENCE IS A VIRTUE"/ POST2: .ASCIZ /%NCLM -- TOO MANY ERRORS FOR POST-PROCESSING BUFFER,/ POST3: .ASCIZ / PROGRAM WILL OUTPUT MORE THAN ONE ERROR LIST/ DONE1: .ASCIZ /%NCLM -- FINISHED WITH COMPARE/ NOERR: .ASCIZ /%NCLM -- NO DIFFERENCES BETWEEN FILE 1 AND FILE 2/ ; ; ; .LIST BIN .EVEN .PSECT CODE ; ; ; ; ; ; THE "OUT1" ROUTINE IS USED TO OUTPUT LOCATIONS THAT ARE FOUND IN ; FILE 1 BUT NOT IN FILE 2. ; ; OUT1: MOV #FILE1,R5 ; SET UP FOR FILE 1 CALL GETIT ; GET PARAMETERS AT ERROR MOV S.ERLO(R1),R3 ; MOVE BUFFER POINTER BACK CALL F1VIRT ; GET CURRENT VIRTUAL ADDRESS LOOP1: CMP R3,S.MALO(R1) ; AT LOCATION WHERE FILES MATCH? BLT REST1 ; NO - SO CONTINUE OUTPUT TST S.EOF(R1) ; YES - DID WE GET TO EOF? BEQ 1$ ; NO - SO JUST GO MOV #F1EOF,R5 ; OUTPUT MESS. CALL OUT ; SEND IT OUT 1$: RETURN ; GO BACK WHENCE YOU CAME REST1: MOV (R3),ARG+2 ; DATA TO OUTPUT BUFFER CALL ADRES1 ; GET ASCII FOR OUTPUT ADDRESS MOV #F01,R5 ; GET THE $EDMSG INPUT STRING CALL OUT ; OUTPUT THE MISMATCH BIT #20,FLAG ; IS POST-PROCESSING REQUIRED? BEQ 1$ ; NO - SO SKIP PPOUT1 CALL PPOUT1 ; WRITE DATA FOR POST-PROCESS. 1$: TST (R3)+ ; MOVE POINTER TO NEXT WORD TST LIMIT1 ; IS THERE A LIMIT SET? BEQ 2$ ; NO - SO CONTINUE DEC LIMIT1 ; COUNT IT DOWN BNE 2$ ; CONTINUE ON FOR THE REST MOV #POINT1,R5 ; CALL OUT ; SEND IT OUT RETURN ; ALL DONE, SO GO AWAY 2$: BIT #1,FLAG ; USE HONEYWELL ADDRESSING? BNE 3$ ; YES - BUMP ADDRESS ONLY ONCE INC S.VIRT(R1) ; BUMP THE VIRTUAL ADDRESS 3$: INC S.VIRT(R1) ; BUMP THE VIRTUAL ADDRESS ADD #2,S.BTCT(R1) ; INCREMENT THE BYTE COUNT CMP S.BTCT(R1),S.MAXB(R1) ; ARE WE AT END OF THE RECORD? BLT LOOP1 ; NO - SO OUTPUT SOME MORE CALL BTCBA1 ; GET NEW BYTE CT. $ BASE ADD. MOV S.BAAD(R1),S.VIRT(R1) ; MIGHT BE NEW BASE ADD. BR LOOP1 ; OUTPUT SOME MORE ; ; ; ; ; ; THE "OUT2" ROUTINE IS USED TO OUTPUT LOCATIONS THAT ARE FOUND IN ; FILE 2 BUT NOT IN FILE 1. ; ; OUT2: MOV #FILE2,R5 ; SET UP FOR FILE 2 CALL GETIT ; GO BACK TO THE ERROR MOV S.ERLO(R2),R4 ; MOVE POINTER BACK CALL F2VIRT ; GET CURRENT VIRTUAL ADDRESS LOOP2: CMP R4,S.MALO(R2) ; ARE WE DONE WITH OUTPUTS? BLT REST2 ; NO - SO OUTPUT SOME MORE TST S.EOF(R2) ; YES - DID WE GET TO EOF? BEQ 1$ ; NO - SO JUST GO MOV #F2EOF,R5 ; CALL OUT ; SEND IT 1$: RETURN ; MAKE LIKE A TREE AND _____ REST2: MOV (R4),ARG+2 ; MOVE DATA TO OUTPUT BUFFER CALL ADRES2 ; GET THE PHYSICAL ADDRESS MOV #F02,R5 ; GET THE $EDMSG OUTPUT STRING CALL OUT ; OUTPUT THE MISMATCH BIT #20,FLAG ; IS POST-PROCESSING REQUIRED? BEQ 1$ ; NO - SO SKIP PPOUT2 CALL PPOUT2 ; OUTPUT POST PROCESSING DATA 1$: TST (R4)+ ; MOVE POINTER TO NEXT WORD TST LIMIT2 ; IS THERE A LIMIT SET? BEQ 2$ ; NO - SO CONTINUE DEC LIMIT2 ; COUNT IT DOWN BNE 2$ ; CONTINUE ON FOR THE REST MOV #POINT2,R5 ; CALL OUT ; SEND IT OUT RETURN ; ALL DONE, SO GO AWAY 2$: BIT #1,FLAG ; USE HONEYWELL ADDRESSING? BNE 3$ ; YES - INCREMENT ADDRESS BY ONE INC S.VIRT(R2) ; BUMP VIRTUAL ADDRESS BY ONE 3$: INC S.VIRT(R2) ; BUMP VIRTUAL ADDRESS BY ONE ADD #2,S.BTCT(R2) ; INCREMENT THE BYTE COUNT CMP S.BTCT(R2),S.MAXB(R2) ; AT END OF RECORD? BLT LOOP2 ; NO - SO OUTPUT SOME MORE CALL BTCBA2 ; GET NEW BYTE CT. & BASE ADD. MOV S.BAAD(R2),S.VIRT(R2) ; KEEP UP WITH BASE ADDRESS BR LOOP2 ; OUTPUT SOME MORE ; ; ; ; ; ; ; THE "OUT3" ROUTINE IS USED TO OUTPUT LOCATIONS THAT ARE DIFFERENT ; IN FILE 1 AND FILE 2. ; ; BECAUSE OF THE POSSIBILITY THAT THE BASE ADDRESS CAN BE ODD (DUE TO ; BYTE ADDRESSING) THE OUTPUT DATA WILL APPEAR IN TWO CONTIGUOUS BUFFER ; LOCATIONS. THEREFORE PROVISIONS HAVE BEEN MADE TO CHECK FOR AN ODD ; BASE ADDRESS, AND IF IT IS ODD, PACK THE OUTPUT DATA BUFFER WITH THE ; PROPER BYTES TO FORM THE CORRECT OUTPUT WORD. THIS PERTAINS ONLY TO ; 11/55 LOAD MODULES. ; ; THIS ROUTINE CHECKS TO SEE IF THE DATA IS THE SAME BEFORE OUTPUT. IF ; IF THE DATA IS EQUAL IT WILL NOT OUTPUT THOSE ERROR LOCATIONS. ; ; THIS ROUTINE ALSO OUTPUTS THE DIFFERENCE BETWEEN THE DATA FROM FILE 1 ; AND THE DATA FROM FILE 2. THIS FIGURE WILL HELP THE USER DETERMINE ; THE OFFSETS (/O1 THRU /O5) NEEDED TO ELIMINATE EXTRANEOUS ERRORS DUE ; TO RELATIVE ADDRESSING. ; ; OUT3: MOV #FILE1,R5 ; SET UP FOR FILE 1 CALL GETIT ; GO BACK TO ERROR MOV S.ERLO(R1),R3 ; RESET THE BUFFER POINTER MOV #FILE2,R5 ; SET UP FOR FILE 2 CALL GETIT ; GO BACK TO ERROR MOV S.ERLO(R2),R4 ; RESET THE BUFFER POINTER CALL F1VIRT ; GET CURRENT VIRTUAL ADDRESS CALL F2VIRT ; GET CURRENT VIRTUAL ADDRESS 1$: CMP R3,S.MALO(R1) ; DONE WITH FILE 1? BGE 3$ ; YES - CK. DONE WITH FILE 2 CMP R4,S.MALO(R2) ; DONE OUTPUTTING FILE 2 BNE 6$ ; NOT DONE WITH FILES 1 OR 2 TST S.EOF(R2) ; IS FILE 2 AT EOF? BEQ 2$ ; NO - SO CONTINUE MOV #F2EOF,R5 ; MESSAGE CALL OUT ; SEND IT 2$: CALL REST1 ; DONE FILE 2, GO FINISH FILE 1 RETURN ; DONE WITH EVERYTHING 3$: CMP R4,S.MALO(R2) ; CHECK IF FILE 2 ALSO FINISHED BLT 4$ ; NO RETURN ; YES - FINISHED WITH OUTPUT 4$: TST S.EOF(R1) ; FILE 1 AT EOF? BEQ 5$ ; NO - SO CONTINUE MOV #F1EOF,R5 ; MESSAGE CALL OUT ; SEND IT 5$: MOV S.VIRT(R2),ARG ; SET UP VIRTUAL ADD. FOR OUT2 CALL REST2 ; DONE WITH 1, GO FINISH FILE 2 RETURN ; ALL DONE NOW 6$: BIT #1,FLAG ; TEST IF HONEYWELL ADDRESSING BNE 10$ ; YES - SO NO BYTE ADDRESSING BIT #1,S.BAAD(R1) ; TEST IF BASE IS ODD ADDRESS BEQ 10$ ; NO - SO SKIP BYTE PROCESSING CMP S.VIRT(R1),S.BAAD(R1) ; ARE WE AT FIRST DATA BYTE? BNE 7$ ; NO - SO WE MUST DO TWO BYTES CLR ARG+2 ; CLEAR DATA OUTPUT LOCATION MOVB (R3),ARG+2 ; GET THE BYTE SWAB ARG+2 ; MOVE THE BYTE TO ODD ADDRESS BR 8$ ; DO FILE 2 7$: MOVB (R3),ARG+2 ; GET HIGH ORDER BYTE SWAB ARG+2 ; MOVE TO ODD ADDRESS MOVB -(R3),ARG+2 ; GET LOW ORDER BYTE TSTB (R3)+ ; RESTORE BUFFER POINTER 8$: BIT #1,S.BAAD(R2) ; TEST IF BASE IS ODD ADDRESS BEQ 10$ ; NO - SO SKIP BYTE PROCESSING CMP S.VIRT(R2),S.BAAD(R2) ; ARE WE AT FIRST DATA BYTE? BNE 9$ ; NO - SO WE MUST DO TWO BYTES CLR ARG+6 ; CLEAR DATA OUTPUT LOCATION MOVB (R4),ARG+6 ; GET THE BYTE SWAB ARG+6 ; MOVE THE BYTE TO ODD ADDRESS BR 11$ ; CHECK IF EQUAL 9$: MOVB (R4),ARG+6 ; GET HIGH ORDER BYTE SWAB ARG+6 ; MOVE TO ODD ADDRESS MOVB -(R4),ARG+6 ; GET LOW ORDER BYTE TSTB (R4)+ ; RESTORE BUFFER POINTER BR 11$ ; CHECK IF DATA IS EQUAL 10$: MOV (R3),ARG+2 ; STORE DATA FILE 1 MOV (R4),ARG+6 ; STORE DATA FILE 2 11$: CMP ARG+2,ARG+6 ; IS THE DATA THE SAME? BEQ 15$ ; YES - SO SKIP OUTPUT BIT #4,FLAG ; ANY OFFSETS ENTERED? BEQ 13$ ; NO - SKIP OFFSET CALCULATIONS MOV #5,R5 ; SET UP LOOP COUNT MOV #O1,R0 ; POINTER TO FIRST OFFSET 12$: MOV ARG+6,S.DATA(R2) ; STORE DATA FILE 2 ADD (R0),S.DATA(R2) ; ADD OFFSET TO FILE 2 CMP ARG+2,S.DATA(R2) ; CMP DATA INCLUDING OFFSET BEQ 15$ ; THIS COMPARES SO GO ON MOV ARG+6,S.DATA(R2) ; STORE DATA FILE 2 SUB (R0)+,S.DATA(R2) ; SUB OFFSET FILE 2 AND BUMP CMP ARG+2,S.DATA(R2) ; CMP DATA INCLUDING OFFSET BEQ 15$ ; THIS COMPARES SO GO ON SOB R5,12$ ; LOOP TO DO ALL OFFSETS 13$: INC PASS2 ; SET UP FOR TWO PASSES CALL ADRES1 ; GET ASCII ADDRESS MOV ARG+2,ARG+10 ; GET DATA FROM FILE 1 SUB ARG+6,ARG+10 ; SUB DATA FILE 1 - FILE 2 MOV #F03,R5 ; SET UP FOR PHSYICAL ADDRESS CALL OUT ; OUTPUT DATA BIT #20,FLAG ; IS POST-PROCESSING REQUIRED? BEQ 14$ ; NO - SO SKIP POST-PROCESSING CALL PPOUT1 ; FILE 1 POST-PROCESS DATA OUT CALL PPOUT3 ; FILE 2 POST-PROCESS DATA OUT 14$: TST LIMIT3 ; ARE WE IN LIMIT MODE? BEQ 15$ ; NO - SO CONTINUE DEC LIMIT3 ; COUNT DOWN THE LIMIT BNE 15$ ; KEEP GOING IF NOT ZERO MOV #PLESS2,R5 ; CALL OUT ; SEND IT RETURN ; ALL DONE, GO AWAY 15$: TST (R3)+ ; INCREMENT DATA POINTER TST (R4)+ ; SAME FOR FILE 2 BIT #1,FLAG ; HONEYWELL ADDRESSING? BNE 16$ ; YES - INCREASE ADDRESS BY ONE INC S.VIRT(R1) ; ADD 1 TO FILE 1 VIRTUAL ADD. INC S.VIRT(R2) ; ADD 1 TO FILE 2 VIRTUAL ADD. 16$: INC S.VIRT(R1) ; ADD 1 TO FILE 1 VIRTUAL ADD. INC S.VIRT(R2) ; ADD 1 TO FILE 2 VIRTUAL ADD. ADD #2,S.BTCT(R1) ; INCREMENT THE BYTE COUNT CMP S.BTCT(R1),S.MAXB(R1) ; NEED ANOTHER BYTE COUNT? BLT 17$ ; NO - SO GO ON CALL BTCBA1 ; GET NEW BYTE CT. & BASE ADD. MOV S.BAAD(R1),S.VIRT(R1) ; KEEP UP WITH BASE ADDRESS 17$: ADD #2,S.BTCT(R2) ; INC. BYTE COUNT CMP S.BTCT(R2),S.MAXB(R2) ; NEED ANOTHER BYTE COUNT? BLT 18$ ; NO - SO GO ON CALL BTCBA2 ; GET BYTE CT. & BASE ADD. MOV S.BAAD(R2),S.VIRT(R2) ; KEEP UP WITH BASE ADDRESS 18$: JMP 1$ ; OUTPUT SOME MORE ; ; ; ; ; ; THE "OUT4" ROUTINE IS USED TO OUTPUT THE PHYSICAL ADDRESSES (VIRTUAL ; IF SELECTED) OF FILES 1 AND 2. THIS ROUTINE IS CALLED WHENEVER THE ; FILES VIRTUAL ADDRESSES BECOME DIFFERENT. ; ; OUT4: INC PASS2 ; SET UP FOR 2 PASSES CALL ADRES1 ; GO DO THE ASCII CONVERTION MOV #ASCII+6,ARG+2 ; OUTPUT ONLY THE ADDRESSES MOV #F07,R5 ; SET UP TO OUTPUT CALL OUT ; OUTPUT IT RETURN ; GO BACK ; ; ; ; ; ; THE "ADRES1" AND "ADRES2" SUBROUTINE IS USED TO CALCULATE A PHYSICAL ; ADDRESS FROM THE FILES VIRTUAL ADDRESS AND THE MEMORY MANAGEMENT DATA. ; BECAUSE THE PHYSICAL ADDRESS IS 6 DIGITS LONG IT CAN'T BE CONTAINED, ; IN OCTAL, IN ONE 16 BIT WORD. THEREFORE THIS ROUTINE CONVERTS THE ; PHYSICAL ADDRESS TO ASCII AND STORES IT IN A BUFFER FOR OUTPUT BY ; $EDMSG. ; ; THE SUBROUTINE IS SET UP TO BE EITHER ONE PASS OR TWO PASS DEPENDING ; ON THE PASS2 FLAG. "OUT1" AND "OUT2" USE IT AS A ONE PASS SUBROUTINE ; WHILE "OUT3" AND "OUT4" USE IT AS A TWO PASS SUBROUTINE. ; ; A KNOWLEDGE OF THE DEC MEMORY MANAGEMENT SYSTEM WILL BE QUITE BENE- ; FICIAL IN UNDERSTANDING THIS SUBROUTINE. ; ; ADRES1: JSR PC,$SAVAL ; SAVE REGISTERS MOV #FILE1,R3 ; SET UP FOR FILE 1 BR ADDRES ; GO DO IT ADRES2: JSR PC,$SAVAL ; SAVE REGISTERS MOV #FILE2,R3 ; SET UP FOR FILE 2 ADDRES: MOV S.VIRT(R3),R0 ; GET VIRTUAL ADDRESS MOV #ASCII,R2 ; THIS IS WHERE WE STORE ASCII MOV #ASCII,ARG ; ADDRESS OF ASCII STORAGE BR 2$ ; BRANCH AROUND PASS 2 SETUP 1$: MOV #FILE2,R3 ; POINTER TO FILE 2 MOV S.VIRT(R3),R0 ; GET VIRTUAL ADDRESS MOV #ASCII+6,ARG+4 ; ASCII STORAGE PASS 2 CLR PASS2 ; NO MORE PASSES 2$: BIT #1,FLAG ; HONEYWELL ADDRESSING? BNE 3$ ; YES - DONT MAKE ADDRESS EVEN BIC #1,R0 ; CLEAR BIT ONE 3$: ASHC #-6.,R0 ; DISPLACEMENT IN BLOCK TO R1 BIC #176000,R0 ; IN CASE BIT 15 WAS REPLICATED BIT #10,FLAG ; VIRTUAL ADDRESS SELECTED? BNE 4$ ; YES - DON'T ADD PAGE ADD. BIT #1,S.MMR0(R3) ; MEMORY MANAGEMENT ON? BEQ 4$ ; NO - SO CONTINUE BIC #1600,R0 ; CLEAR ACTIVE PAGE FIELD ADD S.PAF(R3),R0 ; ADD IN PAGE ADDRESS FIELD 4$: ASHC #-9.,R0 ; ALL BUT 1ST 3 BITS TO R5 MOV #6,R4 ; SET UP FOR 6 CHARACTERS BR 6$ ; ALREADY SET UP THIS PASS 5$: CLR R0 ; GET READY FOR NEXT CHARACTER ASHC #3.,R0 ; SHIFT IN NEXT THREE BITS 6$: ADD #'0,R0 ; MAKE ASCII MOVB R0,(R2)+ ; STORE ASCII CODE SOB R4,5$ ; LOOP FOR REST OF CHARACTERS TST PASS2 ; DO WE WANT ANOTHER PASS? BNE 1$ ; YES - GO BACK FOR ANOTHER RETURN ; GO BACK TO CALLER ; ; ; ; ; ; THIS IS THE SUBROUTINE THAT WRITES INTO THE OUTPUT FILES. THE ENTRY ; AT "OUTTI" WILL WRITE TO THE USERS TERMINAL AND "OUT" WILL WRITE TO ; THE COMMAND LINE OUTPUT FILE SPECIFICATION. SEE THE RSX-11M SYSTEM ; LIBRARY ROUTINES REFERENCE MANUAL FOR A DISCRIPTION OF $EDMSG. ; ; OUTTI: JSR PC,$SAVAL ; SAVE THE REGISTERS MOV #TOFDB,R3 ; SET UP TO OUTPUT TO TI: BR SETUP ; SKIP SETUP FOR OUTPUT FILE OUT: JSR PC,$SAVAL ; SAVE THE REGISTERS MOV #LSTFDB,R3 ; OUTPUT TO THE OUTPUT FILE SETUP: MOV #OUTBLK,R0 ; OUTPUT STORAGE BLK MOV R5,R1 ; THE TYPE FORMAT IS IN R5 MOV #ARG,R2 ; ARGUMENT BLOCK CALL $EDMSG ; EDIT MESSAGE SYS LIB ROUTINE PUT$ R3,#OUTBLK,R1 ; PUT MESSAGE TO OUTPUT FILE BCS 1$ ; ERROR WITH I/O? RETURN ; NO - ALL DONE 1$: CMP #TOFDB,R3 ; OUTPUT TO TI: OR OUTFILE? BNE 2$ ; OUTPUT ERROR TO TI: MOV #ERR10,R5 ; CALL OUT ; OUTPUT ERROR TO OUTPUT FILE BR 3$ ; RESTART THE PROGRAM 2$: MOV #ERR9,R5 ; CALL OUTTI ; OUTPUT TO TI: 3$: JMP RESTRT ; RESTART PROGRAM .PAGE .SBTTL POST-PROCESSING ROUTINES ; ; ; ; ; ; THE POST-PROCESSING OUTPUT ROUTINE IS USED TO STORE THE MISMATCH ; OUTPUTS FOR LATER PROCESSING ; ; THE DATA IS WRITTEN TO EITHER ONE OF TWO TEMPORARY FILES DEPENDING ; ON WHICH FILE THE ERROR OCCURED IN. THE DATA IS STORED IN A 3 WORD ; RECORD CONSISTING OF: ; 1) MSH OF ADDRESS IN RAD50 FORMAT ; 2) LSH OF ADDRESS IN RAD50 FORMAT ; 3) DATA IN OCTAL FORMAT ; ; SEE THE RSX-11M SYSTEM LIBRARY ROUTINES REFERENCE MANUAL FOR ; INFORMATION ON THE $CAT5 MACRO ; PPOUT1: JSR PC,$SAVAL ; SAVE ALL REGISTERS MOV #ASCII,R0 ; ADDRESS OF ASCII CHARACTERS MOV #F1TEMP,R4 ; SET UP TO ACCESS FILE F1TEMP BR CONV2 ; BRANCH AROUND OTHER SETUPS PPOUT2: JSR PC,$SAVAL ; SAVE ALL REGISTERS MOV #ASCII,R0 ; ADDRESS OF ASCII CHARACTERS BR CONV1 ; BRANCH AROUND OTHER SETUP PPOUT3: JSR PC,$SAVAL ; SAVE ALL REGISTERS MOV #ASCII+6,R0 ; ADDRESS OF ASCII CHARACTERS CONV1: MOV R4,R3 ; POINTER TO DATA IN R3 MOV #F2TEMP,R4 ; SET UP TO ACCESS FILE F2TEMP CONV2: CALL $CAT5 ; CONVERT MSH TO RAD50 MOV R1,PPBUFA ; AND STORE IN OUTPUT BUFF. CALL $CAT5 ; LSH ASCII TO RAD50 CONVERSION MOV R1,PPBUFA+2 ; AND STORE IT AWAY MOV (R3),PPBUFA+4 ; STORE DATA WORD FOR OUTPUT PUT$ R4,#PPBUFA,#6. ; OUTPUT THE RECORD BCS 1$ ; OUTPUT ERROR MESSAGE RETURN ; GO BACK 1$: MOV #ERR11,R5 ; CALL OUT ; OUTPUT THE MESSAGE RETURN ; AND GO BACK ; ; ; ; ; ; THE "POSTPR" ROUTINE SORTS THE ERRORS THAT WERE STORED IN THE TEMP- ; ORARY FILES, IN THE NUMERICAL ORDER OF THEIR ADDRESSES. IT THEN ; STORES THEM IN A BUFFER IN MEMORY FOR FUTHER PROCESSING. ; ; IF THE BUFFER GETS FULL BEFORE ALL THE ERRORS HAVE BEEN SORTED, THE ; "PPCOMP" ROUTINE IS CALLED TO PROCESS AND OUTPUT THE ERRORS IN THE ; BUFFER. "POSTPR" IS THEN RE-CALLED TO SKORT THE REMAINING ERRORS. ; ; IF A FILE HAS TWO ERRORS WITH THE SAME ADDRESS, THE LAST ERROR ; ENCOUNTERED IS THE ONE THAT WILL BE STORED IN THE POST-PROCESSING ; BUFFER THIS ELIMINATES EXTRANEOUS ERRORS DUE TO ONE LOAD MODULE ; STORING DATA IN A LOCATION TWICE (FIRST A OFFSET, THEN A VIRTUAL ; ADDRESS) AND THE OTHER LOAD MODULE STORING DATA IN THE SAME LOCATION ; ONLY ONCE(JUST THE VIRTUAL ADDRESS). ; ; POSTPR: MOV #POST1,R5 ; CALL OUTTI ; OUTPUT MESSAGE TO TI: MOV #F1TEMP,R0 ; SET UP FOR FILE 1 MOV #FILE1,R1 ; POINTER TO FILE 1 DATA MOV #F1BUFA,R2 ; STORE PROCESSED DATA IN BUF A INC PASS2 ; SET UP FOR SECOND PASS MOV #F1BUFA,S.OTCT(R1) ; RESET THE END OF DATA POINTER BR SORT ; DO THE SORTING F2POST: MOV #F2TEMP,R0 ; PASS 2, DO FILE 2 MOV #FILE2,R1 ; POINTER TO FILE 2 DATA MOV #F2BUFA,R2 ; PROCESSED DATA FILE 2 CLR PASS2 ; THIS IS LAST PASS MOV #F2BUFA,S.OTCT(R1) ; RESET THE DATA END POINTER SORT: MOV #1,F.RCNM+2(R0) ; READ THE FIRST RECORD 1$: GET$ R0,#PPBUFA ; GET A RECORD, STORE IN BUF A BCS 4$ ; GO CHECK THE ERROR MOV F.RCNM+2(R0),R3 ; STORE THE RECORD NUMBER CMP #77777,PPBUFA ; HAS THIS RECORD BEEN STORED? BEQ 1$ ; YES - SO GO GET ANOTHER 2$: GET$ R0,#PPBUFB ; NEXT RECORD TO BUF B BCS 6$ ; GO CHECK THE ERROR CMP #77777,PPBUFB ; HAS THIS RECORD BEEN STORED? BEQ 2$ ; YES - SO GET ANOTHER CMP PPBUFA,PPBUFB ; COMPARE MSH OF ADDRESS BLT 2$ ; SMALLEST SO FAR, TRY ANOTHER BGT 3$ ; NEW ONE IS SMALLER, STORE IT CMP PPBUFA+2,PPBUFB+2 ; MSH IS EQUAL, TRY LSH BLT 2$ ; WE HAVE THE SMALLEST SO FAR BGT 3$ ; RECORD THE NEW SMALLEST ONE CALL PUTPP ; 2 ADD. SAME NULL THE FIRST BR SORT ; LOOP TO GET NEXT RECORD 3$: MOV F.RCNM+2(R0),R3 ; RECORD THE RECORD NUMBER MOV PPBUFB,PPBUFA ; USE NEW MSH ADDRESS MOV PPBUFB+2,PPBUFA+2 ; USE NEW LSH ADDRESS MOV PPBUFB+4,PPBUFA+4 ; USE NEW DATA BR 2$ ; LOOP TO GET NEXT RECORD 4$: CMPB F.ERR(R0),#IE.EOF ; END OF FILE? BNE 5$ ; OUTPUT ERROR MESSAGE TST PASS2 ; FILE 2 STILL TO GO? BNE F2POST ; GO DO FILE 2 CALL PPCOMP ; COMPARE POST PROCESSING RETURN ; ALL DONE 5$: MOV #ERR13,R5 ; CALL OUT ; OUTPUT MESSAGE JMP RESTRT ; ABORT POST-PROCESSING 6$: CMPB F.ERR(R0),#IE.EOF ; ARE WE AT END OF FILE? BNE 5$ ; NO - OUTPUT ERROR MOV S.ENDB(R1),R5 ; USE R5 FOR CALCULATIONS SUB R2,R5 ; HOW CLOSE TO END OF BUFFER? CMP #6,R5 ; NEED 6 BYTES TO STORE INFO. BLT 7$ ; WE HAVE ENOUGH ROOM, SO GO TST PASS2 ; HAVE WE DONE FILE 2? BNE F2POST ; GO DO FILE 2 MOV #POST2,R5 ; CALL OUT ; OUTPUT MESSAGE MOV #POST3,R5 ; CALL OUT ; OUTPUT MESSAGE CALL PPCOMP ; YES - SO COMPARE WHAT WE HAVE BR POSTPR ; GO BACK AND DO THE REST 7$: MOV PPBUFA,(R2)+ ; THIS IS THE LOWEST ADDRESS MOV PPBUFA+2,(R2)+ ; THIS PASS SO STORE IT AWAY MOV PPBUFA+4,(R2)+ ; STORE AWAY THE DATA ADD #6,S.OTCT(R1) ; POINTER TO END OF DATA CALL PUTPP ; STORE #77777 IN THIS RECORD BR SORT ; LOOK FOR NEXT LOWEST ADDRESS ; ; ; ; ; ; THE "PUTPP" SUBROUTINE IS USED TO WRITE A NULL RECORD IN THE ; TEMPORARY FILE. THE NULL RECORD REPLACES AN ERROR RECORD THAT ; HAS BEEN SORTED, AND STORED IN THE POST-PROCESSING BUFFER. ; ; PUTPP: DEC R3 ; R3 MINUS 1 = RECORD TO NULL MOV R3,F.RCNM+2(R0) ; PUT IN FILE FDB PUT$ R0,#PPNULL ; NULL OUT THE RECORD BCS 1$ ; ERROR ON WRITE RETURN ; GO BACK 1$: MOV #ERR13,R5 ; CALL OUT ; OUTPUT MESSAGE JMP RESTRT ; ABORT POST-PROCESSING ; ; ; ; ; ; THE "PPCOMP" ROUTINE IS USED TO COMPARE THE SORTED ERRORS OF FILE 1 ; TO FILE 2. THIS ELIMINATES EXTRANEOUS ERRORS THAT OCCURED BECAUSE, ; ALTHOUGH THE DATA WAS THE SAME, LOAD MODULE 1 STORED THE DATA IN A ; DIFFERENT ORDER THAN LOAD MODULE 2. ; ; PPCOMP: MOV #FILE1,R1 ; POINTER TO FILE 1 PARAMETERS MOV #FILE2,R2 ; POINTER TO FILE 2 PARAMETERS MOV #F1BUFA,R3 ; POINTER TO START OF BUF A 1$: MOV #F2BUFA,R4 ; POINTER TO START OF BUF B 2$: TST (R4) ; HAS THIS ERROR GROUP BEEN USED? BEQ 4$ ; YES - SO GET ANOTHER CMP 4(R3),4(R4) ; COMPARE DATA THIS ERR GROUP BEQ 3$ ; DATA EQUAL, TRY FOR TWO MOV 4(R3),S.DATA(R1) ; GET DATA FROM FILE 1 MOV 4(R4),S.DATA(R2) ; GET DATA FROM FILE 2 CALL OFFCMP ; CMP DATA INCLUDING OFFSET BNE 4$ ; DATA NOT EQUAL, TRY ANOTHER 3$: CMP 12(R3),12(R4) ; CMP DATA NEXT ERROR GROUP BEQ 5$ ; TWO GROUPS MATCH, ZERO THEM MOV 12(R3),S.DATA(R1) ; GET DATA FROM FILE 1 MOV 12(R4),S.DATA(R2) ; GET DATA FROM FILE 2 CALL OFFCMP ; TRY IT WITH OFFSET BEQ 5$ ; TWO GROUPS MATCH, ZERO THEM 4$: ADD #6,R4 ; TRY NEXT GROUP FILE 2 CMP R4,S.OTCT(R2) ; AT THE END OF ERROR DATA? BLE 2$ ; NO - SO LOOP TO COMPARE ADD #6,R3 ; TRY NEXT ERROR GROUP FILE 1 CMP R3,S.OTCT(R1) ; END OF FILE 1? BLE 1$ ; NO - CMP NEW ERROR GROUP BR 6$ ; OUTPUT WHAT IS LEFT 5$: CLR (R3) ; CLEAR MSH ADDRESS THIS GROUP CLR (R4) ; DO THE SAME FOR FILE 2 ADD #6,R3 ; STEP TO NEXT ERROR GROUP CMP R3,S.OTCT(R1) ; AT END OF ERROR BUF 1? BGT 6$ ; YES - SO GO TO OUTPUT ADD #6,R4 ; DO THE SAME FOR FILE 2 CMP R4,S.OTCT(R2) ; AT THE END OF ERROR BUF 2? BGT 6$ ; NO - SO TRY FOR MORE MATCHES CMP 4(R3),4(R4) ; COMPARE DATA THIS ERR GROUP BEQ 5$ ; DATA EQUAL, ZERO IT MOV 4(R3),S.DATA(R1) ; GET DATA FROM FILE 1 MOV 4(R4),S.DATA(R2) ; GET DATA FROM FILE 2 CALL OFFCMP ; CMP DATA INCLUDING OFFSET BEQ 5$ ; DATA EQUAL, TRY ANOTHER BR 4$ ; NOT EQUAL, CONTINUE SEARCH 6$: CALL OUTPP1 ; OUTPUT WHAT IS LEFT RETURN ; AND GO BACK ; ; ; ; ; ; THIS SUBROUTINE COMPARES THE DATA + OR - THE OFFSETS ENTERED BY THE ; OPERATOR. ; ; OFFCMP: BIT #4,FLAG ; ANY OFFSETS ENTERED? BEQ 2$ ; NO - SKIP OFFSET CALCULATIONS MOV #5,R5 ; SET UP LOOP COUNT MOV #O1,R0 ; POINTER TO FIRST OFFSET 1$: ADD (R0),S.DATA(R2) ; ADD OFFSET FILE 2 CMP S.DATA(R1),S.DATA(R2) ; CMP DATA INCLUDING + OFFSET BEQ 3$ ; THIS COMPARES SO GO ON SUB (R0),S.DATA(R2) ; GET BACK TO ORIGINAL S.DATA SUB (R0),S.DATA(R2) ; SUB OFFSET FILE 2 AND BUMP CMP S.DATA(R1),S.DATA(R2) ; CMP DATA INCLUDING - OFFSET BEQ 3$ ; THIS COMPARES SO GO ON ADD (R0)+,S.DATA(R2) ; RESTORE ORIGINAL S.DATA SOB R5,1$ ; LOOP TO DO ALL OFFSETS 2$: CLZ ; CLEAR Z BIT FOR RETURN 3$: RETURN ; AND GO BACK FOR DECISION ; ; ; ; ; ; THE "OUTPP1" ROUTINE OUTPUTS THE RESULTS OF THE POST-PROCESSING ; OF THE COMPARE ERRORS. THE FILE 1 AND FILE 2 ERRORS ARE OUTPUT ; IN NUMERICAL ORDER. ; ; OUTPP1: MOV #ASTRI1,R5 ; POINTER TO TOP ASTRICS CALL OUT ; OUTPUT THEM MOV #POST,R5 ; POST-PROCESSING MESSAGE CALL OUT ; OUTPUT IT MOV #ASTRI2,R5 ; POINTER TO BOTTOM ASTRICS CALL OUT ; OUTPUT THEM MOV #F1BUFA,R3 ; POINTER TO FILE 1 BUFFER MOV #F2BUFA,R4 ; POINTER TO FILE 2 BUFFER 1$: TST (R3) ; ANYTHING TO OUTPUT? BNE 3$ ; YES - GO GET FILE 2 2$: ADD #6,R3 ; NO - ADVANCE POINTER CMP R3,FILE1+S.OTCT ; AT END OF OUTPUT DATA? BLT 1$ ; NO - CHECK FOR OUTPUT MOV #177777,(R3) ; INSERT MAX DUMMY ADDRESS CMP (R3),(R4) ; ARE BOTH AT END OF DATA? BEQ 9$ ; WE MUST BE DONE, SO GO 3$: TST (R4) ; ANYTHING TO OUTPUT FILE 2? BNE 5$ ; YES - CHECK FOR LOWEST ADDR. 4$: ADD #6,R4 ; NO - SO TRY THE NEXT ONE CMP R4,FILE2+S.OTCT ; AT END OF OUTPUT DATA? BLT 3$ ; TST THIS ONE FOR OUTPUT MOV #177777,(R4) ; INSERT MAX DUMMY ADDRESS CMP (R3),(R4) ; ARE BOTH AT END OF DATA? BEQ 9$ ; WE MUST BE DONE, SO GO 5$: CMP (R3),(R4) ; COMPARE MSH OF ADDRESSES BLT 7$ ; OUTPUT ERROR FROM FILE 1 BGT 8$ ; OUTPUT ERROR FROM FILE 2 CMP 2(R3),2(R4) ; COMPARE LSH OF ADRESSES BLT 7$ ; OUTPUT ERROR FROM FILE 1 BGT 8$ ; OUTPUT ERROR FROM FILE 2 CMP 4(R3),4(R4) ; ADDR. ARE EQUAL, CHECK DATA BEQ 6$ ; DATA IS EQUAL, SKIP OUTPUT MOV #F06,R5 ; ADDR. ARE EQUAL, OUTPUT BOTH MOV R3,R0 ; DATA FILE 1 FIRST CALL OUTPP2 ; STORE FIRST PART OF OUTPUT MOV R4,R0 ; DATA FROM FILE 2 MOV #ARG+6,R1 ; POINTER TO OUTPUT STORAGE CALL OUTPP3 ; STORE SECOND PART OF OUTPUT CALL OUT ; OUTPUT FILE 1 AND FILE 2 6$: ADD #6,R4 ; ADVANCE FILE 2 POINTER CMP R4,FILE2+S.OTCT ; CHECK IF AT END OF DATA BLT 2$ ; NO - SO GO ADVANCE FILE 1 MOV #177777,(R4) ; INSERT MAX DUMMY ADDRESS BR 2$ ; LOOP TO CONTINUE OUTPUT 7$: MOV #F04,R5 ; OUTPUT JUST FILE 1 MOV R3,R0 ; POINTER TO ERROR DATA FILE 1 CALL OUTPP2 ; STORE THE DATA FOR OUTPUT CALL OUT ; AND OUTPUT IT BR 2$ ; LOOP TO CONTINUE OUTPUT 8$: MOV #F05,R5 ; OUTPUT JUST FILE 2 MOV R4,R0 ; POINTER TO ERROR DATA FILE 2 CALL OUTPP2 ; STORE THE DATA FOR OUTPUT CALL OUT ; AND OUTPUT IT BR 4$ ; LOOP TO CONTINUE OUTPUT 9$: RETURN ; GO BACK ; OUTPP2: MOV #ARG,R1 ; POINTER OUTPUT STRORAGE AREA OUTPP3: MOV #3,R2 ; LOOP COUNT 1$: MOV (R0)+,(R1)+ ; STORE THE ERROR DATA SOB R2,1$ ; CHECK LOOP COUNT RETURN ; ALL DONE, SO GO BACK .END GO KKK