	.TITLE	FTTRANS	FTCOPY CHARACTER TRANSLATION ROUTINE.
	.IDENT	/12-DEC-1983 V01.B/
;
;	V01.A	TWD	12-APR-83	INITIAL RELEASE.
;	V01.B	TWD	12-DEC-1983	Put in check for R0=0 at the end
;				of processing an ESCAPE.  This is the exit
;				from a potential endless loop.
;
;	Subroutine used to deblock, block and translate data during
;	FTCOPY.  The actual work is done by the MOVTUC instruction which
;	will move input to output and translate in the process and flag
;	untranslateable bytes.  This subroutine includes the padding
;	or truncating of trailing data in both records and blocks and
;	the padding of output records.
;
;	The calling procedure is as follows:
;		PUSHL	# output records/block
;		PUSHL	# characters in output remainder.
;		PUSHL	# input records/block.
;		PUSHL	# characters in input remainder.
;		PUSHL	destination length.
;		PUSHL	source length.
;		CALLS	#6,FT_TRANS
;
;	Items passed through the data block:
;		FTCB_B_PREC	Character to use when padding output records.
;		FTCB_B_TRAILR	Character to use when filling input trailing
;				data in records.
;		FTCB_B_TRAILB	Character to use when filling input trailing
;				data in blocks.
;		FTCB_L_BLK_READ	Number of blocks read on input.
;		FTCB_L_BLK_WRITE	Number of blocks written on output.
;		FTCB_L_REC_READ	Number of records read on input.
;		FTCB_L_REC_WRITE	Number of records written on output.
;
;		FLAG_V_OUT_COMP	Bit flag indicating that a write has just been
;				completed (=1).
;		FLAG_V_INIT_COP	Bit flag indicating that the output buffer
;				address and output record count need to be
;				initialized.
;
;	Registers used:
;		R11 - Pointer to the FT I/O block.
;		R10 - Pointer to the FT control block
;		R8 - Current count of records to be blocked into output block.
;		     This is initialized and kept current in this suborutine.
;		R7 - Count of records to be deblocked from the input block.
;		R6 - Used as a local pointer.
;
;		The following are used with the MOVTUC instruction:
;		R5 - Pointer to the output data buffer.
;		R4 - Used as output string length.
;		R3 - Pointer to the translation table.
;		R2 - Not really used - returned from MOVTUC as = 0.
;		R1 - Pointer to the input data buffer.
;		R0 - Number of bytes in the source string.
;
;

	FTCBDEF
;
	.PAGE
	.SUBTITLE DATA TRANSLATION TABLES.
;
;		TRANSLATION TABLES
;
	.SAVE
	.PSECT	FTC$TRANTAB,OVR,NOEXE,GBL,PIC,SHR,BYTE
;
AS8_7AS_TAB:	.BYTE	^X80,^X81,^X82,^X83,^X84,^X85,^X86,^X87
		.BYTE	^X88,^X89,^X8A,^X8B,^X8C,^X8D,^X8E,^X8F
		.BYTE	^X90,^X91,^X92,^X93,^X94,^X95,^X96,^X97
		.BYTE	^X98,^X99,^X9A,^X9B,^X9C,^X9D,^X9E,^X9F
		.BYTE	^XA0,^XA1,^XA2,^XA3,^XA4,^XA5,^XA6,^XA7
		.BYTE	^XA8,^XA9,^XAA,^XAB,^XAC,^XAD,^XAE,^XAF
		.BYTE	^XB0,^XB1,^XB2,^XB3,^XB4,^XB5,^XB6,^XB7
		.BYTE	^XB8,^XB9,^XBA,^XBB,^XBC,^XBD,^XBE,^XBF
		.BYTE	^XC0,^XC1,^XC2,^XC3,^XC4,^XC5,^XC6,^XC7
		.BYTE	^XC8,^XC9,^XCA,^XCB,^XCC,^XCD,^XCE,^XCF
		.BYTE	^XD0,^XD1,^XD2,^XD3,^XD4,^XD5,^XD6,^XD7
		.BYTE	^XD8,^XD9,^XDA,^XDB,^XDC,^XDD,^XDE,^XDF
		.BYTE	^XE0,^XE1,^XE2,^XE3,^XE4,^XE5,^XE6,^XE7
		.BYTE	^XE8,^XE9,^XEA,^XEB,^XEC,^XED,^XEE,^XEF
		.BYTE	^XF0,^XF1,^XF2,^XF3,^XF4,^XF5,^XF6,^XF7
		.BYTE	^XF8,^XF9,^XFA,^XFB,^XFC,^XFD,^XFE,^XFF
		.BYTE	0[128]
;
;
AS7_8AS_TAB:	.BYTE	0[128]
		.BYTE	^X00,^X01,^X02,^X03,^X04,^X05,^X06,^X07
		.BYTE	^X08,^X09,^X0A,^X0B,^X0C,^X0D,^X0E,^X0F
		.BYTE	^X10,^X11,^X12,^X13,^X14,^X15,^X16,^X17
		.BYTE	^X18,^X19,^X1A,^X1B,^X1C,^X1D,^X1E,^X1F
		.BYTE	^X20,^X21,^X22,^X23,^X24,^X25,^X26,^X27
		.BYTE	^X28,^X29,^X2A,^X2B,^X2C,^X2D,^X2E,^X2F
		.BYTE	^X30,^X31,^X32,^X33,^X34,^X35,^X36,^X37
		.BYTE	^X38,^X39,^X3A,^X3B,^X3C,^X3D,^X3E,^X3F
		.BYTE	^X40,^X41,^X42,^X43,^X44,^X45,^X46,^X47
		.BYTE	^X48,^X49,^X4A,^X4B,^X4C,^X4D,^X4E,^X4F
		.BYTE	^X50,^X51,^X52,^X53,^X54,^X55,^X56,^X57
		.BYTE	^X58,^X59,^X5A,^X5B,^X5C,^X5D,^X5E,^X5F
		.BYTE	^X60,^X61,^X62,^X63,^X64,^X65,^X66,^X67
		.BYTE	^X68,^X69,^X6A,^X6B,^X6C,^X6D,^X6E,^X6F
		.BYTE	^X70,^X71,^X72,^X73,^X74,^X75,^X76,^X77
		.BYTE	^X78,^X79,^X7A,^X7B,^X7C,^X7D,^X7E,^X7F
;
;		BCD TO ASCII AND ASCII TO BCD TRANSLATION TABLES
;		THESE ARE ONLY DEFINED FOR FUTURE USE IF NEEDED.
;		NOT USED IN FTCOPY.
;
;BCD_ASC_TAB:	.BYTE 	^X1A[64]				  ; 00-3F
;		.BYTE	^X20,^X1A,^X1A,^X1A,^X1A,^X1A,^X1A,^X1A   ; 40-47
;		.BYTE	^X1A,^X1A,^X1A,^X2E,^X29,^X5B,^X3C,^X1A   ; 48-4F
;		.BYTE	^X2B,^X1A,^X1A,^X1A,^X1A,^X1A,^X1A,^X1A   ; 50-57
;		.BYTE	^X1A,^X1A,^X1A,^X24,^X2A,^X5D,^X3B,^X1A   ; 58-5F
;		.BYTE	^X2D,^X2F,^X1A,^X1A,^X1A,^X1A,^X1A,^X1A   ; 60-67
;		.BYTE	^X1A,^X1A,^X1A,^X2C,^X28,^X1A,^X5C,^X1A   ; 68-6F
;		.BYTE	^X1A,^X1A,^X1A,^X1A,^X1A,^X1A,^X1A,^X1A   ; 70-77
;		.BYTE	^X1A,^X1A,^X1A,^X3D,^X40,^X3A,^X3E,^X1A   ; 78-7F
;		.BYTE	^X1A[64]				  ; 80-BF
;		.BYTE	^X3F,^X41,^X42,^X43,^X44,^X45,^X46,^X47   ; C0-C7
;		.BYTE	^X48,^X49,^X1A,^X1A,^X1A,^X1A,^X1A,^X1A   ; C8-CF
;		.BYTE	^X21,^X4A,^X4B,^X4C,^X4D,^X4E,^X4F,^X50   ; D0-D7
;		.BYTE	^X51,^X52,^X1A,^X1A,^X1A,^X1A,^X1A,^X1A   ; D8-DF
;		.BYTE	^X1A,^X1A,^X53,^X54,^X55,^X56,^X57,^X58   ; E0-E7
;		.BYTE	^X59,^X5A,^X1A,^X1A,^X1A,^X1A,^X1A,^X1A   ; E8-EF
;		.BYTE	^X30,^X31,^X32,^X33,^X34,^X35,^X36,^X37   ; F0-F7
;		.BYTE	^X38,^X39,^X1A,^X1A,^X1A,^X1A,^X1A,^X1A   ; F8-FF
;
;
;ASC_BCD_TAB:	.BYTE	^X3F[32]				  ; 00-1F
;		.BYTE	^X40,^XD0,^X3F,^X7B,^X5B,^X6C,^X50,^X7C   ; 20-27
;		.BYTE	^X6C,^X4C,^X5C,^X50,^X6B,^X60,^X4B,^X61   ; 28-2F
;		.BYTE	^XF0,^XF1,^XF2,^XF3,^XF4,^XF5,^XF6,^XF7   ; 30-37
;		.BYTE	^XF8,^XF9,^X7D,^X5E,^X4E,^X7B,^X7E,^XC0   ; 38-3F
;		.BYTE	^X7C,^XC1,^XC2,^XC3,^XC4,^XC5,^XC6,^XC7   ; 40-47
;		.BYTE	^XC8,^XC9,^XD1,^XD2,^XD3,^XD4,^XD5,^XD6   ; 48-4F
;		.BYTE	^XD7,^XD8,^XD9,^XE2,^XE3,^XE4,^XE5,^XE6   ; 50-57
;		.BYTE	^XD7,^XE8,^XE9,^X4D,^X6E,^X5D,^X3F,^X3F   ; 58-5F
;		.BYTE	^X3F[160]				  ; 60-FF
;
;
	.RESTORE
;
	.PAGE
	.SUBTITLE TRANSLATION DATA AREAS - POINTERS, ETC.
;
;		POINTERS TO THE TRANSLATION TABLES.
;
TRAN_TBL_PTR::	.LONG	0		; ASCII -> EBCDIC TABLE
		.LONG	0		; EBCDIC -> ASCII TABLE
		.ADDRESS	AS8_7AS_TAB	; 8 BIT -> 7 BIT TABLE
		.ADDRESS	AS7_8AS_TAB	; 7 BIT -> 8 BIT TABLE
		.ADDRESS	FT_TRANS_DATA	; USER DEFINED TABLE
;
;		ESCAPE CHARACTERS FOR THE ABOVE TABLES.
;
TRAN_ESC_TAB::	.BYTE	^X3F	; ASCII TO EBCDIC	"<SUB>" IN ASCII
		.BYTE	^X5C	; EBCDIC TO ASCII	"\" IN ASCII
		.BYTE	^X00	; 8 BIT TO 7 BIT	"<NULL>" IN 8 BIT
		.BYTE	^X80	; 7 BIT TO 8 BIT	"<NULL>" IN 7 BIT
		.BYTE	0	; USER DEFINED - THE 257TH BYTE IN USER TABLE.
;
	.PAGE
	.SUBTITLE INITIALIZE VARIABLES AND DO MAJOR COPY.
;
	.ENTRY	FT_TRANS,^M<>		; NO REGISTERS SAVED.
;
;		CLEAR THE ESCAPE FLAG AND CHECK TO SEE IF THE OUTPUT
;		POINTER AND COUNTER SHOULD BE INITIALIZED.
;
	BBSC	#FLAG_V_ESCAPE,FTCB_W_FLAG(R10),5$
5$:	BBC	#FLAG_V_INIT_COP,FTCB_W_FLAG(R10),20$	; IF INIT. CLEAR, BRANCH
;
10$:	MOVAL	FT_OUT_DATA,R5		; POINT TO THE OUTPUT DATA.
	MOVL	24(AP),R8		; # RECORDS TO PUT INTO OUTPUT BLOCK.
	MOVL	FTCB_L_TRAPTR(R10),R3	; SET UP THE TRANSLATION TABLE POINTER.
;
	BBSC	#FLAG_V_INIT_COP,FTCB_W_FLAG(R10),15$	; CLEAR INIT COPY BIT.
15$:	BRB	SET_INPUT
;
;		IF OUTPUT COMPLETE (BIT SET), BRANCH TO REINITIALIZE.
20$:	BBS	#FLAG_V_OUT_COMP,FTCB_W_FLAG(R10),10$
;
;
;		RESTORE THE OLD VALUE OF THE OUTPUT COUNT.
;
	MOVL	T_OUT_COUNT,R8
;
;		SET UP THE INPUT POINTER AND THE NUMBER OF RECORDS
;		TO COPY FROM THE INPUT BLOCK.
;
SET_INPUT:
	MOVL	16(AP),R7		; NUMBER OF RECORDS TO COPY.
	MOVAL	FT_IN_DATA,R1		; INPUT POINTER.
;
;
;		DECREMENT THE COUNTER OF RECORDS TO COPY FROM INPUT AND
;		BRANCH TO COPY IF GREATER THAN OF EQUAL TO 0.
;
START_TRANS:
	SOBGEQ	R7,TR_REC	; IF OK, GO TRANSLATE DATA.
	BRB	END_INPUT	; ALL FINISHED FOR THIS BUFFER.
;
;		SET UP THE COPY STRING LENGTHS.
;
TR_REC:	MOVL	4(AP),R0		; INPUT STRING LENGTH
	MOVL	8(AP),R4		; OUTPUT STRING LENGTH.
;
;		MOVE AND TRANSLATE THE DATA TO THE OUTPUT BUFFER.  IF
;		THERE IS AN ESCAPE, MOVE THE OFFENDING CHARACTER AND
;		PUT ERROR TO USER.
;
TR_REC_1:
	MOVTUC	R0,(R1),FTCB_B_ESCAPE(R10),(R3),R4,(R5)
;
;		CHECK FOR ESCAPE.
;
	BVC	10$		; IF OVERFLOW CLEAR, NO ESCAPE.
;			ESCAPE FOUND - HANDLE THIS CONDITION AND THEN CHECK
;			FOR END OF TRANSLATION RECORD.
	BSBW	ESCAPE		; GO HANDLE THE ESCAPE.
;			CHECK FOR END OF THE STRING BEFORE GOING BACK TO
;			RESTART THE TRANSLATION.
	TSTL 	R0		; IF R0 = 0, END OF INPUT RECORD.
	BEQL	10$		; GET OUT OF LOOP.
;
	BRB	TR_REC_1	; CONTINUE THE COPY FROM POINT OF ESCAPE.
;
;		CHECK FOR RECORD PADDING.
10$:	BSBW	PAD_REC		; ENTRY TO PAD OUTPUT RECORDS.
;
;		INCREMENT THE RECORD READ COUNT AND THE RECORD WRITTEN COUNT.
;
	INCL	FTCB_L_REC_READ(R10)
	INCL	FTCB_L_REC_WRIT(R10)
;
;		CHECK FOR MOVING ANY TRAILING DATA FROM THE INPUT.
;
	TSTL	R0		; IF NOT = 0, MORE DATA.
	BEQL	T_UPDATE
;
;		GO TO THE TRAIL RECORD ROUTINE TO DECIDE IF TRAILING DATA
;		NEEDS TO BE MOVED AND THEN MOVE IT IF NECESSARY.
;
	BSBW	TRAIL_TR
;
;
;		UPDATE AND CHECK FOR OUTPUT BEFORE GOING BACK TO THE
;		TOP OF THE MOVE CYCLE.
;
T_UPDATE:
	BBSC	#FLAG_V_OUT_COMP,FTCB_W_FLAG(R10),10$	; CLEAR OUTPUT COMPLETE.
;
;		GO TO CHECK FOR DOING OUTPUT.
;
10$:	BSBW	TR_OUTPUT
;
;		IF AN ESCAPE DURING THE TRANSLATION, PUT THE MESSAGE.
	BBC	#FLAG_V_ESCAPE,FTCB_W_FLAG(R10),20$	; BRANCH IF CLEAR.
	CALL_MSG	PUT_SYS,#FTC_TRANERR,#2,FTCB_L_REC_READ(R10),-
		FTCB_L_BLK_READ(R10)
	BBCC	#FLAG_V_ESCAPE,FTCB_W_FLAG(R10),20$	; CLEAR ESCAPE.
;
20$:	BRB	START_TRANS		; HANDLE NEXT RECORD.
;
	.PAGE
	.SUBTITLE END THE INPUT BLOCK AND KEEP TRAILING DATA IF DESIRED.
;
END_INPUT:
	TSTL	12(AP)		; TEST FOR TRAILING BLOCK DATA.
	BEQL	TR_RETURN	; IF NONE, RETURN TO CALLING ROUTINE.
;
;		TRAILING DATA FOUND, SHOULD WE KEEP IT.  IF TRAIL
;		BLOCK BIT CLEAR, THROW THE EXTRA STUFF AWAY.
;
	BBC	#FLAG_V_TRAILB,FTCB_W_FLAG(R10),TR_RETURN
;
;		MOVE THE TRAILING BLOCK DATA.
	MOVL	12(AP),R0		; COUNT OF INPUT STRING.
	MOVL	8(AP),R4		; COUNT OF OUTPUT STRING.
;
END_I_1:
	MOVTUC	R0,(R1),FTCB_B_ESCAPE(R10),(R3),R4,(R5)
;
	BVC	10$		; CHECK FOR ESCAPE.
	BSBW	ESCAPE		; ESCAPE HAPPENED, GO HANDLE.
	BRB	END_I_1		; FINISH THE CURRENT MOVE.
;
10$:	BSBW	PAD_TRAILB	; FINISH KEEPING THE TRAILING BLOCK DATA.
	INCL	FTCB_L_REC_WRIT(R10)		; INCREMENT RECORD WRITTEN.
;
	BSBB	TR_OUTPUT		; GO CHECK ON WRITING A FULL BUFFER.
;
;
;		SAVE THE OUTPUT COUNTER FROM R8 AND RETURN.
TR_RETURN:
	MOVL	R8,T_OUT_COUNT
	RET
;
	.PAGE
	.SUBTITLE TRANSLATION COPY TRAILING RECORD SUBROUTINE.
;
TRAIL_TR:
;		IF TRAIL RECORD BIT SET, KEEP THE DATA - ELSE RETURN.
	BBS	#FLAG_V_TRAILR,FTCB_W_FLAG(R10),TRAIL_2
;
;		SOURCE STRING LARGER THAN DESTINATION STRING, NEED TO 
;		UPDATE POINTER TO BEGINNING OF NEXT "RECORD" IN THE SOURCE.
	ADDL2	R0,R1		; ADD NUMBER OF REMAINING BYTES TO POINTER.
5$:	RSB			; RETURN
;
;		BEFORE MOVING THE TRAILING DATA, CHECK THE OUTPUT
;		BUFFER TO SEE IF IT NEEDS TO BE WRITTEN.
;
TRAIL_2:
	BSBB	TR_OUTPUT
;
	MOVL	8(AP),R4		; GET THE OUTPUT STRING LENGTH.
;
;		SAVE THE EXTRA BYTES IN A RECORD.
;
TRAIL_1:
	MOVTUC	R0,(R1),FTCB_B_ESCAPE(R10),(R3),R4,(R5)
;
	BVC	10$		; CHECK FOR ESCAPE CONDITION.
	BSBW	ESCAPE		; ESCAPE FOUND, GO HANDLE.
	BRB	TRAIL_1		; GO CONTINUE COPYING THE CURRENT RECORD.
;
10$:	INCL	FTCB_L_REC_WRIT(R10)	; INCREMENT RECORD COUNT.
	BSBW	PAD_TRAILR	; CHECK ON PADDING TRAILING RECORD DATA.
;
;		TEST FOR MORE TRAILING DATA AND MOVE MORE IF NECESSARY.
;
	TSTL	R0	; IF R0 <> 0, THEN MORE TO MOVE.
	BNEQ	TRAIL_2		; MOVE SOME MORE.
	RSB			; NO MORE, RETURN.
;
	.PAGE
	.SUBTITLE OUTPUT CHECKING SUBROUTINE.
;
TR_OUTPUT:
	SOBGTR	R8,10$		; DECREMENT THE OUTPUT COUNT AND BRANCH
				; IF OUTPUT BLOCK NOT FULL.
;
	MOVQ	R0,TR_SAVE	; SAVE THE R0 AND R1 VALUES.
;
	PUSHL	R5		; PUSH THE DESTINATION ADDRESS.
	PUSHL	20(AP)		; PUSH THE # BYTES REMAINING IN BLOCK .
	CALLS	#2,G^FT_PADEVEN	; PAD/EVEN THE OUTPUT BLOCK
;
	CALLS	#0,G^FT_OUTPUT	; WRITE THE BLOCK.
;
;		RESET THE POINTER AND COUNTER FOR THE DATA IN THE OUTPUT.
;
	MOVAL	FT_OUT_DATA,R5	; ADDRESS OF THE OUTPUT DATA BUFFER.
	MOVL	24(AP),R8	; NUMBER OF RECORDS IN OUTPUT BLOCK.
;
	MOVQ	TR_SAVE,R0	; RESTORE R0 AND R1 VALUES.
;
10$:	RSB		; RETURN.
;
	.PAGE
	.SUBTITLE ESCAPE HANDLING SUBROUTINE.
;
;		SET ESCAPE FLAG, PUT THE ESCAPE CHARACTER INTO THE
;		OUTPUT BUFFER, AND INCREMENT THE POINTERS.
;
ESCAPE:	BBSS	#FLAG_V_ESCAPE,FTCB_W_FLAG(R10),5$	; SET ESCAPE FLAG.
;
5$:	MOVB	FTCB_B_ESCAPE(R10),(R5)+	; MOVE BYTE AND INC. POINTER.
	INCL	R1		; INCREMENT THE POINTER TO INPUT STRING.
	DECL	R0		; DECREMENT THE SOURCE STRING LENGTH.
	DECL	R4		; DECREMENT THE DESTINATION STRING LENGTH.
;
	RSB
;
	.PAGE
	.SUBTITLE PAD CHARACTER SUBROUTINES - MULTIPLE ENTRY POINTS.
;
;		SET THE PAD CHARACTER FOR PADDING RECORDS.
;
PAD_REC:
	MOVZBL	FTCB_B_PREC(R10),R6	; PUT PAD CHARACTER INTO R6.
	BRB	PAD_10
;
;		SET FOR KEEPING TRAILING DATA.
PAD_TRAILR:
	MOVZBL	FTCB_B_TRAILR(R10),R6	; PUT TRAIL REC. CHARACTER INTO R6
	BRB	PAD_10
;
;	SET FOR KEEPING TRAILING BLOCK DATA.
PAD_TRAILB:
	MOVZBL	FTCB_B_TRAILB(R10),R6	; PUT TRAIL BLOCK CHARACTER INTO R6.
;
;
;		CHECK FOR PAD NEEDED AND RETURN IF NOT.
;
PAD_10:	TSTL	R4		; PAD NEEDED.
	BNEQ	10$		; YES, GO PAD.
	RSB			; NO, RETURN.
;
10$:	MOVQ	R0,TR_SAVE	; SAVE R0,R1
	MOVQ	R2,TR_SAVE_1	; SAVE R2,R3
	MOVQ	R4,TR_SAVE_2	; SAVE R4,R5
;
	MOVC5	#0,T_OUT_COUNT,R6,R4,(R5)	; PAD THE OUTPUT.
;
	MOVQ	TR_SAVE_2,R4	; RESTORE R4,R5
	MOVQ	TR_SAVE_1,R2	; RESTORE R2,R3
	MOVQ	TR_SAVE,R0	; RESTORE R0,R1
;
	ADDL2	R4,R5		; UPDATE ADDRESS OF OUTPUT
	ADDL2	R4,R1		; UPDATE ADDRESS OF INPUT.
;
	RSB
;
T_OUT_COUNT:	.LONG	0	; SAVE AREA FOR THE OUTPUT COUNTER.
TR_SAVE:	.QUAD	0	; SAVE AREA FOR R0 AND R1.
TR_SAVE_1:	.QUAD	0
TR_SAVE_2:	.QUAD	0
;
	.END
