Google
 

Trailing-Edge - PDP-10 Archives - BB-H580C-SB_1981 - nstrng.mac
There are 11 other files named nstrng.mac in the archive. Click here to see a list.
; UPD ID= 2769 on 4/9/80 at 2:26 PM by WRIGHT                           
TITLE	NSTRNG - NEW LIBOL STRING/UNSTRING ROUTINES
SUBTTL	D.A.WRIGHT

;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
;  OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (C) 1979, 1981 BY DIGITAL EQUIPMENT CORPORATION

	SEARCH	LBLPRM		;DEFINE PARAMETERS
	%%LBLP==:%%LBLP
	EXTERN	EASTB.		;MAKE SURE EASTBL IS LOADED

;GET COMMON MACRO DEFINITIONS
	IFN TOPS20,	SEARCH MACSYM
	IFE TOPS20,	SEARCH MACTEN


	HISEG
	SALL

	ENTRY	%STR.		;STRING
	ENTRY	%STR.O		;STRING WITH OVERFLOW CLAUSE
	ENTRY	%UNS.		;UNSTRING
	ENTRY	%UNS.O		;UNSTRING WITH OVERFLOW CLAUSE

	OPDEF	PJRST	[JRST]
	OPDEF	NOP	[TRN]	;FAST NO-OP

;THESE ROUTINES ARE CALLED AS FOLLOWS:
;	[JRST	%TAG]		;SKIP OVER RUNTIME ROUTINES
;	[<RUNTIME ROUTINES>]
;[%TAG:]			;TAG PRESENT IF RUNTIME ROUTINES PRESENT
;	MOVEI	AC16,%LITNN	;ADDRESS OF ARGUMENT LIST
;	PUSHJ	PP,XXX


SUBTTL	REVISION HISTORY

;NAME	DATE		COMMENTS
;
;
;
;
;
;
;
;
;
;
;
;
;
;DAW	1-AUG-79	EXTENSIVE REWRITE OF STRING/UNSTRING
;			TO SUPPORT VARIABLE-LENGTH ITEMS
;
;** V12A SHIPPED WITH OLD STRING/UNSTRING **

;COMMON DEFINITIONS FOR STRING AND UNSTRING

;ACS

CV=0		;CONVERSION INSTRUCTION
T1=1		;TEMP.
T2=2
T3=3
T4=4
TAG=5		;ADDRESS OF A ROUTINE TO CALL
DSTBP=6		;CURRENT DEST. BYTE PTR
DSTCC=7		;CURRENT DEST. CHARACTER-COUNT
SRCBP=10	;CURRENT SOURCE BYTE PTR
SRCCC=11	;CURRENT SOURCE CHAR COUNT

;*** WARNING - TO CHANGE THE VALUE OF "C" HERE REQUIRES CHANGING EASTBL ***
C=12		;CHARACTER VALUES
DLMBP=13	;CURRENT DELIMITER BYTE PTR
DLMCC=14	;CURRENT DELIMITER CC

F=15		;FLAGS
PA=16		;ADDRESS OF ARGUMENT LIST
PP=17		;PUSHDOWN PTR.


;COMMON FLAGS -1B0 THRU 1B9
FL.OVF==1B0		;'OVERFLOW' OCCURRED

SUBTTL	CONCEPTS FOR THE PROGRAMMER

;  This page is for programmers who wish to understand/modify
;the argument list for the STRING and UNSTRING code.
;
;  Since STRING and UNSTRING only deal with DISPLAY mode strings,
;all items that are non-DISPLAY (such as COMP items) must
;be moved to a temporary DISPLAY area before they can be used
;by STRING and UNSTRING.
;
;  When dealing with an item, a 2-word block is used to hold
;the byte pointer and character count of the item. This block
;is called a "BP-CC-BLOCK", it's format is:
;	<Byte pointer to the item>	;1 word
;	<# of bytes in the item>	;1 word
;
;  Whenever STRING and UNSTRING are passed pointers to items,
;they must be given the address of the BP-CC-BLOCK for the item.
;Sometimes the BP-CC-BLOCK may be elsewhere in the literal table,
;or it may not be known at runtime (this happens if the item
;has a depending variable or is subscripted).
;
;  BSI = Byte Size Indicator. Every BSI has one of three values:
;	0 = The item is SIXBIT  (6-bit bytes)
;	1 = The item is ASCII   (7-bit bytes)
;	2 = The item is EBCDIC  (9-bit bytes)
;  Along with the BP-CC-BLOCK information, STR. and UNS. must
;be aware of the usage of the item. The BSI of each item
;is put somewhere handy in the argument list.

;  The argument lists may contain pointers to runtime
;routines to set up the BP-CC-BLOCK, and/or move non-DISPLAY mode
;items to a temporary DISPLAY-mode area or visa versa.
;Since the STRING and UNSTRING algorithms sometimes require
;that subscripting be done dynamically during the execution
;of the statement, it may be necessary to call a routine to setup
;the BP-CC-BLOCK for an item. The routines are always called with
;a "PUSHJ 17,address" and should return with a "POPJ 17,".
;All AC's (except 17, of course) may be smashed to accomplish
;the purpose of the runtime routine.
;
;  The STRING argument list is detailed before the STRING code,
;and the UNSTRING argument list is detailed before the UNSTRING code.


SUBTTL	STRING

;The argument list format is:
;
;%LITNN: <STRING-HEADER-WORD>		;1 word
;	<DEST.INFO>			;1 word
;	[<POINTER.INFO>]		;1 word (optional)
;	<SOURCE-SERIES-INFO-ENTRIES>	;one or more entries (each .GT.1 word)
;
;In detail:
;
;<STRING-HEADER-WORD> is
;	XWD  -# OF SOURCE-SERIES-ENTRIES,STRING-FLAGS
;
;<DEST.INFO> is
;	2B35 = BSI of the destination data item.
;Note:	STR. assumes that the BP-CC of the destination
;	item has been stored in DSP.BP and DSP.CC.
;
;<POINTER.INFO> (only present is there was a pointer item) is:
;	XWD 0,%TAG (address of runtime routine to store pointer value)
;
;Note:	Whether or not there was a pointer item, STR. expects an
;	appropriate value for the pointer item to have been stored in
;	PT.VAL. When there is no pointer item, PT.VAL should contain 1.
;
;  The code at %TAG is "PUSHJ'd" to. It should move the value in PT.VAL
;to the actual POINTER data item.
;
;
;  (continued on the following page)
; Format of the STRING argument list  (continued)

;
;<SOURCE-SERIES-INFO-ENTRIES> is one or more <SS-INFO-ENTRY>'s.
;
;<SS-INFO-ENTRY> is:
;	<# of source items in this series>
;	[XWD DELIMITER-FLAGS + BSI ,, DLM.TP] ;1 Word (Optional)
;	[%TAG.DL or 0]			;1 Word (Optional)
;	<SOURCE-ARG-ENTRIES>		;1 or more entries, each 2 words
;
;	BIT 0 THRU BIT 16 = DELIMITER-FLAGS
;	2B17 = BSI of the delimiter
;	DLM.TP = Address of the BP-CC for this delimiter, or 0
;
; If %TAG.DL is non-zero, it is an address of a runtime routine to setup
;DLM.BP and DLM.CC for this delimiter. If %TAG.DL is zero, DLM.TP will
;point to the BP-CC-BLOCK for the delimiter, which will be copied
;into DLM.BP and DLM.CC.
;
;<SOURCE-ARG-ENTRIES> is one or more <SOURCE-ARG-ENTRY>.
;
;<SOURCE-ARG-ENTRY> is:
;	BSI.Source,,SRC.TP	;1 word
;	%TAG.SR or 0		;1 word
;
;	2B17 = BSI of the source item
;	SRC.TP = Address of the BP-CC for this source, or 0 (if %TAG.SR).
; If %TAG.SR is present, it is the address of a runtime routine to setup
;SRC.BP and SRC.CC for this source. STR. dynamically gets the BP and CC
;for each source item by using either SRC.TP or calling the routine at
;%TAG.SR.

;DEFINITIONS FOR "STRING"
;FLAGS
	FL.DSZ==1B10		;THIS GROUP OF SOURCES IS DELIMITED BY SIZE

;STRING-FLAGS (copied from argument list)
	FL.GPT==1B18		;THERE WAS A POINTER ITEM

;DELIMITER-FLAGS
	SF%DSZ==1B0		;NO DELIMITER ITEM - DELIMITED BY SIZE

;HERE IS THE ENTRY POINT FOR "STRING" WITH OVERFLOW CLAUSE
%STR.O:	PUSHJ	PP,%STR.		;CALL STRING ROUTINE
	TXNE	F,FL.OVF	;WAS THERE OVERFLOW?
	AOS	(PP)		;YES, RETURN TO CALL+2
	POPJ	PP,		;IF NO OVERFLOW, RETURN TO CALL+1

;HERE IS THE ENTRY POINT FOR THE "STRING" STATEMENT
%STR.:	MOVEM	PA,BS.AGL##	;SAVE BASE ADDRESS OF ARG LIST
	HRRZ	F,(PA)		;SET FLAG WORD TO THE STRING FLAGS
	HLRE	T1,(PA)		;GET -# OF SOURCE STRINGS
	MOVMM	T1,SS.CNT##	;SAVE COUNT

	MOVE	T1,1(PA)	;GET DEST. INFO
	MOVEM	T1,DST.MD##	;SAVE DEST. MODE

	TXNE	F,FL.GPT	;GOT A "POINTER" ITEM?
	 JRST	[MOVE T1,2(PA)	;YES, GET THE TAG
		MOVEM T1,TAG.PT## ;SAVE "POINTER ITEM" TAG
		MOVEI T2,3(PA)	;ADDR OF FIRST SOURCE-SERIES ARG
		JRST STR01]	;GO ON
	SETZM	TAG.PT##	;NO 'POINTER ITEM' TAG, CLEAR IT
	MOVEI	T2,2(PA)	;ADDR OF FIRST SOURCE-SERIES ARG
STR01:	MOVEM	T2,NX.SSA##	;SAVE "NEXT SOURCE-SERIES" ARG.
;CHECK FOR INITIAL OVERFLOW.  THE POINTER ITEM HAS BEEN STORED IN PT.VAL.
; THE INITIAL CC OF THE RECEIVING ITEM IS IN DST.CC

IFN  BIS,<
	DMOVE	DSTBP,DST.BP##	;GET BP IN DSTBP, CC IN DSTCC
>
IFE BIS,<
	MOVE	DSTBP,DST.BP##
	MOVE	DSTCC,DST.CC##
>
	HRRZ	T1,PT.VAL##
	JUMPLE	T1,SOVFLO	;IF PTR ITEM IS LESS THAN 1, OVERFLOW
	CAIL	T1,(DSTCC)	;ENOUGH CHARS IN DEST?
	 JRST	SOVFLO		;NO, OVERFLOW

;ADJUST BYTE PTR AND COUNT OF THE RECEIVING ITEM.
	SOJE	T1,STR02	;IF WE DON'T HAVE TO ADJUST IT, LEAVE
	SUBI	DSTCC,(T1)	;ADJUST THE COUNT.
IFN BIS,<
	ADJBP	T1,DSTBP	;ADJUST THE BYTE PTR
	MOVE	DSTBP,T1	;PUT BYTE PTR BACK
>
IFE BIS,<
	IBP	DSTBP		;BUMP THE BYTE PTR OVER THE
	SOJG	T1,.-1		; UNWANTED BYTES.
>

;FALL INTO STR02  TO TRANSFER 1ST SET OF SOURCES.
;TRANSFER A SET OF SOURCES TO THE DESTINATION.
; HERE WITH NX.SSA POINTING TO THE NEXT STRING-SERIES ARG.
;
; DSTBP IS THE CURRENT BP TO THE DESTINATION
; DSTCC IS THE CURRENT CC OF THE DESTINATION

STR02:	HRRZ	T1,NX.SSA##	;POINT AT FIRST WORD OF SOURCE-SERIES ENTRY
	MOVE	T2,(T1)		;GET # SOURCES
	MOVEM	T2,NUM.SR##	;SAVE # SOURCES
	MOVE	T3,1(T1)	;GET FLAGS WORD FOR DELIMITER
	TXNE	T3,SF%DSZ	;WAS IT DELIMITED BY SIZE
	 JRST	STR03		;YES
	TXZ	F,FL.DSZ	;NO, CLEAR FLAG

;STORE %TAG OR 0 IN TAG.DL
	MOVE	T2,2(T1)
	MOVEM	T2,TAG.DL##

;STORE %TEMP PTR
	HRRZ	T2,1(T1)
	MOVEM	T2,DLM.TP##	;SAVE IT

;SETUP DELIMITER BP AND CC
	SKIPN	TAG,TAG.DL##	;IS THERE A TAG?
	 JRST	[IFN BIS,<
		DMOVE	T1,@DLM.TP	;NO, GET BP AND CC FROM %LIT
		DMOVEM	T1,DLM.BP##	;STORE IN DLM.BP
		>
		IFE BIS,<
		MOVE	T1,DLM.TP
		MOVE	T2,1(T1)
		MOVE	T1,0(T1)
		MOVEM	T1,DLM.BP##
		MOVEM	T2,DLM.CC##
		>
		JRST	STR04]		;GO TO COMMON CODE
	PUSHJ	PP,CALTAG	;GO SETUP DLM.BP AND DLM.CC
	JRST	STR04		;GO TO COMMON CODE


;HERE IF NO DELIMITER
STR03:	TXO	F,FL.DSZ	;SET "DELIMITED BY SIZE" FLAG
;	JRST	STR04
; HERE WITH DLM.BP AND DLM.CC SET UP IF A DELIMITER.
; IF THERE WAS NO DELIMITER (DELIMITED BY SIZE), THE FLAG FL.DSZ IS ON.

STR04:	HRRZ	T1,NX.SSA##	;START OF SOURCE-SERIES
	MOVEI	T1,3(T1)	;POINT TO FIRST SOURCE
	MOVEM	T1,NX.SRC##	;SAVE START OF NEXT SOURCE

;HERE WITH T1 POINTING TO THE NEXT SOURCE ARGUMENT
STR05:	MOVE	T2,(T1)		;GET FLAGS + BSI.SOURCE,,%TEMP OR 0
	HRRZM	T2,SRC.TP##

	MOVE	T3,1(T1)	;%TAG OR 0
	MOVEM	T3,TAG.SR##	;TAG FOR SOURCE

;SETUP CONVERSION INSTRUCTION(S)
	LDB	T4,[POINT 3,T2,17]	;T4:= BSI OF SOURCE STRING
	TXNE	F,FL.DSZ	;IF DELIMITED BY SIZE,
	 JRST	STR05A		; SKIP THIS
IFN BIS,<
	DMOVE	DLMBP,DLM.BP	;GET BP AND CC FOR DELIM ITEM
>
IFE BIS,<
	MOVE	DLMBP,DLM.BP
	MOVE	DLMCC,DLM.CC
>
	HRRZ	T1,NX.SSA##	;GET BSI OF DELIMITER IN T3
	LDB	T3,[POINT 3,1(T1),17]
	XCT	TT.CVD(T4)	;GET INST TO CONVERT DELIMITER TO SOURCE MODE
	MOVEM	CV,CV.DLM##	;SAVE IT

;SETUP CONVERSION INSTRUCTION TO CONVERT SOURCE TO RECEIVING ITEM'S MODE
STR05A:	MOVE	T3,T4		;SOURCE MODE IN T3
	HRRZ	T1,DST.MD##	;DEST. MODE TO INDEX BY
	XCT	TT.CVD(T1)	;GET INST TO CONVERT SOURCE TO DEST.


;(LEAVE SOURCE CONVERSION INSTRUCTION IN CV)

;SETUP SRC.BP AND SRC.CC
	SKIPN	TAG,TAG.SR##	;TAG FOR SOURCE?
	 JRST	[IFN BIS,<
		DMOVE	SRCBP,@SRC.TP##	;NO, GET %LIT BLOCK
		DMOVEM	SRCBP,SRC.BP##	;SAVE SRC.BP
		>
		IFE BIS,<
		MOVE	SRCBP,SRC.TP##
		MOVE	SRCCC,1(SRCBP)
		MOVE	SRCBP,0(SRCBP)
		MOVEM	SRCBP,SRC.BP##
		MOVEM	SRCCC,SRC.CC##
		>
		JRST	STR06]
	PUSHJ	PP,CALTAG	;CALL USER ROUTINE TO SETUP SRC.CC AND SRC.BP
IFN BIS,<
	DMOVE	SRCBP,SRC.BP##	;FETCH INITIAL SOURCE ENTRIES
>
IFE BIS,<
	MOVE	SRCBP,SRC.BP##
	MOVE	SRCCC,SRC.CC##
>
;HERE WITH SRC.BP AND SRC.CC = INITIAL BP AND CC OF SOURCE ITEM
;SRCBP, SRCCC ARE SET UP

;THIS IS MAIN LOOP OF STRING/UNSTRING ROUTINE.

STR06:	TXNE	F,FL.DSZ	;IF DELIMITED BY SIZE,
	 JRST	STR10		;GO STUFF AS MUCH AS WE CAN

	ILDB	T1,DLMBP	;GET 1ST CHAR OF DELIMITER

SMLD:	ILDB	C,SRCBP		;GET A SOURCE CHAR
	XCT	CV.DLM##	;CONVERT CHARS TO SAME MODE
	CAIN	C,(T1)		;SAME?
	 JRST	SMLL		;EQUAL, TRY TO MATCH MORE

SMLH:	SOJL	DSTCC,SOVFLO	;IS THE DESTINATION IS FULL, IT'S
				; AN OVERFLOW
	LDB	T1,SRCBP	;GET THE CHAR AGAIN, IN T1 NOW
	XCT	CV		;CONVERT TO DEST. MODE
	IDPB	T1,DSTBP	;STORE CHAR IN DESTINATION
	AOS	PT.VAL##	;BUMP THE POINTER VALUE
	LDB	T1,DLMBP	;GET 1ST CHAR OF DELIM AGAIN
	SOJG	SRCCC,SMLD	;IF THERE ARE MORE SOURCE CHARS,
				; GO TRY TO MATCH AGAIN.
	JRST	NXTSR		;OTHERWISE, GO GET THE NEXT SOURCE

;FIRST CHAR OF DELIMITER MATCHES A SOURCE CHAR.
SMLL:	CAIN	DLMCC,1		;IF DELIMITER IS ONLY 1 CHAR LONG,
	 JRST	NXTSR		;GO TO NEXT SOURCE

IFN BIS,<
	DMOVEM	SRCBP,SRC.BP	;SAVE SOURCE INFO (WHERE WE ARE NOW)
>
IFE BIS,<
	MOVEM	SRCBP,SRC.BP
	MOVEM	SRCCC,SRC.CC
>
SMLP:	SOJLE	DLMCC,NXTSR	;IF THERE IS NO MORE DELIMITER, IT'S A MATCH
	SOJLE	SRCCC,SMLT	;IF THERE IS NO MORE SOURCE, IT'S NOT A MATCH
	ILDB	T1,DLMBP	;GET NEXT DELIMITER CHARACTER
	ILDB	C,SRCBP		;GET NEXT SOURCE CHARACTER
	XCT	CV.DLM##	;CONVERT IF NECESSARY
	CAIN	T1,(C)		;DOES THIS CHAR MATCH?
	 JRST	SMLP		;YES, KEEP GOING

;DELIMITER DOESN'T MATCH SOURCE.
SMLT:
IFN BIS,<
	DMOVE	SRCBP,SRC.BP	;RESTORE SOURCE INFO.
	DMOVE	DLMBP,DLM.BP	;RESTORE INITIAL DELIM INFO
>
IFE BIS,<
	MOVE	SRCBP,SRC.BP
	MOVE	SRCCC,SRC.CC
	MOVE	DLMBP,DLM.BP
	MOVE	DLMCC,DLM.CC
>
	ILDB	T1,DLMBP	; GET 1ST CHAR IN T1
	LDB	C,SRCBP		;GET 1ST (MATCHING) CHAR IN SOURCE
	JRST	SMLH		;PICK UP WHERE WE LEFT OFF.

;HERE IF DELIMITED BY SIZE. STUFF AS MUCH AS WE CAN INTO THE DEST.
STR10:	SOJL	SRCCC,NXTSR	;JUMP IF NO MORE SOURCE
	ILDB	T1,SRCBP	;GET A SOURCE CHAR
	XCT	CV		;CONVERT SOURCE TO DEST MODE
	SOJL	DSTCC,SOVFLO	;OVERFLOW IF NO MORE DEST.
	IDPB	T1,DSTBP	;ELSE STORE CHAR
	AOS	PT.VAL##	;BUMP POINTER VALUE
	JRST	STR10		;LOOP

;HERE TO GO ON TO NEXT SOURCE ITEM
NXTSR:	SOSG	NUM.SR		;ANY MORE SOURCES?
	 JRST	NXTSS		;NO, GO ON TO NEXT SOURCE-SERIES
	MOVEI	T1,2		;YES, BUMP PTR
	ADDB	T1,NX.SRC##	; AND GET THE NEW ONE IN T1
	JRST	STR05		;GO DO IT

;HERE TO GO ON TO NEXT SOURCE-SERIES
NXTSS:	SOSG	SS.CNT		;ANY MORE?
	 JRST	STRDON		;NO, DONE
	SKIPE	TAG,TAG.PT##	;STORE POINTER ITEM
	 PUSHJ	PP,CALTAG	; INCASE SUBSCRIPTING NEEDS NEW VALUE
	HRRZ	T1,NX.SSA	;GET PTR TO THE SOURCE-SERIES WE JUST DID
	MOVE	T2,(T1)		;GET # SOURCES
	LSH	T2,1		; TWO WORDS FOR EACH ONE
	ADDI	T2,3		;+2 FOR THE DELIMITER ITEM +1 FOR SOURCE COUNT
	ADD	T2,T1		;+OLD LOC
	MOVEM	T2,NX.SSA	;SAVE NEW NX.SSA
	JRST	STR02		;GO DO IT


;HERE WHEN STRING IS DONE, NO OVERFLOW ENCOUNTERED
STRDON:	SKIPE	TAG,TAG.PT##	;STORE FINAL POINTER VALUE
	 PUSHJ	PP,CALTAG	;IF THERE WAS A POINTER ITEM
	POPJ	PP,		;RETURN

;HERE FOR OVERFLOW
SOVFLO:	TXO	F,FL.OVF	;SET OVERFLOW FLAG
	JRST	STRDON		;RETURN

SUBTTL	UNSTRING

;THE ARGUMENT LIST FORMAT IS:
;
;%LITNN: <UNSTRING-HEADER-WORD>		;1 word
;	<SOURCE-ITEM-INFO>		;1 word
;	[<POINTER-ITEM-INFO>]		;1 word (optional)
;	[<TALLYING-ITEM-INFO>]		;1 word (optional)
;	# delimiter items		;1 word
;	[<DELIMITER-ITEM-INFO>]		;optional 2-word blocks
;	<DESTINATION-ITEM-BLOCK>	;1 or more, 2 to 5 words each
;
;<UNSTRING-HEADER-WORD> is:
;	-# of destinations,,UNSTRING-FLAGS
;
;<SOURCE-ITEM-INFO> is:
;	2B35 = BSI of the source item
;Note:	UNS. assumes that the BP-CC of the source item has been
;	stored in SRC.BP and SRC.CC.
;
;<POINTER-ITEM-INFO> is:
;	XWD 0,%TAG.PT
; %TAG.PT is the address of a routine that is called by UNS. to
;store the pointer item away from PT.VAL.
;
;<TALLYING-ITEM-INFO> is:
;	XWD 0,%TAG.TL
;  %TAG.TL is the address of a routine that is called by UNS. to
;store the tallying item away from TL.VAL.
;
;<DELIMITER-ITEM-INFO> is a 2-word block for each delimiter:
;	DELIM-FLAGS + BSI.DELIMITER ,, PTR TO BP-CC-BLOCK
;	%TAG.DELIM or 0
;
;  %TAG.DELIM is the address of a routine that is called to
;setup the BP-CC block. If the TAG is present, the BP-CC-BLOCK
;will be setup in %TEMP, else it will be in the literals.
;
; (continued on next page)
;
; Format of the UNSTRING arg list  (continued)
;
;<DESTINATION-ITEM-BLOCK> is:
;	<DESTINATION-ITEM-INFO>		;2 words
;	[<DELIMITER-STORE-INFO>]	;optional, 2 words
;	[<COUNT-ITEM-INFO>]		;optional, 1 word
;
;<DESTINATION-ITEM-INFO> is:
;	DEST-FLAGS + BSI.DEST ,, PTR TO BP-CC BLOCK FOR DEST.
;	%TAG.ST ,, %TAG.DA
;
; If %TAG.ST is non-zero, it is the address of a routine to setup
;the BP-CC block.  If %TAG.DA is non-zero, it is the address of a routine
;that stores away the destination from OU.TMP to the actual destination
;item.
;
;<DELIMITER-STORE-INFO> is:
;	DELSTORE-FLAGS + BSI.DELSTORE ,, PTR TO BP-CC BLOCK FOR DELSTORE.
;	%TAG.ST ,, %TAG.DA
;
;  The tags are used in the same manner as for the destination items.
;
;<COUNT-ITEM-INFO> is:
;	XWD 0, %TAG.CT	;address of runtime routine.
;
; %TAG.CT points to code that stores away the value of the count item
;from CT.VAL to the real data item.

;DEFINITIONS FOR UNSTRING

FL.NDL==1B10		;NO DELIMITER ITEMS PRESENT
FL.ALL==1B11		;"ALL" SPECIFIED FOR CURRENT DELIMITER
FL.MAT==1B12		; WE HAD AT LEAST 1 MATCHING OCCURANCE OF AN 'ALL'
			;DELIMITER

;UNSTRING-FLAGS (copied from the the argument list)
FL.UPT==1B18		;POINTER ITEM PRESENT
FL.UTL==1B19		;TALLYING ITEM PRESENT

;DELIM-FLAGS
	DE%ALL==1B1		;'ALL' SPECIFIED FOR THIS DELIMITER

;DEST-FLAGS
	US%RIN==1B0		;RECEIVING ITEM IS NUMERIC
	US%RRJ==1B1		;RECEIVING ITEM IS RIGHT-JUSTIFIED
	US%GDS==1B2		;GOT DEL-STORE
	US%GCT==1B3		;GOT COUNT ITEM

;DELSTORE-FLAGS
	DS%NUM==1B0		;DELIM STORE IS NUMERIC
	DS%JST==1B1		;DELIM STORE IS RIGHT-JUSTIFIED
;HERE FOR UNSTRING WITH OVERFLOW CLAUSE
%UNS.O:	PUSHJ	PP,%UNS.		;DO THE UNSTRING
	TXNE	F,FL.OVF	;WAS THERE OVERFLOW?
	AOS	(PP)		;YES, RETURN TO CALL+2
	POPJ	PP,		;IF NO OVERFLOW, RETURN TO CALL+1

;HERE FOR UNSTRING
%UNS.:	HRRZ	F,(PA)		;GET INITIAL UNSTRING FLAGS
	HLRE	T1,(PA)		;GET -# OF "INTO" ITEMS
	MOVMM	T1,NUM.RC##	;SAVE # RECEIVING ITEMS LEFT TO DO

	MOVE	T1,1(PA)	;GET SOURCE INFO.
	MOVEM	T1,SRC.MD##	;SAVE SOURCE MODE

	MOVEI	T4,2(PA)	;T4:=WHERE WE ARE IN ARG LIST
	TXNN	F,FL.UPT	;GOT A POINTER ITEM?
	 JRST	UNS01		;NO
	MOVE	T1,(T4)		;YES, GET THE TAG
	MOVEM	T1,TAG.PT##	;SAVE "POINTER ITEM" TAG
	AOJA	T4,.+2
UNS01:	SETZM	TAG.PT##	;CLEAR TAG IF NO POINTER ITEM
	TXNN	F,FL.UTL	;GOT A TALLYING ITEM
	 JRST	UNS02		;NO
	MOVE	T1,(T4)		;YES, GET THE TAG
	MOVEM	T1,TAG.TL##	;SAVE "TALLYING ITEM" TAG
	AOJA	T4,.+2
UNS02:	SETZM	TAG.TL##	;CLEAR TAG IF NO TALLYING ITEM
	MOVEM	T4,BS.AGL##	;SAVE BASE FOR DELIMITER ITEMS
;CHECK FOR INITIAL OVERFLOW, AND ADJUST THE SOURCE STRING.
;THE POINTER ITEM HAS BEEN STORED IN PT.VAL.  THE INITIAL
; CC AND BP OF THE SOURCE ITEM IS IN SRC.BP AND SRC.CC.

IFN BIS,<
	DMOVE	SRCBP,SRC.BP##	;GET BP IN SRCBP, CC IN SRCCC
>
IFE BIS,<
	MOVE	SRCBP,SRC.BP##
	MOVE	SRCCC,SRC.CC##
>
	HRRZ	T1,PT.VAL##
	JUMPLE	T1,UNSOVL	;IF PTR ITEM .LT. 1, OVERFLOW

	SOJE	T1,UNS03	;IF WE DON'T HAVE TO ADJUST IT, LEAVE
	SUBI	SRCCC,(T1)	;ADJUST THE COUNT
	JUMPLE	SRCCC,UNSOVL	;IF PTR PAST END OF SOURCE, LEAVE

;ADJUST BYTE PTR AND COUNT OF THE SOURCE ITEM
IFN BIS,<
	ADJBP	T1,SRCBP
	MOVE	SRCBP,T1	;PUT NEW BYTE PTR IN SRCBP
	DMOVEM	SRCBP,SRC.BP##	;SAVE NEW SOURCE BP.
>
IFE BIS,<
	IBP	SRCBP		;BUMP PTR OVER THE
	SOJG	T1,.-1		; UNWANTED BYTES.
	MOVEM	SRCBP,SRC.BP##
	MOVEM	SRCCC,SRC.CC##
>
;FALL INTO UNS03
;SOURCE STRING IS NOW SETUP IN SRCBP AND SRCCC.

UNS03:	HRRZ	T1,BS.AGL	;GET BASE OF DELIMITER ARGS
	SKIPN	T2,(T1)		;GET M= # DELIMITERS
	 TXO	F,FL.NDL	;"NO DELIMITERS"
	LSH	T2,1		; 2 WORDS FOR EACH DELIMITER
	ADDI	T1,1(T2)	;T1:= BASE OF DEST. ITEMS
	MOVEM	T1,NX.SRC##	;NX.SRC:= NEXT DEST. ITEM

;HERE IS MAIN LOOP OF UNSTRING ROUTINE.
; SRCBP AND SRCCC REFLECT WHERE WE ARE IN THE SOURCE SO FAR.
;NX.SRC POINTS TO THE NEXT DEST.  NUM.RC IS THE NUMBER OF
; RECEIVING ITEMS LEFT TO DO. BS.AGL POINTS TO THE DELIMITER ITEMS.

;SETUP NEXT DEST BP AND CC

UNS04:	HRRZ	T1,NX.SRC##	;POINT TO 2-WORD DEST INFO
	LDB	T4,[POINT 3,(T1),17] ;GET BSI OF DEST.
	HRRZ	T3,SRC.MD##	;CONVERTING FROM BSI OF SOURCE
	XCT	TT.CVD(T4)	;GET CONVERSION INSTRUCTION.
	MOVEM	CV,CV.SDS##	; SAVE IT

	HRRZ	T2,(T1)		;GET %LIT OR %TEMP PTR
	MOVEM	T2,DST.TP##	;SAVE IT (NOTE: MUST BE NON-ZERO!)
	MOVE	T3,1(T1)	;GET %TAG1,%TAG2
	HLRZM	T3,TAG.ST##	; TAG TO SETUP %TEMP
	HRRZM	T3,TAG.DA##	; TAG TO STORE OU.TMP AWAY
	SKIPE	TAG,TAG.ST##	;HAVE TO SETUP %TEMP?
	 PUSHJ	PP,CALTAG	;YES, SETUP %TEMP NOW

IFN BIS,<
	DMOVE	DSTBP,@DST.TP##	;GET DEST BP AND CC
	DMOVEM	DSTBP,DST.BP##	;SAVE INITIAL VALUES
>
IFE BIS,<
	MOVE	DSTBP,DST.TP
	MOVE	DSTCC,1(DSTBP)
	MOVE	DSTBP,0(DSTBP)
	MOVEM	DSTBP,DST.BP##
	MOVEM	DSTCC,DST.CC##
>

	HRRZ	T1,NX.SRC##	;LOOK AT NEXT SOURCE
	MOVE	T2,(T1)		;GET FLAG WORD
	TXNN	T2,US%GCT	;GOT A COUNT ITEM?
	 JRST	UNS05		;NO
	TXNE	T2,US%GDS	;ALSO GOT A DELIM STORE?
	 SKIPA	TAG,4(T1)	;YES, GET FIFTH WORD
	MOVE	TAG,2(T1)	;NO, GET 3RD WORD OF ENTRY
	MOVEM	TAG,TAG.CT##	;STORE TAG FOR THE COUNT ITEM
	  TRNA			;AND SKIP
UNS05:	SETZM	TAG.CT##	;NO TAG FOR THE COUNT ITEM
;NOW DSTBP AND DSTCC ARE SETUP FOR THE NEXT DESTINATION.
;CV.SDS CONTAINS THE INSTRUCTION TO CONVERT FROM SOURCE TO DEST MODE.

;CHECK FOR DELIMITERS
	TXNN	F,FL.NDL	;SKIP IF NO DELIMITERS TO WORRY ABOUT
	 JRST	UNS10		; THERE ARE, GO WORRY ABOUT THEM

;THERE WEREN'T ANY DELIMITERS. MOVE AS MUCH AS WE CAN
; INTO THE DESTINATION.
;HERE WITH NO DELIMITERS TO WORRY ABOUT, DEST ALL SET UP.
;FIND # CHARS TO MOVE INTO THIS DEST.
	CAILE	DSTCC,(SRCCC)	;IF DEST. IS LARGER THAN
	 JRST	UNS06		;SOURCE, MOVE ALL CHARS IN THE SOURCE

;DEST IS SMALLER THAN SOURCE. MOVE AS MANY CHARS AS WE CAN,
; DON'T HAVE TO WORRY ABOUT JUSTIFICATION.
UNS05A:	MOVE	T3,DSTCC	;# CHARS TO MOVE
	MOVEM	T3,CT.VAL##	;SAVE COUNT VALUE
	ADDM	T3,PT.VAL##	;ADJUST POINTER VALUE
	PUSHJ	PP,MOVSDS	;MOVE SOURCE TO DEST..
	SKIPE	TAG,TAG.DA##	;STORE AWAY FROM OU.TMP?
	 PUSHJ	PP,CALTAG	;YES, GO DO IT
	PUSHJ	PP,BMPTAL	;BUMP "TALLYING" ITEM
	SKIPE	TAG,TAG.CT##	;DO WE HAVE A COUNT ITEM?
	  PUSHJ	PP,CALTAG	;YES, STORE IT AWAY
	SKIPE	TAG,TAG.PT##	;DO WE HAVE A POINTER ITEM?
	 PUSHJ	PP,CALTAG	;YES, STORE NEW VALUE

;GO ON TO NEXT DEST.
UNS05B:	JUMPE	SRCCC,UNSDON	;DONE IF SOURCE RAN OUT
	SOSG	NUM.RC##	;ANY MORE RECEIVING ITEMS?
	 JRST	UNSOVL		;NO, OVERFLOW
	PUSHJ	PP,NXTDST	;SETUP NEXT DEST
	JRST	UNS04		;GO ON TO NEXT DEST.
;HERE WHEN DEST. IS .GT. # CHARS REMAINING IN SOURCE.
;WE HAVE TO CHECK FOR JUSTIFICATION AND DO THE APPROPRIATE THING.

UNS06:	HRRZ	T1,NX.SRC##	;START OF 2-WORD BLOCK
	MOVE	T3,(T1)		;GET FLAG WORD
	TXNE	T3,US%RRJ	;IF RECEIVING ITEM IS RIGHT-JUSTIFIED, PAD
	 JRST	UNS07		;GO PAD TO THE LEFT FIRST

;MOVE THE CHARS, THEN PAD TO THE RIGHT
	MOVE	T3,SRCCC	;# CHARS TO MOVE
	MOVEM	T3,CT.VAL##	;SAVE COUNT VALUE
	ADDM	T3,PT.VAL##	;ADD TO POINTER VALUE
	PUSHJ	PP,MOVSDS	;MOVE SOURCE TO DEST..
	SKIPE	TAG,TAG.DA##	; STORE DEST FROM OU.TMP?
	 PUSHJ	PP,CALTAG	;YES
	PUSHJ	PP,BMPTAL	;BUMP "TALLYING" ITEM
	SKIPE	TAG,TAG.CT##	;DO WE HAVE A COUNT ITEM?
	  PUSHJ	PP,CALTAG	;YES, STORE IT AWAY
	SKIPE	TAG,TAG.PT##	;DO WE HAVE A POINTER ITEM?
	 PUSHJ	PP,CALTAG	;YES, STORE VALUE

	MOVE	T1,DSTCC	;# CHARS LEFT IN DESTINATION
	PUSHJ	PP,PADDST	;PAD IT OUT
	JRST	UNS05B		;GO DO NEXT DEST, IF ANY


;HERE TO RIGHT-JUSTIFY THE DEST.
UNS07:	HRRZ	T1,DSTCC	;FIND # CHARS TO PAD WITH
	SUB	T1,SRCCC
	PUSHJ	PP,PADDST	;GO PAD THE DEST NOW.
	JRST	UNS05A		;NOW MOVE EQUAL # OF CHARS

;HERE FOR UNSTRING WITH DELIMITERS TO WORRY ABOUT
;NOW DSTCC AND DSTBP ARE SETUP FOR THE NEXT DESTINATION.
; TAG.CT IS THE TAG FOR THE COUNT ITEM (IF ANY).

;SETUP DELIMITERS
UNS10:	HRRZ	T1,BS.AGL##	;POINTER TO BASE OF DELIMITER ARGS
	MOVE	T2,(T1)		;GET # OF DELIMITERS
	MOVEM	T2,NUM.DL##	;SAVE # LEFT TO DO
	MOVEI	T1,1(T1)	;T1:= PTR TO FIRST DELIM ARG.

;HERE WITH T1 POINTING TO NEXT DELIM ENTRY
UNS11:	SKIPE	TAG,1(T1)	;CALL EACH %TAG
	 PUSHJ	PP,CALTAG	;TO SETUP %TEMP, IF NECESSARY
	SOSG	NUM.DL##	;ANY MORE TO DO?
	 JRST	UNS12		;NO, DONE
	ADDI	T1,2		;BUMP PTR TO NEXT DELIMITER ENTRY
	JRST	UNS11		;LOOP

;HERE WHEN ALL DELIMS HAVE BEEN SETUP
; FIND AN OCCURANCE OF A DELIMITER OR END OF SOURCE.

UNS12:
IFN BIS,<
	DMOVEM	SRCBP,SRD.BP##	;SAVE WHERE WE ARE IN SOURCE NOW
>
IFE BIS,<
	MOVEM	SRCBP,SRD.BP##
	MOVEM	SRCCC,SRD.CC##
>
	SETZM	CT.VAL##	;# CHARS EXAMINED

;CHECK ALL DELIMITERS TO SEE IF ONE STARTS MATCHING AT THIS CHARACTER

UNS15:	HRRZ	T1,BS.AGL##	;POINTER TO BASE OF DELIMITER ARGS
	MOVE	T2,(T1)		;GET # OF DELIMITERS
	MOVEM	T2,NUM.DL##	;SAVE # LEFT TO DO
	MOVEI	T1,1(T1)	;WHERE NEXT DELIMITER IS
	MOVEM	T1,NX.DLM##	;SAVE "NEXT DELIMITER" ENTRY
;	JRST	UNS16		;GO CHECK FIRST DELIM AGAINST
				; THE CURRENT SOURCE CHARACTER
;HERE TO CHECK NEXT DELIMITER AGAINST THE CURRENT SOURCE CHAR
UNS16:	TXZ	F,FL.MAT	;NO MATCH YET
IFN BIS,<
	DMOVE	SRCBP,SRD.BP##	;GET CURRENT SOURCE POSITION
>
IFE BIS,<
	MOVE	SRCBP,SRD.BP##
	MOVE	SRCCC,SRD.CC##
>
	HRRZ	T1,NX.DLM##	;HERE IS DELIMITER ENTRY
	MOVE	T2,(T1)		;GET FLAG WORD
	TXNE	T2,DE%ALL	;"ALL" SPECIFIED?
	 TXOA	F,FL.ALL	;YES, SET FLAG
	TXZ	F,FL.ALL	; ELSE CLEAR FLAG
	SETZM	CT.DLM##	;COUNT OF CHARS MATCHED BY THE DELIMITER

;SET CV:= CONVERSION INSTRUCTION
	LDB	T3,[POINT 3,T2,17] ;CONVERT FROM MODE OF DELIMITER
	HRRZ	T4,SRC.MD##	;SOURCE MODE
	XCT	TT.CVD(T4)	;CV:= INST TO CONVERT

;SETUP DLMBP AND DLMCC, DLM.BP AND DLM.CC
	HRRZ	T1,(T1)		;%LIT OR %TEMP
IFN BIS,<
	DMOVE	DLMBP,(T1)	;SETUP BP AND CC
	DMOVEM	DLMBP,DLM.BP##	;AND STORE AWAY INCASE "ALL" SPECIFIED
>
IFE BIS,<
	MOVE	DLMBP,0(T1)
	MOVE	DLMCC,1(T1)
	MOVEM	DLMBP,DLM.BP##
	MOVEM	DLMCC,DLM.CC##
>

	ILDB	C,SRCBP		;LOOK AT NEXT CHAR
	SUBI	SRCCC,1
	ILDB	T1,DLMBP	;GET DELIM CHAR
	SUBI	DLMCC,1
	XCT	CV		;CONVERT DELIM TO SOURCE MODE
	CAIN	T1,(C)		;FIRST CHAR MATCH?
	 JRST	UNS17		;YES

;HERE IF THIS DELIM DOESN'T MATCH
UNS16A:	SOSG	NUM.DL##	;MORE DELIMITERS TO DO?
	 JRST	UNS16B		;NO, DO NEXT CHAR OF SOURCE
	MOVEI	T1,2
	ADDM	T1,NX.DLM##	;BUMP PTR TO NEXT DELIMITER
	JRST	UNS16

;NO MATCH AT THIS CHARACTER POSITION. TRY NEXT ONE
UNS16B:	IBP	SRD.BP##	;INCREMENT BYTE PTR
	SOSE	SRD.CC##	;ANY MORE SOURCE CHARS?
	JRST	UNS15		;YES, TRY AGAIN FOR THIS CHAR

;HERE WHEN ALL CHARS IN SOURCE HAVE BEEN EXAMINED, 
; WITH NO MATCHING DELIMITERS.

UNS16C:	MOVE	T3,SRC.CC##	;COPY REST OF SOURCE TO THIS DESTINATION
IFN BIS,<
	DMOVE	SRCBP,SRD.BP##	;GET START FOR NEXT EXAMIN. IN SRCBP
>
IFE BIS,<
	MOVE	SRCBP,SRD.BP##
	MOVE	SRCCC,SRD.CC##
>
	JRST	UNS21

;ANOTHER CHAR OF DELIMITER MATCHED
UNS17:	JUMPE	DLMCC,UNS18	;THIS DELIM MATCHED
	JUMPE	SRCCC,[TXNE F,FL.MAT ;SOURCE RAN OUT, DID WE MATCH
					; ONCE BEFORE THIS?
			JRST UNS17A	;YES
			JRST UNS16A]	;NO MATCH FOR THIS DELIM

;MORE CHARS IN BOTH SOURCE AND DELIMITER.. KEEP CHECKING
	ILDB	C,SRCBP
	SUBI	SRCCC,1
	ILDB	T1,DLMBP
	SUBI	DLMCC,1
	XCT	CV		;CONVERT DELIM TO SOURCE MODE
	CAIN	T1,(C)		;STILL MATCH?
	 JRST	UNS17		;YES.

;STOPPED MATCHING.. IF "ALL" WAS SPECIFIED,
; AND AT LEAST ONE MATCH, IT'S A MATCH
	TXNN	F,FL.MAT	;DID WE GET A MATCH?
	 JRST	UNS16A		;NO

;HERE IF ONE OR MORE OCCURANCES OF 'ALL' DELIMITER MATCHED.
;RESET THE SRCCC AND SRCBP TO AFTER THE LAST ONE THAT MATCHED.

UNS17A:
IFN BIS,<
	DMOVE	SRCBP,SRA.BP##	;GET LAST SAVED SOURCE BP AND CC
>
IFE BIS,<
	MOVE	SRCBP,SRA.BP##
	MOVE	SRCCC,SRA.CC##
>
	JRST	UNS20		;MATCHED, # CHARS IN "CT.VAL"

;THIS DELIM MATCHED. IF "ALL" SPECIFIED, TRY TO MATCH SOME MORE
UNS18:
IFN BIS,<
	DMOVE	DLMBP,DLM.BP##	;GET INITIAL DELIM PARAMS
>
IFE BIS,<
	MOVE	DLMBP,DLM.BP##
	MOVE	DLMCC,DLM.CC##
>
	TXNN	F,FL.ALL	;"ALL" SPECIFIED FOR THIS DELIM?
	 JRST	UNS19		;NO
	TXO	F,FL.MAT	;SET "MATCHED" FLAG
	ADDM	DLMCC,CT.DLM##	; BUMP COUNTER ANOTHER N PLACES

; SAVE POSITION OF THE SOURCE, INCASE IT STOPS MATCHING.
;IF IT DOES, THE SAVED POSITION WILL BE USED TO RESUME EXAMINATION
;OF THE SOURCE STRING.
IFN BIS,<
	DMOVEM	SRCBP,SRA.BP##
>
IFE BIS,<
	MOVEM	SRCBP,SRA.BP##
	MOVEM	SRCCC,SRA.CC##
>

	JRST	UNS17		;TRY FOR SOME MORE

;HERE IF DELIM MATCHED, 'ALL' NOT SPECIFIED
UNS19:	MOVEM	DLMCC,CT.DLM##	; # CHARS TO COPY
;	JRST	UNS20		;GO DO THIS DEST.
;HERE WHEN A DELIMITER MATCHED, # CHARS OF DELIMITER THAT MATCHED IN CT.DLM
; THE POSITION AND COUNT OF THE SOURCE STRING WHEN IT STARTED
;MATCHING THE DELIMITER IS IN SRD.BP AND SRD.CC.
; THE ADDRESS OF THE 2-WORD BLOCK DESCRIBING THIS DELIMITER IS IN NX.DLM

UNS20:	MOVE	T3,SRC.CC##	;FIND # CHARS TO COPY
	SUB	T3,SRD.CC##

;HERE WITH T3= # CHARS TO COPY TO DESTINATION.
; DST.BP , DST.CC , DSTBP AND DSTCC ARE ALL SETUP NOW.
; SRCBP AND SRCCC CONTAINS THE BP AND CC AFTER THE DELIMITER
; (TO START EXAMINATION FOR NEXT DESTINATION)

UNS21:	MOVEM	T3,CT.VAL##	;SAVE COUNT VALUE
	ADDM	T3,PT.VAL##	;ADJUST POINTER VALUE
	EXCH	SRCBP,SRC.BP##	;GET SOURCE BP, STORE NEW ONE
	EXCH	SRCCC,SRC.CC##	;GET SOURCE CC, STORE NEW ONE
	CAIGE	T3,(DSTCC)	;FILL UP THIS DEST?
	 JRST	UNS22		;NO, FILLER PROBLEMS

;DEST IS SMALLER THAN SOURCE. MOVE (DSTCC) CHARS.
	HRRZ	T1,NX.SRC##	;CHECK FOR RIGHT JUSTIFICATION
	MOVE	T2,(T1)
	TXNE	T2,US%RRJ	;IS THERE ANY?
	 JRST	UNS21A		;YES
UNS21B:	MOVE	T3,DSTCC	;# CHARS TO MOVE
	PUSHJ	PP,MOVSDS	;MOVE SOURCE TO DEST..
	SKIPE	TAG,TAG.DA##	;STORE DELIM AWAY FROM OU.TMP?
	 PUSHJ	PP,CALTAG	;YES
	JRST	UNS30		;GO STORE DELIM STORE

;RIGHT-JUSTIFICATION, HAVE TO SKIP OVER SOURCE CHARS
UNS21A:	SUB	T3,DSTCC	;# CHARS TO ADJUST SOURCE
	JUMPE	T3,UNS21B	;JUMP IF NO ADJUSTMENT NEEDED
	SUB	SRCCC,T3
	IBP	SRCBP
	SOJG	T3,.-1
	JRST	UNS21B		;FINISHED ADJUSTING SOURCE

;WORRY ABOUT JUSTIFICATION IN DESTINATION
UNS22:	HRRZ	T1,NX.SRC##	;POINT TO THIS ENTRY
	MOVE	T2,(T1)		;GET FLAG WORD
	TXNE	T2,US%RRJ	;IS RECEIVING ITEM RIGHT-JUSTIFIED?
	 JRST	UNS23		;YES, GO DO THAT

;NORMAL JUSTIFICATION. MOVE (T3) CHARS, THEN PAD THE REST
	PUSHJ	PP,MOVSDS	;MOVE THE CHARS
	MOVE	T1,DSTCC	;# CHARS LEFT IN DEST..
	PUSHJ	PP,PADDST	;PAD IT OUT
	JRST	UNS30		;GO STORE DELIM STORE

;RIGHT JUSTIFICATION. PAD, THEN MOVE (T3) CHARS.
UNS23:	HRRZ	T1,DSTCC	;FIND # CHARS TO PAD
	SUB	T1,T3
	PUSH	PP,T3		;SAVE # CHARS TO MOVE
	PUSHJ	PP,PADDST
	POP	PP,T3		;RESTORE # CHARS TO MOVE
	PUSHJ	PP,MOVSDS	;MOVE (T3) CHARS
	SKIPE	TAG,TAG.DA##	;STORE DELIM AWAY FROM OU.TMP?
	 PUSHJ	PP,CALTAG	;YES
;	JRST	UNS30		;GO STORE DELIM STORE
;PUT DELIMITER IN DELIMITER STORE
UNS30:	MOVE	T1,CT.DLM##	;# CHARS IN DELIMITER
	ADDM	T1,PT.VAL##	;WE WILL SKIP OVER THIS MANY SOURCE CHARS
	HRRZ	T1,NX.SRC##	;FIND THIS ENTRY
	MOVE	T2,(T1)		;GET FLAGS
	TXNN	T2,US%GDS	;DO WE HAVE A DELIMITER STORE?
	 JRST	UNS80		;NO

IFN BIS,<
	DMOVE	DLMBP,DLM.BP##	;GET THIS DELIMITER BP AND CC
>
IFE BIS,<
	MOVE	DLMBP,DLM.BP##
	MOVE	DLMCC,DLM.CC##
>
IFN ANS74,<
;IF "ALL" WAS SPECIFIED, WE ONLY STORE 1 OCCURANCE OF THE DELIMITER
; IN THE DELIMITER STORE.  ANS68 STORED THE ACTUAL TEXT OF THE DELIMITER.
	HRRZ	T2,CT.DLM##	;GET # CHARS IN REAL DELIMITER
	CAILE	T2,(DLMCC)	;IF BIGGER THAN DELIM SIZE,
	MOVE	T2,DLMCC	; USE # CHARS IN THE DELIMITER
	MOVEM	T2,CT.DLM##	;PRETEND THIS IS NEW DELIM COUNT
>;END IFN ANS74
	MOVE	T3,3(T1)	;GET %TAG1, %TAG2
	HLRZM	T3,TAG.ST##	;TAG TO SETUP %TEMP FOR DELIM STORE
	HRRZM	T3,TAG.DA##	;TAG TO STORE DELIM STORE AWAY FROM OU.TMP

	HRRZ	T2,2(T1)	;%LIT OR %TEMP
	MOVEM	T2,DST.TP##	; STORE AWAY

;SETUP BP AND CC IN DSTBP AND DSTCC
	SKIPE	TAG,TAG.ST##	;HAVE TO SETUP %TEMP?
	 PUSHJ	PP,CALTAG	;YES, GO DO IT
IFN BIS,<
	DMOVE	DSTBP,@DST.TP##	;GET BP AND CC FOR DELSTORE
>
IFE BIS,<
	MOVE	DSTBP,DST.TP##
	MOVE	DSTCC,1(DSTBP)
	MOVE	DSTBP,0(DSTBP)
>
; SETUP THE INSTRUCTION TO CONVERT FROM DELIM MODE TO DELSTORE MODE,
; AND PUT IN CV
	LDB	T4,[POINT 3,2(T1),17] ;GET BSI OF DELSTORE ITEM
	HRRZ	T1,NX.DLM	;GET DELIMITER ARGUMENTS
	MOVE	T2,(T1)		;GET FLAG WORD
	LDB	T3,[POINT 3,T2,17] ;CONVERT FROM MODE OF DELIMITER.
	XCT	TT.CVD(T4)	;SETUP CV= CONVERSION INSTRUCTION

	MOVE	T3,CT.DLM##	;GET # CHARS TO COPY TO DEST.
	CAIGE	T3,(DSTCC)	;FILL UP THIS DELSTORE?
	 JRST	UNS35		;NO, HAVE TO PAD

;DELSTORE IS SMALLER (OR EQUAL IN SIZE) TO # CHARS TO STORE.
;  MOVE (DSTCC) CHARS.
	HRRZ	T1,NX.SRC
	MOVE	T2,2(T1)	;GET FLAGS
	TXNE	T2,DS%JST	;RIGHT-JUSTIFIED DELSTORE?
	 JRST	UNS33		;YES

	MOVE	T3,DSTCC
	PUSHJ	PP,MOVDDS	;MOVE DELIMITER TO DELSTORE
	JRST	UNS39		;MOVE DONE

;HERE IF DELSTORE IS RIGHT-JUSTIFIED, AND WE ARE TRUNCATING.
UNS33:	SUB	T3,DSTCC	;# CHARS TO SKIP OVER IN DELIM
UNS33A:	SOJL	T3,UNS34	;JUMP WHEN DONE
	SUBI	DLMCC,1
	IBP	DLMBP		;SKIP OVER A CHAR IN DELIMITER
IFN BIS,<
	SKIPN	DLMCC		; AT END OF DELIMITER?
	DMOVE	DLMBP,DLM.BP##	;YES, SET TO BEGINNING AGAIN
>
IFE BIS,<
	SKIPE	DLMCC
	JRST	UNS33A
	MOVE	DLMBP,DLM.BP##
	MOVE	DLMCC,DLM.CC##
>
	JRST	UNS33A		;LOOP TO SKIP CHARS

UNS34:	MOVE	T3,DSTCC	;# CHARS TO MOVE
	PUSHJ	PP,MOVDDS	;MOVE DELIMITER TO DELSTORE
	JRST	UNS39		;MOVE DONE

;WORRY ABOUT JUSTIFICATION IN DELSTORE
UNS35:	HRRZ	T1,NX.SRC##
	MOVE	T2,2(T1)	;GET FLAG WORD
	TXNE	T2,DS%JST	; IS DEL STORE JUST RIGHT?
	 JRST	UNS37		;YES

;NORMAL JUSTIFICATION.
	PUSHJ	PP,MOVDDS	;MOVE (T3) CHARS
	MOVE	T1,DSTCC	;# CHARS LEFT IN DELSTORE
	PUSHJ	PP,PADDLS	;PAD THE DELSTORE
	JRST	UNS39		;DONE

;RIGHT JUSTIFICATION IN DELSTORE.
UNS37:	HRRZ	T1,DSTCC	;FIND # CHARS TO PAD WITH
	SUB	T1,T3
	PUSH	PP,T3		;SAVE # CHARS TO MOVE
	PUSHJ	PP,PADDLS	;PAD IT
	POP	PP,T3		;RESTORE # CHARS TO MOVE
	PUSHJ	PP,MOVDDS	;MOVE (T3) CHARS
;	JRST	UNS39		;DONE THE MOVE

;THE MOVE IS DONE (TO DELIMITER STORE).
; STORE IT AWAY FROM OU.TMP IF NECESSARY.
UNS39:	SKIPE	TAG,TAG.DA##
	 PUSHJ	PP,CALTAG

;DELIM STORE IS STORED. BUMP THE COUNT AND TALLY ITEMS
UNS80:	PUSHJ	PP,BMPTAL	;BUMP TALLY ITEM
	SKIPE	TAG,TAG.CT	; IF COUNT ITEM PRESENT,
	 PUSHJ	PP,CALTAG	;STORE THE VALUE
	SKIPE	TAG,TAG.PT##	;IF POINTER ITEM PRESENT,
	 PUSHJ	PP,CALTAG	;STORE THE NEW VALUE
IFN BIS,<
	DMOVE	SRCBP,SRC.BP##	;GET NEW POSITION TO START IN SOURCE
>
IFE BIS,<
	MOVE	SRCBP,SRC.BP##
	MOVE	SRCCC,SRC.CC##
>

	JRST	UNS05B		;GO ON TO NEXT DESTINATION

;HERE TO RETURN FROM UNSTRING
UNSDON:	POPJ	PP,

;HERE WHEN OVERFLOW OCCURS IN UNSTRING STMT.
UNSOVL:	TXO	F,FL.OVF	;SET "OVERFLOW" FLAG
	JRST	UNSDON		;AND GO DO FINAL ACTIONS

SUBTTL SUBROUTINES

;ROUTINE TO CALL A TAG ROUTINE.
;ENTER WITH TAG/  ROUTINE ADDRESS
;	PUSHJ	PP,CALTAG
;	<RETURNS HERE AFTER ROUTINE DONE>
;ALL ACS ARE PRESERVED EXCEPT 16 AND 17

CALTAG:	MOVEM	0,SSACB.##	;SAVE AC0
	MOVE	0,[1,,SSACB.+1]
	BLT	0,SSACB.+15	;SAVE AC1-AC15
	PUSHJ	PP,@TAG		;CALL THE USER ROUTINE
	MOVE	0,[SSACB.+1,,1]	;RESTORE ACS
	BLT	0,15
	MOVE	0,SSACB.	;RESTORE AC0
	POPJ	PP,		;RETURN

;ROUTINE TO BUMP THE TALLYING ITEM
; ONLY DESTROYS AC "TAG"
BMPTAL:	AOS	TL.VAL##	;COUNT ANOTHER RECEIVING ITEM ACTED UPON
	SKIPE	TAG,TAG.TL##	;WAS THERE A TAG FOR THE TALLYING ITEM?
	 PUSHJ	PP,CALTAG	;YES, CALL ROUTINE TO STORE IT
	POPJ	PP,		;NO, RETURN


;ROUTINE TO GO ON TO NEXT DESTINATION.
;FIGURES OUT HOW MUCH TO BUMP NX.SRC.

NXTDST:	HRRZ	T1,NX.SRC##	;CURRENT DEST ARGUMENTS
	MOVE	T2,(T1)		;GET FLAG WORD
	TXNE	T2,US%GDS	;GOT A DELIM STORE?
	ADDI	T1,2		;YES, TWO WORDS FOR IT
	TXNE	T2,US%GCT	;GOT A COUNT ITEM?
	ADDI	T1,1		;YES, ONE WORD FOR IT
	ADDI	T1,2		;+2 FOR THE DEST ITEM
	MOVEM	T1,NX.SRC##	;SAVE START OF NEXT DEST.
	POPJ	PP,		;RETURN
;ROUTINE TO MOVE CHARS FROM SOURCE TO DEST.
;CALL:	T3/ # CHARS TO MOVE
;	PUSHJ PP,MOVSDS
;	<RETURNS HERE>

MOVSDS:	SOJL	T3,CPOPJ	;JUMP IF NO MORE CHARS TO MOVE
	ILDB	T1,SRCBP	;GET A SOURCE CHAR
	SUBI	SRCCC,1		;ADJUST SRC PTR
	XCT	CV.SDS##	;CONVERT TO DEST MODE
	IDPB	T1,DSTBP	;STORE IN DEST STRING
	SUBI	DSTCC,1		;ADJUST DST COUNT
	JRST	MOVSDS		;GO ON TO NEXT CHAR


;ROUTINE TO MOVE CHARS FROM DELIMITER TO DELSTORE.
;CALL:	T3/ # CHARS TO MOVE
;	CV/ INSTRUCTION TO CONVERT DELIM CHARS TO DELSTORE MODE CHARS
;	DLMBP AND DLMCC ARE CURRENT PTR TO DELIMITER.
;	PUSHJ	PP,MOVDDS
;	<RETURNS HERE>

MOVDDS:	SOJL	T3,CPOPJ	;JUMP IF NO MORE CHARS TO MOVE
	ILDB	T1,DLMBP	;GET A CHAR FROM DELIMITER
	SUBI	DLMCC,1		;ADJUST DELIM PTR
	XCT	CV		;CONVERT TO DELSTORE MODE
	IDPB	T1,DSTBP	;STORE IN DELSTORE
	SUBI	DSTCC,1
	JUMPG	DLMCC,MOVDDS	;KEEP GOING IF MORE CHARS IN DELIMITER
IFN BIS,<
	DMOVE	DLMBP,DLM.BP##	;SETUP DELIM AGAIN ("ALL" WAS SPECIFIED")
>
IFE BIS,<
	MOVE	DLMBP,DLM.BP##
	MOVE	DLMCC,DLM.CC##
>
	JRST	MOVDDS		;CONTINUE ON

;ROUTINE TO PAD THE DESTINATION.
;CALL:	T1/ # CHARS TO PAD
;	NX.SRC POINTS TO DEST ENTRY
; DSTBP AND DSTCC WILL BE MODIFIED.

PADDST:	HRRZ	T4,NX.SRC##	;POINT TO ENTRY
	LDB	T3,[POINT 3,(T4),17] ;GET BSI OF DEST.
	MOVE	T2,(T4)		;;GET FLAGS
	TXNE	T2,US%RIN	;IS RECEIVING ITEM NUMERIC?
	 JRST	PADZRO		;YES, PAD WITH ZEROES
	HLRZ	T2,SPCZRO(T3)	;GET A SPACE IN PROPER MODE
	JRST	PADDS1		;GO DO IT
PADZRO:	HRRZ	T2,SPCZRO(T3)	;GET A ZERO IN PROPER MODE
PADDS1:	IDPB	T2,DSTBP	;STORE A PAD CHAR IN DEST.
	SUBI	DSTCC,1		;FIX DEST COUNT
	SOJG	T1,PADDS1	;LOOP FOR ALL CHARS WE ARE SUPPOSED TO PAD
CPOPJ:	POPJ	PP,		;THEN RETURN

;ROUTINE TO PAD THE DELIMITER-STORE ITEM.
;JUST LIKE PADDST, EXCEPT LOOKS AT A DIFFERENT BIT.
PADDLS:	HRRZ	T4,NX.SRC##	;POINT TO ENTRY
	LDB	T3,[POINT 3,2(T4),17] ;GET BSI OF DELSTORE
	MOVE	T2,2(T4)		;GET FLAGS
	TXNE	T2,DS%NUM	;IS DELIM STORE NUMERIC?
	 JRST	PADZRO		;YES, PAD WITH ZEROES
	HLRZ	T2,SPCZRO(T3)	;NO, PAD WITH SPACES
	JRST	PADDS1

SPCZRO:	XWD	0,20		;SIXBIT SPACE,,ZERO
	XWD	40,60		;ASCII SPACE,,ZERO
	XWD	100,360		;EBCDIC SPACE,,ZERO
SUBTTL	TABLES

;TT.CVD - CONVERT CHARACTERS FROM ONE MODE TO ANOTHER
;INDEXED BY BSI OF SOURCE ITEM
; T3 CONTAINS THE BSI OF THE DESTINATION CHARACTERS
;CV WILL BE THE INSTRUCTION TO CONVERT THE CHARACTER IN T1

TT.CVD:	MOVE	CV,TT.RE6(T3)
	MOVE	CV,TT.RE7(T3)
	MOVE	CV,TT.RE9(T3)

TT.RE6:	NOP
	LDB	T1,IPT761##
	LDB	T1,IPT961##

TT.RE7:	LDB	T1,IPT671##
	NOP
	LDB	T1,IPT971##

TT.RE9:	LDB	T1,IPT691##
	LDB	T1,IPT791##
	NOP

END