;***************************************************
;
;   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