; Figure 5-13
;
;	RSA
;	Return Subprocessor Address
;	This subroutine returns one of several addresses selected
;	from a table by matching keyboard input against
;	specified strings. It is normally used to switch control
;	to a particular subprocessor according to an option entered
;	by the operator from the keyboard.
;
;	Character string comparisons are performed with case-folding,
;	that is lower-case letters are converted to upper-case.
;
;	If the operator input fails to match any of the specified
;	strings, then the Carry flag is set, otherwise it is cleared.
;
;	Entry Parameters
;
;		HL -> Subprocessor Select Table
;			This has the form :
;			DW	TEXT0,SUBPROC0
;			DW	TEXT1,SUBPROC1
;			DW	0	;Terminator
;
;		TEXT0:	DB	'add',0		;00H-byte terminated
;		TEXT1:	DB	'subtract',0
;
;		SUBPROC0:
;			Code for processing ADD function.
;		SUBPROC1:
;			Code for processing SUBTRACT function.
;
;	Exit Parameters
;
;		DE -> operator input string (00H-terminated input string).
;		Carry Clear, HL -> Subprocessor.
;		Carry Set, HL = 0000H.
;
;	Calling Sequence
;
;		LXI	H,SUBPROCTAB	;Subprocessor Table
;		CALL	RSA
;		JC	ERROR		;Carry set only on error
;		LXI	D,RETURN	;Fake CALL instruction
;		PUSH	D		;Push Return address on stack
;		PCHL			;"CALL" to Subprocessor
;	RETURN:
;
B$READCONS	EQU	10	;Read Console String into Buffer
BDOS		EQU	5	;BDOS Entry Point
;
RSA$BL		EQU	80	;Buffer Length
RSA$BUF:	DB	RSA$BL	;Max. no. of characters
RSA$ACTC:	DB	0	;Actual no. of characters
RSA$BUFC:	DS	RSA$BL	;Buffer characters
		DB	0	;Safety terminator
;
;
RSA:
	DCX	H		;Adjust Subproc. pointer for code below
	DCX	H
	PUSH	H		;Top of Stack (TOS) -> Subproc. table - 2
	MVI	C,B$READCONS	;Function Code
	LXI	D,RSA$BUF	;DE -> Buffer
	CALL	BDOS		;Read operator input
			;Convert input to 00H-terminated
	LXI	H,RSA$ACTC	;HL -> Actual no. of chars input
	MOV	E,M		;Get Actual no. of chars input
	MVI	D,0		;Make into word value
	INX	H		;HL -> first data character
	DAD	D		;HL -> first UNUSED character in buffer
	MVI	M,0		;Make input buffer 00H-terminated
			;Compare input to specified values
			;Main loop
RSA$ML:
	POP	H		;Recover subprocessor table pointer
	INX	H		;Move to top of next entry
	INX	H		;HL -> Text Address
	MOV	E,M		;Get text address
	INX	H
	MOV	D,M		;DE -> text

	MOV	A,D		;Check if at end of subproc. table
	ORA	E
	JZ	RSA$NFND	;Match not Found

	INX	H		;HL -> subprocessor address
	PUSH	H		;Save ptr to subprocessor table
	LXI	H,RSA$BUFC	;HL -> input characters
	CALL	FSCMP		;Folded string compare
	JNZ	RSA$ML		;No match, move to next entry
	POP	H		;Match found, recover subproc. ptr
	MOV	E,M		;Get actual subprocessor address
	INX	H
	MOV	D,M		;DE -> Subprocessor code
	XCHG			;HL -> Subprocessor code
	ORA	A		;Clear carry (match found)
	RET
;
RSA$NFND:
	LXI	H,0		;Indicate no match found
	STC			;Set carry
	RET
;
;
;	FSCMP
;	Folded (lower case to upper) string compare.
;	This subroutine compares two 00H-byte terminated
;	strings and returns with the condition flags set
;	to indicate their relationship.
;
;	Entry parameters
;
;		DE -> String 1
;		HL -> String 2
;
;	Exit parameters
;
;		Flags set (based on String1 - String2, on a 
;			   character-by-character basis)
;
;
FSCMP:
	LDAX	D		;Get String 1 character
	CALL	FOLD		;Fold to upper case
	PUSH	PSW		;Save String 1 character
	MOV	A,M		;Get String 2 character
	CALL	FOLD		;Fold to upper case
	MOV	B,A		;Save String 2 character
	POP	PSW		;Recover String 1 character
	CMP	B		;String 1 - String 2
	RNZ			;Return if not equal
	ORA	A		;Equal, so check if end of strings
	RZ			;Yes
	INX	D		;No, update String 1 pointer
	INX	H		;	and String 2 pointer
	JMP	FSCMP		;Check next character
;
;
;	FOLD
;	Folds a lower case letter (a-z) to UPPER CASE (A-Z)
;
;	The character to be folded is in A on entry and on exit.
;
FOLD:
	MOV	C,A		;Preserve input character
	MVI	A,'a'-1		;Check if folding needed
	CMP	C		;Compare to input character
	JNC	FOLDX		;No, char. is <= 'a'
	MVI	A,'z'		;Check if < 'z'
	CMP	C
	JC	FOLDX		;No, char. is > 'z'
	MVI	A,0DFH		;Fold character
	ANA	C
	RET
FOLDX:
	MOV	A,C		;Recover original input char.
	RET
