asm_dip/toolchain/fasm2/source/directives.inc
2024-11-25 00:04:53 -05:00

4853 lines
113 KiB
PHP

struct DirectiveBlock
type db ? ; DBLOCK_#
subtype db ? ; CTRL_# for DBLOCK_CONTROL
flags db ? ; CTRLF_# for DBLOCK_CONTROL
reserved db ?
reserved2 dw ?
prior_assembly_mode db ?
prior_special_parameters db ?
prior_counter_position dd ?
parameter_namespace dd ?
parameter dd ? ; pointer to first BlockParameter
length_of_data dd ?
ends
struct BlockParameter
symbol dd ? ; pointer to SymbolTree_Leaf
definition dd ? ; pointer to ValueDefinition
next dd ? ; pointer to another BlockParameter
ends
struct NamespaceData
prior_namespace dd ?
prior_label dd ?
ends
struct VirtualBlockData
outer_area dd ?
shift_tracking db ?
ends
struct ConditionalRepeatData
condition_length dd ?
ends
struct RepeatData
limit_length dd ?
index_position dd ?
ends
struct MacroData
nesting_counter dd ?
ends
struct SymbolSubstitution
symbol_start dd ?
symbol_end dd ?
value_start dd ?
value_end dd ?
leftover_context dd ?
ends
struct MatchedParameter
pattern dd ?
assembly_position dd ?
ends
DBLOCK_CLOSED = 0
DBLOCK_NAMESPACE = 1
DBLOCK_CONTROL = 2
DBLOCK_MACRO = 3
DBLOCK_VIRTUAL = 4
DBLOCK_CALMINSTRUCTION = 5
DBLOCK_POSTPONED = 8
DBLOCK_SUSPENDED = 9
CTRL_IF = 0
CTRL_WHILE = 2
CTRL_REPEAT = 3
CTRL_IRP = 4
CTRL_IRPV = 5
CTRL_MATCH = 6
CTRL_RMATCH = 7
CTRL_POSTPONE = 9
CTRLF_INACTIVE = 1
CTRLF_BREAKABLE = 2
CTRLF_HAS_REPEAT_DATA = 4
CTRLF_HAS_WRITABLE_INDEX = 8
CTRLF_ALLOWS_ELSE = 16
CTRLF_SUSPENDED = 32
add_directive_block:
; in:
; dl = DBLOCK_#
; ecx = length of additional data
; out: edi - new DirectiveBlock
; note: area for additional data is placed below the DirectiveBlock structure
; preserves: ebx, edx, esi
dec ecx
and ecx,(-1) shl 2
add ecx,1 shl 2
push esi ecx
mov esi,[source_context]
mov eax,[esi+SourceContext.number_of_entries]
imul eax,sizeof.SourceEntry
add eax,sizeof.SourceContext
add ecx,eax
add ecx,sizeof.DirectiveBlock
mov edi,[directives_stack]
lea eax,[edi+ecx]
cmp eax,[directives_stack_end]
jbe directives_stack_ready
add ecx,[directives_stack_end]
jc out_of_memory
mov eax,[directives_stack_base]
sub ecx,eax
push edx
call grow_stack
pop edx
add ecx,eax
mov [directives_stack_end],ecx
mov edi,eax
xchg eax,[directives_stack_base]
sub edi,eax
add edi,[directives_stack]
mov [directives_stack],edi
directives_stack_ready:
push edx
call clone_source_context
pop edx ecx
add edi,ecx
mov eax,edi
sub eax,[directives_stack]
mov [edi+DirectiveBlock.length_of_data],eax
mov [edi+DirectiveBlock.type],dl
mov al,[assembly_mode]
mov [edi+DirectiveBlock.prior_assembly_mode],al
mov ecx,[parameter_namespace]
mov [edi+DirectiveBlock.parameter_namespace],ecx
mov al,[ecx+SymbolTree_Root.parameters]
mov [edi+DirectiveBlock.prior_special_parameters],al
xor eax,eax
mov [edi+DirectiveBlock.subtype],al
mov [edi+DirectiveBlock.flags],al
mov [edi+DirectiveBlock.parameter],eax
mov eax,[current_counter]
sub eax,[counters_stack_base]
mov [edi+DirectiveBlock.prior_counter_position],eax
lea eax,[edi+sizeof.DirectiveBlock]
mov [directives_stack],eax
pop esi
retn
find_directive_block:
; in:
; dl = DBLOCK_#
; out:
; cf set when no such block found
; when cf = 0
; edi - DirectiveBlock of the latest block of this type
; preserves: ebx, edx, esi
mov edi,[directives_stack]
scan_directive_blocks:
cmp edi,[directives_stack_base]
je directive_block_not_found
sub edi,sizeof.DirectiveBlock
cmp dl,[edi+DirectiveBlock.type]
je directive_block_found
find_next_directive_block:
; in:
; dl = DBLOCK_#
; edi - DirectiveBlock
; out:
; cf set when no such block found
; when cf = 0
; edi - DirectiveBlock of the next latest block of this type
; preserves: ebx, edx, esi
mov ecx,[edi+DirectiveBlock.length_of_data]
sub edi,ecx
jmp scan_directive_blocks
directive_block_found:
clc
retn
directive_block_not_found:
stc
retn
close_control_directive_block:
; in: edi - DirectiveBlock
; preserves: esi
mov al,[edi+DirectiveBlock.prior_assembly_mode]
mov [assembly_mode],al
mov eax,[edi+DirectiveBlock.prior_counter_position]
add eax,[counters_stack_base]
mov [current_counter],eax
mov ecx,[edi+DirectiveBlock.parameter_namespace]
mov al,[edi+DirectiveBlock.prior_special_parameters]
mov [ecx+SymbolTree_Root.parameters],al
close_directive_block:
; in: edi - DirectiveBlock
; preserves: esi
mov [edi+DirectiveBlock.type],DBLOCK_CLOSED
mov eax,edi
mov ecx,[eax+DirectiveBlock.length_of_data]
sub eax,ecx
call release_source_context
call remove_block_parameters
lea eax,[edi+sizeof.DirectiveBlock]
cmp eax,[directives_stack]
je remove_directive_block
retn
remove_directive_block:
sub eax,sizeof.DirectiveBlock
mov ecx,[eax+DirectiveBlock.length_of_data]
sub eax,ecx
cmp eax,[directives_stack_base]
je directives_stack_cleared
cmp [eax-sizeof.DirectiveBlock+DirectiveBlock.type],DBLOCK_CLOSED
je remove_directive_block
directives_stack_cleared:
mov [directives_stack],eax
retn
add_block_parameter:
; in:
; ebx - SymbolTree_Leaf
; edi - DirectiveBlock
; esi - value
; ecx = length of value
; [value_type] = VALTYPE_#
; preserves: ebx, edi
push ecx
or [ebx+SymbolTree_Leaf.flags],SYM_VARIABLE
call create_value_definition
pop ecx
mov eax,[current_pass]
mov [edx+ValueDefinition.pass],eax
mov [edx+ValueDefinition.value_length],ecx
add ecx,sizeof.BlockParameter
push edi
mov edi,[edx+ValueDefinition.value]
cmp ecx,[edx+ValueDefinition.block_length]
jbe write_parameter_value
push edx
push ecx
cmp [edx+ValueDefinition.block_length],0
je allocate_memory_for_parameter
xor eax,eax
xchg eax,[edx+ValueDefinition.value]
call mfree
allocate_memory_for_parameter:
pop ecx
call malloc
pop edx
mov [edx+ValueDefinition.value],eax
mov [edx+ValueDefinition.block_length],ecx
mov edi,eax
write_parameter_value:
mov al,[value_type]
mov [edx+ValueDefinition.type],al
mov ecx,[edx+ValueDefinition.value_length]
rep movsb
mov ecx,edi
pop edi
mov [ecx+BlockParameter.symbol],ebx
mov [ecx+BlockParameter.definition],edx
inc [edx+ValueDefinition.reference_count]
mov eax,ecx
xchg eax,[edi+DirectiveBlock.parameter]
mov [ecx+BlockParameter.next],eax
retn
remove_block_parameters:
; in: edi - DirectiveBlock
; preserves: esi, edi
mov eax,[edi+DirectiveBlock.parameter]
test eax,eax
jz no_block_parameters
push esi edi
mov esi,eax
remove_block_parameter:
mov ebx,[esi+BlockParameter.symbol]
mov edx,[esi+BlockParameter.definition]
dec [edx+ValueDefinition.reference_count]
xor edi,edi
call remove_value_definition
mov esi,[esi+BlockParameter.next]
test esi,esi
jnz remove_block_parameter
pop edi esi
no_block_parameters:
retn
identify_parameter_symbol:
; in:
; esi = pointer into preprocessed line or current embedded value
; out:
; same as from identify_symbol_in_namespace
or [symbol_definition],1
mov ebx,[parameter_namespace]
mov dl,SYMCLASS_PARAMETER
call identify_symbol_in_namespace
jc parameter_symbol_identified
cmp edi,[parameter_namespace]
je parameter_symbol_identified
xor ebx,ebx
parameter_symbol_identified:
retn
cut_argument_value:
; in:
; esi = pointer into preprocessed line or current embedded value
; edi - LineExcerpt to be filled with information about cut piece of line
; [breakpoint_token] = initial byte of symbol that - if encountered - should immediately end the value
; out:
; esi = pointer advanced past the cut piece
; al = initial byte of symbol at pointer, zero when no more symbols there
; preserves: ebx, edi
call move_to_next_symbol
jc cut_plain_value
cmp byte [esi],'<'
je cut_enclosed_value
cut_plain_value:
mov dl,','
xor dh,dh
call cut_piece_of_line
retn
cut_enclosed_value:
inc esi
mov dl,'>'
mov dh,'<'
call cut_piece_of_line
cmp al,'>'
jne missing_enclosing
inc esi
call move_to_next_symbol
jnc parameter_value_cut
xor al,al
parameter_value_cut:
retn
missing_enclosing:
mov edx,_missing_closing_chevron
call register_error
retn
extract_argument_value:
; in:
; esi = pointer into preprocessed line (not an embedded value)
; edi - buffer for token sequence, must be large enough to hold all the remaining tokens in line and an additional context token
; [breakpoint_token] = initial byte of symbol that - if encountered - should immediately end the value
; [contextless_processing] = zero to have current context added to the extracted value
; out:
; esi = pointer advanced past the processed piece
; edi - end of the extracted sequence of tokens in provided buffer
; al = initial byte of symbol at pointer, zero when no more symbols there
; preserves: ebx
; note:
; when AMODE_DEFINITION is active, current context is not added to the extracted value
call move_to_next_symbol
jc extract_plain_value
cmp byte [esi],'<'
je extract_enclosed_value
extract_plain_value:
mov dl,','
xor dh,dh
call extract_piece_of_line
retn
extract_enclosed_value:
inc esi
mov dl,'>'
mov dh,'<'
call extract_piece_of_line
cmp al,'>'
jne missing_enclosing
inc esi
call move_to_next_symbol
jnc parameter_value_extracted
xor al,al
parameter_value_extracted:
retn
get_macro_definition_symbol:
; in:
; esi = pointer into preprocessed line or current embedded value
; al = initial byte of symbol at esi
; dl = SYMCLASS_#
; out:
; ebx - SymbolTree_Leaf
; esi = pointer advanced past the processed declaration
; [macro_leaf] - SymbolTree_Leaf
; [macro_flags] = VAL_#
mov [macro_flags],VAL_NONRECURSIVE
cmp al,'!'
je unconditional_interceptor
or [symbol_definition],1
call identify_symbol
jc invalid_macro_symbol
test ebx,ebx
jz invalid_macro_symbol
macro_symbol_identified:
call move_to_next_symbol
jc macro_symbol_ok
cmp al,':'
je recursive_macro
test ecx,ecx
jnz macro_symbol_ok
cmp al,'!'
je unconditional_macro
jmp macro_symbol_ok
unconditional_interceptor:
mov ebx,[interceptor_symbol]
cmp dl,SYMCLASS_STRUCTURE
jne unconditional_macro
mov ebx,[label_interceptor_symbol]
unconditional_macro:
or [macro_flags],VAL_UNCONDITIONAL
inc esi
call move_to_next_symbol
jc macro_symbol_ok
cmp al,':'
jne macro_symbol_ok
recursive_macro:
inc esi
call move_to_next_symbol
and [macro_flags],not VAL_NONRECURSIVE
or [ebx+SymbolTree_Leaf.flags],SYM_CONSTANT
jmp macro_symbol_ok
macro_symbol_ok:
mov [macro_leaf],ebx
mov edx,[ebx+SymbolTree_Leaf.definition]
test edx,edx
jz create_placeholder_value
test [edx+ValueDefinition.flags],VAL_INTERNAL
jnz macro_already_defined
mov eax,[current_pass]
sub eax,[edx+ValueDefinition.pass]
jz macro_already_defined
cmp eax,1
je macro_symbol_ready
create_placeholder_value:
; for VAL_UNCONDITIONAL macros this helps to detect when a macro tries to call itself,
; for regular ones this section interferes with operation of SYM_PREDICTED to sometimes prevent excess passes,
; when SYM_PREDICTED is needed to behave reliably for an instruction, its symbol
; should be marked with SYMX_INSTRUCTION_PREDICTED to skip this section
test [ebx+SymbolTree_Leaf.extra_flags],SYMX_INSTRUCTION_PREDICTED
jnz macro_symbol_ready
call create_value_definition
test edx,edx
jz macro_symbol_ready
mov eax,[current_pass]
dec eax
mov [edx+ValueDefinition.pass],eax
mov [edx+ValueDefinition.type],VALTYPE_RESERVED
mov al,[macro_flags]
mov [edx+ValueDefinition.flags],al
test al,VAL_UNCONDITIONAL
jnz macro_symbol_ready
or [edx+ValueDefinition.flags],VAL_IN_USE
test [ebx+SymbolTree_Leaf.flags],SYM_PREDICTED
jz macro_symbol_ready
mov edi,ebx
mov ecx,[current_pass]
check_macro_usage:
cmp ecx,[edi+SymbolTree_Leaf.last_use_pass]
je macro_possibly_used_earlier
mov edx,[edi+SymbolTree_Leaf.fallback_neighbour]
test edx,edx
jz look_up_parent_namespace_macro
cmp ecx,[edx+SymbolTree_Leaf.last_use_pass]
je macro_possibly_used_earlier
look_up_parent_namespace_macro:
mov edi,[edi+SymbolTree_Leaf.fallback_parent]
test edi,edi
jnz check_macro_usage
and [ebx+SymbolTree_Leaf.flags],not SYM_PREDICTED
jmp macro_symbol_ready
macro_possibly_used_earlier:
test al,VAL_NONRECURSIVE
jnz macro_symbol_ready
or [next_pass_needed],-1
macro_symbol_ready:
clc
retn
macro_already_defined:
test [ebx+SymbolTree_Leaf.flags],SYM_CONSTANT
jz macro_symbol_ready
mov edx,_conflicting_definition
call register_error
invalid_macro_symbol:
stc
retn
; instruction handler
; in:
; esi = pointer into preprocessed line
; ecx = number of whitespace tokens between previous symbol and current position
; edx - ValueDefinition of instruction
; ebx - SymbolTree_Leaf of instruction
; edi - SymbolTree_Root of instruction
; when [SymbolTree_Leaf.class] = SYMCLASS_STRUCTURE:
; [label_leaf] - SymbolTree_Leaf of structure label
; [label_branch] - SymbolTree_Foliage of structure label
; [label_independent] = zero when identifier of structure label is relative to current label
; out:
; when done, handler should jump to instruction_assembled with esi containing a pointer moved past the processed part of line,
; or jump directly to assembly_line when the rest of line should be ignored
; note:
; when esi is equal to [line_end], pointer is at the end of line and there is no data available at this address
set_namespace:
mov dl,DBLOCK_NAMESPACE
mov ecx,sizeof.NamespaceData
call add_directive_block
mov edx,[current_context.base_namespace]
mov [edi-sizeof.NamespaceData+NamespaceData.prior_namespace],edx
mov eax,[edx+SymbolTree_Root.current_label]
mov [edi-sizeof.NamespaceData+NamespaceData.prior_label],eax
and [symbol_definition],0
mov dl,SYMCLASS_EXPRESSION
call identify_symbol
jc missing_argument
test ebx,ebx
jz invalid_identifier
call get_symbol_namespace
mov [current_context.base_namespace],ebx
and [ebx+SymbolTree_Root.current_label],0
jmp instruction_assembled
end_namespace:
mov dl,DBLOCK_NAMESPACE
call find_directive_block
jc unexpected_instruction
mov edx,[edi-sizeof.NamespaceData+NamespaceData.prior_namespace]
mov eax,[edi-sizeof.NamespaceData+NamespaceData.prior_label]
mov [current_context.base_namespace],edx
mov [edx+SymbolTree_Root.current_label],eax
call close_directive_block
jmp instruction_assembled
set_base_address:
mov edx,[current_area]
mov ebx,[edx+ValueDefinition.value]
test [ebx+AreaHeader.flags],AREA_VIRTUAL
jnz unexpected_instruction
call get_expression_value
jc invalid_argument
push esi
call convert_terms_to_numeric_value
begin_new_output_area:
call create_output_area
inc [edx+ValueDefinition.reference_count]
xchg edx,[current_area]
dec [edx+ValueDefinition.reference_count]
; jz internal_error
pop esi
jmp instruction_assembled
begin_new_section:
mov edx,[current_area]
mov ebx,[edx+ValueDefinition.value]
test [ebx+AreaHeader.flags],AREA_VIRTUAL
jnz unexpected_instruction
call get_expression_value
jc invalid_argument
push esi
call convert_terms_to_numeric_value
call trim_output
call create_output_area
mov eax,edx
inc [eax+ValueDefinition.reference_count]
xchg eax,[current_area]
dec [eax+ValueDefinition.reference_count]
; jz internal_error
pop esi
jmp instruction_assembled
restart_output:
mov edx,[current_area]
mov ebx,[edx+ValueDefinition.value]
test [ebx+AreaHeader.flags],AREA_VIRTUAL
jnz unexpected_instruction
call peek_at_constituent_value
jc restart_output_at_current_address
call get_expression_value
jc invalid_argument
push esi
call convert_terms_to_numeric_value
jmp make_new_initial_output_area
restart_output_at_current_address:
push esi
call get_current_address_value
make_new_initial_output_area:
and [initial_output_area_entry],0
jmp begin_new_output_area
define_label:
inc esi
xor ecx,ecx
call move_to_next_symbol
jc define_simple_label
test ecx,ecx
jnz define_simple_label
cmp al,'='
je define_numeric_constant
cmp al,':'
je define_area_label
define_simple_label:
test [assembly_mode],AMODE_SKIP
jnz assemble_after_label
test [assembly_mode],AMODE_DEFINITION
jnz add_label_to_macro
cmp [interceptor],0
jne execute_interceptor
mov [argument_start],esi
call get_current_address_value
mov edi,ecx
mov ebx,[label_leaf]
call create_constant_value_definition
test edx,edx
jz assembly_line
mov ecx,edi
call assign_shiftable_value
label_defined:
call update_current_label
mov esi,[argument_start]
assemble_after_label:
mov [line_start],esi
mov eax,[embedded_context]
mov [line_context],eax
jmp assemble_instruction
define_area_label:
inc esi
test [assembly_mode],AMODE_SKIP
jnz assemble_after_label
test [assembly_mode],AMODE_DEFINITION
jnz add_label_to_macro
cmp [interceptor],0
jne execute_interceptor
mov [argument_start],esi
mov ebx,[label_leaf]
mov edx,[current_area]
call update_value_link
jmp label_defined
assign_shiftable_value:
mov [value_type],VALTYPE_NUMERIC
mov eax,[current_area]
mov eax,[eax+ValueDefinition.value]
test [eax+AreaHeader.flags],AREA_SHIFT_TRACKING_DISABLED
jnz assign_value
or [shift_tracking],-1
call update_predicted_shift
call assign_value
or [edx+ValueDefinition.flags],VAL_SHIFTABLE
retn
update_current_label:
mov edx,[label_branch]
cmp [label_independent],0
je current_label_ok
mov edi,[edx+SymbolTree_Foliage.root]
test [edi+SymbolTree_Root.flags],NAMESPACE_LOCAL
jnz current_label_ok
mov edi,[current_context.base_namespace]
mov [edi+SymbolTree_Root.current_label],edx
current_label_ok:
retn
define_numeric_symbol:
test [assembly_mode],AMODE_SKIP
jnz assembly_line
test [assembly_mode],AMODE_DEFINITION
jnz add_line_to_macro
cmp [interceptor],0
jne execute_interceptor
inc esi
xor ecx,ecx
call move_to_next_symbol
jc define_numeric_variable
test ecx,ecx
jnz define_numeric_variable
cmp al,':'
jne define_numeric_variable
inc esi
call get_expression_value
jc missing_argument
mov ebx,[label_leaf]
call create_value_definition
jmp define_numeric_value
define_numeric_constant:
test [assembly_mode],AMODE_SKIP
jnz assembly_line
test [assembly_mode],AMODE_DEFINITION
jnz add_line_to_macro
cmp [interceptor],0
jne execute_interceptor
inc esi
call get_expression_value
jc missing_argument
mov ebx,[label_leaf]
call create_constant_value_definition
jmp define_numeric_value
define_numeric_variable:
call get_expression_value
jc missing_argument
mov ebx,[label_leaf]
call update_value_definition
define_numeric_value:
test edx,edx
jz assembly_line
push esi
push ebx edx
mov eax,[edi+ExpressionTerm.attributes]
cmp al,EXPR_STRING
je define_string_variable
cmp al,EXPR_FLOAT
je define_float_variable
mov [value_type],VALTYPE_NUMERIC
call convert_terms_to_numeric_value
assign_numeric_value:
pop edx ebx
call assign_value
pop esi
jmp instruction_assembled
define_string_variable:
mov [value_type],VALTYPE_STRING
call get_term_value
mov esi,edx
mov ecx,[esi]
add ecx,4
jmp assign_numeric_value
define_float_variable:
mov [value_type],VALTYPE_FLOAT
call get_term_value
mov esi,edx
mov ecx,sizeof.FloatData
jmp assign_numeric_value
define_element:
or [symbol_definition],1
mov dl,SYMCLASS_EXPRESSION
call identify_symbol
jc missing_argument
test ebx,ebx
jz invalid_identifier
mov [label_leaf],ebx
call move_to_next_symbol
jc element_with_no_metadata
cmp al,':'
jne get_element_metadata
inc esi
get_element_metadata:
call get_expression_value
jc invalid_argument
mov ebx,[label_leaf]
call create_constant_value_definition
test edx,edx
jz assembly_line
mov [value_type],VALTYPE_ELEMENT
push esi
push ebx edx
call convert_terms_to_numeric_value
pop edx ebx
call assign_value
pop esi
jmp instruction_assembled
element_with_no_metadata:
mov ebx,[label_leaf]
call create_constant_value_definition
test edx,edx
jz assembly_line
mov [value_type],VALTYPE_ELEMENT
push esi
xor esi,esi
xor ecx,ecx
call assign_value
pop esi
jmp instruction_assembled
redefine_raw_symbolic_variable:
mov [update_function],update_value_definition
jmp raw_symbolic_variable
define_raw_symbolic_variable:
mov [update_function],create_value_definition
raw_symbolic_variable:
or [symbol_definition],1
mov dl,SYMCLASS_EXPRESSION
call identify_symbol
jc missing_argument
test ebx,ebx
jz invalid_identifier
mov [label_leaf],ebx
or [raw_value],1
jmp symbolic_variable
redefine_symbolic_variable:
mov [update_function],update_value_definition
and [raw_value],0
jmp symbolic_variable
define_symbolic_variable:
mov [update_function],create_value_definition
and [raw_value],0
symbolic_variable:
mov edi,[assembly_workspace.memory_start]
and [previous_symbol_end],0
and [contextless_processing],0
expand_symbols:
cmp [raw_value],0
jne copy_raw_symbols
and [symbol_definition],0
mov dl,SYMCLASS_EXPRESSION
push edi
call identify_symbol
jc symbols_expanded
test edi,edi
jnz symbol_ready
call skip_literal
xor ebx,ebx
symbol_ready:
pop edi
test ebx,ebx
jz copy_symbol
mov [further_whitespace],ecx
call get_available_value
jc copy_symbol
cmp [edx+ValueDefinition.type],VALTYPE_SYMBOLIC
jne copy_symbol
and [previous_symbol_end],0
mov eax,[current_pass]
mov [ebx+SymbolTree_Leaf.last_use_pass],eax
cmp ebx,[label_leaf]
jne replace_symbolic_variable
mov ecx,[edx+ValueDefinition.pass]
cmp ecx,[current_pass]
je replace_symbolic_variable
mov edx,_symbolic_self_reference
call register_error
jmp expand_symbols
replace_symbolic_variable:
mov ecx,[edx+ValueDefinition.value_length]
test ecx,ecx
jz expand_symbols
push esi
mov esi,[edx+ValueDefinition.value]
push ecx
add ecx,1+sizeof.RecognitionContext
add ecx,[further_whitespace]
mov edx,assembly_workspace
call reserve_workspace
mov al,40h
cmp al,[esi]
je copy_symbolic_value
stosb
mov eax,esi
mov esi,current_context
assert sizeof.RecognitionContext and 11b = 0
mov ecx,sizeof.RecognitionContext shr 2
rep movsd
mov esi,eax
copy_symbolic_value:
pop ecx
rep movsb
pop esi
mov al,20h
mov ecx,[further_whitespace]
rep stosb
jmp expand_symbols
copy_raw_symbols:
mov eax,esi
mov esi,[line_end]
cmp esi,eax
je symbolic_value_ready
mov [symbol_start],eax
copy_symbol:
mov ebx,esi
xchg [previous_symbol_end],esi
test esi,esi
jz copy_symbol_with_recognition_context
mov ecx,ebx
sub ecx,esi
mov edx,assembly_workspace
call reserve_workspace
and [context_boundary],0
jmp copy_symbol_tokens
copy_symbol_with_recognition_context:
mov ecx,ebx
sub ecx,[symbol_start]
add ecx,1+sizeof.RecognitionContext
mov edx,assembly_workspace
call reserve_workspace
mov al,40h
stosb
cmp [raw_value],0
je use_recognition_context
mov esi,[embedded_context]
test esi,esi
jz use_current_context
call store_recognition_context
jmp symbol_context_stored
use_current_context:
call store_current_context
jmp symbol_context_stored
use_recognition_context:
mov esi,recognition_context
assert sizeof.RecognitionContext and 11b = 0
mov ecx,sizeof.RecognitionContext shr 2
rep movsd
mov [context_boundary],edi
symbol_context_stored:
mov esi,[symbol_start]
copy_symbol_tokens:
cmp esi,ebx
jae expand_symbols
call store_token
jmp copy_symbol_tokens
symbols_expanded:
pop edi
symbolic_value_ready:
mov ebx,[label_leaf]
call [update_function]
test edx,edx
jz assembly_line
mov [value_type],VALTYPE_SYMBOLIC
mov esi,[assembly_workspace.memory_start]
mov ecx,edi
sub ecx,esi
call assign_value
jmp assembly_line
store_token:
lodsb
cmp al,40h
je make_recognition_context_token
stosb
cmp al,1Ah
je store_token_with_data
cmp al,22h
je store_token_with_data
cmp al,27h
je store_token_with_data
cmp al,30h
je store_internal_token
retn
store_token_with_data:
movsd
retn
store_internal_token:
lodsd
stosd
mov ecx,eax
rep movsb
retn
restore_variables:
mov al,[edx+ValueDefinition.attribute]
mov [chosen_class],al
restore_symbol_value:
mov dl,[chosen_class]
or [symbol_definition],1
call identify_symbol
jc missing_argument
test ebx,ebx
jz invalid_identifier
remove_variable_value:
xor edx,edx
xor edi,edi
call remove_value_definition
call move_to_next_symbol
jc assembly_line
cmp al,','
jne invalid_argument
inc esi
jmp restore_symbol_value
move_variable_values:
mov dl,[edx+ValueDefinition.attribute]
mov [chosen_class],dl
or [symbol_definition],1
call identify_symbol
jc missing_argument
test ebx,ebx
jz invalid_identifier
mov [label_leaf],ebx
call move_to_next_symbol
jc missing_argument
cmp al,','
jne invalid_argument
inc esi
mov dl,[chosen_class]
call identify_symbol
jc missing_argument
test ebx,ebx
jz invalid_identifier
xor edx,edx
mov edi,[label_leaf]
call remove_value_definition
jmp instruction_assembled
label_directive:
or [symbol_definition],1
mov dl,SYMCLASS_EXPRESSION
call identify_symbol
jc missing_argument
test ebx,ebx
jz invalid_identifier
mov [label_leaf],ebx
mov [label_branch],edx
mov al,[symbol_independent]
mov [label_independent],al
and [metadata_length],0
call peek_at_constituent_value
jc label_at_current_address
cmp al,1Ah
jne label_with_size
test edx,edx
jz label_with_size
cmp [edx+ValueDefinition.type],VALTYPE_NATIVE_PREPOSITION
jne label_with_size
cmp [edx+ValueDefinition.value],PREPOSITION_AT
je label_at_specified_address
label_with_size:
cmp al,':'
jne get_label_size
and [current_constituent],0
get_label_size:
call get_expression_value
jc invalid_argument
push esi
mov edx,auxiliary_workspace
call convert_terms_to_numeric_value_in_workspace
mov [metadata_length],ecx
pop esi
call peek_at_constituent_value
jc label_at_current_address
cmp al,1Ah
jne label_at_current_address
test edx,edx
jz invalid_argument
cmp [edx+ValueDefinition.type],VALTYPE_NATIVE_PREPOSITION
jne label_at_current_address
cmp [edx+ValueDefinition.value],PREPOSITION_AT
jne invalid_argument
label_at_specified_address:
and [current_constituent],0
call get_expression_value
jc invalid_argument
push esi
call convert_terms_to_numeric_value
mov edi,ecx
mov ebx,[label_leaf]
call create_constant_value_definition
test edx,edx
jz label_ready
call prepare_label_value
mov [value_type],VALTYPE_NUMERIC
call assign_value
jmp label_ready
label_at_current_address:
push esi
call get_current_address_value
mov edi,ecx
mov ebx,[label_leaf]
call create_constant_value_definition
test edx,edx
jz label_ready
call prepare_label_value
call assign_shiftable_value
label_ready:
pop esi
call update_current_label
jmp instruction_assembled
prepare_label_value:
mov ecx,edi
cmp [metadata_length],0
je label_metadata_ok
add edi,esi
push edx ecx
mov ecx,[metadata_length]
mov edx,assembly_workspace
call reserve_workspace
mov esi,[auxiliary_workspace.memory_start]
mov ecx,[metadata_length]
pop eax
add eax,ecx
rep movsb
pop edx
mov ecx,eax
mov esi,edi
sub esi,ecx
label_metadata_ok:
retn
virtual_block:
mov dl,DBLOCK_VIRTUAL
mov ecx,sizeof.VirtualBlockData
call add_directive_block
mov edx,[current_area]
mov [edi-sizeof.VirtualBlockData+VirtualBlockData.outer_area],edx
mov al,[shift_tracking]
mov [edi-sizeof.VirtualBlockData+VirtualBlockData.shift_tracking],al
call peek_at_constituent_value
jc virtual_at_current_address
cmp al,1Ah
jne invalid_argument
test edx,edx
jz invalid_argument
cmp [edx+ValueDefinition.type],VALTYPE_NATIVE_PREPOSITION
jne continue_virtual_block
mov eax,[edx+ValueDefinition.value]
cmp eax,PREPOSITION_AS
je virtual_at_current_address
cmp eax,PREPOSITION_AT
jne invalid_argument
and [current_constituent],0
call get_expression_value
jc invalid_argument
push esi
call convert_terms_to_numeric_value
jmp create_virtual_block
virtual_at_current_address:
push esi
call get_current_address_value
create_virtual_block:
lea ebx,[virtual_area]
call create_area
or [ebx+AreaHeader.flags],AREA_VIRTUAL
cmp [shift_tracking],0
je virtual_block_ready
or [ebx+AreaHeader.flags],AREA_SHIFT_TRACKING_DISABLED
virtual_block_ready:
inc [edx+ValueDefinition.reference_count]
or [edx+ValueDefinition.flags],VAL_IN_USE
mov [current_area],edx
pop esi
call get_constituent_value
jc instruction_assembled
cmp al,1Ah
jne invalid_argument
test edx,edx
jz invalid_argument
cmp [edx+ValueDefinition.type],VALTYPE_NATIVE_PREPOSITION
jne invalid_argument
cmp [edx+ValueDefinition.value],PREPOSITION_AS
jne invalid_argument
call get_constant_value
cmp al,22h
jne invalid_argument
mov ebx,[auxiliary_output_areas]
mov edi,esi
mov ecx,[edx]
lea esi,[edx+4]
test ecx,ecx
jnz register_auxiliary_file
dec esi
register_auxiliary_file:
mov eax,[current_area]
inc [eax+ValueDefinition.reference_count]
push ecx
call put_into_map
pop ecx
jmp validate_extension
continue_virtual_block:
and [leave_opening_parentheses],0
mov edi,[expression_workspace.memory_start]
call parse_expression
mov edi,[expression_workspace.memory_start]
call get_area_value
jc invalid_area
mov ecx,[current_pass]
cmp [edx+ValueDefinition.pass],ecx
jne invalid_area
mov eax,[edx+ValueDefinition.value]
test [eax+AreaHeader.flags],AREA_VIRTUAL
jz invalid_area
test [edx+ValueDefinition.flags],VAL_IN_USE
jnz invalid_area
inc [edx+ValueDefinition.reference_count]
or [edx+ValueDefinition.flags],VAL_IN_USE
mov [current_area],edx
jmp instruction_assembled
invalid_area:
mov edx,_invalid_area
call register_error
jmp assembly_line
end_virtual_block:
mov dl,DBLOCK_VIRTUAL
call find_directive_block
jc unexpected_instruction
mov al,[edi-sizeof.VirtualBlockData+VirtualBlockData.shift_tracking]
mov [shift_tracking],al
mov edx,[edi-sizeof.VirtualBlockData+VirtualBlockData.outer_area]
xchg edx,[current_area]
and [edx+ValueDefinition.flags],not VAL_IN_USE
dec [edx+ValueDefinition.reference_count]
jnz close_virtual_block
mov eax,edx
xchg eax,[retired_definition]
mov [edx+ValueDefinition.previous],eax
close_virtual_block:
call close_directive_block
jmp instruction_assembled
include_source:
call move_to_next_symbol
jc missing_argument
cmp al,'!'
jne conditional_include
inc esi
jmp get_file_name
conditional_include:
test [assembly_mode],AMODE_SKIP
jnz assembly_line
test [assembly_mode],AMODE_DEFINITION
jnz add_line_to_macro
get_file_name:
call get_constant_value
cmp al,22h
jne invalid_argument
push esi
mov [file_name],edx
call prepare_file_path
mov esi,[assembly_workspace.memory_start]
call read_source
test eax,eax
jnz include_read
mov esi,[local_path]
call read_source
test eax,eax
jnz include_read
mov ebx,esi
mov esi,[include_paths]
try_include_paths:
lodsb
test al,al
jz include_not_found
cmp al,';'
je try_include_paths
lea ebx,[esi-1]
measure_path:
lodsb
test al,al
jz path_measured
cmp al,';'
jne measure_path
path_measured:
dec esi
xchg esi,ebx
mov ecx,ebx
sub ecx,esi
mov edx,[file_name]
add ecx,[edx]
add ecx,2
mov edx,assembly_workspace
mov edi,[edx+Workspace.memory_start]
call reserve_workspace
mov ecx,ebx
sub ecx,esi
rep movsb
mov al,[esi-1]
cmp al,'/'
je path_separator_ok
cmp al,'\'
je path_separator_ok
mov al,'/'
stosb
path_separator_ok:
mov esi,[file_name]
lodsd
mov ecx,eax
rep movsb
xor al,al
stosb
mov esi,[assembly_workspace.memory_start]
push ebx
call read_source
mov ebx,esi
pop esi
test eax,eax
jz try_include_paths
mov esi,ebx
include_read:
mov edx,eax
call create_source_entry
jc include_stack_limit_exceeded
mov [ebx+SourceEntry.type],SOURCE_FILE
mov [ebx+SourceEntry.name],esi
mov [ebx+SourceEntry.text],edx
mov edx,[local_parameter_namespace]
mov eax,[edx+SymbolTree_Root.chain]
test eax,eax
jnz new_parameter_namespace_ok
call create_parameter_namespace
mov [edx+SymbolTree_Root.chain],eax
new_parameter_namespace_ok:
and [eax+SymbolTree_Root.parameters],0
mov [ebx+SourceEntry.local_namespace],eax
pop esi
call get_constituent_value
jc instruction_assembled
cmp al,','
jne extra_characters_on_line
cmp [number_of_line_embeddings],0
jne invalid_argument
jmp assemble_after_label
include_stack_limit_exceeded:
pop esi
mov edx,_stack_limit_exceeded
call register_error
jmp instruction_assembled
include_not_found:
pop esi
mov edx,_source_file_not_found
call register_error
jmp instruction_assembled
prepare_file_path:
mov [local_path],edx
call get_file_source_entry
mov esi,[ebx+SourceEntry.name]
mov ecx,esi
cut_parent_path:
lodsb
test al,al
jz parent_path_cut
cmp al,'/'
je found_path_segment
cmp al,'\'
jne cut_parent_path
found_path_segment:
mov ecx,esi
jmp cut_parent_path
parent_path_cut:
mov esi,[ebx+SourceEntry.name]
sub ecx,esi
mov ebx,ecx
add ecx,[edx]
inc ecx
mov edx,assembly_workspace
mov edi,[edx+Workspace.memory_start]
call reserve_workspace
mov ecx,ebx
rep movsb
mov edx,edi
xchg edx,[local_path]
lea esi,[edx+4]
mov ecx,[edx]
mov ebx,edi
rep movsb
xor al,al
stosb
retn
evaluate_string:
mov edi,[assembly_workspace.memory_start]
mov [string_end],edi
collect_source_string:
call get_constant_value
cmp al,30h
je collect_source_byte
cmp al,22h
jne invalid_argument
mov ebx,edx
mov edi,[string_end]
mov ecx,[ebx]
inc ecx
mov edx,assembly_workspace
call reserve_workspace
xchg esi,ebx
lodsd
mov ecx,eax
rep movsb
mov esi,ebx
source_fragment_collected:
mov [string_end],edi
call get_constituent_value
jc source_string_ready
cmp al,','
jne invalid_argument
jmp collect_source_string
collect_source_byte:
mov ebx,edx
mov edi,[string_end]
mov ecx,2
mov edx,assembly_workspace
call reserve_workspace
mov edx,ebx
mov ecx,1
call fit_value
jc value_out_of_range
inc edi
jmp source_fragment_collected
source_string_ready:
mov edi,[string_end]
xor al,al
stosb
push esi
mov esi,[assembly_workspace.memory_start]
call use_source
mov edx,eax
call create_source_entry
jc include_stack_limit_exceeded
mov [ebx+SourceEntry.type],SOURCE_MEMORY
mov [ebx+SourceEntry.name],esi
mov [ebx+SourceEntry.text],edx
mov eax,[parameter_namespace]
mov [ebx+SourceEntry.local_namespace],eax
pop esi
jmp instruction_assembled
assert_condition:
call get_condition_value
test al,al
jnz instruction_assembled
mov edx,_assertion_failed
call register_error
jmp instruction_assembled
conditional_block:
test [assembly_mode],AMODE_DEFINITION
jnz ignored_directive
mov dl,DBLOCK_CONTROL
xor ecx,ecx
call add_directive_block
mov [edi+DirectiveBlock.subtype],CTRL_IF
or [edi+DirectiveBlock.flags],CTRLF_ALLOWS_ELSE
test [assembly_mode],AMODE_SKIP
jnz skip_conditional_block
evaluate_conditional_block:
call get_condition_value
test al,al
jnz instruction_assembled
or [assembly_mode],AMODE_SKIP
jmp instruction_assembled
ignored_directive:
test [assembly_mode],AMODE_SKIP
jz add_line_to_macro
jmp assembly_line
else_conditional_block:
test [assembly_mode],AMODE_DEFINITION
jnz ignored_directive
mov dl,DBLOCK_CONTROL
call find_directive_block
jc unexpected_instruction
mov al,[edi+DirectiveBlock.flags]
test al,CTRLF_ALLOWS_ELSE
jz unexpected_instruction
mov ah,[assembly_mode]
push eax
call close_control_directive_block
mov dl,DBLOCK_CONTROL
xor ecx,ecx
call add_directive_block
mov [edi+DirectiveBlock.subtype],CTRL_IF
or [edi+DirectiveBlock.flags],CTRLF_ALLOWS_ELSE
pop eax
test al,CTRLF_INACTIVE
jnz skip_conditional_block
test ah,AMODE_SKIP
jnz evaluate_conditional_block
skip_conditional_block:
or [assembly_mode],AMODE_SKIP
or [edi+DirectiveBlock.flags],CTRLF_INACTIVE
jmp assembly_line
end_conditional_block:
test [assembly_mode],AMODE_DEFINITION
jnz ignored_directive
mov dl,DBLOCK_CONTROL
call find_directive_block
jc unexpected_instruction
cmp [edi+DirectiveBlock.subtype],CTRL_IF
jne unexpected_instruction
end_control_block:
call close_control_directive_block
jmp instruction_assembled
conditionally_repeated_block:
test [assembly_mode],AMODE_DEFINITION
jnz ignored_directive
test [assembly_mode],AMODE_SKIP
jnz inactive_conditionally_repeated_block
mov ecx,[line_end]
sub ecx,esi
add ecx,sizeof.ConditionalRepeatData
cmp [embedded_context],0
je condition_length_ok
add ecx,1+sizeof.RecognitionContext
condition_length_ok:
mov dl,DBLOCK_CONTROL
call add_directive_block
push esi
mov ecx,[line_end]
sub ecx,esi
sub edi,sizeof.ConditionalRepeatData
mov edx,ecx
sub edi,ecx
rep movsb
mov esi,[embedded_context]
test esi,esi
jz condition_stored
add edx,1+sizeof.RecognitionContext
mov ebx,edi
sub edi,edx
mov al,40h
stosb
assert sizeof.RecognitionContext and 11b = 0
mov ecx,sizeof.RecognitionContext shr 2
rep movsd
mov edi,ebx
condition_stored:
mov [edi+ConditionalRepeatData.condition_length],edx
add edi,sizeof.ConditionalRepeatData
pop esi
mov [edi+DirectiveBlock.subtype],CTRL_WHILE
or [edi+DirectiveBlock.flags],CTRLF_BREAKABLE
call get_condition_value
test al,al
jz skip_repeated_block
start_repeated_block:
mov ecx,2
call allocate_counter
mov edi,ebx
mov al,1
stosb
stosb
mov [current_counter],ebx
mov ecx,[parameter_namespace]
mov [ecx+SymbolTree_Root.parameters],SPECPARM_COUNTER
test esi,esi
jz assembly_line
jmp instruction_assembled
inactive_conditionally_repeated_block:
xor esi,esi
mov dh,CTRL_WHILE
inactive_breakable_block:
mov dl,DBLOCK_CONTROL
xor ecx,ecx
call add_directive_block
mov [edi+DirectiveBlock.subtype],dh
or [edi+DirectiveBlock.flags],CTRLF_BREAKABLE
skip_repeated_block:
or [assembly_mode],AMODE_SKIP
mov ecx,1
call allocate_counter
mov byte [ebx],0
mov [current_counter],ebx
mov ecx,[parameter_namespace]
mov [ecx+SymbolTree_Root.parameters],0
test esi,esi
jz assembly_line
jmp instruction_assembled
allocate_counter:
mov ebx,[current_counter]
movzx eax,byte [ebx]
lea ebx,[ebx+1+eax]
add ecx,ebx
cmp ecx,[counters_stack_end]
jbe counter_allocated
mov eax,[counters_stack_base]
sub ecx,eax
sub ebx,eax
call grow_stack
add ecx,eax
mov [counters_stack_end],ecx
mov [counters_stack_base],eax
add ebx,eax
counter_allocated:
retn
end_conditionally_repeated_block:
test [assembly_mode],AMODE_DEFINITION
jnz ignored_directive
mov dl,DBLOCK_CONTROL
call find_directive_block
jc unexpected_instruction
cmp [edi+DirectiveBlock.subtype],CTRL_WHILE
jne unexpected_instruction
test [assembly_mode],AMODE_SKIP
jnz end_control_block
push esi edi
push [line_end]
push [source_context]
lea esi,[edi-sizeof.ConditionalRepeatData]
mov [line_end],esi
sub esi,[esi+ConditionalRepeatData.condition_length]
sub edi,[edi+DirectiveBlock.length_of_data]
mov [source_context],edi
and [embedded_context],0
call get_condition_value
pop [source_context]
pop [line_end]
pop edi esi
test al,al
jz end_control_block
repeat_condition_upheld:
mov ebx,[current_counter]
movzx ecx,byte [ebx]
inc ebx
increase_counter:
inc byte [ebx]
jnz counter_increased
inc ebx
loop increase_counter
cmp ebx,[counters_stack_end]
jb counter_length_grown
lea ecx,[ebx+1]
mov eax,[counters_stack_base]
sub ecx,eax
sub ebx,eax
sub [current_counter],eax
call grow_stack
add ecx,eax
mov [counters_stack_end],ecx
mov [counters_stack_base],eax
add [current_counter],eax
add ebx,eax
counter_length_grown:
mov byte [ebx],1
mov ebx,[current_counter]
inc byte [ebx]
counter_increased:
push esi
test [edi+DirectiveBlock.flags],CTRLF_HAS_REPEAT_DATA
jz index_updated
mov esi,[current_counter]
mov eax,[counters_stack_base]
add eax,[edi-sizeof.RepeatData+RepeatData.index_position]
cmp eax,esi
je index_updated
xchg eax,edi
movzx ecx,byte [esi]
inc ecx
rep movsb
mov edi,eax
index_updated:
mov eax,[source_context]
mov esi,eax
call release_source_context
sub edi,[edi+DirectiveBlock.length_of_data]
xchg esi,edi
call clone_source_context
pop esi
jmp instruction_assembled
repeated_block:
test [assembly_mode],AMODE_DEFINITION
jnz ignored_directive
test [assembly_mode],AMODE_SKIP
jnz inactive_repeated_block
call get_numeric_constant_value
test edx,edx
jz invalid_count
mov ecx,[edx]
add edx,4
test ecx,ecx
jz inactive_repeated_block
mov al,[edx+ecx-1]
test al,al
js count_out_of_range
jnz count_ok
optimize_counter:
test ecx,ecx
jz inactive_repeated_block
dec ecx
mov al,[edx+ecx-1]
test al,al
jz optimize_counter
count_ok:
push esi ecx
mov esi,edx
mov dl,DBLOCK_CONTROL
add ecx,sizeof.RepeatData
call add_directive_block
mov [edi+DirectiveBlock.subtype],CTRL_REPEAT
or [edi+DirectiveBlock.flags],CTRLF_BREAKABLE + CTRLF_HAS_REPEAT_DATA
mov [directive_block],edi
pop ecx
sub edi,sizeof.RepeatData
mov [edi+RepeatData.limit_length],ecx
sub edi,ecx
rep movsb
pop esi
mov ecx,2
call allocate_counter
mov eax,ebx
sub eax,[counters_stack_base]
mov [edi+RepeatData.index_position],eax
mov edi,ebx
mov al,1
stosb
stosb
mov [current_counter],ebx
mov ecx,[parameter_namespace]
mov [ecx+SymbolTree_Root.parameters],SPECPARM_COUNTER + SPECPARM_LIMIT
define_named_counters:
xor al,al
xchg al,[current_constituent]
test al,al
jz get_counter_name
cmp al,','
je get_counter_name
cmp al,1Ah
jne invalid_argument
mov esi,[symbol_start]
get_counter_name:
call identify_parameter_symbol
jc instruction_assembled
test ebx,ebx
jz invalid_argument
mov [label_leaf],ebx
call peek_at_constituent_value
jc counter_with_default_base
cmp al,':'
jne counter_with_default_base
and [current_constituent],0
call get_numeric_constant_value
test edx,edx
jz invalid_counter_base
mov ecx,[edx]
test byte [edx+4+ecx-1],80h
jns counter_base_ok
mov edx,_value_out_of_range
call register_error
jmp counter_with_default_base
invalid_counter_base:
mov edx,_invalid_value
call register_error
counter_with_default_base:
mov edx,singular_value
counter_base_ok:
push esi
mov esi,edx
mov edx,assembly_workspace
mov edi,[edx+Workspace.memory_start]
mov ecx,[esi]
add ecx,8
call reserve_workspace
mov eax,[current_counter]
sub eax,[counters_stack_base]
stosd
lodsd
mov ecx,eax
stosd
rep movsb
mov esi,[assembly_workspace.memory_start]
mov ecx,edi
sub ecx,esi
mov [value_type],VALTYPE_NUMERIC_SEQUENCE
mov ebx,[label_leaf]
mov edi,[directive_block]
call add_block_parameter
pop esi
jmp define_named_counters
invalid_count:
mov edx,_invalid_value
call register_error
jmp inactive_repeated_block
count_out_of_range:
mov edx,_value_out_of_range
call register_error
inactive_repeated_block:
xor esi,esi
mov dh,CTRL_REPEAT
jmp inactive_breakable_block
end_repeated_block:
mov dh,CTRL_REPEAT
close_repeat:
test [assembly_mode],AMODE_DEFINITION
jnz ignored_directive
mov dl,DBLOCK_CONTROL
call find_directive_block
jc unexpected_instruction
cmp dh,[edi+DirectiveBlock.subtype]
jne unexpected_instruction
test [assembly_mode],AMODE_SKIP
jnz end_control_block
mov edx,[current_counter]
movzx ecx,byte [edx]
inc edx
lea ebx,[edi-sizeof.RepeatData]
cmp ecx,[ebx+RepeatData.limit_length]
jne repeat_condition_upheld
sub ebx,ecx
compare_counter_with_limit:
mov al,[ebx]
cmp al,[edx]
jne repeat_condition_upheld
inc ebx
inc edx
loop compare_counter_with_limit
jmp end_control_block
iterator_block:
test [assembly_mode],AMODE_DEFINITION
jnz ignored_directive
test [assembly_mode],AMODE_SKIP
jnz inactive_iterator_block
xor eax,eax
mov [breakpoint_token],al
mov [number_of_parameters],eax
mov edi,[expression_workspace.memory_start]
call move_to_next_symbol
jc invalid_iterator
cmp al,'<'
jne iterator_parameter_declaration
inc esi
mov [breakpoint_token],'>'
iterator_parameter_declaration:
push edi
call identify_parameter_symbol
pop edi
jc invalid_iterator
test ebx,ebx
jz invalid_iterator
mov eax,[number_of_parameters]
shl eax,2
add eax,[assembly_stack_base]
lea ecx,[eax+4]
cmp ecx,[assembly_stack_end]
jbe store_parameter_leaf
mov eax,[assembly_stack_base]
sub ecx,eax
call grow_stack
mov [assembly_stack_base],eax
add ecx,eax
mov [assembly_stack_end],ecx
mov ecx,[number_of_parameters]
shl ecx,2
add eax,ecx
store_parameter_leaf:
mov [eax],ebx
mov edx,expression_workspace
mov ecx,sizeof.LineExcerpt
call reserve_workspace
mov [edi+LineExcerpt.data_start],esi
mov [edi+LineExcerpt.data_end],esi
inc [number_of_parameters]
call move_to_next_symbol
jc invalid_iterator
cmp al,':'
je parameter_with_default_value
cmp al,'='
je parameter_with_default_value
cmp al,'*'
jne parameter_declaration_done
and [edi+LineExcerpt.data_start],0
inc esi
call move_to_next_symbol
jc invalid_iterator
jmp parameter_declaration_done
parameter_with_default_value:
inc esi
call cut_argument_value
parameter_declaration_done:
add edi,sizeof.LineExcerpt
mov ah,[breakpoint_token]
test ah,ah
jz iterator_parameters_declared
inc esi
cmp al,','
je iterator_parameter_declaration
cmp al,ah
jne invalid_iterator
call move_to_next_symbol
jc invalid_iterator
iterator_parameters_declared:
cmp al,','
jne invalid_iterator
mov ebx,[number_of_parameters]
mov [number_of_values],ebx
and [number_of_iterations],0
collect_iterator_values:
inc esi
call move_to_next_symbol
jc initialize_iterator
mov edx,expression_workspace
mov ecx,sizeof.LineExcerpt
call reserve_workspace
call cut_argument_value
add edi,sizeof.LineExcerpt
inc [number_of_values]
cmp ebx,[number_of_parameters]
jne iterator_value_collected
inc [number_of_iterations]
xor ebx,ebx
iterator_value_collected:
inc ebx
cmp al,','
je collect_iterator_values
initialize_iterator:
cmp [number_of_iterations],0
je inactive_iterator_block
mov dl,DBLOCK_CONTROL
mov ecx,5+sizeof.RepeatData
call add_directive_block
mov [edi+DirectiveBlock.subtype],CTRL_IRP
or [edi+DirectiveBlock.flags],CTRLF_BREAKABLE + CTRLF_HAS_REPEAT_DATA + CTRLF_HAS_WRITABLE_INDEX
mov [directive_block],edi
bsr ecx,[number_of_iterations]
shr ecx,3
inc ecx
push esi
sub edi,sizeof.RepeatData
mov [edi+RepeatData.limit_length],ecx
sub edi,ecx
mov esi,number_of_iterations
rep movsb
mov ecx,[edi+RepeatData.limit_length]
add ecx,3
call allocate_counter
mov eax,ebx
sub eax,[counters_stack_base]
mov [edi+RepeatData.index_position],eax
mov ecx,[edi+RepeatData.limit_length]
mov edi,ebx
mov al,1
stosb
stosb
lea edi,[edi+ecx-1]
mov [current_counter],edi
stosb
stosb
mov ecx,[parameter_namespace]
mov [ecx+SymbolTree_Root.parameters],SPECPARM_COUNTER + SPECPARM_LIMIT
xor eax,eax
create_iterator_sequences:
mov [parameter_index],eax
mov edx,assembly_workspace
mov edi,[edx+Workspace.memory_start]
mov ecx,[number_of_iterations]
add ecx,2
shl ecx,2
call reserve_workspace
mov eax,[directive_block]
mov eax,[eax-sizeof.RepeatData+RepeatData.index_position]
stosd
mov eax,[number_of_iterations]
add eax,2
shl eax,2
stosd
mov [sequence_header_length],eax
mov edx,edi
mov edi,[assembly_workspace.memory_start]
sub edx,edi
mov [sequence_header_cursor],edx
add edi,eax
mov eax,[number_of_parameters]
add eax,[parameter_index]
cmp eax,[number_of_values]
jae copy_default_value
copy_individual_value:
mov [value_index],eax
mov ebx,eax
assert sizeof.LineExcerpt = 1 shl 4
shl ebx,4
add ebx,[expression_workspace.memory_start]
mov esi,[ebx+LineExcerpt.data_start]
mov ecx,[ebx+LineExcerpt.data_end]
sub ecx,esi
jnz individual_value_ready
copy_default_value:
mov ebx,[parameter_index]
assert sizeof.LineExcerpt = 1 shl 4
shl ebx,4
add ebx,[expression_workspace.memory_start]
mov esi,[ebx+LineExcerpt.data_start]
test esi,esi
jz missing_required_individual_value
mov ecx,[ebx+LineExcerpt.data_end]
sub ecx,esi
individual_value_ready:
mov edx,assembly_workspace
add ecx,2*(1+sizeof.RecognitionContext)
call reserve_workspace
mov ecx,[ebx+LineExcerpt.data_end]
sub ecx,esi
jz next_iterator_value
cmp [ebx+LineExcerpt.recognition_context],0
je copy_iterator_value
mov al,40h
stosb
mov eax,esi
mov edx,ecx
mov esi,[ebx+LineExcerpt.recognition_context]
assert sizeof.RecognitionContext and 11b = 0
mov ecx,sizeof.RecognitionContext shr 2
rep movsd
mov ecx,edx
mov esi,eax
copy_iterator_value:
rep movsb
mov eax,[ebx+LineExcerpt.recognition_context]
or eax,[ebx+LineExcerpt.leftover_context]
jz next_iterator_value
mov al,40h
stosb
xor eax,eax
assert sizeof.RecognitionContext and 11b = 0
mov ecx,sizeof.RecognitionContext shr 2
rep stosd
next_iterator_value:
mov edx,[assembly_workspace.memory_start]
mov ecx,edi
sub ecx,edx
add edx,[sequence_header_cursor]
mov [edx],ecx
add [sequence_header_cursor],4
mov eax,[value_index]
add eax,[number_of_parameters]
cmp eax,[number_of_values]
jb copy_individual_value
mov eax,[sequence_header_length]
sub eax,[sequence_header_cursor]
jne copy_default_value
mov ecx,edi
mov esi,[assembly_workspace.memory_start]
sub ecx,esi
mov eax,[parameter_index]
shl eax,2
add eax,[assembly_stack_base]
mov ebx,[eax]
mov edi,[directive_block]
mov [value_type],VALTYPE_SYMBOLIC_SEQUENCE
call add_block_parameter
mov eax,[parameter_index]
inc eax
cmp eax,[number_of_parameters]
jb create_iterator_sequences
pop esi
jmp instruction_assembled
missing_required_individual_value:
mov edx,_missing_argument
call register_error
jmp next_iterator_value
invalid_iterator:
mov edx,_invalid_argument
call register_error
inactive_iterator_block:
xor esi,esi
mov dh,CTRL_IRP
jmp inactive_breakable_block
end_iterator_block:
mov dh,CTRL_IRP
jmp close_repeat
variable_iterator_block:
test [assembly_mode],AMODE_DEFINITION
jnz ignored_directive
test [assembly_mode],AMODE_SKIP
jnz skipped_variable_iterator_block
call move_to_next_symbol
jc invalid_iterator
call identify_parameter_symbol
jc invalid_variable_iterator
test ebx,ebx
jz invalid_variable_iterator
mov [label_leaf],ebx
call move_to_next_symbol
jc invalid_variable_iterator
cmp al,','
jne invalid_variable_iterator
inc esi
and [symbol_definition],0
mov dl,SYMCLASS_EXPRESSION
call identify_symbol
jc invalid_variable_identifier
test ebx,ebx
jz invalid_variable_identifier
mov eax,[current_pass]
mov [ebx+SymbolTree_Leaf.last_use_pass],eax
mov edi,[assembly_stack_base]
xor ecx,ecx
mov [number_of_values],ecx
mov edx,[ebx+SymbolTree_Leaf.definition]
collect_variable_values:
test edx,edx
jz variable_values_collected
mov eax,[edx+ValueDefinition.pass]
cmp eax,[current_pass]
jne variable_values_collected
cmp [edx+ValueDefinition.type],VALTYPE_RESERVED
je skip_variable_value
add edi,4
cmp edi,[assembly_stack_end]
jbe store_variable_value
push ecx edx
mov eax,[assembly_stack_base]
sub edi,eax
mov ecx,edi
call grow_stack
add edi,eax
mov [assembly_stack_base],eax
add eax,ecx
mov [assembly_stack_end],eax
pop edx ecx
store_variable_value:
mov [edi-4],edx
inc [number_of_values]
add ecx,[edx+ValueDefinition.value_length]
add ecx,1+sizeof.RecognitionContext
skip_variable_value:
mov edx,[edx+ValueDefinition.previous]
jmp collect_variable_values
variable_values_collected:
mov eax,[number_of_values]
test eax,eax
jz inactive_variable_iterator_block
add eax,2
shl eax,2
add ecx,eax
mov edx,assembly_workspace
mov edi,[edx+Workspace.memory_start]
call reserve_workspace
mov dl,DBLOCK_CONTROL
mov ecx,5+sizeof.RepeatData
call add_directive_block
mov [edi+DirectiveBlock.subtype],CTRL_IRPV
or [edi+DirectiveBlock.flags],CTRLF_BREAKABLE + CTRLF_HAS_REPEAT_DATA + CTRLF_HAS_WRITABLE_INDEX
mov [directive_block],edi
bsr ecx,[number_of_values]
shr ecx,3
inc ecx
push esi
sub edi,sizeof.RepeatData
mov [edi+RepeatData.limit_length],ecx
sub edi,ecx
mov esi,number_of_values
rep movsb
mov ecx,[edi+RepeatData.limit_length]
add ecx,3
call allocate_counter
mov eax,ebx
sub eax,[counters_stack_base]
mov [edi+RepeatData.index_position],eax
mov ecx,[edi+RepeatData.limit_length]
mov edi,ebx
mov al,1
stosb
stosb
lea edi,[edi+ecx-1]
mov [current_counter],edi
stosb
stosb
mov ecx,[parameter_namespace]
mov [ecx+SymbolTree_Root.parameters],SPECPARM_COUNTER + SPECPARM_LIMIT
mov edi,[assembly_workspace.memory_start]
mov ecx,[number_of_values]
mov edx,ecx
add ecx,2
shl ecx,2
mov ebx,edi
add edi,ecx
mov eax,[directive_block]
mov eax,[eax-sizeof.RepeatData+RepeatData.index_position]
mov [ebx],eax
add ebx,4
mov [ebx],ecx
create_value_sequence:
mov eax,edx
dec eax
shl eax,2
add eax,[assembly_stack_base]
mov eax,[eax]
push edx
mov cl,[eax+ValueDefinition.type]
cmp cl,VALTYPE_SYMBOLIC
je symbolic_value_in_sequence
cmp cl,VALTYPE_NUMERIC
jne proxy_value_in_sequence
mov esi,[eax+ValueDefinition.value]
mov ecx,[esi]
add esi,4
test byte [esi+ecx-1],80h
jnz proxy_value_in_sequence
cmp dword [esi+ecx],0
jne proxy_value_in_sequence
push ecx
add ecx,1+4
call allocate_value_in_sequence
pop ecx
mov al,30h
stosb
mov eax,ecx
stosd
rep movsb
jmp next_value_in_sequence
allocate_value_in_sequence:
mov eax,[ebx]
add eax,ecx
add ebx,4
mov [ebx],eax
mov edx,assembly_workspace
sub ebx,[edx+Workspace.memory_start]
call reserve_workspace
add ebx,[assembly_workspace.memory_start]
retn
proxy_value_in_sequence:
mov esi,eax
mov ecx,(1+sizeof.RecognitionContext)*2+1
call allocate_value_in_sequence
push ebx edi
push esi
xor eax,eax
mov ecx,[proxy_number]
inc [proxy_number]
mov dl,SYMCLASS_EXPRESSION
mov ebx,[current_context.base_namespace]
call get_abstract_symbol
xchg edx,[esp]
call update_value_link
pop edx
pop edi ebx
mov al,40h
stosb
mov eax,[current_context.base_namespace]
mov [edi+RecognitionContext.base_namespace],eax
mov [edi+RecognitionContext.base_label],edx
add edi,sizeof.RecognitionContext
mov al,'.'
stosb
jmp close_symbolic_value_in_sequence
symbolic_value_in_sequence:
mov esi,[eax+ValueDefinition.value]
mov ecx,[eax+ValueDefinition.value_length]
push ecx
add ecx,1+sizeof.RecognitionContext
call allocate_value_in_sequence
pop ecx
rep movsb
close_symbolic_value_in_sequence:
mov al,40h
stosb
xor eax,eax
assert sizeof.RecognitionContext and 11b = 0
mov ecx,sizeof.RecognitionContext shr 2
rep stosd
next_value_in_sequence:
pop edx
dec edx
jnz create_value_sequence
mov esi,[assembly_workspace.memory_start]
mov ecx,edi
sub ecx,esi
mov ebx,[label_leaf]
mov edi,[directive_block]
mov [value_type],VALTYPE_SYMBOLIC_SEQUENCE
call add_block_parameter
pop esi
jmp instruction_assembled
invalid_variable_identifier:
mov edx,_invalid_identifier
call register_error
jmp inactive_variable_iterator_block
invalid_variable_iterator:
mov edx,_invalid_argument
call register_error
skipped_variable_iterator_block:
xor esi,esi
inactive_variable_iterator_block:
mov dh,CTRL_IRPV
jmp inactive_breakable_block
end_variable_iterator_block:
mov dh,CTRL_IRPV
jmp close_repeat
set_iterator_index:
mov dl,DBLOCK_CONTROL
call find_directive_block
jc unexpected_instruction
find_indexable_block:
test [edi+DirectiveBlock.flags],CTRLF_HAS_WRITABLE_INDEX
jnz indexable_block_found
call find_next_directive_block
jc unexpected_instruction
jmp find_indexable_block
indexable_block_found:
; test [edi+DirectiveBlock.flags],CTRLF_HAS_REPEAT_DATA
; jnz internal_error
mov [directive_block],edi
call get_numeric_constant_value
test edx,edx
jz invalid_argument
mov ecx,[edx]
add edx,4
mov al,[edx+ecx-1]
test al,al
js value_out_of_range
jnz index_optimized
optimize_index:
test ecx,ecx
jz value_out_of_range
dec ecx
mov al,[edx+ecx-1]
test al,al
jz optimize_index
index_optimized:
mov edi,[directive_block]
sub edi,sizeof.RepeatData
mov ebx,[edi+RepeatData.limit_length]
cmp ecx,ebx
ja value_out_of_range
jb index_ok
sub edi,ebx
compare_index_with_limit:
mov al,[edx+ebx-1]
cmp al,[edi+ebx-1]
ja value_out_of_range
jb index_ok
dec ebx
jnz compare_index_with_limit
index_ok:
xchg esi,edx
mov edi,[directive_block]
mov edi,[edi-sizeof.RepeatData+RepeatData.index_position]
add edi,[counters_stack_base]
mov al,cl
stosb
rep movsb
mov esi,edx
jmp instruction_assembled
break_directive:
mov dl,DBLOCK_CONTROL
call find_directive_block
jc unexpected_instruction
find_block_to_break:
test [edi+DirectiveBlock.flags],CTRLF_BREAKABLE
jnz block_to_break_found
call find_next_directive_block
jc unexpected_instruction
jmp find_block_to_break
block_to_break_found:
or [assembly_mode],AMODE_SKIP
mov dl,DBLOCK_CONTROL
call find_directive_block
break_blocks:
or [edi+DirectiveBlock.flags],CTRLF_INACTIVE
test [edi+DirectiveBlock.flags],CTRLF_BREAKABLE
jnz disable_counter
or [edi+DirectiveBlock.prior_assembly_mode],AMODE_SKIP
call find_next_directive_block
jc unexpected_instruction
jmp break_blocks
disable_counter:
mov edi,[current_counter]
xor al,al
stosb
jmp instruction_assembled
else_directive:
mov edx,[ebx+SymbolTree_Leaf.branch]
call get_symbol_namespace
and [symbol_definition],0
mov dl,SYMCLASS_INSTRUCTION
call identify_symbol_in_namespace
jc plain_else
test ebx,ebx
jz invalid_else
mov al,[ebx+SymbolTree_Leaf.class]
cmp al,SYMCLASS_INSTRUCTION
jne invalid_else
call get_available_value
jc invalid_else
jmp prefixed_directive
invalid_else:
mov esi,[symbol_start]
plain_else:
test [assembly_mode],AMODE_DEFINITION
jnz ignored_directive
mov dl,DBLOCK_CONTROL
call find_directive_block
jc unexpected_instruction
test [edi+DirectiveBlock.flags],CTRLF_ALLOWS_ELSE
jz unexpected_instruction
and [edi+DirectiveBlock.flags],not CTRLF_ALLOWS_ELSE
call remove_block_parameters
test [edi+DirectiveBlock.flags],CTRLF_INACTIVE
jnz assembly_line
xor [assembly_mode],AMODE_SKIP
jmp instruction_assembled
end_directive:
mov edx,[ebx+SymbolTree_Leaf.branch]
call get_symbol_namespace
and [symbol_definition],0
mov dl,SYMCLASS_INSTRUCTION
call identify_symbol_in_namespace
jc missing_prefixed_directive
test ebx,ebx
jz invalid_prefixed_directive
mov al,[ebx+SymbolTree_Leaf.class]
cmp al,SYMCLASS_INSTRUCTION
jne invalid_prefixed_directive
call get_available_value
jc invalid_prefixed_directive
prefixed_directive:
test [edx+ValueDefinition.flags],VAL_UNCONDITIONAL
jnz execute_prefixed_directive
test [assembly_mode],AMODE_SKIP
jnz assembly_line
test [assembly_mode],AMODE_DEFINITION
jnz add_line_to_macro
execute_prefixed_directive:
mov al,[edx+ValueDefinition.type]
cmp al,VALTYPE_CALM
je launch_calm
cmp al,VALTYPE_SYMBOLIC
je use_macro
cmp al,VALTYPE_NATIVE_COMMAND
jne invalid_argument
jmp [edx+ValueDefinition.value]
missing_prefixed_directive:
test [assembly_mode],AMODE_SKIP
jnz assembly_line
test [assembly_mode],AMODE_DEFINITION
jnz add_line_to_macro
cmp [interceptor],0
jne execute_interceptor
jmp missing_argument
invalid_prefixed_directive:
test [assembly_mode],AMODE_SKIP
jnz assembly_line
test [assembly_mode],AMODE_DEFINITION
jnz add_line_to_macro
cmp [interceptor],0
jne execute_interceptor
jmp invalid_argument
raw_match_block:
mov bl,CTRL_RMATCH
jmp begin_match_block
match_block:
mov bl,CTRL_MATCH
begin_match_block:
test [assembly_mode],AMODE_DEFINITION
jnz ignored_directive
cmp bl,CTRL_RMATCH
sete [unprocessed_matching]
mov dl,DBLOCK_CONTROL
xor ecx,ecx
call add_directive_block
mov [directive_block],edi
mov [edi+DirectiveBlock.subtype],bl
or [edi+DirectiveBlock.flags],CTRLF_ALLOWS_ELSE
test [assembly_mode],AMODE_SKIP
jnz skip_conditional_block
evaluate_match:
mov [pattern_start],esi
and [number_of_parameters],0
get_match_pattern:
call move_to_next_symbol
jc invalid_match
qualify_pattern_element:
cmp al,','
je match_pattern_ok
cmp al,1Ah
je count_pattern_parameter
cmp al,30h
je invalid_match
cmp al,'='
jne skip_pattern_symbol
call skip_token
xor ecx,ecx
call move_to_next_symbol
jc invalid_match
test ecx,ecx
jz skip_pattern_symbol
jmp qualify_pattern_element
count_pattern_parameter:
call detect_numeric_symbol
jc invalid_match
inc [number_of_parameters]
add esi,1+4
jmp get_match_pattern
skip_pattern_symbol:
call skip_token
jmp get_match_pattern
match_pattern_ok:
mov [pattern_end],esi
inc esi
mov [argument_start],esi
mov eax,[embedded_context]
mov [matched_context],eax
mov edi,[expression_workspace.memory_start]
mov ecx,[number_of_parameters]
assert sizeof.MatchedParameter = 1 shl 3
shl ecx,3
mov ebx,ecx
mov edx,expression_workspace
call reserve_workspace
add edi,ebx
mov [substitutions_end],edi
cmp [unprocessed_matching],0
jne substitutions_ready
detect_substitutions:
mov eax,[embedded_context]
mov [stored_context],eax
and [symbol_definition],0
mov dl,SYMCLASS_EXPRESSION
call identify_symbol
jc substitutions_ready
test edi,edi
jnz check_for_substitution
call skip_literal
xor ebx,ebx
check_for_substitution:
test ebx,ebx
jz detect_substitutions
call get_available_value
jc detect_substitutions
cmp [edx+ValueDefinition.type],VALTYPE_SYMBOLIC
jne detect_substitutions
mov eax,[current_pass]
mov [ebx+SymbolTree_Leaf.last_use_pass],eax
mov ebx,edx
mov edi,[substitutions_end]
mov edx,expression_workspace
mov ecx,sizeof.SymbolSubstitution
call reserve_workspace
mov eax,[ebx+ValueDefinition.value]
mov [edi+SymbolSubstitution.value_start],eax
add eax,[ebx+ValueDefinition.value_length]
mov [edi+SymbolSubstitution.value_end],eax
mov ebx,esi
mov esi,[symbol_start]
mov [edi+SymbolSubstitution.symbol_start],esi
scan_replaced_symbol:
mov al,[esi]
cmp al,20h
je whitespace_in_replaced_symbol
cmp al,40h
jne actual_replaced_symbol
inc esi
mov [stored_context],esi
add esi,sizeof.RecognitionContext
jmp next_token_in_replaced_symbol
whitespace_in_replaced_symbol:
inc esi
jmp next_token_in_replaced_symbol
actual_replaced_symbol:
call skip_token
mov ecx,esi
mov edx,[stored_context]
next_token_in_replaced_symbol:
cmp esi,ebx
jb scan_replaced_symbol
mov [edi+SymbolSubstitution.symbol_end],ecx
mov [edi+SymbolSubstitution.leftover_context],edx
add edi,sizeof.SymbolSubstitution
mov [substitutions_end],edi
jmp detect_substitutions
substitutions_ready:
mov ebx,[number_of_parameters]
assert sizeof.MatchedParameter = 1 shl 3
shl ebx,3
add ebx,[expression_workspace.memory_start]
mov esi,[argument_start]
mov edi,[pattern_start]
xor eax,eax
mov [parameter_index],eax
mov [stored_position],eax
mov [substitution_active],al
match_with_pattern:
call get_pattern_token
cmp ah,1Ah
jne exact_match
wildcard_match:
call get_matched_token
jc no_match
cmp al,20h
jne wildcard_matched
inc esi
jmp wildcard_match
wildcard_matched:
xor eax,eax
mov edx,[expression_workspace.memory_start]
mov ecx,[parameter_index]
jecxz prepare_matched_parameter
dec ecx
assert sizeof.MatchedParameter = 1 shl 3
shl ecx,3
add edx,ecx
push edi
mov edi,[assembly_workspace.memory_start]
add edi,[edx+MatchedParameter.assembly_position]
push edx
call close_matched_value
pop edx
mov eax,edi
sub eax,[assembly_workspace.memory_start]
mov [edx+MatchedParameter.assembly_position],eax
pop edi
add edx,sizeof.MatchedParameter
prepare_matched_parameter:
mov [edx+MatchedParameter.pattern],edi
inc [parameter_index]
mov edi,[assembly_workspace.memory_start]
add edi,eax
xor eax,eax
mov [embedded_context],eax
mov [stored_position],eax
mov [whitespace_matching],al
push edx
call copy_matched_token
pop edx
sub edi,[assembly_workspace.memory_start]
mov [edx+MatchedParameter.assembly_position],edi
mov edi,[edx+MatchedParameter.pattern]
add edi,1+4
call get_pattern_token
cmp ah,1Ah
je wildcard_match
cmp ah,'?'
jne exact_match
inc edi
jmp match_with_pattern
exact_match:
cmp [stored_position],0
jne match_position_stored
mov [stored_position],esi
mov [stored_substitution],ebx
mov dl,[substitution_active]
mov [stored_substitution_activity],dl
mov ecx,[matched_context]
mov [stored_context],ecx
mov [stored_pattern],edi
or [whitespace_matching],1
match_position_stored:
cmp ah,','
je end_of_pattern
cmp ah,20h
je allow_whitespace
cmp ah,'='
jne match_tokens
inc edi
call get_pattern_token
match_tokens:
call get_matched_token
jc no_match
cmp al,20h
je match_whitespace
and [whitespace_matching],0
cmpsb
jne token_mismatch
cmp ah,1Ah
je match_name_tokens
cmp ah,22h
je match_string_tokens
cmp ah,27h
je match_string_tokens
cmp ah,30h
jne match_with_pattern
mov ecx,esi
mov edx,edi
lodsd
add esi,eax
mov eax,[edi]
lea edi,[edi+4+eax]
call get_pattern_token
cmp ah,'?'
jne compare_token_contents
inc edi
jmp compare_token_contents
match_string_tokens:
lodsd
mov ecx,eax
mov edx,[edi]
add edi,4
compare_token_contents:
cmp ecx,edx
je match_with_pattern
push esi edi
mov esi,ecx
mov edi,edx
mov ecx,[esi]
add ecx,4
repe cmpsb
pop edi esi
jne retract_match
jmp match_with_pattern
match_name_tokens:
lodsd
mov ecx,eax
mov edx,[edi]
add edi,4
call get_pattern_token
cmp ah,'?'
je case_insensitive_match
cmp ecx,edx
je match_with_pattern
push esi edi
mov esi,ecx
mov edi,edx
lodsd
scasd
jne name_mismatch
mov ecx,eax
mov eax,[esi+ecx]
cmp eax,[edi+ecx]
jne name_mismatch
repe cmpsb
jne name_mismatch
pop edi esi
jmp match_with_pattern
name_mismatch:
pop edi esi
jmp retract_match
case_insensitive_match:
inc edi
cmp ecx,edx
je match_with_pattern
push esi edi
mov esi,ecx
mov edi,edx
lodsd
scasd
jne name_mismatch
mov ecx,eax
mov eax,[esi+ecx+4]
cmp eax,[edi+ecx+4]
jne name_mismatch
xor eax,eax
compare_case_insensitively:
lodsb
mov dl,[characters+eax]
mov al,[edi]
inc edi
cmp dl,[characters+eax]
jne name_mismatch
loop compare_case_insensitively
pop edi esi
jmp match_with_pattern
match_converted_number:
call convert_number_to_match
jmp compare_token_contents
match_with_converted_number:
xchg esi,edi
call convert_number_to_match
xchg esi,edi
jmp compare_token_contents
convert_number_to_match:
mov edx,esi
lodsd
add esi,eax
push ebx esi edi
call convert_number_back
pop edi esi ebx
mov ecx,[edi]
add edi,4
retn
token_mismatch:
cmp ax,1A30h
je match_converted_number
cmp ax,301Ah
je match_with_converted_number
retract_match:
xor esi,esi
xchg esi,[stored_position]
test esi,esi
jz no_match
mov ebx,[stored_substitution]
mov dl,[stored_substitution_activity]
mov [substitution_active],dl
mov ecx,[stored_context]
mov [matched_context],ecx
mov edi,[stored_pattern]
and [whitespace_matching],0
mov edx,[parameter_index]
sub edx,1
jc no_match
assert sizeof.MatchedParameter = 1 shl 3
shl edx,3
add edx,[expression_workspace.memory_start]
push edi
mov edi,[assembly_workspace.memory_start]
add edi,[edx+MatchedParameter.assembly_position]
push edx
copy_whitespace:
call get_matched_token
jc no_match
cmp al,20h
jne copy_additional_symbol
call copy_matched_token
jmp copy_whitespace
copy_additional_symbol:
call copy_matched_token
pop edx
sub edi,[assembly_workspace.memory_start]
mov [edx+MatchedParameter.assembly_position],edi
pop edi
jmp match_with_pattern
match_whitespace:
cmp al,ah
je required_whitespace
cmp [whitespace_matching],0
je retract_match
inc esi
jmp match_tokens
required_whitespace:
inc esi
allow_whitespace:
inc edi
or [whitespace_matching],1
jmp match_with_pattern
end_of_pattern:
call get_matched_token
jc pattern_matched
cmp al,20h
jne retract_match
call skip_token
jmp end_of_pattern
pattern_matched:
mov ebx,[parameter_index]
sub ebx,1
jc matching_done
assert sizeof.MatchedParameter = 1 shl 3
shl ebx,3
add ebx,[expression_workspace.memory_start]
mov edi,[assembly_workspace.memory_start]
add edi,[ebx+MatchedParameter.assembly_position]
call close_matched_value
sub edi,[assembly_workspace.memory_start]
mov [ebx+MatchedParameter.assembly_position],edi
matching_done:
cmp [number_of_parameters],0
je assembly_line
mov [symbol_class],SYMCLASS_PARAMETER
and [name_volatile],0
and [name_token],0
or [symbol_required],1
or [symbol_expected],1
mov [value_type],VALTYPE_SYMBOLIC
xor eax,eax
mov [value_index],eax
define_matched_parameters:
mov [parameter_index],eax
assert sizeof.MatchedParameter = 1 shl 3
shl eax,3
add eax,[expression_workspace.memory_start]
mov edi,[eax+MatchedParameter.pattern]
mov esi,[edi+1]
lodsd
mov ecx,eax
add edi,1+4
call get_pattern_token
mov edx,[esi+ecx]
mov al,NAME_CASESENSITIVE
cmp ah,'?'
jne matched_name_kind_ok
mov edx,[esi+ecx+4]
mov al,NAME_CASEINSENSITIVE
matched_name_kind_ok:
mov [name_kind],al
mov ebx,[parameter_namespace]
call scan_namespace
mov eax,[parameter_index]
assert sizeof.MatchedParameter = 1 shl 3
shl eax,3
add eax,[expression_workspace.memory_start]
mov ecx,[eax+MatchedParameter.assembly_position]
mov esi,ecx
xchg esi,[value_index]
sub ecx,esi
add esi,[assembly_workspace.memory_start]
mov edi,[directive_block]
call add_block_parameter
mov eax,[parameter_index]
inc eax
cmp eax,[number_of_parameters]
jb define_matched_parameters
jmp assembly_line
no_match:
or [assembly_mode],AMODE_SKIP
jmp assembly_line
invalid_match:
mov edx,_invalid_argument
call register_error
or [assembly_mode],AMODE_SKIP
jmp assembly_line
get_pattern_token:
mov ah,[edi]
cmp ah,40h
je skip_pattern_context
retn
skip_pattern_context:
add edi,1+sizeof.RecognitionContext
jmp get_pattern_token
get_matched_token:
cmp ebx,[substitutions_end]
je token_in_line
cmp [substitution_active],0
jne token_in_substitution
cmp esi,[ebx+SymbolSubstitution.symbol_start]
je substitution_encountered
token_in_line:
cmp esi,[line_end]
je no_more_matched_tokens
check_for_matched_token:
mov al,[esi]
cmp al,40h
je matched_context_change
clc
retn
no_more_matched_tokens:
stc
retn
matched_context_change:
inc esi
cmp [unprocessed_matching],0
jne matched_context_change_done
mov [matched_context],esi
matched_context_change_done:
add esi,sizeof.RecognitionContext
jmp get_matched_token
substitution_encountered:
mov esi,[ebx+SymbolSubstitution.value_start]
and [matched_context],0
or [substitution_active],1
token_in_substitution:
cmp esi,[ebx+SymbolSubstitution.value_end]
jb check_for_matched_token
mov esi,[ebx+SymbolSubstitution.symbol_end]
mov ecx,[ebx+SymbolSubstitution.leftover_context]
mov [matched_context],ecx
add ebx,sizeof.SymbolSubstitution
and [substitution_active],0
jmp get_matched_token
skip_token:
inc esi
cmp al,1Ah
je skip_token_with_data
cmp al,22h
je skip_token_with_data
cmp al,27h
je skip_token_with_data
cmp al,30h
je skip_internal_token
cmp al,40h
je skip_context_token
retn
skip_token_with_data:
add esi,4
retn
skip_internal_token:
lodsd
add esi,eax
retn
skip_context_token:
add esi,sizeof.RecognitionContext
retn
copy_matched_token:
mov edx,[matched_context]
cmp edx,[embedded_context]
je matched_context_ok
test edx,edx
jz copy_matched_context
mov eax,[edx]
test eax,eax
jnz copy_matched_context
mov [matched_context],eax
cmp eax,[embedded_context]
je matched_context_ok
mov edx,eax
copy_matched_context:
mov [embedded_context],edx
mov ecx,1+sizeof.RecognitionContext
mov edx,assembly_workspace
call reserve_workspace
mov al,40h
stosb
assert sizeof.RecognitionContext and 11b = 0
mov ecx,sizeof.RecognitionContext shr 2
mov edx,[matched_context]
test edx,edx
jz clear_matched_context
xchg esi,edx
rep movsd
mov esi,edx
jmp matched_context_ok
clear_matched_context:
xor eax,eax
rep stosd
matched_context_ok:
mov ecx,1+4
mov edx,assembly_workspace
call reserve_workspace
lodsb
stosb
cmp al,1Ah
je copy_token_with_data
cmp al,22h
je copy_token_with_data
cmp al,27h
je copy_token_with_data
cmp al,30h
je copy_internal_token
retn
copy_token_with_data:
movsd
retn
copy_internal_token:
mov ecx,[esi]
add ecx,4
mov edx,assembly_workspace
call reserve_workspace
lodsd
stosd
mov ecx,eax
rep movsb
retn
close_matched_value:
mov eax,[embedded_context]
test eax,eax
jz matched_value_closed
mov ecx,1+sizeof.RecognitionContext
mov edx,assembly_workspace
call reserve_workspace
mov al,40h
stosb
xor eax,eax
assert sizeof.RecognitionContext and 11b = 0
mov ecx,sizeof.RecognitionContext shr 2
rep stosd
matched_value_closed:
retn
else_raw_match_block:
mov bl,CTRL_RMATCH
jmp begin_else_match_block
else_match_block:
mov bl,CTRL_MATCH
begin_else_match_block:
test [assembly_mode],AMODE_DEFINITION
jnz ignored_directive
mov dl,DBLOCK_CONTROL
call find_directive_block
jc unexpected_instruction
mov al,[edi+DirectiveBlock.flags]
test al,CTRLF_ALLOWS_ELSE
jz unexpected_instruction
mov ah,[assembly_mode]
push eax ebx
call close_control_directive_block
mov dl,DBLOCK_CONTROL
xor ecx,ecx
call add_directive_block
mov [directive_block],edi
pop ebx eax
cmp bl,CTRL_RMATCH
sete [unprocessed_matching]
mov [edi+DirectiveBlock.subtype],bl
or [edi+DirectiveBlock.flags],CTRLF_ALLOWS_ELSE
test al,CTRLF_INACTIVE
jnz skip_conditional_block
test ah,AMODE_SKIP
jnz evaluate_match
jmp skip_conditional_block
end_raw_match_block:
mov bl,CTRL_RMATCH
jmp close_match_block
end_match_block:
mov bl,CTRL_MATCH
close_match_block:
test [assembly_mode],AMODE_DEFINITION
jnz ignored_directive
mov dl,DBLOCK_CONTROL
call find_directive_block
jc unexpected_instruction
cmp [edi+DirectiveBlock.subtype],bl
jne unexpected_instruction
call close_control_directive_block
jmp instruction_assembled
postponed_block:
test [assembly_mode],AMODE_DEFINITION
jnz ignored_directive
mov dl,DBLOCK_CONTROL
xor ecx,ecx
call add_directive_block
mov [edi+DirectiveBlock.subtype],CTRL_POSTPONE
mov [directive_block],edi
or [assembly_mode],AMODE_SKIP
call get_constituent_value
jc instruction_assembled
cmp al,'?'
jne invalid_argument
mov edi,[directive_block]
or [edi+DirectiveBlock.flags],CTRLF_SUSPENDED
jmp instruction_assembled
end_postponed_block:
test [assembly_mode],AMODE_DEFINITION
jnz ignored_directive
mov dl,DBLOCK_CONTROL
call find_directive_block
jc end_postponed_execution
cmp [edi+DirectiveBlock.subtype],CTRL_POSTPONE
jne unexpected_instruction
mov al,[edi+DirectiveBlock.prior_assembly_mode]
mov [assembly_mode],al
test al,AMODE_SKIP
jz keep_postponed_block
call close_directive_block
jmp instruction_assembled
keep_postponed_block:
test [edi+DirectiveBlock.flags],CTRLF_SUSPENDED
jnz keep_suspended_block
mov [edi+DirectiveBlock.type],DBLOCK_POSTPONED
jmp instruction_assembled
keep_suspended_block:
mov [edi+DirectiveBlock.type],DBLOCK_SUSPENDED
jmp instruction_assembled
end_postponed_execution:
test [assembly_mode],AMODE_POSTPONED
jz unexpected_instruction
mov eax,[source_context]
mov esi,eax
call release_source_context
and [esi+SourceContext.number_of_entries],0
jmp pass_done
define_struc:
mov bl,SYMCLASS_STRUCTURE
jmp begin_macro_definition
define_macro:
mov bl,SYMCLASS_INSTRUCTION
begin_macro_definition:
test [assembly_mode],AMODE_DEFINITION
jnz nested_macro_definition
mov dl,DBLOCK_MACRO
mov ecx,sizeof.MacroData
call add_directive_block
mov [edi+DirectiveBlock.subtype],bl
mov [edi-sizeof.MacroData+MacroData.nesting_counter],1
xor eax,eax
mov [macro_end_position],eax
mov [macro_definition_active],al
or [assembly_mode],AMODE_DEFINITION
test [assembly_mode],AMODE_SKIP
jnz assembly_line
xor ecx,ecx
call move_to_next_symbol
jc invalid_macro_definition
cmp al,'('
je macro_with_label_parameter
read_macro_name:
mov dl,bl
call get_macro_definition_symbol
jc invalid_identifier
mov [argument_start],esi
mov eax,[embedded_context]
mov [macro_parameters_context],eax
xor ecx,ecx
call move_to_next_symbol
jc macro_parameters_correct
check_macro_parameters:
cmp al,'&'
jne macro_parameter_prefix_ok
inc esi
call move_to_next_symbol
jc invalid_macro_definition
macro_parameter_prefix_ok:
cmp al,'#'
jne check_parameter_name
call check_concatenation
jnc check_macro_parameters
invalid_macro_definition:
mov edx,_invalid_argument
call register_error
jmp assembly_line
check_parameter_name:
cmp al,'?'
je parameter_starting_question_mark
cmp al,1Ah
jne invalid_macro_definition
call detect_numeric_symbol
jc invalid_macro_definition
parameter_name_token:
inc esi
lodsd
parameter_name_present:
xor ecx,ecx
call move_to_next_symbol
jc macro_parameters_correct
cmp al,'?'
je check_parameter_name_modifier
cmp al,'#'
jne check_parameter_modifiers
call check_concatenation
jnc check_parameter_name_concatenation
call move_to_next_symbol
jc macro_parameters_correct
jmp check_parameter_modifiers
parameter_starting_question_mark:
inc esi
parameter_name_freeform:
call move_to_next_symbol
jc macro_parameters_correct
cmp al,1Ah
je parameter_name_token
cmp al,'#'
je parameter_name_freeform_concatenation
cmp al,30h
jne invalid_macro_definition
parameter_number_token:
inc esi
lodsd
add esi,eax
jmp parameter_name_present
parameter_name_freeform_concatenation:
call check_concatenation
jc invalid_macro_definition
jmp parameter_name_freeform
check_parameter_name_concatenation:
cmp al,1Ah
je parameter_name_token
cmp al,30h
je parameter_number_token
cmp al,'?'
jne check_parameter_modifiers
check_parameter_name_modifier:
inc esi
call move_to_next_symbol
jc macro_parameters_correct
check_parameter_modifiers:
cmp al,':'
je check_default_value
cmp al,'='
je check_default_value
cmp al,'*'
jne check_next_parameter
inc esi
call move_to_next_symbol
jnc check_next_parameter
jmp macro_parameters_correct
check_default_value:
mov edi,[expression_workspace.memory_start]
inc esi
call move_to_next_symbol
jc check_plain_default_value
cmp al,'<'
je check_enclosed_default_value
check_plain_default_value:
mov dl,','
xor dh,dh
mov [breakpoint_token],'&'
call cut_piece_of_line
jmp check_next_parameter
check_enclosed_default_value:
inc esi
mov dl,'>'
mov dh,'<'
mov [breakpoint_token],0
call cut_piece_of_line
cmp al,'>'
jne invalid_macro_definition
inc esi
call move_to_next_symbol
jc macro_parameters_correct
check_next_parameter:
test al,al
jz macro_parameters_correct
inc esi
cmp al,','
jne check_final_parameter_modifiers
call move_to_next_symbol
jc invalid_macro_definition
jmp check_macro_parameters
check_final_parameter_modifiers:
cmp al,'&'
jne invalid_macro_definition
call move_to_next_symbol
jnc invalid_macro_definition
macro_parameters_correct:
or [macro_definition_active],1
cmp [macro_parameters_context],0
je store_macro_header
xor esi,esi
mov ecx,1+sizeof.RecognitionContext
call append_to_macro
mov al,40h
stosb
mov esi,[macro_parameters_context]
assert sizeof.RecognitionContext and 11b = 0
mov ecx,sizeof.RecognitionContext shr 2
rep movsd
store_macro_header:
mov esi,[argument_start]
mov ecx,[line_end]
sub ecx,esi
call append_to_macro
call add_line_break_to_macro
jmp instruction_assembled
nested_macro_definition:
mov dl,DBLOCK_MACRO
call find_directive_block
; jc internal_error
cmp bl,[edi+DirectiveBlock.subtype]
jne add_nested_macro_block
inc [edi-sizeof.MacroData+MacroData.nesting_counter]
jmp add_line_to_macro
add_nested_macro_block:
mov ecx,sizeof.MacroData
call add_directive_block
mov [edi+DirectiveBlock.subtype],bl
mov [edi-sizeof.MacroData+MacroData.nesting_counter],1
jmp add_line_to_macro
macro_with_label_parameter:
cmp bl,SYMCLASS_STRUCTURE
jne invalid_macro_definition
mov [argument_start],esi
inc esi
xor ecx,ecx
call move_to_next_symbol
jc invalid_macro_definition
cmp al,'&'
jne check_label_parameter_initial_concatenation
inc esi
call move_to_next_symbol
jc invalid_macro_definition
check_label_parameter_initial_concatenation:
cmp al,'#'
jne check_label_parameter_name
call check_concatenation
jnc check_label_parameter_initial_concatenation
jmp invalid_macro_definition
check_label_parameter_name:
cmp al,1Ah
jne invalid_macro_definition
call detect_numeric_symbol
jc invalid_macro_definition
label_parameter_name_present:
inc esi
lodsd
xor ecx,ecx
call move_to_next_symbol
jc invalid_macro_definition
cmp al,'?'
je check_label_parameter_name_modifier
cmp al,'#'
jne label_parameter_name_end
call check_concatenation
jnc check_label_parameter_name_concatenation
call move_to_next_symbol
jc invalid_macro_definition
jmp label_parameter_name_end
check_label_parameter_name_concatenation:
cmp al,1Ah
je label_parameter_name_present
cmp al,'?'
jne label_parameter_name_end
check_label_parameter_name_modifier:
inc esi
call move_to_next_symbol
jc invalid_macro_definition
label_parameter_name_end:
inc esi
cmp al,')'
jne invalid_macro_definition
push esi
or [macro_definition_active],1
mov ecx,esi
mov esi,[argument_start]
sub ecx,esi
call append_to_macro
and [macro_definition_active],0
pop esi
xor ecx,ecx
call move_to_next_symbol
jc invalid_macro_definition
jmp read_macro_name
end_struc:
mov bl,SYMCLASS_STRUCTURE
jmp close_macro_block
end_macro:
mov bl,SYMCLASS_INSTRUCTION
close_macro_block:
mov dl,DBLOCK_MACRO
call find_directive_block
jc unexpected_instruction
cmp bl,[edi+DirectiveBlock.subtype]
je close_macro_definition
; handle improper nesting, for partial backward-compatibility:
cmp bl,SYMCLASS_INSTRUCTION
jne add_line_to_macro
call close_directive_block
mov dl,DBLOCK_MACRO
call find_directive_block
jc unexpected_instruction
; cmp [edi+DirectiveBlock.subtype],SYMCLASS_INSTRUCTION
; jne internal_error
close_macro_definition:
dec [edi-sizeof.MacroData+MacroData.nesting_counter]
jnz add_line_to_macro
mov al,[assembly_mode]
and al,not (AMODE_SKIP or AMODE_DEFINITION)
or al,[edi+DirectiveBlock.prior_assembly_mode]
mov [assembly_mode],al
call close_directive_block
mov al,[assembly_mode]
test al,AMODE_DEFINITION
jne add_line_to_macro
test al,AMODE_SKIP
jnz assembly_line
push esi
cmp [macro_definition_active],0
je macro_definition_done
mov ebx,[macro_leaf]
call create_value_definition
test edx,edx
jz macro_definition_done
mov [value],eax
mov [value_length],ecx
mov esi,[macro_buffer]
mov ecx,[macro_end_position]
mov [value_type],VALTYPE_SYMBOLIC
call assign_value
mov al,[macro_flags]
or [edx+ValueDefinition.flags],al
macro_definition_done:
pop esi
jmp instruction_assembled
escape_directive:
mov dl,DBLOCK_MACRO
call find_directive_block
jc unexpected_instruction
cmp [edi-sizeof.MacroData+MacroData.nesting_counter],1
ja add_line_to_macro
test [edi+DirectiveBlock.prior_assembly_mode],AMODE_DEFINITION
jnz add_line_to_macro
cmp [embedded_context],0
je escape_context_ok
push esi
xor esi,esi
mov ecx,1+sizeof.RecognitionContext
call append_to_macro
mov al,40h
stosb
mov esi,[embedded_context]
assert sizeof.RecognitionContext and 11b = 0
mov ecx,sizeof.RecognitionContext shr 2
rep movsd
pop esi
escape_context_ok:
mov ecx,[line_end]
sub ecx,esi
call append_to_macro
call add_line_break_to_macro
jmp assembly_line
add_line_to_macro:
mov esi,[line_start]
mov ecx,[line_end]
sub ecx,esi
call append_to_macro
call add_line_break_to_macro
jmp assembly_line
append_to_macro:
cmp [macro_definition_active],0
je macro_appended
mov edi,[macro_buffer]
mov eax,[macro_end_position]
add edi,eax
add eax,ecx
mov [macro_end_position],eax
cmp eax,[macro_buffer_length]
jbe macro_block_ready
push ecx
mov ecx,eax
mov eax,[macro_buffer]
sub edi,eax
call realloc
add edi,eax
mov [macro_buffer],eax
mov [macro_buffer_length],ecx
pop ecx
macro_block_ready:
test esi,esi
jz macro_appended
rep movsb
macro_appended:
retn
add_label_to_macro:
mov ecx,esi
xchg esi,[line_start]
sub ecx,esi
call append_to_macro
mov esi,[line_start]
cmp esi,[line_end]
jne assemble_instruction
call add_line_break_to_macro
jmp assemble_instruction
add_line_break_to_macro:
mov eax,[macro_buffer]
mov ecx,[macro_end_position]
cmp ecx,[macro_buffer_length]
jb macro_line_break
add ecx,100h
call realloc
mov [macro_buffer],eax
mov [macro_buffer_length],ecx
mov ecx,[macro_end_position]
macro_line_break:
lea edi,[eax+ecx]
xor al,al
stosb
inc [macro_end_position]
retn
use_macro:
and [label_branch],0
use_struc:
mov eax,[current_pass]
mov [ebx+SymbolTree_Leaf.last_use_pass],eax
mov [instruction_value],edx
mov eax,[ebx+SymbolTree_Leaf.branch]
mov [instruction_branch],eax
xor ecx,ecx
call embed_symbolic_value
measure_macro_header:
lodsb
test al,al
jz macro_header_measured
cmp al,1Ah
je measure_token_with_data
cmp al,22h
je measure_token_with_data
cmp al,27h
je measure_token_with_data
cmp al,30h
je measure_internal_token
cmp al,40h
jne measure_macro_header
add esi,sizeof.RecognitionContext
jmp measure_macro_header
measure_token_with_data:
add esi,4
jmp measure_macro_header
measure_internal_token:
lodsd
add esi,eax
jmp measure_macro_header
macro_header_measured:
mov [instruction_body],esi
dec esi
mov [line_end],esi
mov eax,ebx
mov ecx,[parameter_namespace]
call get_local_anchor
call get_local_namespace
mov [new_local_namespace],ebx
mov eax,[parameter_namespace]
mov [ebx+SymbolTree_Root.chain],eax
mov edx,[instruction_value]
local_namespace_ready:
mov esi,[edx+ValueDefinition.value]
or [symbol_definition],1
mov ebx,[new_local_namespace]
mov eax,[label_branch]
mov [ebx+SymbolTree_Root.current_label],eax
cmp [label_independent],0
je struc_label_ok
or [ebx+SymbolTree_Root.flags],NAMESPACE_LABEL_FORWARDING
struc_label_ok:
cmp byte [esi],'('
jne prepare_macro_parameters
inc esi
call move_to_next_symbol
jc invalid_argument
test [assembly_mode],AMODE_DEFINITION
setnz dl
cmp al,'&'
sete al
jne struc_label_prefix_ok
inc esi
struc_label_prefix_ok:
or al,dl
mov [contextless_processing],al
mov ebx,[new_local_namespace]
mov dl,SYMCLASS_PARAMETER
call identify_symbol_in_namespace
jc invalid_argument
test ebx,ebx
jz invalid_argument
cmp edi,[new_local_namespace]
jne invalid_argument
push esi
push [line_end]
push [embedded_context]
mov eax,[line_context]
mov [embedded_context],eax
mov esi,[line_start]
mov ecx,[label_instruction_start]
mov [line_end],ecx
sub ecx,esi
add ecx,(1+sizeof.RecognitionContext)*2
mov edx,assembly_workspace
mov edi,[edx+Workspace.memory_start]
call reserve_workspace
xor edx,edx
mov [breakpoint_token],dl
call extract_piece_of_line
call finish_extracted_parameter
pop [embedded_context]
pop [line_end]
or [ebx+SymbolTree_Leaf.flags],SYM_VARIABLE
call update_value_definition
mov [value_type],VALTYPE_SYMBOLIC
mov esi,[assembly_workspace.memory_start]
mov ecx,edi
sub ecx,esi
call assign_value
pop esi
call move_to_next_symbol
jc invalid_argument
cmp al,')'
jne invalid_argument
inc esi
prepare_macro_parameters:
mov edi,[expression_workspace.memory_start]
add edi,sizeof.LineExcerpt
xor eax,eax
mov [macro_greedy],al
mov [number_of_parameters],eax
macro_parameter_declaration:
call move_to_next_symbol
jc macro_parameters_declared
cmp al,'&'
sete al
mov [contextless_processing],al
jne identify_macro_parameter_name
inc esi
identify_macro_parameter_name:
mov ebx,[new_local_namespace]
mov dl,SYMCLASS_PARAMETER
push edi
call identify_symbol_in_namespace
mov eax,edi
pop edi
jc macro_parameters_declared
test ebx,ebx
jz invalid_argument
cmp eax,[new_local_namespace]
jne invalid_argument
mov eax,[number_of_parameters]
shl eax,3
add eax,[assembly_stack_base]
lea ecx,[eax+8]
cmp ecx,[assembly_stack_end]
jbe store_macro_parameter_leaf
mov eax,[assembly_stack_base]
sub ecx,eax
call grow_stack
mov [assembly_stack_base],eax
add ecx,eax
mov [assembly_stack_end],ecx
mov ecx,[number_of_parameters]
shl ecx,3
add eax,ecx
store_macro_parameter_leaf:
mov [eax],ebx
mov cl,[contextless_processing]
mov [eax+4],cl
mov edx,expression_workspace
mov ecx,sizeof.LineExcerpt
call reserve_workspace
mov [edi+LineExcerpt.data_start],esi
mov [edi+LineExcerpt.data_end],esi
inc [number_of_parameters]
call move_to_next_symbol
jc macro_parameters_declared
cmp al,':'
je macro_parameter_with_default_value
cmp al,'='
je macro_parameter_with_default_value
cmp al,'*'
jne next_parameter_declaration
and [edi+LineExcerpt.data_start],0
inc esi
call move_to_next_symbol
jnc next_parameter_declaration
xor al,al
jmp next_parameter_declaration
macro_parameter_with_default_value:
inc esi
call move_to_next_symbol
jc get_plain_default_value
cmp al,'<'
je get_enclosed_default_value
get_plain_default_value:
mov dl,','
xor dh,dh
mov [breakpoint_token],'&'
call cut_piece_of_line
jmp next_parameter_declaration
get_enclosed_default_value:
inc esi
mov dl,'>'
mov dh,'<'
mov [breakpoint_token],0
call cut_piece_of_line
cmp al,'>'
jne invalid_argument
inc esi
call move_to_next_symbol
jc macro_parameters_declared
next_parameter_declaration:
test al,al
jz macro_parameters_declared
inc esi
add edi,sizeof.LineExcerpt
cmp al,','
je macro_parameter_declaration
cmp al,'&'
jne invalid_argument
or [macro_greedy],1
call move_to_next_symbol
jnc invalid_argument
macro_parameters_declared:
call warp_to_next_symbol
; cmp [number_of_line_embeddings],0
; jne internal_error
mov edx,assembly_workspace
mov edi,[edx+Workspace.memory_start]
mov ecx,[line_end]
sub ecx,esi
add ecx,(1+sizeof.RecognitionContext)*2
call reserve_workspace
xor eax,eax
mov [breakpoint_token],al
mov [parameter_index],eax
macro_parameter_definition:
mov eax,[number_of_parameters]
sub eax,[parameter_index]
jz macro_parameters_ready
jmp get_macro_parameter
macro_parameter_after_comma:
mov eax,[number_of_parameters]
sub eax,[parameter_index]
jz macro_parameters_ready
inc esi
get_macro_parameter:
mov edi,[assembly_workspace.memory_start]
mov ecx,[parameter_index]
shl ecx,3
add ecx,[assembly_stack_base]
mov ebx,[ecx]
test [assembly_mode],AMODE_DEFINITION
setnz dl
or dl,[ecx+4]
mov [contextless_processing],dl
cmp [macro_greedy],0
je standard_parameter_value
cmp eax,1
ja standard_parameter_value
xor edx,edx
call extract_piece_of_line
jmp parameter_value_ready
standard_parameter_value:
call extract_argument_value
parameter_value_ready:
or [ebx+SymbolTree_Leaf.flags],SYM_VARIABLE
call update_value_definition
mov [value_type],VALTYPE_SYMBOLIC
cmp edi,[assembly_workspace.memory_start]
je empty_parameter_value
call finish_extracted_parameter
push esi
mov esi,[assembly_workspace.memory_start]
mov ecx,edi
sub ecx,esi
assign_parameter_value:
call assign_value
pop esi
parameter_value_assigned:
inc [parameter_index]
call move_to_next_symbol
jc macro_parameter_definition
cmp al,','
je macro_parameter_after_comma
macro_parameters_ready:
mov edx,[instruction_value]
mov ecx,[instruction_body]
sub ecx,[edx+ValueDefinition.value]
push ecx
call create_source_entry
pop eax
jc stack_limit_exceeded
mov [ebx+SourceEntry.type],SOURCE_MACRO
mov [ebx+SourceEntry.text],edx
mov [ebx+SourceEntry.offset],eax
or [edx+ValueDefinition.flags],VAL_IN_USE
inc [edx+ValueDefinition.reference_count]
mov eax,[new_local_namespace]
mov [local_namespace],eax
and [eax+SymbolTree_Root.parameters],0
mov [ebx+SourceEntry.local_namespace],eax
mov ecx,[instruction_branch]
test ecx,ecx
jz instruction_assembled
mov [ebx+SourceEntry.name],ecx
or [ebx+SourceEntry.name_length],-1
jmp instruction_assembled
stack_limit_exceeded:
mov edx,_stack_limit_exceeded
call register_error
test [assembly_mode],AMODE_SKIP
jnz assembly_line
test [assembly_mode],AMODE_DEFINITION
jz assembly_line
jmp add_line_to_macro
empty_parameter_value:
mov edi,[parameter_index]
inc edi
assert sizeof.LineExcerpt = 1 shl 4
shl edi,4
add edi,[expression_workspace.memory_start]
mov eax,[edi+LineExcerpt.data_start]
test eax,eax
jz missing_argument
mov ecx,[edi+LineExcerpt.data_end]
sub ecx,eax
push esi
mov esi,eax
test ecx,ecx
jz assign_parameter_value
push ebx edx
mov ebx,edi
mov edi,[assembly_workspace.memory_start]
add ecx,2*(1+sizeof.RecognitionContext)
mov edx,assembly_workspace
call reserve_workspace
mov al,40h
cmp [ebx+LineExcerpt.recognition_context],0
je parameter_with_current_context
stosb
mov eax,esi
mov esi,[ebx+LineExcerpt.recognition_context]
assert sizeof.RecognitionContext and 11b = 0
mov ecx,sizeof.RecognitionContext shr 2
rep movsd
mov [context_boundary],edi
mov esi,eax
jmp copy_parameter_contents
parameter_with_current_context:
cmp [contextless_processing],0
jne copy_parameter_contents
stosb
call store_current_context
copy_parameter_contents:
call store_token
cmp esi,[ebx+LineExcerpt.data_end]
jne copy_parameter_contents
call store_context_reset_token
pop edx ebx
mov esi,[assembly_workspace.memory_start]
mov ecx,edi
sub ecx,esi
jmp assign_parameter_value
finish_extracted_parameter:
test [assembly_mode],AMODE_DEFINITION
jz store_context_reset_token
cmp [embedded_context],0
jne store_context_reset_token
retn
store_context_reset_token:
cmp edi,[context_boundary]
je context_reset_in_reused_token
mov al,40h
stosb
store_context_reset:
xor eax,eax
assert sizeof.RecognitionContext and 11b = 0
mov ecx,sizeof.RecognitionContext shr 2
rep stosd
retn
context_reset_in_reused_token:
sub edi,sizeof.RecognitionContext
jmp store_context_reset
local_directive:
test [assembly_mode],AMODE_SKIP
jnz assembly_line
test [assembly_mode],AMODE_DEFINITION
jnz add_line_to_macro
mov ebx,[local_namespace]
test ebx,ebx
jz unexpected_instruction
or [symbol_definition],1
mov dl,SYMCLASS_PARAMETER
call identify_symbol_in_namespace
jc missing_argument
test ebx,ebx
jz invalid_argument
cmp edi,[local_namespace]
jne invalid_argument
or [ebx+SymbolTree_Leaf.flags],SYM_VARIABLE
call update_value_definition
mov eax,[current_pass]
mov [edx+ValueDefinition.pass],eax
mov [edx+ValueDefinition.type],VALTYPE_NATIVE_COMMAND
mov eax,local_symbol_name
xchg eax,[edx+ValueDefinition.value]
cmp [edx+ValueDefinition.block_length],0
je next_local_declaration
and [edx+ValueDefinition.block_length],0
call mfree
next_local_declaration:
call move_to_next_symbol
jc assembly_line
cmp al,','
jne invalid_argument
inc esi
jmp local_directive
outscope_directive:
test [assembly_mode],AMODE_SKIP
jnz assemble_prefixed_instruction
mov ebx,[source_context]
mov eax,[ebx+SourceContext.number_of_entries]
dec eax
imul eax,sizeof.SourceEntry
lea ebx,[ebx+sizeof.SourceContext+eax]
test [assembly_mode],AMODE_DEFINITION
jnz define_outscope
mov ecx,[ebx+SourceEntry.local_namespace]
test [ecx+SymbolTree_Root.flags],NAMESPACE_UNATTACHED
jnz unexpected_instruction
mov eax,[ecx+SymbolTree_Root.chain]
test eax,eax
jz unexpected_instruction
outscope_namespace_ok:
mov [parameter_namespace],eax
test [eax+SymbolTree_Root.flags],NAMESPACE_UNATTACHED
jz outscope_local_namespace_ok
xor eax,eax
outscope_local_namespace_ok:
mov [local_namespace],eax
assemble_prefixed_instruction:
mov [line_start],esi
mov eax,[embedded_context]
mov [line_context],eax
jmp assemble_instruction
define_outscope:
cmp [ebx+SourceEntry.type],SOURCE_MACRO
je assemble_prefixed_instruction
jmp ignored_directive
define_data:
and [label_leaf],0
define_labeled_data:
movzx eax,[edx+ValueDefinition.attribute]
mov [data_unit_length],eax
test eax,eax
jnz data_unit_length_ok
call get_numeric_constant_value
test edx,edx
jz invalid_argument
mov ecx,4
mov edi,data_unit_length
call fit_value
jc value_out_of_range
js value_out_of_range
cmp [data_unit_length],0
je value_out_of_range
call get_constituent_value
jc missing_argument
cmp al,':'
je data_unit_length_ok
cmp al,','
jne invalid_argument
data_unit_length_ok:
cmp [label_leaf],0
je data_definition
call define_data_label
data_definition:
call peek_at_constituent_value
jc missing_argument
cmp al,'?'
je single_uninitialized_unit
call get_constant_value
cmp al,30h
je numeric_data
cmp al,2Eh
je float_data
cmp al,22h
jne invalid_argument
call output_string
data_outputted:
call get_constituent_value
jc instruction_assembled
cmp al,','
jne invalid_argument
jmp data_definition
float_data:
push esi
push edx
mov ecx,[data_unit_length]
call initialize_output
pop esi
mov ecx,[data_unit_length]
call fit_float
pop esi
jmp data_outputted
numeric_data:
call keep_value
call peek_at_constituent_value
jc single_data_unit
cmp al,1Ah
jne single_data_unit
test edx,edx
jz single_data_unit
cmp [edx+ValueDefinition.type],VALTYPE_NATIVE_PREPOSITION
jne single_data_unit
cmp [edx+ValueDefinition.value],PREPOSITION_DUP
je duplication_operator
single_data_unit:
mov ecx,[data_unit_length]
call initialize_output
call get_kept_value
mov ecx,[data_unit_length]
call fit_value
jc value_out_of_range
jmp data_outputted
single_uninitialized_unit:
and [current_constituent],0
mov ecx,[data_unit_length]
call uninitialized_output
jmp data_outputted
duplication_operator:
call get_kept_value
mov edi,number_of_iterations
mov ecx,4
call fit_value
jc value_out_of_range
js value_out_of_range
xor eax,eax
mov [current_constituent],al
mov [initial_parentheses],eax
call peek_at_constituent_value
jc invalid_argument
cmp al,'?'
je reserve_through_duplication
mov edi,[expression_workspace.memory_start]
mov [expression_sequence_end],edi
or [leave_opening_parentheses],1
parse_duplicated_expression:
call parse_expression
add [initial_parentheses],ecx
jecxz duplicated_value_parsed
mov eax,[expression_workspace.memory_start]
mov eax,[eax]
test eax,eax
jnz duplicated_value_parsed
call get_constituent_value
jc invalid_argument
cmp al,'?'
jne invalid_argument
mov edi,[expression_workspace.memory_start]
or eax,-1
stosd
duplicated_value_parsed:
mov [expression_sequence_end],edi
and [leave_opening_parentheses],0
cmp [initial_parentheses],1
jb duplicated_data_parsed
ja invalid_argument
call get_constituent_value
jc missing_closing_parenthesis
cmp al,')'
je duplicated_data_parsed
cmp al,','
jne invalid_argument
mov edi,[expression_sequence_end]
call peek_at_constituent_value
jc invalid_argument
mov edi,[expression_sequence_end]
cmp al,'?'
jne parse_duplicated_expression
and [current_constituent],0
mov ecx,4
mov edx,expression_workspace
call reserve_workspace
or eax,-1
stosd
jmp duplicated_value_parsed
duplicated_data_parsed:
cmp [number_of_iterations],0
je data_outputted
duplicated_data:
mov eax,[expression_workspace.memory_start]
mov [expression_sequence_cursor],eax
generate_duplicate:
mov eax,[expression_sequence_cursor]
cmp eax,[expression_sequence_end]
je duplicate_outputted
cmp dword [eax],-1
je duplicated_uninitialized_unit
push esi
mov esi,eax
mov edi,[calculation_workspace.memory_start]
call calculate_parsed_expression
mov [expression_sequence_cursor],esi
pop esi
jc duplicate_outputted
call pop_terms
jc invalid_argument
call get_calculated_constant_value
cmp al,30h
je duplicated_data_unit
cmp al,2Eh
je duplicated_data_unit
cmp al,22h
jne invalid_argument
call output_string
jmp generate_duplicate
duplicated_data_unit:
push eax edx
mov ecx,[data_unit_length]
call initialize_output
pop edx eax
mov ecx,[data_unit_length]
cmp al,2Eh
je duplicated_float
call fit_value
jc value_out_of_range
jmp generate_duplicate
duplicated_float:
push esi
mov esi,edx
call fit_float
pop esi
jmp generate_duplicate
duplicated_uninitialized_unit:
add eax,4
mov [expression_sequence_cursor],eax
mov ecx,[data_unit_length]
call uninitialized_output
jmp generate_duplicate
duplicate_outputted:
dec [number_of_iterations]
jnz duplicated_data
jmp data_outputted
reserve_through_duplication:
and [current_constituent],0
mov eax,[number_of_iterations]
mul [data_unit_length]
test edx,edx
jnz duplication_overflow
mov ecx,eax
call uninitialized_output
jmp data_outputted
duplication_overflow:
mov edx,_area_overflow
call register_error
jmp data_outputted
output_string:
push esi
mov esi,edx
mov ecx,[esi]
call initialize_output
lodsd
mov ecx,eax
rep movsb
pop esi
mov ecx,[data_unit_length]
xor edx,edx
div ecx
test edx,edx
jz string_outputted
sub ecx,edx
push ecx
call initialize_output
pop ecx
xor al,al
rep stosb
string_outputted:
retn
define_data_label:
push esi
call get_current_address_value
lea edi,[esi+ecx]
mov ecx,4+4+4
mov edx,assembly_workspace
call reserve_workspace
mov edx,[data_unit_length]
bsr eax,edx
inc al
shr al,3
inc al
stosd
mov [edi],edx
add edi,eax
xor eax,eax
stosd
mov ebx,[label_leaf]
call create_constant_value_definition
test edx,edx
jz data_label_defined
mov ecx,edi
sub ecx,esi
call assign_shiftable_value
data_label_defined:
call update_current_label
pop esi
retn
reserve_labeled_data:
movzx eax,[edx+ValueDefinition.attribute]
mov [data_unit_length],eax
call define_data_label
jmp data_reservation
reserve_data:
movzx eax,[edx+ValueDefinition.attribute]
mov [data_unit_length],eax
data_reservation:
call get_numeric_constant_value
test edx,edx
jz invalid_argument
mov ecx,4
mov edi,[assembly_workspace.memory_start]
call fit_value
jc reservation_out_of_range
js reservation_out_of_range
mov eax,[edi]
mul [data_unit_length]
test edx,edx
jnz reservation_overflow
mov ecx,eax
call uninitialized_output
jmp instruction_assembled
reservation_out_of_range:
mov edx,_value_out_of_range
call register_error
jmp instruction_assembled
reservation_overflow:
mov edx,_area_overflow
call register_error
jmp instruction_assembled
include_labeled_data:
mov [data_unit_length],1
call define_data_label
include_data:
xor eax,eax
mov [data_offset],eax
mov [data_offset+4],eax
call get_constant_value
cmp al,22h
jne invalid_argument
push esi
call prepare_file_path
pop esi
call get_constituent_value
jc include_all_available_data
cmp al,':'
jne get_data_length
call get_numeric_constant_value
test edx,edx
jz invalid_argument
mov edi,file_offset
mov ecx,8
call fit_value
jc value_out_of_range
js value_out_of_range
call get_constituent_value
jc include_all_available_data
get_data_length:
cmp al,','
jne invalid_argument
call get_numeric_constant_value
test edx,edx
jz invalid_argument
mov edi,data_length
mov ecx,4
call fit_value
jc value_out_of_range
js value_out_of_range
push esi
mov ecx,[data_length]
call initialize_output
mov esi,[assembly_workspace.memory_start]
call get_file_data
test ebx,ebx
jnz read_from_file
mov esi,[local_path]
call get_file_data
test ebx,ebx
jz data_file_not_found
read_from_file:
call read_file_data
jc file_data_not_read
pop esi
jmp instruction_assembled
data_file_not_found:
mov ebx,esi
mov edx,_source_file_not_found
call register_error
pop esi
jmp instruction_assembled
include_all_available_data:
push esi
mov esi,[assembly_workspace.memory_start]
call get_file_data
test ebx,ebx
jnz measure_available_data
mov esi,[local_path]
call get_file_data
test ebx,ebx
jz data_file_not_found
measure_available_data:
mov ecx,dword [ebx+FileData.length]
mov edx,dword [ebx+FileData.length+4]
sub ecx,dword [file_offset]
sbb edx,dword [file_offset+4]
jc file_data_not_read
jnz out_of_memory
mov [data_length],ecx
push ebx
call initialize_output
pop ebx
call read_file_data
jc file_data_not_read
pop esi
jmp instruction_assembled
file_data_not_read:
mov ebx,esi
mov edx,_error_reading_file
call register_error
pop esi
jmp instruction_assembled
load_value:
or [symbol_definition],1
mov dl,SYMCLASS_EXPRESSION
call identify_symbol
jc missing_argument
test ebx,ebx
jz invalid_identifier
mov [label_leaf],ebx
mov [size_specified],0
call peek_at_constituent_value
jc load_syntax_error
cmp al,':'
je size_after_separator
cmp al,1Ah
jne get_load_size
test edx,edx
jz get_load_size
cmp [edx+ValueDefinition.type],VALTYPE_NATIVE_PREPOSITION
jne get_load_size
cmp [edx+ValueDefinition.value],PREPOSITION_FROM
jne load_syntax_error
and [current_constituent],0
jmp get_source_address
size_after_separator:
and [current_constituent],0
get_load_size:
call get_numeric_constant_value
test edx,edx
jz load_syntax_error
or [size_specified],1
mov edi,value_length
mov ecx,4
call fit_value
jc value_out_of_range
js value_out_of_range
call get_constituent_value
jc load_syntax_error
cmp al,1Ah
jne load_syntax_error
test edx,edx
jz load_syntax_error
cmp [edx+ValueDefinition.type],VALTYPE_NATIVE_PREPOSITION
jne load_syntax_error
cmp [edx+ValueDefinition.value],PREPOSITION_FROM
jne load_syntax_error
get_source_address:
call peek_at_constituent_value
jc invalid_argument
cmp al,':'
je load_from_output_offset
mov eax,[current_area]
mov [data_area],eax
and [data_area_symbol],0
and [leave_opening_parentheses],0
mov edi,[expression_workspace.memory_start]
call parse_expression
call peek_at_constituent_value
jc source_address_parsed
cmp al,':'
jne source_address_parsed
and [current_constituent],0
mov edi,[expression_workspace.memory_start]
call get_area_value
jc invalid_area
mov [data_area],edx
mov [data_area_symbol],ebx
mov edi,[expression_workspace.memory_start]
call parse_expression
source_address_parsed:
call calculate_relative_address
jc invalid_argument
mov edi,data_offset
mov ecx,4
call fit_value
jc data_out_of_area
js data_out_of_area
mov edx,assembly_workspace
mov edi,[edx+Workspace.memory_start]
mov eax,[value_length]
stosd
mov ecx,eax
call reserve_workspace
mov edx,[data_area]
call load_from_area
jc loaded_no_value
value_loaded:
mov ebx,[label_leaf]
call update_value_definition
test edx,edx
jz instruction_assembled
push esi
mov esi,[assembly_workspace.memory_start]
mov ecx,[esi]
add ecx,4
mov [value_type],VALTYPE_STRING
call assign_value
pop esi
jmp instruction_assembled
load_syntax_error:
mov edx,_invalid_argument
jmp error_while_loading
data_out_of_area:
mov edx,_address_out_of_range
error_while_loading:
call register_error
loaded_no_value:
mov edi,[assembly_workspace.memory_start]
xor eax,eax
stosd
jmp value_loaded
calculate_relative_address:
push esi
mov esi,[expression_workspace.memory_start]
mov edi,[calculation_workspace.memory_start]
call calculate_parsed_expression
jc invalid_relative_address
mov ebx,edi
mov edi,[expression_workspace.memory_start]
mov esi,edi
mov eax,EXPR_SYMBOL_VALUE
stosd
mov edx,[data_area]
mov eax,[data_area_symbol]
test eax,eax
jnz data_area_symbol_ok
mov eax,[void_symbol]
mov [eax+SymbolTree_Leaf.definition],edx
data_area_symbol_ok:
stosd
mov eax,edx
stosd
mov eax,EXPR_OPERATOR
stosd
mov eax,extract_first_term_metadata
stosd
mov eax,EXPR_OPERATOR
stosd
mov eax,calculate_sub
stosd
xor eax,eax
stosd
mov edi,ebx
call calculate_parsed_expression
jc invalid_relative_address
call pop_terms
jc invalid_relative_address
cmp [size_specified],0
jne addressed_length_ok
and [value_length],0
mov edx,[edi+ExpressionTerm.metadata]
test edx,edx
jz addressed_length_ok
cmp dword [edx],0
jne addressed_length_ok
add edx,4
mov esi,edi
mov ecx,4
mov edi,value_length
call fit_value
jc invalid_relative_address
js invalid_relative_address
mov ecx,[edx]
cmp dword [edx+4+ecx],0
jne invalid_relative_address
mov edi,esi
addressed_length_ok:
pop esi
mov eax,edi
check_for_uncanceled_terms:
add eax,sizeof.ExpressionTerm
cmp [eax+ExpressionTerm.attributes],0
je relative_address_ok
cmp [eax+ExpressionTerm.metadata],0
je check_for_uncanceled_terms
mov edx,_address_out_of_range
call register_error
relative_address_ok:
call get_term_value
clc
retn
invalid_relative_address:
pop esi
stc
retn
load_from_output_offset:
call read_output_offset
jc value_out_of_range
mov edx,assembly_workspace
mov edi,[edx+Workspace.memory_start]
mov eax,[value_length]
stosd
mov ecx,eax
call reserve_workspace
push esi
call read_from_output
pop esi
cmp [value_length],0
jne data_out_of_area
jmp value_loaded
read_output_offset:
and [current_constituent],0
call get_numeric_constant_value
test edx,edx
jz output_offset_out_of_range
push edi
mov edi,file_offset
mov ecx,8
call fit_value
pop edi
jc output_offset_out_of_range
js output_offset_out_of_range
cmp [size_specified],0
jne output_offset_ok
and [value_length],0
mov edx,[edi+ExpressionTerm.metadata]
test edx,edx
jz output_offset_ok
cmp dword [edx],0
jne output_offset_ok
add edx,4
mov ecx,4
mov edi,value_length
call fit_value
jc output_offset_out_of_range
js output_offset_out_of_range
output_offset_ok:
clc
retn
output_offset_out_of_range:
stc
retn
store_value:
mov [size_specified],0
call get_constant_value
cmp al,22h
je store_string_value
cmp al,30h
jne invalid_argument
call keep_value
call peek_at_constituent_value
jc invalid_argument
cmp al,':'
je size_after_value
cmp al,1Ah
jne size_before_value
test edx,edx
jz invalid_argument
cmp [edx+ValueDefinition.type],VALTYPE_NATIVE_PREPOSITION
je get_destination_address
size_before_value:
or [size_specified],1
call get_kept_value
mov edi,value_length
mov ecx,4
call fit_value
jc value_out_of_range
js value_out_of_range
call get_constant_value
cmp al,22h
je value_after_size_ok
cmp al,30h
jne invalid_argument
value_after_size_ok:
call keep_value
jmp value_with_size_ready
store_string_value:
mov eax,[edx]
mov [value_length],eax
call keep_value
call peek_at_constituent_value
jc invalid_argument
cmp al,':'
jne check_symbol_after_value_with_size
size_after_value:
and [current_constituent],0
call get_constant_value
cmp al,30h
jne invalid_argument
or [size_specified],1
mov edi,value_length
mov ecx,4
call fit_value
jc value_out_of_range
js value_out_of_range
value_with_size_ready:
call peek_at_constituent_value
jc invalid_argument
check_symbol_after_value_with_size:
cmp al,1Ah
jne invalid_argument
test edx,edx
jz invalid_argument
cmp [edx+ValueDefinition.type],VALTYPE_NATIVE_PREPOSITION
jne invalid_argument
get_destination_address:
cmp [edx+ValueDefinition.value],PREPOSITION_AT
jne invalid_argument
and [current_constituent],0
call peek_at_constituent_value
jc invalid_argument
cmp al,':'
je store_at_output_offset
mov eax,[current_area]
mov [data_area],eax
and [data_area_symbol],0
and [leave_opening_parentheses],0
mov edi,[expression_workspace.memory_start]
call parse_expression
call peek_at_constituent_value
jc destination_address_parsed
cmp al,':'
jne destination_address_parsed
and [current_constituent],0
mov edi,[expression_workspace.memory_start]
call get_area_value
jc invalid_area
mov ecx,[current_pass]
cmp [edx+ValueDefinition.pass],ecx
jne invalid_area
mov [data_area],edx
mov [data_area_symbol],ebx
mov edi,[expression_workspace.memory_start]
call parse_expression
destination_address_parsed:
call calculate_relative_address
jc invalid_argument
mov edi,data_offset
mov ecx,4
call fit_value
jc store_out_of_area
js store_out_of_area
call prepare_area_to_write
call get_kept_value
call fit_value
jc value_out_of_range
jmp instruction_assembled
store_out_of_area:
mov edx,_address_out_of_range
call register_error
jmp instruction_assembled
store_at_output_offset:
call read_output_offset
jc value_out_of_range
mov ecx,[value_length]
mov edx,assembly_workspace
mov edi,[edx+Workspace.memory_start]
call reserve_workspace
call get_kept_value
mov ecx,[value_length]
call fit_value
jc value_out_of_range
push esi
mov esi,[assembly_workspace.memory_start]
call rewrite_output
pop esi
cmp [value_length],0
jne store_out_of_area
jmp instruction_assembled
display_data:
call get_constant_value
cmp al,30h
je display_character_data
cmp al,22h
jne invalid_argument
call display_string_data
display_next_value:
call get_constituent_value
jc assembly_line
cmp al,','
jne invalid_argument
jmp display_data
display_character_data:
call display_single_byte_data
jmp display_next_value
format_directive:
mov edx,[ebx+SymbolTree_Leaf.branch]
call get_symbol_namespace
and [symbol_definition],0
mov dl,SYMCLASS_INSTRUCTION
call identify_symbol_in_namespace
jc invalid_argument
test ebx,ebx
jz invalid_argument
mov al,[ebx+SymbolTree_Leaf.class]
cmp al,SYMCLASS_INSTRUCTION
jne invalid_argument
call get_available_value
jc invalid_argument
jmp prefixed_directive
format_binary:
call get_constituent_value
jc instruction_assembled
cmp al,1Ah
jne invalid_argument
test edx,edx
jz invalid_argument
cmp [edx+ValueDefinition.type],VALTYPE_NATIVE_PREPOSITION
jne invalid_argument
cmp [edx+ValueDefinition.value],PREPOSITION_AS
jne invalid_argument
cmp [output_extension],0
jne repeated_declaration
call get_constant_value
cmp al,22h
jne invalid_argument
mov edi,esi
mov ecx,[edx]
lea esi,[edx+4]
mov [output_extension_length],ecx
mov ebx,[auxiliary_output_areas]
call get_from_map
jnc extension_stored
xor eax,eax
mov ecx,[output_extension_length]
call put_into_map
extension_stored:
mov [output_extension],esi
validate_extension:
mov ebx,characters
scan_extension:
test ecx,ecx
jz extension_valid
lodsb
xlatb
test al,al
jz invalid_argument
dec ecx
jmp scan_extension
extension_valid:
mov esi,edi
jmp instruction_assembled
custom_error:
mov edi,[assembly_workspace.memory_start]
add edi,4
create_custom_error_message:
push edi
call get_constant_value
pop edi
cmp al,30h
je attach_byte_to_error_message
cmp al,22h
jne invalid_argument
mov ebx,edx
mov ecx,[edx]
mov edx,assembly_workspace
call reserve_workspace
mov edx,esi
lea esi,[ebx+4]
mov ecx,[ebx]
rep movsb
mov esi,edx
jmp collect_next_part_of_message
attach_byte_to_error_message:
mov ebx,edx
mov ecx,1
mov edx,assembly_workspace
call reserve_workspace
mov edx,ebx
mov ecx,1
call fit_value
jc value_out_of_range
inc edi
collect_next_part_of_message:
push edi
call get_constituent_value
pop edi
jc custom_error_message_ready
cmp al,','
jne invalid_argument
jmp create_custom_error_message
custom_error_message_ready:
mov edx,[assembly_workspace.memory_start]
sub edi,edx
sub edi,4
mov [edx],edi
call register_volatile_error
test edx,edx
jz instruction_assembled
or [edx+Error.flags],ERR_CUSTOM
jmp instruction_assembled
choose_to_remove_comments:
and [preprocessing_mode],not PMODE_RETAIN_COMMENTS
jmp instruction_assembled
choose_to_retain_comments:
or [preprocessing_mode],PMODE_RETAIN_COMMENTS
jmp instruction_assembled
choose_to_combine_lines:
and [preprocessing_mode],not PMODE_ISOLATE_LINES
jmp instruction_assembled
choose_to_isolate_lines:
or [preprocessing_mode],PMODE_ISOLATE_LINES
jmp instruction_assembled
missing_argument:
mov edx,_missing_argument
call register_error
jmp assembly_line
invalid_argument:
mov edx,_invalid_argument
call register_error
jmp assembly_line
invalid_identifier:
mov edx,_invalid_identifier
call register_error
jmp assembly_line
value_out_of_range:
mov edx,_value_out_of_range
call register_error
jmp assembly_line
missing_closing_parenthesis:
mov edx,_missing_closing_parenthesis
call register_error
jmp assembly_line
unexpected_instruction:
mov edx,_unexpected_instruction
call register_error
jmp assembly_line
repeated_declaration:
mov edx,_repeated_declaration
call register_error
jmp assembly_line