COND_NEGATED = 1 ; only with COND_EVALUATE COND_TRUE = 1 ; only with COND_DETERMINED COND_EVALUATE = 2 COND_DETERMINED = 4 get_condition_value: ; in: ; esi = pointer into preprocessed line or the last embedded line ; out: ; esi = pointer advanced past the processed line ; al = logical value mov ebx,[condition_stack_base] mov [condition_stack],ebx mov byte [ebx],COND_EVALUATE get_logical_value: call peek_at_constituent_value cmp al,'~' jne negation_registered and [current_constituent],0 mov ebx,[condition_stack] mov al,[ebx] test byte [ebx],COND_EVALUATE jz get_logical_value xor byte [ebx],COND_NEGATED jmp get_logical_value negation_registered: call parse_logical_value setnc dh mov dl,al jecxz get_logical_operator mov ebx,[condition_stack] lea eax,[ebx+ecx+1] cmp eax,[condition_stack_end] jbe condition_stack_ready push ecx edx mov ecx,eax mov eax,[condition_stack_base] sub ecx,eax sub ebx,eax call grow_stack mov [condition_stack_base],eax add ebx,eax mov [condition_stack],ebx add eax,ecx mov [condition_stack_end],eax pop edx ecx condition_stack_ready: xor al,al test byte [ebx],COND_EVALUATE jz store_opening_parentheses or al,COND_EVALUATE store_opening_parentheses: inc ebx mov [ebx],al loop store_opening_parentheses mov [condition_stack],ebx cmp dx,'~' je get_logical_value get_logical_operator: call peek_at_constituent_value jc end_of_logical_expression cmp al,')' je close_logical_subexpression cmp al,'|' je logical_or cmp al,'&' jne end_of_logical_expression logical_and: and [current_constituent],0 mov ebx,[condition_stack] mov al,[ebx] test al,COND_EVALUATE jnz evaluate_logical_and test al,COND_DETERMINED jz get_logical_value test al,COND_TRUE jz determined_false jmp continue_evaluation evaluate_logical_and: test al,COND_NEGATED jnz evaluate_negated_logical_and call evaluate_logical_value mov ebx,[condition_stack] test al,al jnz continue_evaluation determined_false: mov byte [ebx],COND_DETERMINED jmp get_logical_value evaluate_negated_logical_and: call evaluate_logical_value mov ebx,[condition_stack] test al,al jnz determined_false continue_evaluation: mov byte [ebx],COND_EVALUATE jmp get_logical_value logical_or: and [current_constituent],0 mov ebx,[condition_stack] mov al,[ebx] test al,COND_EVALUATE jnz evaluate_logical_or test al,COND_DETERMINED jz get_logical_value test al,COND_TRUE jnz determined_true jmp continue_evaluation evaluate_logical_or: test al,COND_NEGATED jnz evaluate_negated_logical_or call evaluate_logical_value mov ebx,[condition_stack] test al,al jnz determined_true jmp continue_evaluation evaluate_negated_logical_or: call evaluate_logical_value mov ebx,[condition_stack] test al,al jnz continue_evaluation determined_true: mov byte [ebx],COND_DETERMINED + COND_TRUE jmp get_logical_value close_logical_subexpression: and [current_constituent],0 mov ebx,[condition_stack] cmp ebx,[condition_stack_base] je excess_parenthesis mov al,[ebx] dec ebx mov [condition_stack],ebx test al,COND_DETERMINED jnz subexpression_determined cmp al,COND_EVALUATE + COND_NEGATED jne get_logical_operator test byte [ebx],COND_EVALUATE jz get_logical_operator xor byte [ebx],COND_NEGATED jmp get_logical_operator subexpression_determined: test al,COND_TRUE jnz subexpression_determined_true mov [comparator],evaluated_false jmp get_logical_operator subexpression_determined_true: mov [comparator],evaluated_true jmp get_logical_operator end_of_logical_expression: mov ebx,[condition_stack] cmp ebx,[condition_stack_base] jne missing_parenthesis mov al,[ebx] test al,COND_DETERMINED jnz condition_determined test al,COND_NEGATED jz evaluate_logical_value call evaluate_logical_value test al,al setz al retn condition_determined: and al,COND_TRUE retn excess_parenthesis: mov edx,_excess_closing_parenthesis call register_error jmp unknown_condition missing_parenthesis: mov edx,_missing_closing_parenthesis call register_error unknown_condition: xor al,al retn parse_logical_value: ; in: ; esi = pointer into preprocessed line or the last embedded line ; out: ; [comparator] - evaluating routine ; [expression_workspace.memory_start] - parsed argument sequences ; [expression_end] - end of the parsed argument sequences ; esi = pointer advanced past the parsed value ; al = special character that follows parsed value, zero if no more symbols in line ; ecx = number of parentheses opened before the value that did not get closed ; cf set if value was empty mov edi,[expression_workspace.memory_start] xor eax,eax mov [comparator],eax or [leave_opening_parentheses],1 call parse_expression mov [initial_parentheses],ecx mov [expression_end],edi call peek_at_constituent_value jc end_of_line cmp al,'&' je end_of_logical_value cmp al,'|' je end_of_logical_value cmp al,'~' je end_of_logical_value cmp al,')' je end_of_logical_value cmp al,1Ah je identify_comparator cmp al,'=' je parse_equal cmp al,'<' je parse_less cmp al,'>' je parse_greater jmp end_of_logical_value identify_comparator: test edx,edx jz end_of_logical_value cmp [edx+ValueDefinition.type],VALTYPE_NATIVE_COMPARATOR jne end_of_logical_value and [current_constituent],0 mov eax,[edx+ValueDefinition.value] jmp set_comparator parse_less: and [current_constituent],0 call warp_to_next_symbol jc parse_less_than test ecx,ecx jnz parse_less_than call peek_at_constituent_value jc parse_less_than cmp al,'=' je parse_less_or_equal cmp al,'>' je parse_not_equal parse_less_than: mov eax,check_if_less jmp set_comparator parse_less_or_equal: and [current_constituent],0 mov eax,check_if_not_greater jmp set_comparator parse_not_equal: and [current_constituent],0 mov eax,check_if_not_equal jmp set_comparator parse_greater: and [current_constituent],0 call warp_to_next_symbol jc parse_greater_than test ecx,ecx jnz parse_greater_than call peek_at_constituent_value jc parse_greater_than cmp al,'=' je parse_greater_or_equal parse_greater_than: mov eax,check_if_greater jmp set_comparator parse_greater_or_equal: and [current_constituent],0 mov eax,check_if_not_less jmp set_comparator parse_equal: and [current_constituent],0 mov eax,check_if_equal set_comparator: mov edi,[expression_end] mov [comparator],eax and [leave_opening_parentheses],0 call parse_expression mov [expression_end],edi call peek_at_constituent_value jnc end_of_logical_value end_of_line: xor al,al end_of_logical_value: mov ecx,[initial_parentheses] cmp [comparator],0 jnz logical_value_not_empty mov [comparator],check_if_not_zero mov ebx,[expression_workspace.memory_start] cmp dword [ebx],0 jne logical_value_not_empty stc retn logical_value_not_empty: clc retn evaluate_logical_value: ; in: ; [comparator] - evaluating routine ; [expression_workspace.memory_start] - parsed argument sequences ; out: al = logical value ; note: evaluates value prepared by previous call to parse_logical_value ; preserves: esi push esi mov esi,[expression_workspace.memory_start] jmp [comparator] evaluated_false: pop esi xor al,al retn evaluated_true: pop esi mov al,1 retn evaluate_stored_logical_value: ; in: esi - pointer to evaluating routine followed by parsed argument sequences ; out: al = logical value ; preserves: esi push esi lodsd jmp eax invalid_logical_value: mov edx,_invalid_expression call register_error jmp evaluated_false check_if_equal: call get_difference_signum test al,al jz evaluated_true jmp evaluated_false check_if_not_equal: call get_difference_signum test al,al jnz evaluated_true jmp evaluated_false check_if_less: call get_difference_signum cmp al,0 jl evaluated_true jmp evaluated_false check_if_not_less: call get_difference_signum cmp al,0 jnl evaluated_true jmp evaluated_false check_if_greater: call get_difference_signum cmp al,0 jg evaluated_true jmp evaluated_false check_if_not_greater: call get_difference_signum cmp al,0 jng evaluated_true jmp evaluated_false get_difference_signum: mov edi,[calculation_workspace.memory_start] call calculate_parsed_expression jc signum_error call calculate_parsed_expression jc signum_error mov esi,subtraction_operator call calculate_parsed_expression call pop_terms mov eax,edi jnc check_difference_for_variable_terms signum_error: xor al,al retn check_difference_for_variable_terms: add eax,sizeof.ExpressionTerm cmp [eax+ExpressionTerm.attributes],0 je difference_terms_ok cmp [eax+ExpressionTerm.metadata],0 je check_difference_for_variable_terms mov edx,_values_not_comparable call register_error difference_terms_ok: cmp byte [edi+ExpressionTerm.attributes],EXPR_FLOAT je get_float_signum call get_numeric_term_value mov ecx,1 call fit_value js signum_negative jc signum_positive xor al,al cmp [edi],al jne signum_positive retn get_float_signum: call get_term_value mov esi,edx call get_float_exponent jz signum_zero test [esi+FloatData.attributes],FLOAT_NEGATIVE jnz signum_negative signum_positive: mov al,1 retn signum_negative: or al,-1 retn signum_zero: xor al,al retn check_if_not_zero: mov edi,[calculation_workspace.memory_start] call calculate_parsed_expression jc evaluated_false call pop_terms jc evaluated_false cmp byte [edi+ExpressionTerm.attributes],EXPR_FLOAT je check_if_not_zero_float call get_numeric_term_value mov ecx,1 call fit_value js evaluated_true jc evaluated_true cmp byte [edi],0 jne evaluated_true check_if_has_variable_terms: add edi,sizeof.ExpressionTerm cmp [edi+ExpressionTerm.attributes],0 je evaluated_false cmp [edi+ExpressionTerm.metadata],0 je check_if_has_variable_terms jmp evaluated_true check_if_not_zero_float: call get_term_value mov esi,edx call get_float_exponent jz check_if_has_variable_terms jmp evaluated_true check_if_relative: mov edi,[calculation_workspace.memory_start] call calculate_parsed_expression jc evaluated_false call calculate_parsed_expression jc evaluated_false mov ebx,edi call pop_terms jc evaluated_false mov edx,edi call pop_terms jc evaluated_false cmp [edx+sizeof.ExpressionTerm+ExpressionTerm.attributes],0 je check_difference_terms xchg edi,edx cmp [edx+sizeof.ExpressionTerm+ExpressionTerm.attributes],0 je check_difference_terms mov esi,subtraction_operator mov edi,ebx call calculate_parsed_expression call pop_terms jc evaluated_false check_difference_terms: add edi,sizeof.ExpressionTerm cmp [edi+ExpressionTerm.attributes],0 je evaluated_true cmp [edi+ExpressionTerm.metadata],0 je check_difference_terms jmp evaluated_false undefined_condition: mov edx,_invalid_value call register_error jmp evaluated_false check_if_type_equal: mov edi,[calculation_workspace.memory_start] call calculate_parsed_expression jc evaluated_false call pop_terms jc evaluated_false mov eax,[edi+ExpressionTerm.attributes] mov [result_type],al call calculate_parsed_expression jc evaluated_false call pop_terms jc evaluated_false mov eax,[edi+ExpressionTerm.attributes] cmp al,[result_type] je evaluated_true jmp evaluated_false check_if_value_equal: mov edi,[calculation_workspace.memory_start] call calculate_parsed_expression jc evaluated_false mov ebx,edi call pop_terms jc evaluated_false mov eax,[edi+ExpressionTerm.attributes] mov [result_type],al mov edi,ebx call calculate_parsed_expression jc evaluated_false mov ebx,edi call pop_terms jc evaluated_false mov eax,[edi+ExpressionTerm.attributes] cmp al,[result_type] jne evaluated_false cmp al,EXPR_STRING jne compare_values_numerically call get_term_value mov ecx,[edx] call pop_terms call get_term_value cmp ecx,[edx] jne evaluated_false compare_values_numerically: mov esi,subtraction_operator mov edi,ebx call calculate_parsed_expression call pop_terms jc evaluated_false mov eax,edi check_if_terms_equal: add eax,sizeof.ExpressionTerm cmp [eax+ExpressionTerm.attributes],0 je check_if_constant_term_equal cmp [eax+ExpressionTerm.metadata],0 je check_if_terms_equal jmp evaluated_false check_if_constant_term_equal: cmp byte [edi+ExpressionTerm.attributes],EXPR_FLOAT je check_if_float_equal call get_numeric_term_value xor ecx,ecx xor edi,edi call fit_value jc evaluated_false jmp evaluated_true check_if_float_equal: call get_term_value mov esi,edx call get_float_exponent jnz evaluated_false jmp evaluated_true check_if_defined: xor ecx,ecx jmp check_if_expression_defined check_if_defined_earlier: mov ecx,[current_pass] check_if_expression_defined: and [outer_expression],0 and [defined_element],0 lodsd test eax,eax jnz checked_expression_invalid check_expression_element: lodsd test eax,eax jz check_expression_end cmp al,EXPR_SYMBOL je check_if_subexpression_defined cmp al,EXPR_SYMBOL_VALUE je check_if_symbol_defined or [defined_element],1 add esi,4 cmp al,EXPR_NUMBER je check_expression_element cmp al,EXPR_STRING je check_expression_element cmp al,EXPR_FLOAT je check_expression_element cmp al,EXPR_OPERATOR je check_expression_element cmp al,EXPR_POLYNOMIAL je check_expression_element checked_expression_invalid: jmp invalid_logical_value check_expression_end: xor esi,esi xchg esi,[outer_expression] test esi,esi jnz check_expression_element jecxz checked_expression_defined cmp [defined_element],0 je checked_expression_invalid checked_expression_defined: jmp evaluated_true check_if_symbol_defined: lodsd test eax,eax jz evaluated_false lodsd test eax,eax jz evaluated_false check_symbol_value: or [defined_element],1 jecxz check_expression_element test [eax+ValueDefinition.flags],VAL_INTERNAL jnz check_expression_element cmp [eax+ValueDefinition.pass],ecx jne evaluated_false jmp check_expression_element check_if_subexpression_defined: mov ebx,[esi] test ebx,ebx jz evaluated_false add esi,4 call get_available_value mov eax,edx test eax,eax jz evaluated_false cmp [eax+ValueDefinition.type],VALTYPE_SYMBOLIC jne check_symbol_value mov [outer_expression],esi push ecx call get_subexpression pop ecx jnc invalid_logical_value jmp check_expression_element get_subexpression: call clear_line_embeddings xor esi,esi xor ecx,ecx call embed_symbolic_value mov edi,[expression_workspace.memory_start] and [leave_opening_parentheses],0 call parse_expression call get_constituent_value mov esi,[expression_workspace.memory_start] retn check_if_used: lodsd test eax,eax jnz invalid_logical_value check_if_expression_is_used_symbol: lodsd cmp al,EXPR_SYMBOL je check_for_indirect_symbol cmp al,EXPR_SYMBOL_VALUE jne invalid_logical_value lodsd mov ebx,eax lodsd check_if_used_symbol: lodsd test eax,eax jnz invalid_logical_value test ebx,ebx jz evaluated_false mov ecx,[ebx+SymbolTree_Leaf.last_use_pass] jecxz symbol_predicted_unused mov eax,[current_pass] sub eax,ecx jz evaluated_true cmp eax,1 ja symbol_predicted_unused symbol_predicted_used: or [ebx+SymbolTree_Leaf.flags],SYM_USAGE_PREDICTED + SYM_PREDICTED_USED jmp evaluated_true symbol_predicted_unused: mov al,[ebx+SymbolTree_Leaf.flags] or al,SYM_USAGE_PREDICTED and al,not SYM_PREDICTED_USED mov [ebx+SymbolTree_Leaf.flags],al jmp evaluated_false check_for_indirect_symbol: lodsd mov ebx,eax call get_available_value test edx,edx jz check_if_used_symbol cmp [edx+ValueDefinition.type],VALTYPE_SYMBOLIC jne check_if_used_symbol call get_subexpression jnc invalid_logical_value jmp check_if_expression_is_used_symbol