	.TITLE	EXAMINE
	.IDENT	"V1.2"
;
;   Author:	D. Mischler	10-JUN-87
;
;   This module implements the EXAMINE command.
;

	.PSECT	RODATA,D,RO
;
;   Table of display routines indexed by data type.
;
DSPTBL:	.WORD	D$ADDR		; Address.
	.WORD	D$ASCI		; ASCII.
	.WORD	D$BYTE		; Byte.
	.WORD	D$INST		; Instruction.
	.WORD	D$RD50		; RAD50.
	.WORD	D$WORD		; Word.
DSPLEN	=	<.-DSPTBL>/2
	.PAGE
	.PSECT	CODE,I,RO
;
;   Parse command line and call appropriate display routine.
;
EXAM::	CALL	TRMATT		; Attach the terminal.
	MOV	SINGLE,-(SP)	; Save single value output flag.
	MOV	NCFLGS,-(SP)	; Save default numeric conversion flags.
	MOV	DSPTYP,-(SP)	; Save default display type.
	MOV	CNMODE,-(SP)	; Save default conversion mode.
;   Loop to process qualifiers.
10$:	CALL	U$FNXT		; Find qualifier or address expression, OK?
	BCS	40$		; No, default to last limits.
	CMPB	#'/,-1(R0)	; Was a qualifier found?
	BNE	30$		; No, it must be an address expression.
	MOV	#TYPTBL,R1	; Point to "SET TYPE" keyword table.
	CALL	U$DCOD		; Look up qualifier in table, OK?
	BCS	20$		; No, search "SET MODE" table.
	MOV	R2,DSPTYP	; Set display type.
	BR	10$		; Search for next command element.
;   Qualifier does not specify a type. See if it specifies a mode.
20$:	MOV	#MODTBL,R1	; Point to "SET MODE" keyword table.
	CALL	U$DCOD		; Look up qualifier in table, OK?
	BCS	60$		; No, complain.
	MOV	R0,-(SP)	; Preserve command line pointer.
	CALL	(R2)		; Set specified mode.
	MOV	(SP)+,R0	; Recover command line pointer.
	BR	10$		; Search for next command element.
;   Process address expression(s).
30$:	CALL	XPRESS		; Evaluate address expression, OK?
	BCS	60$		; No, complain.
	MOV	R1,EXASTA	; Save start address.
	MOV	R1,EXAEND	; Assume no end address.
	CMPB	#':,(R0)	; Does an end address follow?
	BNE	40$		; No, don't worry about it.
	INC	R0		; Skip over colon.
	CALL	XPRESS		; Evaluate end address expression, OK?
	BCS	60$		; No, complain.
	MOV	R1,EXAEND	; Save end address.
;   Display data for the current range.
40$:	MOV	R0,-(SP)	; Preserve command line pointer.
	MOV	DSPTYP,R0	; Get display type code.
	DEC	R0		; Change index origin to zero.
	CMP	R0,#DSPLEN	; Is type code a legal value?
	BHIS	50$		; No, complain.
	ASL	R0		; Make display type a word index.
	CALL	@DSPTBL(R0)	; Display the requested memory contents.
	MOV	(SP)+,R0	; Recover command line pointer.
	CMPB	#',,(R0)+	; Does another address expression follow?
	BEQ	30$		; Yes, take care of it.
	BR	70$		; Exit.
	.PAGE
;
;   Here if an illegal display type value is encountered.
;
50$:	MOV	#E.ICCF,R1	; Point to error message.
;
;   Here if an error is detected.
;
60$:	CALL	ERROR		; Display appropriate error message.
70$:	MOV	(SP)+,CNMODE	; Restore default conversion mode.
	MOV	(SP)+,DSPTYP	; Restore default display type.
	MOV	(SP)+,NCFLGS	; Restore default numeric conversion flags.
	MOV	(SP)+,SINGLE	; Restore single value output flag.
	CALLR	TRMDET		; Detach the terminal and return.
	.PAGE
;
;   Display ASCII type.
;
D$ASCI:	MOV	#5,R3		; Get maximum representation length.
	MOV	#C$ASCB,R4	; Point to conversion routine.
	BR	D.BYTE		; Display bytes.
;
;   Display BYTE type.
;
D$BYTE:	MOV	NCFLGS,R3	; Get numeric conversion flags.
	CLC			; Perform a logical shift right.
	ROR	R3
	ASH	#-11.,R3	; Put half of field width in low bits.
	ADC	R3		; Bias resulting width upwards.
	MOV	#C$NUMB,R4	; Point to conversion routine.
D.BYTE:
	MOV	R3,-(SP)	; Save maximum repesentation length on stack.
	MOV	#TRMBUF+78.,R3	; Get end of line pointer.
	SUB	(SP)+,R3	; Produce maximum line pointer.
	MOV	EXASTA,R5	; Get start address.
10$:	MOV	#TRMBUF,R0	; Point to terminal I/O buffer.
	CALL	U$ADDR		; Buffer the address.
15$:	CALL	M$RDB5		; Fetch a byte, OK?
	BCC	20$		; Yes, convert it.
	CALL	EXAERR		; Indicate error condition.
	BR	30$		; Output line and terminate.
;   Convert the byte fetched.
20$:	INC	R5		; Increment address.
	CALL	(R4)		; Convert byte appropriately.
	CMP	R5,EXAEND	; Hit end point?
	BHI	30$		; Yes, stop now.
	TST	SINGLE		; In single value mode?
	BNE	30$		; No, dump the line.
	CMP	R0,R3		; Is there room for another byte?
	BHI	30$		; No, dump the line.
	CMP	#C$ASCB,R4	; Is this ASCII data?
	BEQ	15$		; Yes, don't separate it.
	MOVB	#' ,(R0)+	; Separate data.
	BR	15$
;   Output the line.
30$:	CLRB	(R0)		; Terminate output buffer.
	MOV	#TRMBUF,R1	; Point to formatted data.
	CALL	LINOUT		; Output the line.
	TST	MCRDEB		; Has an MCR DEBUG command been received?
	BNE	40$		; Yes, cease and desist.
	CMP	R5,EXAEND	; Hit end point?
	BLOS	10$		; No, continue.
40$:	RETURN
	.PAGE
;
;   Display ADDRESS type.
;
D$ADDR:	MOV	NCFLGS,R3	; Get numeric conversion flags.
	ASH	#-11.,R3	; Position field width.
	BIC	#^C<37>,R3	; Mask to field width.
	ADD	#7,R3		; Account for symbol name and plus sign.
	MOV	#C$SYMB,R4	; Point to conversion routine.
	BR	D.WORD
;
;   Display RAD50 type.
;
D$RD50:	MOV	#3,R3		; Get maximum length of representation.
	MOV	#C$R50,R4	; Point to conversion routine.
	BR	D.WORD
;
;   Display WORD type.
;
D$WORD:	MOV	NCFLGS,R3	; Get numeric conversion flags.
	ASH	#-11.,R3	; Position field width.
	BIC	#^C<37>,R3	; Mask to field width.
	MOV	#C$NUM,R4	; Point to conversion routine.
D.WORD:
	MOV	R3,-(SP)	; Save maximum repesentation length on stack.
	MOV	#TRMBUF+78.,R3	; Get end of line pointer.
	SUB	(SP)+,R3	; Produce maximum line pointer.
	MOV	EXASTA,R5	; Get start address.
10$:	MOV	#TRMBUF,R0	; Point to terminal I/O buffer.
	CALL	U$ADDR		; Buffer the address.
15$:	CALL	M$RD5P		; Fetch a word, OK?
	BCC	20$		; Yes, convert it.
	CALL	EXAERR		; Indicate error condition.
	BR	30$		; Output line and terminate.
;   Convert the byte fetched.
20$:	CALL	(R4)		; Convert byte appropriately.
	CMP	R5,EXAEND	; Hit end point?
	BHI	30$		; Yes, stop now.
	TST	SINGLE		; In single value mode?
	BNE	30$		; No, dump the line.
	CMP	R0,R3		; Is there enough room for another word?
	BHI	30$		; No, dump the line.
	MOVB	#' ,(R0)+	; Separate the data.
	BR	15$
;   Output the line.
30$:	CLRB	(R0)		; Terminate output buffer.
	MOV	#TRMBUF,R1	; Point to formatted data.
	CALL	LINOUT		; Output the line.
	TST	MCRDEB		; Has an MCR DEBUG command been received?
	BNE	40$		; Yes, cease and desist.
	CMP	R5,EXAEND	; Hit end point?
	BLOS	10$		; No, continue.
40$:	RETURN
	.PAGE
;
;   Display instruction type.
;
D$INST:	MOV	EXASTA,R5	; Get start address.
10$:	MOV	#TRMBUF,R0	; Point to terminal I/O buffer.
	CALL	U$ADDR		; Buffer the address.
	CALL	DISASM		; Disassemble an instruction.
	ROR	R4		; Pick up disassembly status.
	CLRB	(R0)		; Terminate output buffer.
	MOV	#TRMBUF,R1	; Point to disassembled instruction.
	CALL	LINOUT		; Output the instruction.
	ROL	R4		; Did disassembly fail?
	BCS	20$		; Yes, stop this farce.
	TST	MCRDEB		; Has an MCR DEBUG command been received?
	BNE	20$		; Yes, cease and desist.
	CMP	R5,EXAEND	; Hit end point?
	BLOS	10$		; No, continue.
20$:	RETURN

;
;   Subroutine to indicate a memory read error condition.
;
EXAERR:	MOV	R5,EXAEND	; Force early termination.
	DEC	EXAEND
	MOVB	#'<,(R0)+	; Indicate addressing problem.
	MOVB	#'?,(R0)+
	MOVB	#'>,(R0)+
	RETURN

	.END
