Code: Select all
!;\INCLUDE\MACRO\STRUCT.INC
!; Macroinstructions for defining data structures
!
!macro struct name
! { virtual at 0
! define @struct
! field@struct equ name
! match child parent, name \{ restore field@struct
! field@struct equ child,fields@\#parent \}
! sub@struct equ
! struc db [val] \{ \common define field@struct .,db,<val> \}
! struc dw [val] \{ \common define field@struct .,dw,<val> \}
! struc du [val] \{ \common define field@struct .,du,<val> \}
! struc dd [val] \{ \common define field@struct .,dd,<val> \}
! struc dp [val] \{ \common define field@struct .,dp,<val> \}
! struc dq [val] \{ \common define field@struct .,dq,<val> \}
! struc dt [val] \{ \common define field@struct .,dt,<val> \}
! struc rb count \{ define field@struct .,db,count dup (?) \}
! struc rw count \{ define field@struct .,dw,count dup (?) \}
! struc rd count \{ define field@struct .,dd,count dup (?) \}
! struc rp count \{ define field@struct .,dp,count dup (?) \}
! struc rq count \{ define field@struct .,dq,count dup (?) \}
! struc rt count \{ define field@struct .,dt,count dup (?) \}
! macro db [val] \{ \common \local anonymous
! define field@struct anonymous,db,<val> \}
! macro dw [val] \{ \common \local anonymous
! define field@struct anonymous,dw,<val> \}
! macro du [val] \{ \common \local anonymous
! define field@struct anonymous,du,<val> \}
! macro dd [val] \{ \common \local anonymous
! define field@struct anonymous,dd,<val> \}
! macro dp [val] \{ \common \local anonymous
! define field@struct anonymous,dp,<val> \}
! macro dq [val] \{ \common \local anonymous
! define field@struct anonymous,dq,<val> \}
! macro dt [val] \{ \common \local anonymous
! define field@struct anonymous,dt,<val> \}
! macro rb count \{ \local anonymous
! define field@struct anonymous,db,count dup (?) \}
! macro rw count \{ \local anonymous
! define field@struct anonymous,dw,count dup (?) \}
! macro rd count \{ \local anonymous
! define field@struct anonymous,dd,count dup (?) \}
! macro rp count \{ \local anonymous
! define field@struct anonymous,dp,count dup (?) \}
! macro rq count \{ \local anonymous
! define field@struct anonymous,dq,count dup (?) \}
! macro rt count \{ \local anonymous
! define field@struct anonymous,dt,count dup (?) \}
! macro union \{ field@struct equ ,union,<
! sub@struct equ union \}
! macro struct \{ field@struct equ ,substruct,<
! sub@struct equ substruct \} }
!
!macro ends
! { match , sub@struct \{ restruc db,dw,du,dd,dp,dq,dt
! restruc rb,rw,rd,rp,rq,rt
! purge db,dw,du,dd,dp,dq,dt
! purge rb,rw,rd,rp,rq,rt
! purge union,struct
! irpv fields,field@struct \\{ restore field@struct
! \\common define fields@struct fields \\}
! match name tail,fields@struct, \\{ if $
! display 'Error: definition of ',\\`name,' contains illegal instructions.',0Dh,0Ah
! err
! end if \\}
! match name=,fields,fields@struct \\{ restore @struct
! make@struct name,fields
! define fields@\\#name fields \\}
! end virtual \}
! match any, sub@struct \{ tmp@struct equ field@struct
! restore field@struct
! field@struct equ tmp@struct> \}
! restore sub@struct }
!
!macro make@struct name,[field,type,def]
! { common
! local define
! define equ name
! forward
! local sub
! match , field \{ make@substruct type,name,sub def
! define equ define,.,sub, \}
! match any, field \{ define equ define,.#field,type,<def> \}
! common
! match fields, define \{ define@struct fields \} }
!
!macro define@struct name,[field,type,def]
! { common
! virtual
! db `name
! load initial@struct byte from 0
! if initial@struct = '.'
! display 'Error: name of structure should not begin with a dot.',0Dh,0Ah
! err
! end if
! end virtual
! local list
! list equ
! forward
! if ~ field eq .
! name#field type def
! sizeof.#name#field = $ - name#field
! else
! label name#.#type
! rb sizeof.#type
! end if
! local value
! match any, list \{ list equ list, \}
! list equ list <value>
! common
! sizeof.#name = $
! restruc name
! match values, list \{
! struc name value \\{ \\local \\..base
! match , @struct \\\{ define field@struct .,name,<values> \\\}
! match no, @struct \\\{ label \\..base
! forward
! match , value \\\\{ field type def \\\\}
! match any, value \\\\{ field type value
! if ~ field eq .
! rb sizeof.#name#field - ($-field)
! end if \\\\}
! common label . at \\..base \\\}
! \\}
! macro name value \\{
! match , @struct \\\{ \\\local anonymous
! define field@struct anonymous,name,<values> \\\}
! match no, @struct \\\{
! forward
! match , value \\\\{ type def \\\\}
! match any, value \\\\{ \\\\local ..field
! ..field = $
! type value
! if ~ field eq .
! rb sizeof.#name#field - ($-..field)
! end if \\\\}
! common \\\} \\} \} }
!
!macro enable@substruct
! { macro make@substruct substruct,parent,name,[field,type,def]
! \{ \common
! \local define
! define equ parent,name
! \forward
! \local sub
! match , field \\{ match any, type \\\{ enable@substruct
! make@substruct type,parent,sub def
! purge make@substruct
! define equ define,.,sub, \\\} \\}
! match any, field \\{ define equ define,.\#field,type,<def> \\}
! \common
! match fields, define \\{ define@\#substruct fields \\} \} }
!
!enable@substruct
!
!macro define@union parent,name,[field,type,def]
! { common
! virtual at parent#.#name
! forward
! if ~ field eq .
! virtual at parent#.#name
! parent#field type def
! sizeof.#parent#field = $ - parent#field
! end virtual
! if sizeof.#parent#field > $ - parent#.#name
! rb sizeof.#parent#field - ($ - parent#.#name)
! end if
! else
! virtual at parent#.#name
! label parent#.#type
! type def
! end virtual
! label name#.#type at parent#.#name
! if sizeof.#type > $ - parent#.#name
! rb sizeof.#type - ($ - parent#.#name)
! end if
! end if
! common
! sizeof.#name = $ - parent#.#name
! end virtual
! struc name [value] \{ \common
! label .\#name
! last@union equ
! forward
! match any, last@union \\{ virtual at .\#name
! field type def
! end virtual \\}
! match , last@union \\{ match , value \\\{ field type def \\\}
! match any, value \\\{ field type value \\\} \\}
! last@union equ field
! common rb sizeof.#name - ($ - .\#name) \}
! macro name [value] \{ \common \local ..anonymous
! ..anonymous name value \} }
!
!macro define@substruct parent,name,[field,type,def]
! { common
! virtual at parent#.#name
! forward
! local value
! if ~ field eq .
! parent#field type def
! sizeof.#parent#field = $ - parent#field
! else
! label parent#.#type
! rb sizeof.#type
! end if
! common
! sizeof.#name = $ - parent#.#name
! end virtual
! struc name value \{
! label .\#name
! forward
! match , value \\{ field type def \\}
! match any, value \\{ field type value
! if ~ field eq .
! rb sizeof.#parent#field - ($-field)
! end if \\}
! common \}
! macro name value \{ \local ..anonymous
! ..anonymous name \} }
!
!;\INCLUDE\MACRO\IF.INC
!; Macroinstructions for HLL-style conditional operations
!
!macro .if [arg]
!{
! common
! __IF equ
! local ..endif
! __ENDIF equ ..endif
! local ..else
! __ELSE equ ..else
! JNCOND __ELSE,arg
!}
!
!macro .else
!{
! jmp __ENDIF
! __ELSE:
! restore __IF
! __IF equ ,
!}
!
!macro .elseif [arg]
!{
! common
! jmp __ENDIF
! __ELSE:
! restore __ELSE
! local ..else
! __ELSE equ ..else
! JNCOND __ELSE,arg
!}
!
!macro .endif
!{
! if __IF eq
! __ELSE:
! end if
! __ENDIF:
! restore __ELSE
! restore __ENDIF
! restore __IF
!}
!
!macro .while [arg]
!{
! common
! local ..while
! __WHILE equ ..while
! local ..endw
! __ENDW equ ..endw
! __WHILE:
! JNCOND __ENDW,arg
!}
!
!macro .endw
!{
! jmp __WHILE
! __ENDW:
! restore __ENDW
! restore __WHILE
!}
!
!macro .repeat
!{
! local ..repeat
! __REPEAT equ ..repeat
! __REPEAT:
!}
!
!macro .until [arg]
!{
! common
! JNCOND __REPEAT,arg
! restore __REPEAT
!}
!
!jnne equ je
!jnna equ ja
!jnnb equ jb
!jnng equ jg
!jnnl equ jl
!jnnae equ jae
!jnnbe equ jbe
!jnnge equ jge
!jnnle equ jle
!
!macro JNCOND label,v1,c,v2
!{
! match any,c
! \{
! cmp v1,v2
! jn\#c label
! \}
! match ,c
! \{
! PARSECOND parsed@cond,v1
! match cond,parsed@cond \\{ JNCONDEXPR label,cond \\}
! \}
!}
!
!gt equ >
!lt equ <
!
!macro PARSECOND parsed,cond
!{
! define parsed
! define neg@cond
! define status@cond
! define nest@cond
! irps symb,cond
! \{
! define symb@cond symb
! match >,symb
! \\{
! define symb@cond gt
! \\}
! match <,symb
! \\{
! define symb@cond lt
! \\}
! current@cond equ status@cond
! match ,current@cond
! \\{
! match ~,symb
! \\\{
! neg@cond equ neg@cond ~
! match ~~,neg@cond
! \\\\{
! define neg@cond
! \\\\}
! define symb@cond
! \\\}
! match (,symb
! \\\{
! parsed equ parsed neg@cond,<
! define nest@cond +
! define symb@cond
! define neg@cond
! \\\}
! match any,symb@cond
! \\\{
! parsed equ parsed neg@cond,symb@cond
! define status@cond +
! \\\}
! \\}
! match status,current@cond
! \\{
! match &,symb
! \\\{
! parsed equ parsed,&,
! define status@cond
! define symb@cond
! define neg@cond
! \\\}
! match |,symb
! \\\{
! parsed equ parsed,|,
! define status@cond
! define symb@cond
! define neg@cond
! \\\}
! match (,symb
! \\\{
! define nest@cond (
! \\\}
! match ),symb
! \\\{
! match +,nest@cond
! \\\\{
! parsed equ parsed>
! define symb@cond
! \\\\}
! restore nest@cond
! \\\}
! match any,symb@cond
! \\\{
! parsed equ parsed symb@cond
! \\\}
! \\}
! \}
!}
!
!macro define_JNCONDEXPR
!{
! macro JNCONDEXPR elabel,[mod,cond,op]
! \{
! \common
! \local ..t,..f
! define t@cond ..t
! define f@cond ..f
! \forward
! match ,op
! \\{
! match ,mod \\\{ JNCONDEL elabel,<cond> \\\}
! match ~,mod \\\{ JCONDEL elabel,<cond> \\\}
! \\}
! match &:flabel:tlabel, op:f@cond:t@cond
! \\{
! match ,mod \\\{ JNCONDEL flabel,<cond> \\\}
! match ~,mod \\\{ JCONDEL flabel,<cond> \\\}
! tlabel:
! \\local ..tnew
! restore t@cond
! define t@cond ..tnew
! \\}
! match |:flabel:tlabel, op:f@cond:t@cond
! \\{
! match ,mod \\\{ JCONDEL tlabel,<cond> \\\}
! match ~,mod \\\{ JNCONDEL tlabel,<cond> \\\}
! flabel:
! \\local ..fnew
! restore f@cond
! define f@cond ..fnew
! \\}
! \common
! label f@cond at elabel
! t@cond:
! restore t@cond
! restore f@cond
! \}
!}
!
!macro define_JCONDEXPR
!{
! macro JCONDEXPR elabel,[mod,cond,op]
! \{
! \common
! \local ..t,..f
! define t@cond ..t
! define f@cond ..f
! \forward
! match ,op
! \\{
! match ,mod \\\{ JCONDEL elabel,<cond> \\\}
! match ~,mod \\\{ JNCONDEL elabel,<cond> \\\}
! \\}
! match |:flabel:tlabel, op:f@cond:t@cond
! \\{
! match ,mod \\\{ JCONDEL flabel,<cond> \\\}
! match ~,mod \\\{ JNCONDEL flabel,<cond> \\\}
! tlabel:
! \\local ..tnew
! restore t@cond
! define t@cond ..tnew
! \\}
! match &:flabel:tlabel, op:f@cond:t@cond
! \\{
! match ,mod \\\{ JNCONDEL tlabel,<cond> \\\}
! match ~,mod \\\{ JCONDEL tlabel,<cond> \\\}
! flabel:
! \\local ..fnew
! restore f@cond
! define f@cond ..fnew
! \\}
! \common
! label f@cond at elabel
! t@cond:
! restore t@cond
! restore f@cond
! \}
!}
!
!macro define_JNCONDEL
!{
! macro JNCONDEL label,cond
! \{
! \local COND
! match car=,cdr,:cond
! \\{
! define_JNCONDEXPR
! define_JCONDEXPR
! define_JCONDEL
! define_JNCONDEL
! JNCONDEXPR label,cond
! purge JNCONDEXPR,JCONDEXPR,JCONDEL,JNCONDEL
! define COND
! \\}
! match c,cond ; replace gt and lt
! \\{
! match =COND =signed v1>==v2, COND c
! \\\{
! cmp v1,v2
! jl label
! define COND
! \\\}
! match =COND =signed v1<==v2, COND c
! \\\{
! cmp v1,v2
! jg label
! define COND
! \\\}
! match =COND v1>==v2, COND c
! \\\{
! cmp v1,v2
! jb label
! define COND
! \\\}
! match =COND v1<==v2, COND c
! \\\{
! cmp v1,v2
! ja label
! define COND
! \\\}
! match =COND v1==v2, COND c
! \\\{
! cmp v1,v2
! jne label
! define COND
! \\\}
! match =COND v1<>v2, COND c
! \\\{
! cmp v1,v2
! je label
! define COND
! \\\}
! match =COND =signed v1>v2, COND c
! \\\{
! cmp v1,v2
! jle label
! define COND
! \\\}
! match =COND =signed v1<v2, COND c
! \\\{
! cmp v1,v2
! jge label
! define COND
! \\\}
! match =COND v1>v2, COND c
! \\\{
! cmp v1,v2
! jbe label
! define COND
! \\\}
! match =COND v1<v2, COND c
! \\\{
! cmp v1,v2
! jae label
! define COND
! \\\}
! match =COND =ZERO?, COND c
! \\\{
! jnz label
! define COND
! \\\}
! match =COND =CARRY?, COND c
! \\\{
! jnc label
! define COND
! \\\}
! match =COND =OVERFLOW?, COND c
! \\\{
! jno label
! define COND
! \\\}
! match =COND =SIGN?, COND c
! \\\{
! jns label
! define COND
! \\\}
! match =COND =PARITY?, COND c
! \\\{
! jnp label
! define COND
! \\\}
! match =COND v, COND c
! \\\{
! if v eqtype 0
! if ~ v
! jmp label
! end if
! else if v eqtype eax
! test v,v
! jz label
! else
! cmp v,0
! je label
! end if
! \\\}
! \\}
! \}
!}
!
!macro define_JCONDEL
!{
! macro JCONDEL label,cond
! \{
! \local COND
! match car=,cdr,:cond
! \\{
! define_JNCONDEXPR
! define_JCONDEXPR
! define_JCONDEL
! define_JNCONDEL
! JCONDEXPR label,cond
! purge JNCONDEXPR,JCONDEXPR,JCONDEL,JNCONDEL
! define COND
! \\}
! match c,cond ; replace gt and lt
! \\{
! match =COND =signed v1>==v2, COND c
! \\\{
! cmp v1,v2
! jge label
! define COND
! \\\}
! match =COND =signed v1<==v2, COND c
! \\\{
! cmp v1,v2
! jle label
! define COND
! \\\}
! match =COND v1>==v2, COND c
! \\\{
! cmp v1,v2
! jae label
! define COND
! \\\}
! match =COND v1<==v2, COND c
! \\\{
! cmp v1,v2
! jbe label
! define COND
! \\\}
! match =COND v1==v2, COND c
! \\\{
! cmp v1,v2
! je label
! define COND
! \\\}
! match =COND v1<>v2, COND c
! \\\{
! cmp v1,v2
! jne label
! define COND
! \\\}
! match =COND =signed v1>v2, COND c
! \\\{
! cmp v1,v2
! jg label
! define COND
! \\\}
! match =COND =signed v1<v2, COND c
! \\\{
! cmp v1,v2
! jl label
! define COND
! \\\}
! match =COND v1>v2, COND c
! \\\{
! cmp v1,v2
! ja label
! define COND
! \\\}
! match =COND v1<v2, COND c
! \\\{
! cmp v1,v2
! jb label
! define COND
! \\\}
! match =COND =ZERO?, COND c
! \\\{
! jz label
! define COND
! \\\}
! match =COND =CARRY?, COND c
! \\\{
! jc label
! define COND
! \\\}
! match =COND =OVERFLOW?, COND c
! \\\{
! jo label
! define COND
! \\\}
! match =COND =SIGN?, COND c
! \\\{
! js label
! define COND
! \\\}
! match =COND =PARITY?, COND c
! \\\{
! jp label
! define COND
! \\\}
! match =COND v, COND c
! \\\{
! if v eqtype 0
! if v
! jmp label
! end if
! else if v eqtype eax
! test v,v
! jnz label
! else
! cmp v,0
! jne label
! end if
! \\\}
! \\}
! \}
!}
!
!define_JNCONDEXPR
!define_JCONDEXPR
!define_JNCONDEL
!define_JCONDEL
!
!;\INCLUDE\MACRO\PROC32.INC
!; Macroinstructions for defining and calling procedures
!
!macro stdcall proc,[arg] ; directly call STDCALL procedure
! { common
! if ~ arg eq
! reverse
! pushd arg
! common
! end if
! call proc }
!
!macro invoke proc,[arg] ; indirectly call STDCALL procedure
! { common
! if ~ arg eq
! reverse
! pushd arg
! common
! end if
! call [proc] }
!
!macro ccall proc,[arg] ; directly call CDECL procedure
! { common
! size@ccall = 0
! if ~ arg eq
! reverse
! pushd arg
! size@ccall = size@ccall+4
! common
! end if
! call proc
! if size@ccall
! add esp,size@ccall
! end if }
!
!macro cinvoke proc,[arg] ; indirectly call CDECL procedure
! { common
! size@ccall = 0
! if ~ arg eq
! reverse
! pushd arg
! size@ccall = size@ccall+4
! common
! end if
! call [proc]
! if size@ccall
! add esp,size@ccall
! end if }
!
!macro proc [args] ; define procedure
! { common
! match name params, args>
! \{ define@proc name,<params \} }
!
!prologue@proc equ prologuedef
!
!macro prologuedef procname,flag,parmbytes,localbytes,reglist
! { local loc
! loc = (localbytes+3) and (not 3)
! parmbase@proc equ ebp+8
! localbase@proc equ ebp-loc
! if parmbytes | localbytes
! push ebp
! mov ebp,esp
! if localbytes
! sub esp,loc
! end if
! end if
! irps reg, reglist \{ push reg \} }
!
!epilogue@proc equ epiloguedef
!
!macro epiloguedef procname,flag,parmbytes,localbytes,reglist
! { irps reg, reglist \{ reverse pop reg \}
! if parmbytes | localbytes
! leave
! end if
! if flag and 10000b
! retn
! else
! retn parmbytes
! end if }
!
!close@proc equ
!
!macro define@proc name,statement
! { local params,flag,regs,parmbytes,localbytes,current
! if used name
! name:
! match =stdcall args, statement \{ params equ args
! flag = 11b \}
! match =stdcall, statement \{ params equ
! flag = 11b \}
! match =c args, statement \{ params equ args
! flag = 10001b \}
! match =c, statement \{ params equ
! flag = 10001b \}
! match =params, params \{ params equ statement
! flag = 0 \}
! match =uses reglist=,args, params \{ regs equ reglist
! params equ args \}
! match =regs =uses reglist, regs params \{ regs equ reglist
! params equ \}
! match =regs, regs \{ regs equ \}
! match prologue:reglist, prologue@proc:<regs> \{ prologue name,flag,parmbytes,localbytes,reglist \}
! virtual at parmbase@proc
! match =,args, params \{ defargs@proc args \}
! match =args@proc args, args@proc params \{ defargs@proc args \}
! parmbytes = $-(parmbase@proc)
! end virtual
! name # % = parmbytes/4
! all@vars equ
! current = 0
! macro locals
! \{ virtual at localbase@proc+current
! macro label def \\{ match . type,def> \\\{ deflocal@proc .,label,<type \\\} \\}
! struc db [val] \\{ \common deflocal@proc .,db,val \\}
! struc du [val] \\{ \common deflocal@proc .,du,val \\}
! struc dw [val] \\{ \common deflocal@proc .,dw,val \\}
! struc dp [val] \\{ \common deflocal@proc .,dp,val \\}
! struc dd [val] \\{ \common deflocal@proc .,dd,val \\}
! struc dt [val] \\{ \common deflocal@proc .,dt,val \\}
! struc dq [val] \\{ \common deflocal@proc .,dq,val \\}
! struc rb cnt \\{ deflocal@proc .,rb cnt, \\}
! struc rw cnt \\{ deflocal@proc .,rw cnt, \\}
! struc rp cnt \\{ deflocal@proc .,rp cnt, \\}
! struc rd cnt \\{ deflocal@proc .,rd cnt, \\}
! struc rt cnt \\{ deflocal@proc .,rt cnt, \\}
! struc rq cnt \\{ deflocal@proc .,rq cnt, \\} \}
! macro endl
! \{ purge label
! restruc db,du,dw,dp,dd,dt,dq
! restruc rb,rw,rp,rd,rt,rq
! current = $-(localbase@proc)
! end virtual \}
! macro ret operand
! \{ match any, operand \\{ retn operand \\}
! match , operand \\{ match epilogue:reglist, epilogue@proc:<regs> \\\{ epilogue name,flag,parmbytes,localbytes,reglist \\\} \\} \}
! macro finish@proc
! \{ localbytes = current
! match close:reglist, close@proc:<regs> \\{ close name,flag,parmbytes,localbytes,reglist \\}
! end if \} }
!
!macro defargs@proc [arg]
! { common
! if ~ arg eq
! forward
! local ..arg,current@arg
! match argname:type, arg
! \{ current@arg equ argname
! label ..arg type
! argname equ ..arg
! if qqword eq type
! dd ?,?,?,?,?,?,?,?
! else if dqword eq type
! dd ?,?,?,?
! else if tbyte eq type
! dd ?,?,?
! else if qword eq type | pword eq type
! dd ?,?
! else
! dd ?
! end if \}
! match =current@arg,current@arg
! \{ current@arg equ arg
! arg equ ..arg
! ..arg dd ? \}
! common
! args@proc equ current@arg
! forward
! restore current@arg
! common
! end if }
!
!macro deflocal@proc name,def,[val] { name def val }
!
!macro deflocal@proc name,def,[val]
! { common
! match vars, all@vars \{ all@vars equ all@vars, \}
! all@vars equ all@vars name
! forward
! local ..var,..tmp
! ..var def val
! match =?, val \{ ..tmp equ \}
! match any =?, val \{ ..tmp equ \}
! match any (=?), val \{ ..tmp equ \}
! match =label, def \{ ..tmp equ \}
! match tmp : value, ..tmp : val
! \{ tmp: end virtual
! initlocal@proc ..var,def value
! virtual at tmp\}
! common
! match first rest, ..var, \{ name equ first \} }
!
!struc label type { label . type }
!
!macro initlocal@proc name,def
! { virtual at name
! def
! size@initlocal = $ - name
! end virtual
! position@initlocal = 0
! while size@initlocal > position@initlocal
! virtual at name
! def
! if size@initlocal - position@initlocal < 2
! current@initlocal = 1
! load byte@initlocal byte from name+position@initlocal
! else if size@initlocal - position@initlocal < 4
! current@initlocal = 2
! load word@initlocal word from name+position@initlocal
! else
! current@initlocal = 4
! load dword@initlocal dword from name+position@initlocal
! end if
! end virtual
! if current@initlocal = 1
! mov byte [name+position@initlocal],byte@initlocal
! else if current@initlocal = 2
! mov word [name+position@initlocal],word@initlocal
! else
! mov dword [name+position@initlocal],dword@initlocal
! end if
! position@initlocal = position@initlocal + current@initlocal
! end while }
!
!macro endp
! { purge ret,locals,endl
! finish@proc
! purge finish@proc
! restore regs@proc
! match all,args@proc \{ restore all \}
! restore args@proc
! match all,all@vars \{ restore all \} }
!
!macro local [var]
! { common
! locals
! forward done@local equ
! match varname[count]:vartype, var
! \{ match =BYTE, vartype \\{ varname rb count
! restore done@local \\}
! match =WORD, vartype \\{ varname rw count
! restore done@local \\}
! match =DWORD, vartype \\{ varname rd count
! restore done@local \\}
! match =PWORD, vartype \\{ varname rp count
! restore done@local \\}
! match =QWORD, vartype \\{ varname rq count
! restore done@local \\}
! match =TBYTE, vartype \\{ varname rt count
! restore done@local \\}
! match =DQWORD, vartype \\{ label varname dqword
! rq count*2
! restore done@local \\}
! match =QQWORD, vartype \\{ label varname qqword
! rq count*4
! restore done@local \\}
! match =XWORD, vartype \\{ label varname xword
! rq count*2
! restore done@local \\}
! match =YWORD, vartype \\{ label varname yword
! rq count*4
! restore done@local \\}
! match , done@local \\{ virtual
! varname vartype
! end virtual
! rb count*sizeof.\#vartype
! restore done@local \\} \}
! match :varname:vartype, done@local:var
! \{ match =BYTE, vartype \\{ varname db ?
! restore done@local \\}
! match =WORD, vartype \\{ varname dw ?
! restore done@local \\}
! match =DWORD, vartype \\{ varname dd ?
! restore done@local \\}
! match =PWORD, vartype \\{ varname dp ?
! restore done@local \\}
! match =QWORD, vartype \\{ varname dq ?
! restore done@local \\}
! match =TBYTE, vartype \\{ varname dt ?
! restore done@local \\}
! match =DQWORD, vartype \\{ label varname dqword
! dq ?,?
! restore done@local \\}
! match =QQWORD, vartype \\{ label varname qqword
! dq ?,?,?,?
! restore done@local \\}
! match =XWORD, vartype \\{ label varname xword
! dq ?,?
! restore done@local \\}
! match =YWORD, vartype \\{ label varname yword
! dq ?,?,?,?
! restore done@local \\}
! match , done@local \\{ varname vartype
! restore done@local \\} \}
! match ,done@local
! \{ var
! restore done@local \}
! common
! endl }