asm_dip/toolchain/fasm2/include/macro/struct.inc
2024-11-25 00:04:53 -05:00

456 lines
9.2 KiB
C++

define struct? struct?
namespace struct?
calminstruction instantiate: instance*, sname*, &values&
local tmp
arrange tmp, =label instance : sname.=__size__
assemble tmp
arrange tmp, =namespace instance
assemble tmp
match , values
jyes values_ready
call struct?.initialize, sname, values
values_ready:
local i
compute i, 1
local field, val, stack
process_statement:
arrange field, sname.=__label#i
transform field
jyes labeled_statement
arrange field,
arrange tmp, sname.=__statement#i
transform tmp
jyes statement_ready
jump finish
labeled_statement:
arrange tmp, sname.=__label#i sname.=__definition#i
transform tmp
arrange val, =__init__.#field
transform val
jyes got_value
arrange val, sname.=__default__.#field
arrange field,
transform val
jno statement_ready
got_value:
arrange tmp, tmp val
statement_ready:
take stack, field
take stack, i
take stack, sname
assemble tmp
take , sname
take sname, stack
take , i
take i, stack
take , field
take field, stack
match , field
jyes next_statement
arrange tmp, sname.=__size__.#field - (=$ - field)
compute tmp, tmp
check tmp = 0
jyes next_statement
check tmp > 0
jyes fill_up
stringify field
err 'value too long to fit in ' bappend field
jump next_statement
fill_up:
arrange tmp, =rb tmp
assemble tmp
next_statement:
compute i, i + 1
jump process_statement
finish:
asm end namespace
end calminstruction
calminstruction initialize sname*, values&
local j, a
compute j, 0
arrange a, sname.=__argument
local tmp, field, val, sub
process_argument:
match field=, values, values, <>
jyes got_argument
arrange field, values
arrange values,
got_argument:
match field:val?, field, <>
jyes labeled_argument
check j < 0
jyes mixed_arguments
compute j, j + 1
arrange val, field
match <val>, val
arrange field, a#j
transform field
jno excess_arguments
match <tmp>, field
jno got_argument_field
take a, tmp
compute tmp, 0
take j, tmp
take values, val
jump process_argument
excess_arguments:
err 'excess arguments'
jump arguments_processed
mixed_arguments:
err 'unsupported mixing of labeled and ordered values'
jump arguments_processed
labeled_argument:
check j > 0
jyes mixed_arguments
compute j, -1
match <val>, val
got_argument_field:
arrange tmp, sname.=__default__.#field
transform tmp
jyes argument_ok
match field.sub, field
jno unknown_field
arrange tmp, sname.=__default__.#field
transform tmp
jno unknown_field
arrange val, sub:val
arrange tmp, =__multi__.#field
transform tmp
jno append_value
arrange val, tmp, val
arrange tmp, =__multi__.#field
append_value:
publish tmp, val
jump argument_ok
unknown_field:
stringify field
arrange tmp, sname
stringify tmp
err tmp bappend ' has no field named ' bappend field
jump next_argument
argument_ok:
arrange tmp, =__init__.#field
publish tmp, val
next_argument:
match , values
jno process_argument
arguments_processed:
take , values
take , j
take , a
take values, values
jyes next_argument
end calminstruction
define pname
define i
define j
define u
define a
calminstruction (&label) collect? &definition&
local sym, default, tmp
match , definition
jyes plain
match :tmp?, definition
jyes ignored
match ==tmp?, definition
jyes ignored
arrange default,
match definition= default, definition
arrange sym, pname.=__definition#i
publish sym:, definition
arrange sym, pname.=__label#i
publish sym:, label
arrange sym, pname.=__default__.#label
publish sym:, default
arrange definition, label definition default
assemble definition
arrange definition, =__size__.#label == =$ - label
assemble definition
match , a
jyes done
compute j, j + 1
arrange sym, a#j
publish sym:, label
done:
exit
ignored:
arrange label, label definition
plain:
assemble label
end calminstruction
calminstruction collect? &statement&
local proto, sym, tmp
check i
jyes in_body
compute u, 0
compute i, 1
compute j, 1
asm virtual at 0
match pname= proto, pname
arrange tmp, =namespace pname
assemble tmp
jno prototype_copied
use_prototype:
arrange a,
arrange tmp, proto.=__statement#i
transform tmp
jno prototype_arguments
arrange sym, pname.=__statement#i
publish sym:, tmp
assemble tmp
compute i, i + 1
jump use_prototype
prototype_arguments:
arrange tmp, proto.=__argument#j
transform tmp
jno prototype_copied
arrange sym, pname.=__argument#j
publish sym:, tmp
compute j, j + 1
jump prototype_arguments
prototype_copied:
compute j, j - 1
arrange a, pname.=__argument
in_body:
match =ends?, statement
jyes close
check u
jno process_definition
check u > 1
jno union_divider_ok
arrange tmp, =__union_divider
arrange sym, pname.=__statement#i
publish sym:, tmp
assemble tmp
compute i, i + 1
arrange a,
union_divider_ok:
compute u, u + 1
process_definition:
match =struct?, statement
jyes open_struct
match =union?, statement
jyes open_union
arrange sym, pname.=__statement#i
publish sym:, statement
assemble statement
compute i, i + 1
exit
open_union:
arrange tmp, =__union_start
arrange sym, pname.=__statement#i
publish sym:, tmp
assemble tmp
compute i, i + 1
arrange tmp, a
take a, tmp
compute tmp, 1
take u, tmp
exit
open_struct:
match , a
jyes unlisted_substruct
compute j, j + 1
arrange sym, a#j
arrange tmp, a#j#=_
take a, tmp
arrange tmp, <a>
publish sym:, tmp
jump begin_substruct
unlisted_substruct:
arrange tmp,
take a, tmp
begin_substruct:
compute tmp, 0
take j, tmp
compute tmp, 0
take u, tmp
exit
close:
check u
jno close_struct
arrange tmp, =__union_end
arrange sym, pname.=__statement#i
publish sym:, tmp
assemble tmp
compute i, i + 1
take , a
take , u
exit
close_struct:
take , a
take , j
take , u
take a, a
jyes done
asm end namespace
arrange sym, pname.=__size__
compute tmp, $
publish sym:, tmp
arrange tmp, #sym
arrange sym, =sizeof.pname
publish sym, tmp
asm end virtual
assemble statement
done:
end calminstruction
end namespace
macro struct? declaration*, attributes
if defined Struct.CheckAlignment & Struct.CheckAlignment
struct?.packed = 0
else
struct?.packed = 1
end if
match =packed?, attributes
struct?.packed = 1
else match any, attributes
err 'unknown attribute ',`any
end match
define struct?.pname declaration
struct?.i = 0
mvstruc ?, struct?.collect?
mvmacro ?, struct?.collect?
end macro
macro ends?
mvmacro struct?.collect?, ?
mvstruc struct?.collect?, ?
match name, struct?.pname
label name: name.__size__ at name.__size__
struct?.check name
local sname
define sname name
calminstruction (instance) name values&
call struct?.instantiate, instance, sname, values
end calminstruction
calminstruction name &values&
local ic, iname
init ic
compute ic, ic + 1
arrange iname, sname#ic
call struct?.instantiate, iname, sname, values
end calminstruction
end match
end macro
macro __union_start
local union
union:
union.i = 0
union.size = 0
union.initialized = 0
macro __union_open
union.i = union.i + 1
if (defined union.init & union.i <> union.init) | (~ defined union.init & union.i > 1)
virtual at union
end if
end macro
macro __union_close
if $@ > union
if union.i > 1
union.init := union.i
end if
if union.initialized
err 'conflicting initialization of union'
else
union.initialized = union.i
end if
end if
if $ - union > union.size
union.size = $ - union
end if
if (defined union.init & union.i <> union.init) | (~ defined union.init & union.i > 1)
end virtual
end if
end macro
macro __union_divider
__union_close
__union_open
end macro
macro __union_end
__union_close
if $ - union < union.size
rb union.size - ($ - union)
end if
purge __union_open,__union_close,__union_divider,__union_end
end macro
__union_open
end macro
calminstruction breakifndef? sym
transform sym
jyes ok
asm break
ok:
end calminstruction
macro struct?.check name
if ~ struct?.packed
local alignment, maxalignment
maxalignment = 1
while 1
breakifndef name.__statement#%
match label, name.__label#%
if defined name.label
local alignment
alignment = 1
if sizeof name.label > 0
alignment = 1 shl (bsf sizeof name.label)
end if
match type, name.__definition#%
if defined type.__alignment
alignment = type.__alignment
end if
end match
if name.label mod alignment > 0
repeat 1, natural: alignment
display 'warning: ',`name,'.',`label,' not aligned to its natural boundary (',`natural,')',13,10
end repeat
else if alignment > maxalignment
maxalignment = alignment
end if
end if
end match
end while
if sizeof name mod maxalignment > 0
repeat 1, size: sizeof name, natural: maxalignment
display 'warning: size of ',`name,' (',`size,') not aligned to its natural boundary (',`natural,')',13,10
end repeat
end if
name.__alignment := maxalignment
end if
end macro