; JCCHR.MAC -- CHARACTER COMPARE
; AUTHOR:  S. F. HEFFNER
; DATE WRITTEN:  12/2/76
; DATE REVISED:  12/3/76
;                07/14/77 LEN, FOR ASCII CHARACTERS
;		 11/08/77 LEN, MODE 4 UPDATED FOR ASCII
;
	.NLIST	TOC		;TBL OF CONTENTS NOT WANTED
;
	.TITLE	JCCHR
	.SBTTL	CHARACTER COMPARE
; ***DEBUG<
	.ENABL	AMA		;NO PC-REL ADDRS
; ***DEBUG>
;
	.MCALL	SUBR,FRTN
	.MCALL	MINIT,PUSH,POP
	.MCALL	CPARGS,INIWS,RESWS,NMWS,PTWS
;
	MINIT
;
;*	FUNCTION JCCHR  -  STRING CHARACTER COMPARE
;
;	I =  JCCHR(STR1,STCH1,ECH1,STR2,STCH2,ECH2,MODE)
;
;   WHERE:
;	I	= SET BY JCCHR ACCORDING TO MODE (SEE BELOW)
;	STR1,2	= CHAR STRING ADDRS
;	STCH1,2	= STARTING CHAR POSITIONS
;	ECH1,2	= ENDING CHAR POSITIONS (BUT NULL BYTE W/IN
;		    THIS TERMINATES COMPARE)
;	MODE	= MODE OF COMPARE:
;		  MODE 1:  FOR LGTH OF SHORTER STRING,
;		    IF STR1 = STR2,
;		      IF LGTHS SAME, RETURN 2;
;		      IF STR1 SHORTER, RETURN 1;
;		      IF STR1 LONGER, RETURN 4.
;		    IF STR1 < STR2, RETURN 1.
;		    IF STR1 > STR2, RETURN 4.
;		  MODE 2:  FOR LGTH OF SHORTER STRING,
;		    IF STR1 = STR2, RETURN 8.
;		    IF STR1 <> STR2, RETURN 0.
;		  MODE 3:
;		    IF STR2 A SUBSTR OF STR1, RETURN THE STARTING
;		    POSITION IN STR1 WHERE STR2 APPEARS.
;		    IF NOT, RETURN 0.
;		  MODE 4:  DEFINING A DELIMITER AS ANY
;		    ASCII CHAR .NE. (0-9) OR (A-Z)
;		    IF STR2 IS A DELIMITED SUBSTR OF STR1 (DELIMITERS
;		    NOT REQUIRED AT START OR END OF STR1),
;		    RETURN THE STARTING POSITION IN STR1 WHERE
;		    STR2 APPEARS.
;		    IF NOT, RETURN 0.
;		    E.G.,
;			SEARCH FOR 'BUF' IN 'A = BUFF*BUF-1'
;			'BUFF' WILL BE IGNORED AND 'BUF' SELECTED AS
;			IT IS DELIMITED BY '*' AND '-'
;		 	THE STARTING POSITION IS 10
;
;
;
;-
;
	NMWS	<CFLGS,S1A,S1L,S2A,S2L,MODE,A1S>
; NOTE:  NMWS SEQUENCE S1A,...,S2L IS REQUIRED BY SETUP
; CODE BELOW.
;
; FLAGS IN CFLGS:
;
S1H	=	1		;STR1 > STR2
;
	SUBR	JCCHR,7
	MOV	R5,R0		;SAVE ARG PTR
	RESWS	TOTWS/2		;RESERVE WS ON STK
	PTWS			;SET R5 AS WS PTR
	CLR	CFLGS(R5)	;INIT FLAGS
	MOV	#-1,R3		;SET UP 2 STRS
;EBC	MOV	#1,R4		;PREP TO FLIP BYTES
CCHSET:	MOV	(R0)+,S1A(R5)	;GET STR ADDR
	MOV	S1A(R5),A1S(R5)	;SAVE STR1 ADDR FOR MODE 3/4
	MOV	@(R0)+,R1	;GET ST POS
	DEC	R1		;FROM 0, NOT 1
	ADD	R1,S1A(R5)	;NOW ST CHAR ADDR
	MOV	@(R0)+,R2	;GET END POS
	SUB	R1,R2		;NOW STR LGTH
	MOV	R2,S1L(R5)	;SAVE IT
	MOV	S1A(R5),R1	;GET STR ADDR
CCHSLP:
;EBC	XOR	R4,R1		;FLIP BYTE ADDR
	TSTB	(R1)		;NULL BYTE?
	BEQ	CCH1		;IF SO, ENDS STR
;EBC	XOR	R4,R1		;NO, FLIP BACK
	INC	R1		;BUMP TO NEXT CHAR
	SOB	R2,CCHSLP	;END OF GIVEN LGTH?
CCH1:	SUB	R2,S1L(R5)	;CORRECT LGTH
	SUB	#4,R5		;PT TO NEXT STR WS
	INC	R3		;DONE BOTH STRS?
	BEQ	CCHSET		;IF NOT, DO STR2
	ADD	#8.,R5		;YES, RESET WS PTR
	MOV	@(R0)+,MODE(R5)	;GET CMP MODE
	CMP	MODE(R5),#2	;SUBSTR SRCH?
	BGT	CCHM34		;IF SO
	MOV	S1A(R5),R1	;NO, GET STR ADDRS
	MOV	S2A(R5),R2
	MOV	S1L(R5),R3	;USE SHORTER LGTH
	CMP	R3,S2L(R5)	;STR2 SHORTER?
	BLE	CCH2		;IF NOT
	MOV	S2L(R5),R3	;YES, USE STR2 LGTH
	PUSH	#1		;PREP TO FLIP BYTES
	MOV	(SP),R4
CCH2:
;EBC	XOR	R4,R1		;FLIP BYTE ADDRS
;EBC	XOR	R4,R2
	MOVB	(R1),R0		;GET STR1 CHAR
	BIC	#177400,R0	;CLN IT UP
	MOVB	(R2),R4		;GET STR2 CHAR
	BIC	#177400,R4	;CLN IT UP
	CMP	R0,R4		;STR1 : STR2
	BEQ	CCHEQ1		;IF SAME SO FAR
	BLT	CCHNE1		;IF S1 < S2
	BIS	#S1H,CFLGS(R5)	;S1 > S2, REMEM
CCHNE1:	POP			;CLN UP STK
	CMP	MODE(R5),#1	;MODE 2?
	BGT	CCHRT0		;IF SO RTN 0
	BIT	CFLGS(R5),#S1H	;MODE 1, S1>S2?
	BNE	CCHRT4		;IF SO, RTN 4
CCHRT1:	MOV	#1,R0		;S1<S2, RTN 1
CCHRTN:	FRTN			;RTN RSLT IN R0
CCHRT0:	CLR	R0		;NO MATCH, RTN 0
	BR	CCHRTN
CCHRT2:	MOV	#2,R0		;EXACT MATCH, RTN 2
	BR	CCHRTN
CCHRT4:	MOV	#4,R0		;S1>S2, RTN 4
	BR	CCHRTN
CCHRT8:	MOV	#8.,R0		;MATCH FND, RTN 8
	BR	CCHRTN
CHRT34:	SUB	A1S(R5),S1A(R5)	;GET POS WHERE FOUND FOR 3, 4
	MOV	S1A(5),R0	;FUNCTION RETURN
	ADD	#1,R0		;NOT FROM 0
	BR	CCHRTN
CCHEQ1:	MOV	(SP),R4		;FLIP BYTE ADDRS BACK
;EBC	XOR	R4,R1
;EBC	XOR	R4,R2
	INC	R1		;BUMP CHAR PTRS
	INC	R2
	SOB	R3,CCH2		;END OF CMP?
	POP			;YES, CLN UP STK
	CMP	MODE(R5),#2	;MODE 2?
	BEQ	CCHRT8		;IF SO, RTN 8
	CMP	S1L(R5),S2L(R5)	;MODE 1, CMP LGTHS
	BLT	CCHRT1		;IF S1 SHORTER
	BEQ	CCHRT2		;IF SAME LGTH
	BR	CCHRT4		;S1 LONGER
CCHM34:	MOV	#1,R4		;PREP TO FLIP ADDRS
CCH5:	CMP	S1L(R5),S2L(R5)	;ROOM IN S1 FOR MATCH?
	BLT	CCHRT0		;IF NOT, NO MATCH
	MOV	S1A(R5),R1	;YES, GET STR ADDRS
	MOV	S2A(R5),R2
	MOV	S2L(R5),R3	;LGTH TO CMP
CCH6:
;EBC	XOR	R4,R1		;FLIP BYTE ADDRS
;EBC	XOR	R4,R2
	CMPB	(R1),(R2)	;BYTES SAME?
	BNE	CCHNE2		;IF DIFFERENT
;EBC	XOR	R4,R1		;FLIP BYTE ADDRS BACK
;EBC	XOR	R4,R2
	INC	R1		;BUMP TO NEXT CHAR
	INC	R2
	SOB	R3,CCH6		;END OF THIS CMP?
	CMP	MODE(R5),#3	;YES, MODE 3?
	BEQ	CHRT34		;IF SO, RTN 8
	MOV	R1,R2		;END OF S1?
	SUB	S1A(R5),R2
	CMP	R2,S1L(R5)
	BEQ	CHRT34		;IF SO, RTN 8
;EBC	XOR	R4,R1		;NO, GET NEXT CHAR
	JSR	PC,TSTAS	;CHECK FOR SPECIAL CHARS
	CMP	R2,#0		;0 IF SPECIAL
	BEQ	CHRT34		;IF PUNCT, GD MATCH
	BR	CCH7		;NOT PUNCT, NO MATCH
CCHNE2:	CMP	MODE(R5),#3	;MODE 3?
	BGT	CCH7		;IF NOT, MODE 4
	INC	S1A(R5)		;UPDT S1 ADDR
	DEC	S1L(R5)		;UPDT S1 LGTH
	BR	CCH5		;GO TRY AGN
CCH7:	MOV	S1A(R5),R1	;GET S1 ADDR
;EBC	XOR	R4,R1		;FLIP BYTE ORDER
	JSR	PC,TSTAS	;CHECK FOR SPECIAL CHARS
	CMP	R2,#0		;IS IT PUNCT?
	BEQ	CCH8		;IF SO
	INC	S1A(R5)		;NO, UPDT S1 ADDR
	DEC	S1L(R5)		;UPDT S1 LGTH
	BGT	CCH7		;IF NOT S1 END
	BR	CCHRT0		;S1 END, NO MATCH
CCH8:	INC	S1A(R5)		;BUMP PAST PUNCT
	DEC	S1L(R5)		;UPDT S1 LGTH
	BR	CCH5		;GO TRY AGN
;
;TSTAS	- CHECK FOR SPECIAL CHARACTERS
;
TSTAS:	MOVB	(R1),R2		;GET CHARACTER
	BIC	#177400,R2	;CLEAN IT UP
	CMP	R2,#60		;LESS THAN '0' ?
	BLT	PUNCT
	CMP	R2,#71		;GREATER THAN '9' ?
	BLE	RET		;CHAR IS (0-9), RETURN
	BIC	#40,R2		;MAKE IT UPPER CASE FOR TESTING PURPOSES
	CMP	R2,#101		;LESS THAN 'A' ?
	BLT	PUNCT		;YES, THEN PUNCTUATION
	CMP	R2,#132		;GREATER THAN 'Z' ?
	BLE	RET		;CHAR IS (A-Z), RETURN
PUNCT:	CLR	R2		;CLEAR R2 TO INDIC. SPECIAL CHAR
RET:	RTS	PC		;RETURN TO CALLER
;
	.END
