// File: /workspace/github_c_makefile_star2_O1/martincameron[P]towntalk/towntalk.c
// Function: parse_thiscall_expression
static struct element* parse_thiscall_expression( struct element *elem,
	struct function *func, struct variables *vars, struct expression *prev, char *message ) {
	char *field;
	int idx, count;
	struct variable *var;
	struct structure *struc = NULL;
	struct element *next = elem->next;
	struct global_variable *global = NULL;
	struct string *decl = find_decl( func, &elem->str.string[ 1 ], 0, "!." );
	struct local_variable *captured = NULL, *local = get_local_variable( func->variable_decls, &elem->str.string[ 1 ], "." );
	struct expression param = { 0 }, *this, *expr = calloc( 1, sizeof( struct value_expression ) );
	if( expr ) {
		prev->next = expr;
		expr->line = elem->line;
		if( local ) {
			struc = local->type;
		} else {
			if( vars ) {
				captured = get_local_variable( vars->func->variable_decls, &elem->str.string[ 1 ], "." );
			}
			if( captured ) {
				struc = captured->type;
			} else if( decl ) {
				if( decl->type == GLOBAL ) {
					global = ( struct global_variable * ) decl;
					struc = global->type;
				} else if( decl->type == STRUCT ) {
					struc = ( struct structure * ) decl;
				}
			}
		}
		field = field_end( elem->str.string, "!." );
		if( struc && field[ 0 ] ) {
			( ( struct value_expression * ) expr )->str = &struc->str;
			idx = get_string_list_index( struc->fields, &field[ 1 ] );
			if( idx >= 0 ) {
				if( next && next->str.string[ 0 ] == '(' ) {
					parse_expressions( next->child, func, vars, 0, &param, &count, message );
					expr->parameters = param.next;
					if( local || captured || global ) {
						this = calloc( 1, sizeof( struct value_expression ) );
						if( this ) {
							if( local ) {
								this->index = local->index;
								this->evaluate = evaluate_local;
							} else if( captured ) {
								var = &vars->locals[ captured->index ];
								this->index = ( long_int ) var->number_value;
								( ( struct value_expression * ) this )->num = var->number_value;
								if( var->string_value ) {
									var->string_value->reference_count++;
									( ( struct value_expression * ) this )->str = var->string_value;
									this->evaluate = evaluate_string_literal_expression;
								} else {
									this->evaluate = evaluate_number_literal_expression;
								}
							} else {
								( ( struct value_expression * ) this )->str = &global->str;
								this->evaluate = evaluate_global;
							}
							this->next = expr->parameters;
							expr->parameters = this;
							count++;
						} else {
							strcpy( message, OUT_OF_MEMORY );
						}
					}
					if( message[ 0 ] == 0 ) {
						if( count > 0 && count < 256 ) {
							expr->index = ( ( idx & 0x7FFFFF ) << 8 ) | count;
							expr->evaluate = evaluate_thiscall_expression;
							next = next->next;
						} else {
							sprintf( message, "Expected expression after '(' on line %d.", next->line );
						}
					}
				} else {
					sprintf( message, "Expected '(' after '%.64s' on line %d.", elem->str.string, elem->line );
				}
			} else {
				sprintf( message, "Field '%.64s' not declared on line %d.", &elem->str.string[ 1 ], elem->line );
			}
		} else {
			sprintf( message, "Undeclared variable, structure or field '%.64s' on line %d.", elem->str.string, elem->line );
		}
	} else {
		strcpy( message, OUT_OF_MEMORY );
	}
	return next;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x68, %rsp
movq %r8, %r15
movq %rcx, %rbx
movq %rdx, 0x20(%rsp)
movq %rsi, %r12
movq %rdi, %r14
movq 0x8(%rdi), %rsi
movq 0x20(%rdi), %rax
movq %rax, 0x8(%rsp)
incq %rsi
leaq 0xcd01(%rip), %rcx      # 0x126fc
movq %r12, %rdi
xorl %edx, %edx
callq 0x6103
movq %rax, %r13
movq %r12, 0x38(%rsp)
movq 0x48(%r12), %rdi
movq 0x8(%r14), %r12
leaq 0x1(%r12), %rsi
leaq 0xccdb(%rip), %rdx      # 0x126fd
movq %rsi, 0x30(%rsp)
callq 0x5cf3
movq %rax, %rbp
xorps %xmm0, %xmm0
movaps %xmm0, 0x50(%rsp)
movaps %xmm0, 0x40(%rsp)
movl $0x1, %edi
movl $0x30, %esi
callq 0x3130
testq %rax, %rax
je 0x5a74
movq %r15, 0x18(%rsp)
movq %rax, 0x10(%rbx)
movl 0x28(%r14), %ebx
movl %ebx, (%rax)
testq %rbp, %rbp
movq %rbp, 0x28(%rsp)
movq %rax, %r15
je 0x5a88
movq 0x10(%rbp), %r13
xorl %ebp, %ebp
jmp 0x5abf
movq 0x136f5(%rip), %rsi     # 0x19170
movq %r15, %rdi
callq 0x3070
jmp 0x5bd0
movq 0x20(%rsp), %rax
testq %rax, %rax
je 0x5aad
movq 0x18(%rax), %rax
movq 0x48(%rax), %rdi
leaq 0xcc5c(%rip), %rdx      # 0x126fd
movq 0x30(%rsp), %rsi
callq 0x5cf3
jmp 0x5aaf
xorl %eax, %eax
testq %rax, %rax
je 0x5bf7
movq %rax, %rbp
movq 0x10(%rax), %r13
xorl %r14d, %r14d
leaq 0xcc33(%rip), %rsi      # 0x126fc
movq %r12, %rdi
callq 0x84da
testq %r13, %r13
je 0x5baf
cmpb $0x0, (%rax)
je 0x5baf
movq %r13, 0x20(%r15)
movq 0x20(%r13), %rdi
incq %rax
movq %rax, %rsi
callq 0x852b
testl %eax, %eax
js 0x5be4
movq 0x8(%rsp), %rcx
testq %rcx, %rcx
je 0x5bb8
movl %eax, %r13d
movq 0x8(%rcx), %rax
cmpb $0x28, (%rax)
jne 0x5bb8
movq 0x28(%rsp), %r12
orq %rbp, %r12
movq 0x18(%rcx), %rdi
movq 0x18(%rsp), %rbx
movq %rbx, (%rsp)
leaq 0x40(%rsp), %r8
leaq 0x14(%rsp), %r9
movq 0x38(%rsp), %rsi
movq 0x20(%rsp), %rdx
xorl %ecx, %ecx
callq 0x8314
leaq 0x40(%rsp), %rax
movq 0x10(%rax), %rax
movq %rax, 0x8(%r15)
orq %r14, %r12
movq %rbx, %r12
je 0x5c39
movq %rax, %rbx
movl $0x1, %edi
movl $0x30, %esi
callq 0x3130
testq %rax, %rax
je 0x5c2a
movq 0x28(%rsp), %rcx
testq %rcx, %rcx
je 0x5c9b
movl (%rcx), %ecx
movl %ecx, 0x4(%rax)
leaq -0x198d(%rip), %rcx     # 0x420d
movq %rcx, 0x18(%rax)
movq %rbx, 0x10(%rax)
movq %rax, 0x8(%r15)
incl 0x14(%rsp)
jmp 0x5c39
leaq 0xcb70(%rip), %rsi      # 0x12726
jmp 0x5bbf
leaq 0xc789(%rip), %rsi      # 0x12348
movq 0x18(%rsp), %rdi
movq %r12, %rdx
movl %ebx, %ecx
xorl %eax, %eax
callq 0x3200
movq 0x8(%rsp), %rax
addq $0x68, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0xcb14(%rip), %rsi      # 0x126ff
movq 0x18(%rsp), %rdi
movq 0x30(%rsp), %rdx
jmp 0x5bc7
testq %r13, %r13
je 0x5c1d
movzbl 0x14(%r13), %eax
cmpl $0x3, %eax
je 0x5a70
cmpl $0x4, %eax
jne 0x5c1d
movq %r13, %r14
movq 0x28(%r13), %r13
xorl %ebp, %ebp
jmp 0x5ac2
xorl %ebp, %ebp
xorl %r14d, %r14d
xorl %r13d, %r13d
jmp 0x5ac2
movq 0x1353f(%rip), %rsi     # 0x19170
movq %r12, %rdi
callq 0x3070
cmpb $0x0, (%r12)
jne 0x5bd0
movl 0x14(%rsp), %eax
leal -0x1(%rax), %ecx
cmpl $0xfe, %ecx
ja 0x5c7a
shll $0x8, %r13d
andl $0x7fffff00, %r13d      # imm = 0x7FFFFF00
orl %r13d, %eax
movl %eax, 0x4(%r15)
leaq 0x290b(%rip), %rax      # 0x8573
movq %rax, 0x18(%r15)
movq 0x8(%rsp), %rax
movq 0x20(%rax), %rax
jmp 0x5bd5
movq 0x8(%rsp), %rbx
movl 0x28(%rbx), %edx
leaq 0xc9e0(%rip), %rsi      # 0x12669
movq %r12, %rdi
xorl %eax, %eax
callq 0x3200
movq %rbx, %rax
jmp 0x5bd5
testq %rbp, %rbp
je 0x5cd7
movq 0x20(%rsp), %rcx
movq 0x10(%rcx), %rcx
movslq (%rbp), %rdx
shlq $0x4, %rdx
movl (%rcx,%rdx), %esi
movl %esi, 0x4(%rax)
movl %esi, 0x28(%rax)
movq 0x8(%rcx,%rdx), %rcx
testq %rcx, %rcx
je 0x5ce7
incq (%rcx)
movq %rcx, 0x20(%rax)
leaq -0x21fd(%rip), %rcx     # 0x3ad5
jmp 0x5b9a
movq %r14, 0x20(%rax)
leaq -0x1a23(%rip), %rcx     # 0x42bf
jmp 0x5b9a
leaq -0x2224(%rip), %rcx     # 0x3aca
jmp 0x5b9a