.TITLE AFT - FILES MODIFIED AFTER DATE .SBTTL TITLE PAGE .IDENT -010100- ;+ ; ABSTRACT: AFT ; ; THIS PROGRAM WILL PRODUCE A FILE CONTAINING THE NAMES ; OF THE FILES CREATED OR MODIFIED AFTER A GIVEN DATE AND TIME. ; ; OPERATING PROCEDURES: ; ; THIS TASK CAN BE RUN EITHER AS AN MCR COMMAND OR BY ; SAYING RUN $AFT$. IT PROMPTS WITH ; ; AFT> ; ; AND EXPECTS A COMMAND STRING OF THE FORM: ; ; FILE=DEV:/AF:DD-MMM-YY HH+MM ; ; WHERE DEV: IS THE DEVICE ON WHICH THE SCAN IS TO BE ; DONE (DEV: DEFAULTS TO SY:) AND "FILE" IS THE FILE ; TO WHICH THE INFORMATION IS TO BE WRITTEN. ; AFT WILL ALSO DO A CURSORY CHECK OF THE FILE ; HEADERS ON THE INDEX FILE WHILE IT IS IN THERE ANYWAY. ; THE INFORMATION IS GENERALLY CLOSE TO THAT WHICH YOU ; MIGHT GET FROM RUNNING "VFY" IN READ CHECK MODE, BUT ; RUNS FASTER. "VFY" IS ABLE TO FIND MORE ERRORS OF COURSE ; SINCE IT LOOKS AT WHETHER THE BLOCKS ARE PHYSICALLY ; READABLE (AS WELL AS WHETHER THE INDEX FILE IS INTACT). ; AFT DOES NOT DO ANYTHING ANALOGOUS TO THE "VFY" ; CONSISTENCY CHECK OR LOST FILE SCAN. ; ; SWITCHES: ; ; /CK PRINT OUT INCORRECT FILE CHECKSUMS ; /BI USE THE INDEX FILE BITMAP TO DETERMINE ; WHICH FILES TO EXAMINE. THIS IS THE ; DEFAULT, BUT ALL FILE HEADER NUMBERS ; FROM 1 THROUGH THE NUMBER MAPPED IN ; THE FILE CAN BE EXAMINED BY /-BI. ; THIS IS NORMALLY ONLY USEFUL IF THE ; INDEX FILE HAS BEEN CLOBBERED FOR SOME ; REASON. ; /AF:DATE SELECT ALL FILES MODIFIED AFTER THE ; SPECIFIED DATE AND TIME. THE DATE IS ; GIVEN IN STANDARD DEC FORMAT, FOR EXAMPLE ; ; /AF:1-JUN-80 11+00 ; AFTER 11:00 ON 1-JUN-80 ; /AF:1-MAY-78 18+00 ; AFTER 6PM ON 1-MAY-78 ; ; TASK: AFT ; ; WRITTEN: 11-DEC-78, -0.0.0-, BRUCE C. WRIGHT ; MODIFIED: 23-JUN-80, -1.0.0-, BRUCE C. WRIGHT ; CHANGED TO USE MULTI-BLOCK I/O ; Modified: 07-May-1981, -1.1.0-, Bruce C. Wright ; Corrected running off end of file if index file almost full ; Verified: 07-May-1981, -1.1.0-, Bruce C. Wright ;- .SBTTL MACRO CALLS .MCALL QIOW$,WSIG$S,EXIT$S .MCALL OPNS$R,OPEN$W,READ$,WAIT$,CLOSE$,PUT$ .MCALL CSI$,CSI$1,CSI$2,CSI$SW,CSI$SV,CSI$ND .MCALL GCML$,GCMLB$ .MCALL FDAT$A,FDBF$A,FDRC$A,FDBK$A,FDOP$A .MCALL FDBDF$,FSRSZ$,NMBLK$ .MCALL FDOF$L,FCSBT$,FHDOF$,HMBOF$ FDOF$L FCSBT$ FHDOF$ DEF$L HMBOF$ DEF$L CMDLUN=1 CMDEVF=1 INDLUN=2 INDEVF=2 MSGLUN=3 MSGEVF=3 UICLUN=4 UICEVF=4 .SBTTL MACRO DEFINITIONS .MACRO MSG ARG .NCHR $$$, .WORD $$$ .ASCII "ARG" .EVEN .ENDM .MACRO TYPE STR,LEN MOV STR,-(SP) MOV LEN,-(SP) CALL TYPE CMP (SP)+,(SP)+ .ENDM .MACRO TYPMSG ARG TYPE #ARG+2,ARG .ENDM .MACRO ONERR ARG BCC .+6 JMP ARG .ENDM .SBTTL MAIN LINE CODE .PSECT CODE,RO,I BEGIN:: MOV SP,SPSAVE GCML$ #CMLBLK ; BCC GETOK ;GOT A LINE CMPB CMLBLK+G.ERR,#GE.EOF ;EOF? BNE 10$ ;NO EXIT$S ;YES 10$: CMPB CMLBLK+G.ERR,#GE.IOR ;I/O ERROR? BNE 20$ ;NO TYPMSG M.IOR EXIT$S ;THIS IS FATAL 20$: CMPB CMLBLK+G.ERR,#GE.OPR ;OPEN ERROR? BNE 30$ TYPMSG M.OPR BR BEGIN 30$: CMPB CMLBLK+G.ERR,#GE.BIF ;SYNTAX ERROR? BNE 40$ ;NO TYPMSG M.BIF BR BEGIN 40$: CMPB CMLBLK+G.ERR,#GE.MDE ;MAX @ DEPTH? BNE 50$ TYPMSG M.MDE BR BEGIN 50$: TYPMSG M.UNK ;UNKNOWN ERROR EXIT$S ;AND LEAVE GETOK: TST CMLBLK+G.CMLD ;INPUT? BEQ BEGIN ;NO MOV #SW.BI,SWORD ; INIT SWORD CSI$1 #CSIBLK,CMLBLK+G.CMLD+2,CMLBLK+G.CMLD ; BCC 10$ TYPMSG M.PS1 BR BEGIN 10$: CSI$2 #CSIBLK,INPUT,#CSISWS ; BCC 20$ ;OK? TYPMSG M.PS2 ;NO BR BEGIN ;RESTART 20$: MOV #DEVLEN,DSPT ;SET UP DSPT MOV #DEVSTR,DSPT+2 ;FOR THE OPEN MACRO BITB #CS.NMF!CS.DIF!CS.WLD!CS.MOR,CSIBLK+C.STAT BEQ 30$ ;ANY ILLEGAL BITS SET? TYPMSG M.BAD ;YES -- BAD PARAMETERS JMP BEGIN ; 30$: BITB #CS.DVF,CSIBLK+C.STAT ;DEV STRING? BEQ 40$ ;NO MOV CSIBLK+C.DEVD,DSPT ;MOVE IN DEVICE DESC. MOV CSIBLK+C.DEVD+2,DSPT+2 40$: OPNS$R #INDEX,,#DSPT ;OPEN THE INDEX FILE ONERR ERROR ;SKIP IF ERROR CSI$2 #CSIBLK,OUTPUT,#CSISWS BCC 50$ ;ERROR? TYPMSG M.PS2 ;YES CLOSE$ #INDEX ;CLOSE INDEX FILE JMP BEGIN ;AND LOOP. 50$: BITB #CS.WLD!CS.MOR,CSIBLK+C.STAT ;ILLEGAL PARAMETERS? BEQ 60$ ;NO TYPMSG M.BAD ;YES CLOSE$ #INDEX JMP BEGIN 60$: BIT #SW.AF,SWORD ;WAS THE /AF: SWITCH SPECIFIED? BNE 65$ ;YES TYPMSG M.NODA ;NO DATE SPECIFIED CLOSE$ #INDEX ;CLOSE INDEX FILE JMP BEGIN ;AND BEGIN AGAIN. 65$: CALL PARDAT ;PARSE THE DATE BCC 70$ ;SKIP IF OK TYPMSG M.ILDA ;ILLEGAL DATE SPECIFIED CLOSE$ #INDEX ;CLOSE INDEX FILE JMP BEGIN ;AND BEGIN AGAIN. 70$: OPEN$W #UICFDB,,#CSIBLK+C.DSDS ONERR ERROR ;ERROR? MOV #-1,CURBLK ;INIT CURRENT BLOCK POINTER CLR CURCNT ;AND COUNT OF BLOCKS IN MEMORY. CLR INDEX+F.EFBK ;FIXUP FDB OF INDEX FILE MOV #3,INDEX+F.EFBK+2 ;SO WE DON'T GET AN EOF CLR INDEX+F.HIBK MOV #3,INDEX+F.HIBK+2 ;DITTO CLR INDEX+F.BKVB ;CLEAR HI ORDER BLOCK # MOV #2,INDEX+F.BKVB+2 ;INIT LO ORDER BLOCK # READ$ #INDEX,#HOME,#1000 ;READ HOME BLOCK ONERR ERROR WAIT$ R0 ;WAIT FOR IO ONERR ERROR CLR BITADR ;CLEAR BITMAP OFFSET # CLR CURID ;INIT CURRENT FILE ID MOV HOME+H.IBSZ,R1 ;NOW FIXUP REAL LENGTH OF INDEX FILE ADD HOME+H.FMAX,R1 ;ADD INDEX FILE SIZE + MAX # OF FILES ADD #3,R1 ;PLUS BASE = INDEX FILE SIZE + 1 MOV R1,INDEX+F.HIBK+2 ; (WE DON'T WANT TO GET EOF) MOV R1,INDEX+F.EFBK+2 ; BIT #SW.BI,SWORD ; ARE WE TO USE THE INDEX FILE BITMAP? BEQ 300$ ; J IF NOT 100$: MOV BITADR,R1 ;GET BITMAP OFFSET BLOCK INC BITADR ;INC IT FOR NEXT TIME. CMP R1,HOME+H.IBSZ ;OVER BITMAP SIZE? BHIS 900$ ;YES -- LEAVE. ADD #3,R1 ;CONVERT IT TO VIRTUAL BLOCK # CLR INDEX+F.BKVB ;CLEAR HI BLOCK # MOV R1,INDEX+F.BKVB+2 ;INIT LOW BLOCK # READ$ #INDEX,#BITMAP,#1000 ;READ INDEX FILE BCS 110$ ;SKIP ON ERROR. WAIT$ R0 ;WAIT BCC 119$ ;SKIP ON OK. 110$: CLR FATAL ;INDICATE NON-FATAL ERROR MESSAGE TYPMSG M.INDB ;TYPE INDEX FILE ERROR MESSAGE CALL ERROR ;PRINT THE ERROR CAUSE. INC FATAL ;MAKE FATAL AGAIN MOV #BITMAP,R1 ;POINT TO THE BITMAP MOV #400,R2 ;GET SIZE OF BITMAP (IN WORDS) 118$: MOV #-1,(R1)+ ;FORCE TO ALL 1'S. SOB R2,118$ ;AND LOOP. 119$: MOV #BITMAP,R1 ;POINT TO BITMAP. 120$: MOV (R1)+,R2 ;GET A WORD OF BITMAP BEQ 200$ ;SKIP IF NO FILES HERE CLR R3 ;GET OFFSET OFF OF CURID 125$: INC R3 ;INC COUNTER ROR R2 ;GET NEXT FILE ID BCC 130$ ;SKIP IF NONE THERE MOV R3,R5 ;GET OFFSET OFF CURID ADD CURID,R5 ;ADD IN CURRENT ID # CALL CHECK ;CHECK THIS FILE ID TST R2 ;SEE IF R2 HAS ANYTHING IN IT 130$: BNE 125$ ;LOOP UNTIL THIS GOES TO 0 200$: ADD #20,CURID ;INC CURRENT FILE ID BASE CMP R1,#BITEND ;OFF END OF BITMAP? BLO 120$ ;NO -- LOOP OVER BITMAP BR 100$ ;YES -- NEXT BLOCK 300$: MOV #1,CURID ; SET UP CURRENT BLOCK ID 400$: MOV CURID,R5 ; GET CURRENT FILE ID CALL CHECK ; RETRIEVE FILE INC CURID ; LOOK AT NEXT FILE MOV CURID,R5 ; INTO R5 ADD HOME+H.IBSZ,R5 ; GET HOME BLOCK OFFSET ADD #2,R5 ; GET BASE OFFSET CMP R5,INDEX+F.EFBK+2 ; OVER TOP OF INDEX FILE? BLO 400$ ; J IF NOT. 900$: CLOSE$ #INDEX CLOSE$ #UICFDB JMP BEGIN ;RESTART ERROR: MOV R1,-(SP) ;SAVE REGISTERS MOV R2,-(SP) MOV #BLKPR,R1 MOV #BLKSZ,R2 TST @#$DSW ;ERROR IN DSW? BPL 10$ ;NO MOV @#$DSW,F.ERR(R0) ;MOVE DSW INTO ERROR CODE 10$: CALL .PRFCS ;PRINT FCS ERROR CODE MOV (SP)+,R2 ;RECOVER REGISTERS MOV (SP)+,R1 ; TST FATAL ;IS THIS A FATAL ERROR? BNE RESTRT ;YES -- THEN LEAVE. RETURN ;OTHERWISE RETURN AND CONTINUE. RESTRT: CLOSE$ #INDEX CLOSE$ #UICFDB ; MOV SPSAVE,SP ;RESTORE SP JMP BEGIN ;AND RESTART EXECUTION .SBTTL PARDAT -- PARSE DATE FROM COMMAND STRING ;+ ; THIS SUBROUTINE IS SIMILAR TO THE "GETDAT" SUBROUTINE, BUT IT WORKS ; ON A "NORMAL" PDP-11 DATE/TIME EXTERNAL FORMAT RATHER THAN THE ; INTERNAL FORMAT USED BY THE GETDAT SUBROUTINE. THE METHOD USED IS ; TO PARSE THE DATE, ENSURING MARGINAL LEGALITY, AND THEN PASS THE ; RESULTING "DATE" ON TO GETDAT. ; ; ON ENTRY, ; ; DATBUF = DATE TO BE PARSED. ; ; ON EXIT, ; ; DATE, AND TIME ARE SET TO THE CORRECT VALUES. ; CARRY WILL BE SET IF AN ILLEGAL DATE IS ENCOUNTERED. ; ;- PARDAT: MOV R0,-(SP) ;SAVE R0 MOV R1,-(SP) MOV R2,-(SP) MOV R3,-(SP) MOV R4,-(SP) MOV #DATBUF,R0 ;POINT TO THE DATE BUFFER. MOV #BUFFER,R4 ;POINT TO THE TEMPORARY OUTPUT BUFFER. MOVB (R0)+,R1 ;GET A BYTE. MOVB (R0)+,R2 ;GET ANOTHER BYTE. CMPB R2,#'9 ;IS R2 > 9? BHI 10$ ;YES CMPB R2,#'0 ;OR < 0? BLO 10$ ;YES MOVB R1,(R4)+ ;OUTPUT R1, R2 MOVB R2,(R4)+ ; MOVB (R0)+,R2 ;GET THE NEXT BYTE. BR 20$ ;AND SKIP FIXUP CODE. 10$: MOVB #'0,(R4)+ ;MOVE OUT A 0 MOVB R1,(R4)+ ;AND THE CONTENTS OF R1 20$: CMPB R2,#'- ;NEXT CHAR IS A - BNE 999$ ;NO -- ERROR MOVB (R0)+,(R4)+ ;NOW THREE MONTH CHARS MOVB (R0)+,(R4)+ ;IGNORE THEM FOR NOW. MOVB (R0)+,(R4)+ ;THEY WILL BE CHECKED BY GETDAT CMPB (R0)+,#'- ;ANOTHER DASH IS REQUIRED BNE 999$ ;NO -- ERROR MOVB (R0)+,(R4)+ ;NOW THE YEAR MOVB (R0)+,(R4)+ ;GETDAT WILL ALSO CHECK THIS. 30$: MOVB (R0)+,R1 ;GET A CHARACTER. CMPB R1,#' ;FIND NEXT NON-BLANK BEQ 30$ ;AND LOOP MOVB (R0)+,R2 ;GET THE TIME CMPB R2,#'+ ;IS IT FROM 0-9 O'CLOCK? BEQ 40$ ;YES MOVB R1,(R4)+ ;OUTPUT R1 MOVB R2,(R4)+ ;AND THE NEXT CHAR. MOVB (R0)+,R2 ;GET THE NEXT CHAR BR 50$ ;AND SKIP FIXUP CODE 40$: MOVB #'0,(R4)+ ;OUTPUT A 0 - 0-9 O'CLOCK MOVB R1,(R4)+ ;OUTPUT THE HOUR 50$: CMPB R2,#'+ ;SEPARATOR BETTER BE : BNE 999$ ;NO -- ERROR MOVB (R0)+,R1 ;GET ANOTHER PAIR OF CHARS. MOVB (R0)+,R2 ;ETC CMPB R2,#'0 ;IS R2 NUMERIC? BLO 60$ ;NO CMPB R2,#'9 ;??? BHI 60$ ;NO -- NOT NUMERIC MOVB R1,(R4)+ ;AND OUTPUT R1 MOVB R2,(R4)+ ;AND THE LOW ORDER DIGIT BR 70$ ;AND LEAVE 60$: MOVB #'0,(R4)+ ;OUTPUT A 0 MOVB R1,(R4)+ ;AND OUTPUT THE DIGIT. 70$: MOV #BUFFER,R0 ;GET THE BUFFER FOR GETDAT CALL GETDAT ;CONVERT TO INTERNAL TIME AND DATE BCS 999$ ;ERROR -- ILLEGAL FORMAT MOV R2,DATE ;SET THE INTERNAL DATE MOV R3,TIME ;AND SET THE INTERNAL TIME. 900$: MOV (SP)+,R4 ;RESTORE REGISTERS MOV (SP)+,R3 ; MOV (SP)+,R2 ; MOV (SP)+,R1 MOV (SP)+,R0 ;RESTORE R0 RETURN ;AND RETURN 999$: SEC ;SET ERROR RETURN BR 900$ ;AND RETURN .SBTTL ACCOUNT THIS FILE'S BLOCKS ; ; ENTER SUBROUTINE WITH: ; ; R5 FILE ID OF BLOCK ; ; R0 AND R4 ARE MODIFIED; ALL OTHER REGISTERS ARE ; PRESERVED. ; CHECK: MOV R1,-(SP) ;SAVE R1 MOV R2,-(SP) ;SAVE R2 MOV R3,-(SP) ;SAVE R3 MOV R5,R0 ;GET FILE ID ADD HOME+H.IBSZ,R0 ;GET FIRST BLOCK # ADD #2,R0 ; + 2 FOR ORIGIN. .IF DF SBLOCK ; IF SINGLE BLOCK I/O ... CLR INDEX+F.BKVB ;CLEAR HI ORDER BLOCK MOV R0,INDEX+F.BKVB+2 ;INIT LOW ORDER BLOCK READ$ #INDEX,#INDBUF,#1000 ;READ DATA BCS 10$ ;SKIP ON ERROR WAIT$ R0 ; BCC 19$ ;SKIP ON NO ERROR 10$: CLR FATAL ;INDICATE NON-FATAL ERROR TYPMSG M.INDH ;INDICATE ERROR READING FILE HEADER CALL ERROR ;PRINT THE ERROR MESSAGE INC FATAL ;NEXT MESSAGE IS FATAL. CMPB F.ERR(R0),#IE.EOF ;END-OF-FILE? BNE 18$ ;NO TYPMSG M.UEOF ;NOTE UNEXPECTED E-O-F JMP RESTRT ;AND RESTART 18$: JMP CHECKE ;AND RETURN. 19$: MOV #INDBUF,R0 ; POINT TO THE BUFFER. .IF DF DEBUG BITB #SC.MDL,H.SCHA(R0) ;MARKED FOR DELETE? BEQ 99$ ;NO JMP CHECKE ;YES 99$: .ENDC .IFF ; OTHERWISE ... CALL GETBLK ; GET THE BLOCK .ENDC ;SBLOCK ; (RETURN ADDR IN R0) CMP R5,H.FNUM(R0) ;CORRECT FID? BEQ 20$ ;YES -- NO MESSAGE CALL BADHDR ;NO -- PRINT NASTY MESSAGE 20$: MOV R0,R1 ;POINT TO HEADER MOV #400-1,R2 ;GET COUNT CLR R3 ;CLEAR CHECKSUM C0: ADD (R1)+,R3 ;ADD IN CHECKSUM SOB R2,C0 ; CMP (R1)+,R3 ;EQUAL TO CKSUM? BEQ 10$ ;YES CALL CHKHDR ;NO BIT #SW.CK,SWORD ;PRINT CORRECT CHECKSUMS? BEQ 10$ ; J IF NOT. MOV R0,-(SP) ;SAVE R0 MOV R3,R1 ;GET CHECKSUM INTO R1 MOV #BUFFER,R0 ; POINT TO BUFFER MOV #1,R2 ; NO 0 SUPPRESS CALL $CBOMG ; CONVERT TO OCTAL SUB #BUFFER,R0 ; COMPUTE LENGTH TYPE #BUFFER,R0 ; TYPE OUT MESSAGE MOV (SP)+,R0 ; RECOVER R0 10$: CMP #401,H.FLEV(R0) ;CORRECT VERSION? BEQ 12$ ;NO CALL LEVHDR ;HEADER LEVEL MISMATCH 12$: MOVB H.IDOF(R0),R1 ;GET ID OFFSET ASL R1 CMP R1,#1000-S.IDHD-S.MPHD ;TOO BIG? BLO 15$ ;NO CALL BIDHDR ;YES 15$: CMPB H.IDOF(R0),#27 ;'NORMAL' VALUE? BEQ 16$ ;YES CALL NIDHDR ;NO 16$: BITB #UC.DLK,H.UCHA(R0) ;LOCKED FILE? BEQ 21$ ;NO CALL DLKHDR ;PRINT MESSAGE 21$: BITB #SC.MDL,H.SCHA(R0) ;MARKED FOR DELETE? BEQ 22$ ;NO CALL DELHDR ;PRINT MESSAGE 22$: BITB #SC.BAD,H.SCHA(R0) ;BAD BLOCK IN FILE? BEQ 23$ ;NO CALL BLKHDR ;PRINT MESSAGE 23$: MOVB H.MPOF(R0),R1 ;GET MAP AREA OFFSET ASL R1 ;ADJUST FOR WORDS BIC #^C777,R1 ADD R0,R1 ; ABSOLUTISE MOVB M.USE(R1),R2 ;GET # USED BIC #^C377,R2 ;CLEAR HI BYTE ASL R2 ; ADD R1,R2 ;COMPUTE END OF MAP AREA MOV R0,-(SP) ;SAVE BEGINNING OF BUFFER ADD #1000-2-S.MPHD,(SP) ; COMPUTE END OF BUFFER. CMP R2,(SP)+ ; OVER TOP? BLOS 25$ ;HEADER OK CALL MAPHDR ; JMP CHECKE ; 25$: CMPB H.MPOF(R0),#56 ;IS IT NORMAL? BEQ 26$ ;YES CALL NMPHDR ;NO 26$: MOVB M.USE(R1),R4 ;GET NUMBER OF PTRS IN USE BIC #^C377,R4 ;CLEAN GARBAGE CMP R4,#<1000-S.IDHD-S.MPHD-S.HDHD-2>/2 ;OVER MAX # OF POINTERS? BHI 27$ ;YES -- ERROR CMPB R4,M.MAX(R1) ;OVER MAX # THIS HEADER BLK? BLOS 28$ ;NO -- OK 27$: CALL PTRHDR ;ERROR MESSAGE 28$: CMPB M.CTSZ(R1),#1 ;SIZE OF BLOCK COUNT UNUSUAL? BEQ C1 ;NO CALL BCFHDR ;YES C1: CMPB M.LBSZ(R1),#3 ;LOGICAL BLOCK UNUSUAL? BEQ 10$ ;NO CALL LBNHDR ;YES 10$: CMPB M.MAX(R1),#<1000-S.HDHD-S.IDHD-S.MPHD-2>/2 ;MAX # OF POINTERS NORMAL? BEQ 20$ ;YES CALL MAXHDR ; 20$: MOV R0,R1 ; GET HEADER ADDRESS. MOVB H.IDOF(R0),R2 ;GET ID OFFSET (IN WORDS) BMI CHECKE ;SKIP IF BAD. ASL R2 ;ADJUST TO BYTES. ADD R2,R1 ;POINT TO ID AREA MOV R0,-(SP) ; BUFFER AREA TO STACK. ADD #1000,(SP) ; ADD IN LENGTH OF BLOCK. CMP R1,(SP)+ ; OVER TOP? BHIS CHECKE ;YES -- LEAVE. MOV R0,-(SP) ; SAVE R0 MOV R1,R0 ;GET REVISION DATE ADD #I.RVDT,R0 ; CALL GETDAT ;GET THE DATE AND TIME IN R2,R3 MOV (SP)+,R0 ; RECOVER R0 BCS CHECKE ;SKIP ON ERROR. CMP R2,DATE ;COMPARE AGAINST THE DATE. BLO CHECKE ;LEAVE IF NOT TODAY'S DATE. BNE 80$ ;SKIP TIME CHECK IF NOT TODAY. CMP R3,TIME ;COMPARE AGAINST THE TIME BLO CHECKE ;LEAVE IF NOT RIGHT TIME 80$: MOV R0,R3 ; REMEMBER HEADER ADDRESS. MOV #BUFFER,R0 ;POINT TO BUFFER. MOVB #'[,(R0)+ ;OUTPUT THE UIC. MOVB H.PROJ(R3),R1 ;GET PROJECT CODE BIC #^C377,R1 ;CLEAR HI GARBAGE CLR R2 ;SET ZERO SUPPRESS CALL $CBOMG ;CONVERT TO OCTAL MOVB #',,(R0)+ ;OUTPUT A COMMA MOVB H.PROG(R3),R1 ;GET PROGRAMMER BIC #^C377,R1 ;CLEAN GARBAGE CLR R2 ;SET ZERO SUPPRESS CALL $CBOMG ;CONVERT TO OCTAL MOVB #'],(R0)+ ;TERMINATE THE UIC. MOVB H.IDOF(R3),R4 ;GET ID OFFSET. ASL R4 ;CONVERT TO WORDS ADD R3,R4 ;ADD IN THE HEADER. CLR R2 ;CLEAR FLAG WORD MOV I.FNAM(R4),R1 ;GET FILE NAME CALL $C5TA ;CONVERT TO ASCII MOV I.FNAM+2(R4),R1 ;MORE FILE NAME CALL $C5TA ;AGAIN MOV I.FNAM+4(R4),R1 ;GET LAST OF FILE NAME CALL $C5TA ;TO ASCII! 90$: CMPB -(R0),#' ;ELIMINATE THE BLANKS BEQ 90$ ;LOOP OVER IT ALL. INC R0 ;SKIP BACK TO NON-BLANK JUST SKIPPED. MOVB #'.,(R0)+ ;GET A . FOR EXTENSION. MOV I.FTYP(R4),R1 ;GET EXTENSION CALL $C5TA ;CONVERT IT 91$: CMPB -(R0),#' ;ELIMINATE BLANKS BEQ 91$ ;LOOP OVER ALL OF THEM INC R0 ;POINT PAST NON-BLANK JUST SKIPPED. MOVB #';,(R0)+ ;MOVE IN A ; FOR THE VERSION ID. MOV I.FVER(R4),R1 ;GET THE VERSION NUMBER. CLR R2 ;SET FOR ZERO SUPPRESS. CALL $CBOMG ;CONVERT TO OCTAL MAGNITUDE. MOV R0,R1 ;GET POINTER INTO R1 SUB #BUFFER,R1 ;COMPUTE LENGTH OF BUFFER. PUT$ #UICFDB,#BUFFER,R1 ;PRINT THE BUFFER. ONERR ERROR ;CHECK FOR ERRORS. CHECKE: MOV (SP)+,R3 ;RECOVER R3 MOV (SP)+,R2 ;RECOVER R2 MOV (SP)+,R1 ;RECOVER R1 RETURN ;AND RETURN .SBTTL GETDAT -- DECODE THE DATE AND TIME ;+ ; THIS SUBROUTINE TAKES THE DATE AND TIME AT (R0) AND ; CONVERTS IT INTO A BINARY TIME IN R2 AND R3. THE TIME ; IS NOT MEASURED IN ANY REGULAR UNITS BUT WILL PRESERVE ; THE ORDERING BETWEEN VARIOUS DATES AND TIMES. ; ; ON ENTRY, ; ; R0 -> TIME AND DATE STRING ; ; ON EXIT, ; ; R0 -> END OF TIME AND DATE STRING ; R2 = BINARY ENCODING OF DATE ; R3 = BINARY ENCODING OF TIME ; CARRY WILL BE SET IF THE DATE OR TIME IS INVALID. ;- GETDAT: MOV R1,-(SP) ;SAVE R1 CALL GETDIG ;GET A DIGIT BCS 999$ ;LEAVE IF BAD MUL #10.,R1 ;MULTIPLY BY 10 - HI ORDER DAY MOV R1,R2 ;GET INTO R2 CALL GETDIG ;GET A DIGIT BCS 999$ ;SKIP IF BAD ADD R1,R2 ;ADD IT IN. CMP R2,#31. ;TOO BIG? BHI 999$ ;YES MOV #MONTHS,R3 ;POINT TO THE MONTHS. MOV #12.,R1 ;GET # OF MONTHS. 30$: CMP (R0),(R3)+ ;MATCH? BNE 35$ ;NO CMPB 2(R0),(R3) ;MATCH ON THIRD CHAR? BEQ 40$ ;YES 35$: TST (R3)+ ;SKIP 2 CHARS SOB R1,30$ ;AND LOOP. BR 999$ ;IGNORE THIS FILE -- NO DATE 40$: SUB #13.,R1 ;GET (13-MONTH-13) = -MONTH NEG R1 ;GET THE MONTH ADD #3,R0 ;POINT TO THE YEAR. MUL #40.,R1 ;MAKE MONTH BIGGER THAN DAYS. ADD R1,R2 ;ACCUM INTO THE DATE. CALL GETDIG ;GET HI ORDER YEAR. BCS 999$ ;SKIP IF BAD. MUL #10.,R1 ;MULTIPLY YEAR BY 10. ASH #9.,R1 ;GET INTO RIGHT PLACE. ADD R1,R2 ;ACCUM INTO THE DATE. CALL GETDIG ;GET LOW ORDER YEAR BCS 999$ ;SKIP IF BAD. ASH #9.,R1 ;MAKE INTO RIGHT PLACE. ADD R1,R2 ;ADD IT IN. CALL GETDIG ;GET A DIGIT BCS 999$ ;LEAVE IF BAD. MOV R1,R3 ;MOVE INTO R3 CALL GETDIG ;GET A DIGIT. BCS 999$ ;LEAVE IF BAD MUL #10.,R3 ;MULTIPLY BY 10. ADD R1,R3 ;ADD IT IN CALL GETDIG ;THIRD DIGIT OF TIME BCS 999$ ;BAD DIGIT MUL #10.,R3 ;MULTIPLY BY 10. ADD R1,R3 ;ADD IN NEW DIGIT. CALL GETDIG ;FOURTH AND LAST DIGIT BCS 999$ ;BAD DIGIT MUL #10.,R3 ;MULTIPLY BY 10. ADD R1,R3 ;ADD IN NEW DIGIT. CLC ;CLEAR ERROR RETURN. 998$: MOV (SP)+,R1 ;RECOVER R1 RETURN ;AND RETURN TO CALLER. 999$: SEC ;SET ERROR RETURN BR 998$ ;AND RETURN. GETDIG: MOVB (R0)+,R1 ;GET A DIGIT CMPB R1,#'0 ;A LEGAL DIGIT? BLO 999$ ;NO CMPB R1,#'9 ;ON THE OTHER SIDE? BHI 999$ ;YES -- ILLEGAL SUB #'0,R1 ;MAKE INTO A NUMBER CLC ;CLEAR ERROR RETURN RETURN ;AND RETURN. 999$: SEC ;SET ERROR RETURN RETURN ;AND RETURN TO CALLER. .SBTTL NOTE THAT THIS BLOCK HAS A BAD HEADER ; ; THIS SUBROUTINE NOTES THAT THE HEADER FOR THIS BLOCK IS BAD ; BADHDR: MOV R0,-(SP) ;SAVE R0 MOV R1,-(SP) ;SAVE R1 MOV R2,-(SP) ; MOV R3,-(SP) MOV #HDRMSG,R2 ;SAVE START OF BUFFER PRTMSG: MOV R0,R3 ;REMEMBER BEGINNING OF BUFFER. MOV #BUFFER,R0 ;GET DST ADDR 5$: MOVB (R2)+,(R0)+ ;MOVE IN CHARS BNE 5$ ;LOOP WHILE MORE. DEC R0 ;DECREMENT TO LAST MOVED 0. MOV R5,R1 ;GET REAL NUMBER MOV #1,R2 CALL $CBOMG ; MOVB #'/,(R0)+ MOV H.FNUM(R3),R1 CALL $CBOMG ;BINARY MAGNITUDE MOVB #',,(R0)+ MOV H.FSEQ(R3),R1 CALL $CBOMG ; MOVB #' ,(R0)+ MOVB #' ,(R0)+ MOVB #'[,(R0)+ ;GET UIC MOVB H.PROJ(R3),R1 BIC #^C377,R1 CLR R2 CALL $CBOMG ;CONVERT GROUP CODE MOVB #',,(R0)+ ; MOVB H.PROG(R3),R1 BIC #^C377,R1 CLR R2 CALL $CBOMG MOVB #'],(R0)+ MOV R4,-(SP) ; SAVE R4 MOVB H.IDOF(R3),R4 ;GET HEADER ID OFFSET ASL R4 ;CONVERT TO BYTES ADD R3,R4 ; ABSOLUTISE CLR R2 MOV I.FNAM(R4),R1 ; CALL $C5TA MOV I.FNAM+2(R4),R1 CALL $C5TA MOV I.FNAM+4(R4),R1 CALL $C5TA 10$: CMPB -(R0),#' ;IS IT BLANK? BEQ 10$ ;YES INC R0 ;INC TO NEXT LOCATION. MOVB #'.,(R0)+ MOV I.FTYP(R4),R1 CALL $C5TA ;GET FILE TYPE 20$: CMPB -(R0),#' ;BLANK? BEQ 20$ ;YES INC R0 ; MOV I.FVER(R4),R1 ;GET VERSION # MOV (SP)+,R4 ; RECOVER R4 MOVB #';,(R0)+ CLR R2 ; CALL $CBOSG ;TO OCTAL SUB #BUFFER,R0 TYPE #BUFFER,R0 ;TYPE MESSAGE MOV (SP)+,R3 MOV (SP)+,R2 ;RECOVER R2 MOV (SP)+,R1 MOV (SP)+,R0 RETURN ;AND RETURN .SBTTL NOTE THAT THIS FILE HAS AN ILLEGAL MAX POINTERS ; ; THIS SUBROUTINE NOTES THAT THE FILE HAS AN ILLEGAL MAX # OF ; RETRIEVAL POINTERS. ; MAXHDR: MOV R0,-(SP) MOV R1,-(SP) MOV R2,-(SP) MOV R3,-(SP) MOV #MAXMSG,R2 JMP PRTMSG .SBTTL NOTE THAT THIS FILE HAS AN ILLEGAL STRUCTURE LEVEL ; ; THIS SUBROUTINE NOTES THAT THE FILE HAS AN ILLEGAL STRUCTURE ; LEVEL. THIS NUMBER CAN CHANGE IF FILES-11 IS CHANGED. ; LEVHDR: MOV R0,-(SP) MOV R1,-(SP) MOV R2,-(SP) MOV R3,-(SP) MOV #LEVMSG,R2 JMP PRTMSG .SBTTL NOTE THAT THIS FILE HAS A BAD POINTER ; ; THIS SUBROUTINE NOTES THAT A FILE HAS A BAD INDEX RETRIEVAL ; POINTER VALUE. ; PTRHDR: MOV R0,-(SP) MOV R1,-(SP) MOV R2,-(SP) MOV R3,-(SP) MOV #PTRMSG,R2 JMP PRTMSG .SBTTL NOTE THAT THIS FILE HAS A CHECKSUM ERROR ; ; THIS SUBROUTINE NOTES THAT A FILE HEADER HAS A CHECKSUM ; ERROR. ; CHKHDR: MOV R0,-(SP) MOV R1,-(SP) MOV R2,-(SP) MOV R3,-(SP) MOV #CHKMSG,R2 JMP PRTMSG .SBTTL NOTE THAT THIS FILE HAS A BAD MAP OFFSET ; ; THIS SUBROUTINE NOTES THAT A FILE HAS A BAD MAP AREA OFFSET ; MAPHDR: MOV R0,-(SP) MOV R1,-(SP) MOV R2,-(SP) MOV R3,-(SP) MOV #MAPMSG,R2 JMP PRTMSG .SBTTL NOTE THAT THIS FILE HAS A BAD ID OFFSET ; ; THIS SUBROUTINE NOTES THAT A FILE HAS A BAD ID AREA OFFSET ; BIDHDR: MOV R0,-(SP) MOV R1,-(SP) MOV R2,-(SP) MOV R3,-(SP) MOV #BIDMSG,R2 JMP PRTMSG .SBTTL NOTE THAT THIS FILE HAS A SUSPICIOUS MAP OFFSET ; ; THIS SUBROUTINE NOTES THAT A FILE HAS A 'SUSPICIOUS' MAP OFFSET ; NUMBER. THE 'NORMAL' MAP OFFSET IS 56 (OCTAL), BUT THIS MIGHT ; CHANGE WITH DIFFERENT VERSIONS OF FILES-11 ; NMPHDR: MOV R0,-(SP) MOV R1,-(SP) MOV R2,-(SP) MOV R3,-(SP) MOV #NMPMSG,R2 JMP PRTMSG .SBTTL NOTE THAT THIS FILE HAS A SUSPICIOUS ID OFFSET ; ; THIS SUBROUTINE NOTES THAT A FILE HAS A 'SUSPICIOUS' ID OFFSET ; THE 'NORMAL' OFFSET IS 27, BUT THIS MIGHT CHANGE WITH DIFFERENT ; VERSIONS OF FILES-11 ; NIDHDR: MOV R0,-(SP) MOV R1,-(SP) MOV R2,-(SP) MOV R3,-(SP) MOV #NIDMSG,R2 JMP PRTMSG .SBTTL NOTE THAT THIS FILE HAS AN ILLEGAL BLK-CNT FIELD ; ; THIS SUBROUTINE NOTES THAT THE FILE HAS AN ILLEGAL BLOCK COUNT ; FIELD. ; BCFHDR: MOV R0,-(SP) MOV R1,-(SP) MOV R2,-(SP) MOV R3,-(SP) MOV #BCFMSG,R2 JMP PRTMSG .SBTTL NOTE THAT THIS FILE HAS AN ILLEGAL LBN SIZE ; ; THIS SUBROUTINE NOTES THAT THE FILE HAS AN ILLEGAL VALUE FOR THE ; LBN SIZE FOR THE RETRIEVAL POINTERS ; LBNHDR: MOV R0,-(SP) MOV R1,-(SP) MOV R2,-(SP) MOV R3,-(SP) MOV #LBNMSG,R2 JMP PRTMSG .SBTTL NOTE THAT THIS FILE IS LOCKED ; ; NOTE THAT THE FILE BLOCK IN CORE IS A LOCKED FILE ; DLKHDR: MOV R0,-(SP) MOV R1,-(SP) MOV R2,-(SP) MOV R3,-(SP) MOV #DLKMSG,R2 ; JMP PRTMSG ;PRINT MESSAGE .SBTTL NOTE THAT FILE IS MARKED FOR DELETE ; ; THIS SUBROUTINE NOTES THAT THE FILE HEADER IN CORE IS MARKED FOR ; DELETE ; DELHDR: MOV R0,-(SP) MOV R1,-(SP) MOV R2,-(SP) MOV R3,-(SP) MOV #DELMSG,R2 JMP PRTMSG ;AND PRINT MESSAGE .SBTTL NOTE THAT FILE HAS BAD BLOCK ; ; THIS SUBROUTINE NOTES THAT THE SYSTEM BAD BLOCK IN FILE BIT ; IS SET. ; BLKHDR: MOV R0,-(SP) MOV R1,-(SP) MOV R2,-(SP) MOV R3,-(SP) MOV #BLKMSG,R2 JMP PRTMSG .SBTTL GETBLK - GET BLOCK FROM INDEX FILE ; ; THIS SUBROUTINE GETS A BLOCK FROM THE INDEX FILE. ; ON INPUT, ; ; R0 = BLOCK NUMBER TO RETRIEVE FROM INDEX FILE ; ; ON EXIT, ; ; R0 = ADDRESS OF BUFFER CONTAINING BLOCK ; GETBLK: MOV R1,-(SP) ; SAVE R1 MOV CURBLK,R1 ; GET CURRENT BLOCK CMP R0,R1 ; IS THIS < THE CURRENT BLOCK? BLO 100$ ; J IF SO, MUST READ IN NEW BLOCK. ADD CURCNT,R1 ; ADD IN CURRENT NUMBER OF BLOCKS. CMP R0,R1 ; IS THIS > THE LAST BLOCK? BLO 200$ ; J IF NOT, CAN USE IN CORE BUFFER. 100$: MOV R0,-(SP) ; SAVE R0 FOR FCS CALL MOV R0,R1 ; GET THE BLOCK TO READ. ADD #/1000,R1 ; GET 1+ENDING BLOCK NUMBER. CMP R1,INDEX+F.EFBK+2 ; IS IT TOO LARGE? BLOS 150$ ; J IF NOT. MOV INDEX+F.EFBK+2,R1 ; GET THE LAST BLOCK NO. 150$: mov r0,curblk ; Also remember current block number. SUB R0,R1 ; COMPUTE SIZE (IN BLOCKS) OF BUFFER. MOV R1,CURCNT ; REMEMBER IN CURRENT BUFFER SIZE. ASH #9.,R1 ; COMPUTE SIZE (IN BYTES) OF BUFFER. 160$: mov (sp),index+f.bkvb+2 ; Set the block number. clr index+f.bkvb ; Clear high order block number. READ$ #INDEX,#INDBUF,R1 ; READ IN THE BUFFER. bcs 180$ ; EOF? WAIT$ R0 ; WAIT FOR THE READ TO COMPLETE. bcs 180$ ; EOF? MOV (SP)+,R0 ; RECOVER R0 br 200$ ; And leave. 180$: cmpb #ie.eof,f.err(r0) ; End-of-file? beq 190$ ; J if so. 185$: jmp error ; Error if something worse 190$: sub #1000,r1 ; Reduce buffer size dec curcnt ; Reduce block count beq 185$ ; Gone to 0, report error. br 160$ ; And retry the operation. 200$: SUB CURBLK,R0 ; COMPUTE OFFSET WITHIN BUFFER. ASH #9.,R0 ; COMPUTE BYTE OFFSET WITHIN BUFFER. ADD #INDBUF,R0 ; ABSOLUTISE ADDRESS OF BLOCK MOV (SP)+,R1 ; RECOVER R1 RETURN ; AND RETURN TO THE CALLER. .SBTTL TYPE MESSAGE TO THE TERMINAL ; ; THIS SUBROUTINE TYPES A MESSAGE TO THE TERMINAL ; TYPE: MOV 2(SP),QMSG+Q.IOPL+2 ;LENGTH MOV 4(SP),QMSG+Q.IOPL ;BUFFER ADDRESS MOV #QMSG,-(SP) ;DO I/O CALL .DIRDL ; BCS 10$ ; RETURN ;RETURN TO CALLER 10$: BPT ;ERROR? .SBTTL INDEX FILE BUFFER AREA ; ; THE INDEX FILE IS BUFFERED SEVERAL BLOCKS AT A TIME. ; THIS BUFFER SIZE MAY BE INCREASED BY A TASK BUILD ; EXTENSION OF THE FOLLOWING PSECT. ; .PSECT INDEX1,RW,D INDBUF: .BLKB 20000 ; SPACE FOR 16 INDEX BLOCKS .PSECT INDEX2,RW,D INDEND: ; .SBTTL DATA AREA .PSECT IDATA,RW,D ; ; DATA AREA FOR THE INDEX FILE SCANNER PROGRAM. ; BUFFER: .BLKB 132. ;BUFFER FOR MESSAGES. SPSAVE: .WORD 0 ;SAVE AREA FOR SP FATAL: .WORD 1 ;1= ERROR FATAL, 0=ERROR NON-FATAL IOST: .WORD 0,0 ;IO STATUS BLOCK BITADR: .WORD 0 ;CURRENT BLOCK # OF INDEX FILE BITMAP CURID: .WORD 0 ;CURRENT FILE ID BEING PROCESSED DATE: .WORD 0 ;THE CURRENT DATE TIME: .WORD 0 ;THE CURRENT TIME BITMAP: .BLKB 1000 ;BITMAP BUFFER AREA BITEND: ;END OF BITMAP AREA CURBLK: .WORD 0 ;CURRENT BLOCK ID CURCNT: .WORD 0 ;CURRENT NUMBER OF BLOCKS IN MEMORY HOME: .BLKB 1000 ;HOME BLOCK AREA .NLIST BEX .PSECT PDATA,RO,D HDRMSG: .ASCIZ /AFT -- BAD FILE HEADER FILE / PTRMSG: .ASCIZ /AFT -- BAD RETRIEVAL POINTER / CHKMSG: .ASCIZ /AFT -- HEADER CHECKSUM ERROR FILE / MAPMSG: .ASCIZ /AFT -- BAD MAP OFFSET FILE / BIDMSG: .ASCIZ /AFT -- BAD ID OFFSET FILE / NIDMSG: .ASCIZ /AFT -- SUSPICIOUS ID OFFSET FILE / NMPMSG: .ASCIZ /AFT -- SUSPICIOUS MAP OFFSET FILE / LEVMSG: .ASCIZ /AFT -- ILLEGAL STRUCTURE LEVEL FILE / BCFMSG: .ASCIZ /AFT -- ILLEGAL BLOCK COUNT FILE / LBNMSG: .ASCIZ /AFT -- ILLEGAL LBN SIZE FILE / MAXMSG: .ASCIZ /AFT -- ILLEGAL MAX PTR # FILE / FNDMSG: .ASCIZ /AFT -- BLOCK REFERENCED FILE / DLKMSG: .ASCIZ /AFT -- FILE LOCKED FILE / DELMSG: .ASCIZ /AFT -- FILE MARKED FOR DELETE / BLKMSG: .ASCIZ /AFT -- BAD BLOCK IN FILE / .EVEN M.IOR: MSG M.OPR: MSG M.BIF: MSG M.MDE: MSG M.UNK: MSG M.PS1: MSG M.PS2: MSG M.BAD: MSG M.NODA: MSG M.ILDA: MSG M.INDB: MSG M.INDH: MSG M.UEOF: MSG BLKPR: .ASCII /AFT/ BLKSZ = .-BLKPR .EVEN MONTHS: .ASCII /JAN FEB MAR APR MAY JUN JUL AUG SEP OCT NOV DEC / .LIST BEX .EVEN .PSECT IDATA,RW,D UICFDB: FDBDF$ ;FDB FOR UIC FILE FDAT$A R.VAR,FD.CR FDRC$A ,, ;USE GET/PUT I/O FDOP$A UICLUN,DFNB ; FDBF$A UICEVF INDEX: FDBDF$ ;FDB FOR INDEX FILE FDRC$A FD.RWM ;USE BLOCK IO FDBK$A ,1000,,INDEVF,IOST FDOP$A INDLUN FSRSZ$ 2,2* CMLBLK: GCMLB$ 2,AFT,USRBUF,CMDLUN USRBUF: .BLKB 82. .EVEN CSI$ CSIBLK: .BLKB C.SIZE .EVEN CSISWS: CSI$SW AF,SW.AF,SWORD,SET,,AFSWV CSI$SW CK,SW.CK,SWORD,SET,NEG CSI$SW BI,SW.BI,SWORD,SET,NEG CSI$ND AFSWV: CSI$SV ASCII,DATBUF,DATLEN CSI$ND DATBUF: .BLKB 40. DATLEN = .-DATBUF SW.AF = 000001 ;DATE SWITCH SW.CK = 000002 ;/CK SWITCH - CHECKSUM PRINTER SW.BI = 000004 ;/BI SWITCH - USE BITMAP. SWORD: .WORD 0 QMSG: QIOW$ IO.WVB,MSGLUN,MSGEVF,,IOST,,<0,0,40> DSPT: .WORD DEVLEN,DEVSTR .WORD UICLEN,UICSTR .WORD FILLEN,FILSTR DEVSTR: .ASCII /SY0:/ DEVLEN = .-DEVSTR .EVEN UICSTR: .ASCII /[0,0]/ UICLEN = .-UICSTR .EVEN FILSTR: .ASCII /INDEXF.SYS/ FILLEN = .-FILSTR .EVEN DFNB: NMBLK$ FILES,LST,,SY,0 .END BEGIN