	.TITLE VERBUFF - ROUTINES TO BUFFER OUTPUT
;
;	NAME:	VERBUFF
;
;	LANGUAGE:  VAX-11 MACRO
;
;	OPERATING SYSTEM:  VAX/VMS
;
;	ORDER NUMBER:  12X-9XV
;
;	PART NUMBER:  000-025809-XXX REV. G  MAY, 1985
;
;	PRODUCT: VAX-11 DIAGNOSTIC,
;	PRODUCT: VAX/VMS DRIVER, SYMBIONT, AND OUTPUT PACKAGE
;
;	VERSATEC, INC., SANTA CLARA, CALIFORNIA 95051
;	A XEROX COMPANY
;
;	Copyright (C) 1985 by Xerox Corporation.  All rights reserved.
;
;	"NOTICE. THIS PROGRAM IS THE EXCLUSIVE PROPERTY OF VERSATEC,
;	INC. AND IS ISSUED IN STRICT CONFIDENCE UNDER A PREARRANGED
;	LICENSE AGREEMENT AND IS NOT TO BE DISCLOSED IN ANY MANNER TO
;	PERSONS OUTSIDE THE LICENSED ORGANIZATION AND SHALL NOT BE
;	REPRODUCED OR DISSEMINATED, IN WHOLE OR PART, TO ANYONE OUTSIDE
;	THE LICENSED ORGANIZATION WITHOUT THE PRIOR WRITTEN APPROVAL OF
;	VERSATEC, INC. UNLESS OTHERWISE PROVIDED FOR BY SUCH LICENSE
;	AGREEMENT.  THIS WORK IS PROTECTED AS AN UNPUBLISHED WORK UNDER
;	THE COPYRIGHT ACT OF 1976."
;
;
;	RELEASE DATE: OCT. 16, 1981
;		FIRST RELEASED WITH REV. B DRIVER
;
;	CHANGE HISTORY:
;
;	REV C - APRIL 30, 1982
;	No changes to this module.
;
;	REV D - JUNE 10, 1983 - P.D.
;	No changes to this module.
;
;	REV E - JUNE 27,1983 - P.D.
;	No changes to this module.
;
;	REV F - JUNE 15, 1984 - B.L. AND D.W.
;	Changes made to support remote output
;	module name changed from VERSPOOL to VERBUFF,
;	entry point names changed to emphasize use
;	is not only for spooling.
;
;	REV G - MAY, 1985 - B.L.
;	Remove routine VER_PARSE.
;
;	VERBUFF - SUBROUTINES TO PERFORM BUFFERED I/O OPERATIONS
;
;	The routines (VERFAB_GET, FILL_BUF, FLUSH_BUF) are used
;	to output either raster or data standard data for either
;	spooled or remote output.  The routines use the facilities
;	of RMS-32 to allow the use of double buffering and increase
;	the through-put of the plot package.
;
;
;	ENTRY:	CALL VERFAB_GET
;		This routine is called after subroutine OUTPUT
;		has setup the necessary tables for the output
;		file.  This routine will then get the RAB address
;		for the file and save it for later use in writing
;		to the file.
;
;	EXIT:	The file is open and the RAB address
;		stored for later use.
;
;
;	ENTRY:	CALL FILL_BUF (BUFFER,IBYTE)
;			BUFFER - Address of incoming data buffer
;			IBYTE  - Number of bytes in buffer
;
;	EXIT:	Block of data moved to internal buffer and
;		written to the file.
;
;
;	ENTRY:	CALL FLUSH_BUF
;
;	EXIT:	The last data in the output buffer is written
;		to the file.
;
;
;	ENTRY:	CALL SWAP_BYTE (BUFFER,IBYTE)
;
;	EXIT:	The data in BUFFER is swapped for IBYTEs.
;
;
;	ENTRY:	CALL REMOTE (REM_FUNC)
;
;	EXIT:	The remote function inserted into file
;
;
;	CALLED BY: OUTPUT, ATTACH, DETACH
;	CALLS:	$OPEN,$CREATE,$CONNECT,$PUT,$WAIT
;
; Equates
;
FABOFF	=	4		;Argument offset for FAB address
RABOFF	=	8		;Argument offset for RAB address
BUFFER	=	4		;Argument offset for FILL_BUF call
IBYTE	=	8		;Argument offset for FLUSH_BUF call
REM	=	4		;Argument offset for REMOTE call
DC3	=	19		;DC3 ascii character
;
	$NAMDEF			;DEFINE NAME BLOCK DEFINITIONS
	$RABDEF			;DEFINE RECORD ACCESS BLOCK DEFINITIONS
	$RMSDEF			;DEFINE RMS-32 DEFINITIONS
	$SSDEF			;DEFINE SYSTEM STATUS CODES
;
;	COMMON USED:
;
	.PSECT	VERBUF,PIC,OVR,REL,GBL,SHR,NOEXE,RD,WRT,LONG
FIL_NAM:.BLKB	NAM$C_MAXRSS	;EXPANDED FILE NAME
VRECL:	.BLKL	1		;RECORD LENGTH
FSTBYT:	.BLKL	1		;OFFSET FROM IOBUF(1) TO FIRST DATA
				; LOCATION (2=SPOOLED; 0=REMOTE)
IOBUF:	.BLKB	1		;BUFFER STARTS HERE
;
	.PSECT	$LOCAL,PIC,USR,CON,REL,LCL,NOSHR,NOEXE,RD,WRT
FIL_NAM_L:	.LONG	 NAM$C_MAXRSS	;Length of file name
FIL_NAM_A:	.ADDRESS FIL_NAM	;Address of file name
VER_RAB:	.LONG	0	;RAB address
OVERDRAWN:	.LONG	0	;Overdraft flag
OUTBUF:		.LONG	0	;Current buffer pointer
MAXFRE:		.LONG	0	;Max. no. bytes that can fit in buffer
NUMFRE:		.LONG	0	;Number byte left to fill
BUF_ARG:	.LONG	2
NBYTES:		.LONG	0	;Bytes in output buffer
		.ADDRESS IOBUF
BUFEND_ARG:	.LONG	2
BUFEND_BTCNT:	.LONG	0
		.ADDRESS IOBUF
REM_ARG:	.LONG	2,2
		.ADDRESS REM_PARM
REM_PARM:	.BYTE	DC3	;Parameter block for remote
REM_FUNC:	.BYTE	0	;Space for remote function
	.MACRO	STRING	TEXT,LAB
LAB'_ERR: .LONG		LAB'_END-LAB'_ST
	.ADDRESS	LAB'_ST
LAB'_ST: .ASCII	TEXT
LAB'_END: .ENDM	STRING
	STRING	</OUTPUT - Error writing to buffered file:/>,PUT
	STRING	</OUTPUT - Disk quota exceeded, using overdraft/>,QUOT
;
;
	.PSECT	$CODE,PIC,SHR,NOWRT,LONG
;
; Subroutine VERFAB_GET
;
	.ENTRY	VERFAB_GET,^M<>
	$CREATE	FAB=@FABOFF(AP)		;Create new file
	BLBC	R0,5$			;Error?
	MOVL	RABOFF(AP),R0		;Get RAB address
	MOVL	R0,VER_RAB		;Save RAB address
	INSV	#1,#RAB$V_ASY,#1,RAB$L_ROP(R0) ;Set asynchronous
	$CONNECT RAB=(R0)		;Connect file
	CLRL	OVERDRAWN		;Clear overdraft flag
	MOVAL	IOBUF,OUTBUF		;Reset pointer
	ADDL2	FSTBYT,OUTBUF		;Offset pointer as needed
	MOVL	VRECL,NBYTES		;Set record length
	SUBL3	FSTBYT,NBYTES,MAXFRE	;Init. max. no. free bytes
	MOVL	MAXFRE,NUMFRE		;Init number of free bytes
5$:	RET
;
; SUBROUTINE FILL_BUF (BUFFER,IBYTE)
;
	.ENTRY	FILL_BUF,^M<R2,R3,R4,R5,R6,R7>
	MOVL	@IBYTE(AP),R6		;Get byte count of input buffer
	MOVAL	@BUFFER(AP),R7		;Get input buffer address
10$:	CALLS	#0,BUF_WAIT		;Wait for previous write
	MOVL	OUTBUF,R0		;Get address of output buffer
	CMPL	NUMFRE,R6		;More data in input buffer?
	BLEQ	20$			;Yes
	MOVC3	R6,(R7),(R0)		;Move block of data
	MOVL	R3,OUTBUF		;Save current buffer pointer
	SUBL2	R6,NUMFRE		;Save number bytes to fill
	RET				;Return to subroutine OUTPUT
20$:	MOVC3	NUMFRE,(R7),(R0)	;Move block of data
	SUBL2	NUMFRE,R6		;Decrement number bytes moved
	MOVL	R1,R7			;Copy address of next byte
	CALLG	BUF_ARG,BUF_PUT		;Output block to file
	TSTL	R6			;Any more to move?
	BNEQ	10$			;Yes
	RET				;Return to subroutine OUTPUT
;
; FLUSH OUTPUT BUFFER ROUTINE
;
	.ENTRY	FLUSH_BUF,^M<>
	CALLS	#0,BUF_WAIT		;Wait for previous write
	CMPL	NUMFRE,MAXFRE		;Data in buffer?
	BEQL	100$			;No
	SUBL3	NUMFRE,NBYTES,BUFEND_BTCNT ;No. bytes to output
	CALLG	BUFEND_ARG,BUF_PUT	;Output last record
	CALLS	#0,BUF_WAIT		;Wait for write of last record
100$:	RET				;Return
;
; OUTPUT A RECORD TO FILE
;
	.ENTRY	BUF_PUT,^M<R2>
	MOVL	VER_RAB,R2		;Get RAB address
	MOVW	4(AP),RAB$W_RSZ(R2)	;Store size of record
	MOVL	8(AP),RAB$L_RBF(R2)	;Set buffer address
	$PUT	RAB=R2			;Write record to file
	BLBC	R0,120$			;Branch if error
	CLRW	NUMFRE			;Indicate no free bytes avail.
					; (since buffer in use)
	RET
120$:	BRW	BUF_ERR
;
; WAIT FOR OPERATION TO COMPLETE
;
	.ENTRY	BUF_WAIT,^M<R2>
	TSTL	NUMFRE			;Any operation outstanding?
	BNEQ	200$			;No, return
	MOVL	VER_RAB,R2		;Get RAB address
	$WAIT	RAB=R2			;Yes, wait for completion
	BLBS	R0,150$			;Branch if no error
	CMPL	R0,#RMS$_EXT		;Is error extend fail?
	BNEQ	BUF_ERR			;Branch if not
	CMPL	RAB$L_STV(R2),#SS$_EXDISKQUOTA ;Is err quota exceed?
	BNEQ	BUF_ERR			;Branch if not
	BBSS	#0,OVERDRAWN,BUF_ERR	;Set quota exceed flag
	$PUT	RAB=R2			;Rewrite record
	BLBC	R0,BUF_ERR		;Branch if error
	$WAIT	RAB=R2			;Wait for rewrite completion
	BLBC	R0,BUF_ERR		;Branch if error
	PUSHAL	QUOT_ERR		;Quota message address
	CALLS	#1,G^LIB$PUT_OUTPUT	;Print message
150$:	MOVL	MAXFRE,NUMFRE		;Reset no. of bytes available
	MOVAL	IOBUF,OUTBUF		;Reset pointer
	ADDL2	FSTBYT,OUTBUF		;Offset pointer as needed
200$:	RET
;
; ROUTINE TO HANDLE BUFFER FILE ERRORS
;
BUF_ERR: PUSHL	RAB$L_STV(R2)		;Push RAB RMS error code
	PUSHR	#^M<R0>			;Push R0
	PUSHAL	PUT_ERR			;Error message address
	CALLS	#1,G^LIB$PUT_OUTPUT	;Print message
	PUSHAL	FIL_NAM_L		;File name descriptor address
	CALLS	#1,G^LIB$PUT_OUTPUT	;Print message
	CALLS	#2,G^LIB$STOP		;Abort
;
; SWAP BYTES ROUTINE
;
	.ENTRY	SWAP_BYTES,^M<R2>
	DIVL3	#2,@IBYTE(AP),R2	;Get word count for loop
	BEQL	210$			;Return if zero
	MOVAL	@BUFFER(AP),R0		;Get buffer address
205$:	MOVB	(R0),R1			;Save byte
	MOVB	1(R0),(R0)+		;Swap second byte
	MOVB	R1,(R0)+		;Store first byte
	SOBGTR	R2,205$			;Swap all of buffer
210$:	RET				;Return
;
; REMOTE FUNCTION ROUTINE
;
	.ENTRY	REMOTE,^M<>
	MOVB	@REM(AP),REM_FUNC	;Get remote function
	CALLG	REM_ARG,BUF_PUT		;Transfer remote
	CALLS	#0,BUF_WAIT		;Wait for transfer
	RET				;Return
;
	.END
