;***************************************************
;
;   CONTXT - displays the contexts of disk blocks
;
;***************************************************
;0.0 05-Jul-84 DFP created by David F. Pallmann.
;0.1 12-Jul-84 DFP comment code;  display help text when cmd line missing.
;0.2 26-Sep-84 DFP correct random file processing.

       SEARCH  SYS
       SEARCH  SYSSYM

       VMINOR=1

       MFDIDX=A4                       ;pointer within current MFD
       MFDCTR=D4                       ;number of UFDs left to scan
       UFDIDX=A3                       ;pointer within current UFD
       UFDCTR=D3                       ;number of files left to scan

       M.NXT=506.                      ;location of forward link in MFD

       .OFINI
       .OFDEF  DISK,D.DDB              ;DDB used to read the disk
       .OFDEF  MFD,512.                ;MFD buffer
       .OFDEF  UFD,512.                ;UFD buffer
       .OFDEF  FILE,512.               ;file buffer
       .OFDEF  BLOCK,4                 ;block number
       .OFDEF  MFDLNK,4                ;link to next MFD block
       .OFDEF  UFDLNK,4                ;link to next UFD block
       .OFDEF  CURPPN,2                ;current PPN
       .OFSIZ  MEMSIZ

;standard set-up

START:  PHDR    -1,0,PH$REE!PH$REU      ;program header
       GETIMP  MEMSIZ,A5               ;allocate local memory

;display help text if no command line present

HELP:   BYP                             ;bypass white space
       LIN                             ;end of line?
       BNE     GETDEV                  ; no
       TYPECR  % usage: .CONTXT Devn: block block ... block
       CRLF                            ;newline
       EXIT                            ;bye

;get device name

GETDEV: BYP                             ;bypass white space on cmd line
       FSPEC   DISK(A5)                ;process device name
       INIT    DISK(A5)                ;load driver, allocate buffer

;get block number
;decimal block numbers must have a trailing decimal point (as in 123.)
;otherwise assumed to be binary (octal or hex)

GETBLK: CTRLC   EXIT                    ;branch on ^C
       BYP                             ;bypass white space
       MOV     A2,A1                   ;save line index
       NUM                             ;digit present?
       JNE     EXIT                    ; no - all done
       GTDEC                           ;get block number (decimal)
       CMPB    (A2)+,#'.               ;is number followed by a decimal?
       BEQ     10$                     ; yes
       MOV     A1,A2                   ; no - back-up line index
       GTOCT                           ;      and treat as octal[hex]
10$:    MOV     D1,BLOCK(A5)            ;store block number
       OCVT    10,OT$TRM!OT$ZER        ;print block number
       TYPESP  :                       ;prettyprinting

;check for label block.
;this is simply block 0.

CHKLBL: TST     BLOCK(A5)               ;block 0?
       BNE     CHKBIT                  ; nope
       TTYL    LABEL                   ;yes, this
       TTYL    NEWLIN                  ; is a label
       JMP     GETBLK                  ;  (that was easy)

;check for bitmap.
;this is block 2-N, where N is the determined by the size of the logical
;device in question.

CHKBIT: CMM     BLOCK(A5),#2            ;block 2 or greater?
       BLT     SETUP                   ; no - isn't bitmap
       MOV     DISK+D.DVR(A5),A0       ;index disk driver
       MOV     24(A0),D0               ;D0 := device block size
       DIV     D0,#512.*8.             ;divide to get bitmap size
       AND     #177777,D0              ;clear remainder
       ADD     #2,D0                   ;add offset of 2
       CMM     BLOCK(A5),D0            ;is this a bitmap block?
       BGT     SETUP                   ; no
       TTYL    BITMAP                  ;yes, tell
       TTYL    NEWLIN                  ; the user
       JMP     GETBLK                  ;  as much

;Time to do a simplified DSKANA;  trace through every file in every
;UFD until we find the block or exhaust the diretory.

SETUP:  MOV     #1,MFDLNK(A5)           ;first block of MFD is always 1

GETMFD: CTRLC   EXIT                    ;branch on ^C
       LEA     MFDIDX,MFD(A5)          ;point to MFD buffer
       MOV     MFDIDX,DISK+D.BUF(A5)   ;change buffer address
       MOV     MFDLNK(A5),DISK+D.REC(A5);set record number to MFD block
       JEQ     NOTUSE                  ;jump if end of disk directory
       READ    DISK(A5)                ;read MFD block to MFD(A5)
       CLR     D0                      ;D0 := next
       MOVW    MFD+M.NXT(A5),D0        ; block link of MFD
       MOV     D0,MFDLNK(A5)           ;store D0
       CMM     DISK+D.REC(A5),BLOCK(A5);block match?
       JEQ     DISMFD                  ; yes
       MOV     #63.,MFDCTR             ; no - set up for 0-63 UFDs

GETPPN: CTRLC   EXIT                    ;branch no ^C
       TST     MFDCTR                  ;end of MFD?
       BEQ     GETMFD                  ; yes - branch
       DEC     MFDCTR                  ;decrement counter
       MOVW    @MFDIDX,CURPPN(A5)      ;store current PPN
       BEQ     GETMFD                  ;branch if zero (end MFD)
       ADD     #10,MFDIDX              ;update MFD index
       CLR     D0                      ;D0 := link
       MOVW    -6(MFDIDX),D0           ; to user file directory
       BEQ     GETPPN                  ;zero is empty directory
       MOV     D0,UFDLNK(A5)           ;store link

GETUFD: CTRLC   EXIT                    ;branch on ^C
       LEA     UFDIDX,UFD(A5)          ;set up
       MOV     UFDIDX,DISK+D.BUF(A5)   ; DDB to read
       MOV     UFDLNK(A5),DISK+D.REC(A5); user file directories
       BEQ     GETPPN                  ;zero is end of UFD
       READ    DISK(A5)                ;read UFD
       CLR     D0                      ;D0 := link
       MOVW    (UFDIDX)+,D0            ; to next UFD
       MOV     D0,UFDLNK(A5)           ;store D0
       CMM     DISK+D.REC(A5),BLOCK(A5);block match?
       JEQ     DISUFD                  ; yes - we have a UFD block
       MOV     #42.,UFDCTR             ;set up to scan 0-42 files

GETFIL: CTRLC   EXIT                    ;branch on ^C
       TST     UFDCTR                  ;end of UFD?
       BEQ     GETUFD                  ; yes - branch
       DEC     UFDCTR                  ;decrement counter
       ADD     #14,UFDIDX              ;update UFD index
       TSTW    -14(UFDIDX)             ;check file entry
       BEQ     GETUFD                  ;  0 is end of UFD
       BMI     GETFIL                  ; -1 is deleted file
       CLR     D0                      ;D0 := first
       MOVW    -2(UFDIDX),D0           ; link of file
       BEQ     GETFIL                  ;branch on empty file
       TSTW    -4(UFDIDX)              ;check file type
       BMI     CHKCTG                  ;branch if contiguous

GETLNK: CTRLC   EXIT                    ;branch on ^C
       CMM     D0,BLOCK(A5)            ;is this our block?
       JEQ     DISFIL                  ; yes - branch
       MOV     D0,DISK+D.REC(A5)       ;set up
       LEA     A0,FILE(A5)             ; DDB to read
       MOV     A0,DISK+D.BUF(A5)       ;  a linked file
       READ    DISK(A5)                ;read block
       CLR     D0                      ;D0 := link
       MOVW    FILE(A5),D0             ; to next block
       JNE     GETLNK                  ;branch if not EOF
       BR      GETFIL                  ;else process next file

CHKCTG: CMM     BLOCK(A5),D0            ;is block in range of file?
       BLO     GETFIL                  ; no - too low
       CLR     D1                      ;D1 := size
       MOVW    -6(UFDIDX),D1           ; of contig. file
       ADD     D1,D0                   ;offset by base link
       CMM     BLOCK(A5),D0            ;is block in range of file?
;       BLOS    DISFIL                  ; yes                           0.2
       BLO     DISFIL                  ; yes                           0.2
       BR      GETFIL                  ; no - keep scannin'

DISMFD: TTYL    MASTER                  ;tell user
       TTYL    FILDIR                  ; that specified block
       TTYL    NEWLIN                  ;  is part of a
       JMP     GETBLK                  ;   Master File Directory

DISUFD: TTYL    USER                    ;tell user
       TTYL    FILDIR                  ; that specified block
       TTYL    FOR                     ;  is part of a
       PRPPN   CURPPN(A5)              ;   User
       TTYL    NEWLIN                  ;    File
       JMP     GETBLK                  ;    Directory

DISFIL: TTYL    LFILE                   ;tell user
       PRNAM   -14(UFDIDX)             ; that specified block
       TYPE    [                       ;  is part of
       PRPPN   CURPPN(A5)              ;   a
       TYPECR  ]                       ;    file
       JMP     GETBLK

NOTUSE: TTYL    NOTINU                  ;tell user that
       JMP     GETBLK                  ; specified block is not in use

EXIT:   CRLF                            ;newline
       EXIT                            ;exit

PAGE
;Text

LABEL:  ASCIZ   /Label/
BITMAP: ASCIZ   /Bitmap/
MASTER: ASCIZ   /Master /
USER:   ASCIZ   /User /
FILDIR: ASCIZ   /File Directory /
LFILE:  ASCIZ   /File /
FOR:    ASCIZ   /for /
NOTINU: ASCIZ   /not in use/
NEWLIN: BYTE    15,0

       END