;
; Assembly language & data module 
; for the PL/I FMS interface written in C
;
	.enabl	lc


	.title	pldfms

	.psect	pldfms

	.iif ndf reentrant  reentrant = 0	;default to reentrant version
	;0 means reentrant, -1 means non-reentrant, so .if eq reentrant
	;means if reentrant, and .if ne reentrant means if not reentrant

	.enabl	gbl	;all undeclared symbols are external

	.mcall $FDVDF	;get size parameters
	$FDVDF

	.globl	T$LUN	;make sure FDVDAT is loaded (it defined FMS impure)




;
; Call interface between C and FMS
;

$cfdv::

.if eq reentrant
	mov $VEXT,r1
	mov vx$fms(r1),r0	;argument block pointer is in impure

.iff ;non-reentrant
	mov #fd$$nm,fd$$ar+f$nam  ;most routines - name is in fixed scratch
$cfdvn::
	mov #fd$$ar,r0	;lopen name must be in bigger temp, pointer set by C
.endc

;call FMS & return directly to C (C called us by jsr pc,$cfdv/$cfdvn)

.if eq reentrant
	jmp @vx$fmd(r1)	;reentrant - pointer to driver in impure for clustering
.iff
	jmp $FDV	;non-reentrant - can jmp direct
.endc


.if eq reentrant

;
; reentrant version - define offsets to data from impure pointer
;

	.macro	defblk
	$blk$=0
	.endm

	.macro blk name, size
	name == $blk$
	$blk$ = $blk$+size
	.endm

	.macro endblk size
	.if nb size
	size == $blk$
	.endc
	.endm


defblk

   blk	fd$$ar, F$ASIZ	;argument block (must be at displacement 0 for $cfdv)

   blk	fd$$rq, F$RSIZ	;required argument block

			;(status block is in $$VEX1)

   blk	fd$$nm, 6	;space for one name

   blk	fd$$cn, 2 	;pointer to current field name
   blk	fd$$cx, 2	;current field index

   blk	fd$$im, 0	;start of FMS impure area

endblk fd$$sz		;size of our portion of impure area

.endc


.if ne reentrant

;
; non-reentrant version - variables are in static dirty data area
;

fd$$ar::.blkb	F$ASIZ	;argument block

fd$$rq::.blkb	F$RSIZ	;required argument block

fd$$st::.blkw	2	;status block

fd$$nm::.blkb	6	;space for one name

fd$$cn::.blkw	1	;pointer to current field name
fd$$cx::.blkw	1	;current field index

fd$$in::.word	0	;flag - whether impure area is initialized


;
; These pointers into above areas are needed because Macro does not
; allow equates based on globals (such as fd$fnc==fd$$ar+f$fnc), and
; because C does not pass global expressions to the task builder but
; compiles a bunch of code to evaluate them on every reference.
;

fd$fnc:: .word fd$$ar+f$fnc
fd$req:: .word fd$$ar+f$req
fd$nam:: .word fd$$ar+f$nam
fd$num:: .word fd$$ar+f$num
fd$trm:: .word fd$$ar+f$trm
fd$val:: .word fd$$ar+f$val
fd$len:: .word fd$$ar+f$len
fd$sts:: .word fd$$rq+f$sts
fd$chn:: .word fd$$rq+f$chn
fd$imp:: .word fd$$rq+f$imp

.endc


	.end
