	.TITLE	CONVERT
	.IDENT	"V1.2"
;
;   Author:	D. Mischler	03-JUL-87
;
;   This module contains the routine for converting
;   a value to ASCII depending on the mode.
;
	.PSECT	RODATA,D,RO
;
;   Control character mnemonic table.
;
CTLTBL:	.RAD50	"NULSOHSTXETXEOTENQACKBEL"
	.RAD50	"BS HT LF VT FF CR SO SI "
	.RAD50	"DLEDC1DC2DC3DC4NAKSYNETB"
	.RAD50	"CANEM SUBESCFS GS RS US "
	.PAGE
	.PSECT	CODE,I,RO
;
;   Subroutine to convert the value in R1 to ASCII (R0)+.
;   The mode and radix determine the type of conversion.
;
C$VALU::
	MOV	R2,-(SP)	; Save volatile registers.
	MOV	R1,-(SP)
	CALL	@CNMODE		; Convert value according to mode.
	MOV	(SP)+,R1	; Recover saved volatile registers.
	MOV	(SP)+,R2
	RETURN

;
;   Convert the value to ASCII.
;
C$ASCI::
	MOV	R1,-(SP)	; Save value.
	CALL	C$ASCB		; Convert low byte to ASCII.
	MOV	(SP)+,R1	; Recover value.
	SWAB	R1		; Position high byte.
C$ASCB::BIC	#177600,R1	; Mask to low 7 bits.
	CMPB	#-1,R1		; Delete character?
	BEQ	20$		; Yes, print mnemonic.
	CMPB	#' ,R1		; Is character printable?
	BHI	30$		; No, print control character mnemonic.
	MOVB	R1,(R0)+	; Buffer character.
	RETURN
;   Buffer delete mnemonic.
20$:	MOV	#^RDEL,R1	; Get RAD50 representation of mnemonic.
	BR	40$		; Dump it.
;   Buffer control character mnemonic.
30$:	ASL	R1		; Produce word offset.
	MOV	CTLTBL(R1),R1	; Get mnemonic in RAD50.
40$:	MOVB	#'<,(R0)+	; Buffer opening mnemonic indicator.
	CALL	C$R50		; Convert mnemonic to ASCII.
	CALL	U$RMTB		; Remove trailing blanks.
	MOVB	#'>,(R0)+	; Buffer closing mnemonic indicator.
	RETURN
	.PAGE

;
;   Convert the value to a numeric byte.
;
C$NUMB::
	JSR	R5,.SAVR1	; Save everything but the output pointer.
	MOVB	R1,R1		; Sign extend byte to a word.
	MOV	NCFLGS,R2	; Get numeric conversion flags.
	BIT	#NC.SGN,R2	; Is conversion signed?
	BNE	10$		; Yes, everything is OK.
	BIC	#177400,R1	; Make sure high byte is clear.
10$:	MOV	R2,R3		; Copy conversion flags.
	ROR	R3		; Divide in half.
	BIC	#100000!<NC.WID-1>,R3 ; Get half of normal field width.
	SUB	R3,R2		; Cut field width to half of normal.
	BR	C.NUM		; Perform conversion and exit.
;
;   Convert the value to a numeric.
;
C$NUM::
	MOV	NCFLGS,R2	; Get numeric conversion flags.
C.NUM:	CALL	$CBTA		; Convert to ASCII numeric representation.
	RETURN

;
;   Convert RAD50 word to ASCII.
;
C$R50::
	MOV	R2,-(SP)	; Save volatile registers for later.
	MOV	R1,-(SP)
	CALL	$C5TA		; Convert RAD50 word to ASCII.
	MOV	(SP)+,R1	; Recover saved registers.
	MOV	(SP)+,R2
	RETURN
	.PAGE
;
;   Convert the value symbolically.
;
C$SYMB::
	MOV	R0,-(SP)	; Save output pointer.
;   If value represents a saved register then use the register name.
	MOV	#REGSYM,R0	; Point to register symbol table head.
	CALL	S$LVAL		; Look up symbol by value, OK?
	BCS	10$		; No, use normal symbolic name.
	CMP	R1,S.VALU(R0)	; Is value exact?
	BEQ	20$		; Yes, convert register name to ASCII.
;   Check value against global symbol table.
10$:	CMP	R1,SYMLOW	; Is value too low to be symbolic?
	BLO	40$		; Yes, convert it numerically.
	CMP	R1,SYMHI	; Is value too high to be symbolic?
	BHI	40$		; Yes, convert it numerically.
	MOV	#SYMTBL,R0	; Point to global symbol table head.
	CALL	S$LVAL		; Is value in table?
	BCS	40$		; No, convert it numerically.
20$:	MOV	R1,-(SP)	; Copy value onto stack.
	SUB	S.VALU(R0),R1	; Produce offset from symbol value.
	CMP	R1,SYMOFF	; Is the offset too high to be useful?
	BLOS	30$		; No, go ahead and use it.
	MOV	(SP)+,R1	; Pop incoming value.
	BR	40$		; Just convert it numerically.
;   Offset is not too high.
30$:	MOV	R1,(SP)		; Save offset on top of stack.
	MOV	S.NAME(R0),R1	; Get first word of RAD50 name.
	MOV	S.NAME+2(R0),-(SP) ; Push second word of name on stack.
	MOV	4(SP),R0	; Recover output pointer.
	CALL	$C5TA		; Convert first word of name to ASCII.
	MOV	(SP)+,R1	; Pop second RAD50 name word.
	CALL	$C5TA		; Convert it too.
	CALL	U$RMTB		; Remove trailing blanks.
	MOV	(SP)+,R1	; Is symbol offset non-zero?
	BEQ	50$		; Yes, conversion is complete.
	MOVB	#'+,(R0)+	; Indicate symbol offset.
	MOV	R0,(SP)		; Save updated output pointer.
40$:	MOV	(SP),R0		; Get output pointer.
	CALL	C$NUM		; Convert numeric value.
50$:	TST	(SP)+		; Remove old output pointer from stack.
	RETURN
	.END
