add flat assembler toolchain

This commit is contained in:
2024-11-24 23:13:28 -05:00
parent 99e8e4072b
commit dbfd94ea40
302 changed files with 145599 additions and 0 deletions

View File

@ -0,0 +1,53 @@
; Macroinstructions for interfacing the COM (Component Object Model) classes
macro cominvk object,proc,[arg]
{ common
if ~ arg eq
reverse
pushd arg
common
end if
assert defined object#.com.object ; must be a COM object
mov eax,[object]
push eax
mov eax,[eax]
call [eax+object#.#proc] }
macro comcall handle,interface,proc,[arg]
{ common
if ~ arg eq
reverse
pushd arg
common
end if
assert defined interface#.com.interface ; must be a COM interface
if handle eqtype eax | handle eqtype 0
push handle
local ..handle
label ..handle at handle
mov eax,[..handle]
else
mov eax,handle
push eax
mov eax,[eax]
end if
call [eax+interface#.#proc] }
macro interface name,[proc]
{ common
struc name \{
match , @struct \\{ define field@struct .,name, \\}
match no, @struct \\{ . dd ?
virtual at 0
forward
.#proc dd ?
common
.\#\\.com.object = name#.com.interface
end virtual \\} \}
virtual at 0
forward
name#.#proc dd ?
common
name#.com.interface = $ shr 2
end virtual }

View File

@ -0,0 +1,39 @@
; Macroinstructions for interfacing the COM (Component Object Model) classes
macro cominvk object,proc,[arg]
{ common
assert defined object#.com.object ; must be a COM object
macro call dummy
\{ mov rax,[rcx]
call [rax+object#.#proc] \}
fastcall ,[object],arg
purge call }
macro comcall handle,interface,proc,[arg]
{ common
assert defined interface#.com.interface ; must be a COM interface
macro call dummy
\{ mov rax,[rcx]
call [rax+interface#.#proc] \}
fastcall ,handle,arg
purge call }
macro interface name,[proc]
{ common
struc name \{
match , @struct \\{ define field@struct .,name, \\}
match no, @struct \\{ . dq ?
virtual at 0
forward
.#proc dq ?
common
.\#\\.com.object = name#.com.interface
end virtual \\} \}
virtual at 0
forward
name#.#proc dq ?
common
name#.com.interface = $ shr 3
end virtual }

View File

@ -0,0 +1,66 @@
; Macroinstruction for making export section
macro export dllname,[label,string]
{ common
local module,addresses,names,ordinal,count
count = 0
forward
count = count+1
common
dd 0,0,0,RVA module,1
dd count,count,RVA addresses,RVA names,RVA ordinal
addresses:
forward
dd RVA label
common
names:
forward
local name
dd RVA name
common
ordinal: count = 0
forward
dw count
count = count+1
common
module db dllname,0
forward
name db string,0
common
local x,y,z,str1,str2,v1,v2
x = count shr 1
while x > 0
y = x
while y < count
z = y
while z-x >= 0
load v1 dword from names+z*4
str1=($-RVA $)+v1
load v2 dword from names+(z-x)*4
str2=($-RVA $)+v2
while v1 > 0
load v1 from str1+%-1
load v2 from str2+%-1
if v1 <> v2
break
end if
end while
if v1<v2
load v1 dword from names+z*4
load v2 dword from names+(z-x)*4
store dword v1 at names+(z-x)*4
store dword v2 at names+z*4
load v1 word from ordinal+z*2
load v2 word from ordinal+(z-x)*2
store word v1 at ordinal+(z-x)*2
store word v2 at ordinal+z*2
else
break
end if
z = z-x
end while
y = y+1
end while
x = x shr 1
end while }

View File

@ -0,0 +1,507 @@
; 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

View File

@ -0,0 +1,68 @@
; Macroinstructions for making import section
macro library [name,string]
{ common
import.data:
forward
local _label
if defined name#.redundant
if ~ name#.redundant
dd RVA name#.lookup,0,0,RVA _label,RVA name#.address
end if
end if
name#.referred = 1
common
dd 0,0,0,0,0
forward
if defined name#.redundant
if ~ name#.redundant
_label db string,0
rb RVA $ and 1
end if
end if }
macro import name,[label,string]
{ common
rb (- rva $) and 3
if defined name#.referred
name#.lookup:
forward
if used label
if string eqtype ''
local _label
dd RVA _label
else
dd 80000000h + string
end if
end if
common
if $ > name#.lookup
name#.redundant = 0
dd 0
else
name#.redundant = 1
end if
name#.address:
forward
if used label
if string eqtype ''
label dd RVA _label
else
label dd 80000000h + string
end if
end if
common
if ~ name#.redundant
dd 0
end if
forward
if used label & string eqtype ''
_label dw 0
db string,0
rb RVA $ and 1
end if
common
end if }
macro api [name] {}

View File

@ -0,0 +1,68 @@
; Macroinstructions for making import section (64-bit)
macro library [name,string]
{ common
import.data:
forward
local _label
if defined name#.redundant
if ~ name#.redundant
dd RVA name#.lookup,0,0,RVA _label,RVA name#.address
end if
end if
name#.referred = 1
common
dd 0,0,0,0,0
forward
if defined name#.redundant
if ~ name#.redundant
_label db string,0
rb RVA $ and 1
end if
end if }
macro import name,[label,string]
{ common
rb (- rva $) and 7
if defined name#.referred
name#.lookup:
forward
if used label
if string eqtype ''
local _label
dq RVA _label
else
dq 8000000000000000h + string
end if
end if
common
if $ > name#.lookup
name#.redundant = 0
dq 0
else
name#.redundant = 1
end if
name#.address:
forward
if used label
if string eqtype ''
label dq RVA _label
else
label dq 8000000000000000h + string
end if
end if
common
if ~ name#.redundant
dq 0
end if
forward
if used label & string eqtype ''
_label dw 0
db string,0
rb RVA $ and 1
end if
common
end if }
macro api [name] {}

View File

@ -0,0 +1,66 @@
; Simulate MASM's syntax
struc struct
{ struct .
name@struct equ . }
struc ends
{ match =.,name@struct \{ ends \} }
struc proc [params]
{ common define@proc .,<params>
name@proc equ . }
struc endp
{ match =.,name@proc \{ endp \} }
macro option setting
{ match =prologue:macro, setting \{ prologue@proc equ macro \}
match =epilogue:macro, setting \{ epilogue@proc equ macro \} }
macro none procname,flag,parmbytes,localbytes,reglist { }
macro assume params
{
local expr
define expr params
match reg:struct, expr
\{
match assumed, reg\#@assumed \\{ irp name, assumed \\\{ restore name \\\} \\}
macro label . \\{ local def
define def .
match =reg =at label, def \\\{ define def \\\}
match name at,def \\\{ def@assumed reg,name,label at
define def \\\}
match name,def \\\{ def@assumed reg,.,: \\\} \\}
struc db [val] \\{ \common def@assumed reg,.,<db val> \\}
struc dw [val] \\{ \common def@assumed reg,.,<dw val> \\}
struc dp [val] \\{ \common def@assumed reg,.,<dp val> \\}
struc dd [val] \\{ \common def@assumed reg,.,<dd val> \\}
struc dt [val] \\{ \common def@assumed reg,.,<dt val> \\}
struc dq [val] \\{ \common def@assumed reg,.,<dq val> \\}
struc rb cnt \\{ def@assumed reg,.,rb cnt \\}
struc rw cnt \\{ def@assumed reg,.,rw cnt \\}
struc rp cnt \\{ def@assumed reg,.,rp cnt \\}
struc rd cnt \\{ def@assumed reg,.,rd cnt \\}
struc rt cnt \\{ def@assumed reg,.,rt cnt \\}
struc rq cnt \\{ def@assumed reg,.,rq cnt \\}
reg\#@assumed equ
virtual at reg
reg struct
end virtual
purge label
restruc db,dw,dp,dd,dt,dq
restruc rb,rw,rp,rd,rt,rq \} }
macro def@assumed reg,name,def
{ match vars, reg#@assumed \{ reg#@assumed equ reg#@assumed, \}
reg#@assumed equ reg#@assumed name
local ..label
name equ ..label
..label def }
struc label type { label . type }
struc none { label . }

View File

@ -0,0 +1,301 @@
; 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 }

View File

@ -0,0 +1,618 @@
; Macroinstructions for defining and calling procedures (x64 version)
macro invoke proc,[arg]
{ common fastcall [proc],arg }
macro fastcall proc,[arg]
{ common local stackspace,argscount,counter
if argscount < 4
stackspace = 4*8
else if argscount and 1
stackspace = (argscount+1)*8
else
stackspace = argscount*8
end if
counter = 0
if stackspace
if defined current@frame
if current@frame<stackspace
current@frame = stackspace
end if
else
if stackspace
sub rsp,stackspace
end if
end if
end if
forward
counter = counter + 1
define type@param
define definition@param arg
match =float value,definition@param
\{ define definition@param value
define type@param float \}
match =addr value,definition@param
\{ define definition@param value
define type@param addr \}
match any=,any,definition@param
\{ \local ..string,..continue
jmp ..continue
align sizeof.TCHAR
..string TCHAR definition@param,0
..continue:
define definition@param ..string
define type@param addr \}
match any,definition@param
\{ match \`any,any
\\{ \\local ..string,..continue
jmp ..continue
align sizeof.TCHAR
..string TCHAR definition@param,0
..continue:
define definition@param ..string
define type@param addr \\} \}
match param,definition@param
\{ local opcode,origin
size@param = 0
if param eqtype 0 | param eqtype 0f | type@param eq addr
size@param = 8
else if param eqtype byte 0 | param eqtype byte 0f
match prefix value,definition@param
\\{ if prefix eq qword
size@param = 8
else if prefix eq dword
size@param = 4
else if prefix eq word
size@param = 2
else if prefix eq byte
size@param = 1
end if \\}
else if ~ param in <xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7,xmm8,xmm9,xmm10,xmm11,xmm12,xmm13,xmm14,xmm15>
virtual
origin = $
inc param
load opcode byte from origin
if opcode = 67h | ( opcode > 40h & opcode < 48h )
load opcode byte from origin+1
end if
if opcode and 0F8h = 48h
size@param = 8
else if opcode = 66h
size@param = 2
else if opcode = 0FFh
size@param = 4
else
size@param = 1
end if
end virtual
end if
if counter = 1
if type@param eq float
if ~ param eq xmm0
if size@param = 4
if param eqtype byte 0 | param eqtype byte 0f
mov eax,param
movd xmm0,eax
else
movd xmm0,param
end if
else
if param eqtype 0 | param eqtype 0f | param eqtype byte 0 | param eqtype byte 0f
mov rax,param
movq xmm0,rax
else
movq xmm0,param
end if
end if
end if
if vararg@fastcall & ~ param eq rcx
movq rcx,xmm0
end if
else if type@param eq addr
if ~ param eq rcx
lea rcx,[param]
end if
else if size@param = 8
if ~ param eq rcx
mov rcx,param
end if
else if size@param = 4
if ~ param eq ecx
mov ecx,param
end if
else if size@param = 2
if ~ param eq cx
mov cx,param
end if
else if size@param = 1
if ~ param eq cl
mov cl,param
end if
end if
else if counter = 2
if type@param eq float
if ~ param eq xmm1
if size@param = 4
if param eqtype byte 0 | param eqtype byte 0f
mov eax,param
movd xmm1,eax
else
movd xmm1,param
end if
else
if param eqtype 0 | param eqtype 0f | param eqtype byte 0 | param eqtype byte 0f
mov rax,param
movq xmm1,rax
else
movq xmm1,param
end if
end if
end if
if vararg@fastcall & ~ param eq rdx
movq rdx,xmm1
end if
else if type@param eq addr
if ~ param eq rdx
lea rdx,[param]
end if
else if size@param = 8
if ~ param eq rdx
mov rdx,param
end if
else if size@param = 4
if ~ param eq edx
mov edx,param
end if
else if size@param = 2
if ~ param eq dx
mov dx,param
end if
else if size@param = 1
if ~ param eq dl
mov dl,param
end if
end if
else if counter = 3
if type@param eq float
if ~ param eq xmm2
if size@param = 4
if param eqtype byte 0 | param eqtype byte 0f
mov eax,param
movd xmm2,eax
else
movd xmm2,param
end if
else
if param eqtype 0 | param eqtype 0f | param eqtype byte 0 | param eqtype byte 0f
mov rax,param
movq xmm2,rax
else
movq xmm2,param
end if
end if
end if
if vararg@fastcall & ~ param eq r8
movq r8,xmm2
end if
else if type@param eq addr
if ~ param eq r8
lea r8,[param]
end if
else if size@param = 8
if ~ param eq r8
mov r8,param
end if
else if size@param = 4
if ~ param eq r8d
mov r8d,param
end if
else if size@param = 2
if ~ param eq r8w
mov r8w,param
end if
else if size@param = 1
if ~ param eq r8b
mov r8b,param
end if
end if
else if counter = 4
if type@param eq float
if ~ param eq xmm3
if size@param = 4
if param eqtype byte 0 | param eqtype byte 0f
mov eax,param
movd xmm3,eax
else
movd xmm3,param
end if
else
if param eqtype 0 | param eqtype 0f | param eqtype byte 0 | param eqtype byte 0f
mov rax,param
movq xmm3,rax
else
movq xmm3,param
end if
end if
end if
if vararg@fastcall & ~ param eq r9
movq r9,xmm3
end if
else if type@param eq addr
if ~ param eq r9
lea r9,[param]
end if
else if size@param = 8
if ~ param eq r9
mov r9,param
end if
else if size@param = 4
if ~ param eq r9d
mov r9d,param
end if
else if size@param = 2
if ~ param eq r9w
mov r9w,param
end if
else if size@param = 1
if ~ param eq r9b
mov r9b,param
end if
end if
else
if type@param eq addr
lea rax,[param]
mov [rsp+(counter-1)*8],rax
else if param eqtype [0] | param eqtype byte [0]
if size@param = 8
mov rax,param
mov [rsp+(counter-1)*8],rax
else if size@param = 4
mov eax,param
mov [rsp+(counter-1)*8],eax
else if size@param = 2
mov ax,param
mov [rsp+(counter-1)*8],ax
else
mov al,param
mov [rsp+(counter-1)*8],al
end if
else if size@param = 8
virtual
origin = $
mov rax,param
load opcode byte from origin+1
end virtual
if opcode = 0B8h
mov rax,param
mov [rsp+(counter-1)*8],rax
else
mov qword [rsp+(counter-1)*8],param
end if
else if param in <xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7,xmm8,xmm9,xmm10,xmm11,xmm12,xmm13,xmm14,xmm15>
movq [rsp+(counter-1)*8],param
else
mov [rsp+(counter-1)*8],param
end if
end if \}
common
argscount = counter
call proc
if stackspace & ~defined current@frame
add rsp,stackspace
end if }
macro proc [args]
{ common
match name params, args>
\{ define@proc name,<params \} }
prologue@proc equ prologuedef
macro prologuedef procname,flag,parmbytes,localbytes,reglist
{ local loc,fill,counter
loc = (localbytes+15) and (not 15)
parmbase@proc equ rbp+16
localbase@proc equ rbp-loc
push rbp
mov rbp,rsp
if loc+fill
sub rsp,loc+fill
end if
counter = 0
irps reg, reglist \{ push reg
counter = counter+1 \}
fill = 8*(counter and 1) }
epilogue@proc equ epiloguedef
macro epiloguedef procname,flag,parmbytes,localbytes,reglist
{ irps reg, reglist \{ reverse pop reg \}
leave
retn }
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 = 10000b \}
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/8
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
dq ?,?,?,?
else if dqword eq type
dq ?,?
else if tbyte eq type
dq ?,?
else
dq ?
end if \}
match =current@arg,current@arg
\{ current@arg equ arg
arg equ ..arg
..arg dq ? \}
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 if size@initlocal - position@initlocal < 8
current@initlocal = 4
load dword@initlocal dword from name+position@initlocal
else
load qword@initlocal qword from name+position@initlocal
if ( qword@initlocal > 0 & qword@initlocal < 80000000h ) | ( qword@initlocal < 0 & qword@initlocal >= -80000000h )
current@initlocal = 8
else
current@initlocal = 4
dword@initlocal = qword@initlocal and 0FFFFFFFFh
end if
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 if current@initlocal = 4
mov dword [name+position@initlocal],dword@initlocal
else
mov qword [name+position@initlocal],qword@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 }
macro frame
{ local size,current
if size
sub rsp,size
end if
current = 0
current@frame equ current
size@frame equ size }
macro endf
{ size@frame = current@frame
if size@frame
add rsp,size@frame
end if
restore size@frame,current@frame }
macro static_rsp_prologue procname,flag,parmbytes,localbytes,reglist
{ local counter,loc,frame,current
counter = 0
irps reg, reglist \{ push reg
counter = counter+1 \}
loc = (localbytes+7) and (not 7)
if frame & (counter+loc shr 3+1) and 1
loc = loc + 8
end if
framebytes@proc equ frame+loc
if framebytes@proc
sub rsp,framebytes@proc
end if
localbase@proc equ rsp+frame
regsbase@proc equ rsp+frame+loc
parmbase@proc equ rsp+frame+loc+counter*8+8
current = 0
current@frame equ current
size@frame equ frame }
macro static_rsp_epilogue procname,flag,parmbytes,localbytes,reglist
{ if framebytes@proc
add rsp,framebytes@proc
end if
irps reg, reglist \{ reverse pop reg \}
retn }
macro static_rsp_close procname,flag,parmbytes,localbytes,reglist
{ size@frame = current@frame
restore size@frame,current@frame }
stdcall fix fastcall
macro cinvoke proc,[arg]
{ common ccall [proc],arg }
macro ccall proc,[arg]
{ common vararg@fastcall = 1
fastcall proc,arg
vararg@fastcall = 0 }
vararg@fastcall = 0

View File

@ -0,0 +1,334 @@
; Macroinstructions for making resource section
macro directory [type,label]
{ common
local max,count
count = 0
max = 0
forward
count = count + 1
if type > max
max = type
end if
common
root@resource dd 0,%t,0,count shl 16
repeat max
forward
if % = type
dd type,80000000h+label-root@resource
end if
common
end repeat }
macro resource dir,[id,lang,label]
{ common
dir:
local min,max,count,current
forward
min = id
max = id
common
count = 0
forward
count = count + 1
if id < min
min = id
else if id > max
max = id
end if
common
dd 0,%t,0,count shl 16
repeat max-min+1
current = $
forward
if min+%-1 = id
if current = $
dd id,80000000h+label#.directory-root@resource
end if
end if
common
end repeat
repeat max-min+1
current = $
forward
if min+%-1 = id
if current = $
label#.directory dd 0,%t,0,10000h,lang,label-root@resource
count = 1
else
dd lang,label-root@resource
count = count + 1
end if
end if
label#.resid = id
common
local x,y,z,v1,v2
if count > 1
store word count at current+0Eh
x = count shr 1
while x > 0
y = x
while y < count
z = y
while z-x >= 0
load v1 dword from current+10h+z*8
load v2 dword from current+10h+(z-x)*8
if v1<v2
store dword v1 at current+10h+(z-x)*8
store dword v2 at current+10h+z*8
load v1 dword from current+10h+z*8+4
load v2 dword from current+10h+(z-x)*8+4
store dword v1 at current+10h+(z-x)*8+4
store dword v2 at current+10h+z*8+4
else
break
end if
z = z-x
end while
y = y+1
end while
x = x shr 1
end while
end if
end repeat }
macro bitmap label,bitmap_file
{ local data,size
label dd RVA data,size,0,0
data file bitmap_file:0Eh
size = $ - data
align 4 }
macro icon group,[label,icon_file]
{ common local count
count = 0
forward local data,size,position
label dd RVA data,size,0,0
virtual at 0
file icon_file:6,16
load size dword from 8
load position dword from 12
end virtual
data file icon_file:position,size
count = count+1
common local header
align 4
group dd RVA header,6+count*14,0,0
header dw 0,1,count
forward
file icon_file:6,12
dw label#.resid
common
align 4 }
macro cursor group,[label,cursor_file]
{ common local count
count = 0
forward local data,width,height,size,position
label dd RVA data,size+4,0,0
virtual at 0
file cursor_file:6,16
load width byte from 0
load height byte from 1
load size dword from 8
load position dword from 12
end virtual
data file cursor_file:10,4
file cursor_file:position,size
count = count+1
common local header
align 4
group dd RVA header,6+count*14,0,0
header dw 0,2,count
forward
dw width,height,1,0
dd size+4
dw label#.resid
common
align 4 }
macro menu label
{ local data,size
label dd RVA data,size,0,0
data dw 1,4,0,0
menu_size equ size = $ - data
menu_level = 1 }
macro menuitem string,id,resinfo,status,type
{ dd MFT_STRING or type+0,status+0,id
dw resinfo+0
du string,0
align 4
if ~ resinfo eq
if resinfo and MFR_END
menu_level = menu_level - 1
end if
if resinfo and MFR_POPUP
menu_level = menu_level + 1
dd 0
end if
end if
if menu_level = 0
menu_size
end if }
macro menuseparator resinfo
{ dd MFT_SEPARATOR,0,0
dw resinfo+0,0
if ~ resinfo eq
if resinfo and MFR_END
menu_level = menu_level - 1
end if
end if
if menu_level = 0
menu_size
end if }
macro dialog label,title,x,y,cx,cy,style,exstyle,menu,fontname,fontsize
{ local data,size,items
label dd RVA data,size,0,0
data dd style or DS_SETFONT,exstyle +0
dw items,x,y,cx,cy
if menu+0 <> 0
dw 0FFFFh
end if
du menu+0,0,title,0
if fontname eq
du 8,'MS Sans Serif',0
else
du fontsize+0,fontname,0
end if
align 4
dialog_size equ size = $ - data
dialog_items equ items = dialog_items_counter
dialog_items_counter = 0 }
macro dialogitem class,title,id,x,y,cx,cy,style,exstyle
{ dd style or WS_CHILD,exstyle +0
dw x,y,cx,cy,id
if class eq 'BUTTON'
dw 0FFFFh,80h
else if class eq 'EDIT'
dw 0FFFFh,81h
else if class eq 'STATIC'
dw 0FFFFh,82h
else if class eq 'LISTBOX'
dw 0FFFFh,83h
else if class eq 'SCROLLBAR'
dw 0FFFFh,84h
else if class eq 'COMBOBOX'
dw 0FFFFh,85h
else
du class,0
end if
if title eqtype 0
dw 0FFFFh,title
else
du title,0
end if
dw 0
align 4
dialog_items_counter = dialog_items_counter + 1 }
macro enddialog
{ dialog_items
dialog_size }
macro accelerator label,[fvirt,key,cmd]
{ common
local data,size
label dd RVA data,size,0,0
data:
accel_count = 0
forward
accel_count = accel_count + 1
common
size = accel_count * 8
forward
accel_count = accel_count - 1
if accel_count = 0
dw fvirt or 80h,key
else
dw fvirt,key
end if
dd cmd }
macro versioninfo label,fileos,filetype,filesubtype,lang,cp,[name,value]
{ common
local data,size,vivalue,visize
label dd RVA data,size,0,0
data dw size,visize,0
du 'VS_VERSION_INFO',0,0
vivalue dd 0FEEF04BDh,00010000h
local version,count,shift,char,filever,productver
filever = 0
productver = 0
forward
if name eq 'FileVersion' | name eq 'ProductVersion'
virtual at 0
db value
count = $
version = 0
shift = 16
repeat count
load char from %-1
if char='.'
if shift mod 32
shift = shift-16
else
shift = shift+32+16
end if
else
version = (version and not (0FFFFh shl shift)) or ((version shr shift and 0FFFFh)*10+char-'0') shl shift
end if
end repeat
end virtual
if name eq 'FileVersion'
filever = version
else if name eq 'ProductVersion'
productver = version
end if
end if
common
dq filever,productver
dd 0,0,fileos,filetype+0,filesubtype+0,0,0
visize = $ - vivalue
local sfi_data,sfi_size
sfi_data dd sfi_size
du 1,'StringFileInfo',0
local str_data,str_size
str_data dd str_size
du 1,'040904E4',0
forward
local vs_data,vs_size,value_data,value_size
align 4
vs_data dw vs_size,value_size/2
du 1,name,0
align 4
value_data du value,0
value_size = $ - value_data
vs_size = $ - vs_data
common
align 4
str_size = $ - str_data
sfi_size = $ - sfi_data
local vfi_data,vfi_size,var_data,var_size
vfi_data dd vfi_size
du 1,'VarFileInfo',0,0
var_data dw var_size,4
du 0,'Translation',0,0
dw lang,cp+0
var_size = $ - var_data
vfi_size = $ - vfi_data
size = $ - data }
macro resdata label
{ local data,size
label dd RVA data,size,0,0
data = $
ressize equ size = $ - data }
macro endres
{ ressize
align 4 }

View File

@ -0,0 +1,221 @@
; 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 \} }