;======================================================= ; ; Macros stolen from cmacros.inc (so we don't have to include it all) ; .286p externNP macro n irp x, extrn x:near endm endm externFP macro n irp x, extrn x:far endm endm externW macro w irp x, extrn x:word endm endm assumes macro s,ln assume s:_&ln endm createSeg macro n,ln,a,co,cl,grp n segment a co '&cl' n ends endm sBegin macro seg assume cs:_&seg _&seg segment endm sEnd macro seg _&seg ends assume cs:nothing endm errnz macro x ;;display error if expression is <>0 if2 if x ;;if expression is non-zero, errnz1 ,%(x) endif endif endm errnz1 macro x1,x2 = *errnz* x1 = x2 .err endm errn$ macro l,x ;;error if <$-label1 (exp2)> <>0 errnz endm createSeg _DATA,DATA,WORD,PUBLIC,DATA ;======================================================= ; ; Error API definitions ; ExternFP ; error codes include logerror.inc ;================================================================ ; Variable and temporary initialization VLseg equ <> ; Holds current segment name VLopen = 0 VLerrnotinvoked = 0 ifndef VLnogenpall VLnogenpall = 0 endif VLnogen = 0 VLnogenparm = 0 VLsavees = 0 VLsavebx = 0 ;if1 if 1 ;================================================================ ; Utility macros ;--------------------------------------------------------------------------- ; ; lodsw cs:[si] ; cslodsw macro db 2eh ;; CS override lodsw endm ;--------------------------------------------------------------------------- ; ; lodsb cs:[si] ; cslodsb macro db 2eh ;; CS override lodsb endm SkipTwoBytes macro db 0A9h ;; Opcode for CMP AX,(immediate word) endm ;--------------------------------------------------------------------------- ; ; Define a as the concatenation of b & c ; concat macro a,b,c,d,e,f a equ endm ;--------------------------------------------------------------------------- ; ; Assign a to b. ; equate macro a,b a = b endm ; ; Print a message ; _print macro a,b,c if2 %out a&b&c endif endm ;=============================================================== ;--------------------------------------------------------------------------- ; ; _gensub LABEL ; ; Causes per-segment subroutine code associated with type LABEL ; to be generated, by setting the genLABEL&lseg flag. ; _gensub2 macro l,s gen&l&s = 1 endm _gensub macro l _gensub2 ,%VLseg endm ;--------------------------------------------------------------------------- ; _SwitchSeg ; ; Switches current segment to seg, creating the segment if needed. ; _SwitchSeg macro seg,oldseg ifdifi <&seg>, ifnb sEnd oldseg endif concat ,seg, createSeg _&seg,seg,WORD,PUBLIC,CODE sBegin seg assumes CS,seg endif endm ;--------------------------------------------------------------------------- ; API ; API macro rettype,name,seg,optlist if VLopen APIEND endif VLname equ VLcbparms = 0 VLcbskip = 0 VLerrnotinvoked= 1 VLopen = 1 VLnogen = 0 VLnogenparm = 0 VLasm = 0 VLfunnyframe = 0 VLnodata = 0 VLcargs = 0 VLplist equ <> VLATMframe = 0 ; special entry/exit code sequence for ATM's patching VLATMfrmds = 0 ; ATM entry/exit code: mov ax,_DATA at beginning. VLsavees = 0 VLsavebx = 0 _SwitchSeg seg,%VLseg irp opt, ifidni , VLnogen = 1 endif ifidni , VLnogen = 1 endif ifidni , VLasm = 1 endif ifidni , VLATMframe = 1 endif ifidni , VLATMfrmds = 1 VLATMframe = 1 endif ifidni , VLfunnyframe = 1 endif ifidni , VLnodata = 1 endif ifidni , ifndef DEBUG VLnogen = 1 endif endif ifidni , VLcargs = 1 endif ifidni , VLsavees = 2 ; sizeof(ES) endif ifidni , VLsavebx = 2 ; sizeof(BX) endif endm concat ,, concat ,,<_error> concat ,, if1 equate %VLnamecbparms, %VLcbparms else equate %VLnamecbparms, %VLnamecbparms endif ife VLnogen ife VLcargs concat ,, ExternNP I&name public name name: else concat ,<_I>, ExternNP _I&name public _&name _&name: endif VLframe = 0 ; no frame set up yet. endif ; VLnogen endm ;; VL ;--------------------------------------------------------------------------- ; APIERR ; ; Optionally used after parameter decls to begin error handling code ; APIERR macro opts ife VLnogen ife VLframe _print ,%VLiname else pop dx ; pop off error handler address pop bp ; restore BP if VLATMframe dec bp ; fix BP back up endif if VLsavees pop es endif if VLsavebx pop bx endif endif jmp VLiname ; jmp to internal routine. equate %VLnamecbparms, %VLcbparms VLnameerror: VLerrnotinvoked = 0 endif ; VLnogen endm ;; APIERR ;--------------------------------------------------------------------------- ; APIEND ; ; Used after APIERR to terminate error handling code. ; APIEND macro _PurgeParms %VLplist ife VLnogen if VLerrnotinvoked APIERR endif if VLsavees pop es endif if VLsavebx pop bx endif ife VLcargs retf VLcbparms else retf endif VLopen = 0 endif ; VLnogen endm ;; APIEND ;--------------------------------------------------------------------------- ; ; _FlsFrame - Generate frame code ; _FlsFrame macro ife VLframe if VLATMfrmds mov ax,_DATA endif if VLsavebx push bx endif if VLsavees push es endif if VLATMframe inc bp push bp mov bp,sp push ds ; push ds and pop it off. pop ds ; (we need to pop DS rather than ; something fast like pop AX because ; ATM doesn't preserve DS itself) else push bp mov bp,sp endif push offset VLnameerror ; push address of error handler VLframe = 1 endif endm ;--------------------------------------------------------------------------- ; _ChkName ; ; Ensure name was specified _ChkName macro name ifb _print ,%VLiname endif endm ;--------------------------------------------------------------------------- ; _ParmOpts ; ; Parse parameter option flags ; _ParmOpts macro opts VLnogenparm = VLnogenpall irp opt, ifidni , ifndef DEBUG VLnogenparm = 1 endif ifidni , VLnogenparm = 1 endif endif endm endm ;--------------------------------------------------------------------------- ; _DefParm name,cb,opts ; ; Take care of default parameter stuff, such as defining argument. ; _DP_Add macro old,new ifb VLplist equ else VLplist equ endif endm _DefParm macro name,cb,opts _ChkName _ParmOpts if VLcargs concat _P_&name,<[bp]+6+>,%(VLcbparms+VLsavees+VLsavebx) VLcbparms=VLcbparms+(cb) else VLcbparms=VLcbparms+(cb) concat _P_&name,<[bp]+6->,%VLcbparms,<+>,%(VLnamecbparms+VLsavees+VLsavebx) endif _DP_Add %VLplist,<_P_&name> VLgen = 1 if VLnogenparm or VLnogen VLgen = 0 endif endm ;---------------------------------------------------------------------------- ; ; _GenParm name, cb, opts ; _GenParm macro name,cb,opts _DefParm ,, if VLgen _FlsFrame endif endm lcall2 macro op,label,seg op label&seg endm lcall macro label lcall2 ,