	nlist
;
; %AZTEC.INC -- include file for Aztec C86 use of Tinylib .ASM files
;
;***************************************************************************
;
; This file provides standardized macros to generate ASM code that meets
; the Aztec coding conventions.
;
; Last updated 11/20/86 -- Chip Rabinowitz
;
; Assembler: Aztec V3.40A (also tested with V3.20E)
;
;****************************************************************************

MODEL equ	3		; modify this line for the appropriate memory model
						; 0 - small model
						; 1 - large code, small data
						; 2 - small code, large data
						; 3 - large code, large data
	ifndef	MODEL
MODEL	equ	0
	endif
	if	MODEL and 1
	largecode
FARPROC	equ 1
FPTRSIZE equ	4
	else
FPTRSIZE equ	2
	endif
	if	MODEL and 2
LONGPTR equ 1
	endif

ttl	macro	modnam, vrsn, date , auth
	title	modnam -- Version vrsn -- d2io -- date -- auth
	subttl	Copright 1986 Jim Kyle and Chip Rabinowitz
	name	modnam
;
	endm

;			start of data segment
dseg	macro
dataseg	segment	para public 'DATA'
	endm

;			define space for a pointer
defptr	macro	ptrnam
ifdef	LONGPTR
ptrnam	dd	0
else
ptrnam	dw	0
endif
	endm

;			declare vname as external
extv	macro	vname, type
	extrn	vname&_:type
	endm

;			declare vname as global and initialize it
glblv	macro	vname, type, val
	havtyp = 0
	public	vname&_
ifidn	<type>, <byte>
vname&_	db	val
	havtyp = 1
endif
ifidn	<type>, <word>
vname&_	dw	val
	havtyp = 1
endif
ifidn	<type>, <dword>
vname&_	dd	val
	havtyp = 1
endif
ife	havtyp
	error -- type is unknown.
endif
	endm

glblvl	macro	list
	irp	i, <list>
	glblv	i
	endm
	endm

;			end of data segment, start of code segment
cseg macro
dataseg	ends
codeseg	segment	byte public 'code'
	assume	cs:codeseg,ds:dataseg
	endm

;			declare fname as external
extf	macro	fname
ifdef FARPROC
	extrn	fname&_:far
else
	extrn fname&_:near
endif
	endm

xtfs	macro	list
	irp	i, <list>
	extf	i
	endm
	endm

; declare global error value
exterr	macro
	extrn	errno_:word
endm

; set global error value
moverr	macro	val
	mov	errno_,val
endm

; get global error value
geterr	macro	val
	mov	val,errno_
endm

;copy global error value into stream table
saverr	macro
	push	ax
	geterr	ax
	mov	byte ptr 4[si],al
	pop	ax
endm

;this macro equates 'aname' to arg on stack (parameter)
darg	macro 	aname, type
;;'byte' or anything else
	havtyp	= 0
ifidn	<type>, <byte>
	aname&v	= (_arg + 0)
	aname	equ	byte ptr aname&v[bp]
	_arg	= _arg + 2
	havtyp	= 1
endif
ifidn <type>, <word>
	aname&v	= (_arg + 0)
	aname	equ	word ptr aname&v[bp]
	_arg	= _arg + 2
	havtyp	= 1
endif
ifidn	<type>, <dword>
	aname&v	= (_arg + 0)
	aname	equ	dword ptr aname&v[bp]
	_arg	= _arg + 4
	havtyp	= 1
endif
ifidn <type>, <cdouble>
	aname&v	= (_arg + 0)
	aname	equ	qword ptr aname&v[bp]
	_arg	= _arg + 8
	havtyp	= 1
endif
ifidn <type>, <ptr>
	ifdef LONGPTR
		aname&v	= (_arg + 0)
		aname	equ	dword ptr aname&v[bp]
		_arg	= _arg + 4
	else
		aname&v	= (_arg + 0)
		aname	equ	word ptr aname&v[bp]
		_arg	= _arg + 2
	endif
	havtyp	= 1
endif
ifidn <type>, <fptr>
	ifdef FARPROC
		aname&v	= (_arg + 0)
		aname	equ	dword ptr aname&v[bp]
		_arg	= _arg + 4
	else
		aname&v	= (_arg + 0)
		aname	equ	word ptr aname&v[bp]
		_arg	= _arg + 2
	endif
	havtyp	= 1
endif
ife	havtyp
	error -- type is unknown.
endif
	endm

dargs	macro	list
	irp	i, <list>
	darg	i
	endm
	endm

;			define a global procedure
procdef	macro	pname, args
	public pname&_
ifdef	FARPROC
	_arg	=	6		;;allow for BP and ret adr
	_lsz	=	2
	pname&_	proc	far
else
	_arg	=	4		;;allow for BP and ret adr
	_lsz	=	2
	pname&_	proc	near
endif
	havreg = 0
	haveds = 0
ifb <args>
	havbp = 0
else
	push bp
	mov bp,sp
	havbp = 1
	dargs <args>
endif
	endm

;			equate 'lvnm' to local variable
dclv	macro 	lvnm, type,asiz
;;'byte' or anything else
	havtyp	= 0
ifidn	<type>, <byte>
	_lsz	= _lsz + 2
	lvnm&l	= (0 - _lsz)
	lvnm	equ	byte ptr lvnm&l[bp]
	havtyp	= 1
endif
ifidn <type>, <word>
	_lsz	= _lsz + 2
	lvnm&l	= (0 - _lsz)
	lvnm	equ	word ptr lvnm&l[bp]
	havtyp	= 1
endif
ifidn	<type>, <dword>
	_lsz	= _lsz + 4
	lvnm&l	= (0 - _lsz)
	lvnm	equ	dword ptr lvnm&l[bp]
	havtyp	= 1
endif
ifidn <type>, <cdouble>
	_lsz	= _lsz + 8
	lvnm&l	= (0 - _lsz)
	lvnm	equ	qword ptr lvnm&l[bp]
	havtyp	= 1
endif
ifidn <type>, <ptr>
	ifdef LONGPTR
	_lsz	= _lsz + 4
	lvnm&l = (0 - _lsz)
	lvnm equ dword ptr lvnm&l[bp]
	else
	_lsz	= _lsz + 2
	lvnm&l	= (0 - _lsz)
	lvnm	equ	word ptr lvnm&l[bp]
	endif
	havtyp	= 1
endif
ifidn <type>, <fptr>
	ifdef FARPROC
	_lsz	= _lsz + 4
	lvnm&l = (0 - _lsz)
	lvnm equ dword ptr lvnm&l[bp]
	else
	_lsz	= _lsz + 2
	lvnm&l	= (0 - _lsz)
	lvnm	equ	word ptr lvnm&l[bp]
	endif
	havtyp	= 1
endif
ifidn <type>, <baray>
	_lsz	= _lsz + asiz
	lvnm&l	= (0 - _lsz)
	lvnm	equ	byte ptr lvnm&l[bp]
	havtyp	= 1
endif
ifidn <type>, <iaray>
	_lsz	= _lsz + asiz + asiz
	lvnm&l	= (0 - _lsz)
	lvnm	equ	word ptr lvnm&l[bp]
	havtyp	= 1
endif
ife	havtyp
	error -- type is unknown.
endif
	endm

locs	macro	list
;	_lsz	=	2
	irp	i, <list>
	dclv	i
	endm
if	_lsz-2
	sub	sp, _lsz
endif
	endm

;			declare alt name for global procedure (alias)
alias	macro	pname, altnam
	public	altnam&_
ifdef FARPROC
	altnam&_	label	far
else
	altnam&_	label	near
endif
	endm

;			declare alt entry to global procedure (without args)
entrdef	macro	pname
	public pname&_
pname&_:
if	havbp
	push	bp
	mov	bp, sp
endif
	endm

;			define a static procedure (internal, with args)
statdef	macro	pname, args
ifdef	FARPROC
	_arg	=	6		;;allow for BP and ret adr
	_lsz	=	2
	pname	proc	far
else
	_arg	=	4		;;allow for BP and ret adr
	_lsz	=	2
	pname	proc	near
endif
	havreg = 0
	haveds = 0
ifb	<args>
	havbp = 0
else
	push	bp		;;save frame pointer, set new one
	mov	bp, sp
	havbp	= 1
	dargs	<args>
endif
	endm

;			begin a local procedure (without args)
internal macro	pname
pname	proc	near
	havreg = 0
	haveds = 0
	havbp = 0
	endm

intrdef	macro	pname
ifdef FARPROC
	pname	label	far
else
	pname	label	near
endif
	havreg = 0
	haveds = 0
	havbp = 0
	endm

callit	macro	pname,args
	argsize	= 0
ifnb	<args>
	pushargs <args>
endif
	call	pname&_
if	argsize
	add	sp,argsize
endif
	endm

pushargs	macro list
	irp	i,<list>
	pusharg	i
	endm
	endm

pusharg macro varib,type,segm
havtyp = 0
ifidn <type>,<byte>
	push	word ptr varib
	argsize = argsize + 2
	havtyp = 1
endif
ifidn <type>,<word>
	push	word ptr varib
	argsize = argsize + 2
	havtyp = 1
endif
ifidn <type>,<reg>
	push	varib
	argsize = argsize + 2
	havtyp = 1
endif
ifidn <type>,<preg>
ifdef LONGPTR
	ifnb <segm>
		push	segm
	else
		ifidn <varib>,<si>
			push	ds
		else
			ifidn <varib>,<di>
				push	es
			else
				ifidn <varib>,<dx>
					push	ds
				else
					error - undefined segment
				endif
			endif
		endif
	endif
	push	varib
	argsize = argsize + 4
else
	push	varib
	argsize = argsize + 2
endif
	havtyp = 1
endif
ifidn <type>,<dword>
	push	word ptr varib[2]
	push	word ptr varib
	argsize = argsize + 4
	havtyp = 1
endif
ifidn <type>,<cdouble>
	push	word ptr varib[6]
	push	word ptr varib[4]
	push	word ptr varib[2]
	push	word ptr varib
	argsize = argsize + 8
	havtyp = 1
endif
ifidn <type>,<ptr>
ifdef LONGPTR
	push	word ptr varib[2]
	push	word ptr varib
	argsize = argsize + 4
else
	push	word ptr varib
	argsize = argsize + 2
endif
	havtyp = 1
endif
ifidn <type>,<fptr>
ifdef FARPROC
;	push	word ptr varib&_ + 2
;	push	word ptr varib&_
;	push	seg varib&_
;	push	offset varib&_
	mov	dx,seg varib&_
	push	dx
	mov	dx,offset varib&_
	push	dx
	argsize = argsize + 4
else
	mov	dx,offset varib&_
	push	dx
	argsize = argsize + 2
endif
	havtyp = 1
endif
ife	havtyp
	error -- type is unknown.
endif
	endm



retptrm	macro	src
	local	x1,x2
	jnc	x1
	xor	ax,ax
ifdef LONGPTR
	mov	dx,ax
endif
	jmp	short x2
x1:
	mov	ax, word ptr src
ifdef	LONGPTR
	mov	dx, word ptr src+2
endif
x2:
	pret
	endm

retptrr	macro	src,seg
	local	x1,x2
	jnc	x1
	xor	ax,ax
ifdef LONGPTR
	mov	dx,ax
endif
	jmp	short x2
x1:
	mov	ax,src
ifdef LONGPTR
	ifnb <seg>
		mov	dx, seg
	endif
endif
x2:
	pret
	endm

retnull	macro
	xor	ax,ax
ifdef LONGPTR
	mov	dx,ax
endif
	pret
 	endm

retyes	macro
	mov	ax, 1
	pret
	endm

;			pushes register variables
pushreg	macro
	push	di
	push	si
	havreg = 1
	endm

;			restores bp and registers 
pret	macro
if	haveds
	pop	ds
endif
if	havreg
	pop	si
	pop	di
endif
if havbp
	mov	sp,bp
	pop bp
endif
	ret
	endm

;			restores register variables
popreg	macro
	pop	si
	pop	di
	havreg = 0
	endm

;			end a internal procedure
iend	macro	pname
pname	endp
	endm

;			end a global or static procedure
pend	macro	pname
pname&_	endp
	endm

finish	macro
codeseg	ends
	end
	endm

;	other utility stuff
;
;			push/pop pairs
pushds	macro
	ifdef LONGPTR
	haveds = 1
	push	ds
	endif
	endm

popds	macro
	ifdef LONGPTR
	haveds = 0
	pop	ds
	endif
	endm

pushptr	macro	pointer
	ifdef LONGPTR
	push	word ptr pointer+2
	push	word ptr pointer
	else
	push	word ptr pointer
	endif
	endm

popptr	macro	pointer
	ifdef LONGPTR
	pop	word ptr pointer
	pop	word ptr pointer+2
	else
	pop	word ptr pointer
	endif
	endm

;			push a local variable
pshloc	macro	vnam
	push	word ptr vnam&l[bp]
	endm

;			push an argument
psharg	macro	anam
	push	word ptr anam&v[bp]
	endm


;this macro loads an arg pointer into DEST, with optional SEGment
ldptr	macro	dest, argname, seg
ifdef	LONGPTR
	ifnb <seg>		;;get segment if specified
		ifidn <seg>,<es>
			les	dest,argname
		else
			ifidn <seg>,<ds>
				lds dest,argname
			else
				mov dest, word ptr argname
				mov seg, word ptr argname[2]
			endif
		endif
	else
		ifidn <dest>,<si>		;;si gets seg in ds
			lds	si, argname
		else
			ifidn <dest>,<di>	;;or, es:di
				les	di, argname
			else
				garbage error: no seg for long pointer
			endif
		endif
	endif
else
	mov dest, word ptr argname	;;get the pointer
ENDIF
	ENDM


;this macro unloads an arg pointer from DEST, with optional SEG
svptr	macro	dest, argname, seg
ifdef	LONGPTR
	ifnb <seg>		;;get segment if specified
		mov word ptr argname,dest
		mov word ptr argname[2],seg
	else
		ifidn <dest>,<si>		;;si gets seg in ds
		mov word ptr argname,si
		mov word ptr argname[2],ds
		else
			ifidn <dest>,<di>	;;or, es:di
				mov word ptr argname,di
				mov word ptr argname[2],es
			else
				garbage error: no seg for long pointer
			endif
		endif
	endif
else
	mov word ptr argname,dest	;;get the pointer
ENDIF
	ENDM
;		this macro sets ptrnam to point to SEG:SYM
;			note that AX is destroyed
setptr	macro	ptrnam,sym,seg
	lea	ax,sym
	svptr	ax,ptrnam,seg
endm

;		this macro copies FROM to TO, both pointers
;			note that AX and DX are destroyed
;
ptrcpyinc	macro	from,to
	push	ax
	push	dx
	gwi	from
ifdef	LONGPTR
	xchg	ax,dx
	gwi	from
	xchg	ax,dx
endif
	svptr	ax,to,dx
	pop	dx
	pop	ax
endm

extraseg	macro
ifndef	LONGPTR
	push	ds
	pop	es
endif
	endm

;			get char, unsigned, and increment ptr
gci	macro	ptr
	ldptr	si, ptr
	cld
	lodsb
	sub	ah, ah
	svptr	si, ptr
	endm

;			get word into AX and increment ptr
gwi	macro	ptr
	ldptr	si, ptr
	cld
	lodsw
	svptr	si, ptr
	endm

;			put char, unsigned, and increment ptr
pci	macro	ptr
	ldptr	di, ptr
	cld
	stosb
	svptr	di, ptr
	endm

;			put word into AX and increment ptr
pwi	macro	ptr
	ldptr	di, ptr
	cld
	stosw
	svptr	di, ptr
	endm

;			case test, byte
caseb	macro	val, goto
	cmp	al, val
	je	goto
	endm

;			case test, word
casew	macro	val, goto
	cmp	ax, val
	je	goto
	endm

	list
