Google
 

Trailing-Edge - PDP-10 Archives - decuslib20-02 - decus/20-0057/sddpat.mac
There are 2 other files named sddpat.mac in the archive. Click here to see a list.
	TITLE	S$$PAT PATTERN ROUTINES
	SUBTTL	S$$ARB 'ARB' PATTERN PRIMITIVE ROUTINE

	ENTRY	S$$ARB
	EXTERN	S$$KWD
	RADIX	10
	SEARCH	S$$NDF

	COMMENT/
CALL:	PUSHJ	PS,S$$ARB	; SAVES RETURN LINK ON PS/

S$$ARB:	PUSH	PS,CR	; SAVE CURSOR
	PUSH	PS,RC	; SAVE REM CHARS
	PUSHJ	PS,@-2(PS)	; SAVE ARBRST AND RETURN

; ARB RESTARTED
ARBRST:	SKIPN	S$$KWD+10	; IS &FULLSCAN ON?
	JUMPL	RC,ARBFAL	; NO, QUICKSCAN, FAIL IF CHARFAIL ON
	SOSGE	RC,(PS)	; RESTORE AND DECREMENT RC
	JRST	ARBFAL	; FAIL IF < 0
	IBP	-1(PS)	; INCREMENT CR
	MOVE	CR,-1(PS)	; AND RESTORE
	AOBJN	PS,@-2(PS)	; SIMULATE PUSH OF ARBRST AND CONTINUE

; ARB FAILED
ARBFAL:	SUB	PS,[XWD 3,3]	; POP PS 3 LEVELS
	POPJ	PS,	; GO TO NEXT PREVIOUS RESTART
	PRGEND
	SUBTTL	S$$BAL 'BAL' PATTERN PRIMITIVE ROUTINE

	ENTRY	S$$BAL
	RADIX	10
	SEARCH	S$$NDF

	COMMENT/
CALL:	PUSHJ	PS,S$$BAL	; SAVES RETURN LINK ON PS/

S$$BAL:	ADD	PS,[XWD 2,2]	; SIMULATE 2-LEVEL PUSH
	JUMPGE	PS,FIXPS	; BUT PUSH INSTEAD IF TOO DEEP
	SETZ	R1,	; INITIALIZE PAREN LEVEL
BALOOP:	SOJL	RC,BALFAL	; DECREMENT RC, FAIL IF <O
	ILDB	R0,CR	; INCREMENT CR, GET CHAR
	CAIN	R0,")"	; IS IT A RIGHT PAREN?
	JRST	RPAR	; YES
	CAIN	R0,"("	; NO, IS IT A LEFT PAREN?
	AOJA	R1,BALOOP	; YES, INCREASE PAREN LEVEL AND LOOP
BALCOM:	JUMPN	R1,BALOOP	; NO, OTHER, LOOP IF PAREN LEVEL > 0
	MOVEM	CR,-1(PS)	; SUCCEED, SAVE CR
	MOVEM	RC,(PS)	; AND SAVE RC
	PUSHJ	PS,@-2(PS)	; SAVE BALRST AND RETURN

; BAL RESTARTED
BALRST:	MOVE	CR,-1(PS)	; RESTORE CR
	MOVE	RC,(PS)	; RESTORE RC
	JRST	BALOOP-1	; START LOOP AGAIN

; RIGHT PAREN ENCOUNTERED
RPAR:	SOJGE	R1,BALCOM	; DECREMENT PAREN LEVEL, AND CONTINUE

; BAL FAILED
BALFAL:	SUB	PS,[XWD 3,3]	; OR FAIL (UNMATCHED ")"), POP PS 3 LEVELS
	POPJ	PS,	; GO TO NEXT PREVIOUS RESTART

; PUSH PS 2 LEVELS
FIXPS:	SUB	PS,[XWD 2,2]	; RESET PS
	PUSH	PS,CR	; AND PUSH NORMALLY
	PUSH	PS,RC
	JRST	BALOOP-1	; GO START LOOP
	PRGEND
	SUBTTL	S$$SUC 'SUCCEED' PATTERN PRIMITIVE ROUTINE

	ENTRY	S$$SUC
	RADIX	10
	SEARCH	S$$NDF

	COMMENT/
CALL:	PUSHJ	PS,S$$SUC	; SAVES RETURN LINK ON PS/

S$$SUC:	PUSH	PS,CR	; SAVE CURSOR
	PUSH	PS,RC	; SAVE REM CHARS
	PUSHJ	PS,@-2(PS)	; SAVE SUCRST AND RETURN

; SUCCEED RESTARTED
SUCRST:	MOVE	CR,-1(PS)	; RESTORE CURSOR
	MOVE	RC,(PS)	; RESTORE REM CHARS
	AOBJN	PS,@-2(PS)	; SAVE SUCRST AND RETURN
	PRGEND
	SUBTTL	S$$REM 'REM' PATTERN PRIMITIVE ROUTINE

	ENTRY	S$$REM
	EXTERN	S$$LEN
	RADIX	10
	SEARCH	S$$NDF

	COMMENT/
CALL:	JSP	R9,S$$REM	; SIMULATES LEN(RC)/

S$$REM:	MOVEI	R1,(RC)	; LEN() OF REMAINING CHARS
	JRST	S$$LEN
	PRGEND
	SUBTTL	S$$MIP,S$$MID,S$$MIE POSITIVE INTEGER ASSURANCE ROUTINES

	ENTRY	S$$MIP,S$$MID,S$$MIE
	EXTERN	S$$PGL,S$$MKI
	RADIX	10
	SEARCH	S$$NDF

	COMMENT/
	MAKE POSITIVE INTEGER DESCRIPTOR FROM INTEGER
CALL:	JSP	R9,S$$MIP	; WITH INTEGER IN R1, RETURNS DESCR
IN R1
	MAKE POSITIVE INTEGER DESCRIPTOR FROM DESCRIPTOR
CALL:	JSP	R9,S$$MID	; WITH DESCRIPTOR IN R1, RETURNS INTEGER
DESCR IN R1
	NEGATIVE INTEGER ERROR
CALL:	JRST	S$$MIE/

S$$MID:	SETZ	R2,	; GET TYPE
	ROTC	R1,2
	CAIE	R2,2	; IS IT INTEGER?
	JRST	MAKINT	; NO, MAKE INTEGER
	ROTC	R1,-2	; RESTORE DESCR
	TLNN	R1,1B20	; IS INTEGER <0 ?
	JRST	(R9)	; NO, RETURN
S$$MIE:	MOVEM	R9,S$$PGL	; YES, ERROR
	CFERR	14,S$$PGL	; NEGATIVE INTEGER IN WRONG CONTEXT
MAKINT:	ROTC	R1,-2	; RESTORE DESCR
	JSP	R7,S$$MKI	; MAKE INTEGER
	JRST	TYPERR	; TYPE ERROR
S$$MIP:	JUMPL	R1,S$$MIE	; ERROR IF <0
	TLO	R1,1B18	; FORM DESCR
	JRST	(R9)	; AND RETURN
TYPERR:	MOVEM	R9,S$$PGL	; SAVE LINK
	CFERR	1,S$$PGL	; ERROR EXIT
	PRGEND
	SUBTTL	S$$LEN,S$$TAB,S$$RTB 'LEN','TAB','RTAB' PATTERN PRIMITIVES

	ENTRY	S$$LEN,S$$TAB,S$$RTB
	EXTERN	S$$SJC
	RADIX	10
	SEARCH	S$$NDF

	COMMENT/
CALL:	JSP	R9,S$$LEN[S$$TAB,S$$RTB]	; WITH INTEGER ARG IN R1/

S$$TAB:	HRRZ	R2,@S$$SJC	; GET TOTAL CHARS
	SUBI	R2,(R1)	; SUBTRACT TAB CHARS
	MOVE	R1,R2	; PUT NEW REM CHARS IN R1
S$$RTB:	CAILE	R1,(RC)	; IS NEW RC > OLD RC?
	POPJ	PS,	; YES, ATTEMPT TO BACKUP CURSOR, FAIL
	EXCH	R1,RC	; SET NEW RC
	SUBI	R1,(RC)	; COMPUTE # CHARS TO BE ADVANCED
	JUMPGE	RC,MOVECR	; GO ADVANCE CURSOR IF RC IS NOT < 0
NEGRCF:	POPJ	PS,	; OR FAIL, OFF END OF SUBJECT
S$$LEN:	SUBI	RC,(R1)	; COMPUTE NEW REM CHARS
	JUMPL	RC,NEGRCF	; FAIL IF < 0
MOVECR:	JUMPE	R1,(R9)	; SUCCEED IMMEDIATELY IF MOVEMENT = 0
	MUL	R1,POINT2	; COMPUTE # OF WHOLE WORDS
	ROT	R2,4	; AND REMAINING CHAR INDEX
	XCT	CHNGCR-1(R2)	; PERFORM INCREMENTATION OF CR
	JRST	(R9)	; AND RETURN
CHNGCR:	JRST	ONECHR	; REM=1, 1 CHR
POINT2:	^O63146300000	; REM=2, IMPOSSIBLE, USE SPACE
	JRST	TWOCHR	; REM=3, 2 CHR
	JRST	THRCHR	; REM=4, 3 CHR
	JFCL		; REM=5, IMPOSSIBLE
	JRST	FOUCHR	; REM=6, 4 CHR
	ADDI	CR,1(R1)	; REM=7, 5 CHR
FOUCHR:	IBP	CR	; 4
THRCHR:	IBP	CR	; 3
TWOCHR:	IBP	CR	; 2
ONECHR:	IBP	CR	; 1
	ADDI	CR,(R1)	; ADD WHOLE WORDS
	JRST	(R9)	; AND RETURN
	PRGEND
	SUBTTL	S$$MBT MAKE BREAK TABLE ROUTINE

	ENTRY	S$$MBT
	EXTERN	S$$PGL,S$$LKS,S$$BKT,S$$GNS
	RADIX	10
	SEARCH	S$$NDF

	COMMENT/
CALL:	JSP	R9,S$$MBT	; WITH DESCRIPTOR IN R1, OLDPTR IS POIN-
	OLDPTR	; TER TO PREVIOUS BREAK TABLE SYMBOL TABLE ENTRY (KEY
WORD). RETURN BREAK TABLE DESCRIPTOR (FAKE STRING DESCR) IN R1/

S$$MBT:	MOVE	R2,(R9)	; GET OLDPTR
	CAME	R1,(R2)	; COMPARE STRING WITH OLD STRING
	JRST	LKPMBT	; NOT =, LOOKUP
	MOVE	R1,1(R2)	; GET OLD BREAK TABLE DESCR
	JRST	1(R9)	; RETURN
LKPMBT:	MOVEM	R9,S$$PGL	; SAVE PROGRAM LINK
	HRLZI	R0,9B22	; T=9 FOR BREAK TABLE LOOKUP
	JSP	R8,S$$LKS	; DO LOOKUP
	SOJA	R2,LKPFND	; SYMBOL FOUND
	SETZ	R0,	; NEW ENTRY, GET CHAR COUNT
	HRRZ	R8,(R1)
	MOVE	R7,R1	; SAVE STRING DESCR
	HRRM	R2,GETR2	; AND SYMBOL TABLE ENTRY POINTER
	MOVEI	R0,4	; GET BLOCK FOR BREAK TABLE
	JSP	R6,S$$GNS
	HRLI	R1,^O700	; FAKE STRING DESCR
	MOVEM	R1,@GETR2	; SAVE IN VALUE LOC OF ENTRY
	MOVEI	R0,1	; BIT MARK
	MOVEI	R1,R3	; TEMPORARY TABLE POINTER
	SETZB	R3,R4	; CLEAR TEMP TABLE
	SETZB	R5,R6
	JUMPE	R8,.+4	; SKIP IF 0 CHARS
MBTLOP:	ILDB	R2,R7	; GET NEXT CHAR
	DPB	R0,S$$BKT(R2)	; SET BIT IN TABLE
	SOJG	R8,MBTLOP	; LOOP FOR EACH CHAR
GETR2:	MOVEI	R2,.-.	; RESTORE ENTRY PTR
	MOVE	R1,(R2)	; RESTORE BREAK TABLE POINTER
	HRRM	R3,(R1)	; SAVE BITS IN REAL TABLE
	MOVEM	R4,1(R1)
	MOVEM	R5,2(R1)
	MOVEM	R6,3(R1)
	SOJA	R2,.+2	; PTR TO KEY WORD OF ENTRY
LKPFND:	MOVE	R1,1(R2)	; GET BREAK TABLE DESCR
	MOVEM	R2,(R9)	; SAVE NEW OLDPTR IN CALLING SEQUENCE
	JRST	1(R9)	; AND RETURN
	PRGEND
	SUBTTL	S$$ANY,S$$NTA 'ANY','NOTANY' PATTERN PRIMITIVES

	ENTRY	S$$ANY,S$$NTA
	EXTERN	S$$BKT
	RADIX	10
	SEARCH	S$$NDF

	COMMENT/
CALL:	JSP	R9,S$$ANY[S$$NTA]	; WITH BREAK TABLE POINTER IN R1/

S$$ANY:	JSP	R8,S$$NTA+1	; ANY, INDEX=0
S$$NTA:	JSP	R8,S$$NTA+1	; NOTANY, INDEX=1
	SUBI	R8,S$$NTA
	SOJGE	RC,.+2	; DECREMENT RC
	POPJ	PS,	; OR FAIL IF NO MORE CHARS
	ILDB	R2,CR	; GET CHAR
	LDB	R0,S$$BKT(R2)	; GET BREAK BIT
	CAIE	R0,(R8)	; IS INDEX=BREAK BIT ?
	JRST	(R9)	; NO, SUCCEED
	POPJ	PS,	; YES, FAIL
	PRGEND
	SUBTTL	S$$SPN,S$$NSP 'SPAN','NSPAN' PATTERN PRIMITIVES

	ENTRY	S$$SPN,S$$NSP
	EXTERN	S$$BKT
	RADIX	10
	SEARCH	S$$NDF

	COMMENT/
CALL:	JSP	R9,S$$SPN[S$$NSP]	; WITH BREAK TABLE POINTER IN R1/

S$$SPN:	SOJGE	RC,.+2	; DECREMENT RC
	POPJ	PS,	; FAIL IF NO MORE CHARS (MUST MATCH AT LEAST 1)
	ILDB	R2,CR	; GET CHAR
	LDB	R0,S$$BKT(R2)	; GET BREAK BIT
	JUMPN	R0,S$$NSP	; CONTINUE IF ON
	POPJ	PS,	; OR FAIL
S$$NSP:	SOJGE	RC,.+2	; DECREMENT RC
	AOJA	RC,(R9)	; SUCCEED IF NO MORE CHARS
	MOVE	R8,CR	; SAVE CURSOR IN CASE OF BACKUP
	ILDB	R2,CR	; GET CHAR
	LDB	R0,S$$BKT(R2)	; GET BREAK BIT
	JUMPN	R0,S$$NSP	; LOOP IF ON
	MOVE	CR,R8	; OR BACKUP 1 CHAR
	AOJA	RC,(R9)	; AND SUCCEED
	PRGEND
	SUBTTL	S$$BRX 'BREAKX' PATTERN PRIMITIVE

	ENTRY	S$$BRX
	EXTERN	S$$BRK
	RADIX	10
	SEARCH	S$$NDF

	COMMENT/
CALL:	JSP	R9,S$$BRX	; WITH BREAK TABLE PTR IN R1/

S$$BRX:	HRRM	R9,BEGBRX	; SAVE LINK
	JSP	R9,S$$BRK	; DO BREAK
BEGBRX:	MOVEI	R9,.-.	; RESTORE LINK
	PUSH	PS,CR	; SAVE CURSOR
	PUSH	PS,RC	; SAVE REM CHARS
	PUSH	PS,R1	; SAVE BREAK TABLE POINTER
	PUSH	PS,R9	; SAVE LINK
	PUSHJ	PS,(R9)	; SAVE BRXRST AND RETURN

; BREAKX RESTARTED
BRXRST:	SOS	RC,-2(PS)	; GET REM CHARS AND DECREMENT
	MOVE	CR,-3(PS)	; GET CURSOR
	IBP	CR	; AND INCREMENT
	MOVE	R1,-1(PS)	; GET BREAK TABLE POINTER
	SUB	PS,[XWD 4,4]	; RESET PS
	JSP	R9,S$$BRK	; DO BREAK
	ADD	PS,[XWD 5,5]	; SET PS TO RESTART
	MOVEM	CR,-4(PS)	; SAVE NEW CURSOR
	MOVEM	RC,-3(PS)	; SAVE NEW REM CHARS
	JRST	@-1(PS)	; AND RETURN
	PRGEND
	SUBTTL	S$$BRK 'BREAK' PATTERN PRIMITIVE

	ENTRY	S$$BRK
	EXTERN	S$$BKT
	RADIX	10
	SEARCH	S$$NDF

	COMMENT/
CALL:	JSP	R9,S$$BRK	; WITH BREAK TABLE POINTER IN R1/

S$$BRK:	SOJGE	RC,.+2	; DECREMENT RC
	POPJ	PS,	; OR FAIL IF NO MORE CHARS (MUST FIND BREAK CHAR)
	MOVE	R8,CR	; SAVE CURSOR IN CASE OF BACKUP
	ILDB	R2,CR	; GET CHAR
	LDB	R0,S$$BKT(R2)	; GET BREAK BIT
	JUMPE	R0,S$$BRK	; LOOP IF NOT ON
	MOVE	CR,R8	; BACKUP CURSOR
	AOJA	RC,(R9)	; AND SUCCEED
	PRGEND
	SUBTTL	S$$BRQ 'BREAKQ' PATTERN PRIMITIVE

	ENTRY	S$$BRQ
	EXTERN	S$$BKT
	RADIX	10
	SEARCH	S$$NDF

	COMMENT/
CALL:	JSP	R9,S$$BRQ	; WITH BREAK TABLE POINTER IN R1.
IF SINGLE (') OR DOUBLE (") QUOTES ARE MEMBERS OF THE CHARACTER CLASS,
THEY ARE IGNORED/

S$$BRQ:	SOJGE	RC,.+2	; DECREMENT RC
	POPJ	PS,	; OR FAIL IF NO MORE CHARS
	MOVE	R8,CR	; SAVE CURSOR IN CASE OF BACKUP
	ILDB	R2,CR	; GET CHAR
	CAIE	R2,"'"	; IS IT SINGLE OR DOUBLE QUOTE?
	CAIN	R2,^O42
	JRST	GOBLQT	; YES, GO GOBBLE UP QUOTED SECTION
	LDB	R0,S$$BKT(R2)	; NO, GET BREAK BIT
	JUMPE	R0,S$$BRQ	; LOOP IF NOT ON
	MOVE	CR,R8	; BACKUP CURSOR
	AOJA	RC,(R9)	; AND RETURN SUCCESSFULLY

; GOBBLE UP QUOTED SUBSTRING
GOBLQT:	SOJGE	RC,.+2	; DECREMENT RC
	POPJ	PS,	; FAIL IF NO MORE CHARS
	ILDB	R0,CR	; GET CHAR
	CAIE	R0,(R2)	; IS IT CLOSING QUOTE?
	JRST	GOBLQT	; NO, LOOP
	JRST	S$$BRQ	; YES, GO BACK TO REGULAR LOOP
	PRGEND
	SUBTTL	S$$RBS,S$$RBR 'ARBNO' PATTERN PRIMITIVE

	ENTRY	S$$RBS,S$$RBR
	EXTERN	S$$KWD
	RADIX	10
	SEARCH	S$$NDF

	COMMENT/
	ARBNO START
CALL:	JSP	R9,S$$RBS	; WITH LOC FOLLOWING ARBNO IN R1, START
OF PATTERN ARG AT (R9)
	ARBNO RESTART
CALL:	JSP	R9,S$$RBR	; IMMEDIATELY FOLLOWING PATTERN ARG/

S$$RBS:	PUSH	PS,R9	; SAVE START OF PATTERN ARG
	PUSH	PS,CR	; SAVE CURSOR
	PUSH	PS,RC	; SAVE REM CHARS
	PUSHJ	PS,(R1)	; SAVE RBRST1 AND SKIP OVER PATTERN ARG FIRST TIME

; FIRST ARBNO RESTART
RBRST1:	SUB	PS,[XWD 3,3]	; RESET PS
	JUMPGE	RC,.+2	; CHARFAIL SET?
	POPJ	PS,	; YES, FAIL
	MOVE	CR,2(PS)	; RESTORE CURSOR
	MOVE	RC,3(PS)	; RESTORE REM CHARS
	PUSH	AS,1(PS)	; SAVE START OF PATTERN ARG
	SKIPN	S$$KWD+10	; IS &FULLSCAN ON?
	PUSH	AS,RC	; NO, QUICKSCAN, SAVE REM CHARS
	PUSHJ	PS,@1(PS)	; SAVE RBRST2 AND START PATTERN ARG

; FIRST FAILURE OF PATTERN ARG
RBRST2:	SKIPN	S$$KWD+10	; IS &FULLSCAN ON?
	SUB	AS,[XWD 1,1]	; NO, QUICKSCAN, POP AS EXTRA TIME
	SUB	AS,[XWD 1,1]	; POP AS
	POPJ	PS,	; FAIL

; PATTERN ARG SUCCEEDED
S$$RBR:	SKIPE	S$$KWD+10	; IS &FULLSCAN OFF (QUICKSCAN MODE)?
	JRST	RBRFLS	; NO, SKIP
	CAMN	RC,(AS)	; YES, HAS CURSOR MOVED?
	POPJ	PS,	; NO, RESTART PATTERN ARG
	PUSH	PS,(AS)	; SAVE OLD RC, THIS INSTANCE OF ARG MAY BE RESTARTED
	SUB	AS,[XWD 1,1]	; AND POP AS
RBRFLS:	SUB	AS,[XWD 1,1]	; POP START OF PATTERN ARG OFF AS
	PUSH	PS,1(AS)	; AND SAVE ON PS
	PUSH	PS,CR	; SAVE CURSOR
	PUSH	PS,RC	; SAVE REM CHARS
	PUSHJ	PS,(R9)	; SAVE RBRST3 AND SUCEEDED ARBNO

; SUBSEQUENT ARBNO RESTARTS
RBRST3:	SUB	PS,[XWD 3,3]	; RESET PS
	JUMPGE	RC,RBRNEW	; JUMP IF CHARFAIL NOT SET
	PUSH	AS,1(PS)	; SAVE START OF PATTERN ARG
	SKIPE	S$$KWD+10	; IS &FULLSCAN ON?
	JRST	.+3	; YES, SKIP
	SUB	PS,[XWD 1,1]	; NO, QUICKSCAN, POP OLD RC OFF PS
	PUSH	AS,1(PS)	; AND SAVE ON AS
	POPJ	PS,	; FAIL TO NEXT PREVIOUS RESTART OF PATTERN ARG
RBRNEW:	MOVE	CR,2(PS)	; RESTORE CURSOR
	MOVE	RC,3(PS)	; RESTORE REM CHARS
	PUSH	AS,1(PS)	; SAVE START OF PATTERN ARG
	SKIPN	S$$KWD+10	; IS &FULLSCAN ON?
	PUSH	AS,RC	; NO, QUICKSCAN, SAVE REM CHARS
	PUSHJ	PS,@1(PS)	; SAVE RBRST4 AND START PATTERN ARG

; SUBSEQUENT FAILURE OF PATTERN ARG
RBRST4:	SKIPN	S$$KWD+10	; IS &FULLSCAN ON?
	POP	PS,(AS)	; NO, POP OLD RC OFF PS, REPLACE NEWER VAL ON AS
	POPJ	PS,	; FAIL TO NEXT PREVIOUS RESTART OF PATTERN ARG
	PRGEND
	SUBTTL	S$$UEB,S$$UES UNEVALUATED EXPR WITHOUT FUNCTION CALLS

	ENTRY	S$$UEB,S$$UES
	EXTERN	S$$STB,S$$STS,S$$STP,S$$FLP
	RADIX	10
	SEARCH	S$$NDF

	COMMENT/
CALL:	JSP	R9,S$$UEB[S$$UES]	; START AND SUCCEED OF UNEVALUA-
TED EXPRESSIONS NOT CONTAINING FUNCTION CALLS. S$$UES EXPECTS THE RESULT
VALUE IN R1 AND PRESERVES IT/

S$$UEB:	PUSH	SS,PS	; SAVE PS ON SS
	PUSH	SS,AS	; SAVE AS ON SS
	PUSH	SS,CR	; SAVE CURSOR ON SS
	PUSH	SS,RC	; SAVE REM CHARS ON SS
	PUSH	SS,S$$FLP	; SAVE FAILPOINT ON SS
	MOVE	ES,S$$STB	; RESTORE ES
	ADD	ES,S$$STS	; FROM ES SAVED
	HRROI	R1,UEBFAL	; MAKE NEW FAILPOINT
	MOVEM	R1,S$$FLP
	JRST	(R9)	; START UNEVALUATED EXPRESSION

; FAILURE OF UNEVALUATED EXPRESSION
UEBFAL:	MOVE	SS,S$$STB-1	; RESET SS
	ADD	SS,S$$STP-1	; FROM SS PREVIOUS
	MOVE	PS,1(SS)	; RESTORE PS, AS, AND FAILPOINT
	MOVE	AS,2(SS)
	MOVE	R1,5(SS)
	MOVEM	R1,S$$FLP
	POPJ	PS,	; FAIL TO NEXT PREVIOUS RESTART

; SUCCEEDED UNEVALUATED EXPRESSION
S$$UES:	POP	SS,S$$FLP	; RESTORE FAILPOINT
	SUB	SS,[XWD 4,4]	; POP RC, CR, AS, AND PS OFF SS
	MOVE	PS,1(SS)
	MOVE	AS,2(SS)
	MOVE	CR,3(SS)
	MOVE	RC,4(SS)
	JRST	(R9)	; CONTINUE MATCH
	PRGEND
	SUBTTL	S$$UFB,S$$UFS UNEVALUATED EXPR WITH FUNCTION CALLS

	ENTRY	S$$UFB,S$$UFS
	EXTERN	S$$STB,S$$STS,S$$STP,S$$SJC,S$$FLP
	RADIX	10
	SEARCH	S$$NDF

	COMMENT/
CALL:	JSP	R9,S$$UFB[S$$UFS]	; START AND SUCCEED OF UNEVALUA-
TED EXPRESSION CONTAINING FUNCTION CALLS. S$$UFS EXPECTS THE RESULT VALUE
IN R1 AND PRESERVES IT/

S$$UFB:	SUB	PS,S$$STB+1	; FORM PS-BASE
	EXCH	PS,S$$STP+1	; EXCHANGE WITH PS PREVIOUS
	PUSH	SS,PS	; SAVE OLD PS PREVIOUS
	SUB	AS,S$$STB+2	; DITTO WITH AS
	EXCH	AS,S$$STP+2
	PUSH	SS,AS
	MOVE	R1,S$$STS+3	; GET CS SAVED
	EXCH	R1,S$$STP+3	; EXCHANGE WITH CS PREVIOUS
	PUSH	SS,R1	; SAVE OLD CS PREVIOUS
	PUSH	SS,S$$STP	; SAVE ES PREVIOUS
	MOVE	ES,S$$STS	; UPDATE ES FROM ES SAVED
	ADD	ES,S$$STB
	PUSH	ES,S$$SJC	; SAVE SUBJECT ON ES
	MOVE	R1,ES	; FORM NEW ES PREVIOUS
	SUB	R1,S$$STB
	MOVEM	R1,S$$STP	; AND SAVE
	PUSH	SS,DT	; SAVE DT, CURSOR,REM CHARS, FAILPOINT
	PUSH	SS,CR
	PUSH	SS,RC
	PUSH	SS,S$$FLP
	MOVN	R1,S$$STB-1	; MAKE NEW SS PREVIOUS
	ADD	R1,SS
	MOVEM	R1,S$$STP-1	; SAVE
	HRROI	R1,UFBFAL	; MAKE NEW FAILPOINT
	MOVEM	R1,S$$FLP	; SAVE
	JRST	(R9)	; START UNRVALUATED EXPR

; FAILURE OF UNEVALUATED EXPR
UFBFAL:	MOVE	SS,S$$STB-1	; RESET SS
	ADD	SS,S$$STP-1	; FROM SS PREVIOUS
	SETZ	R9,	; SET FAIL FLAG

; SUCCEEDED UNEVALUATED EXPR
S$$UFS:	POP	SS,S$$FLP	; RESTORE FAILPOINT
	SUB	SS,[XWD 7,7]	; POP PARAMETERS OFF SS
	MOVE	RC,7(SS)	; RESTORE RC, CR, DT
	MOVE	CR,6(SS)
	MOVE	DT,5(SS)
	MOVE	R2,4(SS)	; RESTORE ES PREVIOUS
	EXCH	R2,S$$STP	; EXCHANGE FOR NEWER ES PREVIOUS
	ADD	R2,S$$STB	; UPDATE TO ES
	POP	R2,S$$SJC	; RESTORE SUBJECT
	SUB	R2,S$$STB	; AND RESTORE ES SAVED
	MOVEM	R2,S$$STS
	MOVE	R2,3(SS)	; RESTORE CS PREVIOUS AND CS SAVED
	EXCH	R2,S$$STP+3
	MOVEM	R2,S$$STS+3
	MOVE	AS,2(SS)	; RESTORE AS AND AS PREVIOUS
	EXCH	AS,S$$STP+2
	ADD	AS,S$$STB+2
	MOVE	PS,1(SS)	; DITTO WITH PS
	EXCH	PS,S$$STP+1
	ADD	PS,S$$STB+1
	MOVN	R2,S$$STB-1	; MAKE OLD SS PREVIOS
	ADD	R2,SS
	MOVEM	R2,S$$STP-1	; AND SAVE
	JUMPN	R9,(R9)	; RETURN TO MATCH IF SUCCESSFUL
	POPJ	PS,	; OR FAIL TO NEXT PREVIOUS RESTART
	PRGEND
	SUBTTL	S$$ASC CURSOR ASSIGNMENT ROUTINE

	ENTRY	S$$ASC
	EXTERN	S$$PGL,S$$DSG,S$$SJC
	RADIX	10
	SEARCH	S$$NDF

	COMMENT/
CALL:	JSP	R9,S$$ASC	; WITH VARIABLE NAME DESCR IN R1/

S$$ASC:	MOVEM	R9,S$$PGL	; SAVE LINK
	MOVE	R8,R1	; SAVE NAME DESCR
	HRRZ	R1,@S$$SJC	; FORM CURSOR POSITION
	SUBI	R1,(RC)
	TLO	R1,1B18	; MAKE INTEGER DESCRIPTOR
	TLNE	R8,3B23	; IS VAR DEDICATED?
	JRST	S$$DSG	; YES
	MOVEM	R1,(R8)	; NO, ASSIGN (POSSIBLE OUTPUT)
	JRST	(R9)	; RETURN
	PRGEND
	SUBTTL	S$$VAS PATTERN VALUE ASSIGNMENT START ROUTINE

	ENTRY	S$$VAS
	RADIX	10
	SEARCH	S$$NDF

	COMMENT/
CALL:	JSP	R9,S$$VAS	; SAVES CURSOR, REM CHARS ON AS/

S$$VAS:	PUSH	AS,CR	; PUSH CURSOR ONTO AS
	PUSH	AS,RC	; PUSH REM CHARS ONTO AS
	PUSHJ	PS,(R9)	; PUSH VASRST ONTO PS AND RETURN

; SUBPATTERN FAILURE, RESTART ASSIGNMENT INITIALIZATION
VASRST:	SUB	AS,[XWD 2,2]	; POP AS 2 LEVELS
	POPJ	PS,	; FAIL TO NEXT PREVIOUS RESTART
	PRGEND
	SUBTTL	S$$IVA IMMEDIATE VALUE ASSIGNMENT ROUTINE

	ENTRY	S$$IVA
	EXTERN	S$$PSA
	RADIX	10
	SEARCH	S$$NDF

	COMMENT/
CALL:	JSP	R9,S$$IVA	; WITH INITIAL CR AND RC ON AS, VARIA-
BLE NAME DESCR IN R1/

S$$IVA:	MOVE	R8,R1	; SAVE NAME DESCR
	SUB	AS,[XWD 2,2]	; POP AS 2 LEVELS
	MOVE	R7,1(AS)	; GET OLD CR
	MOVE	R0,2(AS)	; GET OLD RC
	PUSH	PS,R7	; PUSH OLD CR ONTO PS
	PUSH	PS,R0	; PUSH OLD RC ONTO PS
	SUBI	R0,(RC)	; COMPUTE STRING LENGTH
	PUSHJ	PS,S$$PSA	; PUSH IVARST ONTO PS AND PERFORM ASSIGNMENT

; IMMEDIATE VALUE ASSIGNMENT RESTART
IVARST:	SUB	PS,[XWD 2,2]	; POP PS 2 LEVELS
	PUSH	AS,1(PS)	; PUSH OLD CR ONTO AS
	PUSH	AS,2(PS)	; PUSH OLD RC ONTO AS
	POPJ	PS,	; FAIL TO NEXT PREVIOUS RESTART
	PRGEND
	SUBTTL	S$$ACV,S$$CVA CONDITIONAL VALUE ASSIGNMENT ROUTINES

	ENTRY	S$$ACV,S$$CVA
	EXTERN	S$$PGL,S$$STS,S$$STB,S$$PSA
	RADIX	10
	SEARCH	S$$NDF

	COMMENT/
	ASSIGN CONDITIONAL VALUES AT END OF MATCH
CALL:	JRST	S$$ACV	; CALLED FROM S$$MTS WITH RETURN LINK IN R9,
CS INITIAL IN R12, OPERATES AT REGISTER LEVEL 12 AND ASSIGNS SUBSTRINGS
OF THE SUBJECT TO THE GIVEN VARIABLES
	CONDITIONAL VALUE ASSIGNMENT
CALL:	JSP	R9,S$$CVA	; EXPECTS PREVIOUS CR AND RC ON AS, VARIA-
BLE NAME DESCRIPTOR IN R1/

; ASSIGN CONDITIONAL VALUES
S$$ACV:	MOVEM	R9,S$$PGL	; SAVE PROGRAM LINK
	MOVN	R11,S$$STS+3	; GET - CS SAVED
	HRR	R11,S$$STB+3	; GET CS BASE IN RH
	ADD	R12,R11	; FORM -COND VAL*3,FIRSTCV ENTRY PTR
	AOBJN	R12,.+1
ACVLOP:	MOVE	R8,2(R12)	; GET NAME DESCR
	MOVE	R7,(R12)	; GET CURSOR PTR TO BEGINNING OF SUBSTR
	MOVE	R0,1(R12)	; GET LENGTH OF SUBSTRING
	JSP	R9,S$$PSA	; DO PATTERN SUBSTRING ASSIGNMENT
	ADD	R12,[XWD 3,3]	; GO ON TO NEXT CS ENTRY
	JUMPL	R12,ACVLOP	; AND LOOP IF ANY ENTRIES REMAIN
	JRST	@S$$PGL	; OR RETURN

; CONDITIONAL VALUE ASSIGNMENT
S$$CVA:	SUB	AS,[XWD 2,2]	; POP AS 2 LEVELS
	MOVE	CS,S$$STS+3	; UPDATE CS
	ADD	CS,S$$STB+3	; FROM CS SAVED
	MOVE	R2,1(AS)	; GET OLD CR
	MOVE	R3,2(AS)	; GET OLD RC
	PUSH	PS,R3	; SAVE OLD RC ON PS
	PUSH	CS,R2	; SAVE OLD CR ON CS
	SUBI	R3,(RC)	; COMPUTE SUBSTRING LENGTH
	PUSH	CS,R3	; SAVE ON CS
	PUSH	CS,R1	; PUSH VARIABLE NAME DESCR ONTO CS
	SUB	CS,S$$STB+3	; SAVE CS
	MOVEM	CS,S$$STS+3
	PUSHJ	PS,(R9)	; SAVE CVARST ON PS AND RETURN TO MATCH

; CONDITIONAL VALUE ASSIGNMENT RESTARTED
CVARST:	SUB	PS,[XWD 1,1]	; POP PS 1 LEVEL
	MOVN	CS,[XWD 3,3]	; POP CS 3 LEVELS
	ADDB	CS,S$$STS+3	; AND SAVE
	ADD	CS,S$$STB+3	; UPDATE CS
	PUSH	AS,1(CS)	; SAVE OLD CR
	PUSH	AS,1(PS)	; SAVE OLD RC
	POPJ	PS,	; GO TO NEXT PREVIOUS RESTART
	PRGEND
	SUBTTL	S$$PSA PATTERN SUBSTRING ASSIGNMENT ROUTINE

	ENTRY	S$$PSA
	EXTERN	S$$GRS,S$$DSG,S$$MVS
	RADIX	10
	SEARCH	S$$NDF

	COMMENT/
CALL:	JSP	R9,S$$PSA	; WITH NAME DESCR IN R8, INITIAL BYTE
PTR IN R7, AND CHAR COUNT IN R0/

S$$PSA:	JUMPE	R0,NULASG	; SKIP IF 0 CHARS
	HRRM	R0,RESTCT	; SAVE CHAR COUNT
	MUL	R0,[^F0.2B0]	; COMPUTE WORD COUNT
	ADDI	R0,2
	JSP	R6,S$$GRS	; GET BLOCK FOR NEW STRING
	HRLI	R1,^O700	; FORM STRING DESCR
	MOVEM	R1,SAVDSC	; SAVE IT
RESTCT:	MOVEI	R3,.-.	; GET CHAR COUNT
	HRRM	R3,(R1)	; SAVE IN STRING BLOCK
	MOVE	R2,R7	; GET STARTING BYTE POINTER
	JSP	R7,S$$MVS	; MOVE STRING
	MOVE	R1,SAVDSC	; RESTORE DESCR
NULCON:	TLNE	R8,3B23	; IS VARIABLE DEDICATED?
	JRST	S$$DSG	; YES
	MOVEM	R1,(R8)	; NO, ASSIGN, POSSIBLE OUTPUT
	JRST	(R9)	; RETURN

; NULL VALUE
NULASG:	SETZ	R1,	; NULL DESCR
	JRST	NULCON	; GO ASSIGN
; STORAGE
SAVDSC:	BLOCK	1
	PRGEND
	SUBTTL	S$$APS,S$$APR,S$$APF PATTERN ALTERNATION ROUTINES

	ENTRY	S$$APS,S$$APR,S$$APF
	RADIX	10
	SEARCH	S$$NDF

	COMMENT/
	START ALTERNATION
CALL:	JSP	R9,S$$APS	; WHERE STNEXT IS THE START OF THE
	XWD	.-.,STNEXT	; NEXT ALTERNATION

	RESTART ALTERNATION
CALL:	JSP	R9,S$$APR
	XWD	.-.,STNEXT

	FINISH ALTERNATION
CALL:	JSP	R9,S$$APF	; NEXT RESTART WILL FAIL/

; START ALTERNATION
S$$APS:	PUSH	PS,CR	; PUSH CURSOR ONTO PS
	HRLM	RC,(R9)	; SAVE REM CHAR COUNT WITH RESTORT POINT
	PUSH	PS,(R9)	; AND PUSH ONTO PS
	JRST	1(R9)	; AND CONTINUE

; RESTART ALTERNATION
S$$APR:	MOVE	CR,(PS)	; RESTORE CURSOR
	HLRZ	RC,1(PS)	; RESTORE REM CHARS
	HRRZ	R1,(R9)	; GET NEXT RESTART POINT
	HRRM	R1,1(PS)	; AND SAVE ON PS
	AOBJN	PS,1(R9)	; SIMULATE PUSH OF PS, AND CONTINUE

; FINISH ALTERNATION
S$$APF:	POP	PS,CR	; RESTORE CURSOR AND REM CHARS FOR LAST TIME,
	HLRZ	RC,2(PS)	; NEXT RESTART WILL PASS TO NEXT PRE-
	JRST	(R9)	; VIOUS RESTART POINT, CONTINUE
	PRGEND
	SUBTTL	S$$RPS,S$$RPL PATTERN REPLACEMENT ROUTINES

	ENTRY	S$$RPS,S$$RPL
	EXTERN	S$$MTS,S$$KWD,S$$SJC,S$$STB,S$$STP,S$$GRS,S$$MVS,S$$MKS
	EXTERN	S$$PGL,S$$TAC
	RADIX	10
	SEARCH	S$$NDF

	COMMENT/
	SUCCEEDED REPLACEMENT
CALL:	JSP	R9,S$$RPS	; PUSHES CURSOR, REMAINING CHARS, AND
INITIAL POSITION ONTO SS, SUBJECT ONTO ES, THEN GOES TO S$$MTS
	FORM REPLACEMENT STRING
CALL:	JSP	R12,S$$RPL	; WITH SUBSTITUTE STRING IN R1, 
PARAMETERS ON SS AND ES, AND RETURNS REPLACEMENT STRING DESCR IN R1/

; SUCEEDED REPLACEMENT
S$$RPS:	MOVE	ES,S$$STB	; RESTORE ES
	ADD	ES,S$$STP	; FROM ES PREVIOUS
	MOVE	R1,1(ES)	; GET FIRST ELEMENT PUSHED
	TLNN	R1,1B20	; IS IT NAME OR PATTERN?
	AOBJN	ES,.+1	; NAME, EXTRA PUSH FOR ASSIGNMENT
	PUSH	ES,S$$SJC	; SAVE SUBJECT ON ES
	PUSH	SS,CR	; SAVE CURSOR ON SS
	PUSH	SS,RC	; SAVE REM CHARS ON SS
	SKIPN	S$$KWD+9	; IS & ANCHOR NONZERO?
	JRST	UNANCH	; NO, UNANCHORED MODE
	PUSH	SS,[0]	; YES, NO CHARS FROM FRONT
	JRST	S$$MTS+2	; CONTINUE
UNANCH:	HRRZ	R1,@S$$SJC	; GET TOTAL # OF CHARS
	MOVE	R2,S$$STB+1	; FORM PS INITIAL
	ADD	R2,S$$STP+1
	SUB	R1,2(R2)	; GET TOT # - LAST INITIAL RC
	PUSH	SS,R1	; SAVE AS # OF CHARS FROM FRONT
	JRST	S$$MTS+2	; CONTINUE

; FORM REPLACEMENT STRING
S$$RPL:	MOVEM	R12,S$$PGL	; SAVE LINK
	SETO	R0,	; MAKE SURE REPLACEMENT IS STRING
	JSP	R7,S$$MKS
	CFERR	1,S$$PGL	; ERROR IF NOT
	MOVEM	R1,S$$TAC	; SAVE DESCRIPTOR
	SUB	SS,[XWD 3,3]	; POP SS 3 PLACES
	MOVEI	R8,(R3)	; SAVE REPLACEMENT STRING CHAR COUNT
	ADD	R3,3(SS)	; ADD # CHARS FROM FRONT OF SUBJECT
	ADD	R3,2(SS)	; ADD # CHARS FROM REAR OF SUBJECT
	JUMPE	R3,NULRPL	; SKIP OUT IF TOTAL = 0
	MOVEI	R9,(R3)	; SAVE TOT # OF CHARS
	MUL	R3,[^F0.2B0]	; COMPUTE # WORDS NEEDED
	MOVEI	R0,2(R3)
	JSP	R6,S$$GRS	; GET BLOCK FOR NEW STRING
	HRLI	R1,^O700	; FORM STRING DESCR
	MOVE	R10,R1	; SAVE DESCR
	HRRM	R9,(R10)	; SAVE CHAR COUNT IN STRING BLOCK
	MOVE	R3,3(SS)	; GET CHARS FROM FRONT OF SUBJECT
	POP	ES,R2	; GET SUBJECT BYTE POINTER
	JUMPE	R3,MIDRPL	; SKIP IF NONE
	JSP	R7,S$$MVS	; MOVE FRONT IN
MIDRPL:	MOVEI	R3,(R8)	; GET CHARS FROM REPLACEMENT STRING
	JUMPE	R3,ENDRPL	; SKIP IF NONE
	SETZ	R2,	; GET REPLACEMENT BYTE PTR
	EXCH	R2,S$$TAC
	JSP	R7,S$$MVS	; MOVE REPLACEMENT IN
ENDRPL:	MOVE	R3,2(SS)	; GET CHARS FROM REAR OF SUBJECT
	JUMPE	R3,RPLVAL	; SKIP IF NONE
	MOVE	R2,1(SS)	; GET FINAL CURSOR POSITION
	JSP	R7,S$$MVS	; MOVE REAR IN
RPLVAL:	MOVE	R1,R10	; GET NEW STRING DESCR
	JRST	(R12)	; RETURN
NULRPL:	POP	ES,R1	; THROW AWAY SUBJECT DESCR
	SETZ	R1,	; RETURN NULL VALUE
	JRST	(R12)
	PRGEND
	SUBTTL	S$$MTX,S$$MTS,S$$MTA PATTERN MATCH ROUTINES

	ENTRY	S$$MTX,S$$MTS,S$$MTA
	EXTERN	S$$PGL,S$$GRS,S$$FLR,S$$SJC,S$$DBT,S$$MKS,S$$STB,S$$STS
	EXTERN	S$$STP,S$$KWD,S$$ACV,S$$NUL
	RADIX	10
	SEARCH	S$$NDF

	COMMENT/
	EXECUTE MATCH
CALL:	JSP	R12,S$$MTX	; WHERE NPAR, IF POSITIVE, IS NUMBER OF
	XWD	NPAR,POOLPT	; PARMS+1, AND POOLPT IS A POINTER TO THE
DATA BLOCK POOL. PARAMETERS, IF ANY, ARE ON ES. IF NPAR < 0, NO BLOCK
IS ACQUIRED AND THE DUMMY HEADER AT 1(R12) IS USED BY THE PATTERN DESCR
INSTEAD. AFTER TRANSFERRING PARAMETERS (IF ANY) TO THE DATA BLOCK AND
STORING THE PATTERN DESCRIPTOR IN DT, THE SUBJECT, CURSOR, AND REM
CHARS ARE INITIALIZED FROM THE SUBJECT STORED ON ES (WHICH IS FORCED
TO BE STRING), AND THE PATTERN DESCRIPTOR PUSHED ONTO ES. ES IS SAVED,
PS, AS, AND CS INTIALIZED, AND THE NPAR,POOLPT WORD PUSHED ONTO AS.
IF &ANCHOR IS NONZERO, S$$FLR IS PUSHED ONTO PS AND CONTROL IS TRANSFER-
RED TO THE MATCH CODE. IF &ANCHOR IS ZERO, THE CURSOR, RC, AND MATCH
FAIL POINTER ARE PUSHED ONTO PS AND CONTROL TRANSFERRED TO THE MATCH CODE
	SUCCEEDED MATCH
CALL:	JSP	R9,S$$MTS	; RESTORES ES AND PUTS DATA BLOCK, IF
ANY, BACK IN POOL, AND PERFORMS CONDITIONAL ASSIGNMENTS, IF ANY. RE-
TURNS TO 0(R9) AND OPERATES AT REGISTER LEVEL 12
	ABORTED MATCH
CALL:	JRST	S$$MTA	; FROM 'ABORT' OR 'FENCE' PRIMITIVES/

; SUCCEEDED MATCH
S$$MTS:	MOVE	ES,S$$STP	; RESTORE ES
	ADD	ES,S$$STB	; FROM ES PREVIOUS
	JSP	R4,RETBLK	; RETURN DATA BLOCK TO POOL
	MOVE	R12,S$$STP+3	; GET CS INITIAL
	CAME	R12,S$$STS+3	; SAME AS CS SAVED?
	JRST	S$$ACV	; NO, ASSIGN CONDITIONAL VALUES
	JRST	(R9)	; YES, RETURN
RETBLK:	MOVE	R1,(AS)	; GET NPAR,POOLPT WORD PTR OFF AS
	JUMPL	R1,(R4)	; RETURN IF DUMMY DATA BLOCK
	MOVE	R2,(R1)	; GET NPAR,POOLPT WORD
	MOVE	R3,(DT)	; GET FIRST WORD OF DATA BLOCK
	TLC	R3,3B19	; CHANGE BACK TO NONRETURNABLE
	HRRI	R3,(R2)	; AND POINT TO LATEST POOL BLOCK
	MOVEM	R3,(DT)	; PUT BACK IN DATA BLOCK
	HRRI	R2,(DT)	; NEW NPAR,POOLPT WORD
	MOVEM	R2,(R1)	; BACK IN CALLING SEQUENCE
	JRST	(R4)	; RETURN

; ABORTED MATCH
S$$MTA:	MOVE	ES,S$$STB	; RESTORE ES TO INITIAL POSITION
	ADD	ES,S$$STP
	MOVE	DT,1(ES)	; GET FIRST ELT PUSHED
	TLNN	DT,1B20	; IS IT NAME OR PATTERN?
	MOVE	DT,2(ES)	; NAME, GET SECOND ELT PUSHED
	MOVE	AS,S$$STB+2	; RESTORE AS TO INITIAL POSITION
	ADD	AS,S$$STP+2	; USING AS PREVIOUS
	AOBJN	AS,ABTPAT	; + 1 PUSH, AND GO ABORT
; EXECUTE MATCH
S$$MTX:	MOVE	R11,(R12)	; GET NPAR,POOLPT WORD
	HRLZI	DT,6B21	; FORM LH OF PATTERN DESCR
	JUMPGE	R11,GTDBLK	; IF NPAR> 0, SKIP OVER
	HRRI	DT,1(R12)	; OR USE DUMMY DATA BLOCK
	JRST	GTSUBJ	; AND PROCEED WITH SUBJECT
GTDBLK:	HRRZI	R1,(R11)	; GET POOLPT
	JUMPE	R1,[MOVEM	R12,S$$PGL	; IF ZERO, GET NEW DATA BLK
		HLRZ	R0,R11
		JSP	R6,S$$GRS
		MOVE	R10,(R1)	; GET FIRST WORD
		JRST	GTDBLR]	; OF DATA BLOCK AND RETURN
	MOVE	R10,(R1)	; GET FIRST WORD OF DATA BLOCK
	HRRI	R11,(R10)	; GET PTR TO NEXT BLOCK IN POOL
	MOVEM	R11,(R12)	; RESTORE NPAR,POOLPT WORD
	TLC	R10,3B19	; MAKE BLOCK RETURNABLE
GTDBLR:	HRRI	R10,1(R12)	; GET PTR TO PATTERN MATCH CODE
	MOVEM	R10,(R1)	; SAVE BACK IN DATA BLOCK
	HRRI	DT,(R1)	; RH OF PATTERN DESCR POINTS TO DATA BLOCK
	HLRZ	R8,R11	; GET ACTUAL # OF PARAMS
	MOVEI	R8,-1(R8)
	JSP	R9,S$$DBT	; MOVE PARAMETERS FROM ES TO DATA BLOCK
GTSUBJ:	MOVE	R1,(ES)	; GET SUBJECT DESCRIPTOR OFF ES
	MOVEM	DT,(ES)	; SAVE PATTERN DESCRIPTOR ON ES
	TLNE	R1,^O770000	; IS IT A STRING?
	JRST	[SETO	R0,	; NO, MAKE STRING
		JSP	R7,S$$MKS
		CFERR	1,R12	; CAN'T DO, ERROR
		JRST	GTSUBR]	; OK, GO ON BACK
GTSUBR:	JUMPN	R1,.+2	; SKIP IF NON-NULL
	MOVE	R1,S$$NUL	; OR INSURE NULL POINTER
	MOVEM	R1,S$$SJC	; SAVE IN SUBJECT
	SUB	ES,S$$STB	; SAVE ES
	MOVEM	ES,S$$STS	; IN ES SAVED
	MOVE	PS,S$$STB+1	; ACTIVATE PS
	ADD	PS,S$$STP+1	; FROM PS PREVIOUS
	MOVE	AS,S$$STB+2	; DITTO FOR AS
	ADD	AS,S$$STP+2
	MOVE	R0,S$$STP+3	; INITIALIZE CS SAVED
	MOVEM	R0,S$$STS+3	; FROM CS PREVIOUS
	HRRI	R11,(R12)	; GET POINTER TO POOLPT WORD
	PUSH	AS,R11	; PUSH NPAR,[POOLPT] ONTO AS
	MOVE	CR,S$$SJC	; INITIALIZE CURSOR
	HRRZ	RC,(CR)	; AND REM CHAR COUNT
	MOVE	R1,(DT)	; GET PATTERN CODE POINTER
	SKIPN	S$$KWD+9	; IS &ANCHOR NONZERO?
	JRST	UNANCH	; NO, UNANCHORED MODE
	PUSHJ	PS,(R1)	; SAVE ABTPAT ON PS AND GO TO PATTERN CODE
ABTPAT:	JSP	R4,RETBLK	; FAILED MATCH, RETURN DATA BLOCK TO POOL
	JRST	S$$FLR	; AND FAIL
UNANCH:	PUSH	PS,CR	; SAVE CURSOR
	PUSH	PS,RC	; SAVE REM CHARS
	PUSHJ	PS,(R1)	; SAVE MVANCH ON PS AND GO TO PATTERN CODE
MVANCH:	SKIPN	S$$KWD+10	; IS FULLSCAN NONZERO?
	JUMPL	RC,ABTPAT	; NO, QUICKSCAN, ABORT PAT IF CHARFAIL ON
	SOSGE	RC,(PS)	; INCREMENT INITIAL MATCH POSITION
	JRST	ABTPAT	; AND QUIT IF OUT OF SUBJECT
	IBP	-1(PS)	; INCREMENT CURSOR
	MOVE	CR,-1(PS)	; AND UPDATE
	MOVE	R1,(DT)	; GET POINTER TO PATTERN CODE
	AOBJN	PS,(R1)	; SAVE MVANCH ON PS AND GO TO PATTERN CODE
	PRGEND
	SUBTTL	S$$MKP,S$$CKP MAKE ELEMENT FOR PATTERN ROUTINES

	ENTRY	S$$MKP,S$$CKP
	EXTERN	S$$PGL,S$$MKS,S$$STB,S$$STS
	RADIX	10
	SEARCH	S$$NDF

	COMMENT/
CALL:	JSP	R9,S$$MKP[S$$CKP]	; WITH DESCR IN R1, MAKES SURE
DESCR IS STRING OR PATTERN, OR MAKES STRING, RETURNING DESCR IN R1. IN
ADDITION, S$$CKP SAVES A PATTERN DESCR ON ES, AND SETS UP A RESTART TO
POP IT OFF/

S$$CKP:	JSP	R8,S$$MKP+1	; FLAG NOT =0
S$$MKP:	SETZ	R8,	; FLAG = 0
	TLNN	R1,^O770000	; IS IT A STRING?
	JRST	(R9)	; YES, RETURN
	TLC	R1,3B20	; IS IT A PATTERN?
	TLNE	R1,^O17B21
	JRST	MAKSTR	; NO
	TLC	R1,3B20	; YES
	JUMPE	R8,(R9)	; RETURN IF S$$MKP
	EXCH	PS,S$$STS	; SAVE PS, GET ES SAVED
	ADD	ES,S$$STB	; UPDATE ES
	PUSH	ES,R1	; SAVE PATTERN DESCR ON ES
	SUB	ES,S$$STB	; GET NEW ES SAVED
	EXCH	PS,S$$STS	; SAVE, AND RESTORE PS
	PUSHJ	PS,(R9)	; SAVE CKPRST ON PS AND RETURN
CKPRST:	MOVN	R1,[XWD 1,1]	; POP ES SAVED
	ADDM	R1,S$$STS
	POPJ	PS,	; AND FAIL TO NEXT PREVIOUS RESTART
MAKSTR:	TLC	R1,3B20	; RESTORE DESCR
	MOVEM	R9,S$$PGL
	SETO	R0,	; MAKE STRING
	JSP	R7,S$$MKS
	CFERR	1,S$$PGL	; CAN'T DO, ERROR
	JRST	(R9)	; RETURN
	PRGEND
	SUBTTL	S$$GPB,S$$PTS,S$$PTX PATTERN EXECUTION ROUTINES

	ENTRY	S$$GPB,S$$PTS,S$$PTX
	EXTERN	S$$PGL,S$$MST,S$$GRS,S$$DBT
	RADIX	10
	SEARCH	S$$NDF

	COMMENT/
	GET PATTERN BLOCK
CALL:	JSP	R12,S$$GPB	; WHERE NARG IS THE NUMBER OF PARMS+1
	XWD	NARG,SKIPAT	; AND SKIPAT IS THE FIRST LOCATION FOLLOW-
ING THE PATTERN MATCH CODE. EXPECTS PARAMETERS ,IF ANY, ON ES, ACQUIRES
A DATA BLOCK (IF ANY IS REQUIRED, OR USES DUMMY HEADER AT 1(R12)), TRANS-
FERS PARAMETERS INTO DATA BLOCK, POPS ES, AND RETURNS WITH PATTERN DESCR
IN R1 TO SKIPAT. THE RESTARTABLE FLAG IS SET IF NARG IS NEGATIVE OR IF
A PARAMETER IS A RESTARTEABLE PATTERN
	SUCCEEDED PATTERN
CALL:	JRST	S$$PTS	; IF PATTERN CANNOT BE RESTARTED, POP PS, POP
DT OFF AS, AND POPJ AS BACK TO HIGHER PATTERN. IF PATTERN CAN BE RESTAR-
TED, PUSH RETURN LINK, DT, AND PATTERN RESTART ONTO PS, POP DT OFF AS,
AND POPJ AS BACK TO HIGHER PATTERN
	EXECUTE PATTERN
CALL:	JSP	R9,S$$PTX	; WITH STRING OR PATTERN DESCR IN R1. IF
STRING, GO TO S$$MST, OTHERWISE PUSHES RETURN LINK, DT ONTO AS, PATTERN
FAIL ONTO PS, LOADS DT WITH NEW DESCR, AND GOES TO SUBPATTERN EXECUTION
CODE/

; GET PATTERN BLOCK
S$$GPB:	MOVE	R11,(R12)	; GET PARAMETER WORD
	HLRE	R0,R11	; GET NPAR
	MOVEI	R10,6B21	; GET LH OF PATTERN DESCR
	JUMPGE	R0,.+3	; SKIP OVER IF NPAR>0
	TRO	R10,1B22	; OTHERWISE SET RESTARTEABLE FLAG
	MOVN	R0,R0	; AND MAKE NPAR > 0
	CAIE	R0,1	; IS NPAR = 1?
	AOJA	R12,GETDBL	; NO, GET DATA BLOCK
	MOVEI	R1,1(R12)	; YES, FORM POINTER TO DUMMY HEADER
GPBRET:	HRLI	R1,(R10)	; FORM PATTERN DESCR
	JRST	(R11)	; RETURN
GETDBL:	MOVEM	R12,S$$PGL	; SAVE PROGRAM LINK
	JSP	R6,S$$GRS	; GET BLOCK FOR DATA BLOCK
	HRRM	R12,(R1)	; SAVE POINTER TO PATTERN MATCH CODE
	SOS	R8,R0	; GET ACTUAL # OF PARAMS
	JSP	R9,S$$DBT	; TRANSFER PARMS INTO DATA BLOCK
	TRNE	R10,1B22	; IS RESTARTEABLE FLAG SET?
	JRST	GPBRET	; YES, GO OUT
	HRLZI	R7,^O15B22	; NO , SEARCH DATA BLOCK FOR RESTART-
	MOVNI	R8,(R8)	; EABLE PATTERN
	HRLZI	R8,(R8)
	ADDI	R8,1(R1)
	CAMG	R7,(R8)	; IS DESCR A RESTARTEABLE PATTERN?
	TROA	R10,1B22	; YES, SET FLAG AND SKIP
	AOBJN	R8,.-2	; NO, LOOP
	JRST	GPBRET	; OR GO OUT
; SUCCEEDED PATTERN
S$$PTS:	TLNN	DT,1B22	; CAN PATTERN BE RESTARTED?
	JRST	PTCONT-1	; NO, THROW AWAY BACKUP
	PUSH	PS,-1(AS)	; YES,  PUSH RETURN LINK ONTO PS
	PUSH	PS,DT	; PUSH INNER DT ONTO PS
	PUSHJ	PS,PTCONT	; PUSH PATRST ONTO PS , GO CONTINUE
PATRST:	PUSH	AS,-1(PS)	; ON RESTART, PUSH RETURN LINK ONTO AS
	PUSH	AS,DT	; AND PUSH OUTER DT ONTO AS
	SUB	PS,[XWD 2,2]	; POP PS 2 PLACES
	MOVE	DT,2(PS)	; RESTORE INNER DT AND IGNORE RETURN LINK
	POPJ	PS,	; GO TO NEXT PREVIOUS RESTART
	SUB	PS,[XWD 1,1]	; THROW AWAY PATFAIL
PTCONT:	POP	AS,DT	; RESTORE OUTER DT FROM AS
	POPJ	AS,	; GO SUCEED IN OUTER PATTERN

; EXECUTE PATTERN
S$$PTX:	TLNN	R1,^O770000	; IS IT STRING?
	JRST	S$$MST	; YES, GO MATCH
	PUSH	AS,R9	; NO, PUSH RETURN LINK ONTO AS
	PUSH	AS,DT	; PUSH OUTER DT ONTO AS
	MOVE	DT,R1	; SET UP DT FOR INNER PATTERN
	MOVE	R1,(R1)	; GET PTR TO INNER PATTERN CODE
	PUSHJ	PS,(R1)	; PUSH PATFAL ONTO PS AND GO TO INNER PATTERN
PATFAL:	SUB	AS,[XWD 2,2]	; POP AS 2 PLACES
	MOVE	DT,2(AS)	; RESTORE OUTER DT AND IGNORE RET LINK
	POPJ	PS,	; FAIL TO NEXT PREVIOUS RESTART POINT
	PRGEND
	SUBTTL	S$$DBT DATA BLOCK TRANSFER ROUTINE

	ENTRY	S$$DBT
	RADIX	10
	SEARCH	S$$NDF

	P$BRKE=7	; BREAK EVEN POINT BETWEEN BLT AND POPS

	COMMENT/
CALL:	JSP	R9,S$$DBT	; WITH DESCRIPTOR(S) ON ES, DATA BLOCK
POINTER IN R1, NUMBER OF ELEMENTS IN R8. MOVES DESCRS OFF ES INTO BLOCK,
LEAVING ES POINTING TO BEFORE FIRST DESCR. LEAVES R1, RH(R8) UNCHANGED/

S$$DBT:	MOVNI	R7,(R8)	; GET - # OF PARS
	CAIG	R8,P$BRKE	; > BREAK EVEN POINT?
	JRST	BOTPOP(R7)	; NO, DO SERIES OF POPS
	ADDI	R7,1(ES)	; YES, DO BLT, POINT TO FIRST PAR ON ES
	HRLZI	R7,(R7)
	ADDI	R7,1(R1)	; POINT TO FIRST PAR LOC IN DATA BLOCK
	MOVEI	R6,(R8)	; POINT TO LAST PAR LOC IN DATA BLOCK
	ADDI	R6,(R1)
	BLT	R7,(R6)	; MOVE PARMS
	HRLI	R8,(R8)	; POP STACK CORRECT # OF PARMS
	SUB	ES,R8
	JRST	(R9)	; RETURN

	P$BRKR=0	; MAKE SERIES OF POPS
	REPEAT	P$BRKE,
<	POP	ES,P$BRKE-P$BRKR(R1)
	P$BRKR=P$BRKR+1>
BOTPOP:	JRST	(R9)	; RETURN
	PRGEND
	SUBTTL	S$$MST MATCH STRING ROUTINE

	ENTRY	S$$MST
	RADIX	10
	SEARCH	S$$NDF

	P$BRKE=7	; BREAK EVEN POINT FOR GOING TO FAST REG LOOP

	COMMENT/
CALL:	JSP	R9,S$$MST	; WITH DESCR IN R1/

S$$MST:	SETZ	R0,	; GET CHAR COUNT
	HRRZ	R0,(R1)
	SUB	RC,R0	; SUBTRACT FROM REM CHARS
	JUMPL	RC,MSFAIL	; FAIL IF TOO MANY FOR SUBJECT
	CAIL	R0,P$BRKE	; LESS THAN BREAK EVEN POINT?
	JRST	FSTMST	; NO, LOAD LOOP INTO FAST REGISTERS
MSTLP1:	SOJL	R0,(R9)	; YES, SUCCEED IF STRING EXHAUSTED
	ILDB	R2,R1	; GET CHAR FROM STRING
	ILDB	R3,CR	; GET CHAR FROM SUBJECT
	CAIN	R2,(R3)	; DO THEY MATCH?
	JRST	MSTLP1	; YES, LOOP
MSFAIL:	POPJ	PS,	; NO, FAIL TO NEXT PREVIOUS RESTART
FSTMST:	HRRM	R9,MSTLP2	; SAVE RETURN LINK
	MOVE	R9,[XWD MSTLP2,MSTLP3]
	BLT	R9,MSTFIN	; MOVE LOOP INTO R4-R9
	JRST	MSTLP3	; AND START IT
MSTLP2:	PHASE	4
MSTLP3:	SOJL	R0,.-.	; R4: SUCCEED IF STRING EXHAUSTED
	ILDB	R2,R1	; R5: GET CHAR FROM STRING
	ILDB	R3,CR	; R6: GET CHAR FROM SUBJECT
	CAIN	R2,(R3)	; R7: DO THEY MATCH?
	JRST	MSTLP3	; R8: YES, LOOP
MSTFIN:	POPJ	PS,	; R9: NO, FAIL
	DEPHASE
	END