	SECTION	_RexxStub,CODE
	NOLIST
	include 'exec/types.i'
	include 'exec/execbase.i'
	include 'rexx/storage.i'
	include 'rexx/rxslib.i'
	include 'libraries/dos.i'
	include 'libraries/dosextens.i'
_LVOOpenLibrary	EQU	-552
_LVOInput	EQU	-54
_LVOOutput	EQU	-60
	LIST

	xdef	_RexxStub
	xref	_sprintf,_RexxSysBase,_DOSBase

;	Copyright © Dineen Edwards Group, Inc., 1987-91, All rigihts reserved

;	This is a sample stub program to be used when interfacing C
;	and REXX PLUS Compiled programs. 
;	
;	The parameters are:
;		RoutinePtr		address of routine entry point 
;		BufferPtr		optional pointer to buffer
;		PatternPtr		pointer to pattern string for
;		Args			arguments as described by pattern
;
;	The subroutine calls sprintf to convert the parameters passed 
;	into string format for correct interpretation of the REXX PLUS
;	compiled program. It then breaks the parameters into arguments
;	and fills the RexxMsg with those arguments. It calls the routine
;	at the address pointed to by RoutinePtr, cleans up the Message,
;	and returns the result to the caller.
;
 			
RexxRegs	reg	d1-d7/a0-a6
BuffSize	equ	200
;RexxOff	equ	60+BuffSize+RM_SIZEOF
RexxOff		equ	60+BuffSize+RMSIZEOF

	STRUCTURE	RexxStruct,RexxOff
	APTR		RoutinePtr
	APTR		BufferPtr
	APTR		PatternPtr
	APTR		Args
	LABEL		SZ_RexxStruct

rexxlib	dc.b	"rexxsyslib.library",0,0
doslib	dc.b	"dos.library",0

_RexxStub:
	movem.l	d1-d7/a0-a6,-(sp)	; /* save all registers, just incase */
	move.l	$4,a6			; /* get the exec library base */
;	sub.l	#RM_SIZEOF+BuffSize,sp	; /* back up stack pointer */
	sub.l	#RMSIZEOF+BuffSize,sp	; /* back up stack pointer */
	tst.l	_RexxSysBase		; /* rexx base present? */
	bne.s	RexxStubSkipOpen	; /* yes, skip the open */
	lea.l	rexxlib,a1		; /* point to library */
	move.l	#0,d0			; /* set release number */
	jsr	_LVOOpenLibrary(a6)	; /* open the library */
	move.l	d0,_RexxSysBase		; /* fill in the pointer */
	bne.s	RexxStubSkipOpen	; /* skip the error */
	move.l	#-1,d0			; /* no library, return -1 */	
;	add.l	#RM_SIZEOF+BuffSize,sp	; /* reset the pointer */
	add.l	#RMSIZEOF+BuffSize,sp	; /* reset the pointer */
	movem.l	(sp)+,d1-d7/a0-a6	; /* restore registers */
	rts				; /* return to caller */

RexxStubSkipOpen:
	tst.l	_DOSBase		; /* rexx base present? */
	bne.s	RexxStubSkipDos		; /* yes, skip the open */
	lea.l	doslib,a1		; /* point to library */
	move.l	#0,d0			; /* set release number */
	jsr	_LVOOpenLibrary(a6)	; /* open the library */
	move.l	d0,_DOSBase		; /* fill in the pointer */
	bne.s	RexxStubSkipDos		; /* skip the error */
	move.l	#-1,d0			; /* no library, return -1 */	
;	add.l	#RM_SIZEOF+BuffSize,sp	; /* reset the pointer */
	add.l	#RMSIZEOF+BuffSize,sp	; /* reset the pointer */
	movem.l	(sp)+,d1-d7/a0-a6	; /* restore registers */
	rts				; /* return to caller */

RexxStubSkipDos:
	move.l	BufferPtr(sp),d7	; /* get buffer pointer */
	bne.s	RexxStubNoAlloc		; /* no, skip the allocate */
	move.l	sp,d7			; /* get the pointer */
;	add.l	#RM_SIZEOF,d7		; /* point to the buffer */
	add.l	#RMSIZEOF,d7		; /* point to the buffer */

RexxStubNoAlloc:
	move.l	#0,0(a7)		; /* clear the message */
	move.l	#0,4(a7)		; /* clear the message */
	move.l	#0,8(a7)			; /* clear the message */
	move.l	#0,12(a7)			; /* clear the message */
	move.l	#0,ARG0(a7)			; /* clear Arg0 */
	move.l	#0,rm_Result1(a7)		; /* clear the result */
	move.l	#0,rm_Result2(a7)		; /* clear the result */
	move.l	ThisTask(a6),rm_TaskBlock(a7)	; /* get the task block */
	move.l	_RexxSysBase,a0			; /* get the rexx library */
	move.l	rl_REXX(a0),LN_NAME(a7)		; /* fill in the name */
	add.l	#8,LN_NAME(a7)			; /* point to the buffer */
	move.l	LN_NAME(a7),rm_CommAddr(a7)	; /* fill in the name */
	move.l	LN_NAME(a7),rm_FileExt(a7)	; /* fill in the name */
	move.l	#0,MN_REPLYPORT(a7)		; /* move in the port address */
	move.l	#0,rm_PassPort(a7)		; /* move in the port address */
	move.l	_DOSBase,a6			; /* get the dos base */
	jsr	_LVOInput(a6)			; /* get input file */
	move.l	d0,rm_Stdin(a7)			; /* save the input handle */
	jsr	_LVOOutput(a6)			; /* get output file */
	move.l	d0,rm_Stdout(a7)		; /* save the input handle */
	move.l	#0,rm_avail(a7)			; /* clear available */

	move.l	PatternPtr(a7),a1	; /* get the pointer */
	move.l	Args+16*4(a7),-(a7)	; /* fill in the args */
	move.l	Args+16*4(a7),-(a7)	; /* fill in the args */
	move.l	Args+16*4(a7),-(a7)	; /* fill in the args */
	move.l	Args+16*4(a7),-(a7)	; /* fill in the args */
	move.l	Args+16*4(a7),-(a7)	; /* fill in the args */
	move.l	Args+16*4(a7),-(a7)	; /* fill in the args */
	move.l	Args+16*4(a7),-(a7)	; /* fill in the args */
	move.l	Args+16*4(a7),-(a7)	; /* fill in the args */
	move.l	Args+16*4(a7),-(a7)	; /* fill in the args */
	move.l	Args+16*4(a7),-(a7)	; /* fill in the args */
	move.l	Args+16*4(a7),-(a7)	; /* fill in the args */
	move.l	Args+16*4(a7),-(a7)	; /* fill in the args */
	move.l	Args+16*4(a7),-(a7)	; /* fill in the args */
	move.l	Args+16*4(a7),-(a7)	; /* fill in the args */
	move.l	Args+16*4(a7),-(a7)	; /* fill in the args */
	move.l	Args+16*4(a7),-(a7)	; /* fill in the args */
	move.l	Args+16*4(a7),-(a7)	; /* fill in the args */
	pea.l	(a1)			; /* push address on stack */
	move.l	d7,-(sp)		; /* put buffer on stack */
	jsr	_sprintf		; /* format the string */
	add.l	#19*4,sp		; /* reset the pointer */

	move.l	d7,a1			; /* point to the string */
	lea.l	Args(a7),a5		; /* point to the list */
	lea.l	ARG0(a7),a3		; /* point to the list */
	move.l	a1,(a3)+		; /* fill in the pointer */
	move.l	#0,d3			; /* get the flags */

RexxStubPatLoop1:
	move.b	(a1)+,d0		; /* get the character */
	beq.s	RexxStubPatEnd		; /* end the loop */
	cmp.b	#'"',d0			; /* double? */
	beq.s	RexxStubPatDouble	; /* yes, handle it */
	cmp.b	#$27,d0			; /* single? */
	beq.s	RexxStubPatSingle	; /* yes, handle it */
	cmp.b	#',',d0			; /* next arg? */
	bne	RexxStubPatLoop1	; /* no, loop */
	move.b	#0,-1(a1)		; /* clear the byte */
	move.l	a1,(a3)+		; /* fill in the pointer */
	cmp.l	#15,d3			; /* count too large? */
	bge.s	RexxStubPatEnd		; /* yes, get out */
	addq.l	#1,d3			; /* increment the count */
	bra	RexxStubPatLoop1	; /* loop for next entry */

RexxStubPatDouble:
	move.b	(a1)+,d0		; /* get the character */
	beq.s	RexxStubPatEnd		; /* end the loop */
	cmp.b	#'"',d0			; /* double? */
	bne	RexxStubPatDouble	; /* no, handle it */
	bra	RexxStubPatLoop1	; /* loop for next character */

RexxStubPatSingle:
	move.b	(a1)+,d0		; /* get the character */
	beq.s	RexxStubPatEnd		; /* end the loop */
	cmp.b	#$27,d0			; /* single? */
	bne	RexxStubPatSingle	; /* no, handle it */
	bra	RexxStubPatLoop1	; /* loop for next character */

RexxStubPatEnd:
	move.l	a7,a0			; /* get the message pointer */
	add.l	#RXFUNC,d3		; /* say function */
	move.l	d3,rm_Action(a0)	; /* fill in count */
	movea.l	_RexxSysBase,a6		; /* get the rexx library */
	move.l	d3,d0			; /* get the count */
	and.l	#15,d0			; /* get the count */
	addq.l	#1,d0			; /* increment the count */
	move.l	#0,d1			; /* set the mask */
	jsr	_LVOFillRexxMsg(a6)	; /* get the arg string */

	move.l	a7,a0			; /* get pointer for call */
	move.l	RoutinePtr(a7),a6	; /* get routine address */
	jsr	(a6)			; /* jump to the routine */
	move.l	a0,a3			; /* save the RexxMsg */
	tst.l	d0			; /* zero return code? */
	beq.s	RexxStubZero		; /* yes, return result string */
	move.l	#0,a3			; /* clear the result value */

RexxStubZero:
	movea.l	_RexxSysBase,a6		; /* get the rexx library */
	move.l	a7,a0			; /* get arg string zero */
	move.l	rm_Action(a0),d0	; /* get the count */
	and.l	#15,d0			; /* get the count */
	addq.l	#1,d0			; /* increment the count */
	jsr	_LVOClearRexxMsg(a6)	; /* get rid of the strings */

	move.l	a3,d0			; /* get the result string */
;	add.l	#RM_SIZEOF+BuffSize,sp	; /* reset the pointer */
	add.l	#RMSIZEOF+BuffSize,sp	; /* reset the pointer */
	movem.l	(sp)+,d1-d7/a0-a6	; /* restore registers */
	rts				; /* return to caller */

	end
