


*-------------------------------------------------------------------------*
* Xtool
*
*    Xtool functions like the macro tool but its input/output/err parameters
* are defined before the macro call with the macros in, out, and err.
*-------------------------------------------------------------------------*
			MACRO
			xtool &toolname,&err

			lcla &outnum
			lcla &innum
			lclc &size
			lclc &parm
			lcla &count

			gbla &xincnt
			gblc &xin[20]

			gbla &xoutcnt
			gblc &xout[20]
			  
			gbla &xerrflag
			gblc &xerr
		
&count		seta &xoutcnt+1
			WHILE (&count>1) DO
&count			seta &count-1
&size       	setc &substr(&xout[&count],&len(&xout[&count])-1,2)
				IF (&size=':r') or (&size=':R') GOTO .rect
				IF (&size=':l') or (&size=':L') GOTO .long
				IF (&size=':a') or (&size=':A') GOTO .addr
				IF (&size=':w') or (&size=':W') GOTO .word
				IF (&size=':b') or (&size=':B') GOTO .byte
            	macerr 'XTool macro: Output parameter size improperly specified: Ò',&xout[&count],'Ó'
				MEXIT
.addr
				pha
.byte
				phb
				CYCLE
.rect			pha
				pha
.long
				pha
.word
				pha

			ENDWHILE
		
&count		seta 0
			WHILE (&count<&xincnt) DO
&count			seta &count+1
&size			setc &substr(&xin[&count],&len(&xin[&count])-1,2)
&parm       	setc &substr(&xin[&count],1,&len(&xin[&count])-2)
				IF	(&size=':r') or (&size=':R') GOTO .rect
				IF	(&size=':l') or (&size=':L') GOTO .long
				IF	(&size=':a') or (&size=':A') GOTO .addr
				IF	(&size=':w') or (&size=':W') GOTO .word
				IF	(&size=':b') or (&size=':B') GOTO .byte
            	macerr 'XTool macro: Input parameter size improperly specified: Ò',&xin[&count],'Ó'
				MEXIT

.rect
				pushrect  &parm
				CYCLE

.long
				PushLong  &parm
				CYCLE

.addr
				PushAdr   &parm
				CYCLE

.word
				PushWord  &parm
				CYCLE

.byte
				PushByte  &parm
			ENDWHILE

			&toolname
			IF	&len(&err)=0 GOTO .noname
			moveword a,&err
			GOTO .noerr

.noname
			IF	&xerrflag=0 GOTO .noerr
			sta &xerr
.noerr
&count		seta &xoutcnt+1

			WHILE (&count>1) DO
&count			seta &count-1
				IF	&len(&xout[&count])<3 THEN ; leave it on the stack.
					CYCLE
				ENDIF
&size			setc &substr(&xout[&count],&len(&xout[&count])-1,2)
&parm			setc &substr(&xout[&count],1,&len(&xout[&count])-2)

				IF	(&size=':r') or (&size=':R') GOTO .rect
				IF	(&size=':l') or (&size=':L') GOTO .long
				IF	(&size=':a') or (&size=':A') GOTO .addr
				IF	(&size=':w') or (&size=':W') GOTO .word
				IF	(&size=':b') or (&size=':B') GOTO .byte
				macerr 'XTool macro: Output parameter size improperly specified: Ò',&xout[&count],'Ó'
				MEXIT


.rect
				pullrect &parm
				CYCLE

.long
				PullLong  &parm
				CYCLE

.addr
				PullAdr   &parm
				CYCLE

.word
				PullWord  &parm
				CYCLE

.byte
				PullByte  &parm

			ENDWHILE

.quit
&xerrflag	seta 0
&xoutcnt	seta 0
&xincnt		seta 0
&xerr		setc ''

			MEND
*-------------------------------------------------------------------------*
* XCall
*
*    XCall functions like the macro Call but its input/output/err parameters
* are defined before the macro call with the macros in, out, and err.
*-------------------------------------------------------------------------*
			MACRO
			xcall &name,&err

			lcla &outnum
			lcla &innum
			lclc &size
			lclc &parm
			lcla &count

			gbla &xincnt
			gblc &xin[20]

			gbla &xoutcnt
			gblc &xout[20]
			  
			gbla &xerrflag
			gblc &xerr
		
&count		seta &xoutcnt+1
			WHILE (&count>1) DO
&count			seta &count-1
&size       	setc &substr(&xout[&count],&len(&xout[&count])-1,2)
				IF (&size=':r') or (&size=':R') GOTO .rect
				IF (&size=':l') or (&size=':L') GOTO .long
				IF (&size=':a') or (&size=':A') GOTO .addr
				IF (&size=':w') or (&size=':W') GOTO .word
				IF (&size=':b') or (&size=':B') GOTO .byte
            	macerr 'XCall macro: Output parameter size improperly specified: Ò',&xout[&count],'Ó'
				MEXIT
.addr
				pha
.byte
				phb
				CYCLE

.rect
				pha
				pha
.long
				pha
.word
				pha

			ENDWHILE
		
&count		seta 0
			WHILE (&count<&xincnt) DO
&count			seta &count+1
&size			setc &substr(&xin[&count],&len(&xin[&count])-1,2)
&parm       	setc &substr(&xin[&count],1,&len(&xin[&count])-2)
				IF	(&size=':r') or (&size=':R') GOTO .rect
				IF	(&size=':l') or (&size=':L') GOTO .long
				IF	(&size=':a') or (&size=':A') GOTO .addr
				IF	(&size=':w') or (&size=':W') GOTO .word
				IF	(&size=':b') or (&size=':B') GOTO .byte
            	macerr 'XCall macro: Input parameter size improperly specified: Ò',&xin[&count],'Ó'
				MEXIT

.rect
				pushrect &parm
				CYCLE

.long
				PushLong  &parm
				CYCLE

.addr
				PushAdr   &parm
				CYCLE

.word
				PushWord  &parm
				CYCLE

.byte
				PushByte  &parm
			ENDWHILE

			jsl &name
			
			IF	&len(&err)=0 GOTO .noname
			moveword a,&err
			GOTO .noerr

.noname
			IF	&xerrflag=0 GOTO .noerr
			sta &xerr
.noerr
&count		seta &xoutcnt+1

			WHILE (&count>1) DO
&count			seta &count-1
				IF	&len(&xout[&count])<3 THEN	; leave it on the stack.
					CYCLE
				ENDIF
&size			setc &substr(&xout[&count],&len(&xout[&count])-1,2)
&parm			setc &substr(&xout[&count],1,&len(&xout[&count])-2)

				IF	(&size=':r') or (&size=':R') GOTO .rect
				IF	(&size=':l') or (&size=':L') GOTO .long
				IF	(&size=':a') or (&size=':A') GOTO .addr
				IF	(&size=':w') or (&size=':W') GOTO .word
				IF	(&size=':b') or (&size=':B') GOTO .byte
				macerr 'XCall macro: Output parameter size improperly specified: Ò',&xin[&count],'Ó'
				MEXIT

.rect
				pullrect &parm
				CYCLE

.long
				PullLong  &parm
				CYCLE

.addr
				PullAdr   &parm
				CYCLE

.word
				PullWord  &parm
				CYCLE

.byte
				PullByte  &parm

			ENDWHILE

.quit
&xerrflag	seta 0
&xoutcnt	seta 0
&xincnt		seta 0
&xerr		setc ''

			MEND
*-------------------------------------------------------------------------*
			MACRO
			in
			gblc &xin[20]
			gbla &xincnt
			lcla &count
			lcla &params

&count		seta 0
&params		seta &nbr(&syslist)

			WHILE (&count<&params) DO
&count			seta &count+1
&xincnt			seta &xincnt+1
				IF (&xincnt>20) THEN
					macerr 'Too many input parameters for XCall or XTool.'
				ENDIF
&xin[&xincnt]	setc &syslist[&count]
			ENDWHILE
			MEND
			
*-------------------------------------------------------------------------*
			MACRO
			out
			gblc &xout[20]
			gbla &xoutcnt
			lcla &count
			lcla &params

&count		seta 0
&params		seta &nbr(&syslist)

			WHILE (&count<&params) DO
&count			seta &count+1
&xoutcnt        seta &xoutcnt+1
				IF (&xoutcnt>20) THEN
					macerr 'Too many output parameters for XCall or XTool.'
				ENDIF
&xout[&xoutcnt] setc &syslist[&count]
			ENDWHILE
			MEND
			
			
*-------------------------------------------------------------------------*
			MACRO
			xerr &errlabel

			gbla &xerrflag
			gblc &xerr

&xerrflag	seta 1
&xerr		setc &errlabel
			MEND

;...........................................................................;
;
;          generic call subroutine macro
;
;    call  RoutineName,in=(Parm1:L,Parm2:W),out=(Out1:L,Out2:W),err
;
;    This macro will push enough space on the stack for the specified output
; parameters, then push the input parameters in the order given onto stack
; and call the named routine. All parameters must have a size specification
; for this macro to work. The size may be either :w (word) or :l (long).
;
;    If an error label is given then the value of the accumulator after the
; call is saved in the given label position.
;...........................................................................;
                 MACRO
&lab             call       &name,&in,&out,&err
&lab	; 
                 lcla       &outnum
                 lcla       &innum
                 lcla       &count
                 lclc       &insize
                 lclc       &inparm
                 lclc       &outsize
                 lclc       &outparm
				 lclc		&newout[20]
				 lclc		&newin[20]

		IF (&nbr(&out)=0) THEN
			IF (&out = '') THEN
&outnum			seta 0
			ELSE
&outnum			seta 1
&newout[1]		setc &out
			ENDIF
		ELSE
&outnum		seta &nbr(&out)
			WHILE (&outnum ­ 0) DO
&newout[&outnum]	setc &out[&outnum]
&outnum				seta &outnum-1
			ENDWHILE
&outnum		seta &nbr(&out)
		ENDIF

		IF (&nbr(&in)=0) THEN
			IF (&in = '') THEN
&innum			seta 0
			ELSE
&innum			seta 1
&newin[1]			setc &in
			ENDIF
		ELSE
&innum		seta &nbr(&in)
			WHILE (&innum ­ 0) DO
&newin[&innum]		setc &in[&innum]
&innum			seta &innum-1
			ENDWHILE
&innum		seta &nbr(&in)
		ENDIF

		
		
&count           seta       &outnum


		IF	&outnum=0 GOTO .nooutput
.outloop
&outsize         setc &substr(&newout[&count],&len(&newout[&count])-1,2)
		IF	(&outsize=':l') or (&outsize=':L') GOTO .long
		IF	(&outsize=':w') or (&outsize=':W') GOTO .word
		IF	(&outsize=':a') or (&outsize=':A') GOTO .addr
		IF	(&outsize=':b') or (&outsize=':B') GOTO .byte
		IF	(&outsize=':r') or (&outsize=':R') GOTO .rect
                 macerr 'Call macro: Parameter size not specified.'
                 mexit
.addr
                 pha
.byte
                 PushByte a
		GOTO .xx

.rect
                 pha
                 pha
.long
                 pha
.word
                 pha
.xx
&count           seta       &count-1
		IF	&count GOTO .outloop
.nooutput
&count           seta       1
		IF	&innum=0 GOTO .noinput
.inloop
		IF	&len(&newin[&count])<3 GOTO .nextin
&insize          setc &substr(&newin[&count],&len(&newin[&count])-1,2)
&inparm          setc &substr(&newin[&count],1,&len(&newin[&count])-2)
		IF	(&insize=':l') or (&insize=':L') GOTO .long
		IF	(&insize=':w') or (&insize=':W') GOTO .word
		IF	(&insize=':a') or (&insize=':A') GOTO .addr
		IF	(&insize=':b') or (&insize=':B') GOTO .byte
		IF	(&insize=':r') or (&insize=':R') GOTO .rect
                 macerr 'Call macro: Parameter size not specified.'
                 mexit
.rect
                 pushrect   &inparm
		GOTO .nextin

.addr
                 PushAdr    &inparm
		GOTO .nextin

.byte
                 PushByte   &inparm
		GOTO .nextin

.long
                 PushLong   &inparm
		GOTO .nextin

.word
                 PushWord   &inparm
.nextin
&count           seta       &count+1
		IF	&count>&innum GOTO .noinput
		GOTO .inloop      

.noinput
                 jsl        &name
		IF &type('&err')='UNDEFINED' GOTO .dopull
		IF &nbr(&err)=0 THEN
			IF (&err='') GOTO .dopull
			moveword a,&err
		ELSE
            moveword a,&err[1]
		ENDIF
.dopull
&count           seta       &outnum
		IF	&count>0 GOTO .getout
                 mexit
.getout
		IF	&len(&newout[&count])<3 GOTO .nextout
&outsize         setc &substr(&newout[&count],&len(&newout[&count])-1,2)
&outparm         setc &substr(&newout[&count],1,&len(&newout[&count])-2)
		IF	(&outsize=':l') or (&outsize=':L') GOTO .long
		IF	(&outsize=':w') or (&outsize=':W') GOTO .word
		IF	(&outsize=':a') or (&outsize=':A') GOTO .addr
		IF	(&outsize=':b') or (&outsize=':B') GOTO .byte
		IF	(&outsize=':r') or (&outsize=':R') GOTO .rect
                 macerr 'Call macro: Parameter size not specified.'
                 mexit
.rect
                 pullrect   &outparm
		GOTO .nextout

.addr
                 PullAdr    &outparm
		GOTO .nextout

.byte
                 PullByte   &outparm
		GOTO .nextout

.word
                 PullWord   &outparm
		GOTO .nextout

.long
                 PullLong   &outparm
.nextout
&count           seta       &count-1
		IF	&count GOTO .getout
.quit
                 mexit
                 MEND
;...........................................................................;
;
;          generic tool call subroutine macro
;
;    tool  RoutineName,in=(Parm1:L,Parm2:W),out=(Out1:L,Out2:W),err
;
;    This macro will push enough space on the stack for the specified output
; parameters, then push the input parameters in the order given onto stack
; and call the named routine. All parameters must have a size specification
; for this macro to work. The size may be either :w (word) or :l (long).
;
;    If an error label is given then the value of the accumulator after the
; call is saved in the given label position.
;...........................................................................;
                 MACRO
&lab             tool       &name,&in,&out,&err
&lab	; 
                 lcla       &outnum
                 lcla       &innum
                 lcla       &count
                 lclc       &insize
                 lclc       &inparm
                 lclc       &outsize
                 lclc       &outparm
				 lclc		&newout[20]
				 lclc		&newin[20]

		IF (&nbr(&out)=0) THEN
			IF (&out = '') THEN
&outnum			seta 0
			ELSE
&outnum			seta 1
&newout[1]		setc &out
			ENDIF
		ELSE
&outnum		seta &nbr(&out)
			WHILE (&outnum ­ 0) DO
&newout[&outnum]	setc &out[&outnum]
&outnum				seta &outnum-1
			ENDWHILE
&outnum		seta &nbr(&out)
		ENDIF

		IF (&nbr(&in)=0) THEN
			IF (&in = '') THEN
&innum			seta 0
			ELSE
&innum			seta 1
&newin[1]		setc &in
			ENDIF
		ELSE
&innum		seta &nbr(&in)
			WHILE (&innum ­ 0) DO
&newin[&innum]		setc &in[&innum]
&innum				seta &innum-1
			ENDWHILE
&innum		seta &nbr(&in)
		ENDIF

&count           seta       &outnum

		IF	&outnum=0 GOTO .nooutput
.outloop
&outsize         setc &substr(&newout[&count],&len(&newout[&count])-1,2)
		IF	(&outsize=':l') or (&outsize=':L') GOTO .long
		IF	(&outsize=':w') or (&outsize=':W') GOTO .word
		IF	(&outsize=':a') or (&outsize=':A') GOTO .addr
		IF	(&outsize=':b') or (&outsize=':B') GOTO .byte
                 macerr 'Tool macro: Parameter size not specified.'
                 mexit
.addr
                 pha
.byte
                 PushByte a
		GOTO .xx

.long
                 pha
.word
                 pha
.xx
&count           seta       &count-1
		IF	&count GOTO .outloop
.nooutput
&count           seta       1
		IF	&innum=0 GOTO .noinput
.inloop
		IF	&len(&newin[&count])<3 GOTO .nextin
&insize          setc &substr(&newin[&count],&len(&newin[&count])-1,2)
&inparm          setc &substr(&newin[&count],1,&len(&newin[&count])-2)
		IF	(&insize=':l') or (&insize=':L') GOTO .long
		IF	(&insize=':w') or (&insize=':W') GOTO .word
		IF	(&insize=':a') or (&insize=':A') GOTO .addr
		IF	(&insize=':b') or (&insize=':B') GOTO .byte
                 macerr 'Tool macro: Input parameter size not specified.'
                 mexit
.addr
                 PushAdr    &inparm
		GOTO .nextin

.byte
                 PushByte   &inparm
		GOTO .nextin

.long
                 PushLong   &inparm
		GOTO .nextin

.word
                 PushWord   &inparm
.nextin
&count           seta       &count+1
		IF	&count>&innum GOTO .noinput
		GOTO .inloop      

.noinput
                 &name
		IF &type('&err')='UNDEFINED' GOTO .dopull
		IF &nbr(&err)=0 THEN
			IF (&err='') GOTO .dopull
			moveword a,&err
		ELSE
            moveword a,&err[1]
		ENDIF
.dopull
&count           seta       &outnum
		IF	&count>0 GOTO .getout
                 mexit
.getout
		IF	&len(&newout[&count])<3 GOTO .nextout
&outsize         setc &substr(&newout[&count],&len(&newout[&count])-1,2)
&outparm         setc &substr(&newout[&count],1,&len(&newout[&count])-2)
		IF	(&outsize=':l') or (&outsize=':L') GOTO .long
		IF	(&outsize=':w') or (&outsize=':W') GOTO .word
		IF	(&outsize=':a') or (&outsize=':A') GOTO .addr
		IF	(&outsize=':b') or (&outsize=':B') GOTO .byte
                 macerr 'Tool macro: Parameter size not specified.'
                 mexit
.addr
                 PullAdr    &outparm
		GOTO .nextout

.byte
                 PullByte   &outparm
		GOTO .nextout

.word
                 PullWord   &outparm
		GOTO .nextout

.long
                 PullLong   &outparm
.nextout
&count           seta       &count-1
		IF	&count GOTO .getout
.quit
                 mexit
                 MEND

*===========================================================================*

;-------------------------------------------------------------------------------
		MACRO
		input
	
			GBLC	&ginput[20]
			GBLA	&gincnt
			LCLA	&count
			LCLA &limit
&count		SETA 0
&limit		SETA	&nbr(&syslist)

			WHILE (&count<&limit) DO
&gincnt			SETA &gincnt+1
&count			SETA &count+1
&ginput[&gincnt]	SETC &syslist[&count]
			ENDWHILE
			
		MEND
	
;-------------------------------------------------------------------------------
		MACRO
		output
	
			GBLC	&goutput[20]
			GBLA	&goutcnt
			LCLA	&count
			LCLA &limit
&count		SETA 0
&limit		SETA	&nbr(&syslist)

			WHILE (&count<&limit) DO
&goutcnt			SETA &goutcnt+1
&count			SETA &count+1
&goutput[&goutcnt]	SETC &syslist[&count]
			ENDWHILE
			
		MEND

;-------------------------------------------------------------------------------
		MACRO
		local
	
			GBLC	&glocal[40]
			GBLA	&gloccnt
			LCLA	&count
			LCLA &limit
&count		SETA 0
&limit		SETA	&nbr(&syslist)

			WHILE (&count<&limit) DO
&gloccnt			SETA &gloccnt+1
&count			SETA &count+1
&glocal[&gloccnt]	SETC &syslist[&count]
			ENDWHILE
			
		MEND
	
;-------------------------------------------------------------------------------
		MACRO
		error	&op1
		
		GBLC 	&glocal[40]
		GBLA 	&gloccnt
		GBLC 	&gerror
		GBLA		&reterr
&reterr	SETA		1

		IF &nbr(&syslist)=0 THEN
&gerror			SETC		'a'
				MEXIT
		ENDIF

&gerror 	SETC		&op1

		IF &op1­'a' THEN
&gloccnt			SETA	&gloccnt+1
&glocal[&gloccnt]	SETC	&concat(&op1,':w')
		ENDIF

		MEND

;-------------------------------------------------------------------------;

		MACRO
		begin	&op1

		LCLC		&Pname
		LCLC 	&length
		LCLA 	&loccnt
		LCLA 	&locsize
		LCLA 	&incnt
		LCLA 	&inpsize
		LCLA 	&outcnt
		LCLA		&outsize

		GBLA 	&inbegin
		IF (&inbegin = 1) THEN
			macerr 'ÔBeginÕ without a ÔReturnÕ'
		ENDIF
&inbegin	seta 1

		
		GBLC 	&ginput[20]
		GBLA 	&gincnt
		GBLC 	&goutput[20]
		GBLA 	&goutcnt
		GBLC 	&glocal[40]
		GBLA 	&gloccnt
		GBLC 	&gerror
		GBLA 	&reterr

		GBLA 	&glink
		GBLA 	&gbank

		IF (&gincnt+&goutcnt+&gloccnt=0) GOTO .done

;--------------------Locals

		IF (&gloccnt=0) GOTO .skip4

&loccnt	SETA	&gloccnt+1

		WHILE (&loccnt>1) DO

&loccnt		SETA &loccnt-1
&Pname		SETC &substr(&glocal[&loccnt],1,&len(&glocal[&loccnt])-2)
&length		SETC &substr(&glocal[&loccnt],&len(&glocal[&loccnt])-1,2)

			IF (&substr(&Pname,1,1)­'!') THEN
				IF (&ENTERSYM(&SYSLOCAL,&UPCASE(&PNAME),1+&locsize,0)=0) THEN
					macerr 'Begin macro: Could not enter label into symbol table.'
				ENDIF
			ELSE	
&Pname			SETC	&substr(&Pname,2,&len(&Pname)-1)
				IF (&ENTERSYM(&SYSGLOBAL,&UPCASE(&PNAME),1+&locsize,0)=0) THEN
					macerr 'Begin macro: Could not enter label into symbol table'
				ENDIF
			ENDIF


			IF (&length=':b') THEN
&locsize			SETA	&locsize+1
				CYCLE
			ELSEIF (&length=':w') THEN
&locsize			SETA &locsize+2
				CYCLE
			ELSEIF (&length=':a') THEN
&locsize			SETA &locsize+3
				CYCLE
			ELSEIF (&length=':l') THEN
&locsize			SETA &locsize+4
				CYCLE
			ELSEIF (&length=':r') THEN
&locsize			SETA &locsize+8
				CYCLE
			ELSEIF (&length=':x') THEN
&locsize			SETA &locsize+10
				CYCLE
			ELSE
				macerr 'Begin macro: Bad local specification "',&PName,'"'
				MEXIT
			ENDIF

		ENDWHILE
			
.skip4

;--------------------Inputs

		IF (&gincnt=0) GOTO .skip5

&incnt	SETA	&gincnt+1

		WHILE (&incnt>1) DO

&incnt		SETA &incnt-1
&Pname		SETC &substr(&ginput[&incnt],1,&len(&ginput[&incnt])-2)
&length		SETC &substr(&ginput[&incnt],&len(&ginput[&incnt])-1,2)

			IF (&substr(&Pname,1,1)­'!') THEN
				IF (&ENTERSYM(&SYSLOCAL,&UPCASE(&PNAME),6+&locsize+&inpsize,0)=0) THEN
					macerr 'Begin macro: Could not enter label Ò',&UPCASE(&PNAME),'Ó into symbol table'
				ENDIF
			ELSE	
&Pname			SETC	&substr(&Pname,2,&len(&Pname)-1)
				IF (&ENTERSYM(&SYSGLOBAL,&UPCASE(&PNAME),6+&locsize+&inpsize,0)=0) THEN
					macerr 'Begin macro: Could not enter label Ò',&UPCASE(&PNAME),'Ó into symbol table'
				ENDIF
			ENDIF


			IF (&length=':b') THEN
&inpsize			SETA	&inpsize+1
				CYCLE
			ELSEIF (&length=':w') THEN
&inpsize			SETA &inpsize+2
				CYCLE
			ELSEIF (&length=':a') THEN
&inpsize			SETA &inpsize+3
				CYCLE
			ELSEIF (&length=':l') THEN
&inpsize			SETA &inpsize+4
				CYCLE
			ELSEIF (&length=':r') THEN
&inpsize			SETA &inpsize+8
				CYCLE
			ELSEIF (&length=':x') THEN
&inpsize			SETA &inpsize+10
				CYCLE
			ELSE
				macerr 'Begin macro: Bad input specification "',&PName,'"'
				MEXIT
			ENDIF

		ENDWHILE
			
.skip5
&glink	SETA		1

;		Change equates to ENTERSYMs to allow multiple begin-returns in a single code segment


		IF (&ENTERSYM(&SYSLOCAL,'LOCALS',1,0)=0) THEN
			macerr 'Begin macro: Could not enter LOCALS into symbol table'
			MEXIT
		ENDIF
		IF (&ENTERSYM(&SYSLOCAL,'INPUT',&locsize+5+1,0)=0) THEN
			macerr 'Begin macro: Could not enter INPUT into symbol table'
			MEXIT
		ENDIF
		IF (&ENTERSYM(&SYSLOCAL,'OUTPUT',&locsize+5+1+&inpsize,0)=0) THEN
			macerr 'Begin macro: Could not enter OUTPUT into symbol table'
			MEXIT
		ENDIF

.*	locals	equ		1
.*	input	equ		&locsize+5+locals
.*	output	equ		input+&inpsize

		phd								; push current DP
		tsc

		IF &locsize­0 THEN					; make stack space
			sec							; for local variables
			sbc		#&locsize
			tcs
		ENDIF

		tcd								; set new DP

;--------------------Outputs

		IF (&goutcnt=0) GOTO .done

&outcnt	SETA	&goutcnt+1

		WHILE (&outcnt>1) DO

&outcnt		SETA &outcnt-1
&Pname		SETC &substr(&goutput[&outcnt],1,&len(&goutput[&outcnt])-2)
&length		SETC &substr(&goutput[&outcnt],&len(&goutput[&outcnt])-1,2)

			IF (&substr(&Pname,1,1)­'!') THEN
				IF (&ENTERSYM(&SYSLOCAL,&UPCASE(&PNAME),6+&locsize+&inpsize+&outsize,0)=0) THEN
					macerr 'Begin macro: Could not enter label Ò',&UPCASE(&PNAME),'Ó into symbol table'
				ENDIF
			ELSE	
&Pname			SETC	&substr(&Pname,2,&len(&Pname)-1)
				IF (&ENTERSYM(&SYSGLOBAL,&UPCASE(&PNAME),6+&locsize+&inpsize+&outsize,0)=0) THEN
					macerr 'Begin macro: Could not enter label Ò',&UPCASE(&PNAME),'Ó into symbol table'
				ENDIF
			ENDIF


			IF (&length=':b') THEN
&outsize			SETA	&outsize+1
				CYCLE
			ELSEIF (&length=':w') THEN
&outsize			SETA &outsize+2
				CYCLE
			ELSEIF (&length=':a') THEN
&outsize			SETA &outsize+3
				CYCLE
			ELSEIF (&length=':l') THEN
&outsize			SETA &outsize+4
				CYCLE
			ELSEIF (&length=':r') THEN
&outsize			SETA &outsize+8
				CYCLE
			ELSEIF (&length=':x') THEN
&outsize			SETA &outsize+10
				CYCLE
			ELSE
				macerr 'Begin macro: Bad output specification "',&PName,'"'
				MEXIT
			ENDIF

		ENDWHILE

.done
		IF &nbr(&syslist)=0 GOTO .skip6
		IF (&op1­'+b') AND (&op1­'+B') GOTO .skip6
&gbank		seta		1
			phb
			phk
			plb
.skip6
		MEND

;--------------------------------------------------------------------------
		MACRO
&lab		return	&op1
&lab
		GBLC		&gerror
		GBLA		&reterr
		GBLA		&gbank
		GBLA		&glink
		GBLA		&gloccnt
		GBLA		&gincnt
		GBLA		&goutcnt

		GBLA		&inbegin
		IF (&inbegin=0) THEN
			macerr 'ÔReturnÕ without a ÔBeginÕ'
			MEXIT
		ENDIF		
&inbegin	SETA		0

		IF &nbr(&syslist) THEN
&reterr		SETA		1
&gerror		SETC		&op1
		ENDIF

		IF &gbank THEN
			plb
		ENDIF

		IF &glink THEN
			IF &reterr THEN
				IF &gerror­'a' THEN
					ldy		&gerror
				ELSE
					tay
				ENDIF
			ENDIF

			IF input­output THEN
				lda		input-2				;move return address
				sta		output-2
				lda		input-3
				sta		output-3

				lda		input-5				; reset old DP
				tcd

				tsc							; reset stack pointer
				clc
				adc		#output-4
				tcs
			ELSE
				IF input­6 THEN
					tsc						; reset stack pointer
					clc
					adc		#output-6
					tcs
				ENDIF
				pld							; reset old DP
			ENDIF

			IF &reterr THEN
				tya
				cmp		#1
			ENDIF

		ELSEIF &reterr THEN						; nolink
			IF	&gerror­'a' THEN
				lda		&gerror
			ENDIF

			cmp		#1
		ENDIF

		rtl

&gbank             SETA      0
&glink             SETA      0
&reterr            SETA      0
&gloccnt           SETA      0
&gincnt            SETA      0
&goutcnt           SETA      0
&gerror            SETC      ''
                   MEND


;---------------------------------------------------------------------------
;
;               Allocate the Local Space on the stack,
;               Use Stack Space as the new Zero Page,
;               Create labels to the input and output parameters
;               if SizeLocals is not specified, does'nt make local space.
;
;       link SizeInput [,SizeLocals]   or   links SizeInput [,SizeLocals]
;
;
;
;              (stack before macro)
;
;        |         output space        |
;        | _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
;        |                             |
;        |         input space         |
;        |_____________________________|
;        |_                           _|
;        |_            RTA            _|
;        |_____________________________|
;                                        <= SP
;
;
;              (stack after macro)
;
;        |         output space        |
;        | _ _ _ _ _ _ _ _ _ _ _ _ _ _ | <= output
;        |                             |
;        |         input space         |
;        |_____________________________| <= input
;        |_                           _|
;        |_           RTA             _|
;        |_____________________________|
;        |_          old DP           _|
;        |_____________________________|
;        |                             |
;        |       local variables       |
;        | _ _ _ _ _ _ _ _ _ _ _ _ _ _ |
;                                        <=  SP  <= DP
;...........................................................................;

                MACRO
&lab            link    &SizeInput,&SizeLocals
&lab
		IF	(&nbr(&syslist)=2) GOTO .a
                LCLC    &SizeLocals
&SizeLocals     SETC    0
.a
		IF (&type('locals')='EQU') THEN
			macerr  'Multiple ÔbeginÕ statements.'
			MEXIT
		ENDIF
locals          equ     1
input           equ     &SizeLocals+5+locals
output          equ     input+&SizeInput

                phd                                    ; push current DP
                tsc

		IF	&SizeLocals=0 GOTO .b           ; make stack space
                sec                                    ; for local variables
                sbc     #&SizeLocals
                tcs
.b
                tcd
                MEND




;.............................................................................
;
;               Unlink the Local Space, restore the previous Zero Page,
;               Pull the input parameters off the stack, push the RTL address
;               Adjust Carry according to Error Status (in accumulator)
;
;       unlink_err, unlink
;..............................................................................

                MACRO
&lab            unlink_err   &err
&lab	; 

		IF	&nbr(&syslist) GOTO .here
                tay                                    ; save 'a' register
		GOTO .there

.here
                ldy     &err
.there
		IF	input=output GOTO .a
                lda     input-2                        ; move return address
                sta     output-2
                lda     input-3
                sta     output-3

                lda     input-5                        ; reset old DP
                tcd

                tsc                                    ; reset stack pointer
                clc
                adc     #output-4
                tcs
		GOTO .b


.a
		IF	input=6 GOTO .f
                tsc                                    ; reset stack pointer
                clc
                adc     #output-6
                tcs
.f
                pld                                    ; reset old DP

.b
                tya                                    ; reset 'a' and status
                cmp     #1                             ; register
                MEND


;------------------------------------------------------------------------------
                MACRO
&lab            unlink
&lab	; 

		IF	input=output GOTO .a
                lda     input-2                        ;move return address
                sta     output-2
                lda     input-3
                sta     output-3

                lda     input-5                        ; reset old DP
                tcd

                tsc                                    ; reset stack pointer
                clc
                adc     #output-4
                tcs
                MEXIT

.a
		IF	input=6 GOTO .f
                tsc                                    ; reset stack pointer
                clc
                adc     #output-6
                tcs
.f
                pld                                    ; reset old DP
                MEND



;............................................................................;
;
;        Space long (4 bytes) onto stack
;
;    spacelong                    - push 4 bytes on stack
;
;............................................................................;
         MACRO
&lab     spacelong
&lab	; 
         pha
         pha
         MEND
;............................................................................;
;
;        Space word (2 bytes) onto stack
;
;    spaceword                    - push 2 bytes on stack
;
;............................................................................;
         MACRO
&lab     spaceword
&lab	; 
         pha
         MEND

;---------------------------------------------------------------------------
;           Push a byte as a word
            MACRO
&lab        PushWordByte &param
            moveword &param,a
            and #$FF00
            pha
            MEND


;---------------------------------------------------------------------------
;           Push a word as a long

            MACRO
&lab        PushLongWord &param
            pea 0
            pushword &param
            MEND

;---------------------------------------------------------------------------
;           Push a word as a fixedpoint

            MACRO
&lab        PushFixWord &param
            pushword &param
            pea 0
            MEND


;---------------------------------------------------------------------------
;           Pull a fixedpoint as a word

            MACRO
&lab        PullFixWord &param
            pla
            pullword &param
            MEND



;----------------------------------------------------------------------
;         PushRect

            MACRO
&lab        pushrect &param
&lab	; 
            pushlong &param+4
            pushlong &param
            MEND


;----------------------------------------------------------------------
;        PullRect

            MACRO
&lab        pullrect	&param
&lab
		IF	(&nbr(&syslist)=0) OR (&param='a') THEN
			pla
			pla
			pla
			pla
		ELSE
			pulllong	&param
			pulllong	&param+4
		ENDIF

            MEND






;---------------------------------------------------------------------------


;............................................................................;
;
;          Push aliases
;
;............................................................................;
           MACRO
&lab       pushb   &loc
&lab	; 
           pushbyte     &loc
           MEND
           MACRO
&lab       pushw   &loc
&lab	; 
           pushword     &loc
           MEND
           MACRO
&lab       pusha   &loc
&lab	; 
           pushadr      &loc
           MEND
           MACRO
&lab       pushl        &loc
&lab	; 
           pushlong     &loc
           MEND
;............................................................................;
;
;          Pull aliases
;
;............................................................................;
           MACRO
&lab       pullb   &loc
&lab	; 
           pullbyte     &loc
           MEND
           MACRO
&lab       pullw   &loc
&lab	; 
           pullword     &loc
           MEND
           MACRO
&lab       pulla   &loc
&lab	; 
           pulladr      &loc
           MEND
           MACRO
&lab       pulll        &loc
&lab	; 
           pulllong     &loc
           MEND
;............................................................................;
;
;          Push 1 byte word on stack macro
;          modified 6/8/88, Scott Lindsey
;          to fix   pushbyte #const
;          and      pushbyte dp.addr
;          problems.
;                            PushByte   addr            PushByte   addr:#off
;    PushByte    a           PushByte   addr:x          PushByte   [zp]
;    PushByte    x           PushByte   addr:y          PushByte   [zp]:y
;    PushByte    y           PushByte   addr:s          PushByte   [zp]:off
;    PushByte    #const      PushByte   addr:off        PushByte   [zp]:#off
;
;............................................................................;
        MACRO
&lab    PushByte &loc
&lab	; 
        lclc    &char
	   lclc	&newloc
	   lcla	&ppos
&newloc	setc	&loc

		IF	(&newloc='x') or (&newloc='y') or (&newloc='a') GOTO .doreg
        sep     #%00100000
			longa  off
        moveword &newloc,a
        pha
        rep     #%00100000
			longa  on
        MEXIT
.doreg
        sep     #%00110000
			longa   off
			longi   off
        ph&newloc
        rep     #%00110000
			longa   on
			longi   on
        MEND
;............................................................................;
;
;          Push 2 byte word on stack macro
;
;          Modified 5/88, Scott Lindsey
;          to use pei for dp variables.
;
;
;                            PushWord   addr            PushWord   addr:#off
;    PushWord    a           PushWord   addr:x          PushWord   [zp]
;    PushWord    x           PushWord   addr:y          PushWord   [zp]:y
;    PushWord    y           PushWord   addr:s          PushWord   [zp]:off
;    PushWord    #const      PushWord   addr:off        PushWord   [zp]:#off
;
;    Caveat:     Since
;                            Pushword DP
;
;                is translated into a 'pei' instruction,
;
;                            Pushword addr
;
;                where addr is an equated address does not work correctly.
;                e.g.
;
;                Border      equ $00C034
;
;                            pushword Border
;
;                would **not** successfully push the contents of 00/C034
;
;                also note that the accumulator is not affected by pei,
;                so the value of what was pushed does not remain in
;                A as it used to... this is for DP variables ONLY.
;............................................................................;
        MACRO
&lab    PushWord &loc
&lab	; 
        lclc    &newloc
	   lclc	 &newloc2
        lclc    &char
        lclc    &rest
        lclc    &disp
        lcla    &offset
	   lcla	 &ppos
&newloc	setc	&loc
&ppos	seta	&pos('.',&loc)
		IF	&ppos=0 GOTO .noeval
		eval &newloc
&newloc	setc	'a'
.noeval	IF	&newloc <> '?' GOTO .notfromdc
&newloc	setc	'a'
.notfromdc
		IF	&nbr(&syslist)=0 GOTO .dopush
		IF	(&newloc='x') or (&newloc='y') or (&newloc='a') GOTO .doreg
&offset seta &pos(':',&newloc)
&char   setc &substr(&newloc,1,1)
		IF	&offset GOTO .dopushoff
		IF	(&char='#') GOTO .doimm
		IF	(&char='[') or (&char='>') or (&char='$') GOTO .normal
&offset seta &pos('+',&newloc)
&newloc2 setc    &newloc
		IF	&offset GOTO .rmplus
		GOTO .dopei

.rmplus
&newloc2 setc &substr(&newloc,1,&offset-1)
.dopei
.;	IF	&pos('IMPORT',&type(&newloc2)) GOTO .normal
	IF	&type(&newloc2) = 'EQU' OR &isint(&newloc2) THEN
		IF	&eval(&newloc) < 256 THEN
			pei	&newloc
			mexit
		ENDIF
	ENDIF
.;	IF	&type(&newloc)­'EQU' GOTO .normal
.;	IF  not(&findsym(&syslocal,&uc(&newloc))) GOTO .normal

.normal
&offset seta &pos(':',&newloc)
		IF	&offset GOTO .dopushoff
        lda     &newloc
        pha
        mexit
.dopushoff
&rest   setc &substr(&newloc,1,&offset-1)
&disp   setc &substr(&newloc,&offset+1,&len(&newloc)-&offset)
		IF	(&disp='x') or (&disp='y') or (&disp='s') GOTO .dopushoffi
		IF	(&char='[') GOTO .dopushoffzp
        ldx     &disp
        lda     &rest,x
        pha
        mexit
.dopushoffi
        lda     &rest,&disp
        pha
        mexit
.dopushoffzp
        ldy     &disp
        lda     &rest,y
        pha
        mexit
.dopush
        pha
        mexit
.doimm
&char   setc &substr(&newloc,2,1)
		IF	(&char='(') GOTO .doimm2
		pea &substr(&newloc,2,&len(&newloc)-1)
        mexit
.doimm2
		pea &substr(&newloc,3,&len(&newloc)-3)
        mexit
.doreg
        ph&newloc
        MEND
;............................................................................;
;
;          Push 3 byte address on stack macro
;
;    PushAdr    a           PushAdr   addr:y          PushAdr   [zp]
;    PushAdr    #const      PushAdr   addr:s          PushAdr   [zp]:y
;    PushAdr    addr        PushAdr   addr:off        PushAdr   [zp]:off
;    PushAdr    addr:x      PushAdr   addr:#off       PushAdr   [zp]:#off
;
;............................................................................;
        MACRO
&lab    PushAdr &loc
&lab	; 
        lclc    &char
        lclc    &rest
        lclc    &disp
        lcla    &offset
		IF	(&nbr(&syslist)=0) or (&loc='a') GOTO .dopush
&char   setc &substr(&loc,1,1)
		IF	(&char='#') GOTO .doimm
&offset seta &pos(':',&loc)
		IF	&offset GOTO .dopushoff
		IF	(&char='[') GOTO .dopushzp
        lda     &loc+1
        pha
		GOTO .dosimple

.dopushzp
        ldy     #1
        lda     &loc,y
        pha
		GOTO .dosimple

.doimm
&rest   setc &substr(&loc,2,&len(&loc)-1)
        lda     #(&rest>>8)
        pha
		GOTO .dosimple

.dosimple
        phb
        lda     &loc
        sta     1,s
        mexit
.dopush
        pha
        phb
        mexit
.dopushoff
&rest   setc &substr(&loc,1,&offset-1)
&disp   setc &substr(&loc,&offset+1,&len(&loc)-&offset)
		IF	(&char='[') GOTO .dopushoffzp
		IF	(&disp='s') GOTO .dopushoffs
		IF	(&disp='x') or (&disp='y') GOTO .dopushoffi
        ldx     &disp
&disp   setc    'x'
.dopushoffi
        lda     &rest+1,&disp
        pha
        phb
        lda     &rest,&disp
        sta     1,s
        mexit
.dopushoffs
        lda     &rest,s
        tax
        lda     &rest+1,s
        pha
        phb
        txa
        sta     1,s
        mexit
.dopushoffzp
		IF	(&disp='y') GOTO .dopushoffzpy
&char   setc &substr(&disp,1,1)
		IF	(&char='#') GOTO .dopushoffzpimm
        ldy     &disp
.dopushoffzpy
        iny
		GOTO .dopushoffzp2

.dopushoffzpimm
        ldy     &disp+1
.dopushoffzp2
        lda     &rest,y
        pha
        phb
        dey
        lda     &rest,y
        sta     1,s
        MEND
;............................................................................;
;
;          Push 4 byte long word on stack macro
;
;          Modified 5/88, Scott Lindsey
;          to use pei for dp variables.
;
;    PushLong    a           PushLong   addr            PushLong   addr:#off
;    PushLong    ax          PushLong   addr:x          PushLong   [zp]
;    PushLong    ay          PushLong   addr:y          PushLong   [zp]:y
;    PushLong    xy          PushLong   addr:s          PushLong   [zp]:off
;    PushLong    #const      PushLong   addr:off        PushLong   [zp]:#off
;
;    Note: If you wish to push the address of a direct page label then use
;          the following format:  PushLong !label.
;
;    Caveat:     Since
;                            Pushlong DP
;
;                is translated into two 'pei' instructions,
;
;                            Pushlong addr
;
;                where addr is an equated address does not work correctly.
;                e.g.
;
;                Border      equ $00C034
;
;                            pushlong Border
;
;                would **not** successfully push the contents of 00/C034
;
;                also note that the accumulator is not affected by pei,
;                so the lower word of what was pushed does not remain in
;                A as it used to... this is for DP variables ONLY.
;
;
;............................................................................;
        MACRO
&lab    PushLong &loc
&lab	; 
        lclc     &newloc
	   lclc	  &newloc2
        lclc     &char
        lcla     &offset
        lclc     &rest
        lclc     &disp
&newloc	setc &loc
		IF	&newloc<>'?' GOTO .notfromdc
&newloc	setc	'ax'
.notfromdc
		IF	&nbr(&syslist)=0 GOTO .dopush
		IF	(&newloc='a') GOTO .dopush
		IF	(&newloc='ax') GOTO .dopushax
		IF	(&newloc='ay') GOTO .dopushay
		IF	(&newloc='xy') GOTO .dopushxy
&char   setc &substr(&newloc,1,1)
		IF	(&char='#') GOTO .doimm
		IF	(&char='!') GOTO .dopushlocal
&offset seta &pos(':',&newloc)
		IF	&offset GOTO .dopushoff
		IF	(&char='[') GOTO .dopushzp
		IF	(&char='>') or (&char='$') GOTO .normal
&offset seta &pos('+',&newloc)
&newloc2 setc    &newloc
		IF	&offset GOTO .rmplus
		GOTO .dopei

.rmplus
&newloc2 setc &substr(&newloc,1,&offset-1)
.dopei
.;		IF	&pos('IMPORT',&type(&newloc2)) GOTO .normal
	IF	&type(&newloc2) = 'EQU' OR &isint(&newloc2) THEN
		IF	&eval(&newloc) < 256-2 THEN
			pei	&newloc+2
			pei	&newloc
			mexit
		ENDIF
	ENDIF
.;		IF	&type(&newloc2)­'EQU' GOTO .normal
.;		IF  not(&findsym(&syslocal,&uc(&newloc2))) GOTO .normal

.normal
        lda      &newloc+2
        pha
        lda      &newloc
        pha
        mexit
.dopush
        pha
        pha
        mexit
.doimm
&char   setc &substr(&loc,2,1)
		IF	(&char='(') GOTO .doimm2
		lclc &immloc
&immloc    setc &substr(&newloc,2,&len(&newloc)-1)
		pea &immloc>>16
		pea |&immloc
        mexit

.doimm2
		lclc &immloc
&immloc	setc &substr(&newloc,3,&len(&newloc)-3)
		pea &immloc>>16
		pea |&immloc
        mexit

.dopushax
        phx
        pha
        mexit
.dopushay
        phy
        pha
        mexit
.dopushxy
        phy
        phx
        mexit
.dopushzp
        ldy #2
        lda &newloc,y
        pha
        lda &newloc
        pha
        mexit
.dopushoff
&rest   setc &substr(&newloc,1,&offset-1)
&disp   setc &substr(&newloc,&offset+1,&len(&newloc)-&offset)
		IF	&char='[' GOTO .dopushoffzp
		IF	(&disp='s') GOTO .dopushoffs
		IF	(&disp='x') or (&disp='y') GOTO .dopushoffi
        ldx &disp
&disp   setc 'x'
.dopushoffi
        lda &rest+2,&disp
        pha
        lda &rest,&disp
        pha
        mexit
.dopushoffs
        lda &rest+2,s
        pha
        lda &rest+2,s
        pha
        mexit
.dopushoffzp
		IF	(&disp='y') GOTO .dopushoffzpy
&char   setc &substr(&disp,1,1)
		IF	(&char='#') GOTO .dopushoffzpi
        ldy &disp
        iny
        iny
        lda &rest,y
        pha
        ldy &disp
        lda &rest,y
        pha
        mexit
.dopushoffzpi
        ldy &disp+2
        lda &rest,y
        pha
        ldy &disp
        lda &rest,y
        pha
        mexit
.dopushoffzpy
        iny
        iny
        lda &rest,y
        pha
        dey
        dey
        lda &rest,y
        pha
        mexit
.dopushlocal
&newloc	setc &substr(&newloc,2,&len(&newloc)-1)
        pea $0000
        tdc
        clc
        adc #&newloc
        pha
        MEND
;............................................................................;
;
;          Pull 1 byte word off stack macro
;
;    PullByte    a           PullByte   addr:x          PullByte   [zp]
;    PullByte    x           PullByte   addr:y          PullByte   [zp]:y
;    PullByte    y           PullByte   addr:off        PullByte   [zp]:off
;    PullByte    addr        PullByte   addr:#off       PullByte   [zp]:#off
;
;............................................................................;
        MACRO
&lab    PullByte &loc
&lab	; 
		IF	(&loc='x') or (&loc='y') GOTO .doreg
        sep     #%00100000
			longa   off
        PullWord &loc
        rep     #%00100000
			longa   on
        mexit
.doreg
        sep     #%00110000
			longa   off
			longi   off
        PullWord &loc
        rep     #%00110000
			longa   on
			longi   on
        MEND
;............................................................................;
;
;          Pull 2 byte word off stack macro
;
;                            PullWord   addr
;    PullWord                PullWord   addr:x          PullWord   [zp]
;    PullWord    a           PullWord   addr:y          PullWord   [zp]:y
;    PullWord    x           PullWord   addr:off        PullWord   [zp]:off
;    PullWord    y           PullWord   addr:#off       PullWord   [zp]:#off
;
;............................................................................;
        MACRO
&lab    PullWord &loc
&lab	; 
        lclc    &char
        lclc    &rest
        lclc    &disp
        lcla    &offset
	   lclc	 &newloc
&newloc	setc	&loc
		IF	&newloc<>'?' GOTO .notfromdc
&newloc	setc	'a'
.notfromdc
		IF	&nbr(&syslist)=0 GOTO .dopull
		IF	(&newloc='x') or (&newloc='y') or (&newloc='a') GOTO .doreg
        pla
&char   setc &substr(&newloc,1,1)
&offset seta &pos(':',&newloc)
		IF	&offset GOTO .dopulloff
        sta     &newloc
        mexit
.dopulloff
&rest   setc &substr(&newloc,1,&offset-1)
&disp   setc &substr(&newloc,&offset+1,&len(&newloc)-&offset)
		IF	(&disp='x') or (&disp='y') or (&disp='s') GOTO .dopulloffi
		IF	(&char='[') GOTO .dopulloffzp
        ldx     &disp
&disp   setc    'x'
.dopulloffi
        sta     &rest,&disp
        mexit
.dopulloffzp
        ldy     &disp
        sta     &rest,y
        mexit
.dopull
        pla
        mexit
.doreg
        pl&newloc
        MEND
;............................................................................;
;
;          Pull 3 byte address off stack macro
;
;    PullAdr    a                                     PullAdr   [zp]
;    PullAdr    addr        PullAdr   addr:off        PullAdr   [zp]:y
;    PullAdr    addr:x      PullAdr   addr:#off       PullAdr   [zp]:off
;    PullAdr    addr:y                                PullAdr   [zp]:#off
;
;............................................................................;
        MACRO
&lab    PullAdr &loc
&lab	; 
        lclc    &char
        lclc    &rest
        lclc    &disp
        lcla    &offset
		IF	(&nbr(&syslist)=0) or (&loc='a') GOTO .dopull
&char   setc &substr(&loc,1,1)
&offset seta &pos(':',&loc)
		IF	&offset GOTO .dopulloff
        phb
        pla
        xba
        sta      &loc
		IF	&char='[' GOTO .dopullzp
        pla
        sta &loc+1
        mexit
.dopullzp
        ldy #1
        pla
        sta     &loc,y
        mexit
.dopull
        phb
        pla
        pla
        mexit
.dopulloff
&rest   setc &substr(&loc,1,&offset-1)
&disp   setc &substr(&loc,&offset+1,&len(&loc)-&offset)
		IF	(&char='[') GOTO .dopulloffzp
		IF	(&disp='x') or (&disp='y') GOTO .dopulloffi
        ldx     &disp
&disp   setc    'x'
		GOTO .dopulloffi

.dopulloffzp
		IF	&disp='y' GOTO .dopulloffzpy
        ldy     &disp
.dopulloffzpy
        phb
        pla
        xba
        sta      &rest,y
        iny
        pla
        sta      &rest,y
        mexit
.dopulloffi
        phb
        pla
        xba
        sta      &rest,&disp
        pla
        sta      &rest+1,&disp
        MEND
;............................................................................;
;
;          Pull 4 byte long word off stack macro
;
;                            PullLong   addr
;    PullLong     a          PullLong   addr:x          PullLong   [zp]
;    PullLong    ax          PullLong   addr:y          PullLong   [zp]:y
;    PullLong    ay          PullLong   addr:off        PullLong   [zp]:off
;    PullLong    xy          PullLong   addr:#off       PullLong   [zp]:#off
;
;............................................................................;
        MACRO
&lab    PullLong &loc
&lab	; 
	   lclc	  &newloc
        lclc     &char
        lcla     &offset
        lclc     &rest
        lclc     &disp
&newloc	setc	&loc
		IF	&newloc <> '?' GOTO .notfromdc
&newloc	setc 'ax'
.notfromdc
		IF	(&nbr(&syslist)=0) or (&newloc='a') GOTO .dopull
		IF	(&newloc='ax') GOTO .dopullax
		IF	(&newloc='ay') GOTO .dopullay
		IF	(&newloc='xy') GOTO .dopullxy
&char   setc &substr(&newloc,1,1)
&offset seta &pos(':',&newloc)
		IF	&offset GOTO .dopulloff
		IF	(&char='[') GOTO .dopullzp
        pla
        sta      &newloc
        pla
        sta      &newloc+2
        mexit
.dopull
        pla
        pla
        mexit
.dopullax
        pla
        plx
        mexit
.dopullay
        pla
        ply
        mexit
.dopullxy
        plx
        ply
        mexit
.dopullzp
        pla
        sta &newloc
        pla
        ldy #2
        sta &newloc,y
        mexit
.dopulloff
&rest   setc &substr(&newloc,1,&offset-1)
&disp   setc &substr(&newloc,&offset+1,&len(&newloc)-&offset)
		IF	&char='[' GOTO .dopulloffzp
		IF	(&disp='x') or (&disp='y') GOTO .dopulloffi
        ldx &disp
&disp   setc 'x'
.dopulloffi
        pla
        sta &rest,&disp
        pla
        sta &rest+2,&disp
        mexit
.dopulloffzp
		IF	(&disp='y') GOTO .dopulloffzpy
&char   setc &substr(&disp,1,1)
		IF	(&char='#') GOTO .dopulloffzpi
        pla
        ldy &disp
        sta &rest,y
        pla
        ldy &disp
        iny
        iny
        sta &rest,y
        mexit
.dopulloffzpi
        pla
        ldy &disp
        sta &rest,y
        pla
        ldy &disp+2
        sta &rest,y
        mexit
.dopulloffzpy
        pla
        sta &rest,y
        pla
        iny
        iny
        sta &rest,y
        MEND
