// File: /workspace/github_c_makefile_star2_O2/System-Glitch[P]ESGILinter-C/src/parsing_operations.c
// Function: parse_operation
type_t parse_operation(char *line, int line_index, scope_t *scope, messages_t *messages) {
	type_t type;
	type_t left_operand_type;
	type_t right_operand_type;
	type_t *ptr_type;
	scope_t *root_scope       = get_root_scope(scope);
	char *line_wo_comment     = str_remove_comments(line);
	arraylist_t *declarations = NULL;
	char *tmp_line            = NULL;
	char *left_operand        = NULL;
	char *right_operand       = NULL;
	const char *operator      = NULL;
	char *occurrence          = NULL;
	char *tmp                 = NULL;
	int   index_operator      =  0;
	int   left_operand_length = -1;
	int   right_operand_index = -1;
	int   length              = strlen(line_wo_comment);
	int   operator_length     = -1;
	int   rank                = -1;
	int   index_colon         =  0;
	char  has_colon           =  0;

	type.name = strduplicate("NULL");
	type.is_pointer = 0;
	type.is_literal = 0;


	tmp = remove_parenthesis(line_wo_comment, length);
	if(tmp != NULL) {
		free(line_wo_comment);
		line_wo_comment = tmp;
		length = strlen(line_wo_comment);
	}

	while((index_colon = strindexof(line_wo_comment + index_colon + 1, ':')) != -1) {
		if(!check_quotes(line_wo_comment, line_wo_comment + index_colon, length)) {
			has_colon = 1;
			break;
		}
	}

	if(has_colon) {
		//Maybe it's ternary condition
		type = parse_ternary_condition(line_wo_comment, length, line_index, scope, messages);
		if(strcmp(type.name, "NULL")) {
			free(line_wo_comment);
			return type;
		}
	} else if(starts_with_return(line_wo_comment, length)) {
		free(line_wo_comment);
		return type;
	}

	while((operator = known_operators[index_operator++]) != NULL) { //Find operator
		tmp_line = line_wo_comment;
		operator_length = strlen(operator);
		occurrence = strstr(line_wo_comment, operator);
		if(occurrence != NULL) {

			//Check if inside quotes
			while(check_quotes(line_wo_comment, occurrence, length) || check_parenthesis(line_wo_comment, occurrence, length)) {
				occurrence = strstr(occurrence + 1, operator);
				if(occurrence == NULL) break;
			}

			if(occurrence == NULL) continue;

			if(!strcmp(operator, "*") || !strcmp(operator, "&")) {

				//Check if not function declaration
				for(size_t i = 0 ; i < root_scope->functions->size ; i++) {
					if(((function_t*)arraylist_get(root_scope->functions, i))->line == line_index) {
						free(line_wo_comment);
						return type;
					}
				}

				while(is_operator_first(tmp_line, length, occurrence)) {
					tmp_line = occurrence + operator_length;
					occurrence = strstr(tmp_line, operator);
					if(occurrence == NULL)
						break;
				}
			} else if(is_operator_first(tmp_line, length, occurrence)) {
				free(line_wo_comment);
				return type;
			}

			if(occurrence == NULL) continue;

			//Split
			left_operand_length = occurrence - line_wo_comment;
			right_operand_index = left_operand_length + strlen(operator);
			left_operand        = strsubstr(line_wo_comment, 0, left_operand_length);
			right_operand       = strsubstr(line_wo_comment, right_operand_index, length - right_operand_index);

			//Check operator spacing
			if(messages->operator_spacing != NULL) {
				if((*(occurrence - 1) != ' ' || *(occurrence + operator_length) != ' ') && strcmp(right_operand, operator)) {
					arraylist_add(messages->operator_spacing, strduplicate((char*)operator));
				}
			}

			//If left operation is variable declaration
			declarations = get_variables_from_declaration(line_index, line);
			if(declarations != NULL && declarations->size > 0) {
				parse_declarations(declarations, scope, line_index, messages);

				free(type.name);
				type.name = strduplicate(((field_t*)arraylist_get(declarations, 0))->type.name);

				field_list_free(declarations);

				//Find var declaration in scope
				left_operand_type = find_variable_type_from_line(scope, line_index);

			} else {
				
				left_operand_type  = parse_operand(left_operand, line_index, scope, messages);
				right_operand_type = parse_operand(right_operand, line_index, scope, messages);

				if(strcmp(left_operand_type.name,"NULL") && strcmp(right_operand_type.name,"NULL")) {

					if(messages->wrong_assignment != NULL && is_assignation(operator) &&
						!type_equals(&left_operand_type, &right_operand_type)) {

						add_wrong_type_message(messages->wrong_assignment, &left_operand_type, &right_operand_type);
					}

					if(is_comparison(operator)) { //Type is int
						free(type.name);
						type.name = strduplicate("int");
						type.is_pointer = 0;
					} else if(right_operand_type.is_pointer || left_operand_type.is_pointer) {
						ptr_type = right_operand_type.is_pointer > left_operand_type.is_pointer ? &right_operand_type : &left_operand_type;
						free(type.name);
						type.name = strduplicate(ptr_type->name);
						type.is_pointer = ptr_type->is_pointer;
					} else {
						rank = get_highest_rank(right_operand_type.name, left_operand_type.name);
						if(rank != -1) {
							free(type.name);
							type.name = strduplicate((char*)type_rank[rank]);
							type.is_pointer = 0;
						}
					}
				}
				free(right_operand_type.name);
				free(left_operand_type.name);
			}

			//TODO detect forbidden operations (2 * &ptr , void + something, int - ptr)

			free(left_operand);
			free(right_operand);
			break;
		}
	}

	free(line_wo_comment);

	return type;	
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x78, %rsp
movq %rcx, 0x30(%rsp)
movl %esi, 0x4(%rsp)
movq %rdi, %rbx
movq %rdx, 0x38(%rsp)
movq %rdx, %rdi
callq 0x667d
movq %rax, 0x50(%rsp)
movq %rbx, 0x70(%rsp)
movq %rbx, %rdi
callq 0x77dc
movq %rax, %rbx
movq %rax, %rdi
callq 0x20b0
movq %rax, %r13
leaq 0x7b82(%rip), %rdi      # 0xe8b0
callq 0x794d
movq %rax, %r12
movq %rbx, %rdi
movl %r13d, %esi
callq 0x7f1f
testq %rax, %rax
je 0x6d5f
movq %rax, %r14
movq %rbx, %rdi
callq 0x2030
movq %r14, %rdi
callq 0x20b0
movq %rax, %r13
movq %r14, %rbx
leaq 0x1(%rbx), %r15
xorl %r14d, %r14d
pushq $0x3a
popq %rbp
movslq %r14d, %rdi
addq %r15, %rdi
movl %ebp, %esi
callq 0x7b48
cmpl $-0x1, %eax
je 0x6de9
movl %eax, %r14d
movslq %eax, %rsi
addq %rbx, %rsi
movq %rbx, %rdi
movl %r13d, %edx
callq 0x7e2e
testb %al, %al
jne 0x6d69
leaq 0x7b16(%rip), %rdi      # 0xe8b0
callq 0x794d
movq %rax, 0x8(%rsp)
pushq $0x3f
popq %rbp
movq %rbx, %r12
movq %r12, %rdi
movl %ebp, %esi
callq 0x20c0
testq %rax, %rax
je 0x6f26
movq %rax, %r12
movq %rbx, %rdi
movq %rax, %rsi
movl %r13d, %edx
callq 0x7e2e
testb %al, %al
jne 0x6de4
movq %rbx, %rdi
movq %r12, %rsi
movl %r13d, %edx
callq 0x7e63
testb %al, %al
je 0x6e3d
incq %r12
jmp 0x6daa
movslq %r13d, %r14
xorl %ecx, %ecx
movq %rcx, %r15
movsbl (%rbx,%rcx), %edi
callq 0x7ace
leaq 0x1(%r15), %rcx
cmpq %r14, %r15
jge 0x6e07
testb %al, %al
jne 0x6dee
leaq (%rbx,%rcx), %rdi
decq %rdi
leaq 0x79e8(%rip), %rsi      # 0xe7fd
pushq $0x6
popq %rdx
callq 0x2070
testl %eax, %eax
je 0x6e2e
movl $0x0, 0x10(%rsp)
jmp 0x6f48
movq %rbx, %rdi
callq 0x2030
xorl %ebp, %ebp
jmp 0x73a4
pushq $0x3a
popq %r14
movq %r12, %rbp
movq %rbp, %rdi
movl %r14d, %esi
callq 0x20c0
testq %rax, %rax
je 0x6f26
movq %rax, %rbp
movq %rbx, %rdi
movq %rax, %rsi
movl %r13d, %edx
callq 0x7e2e
testb %al, %al
jne 0x6e7f
movq %rbx, %rdi
movq %rbp, %rsi
movl %r13d, %edx
callq 0x7e63
testb %al, %al
je 0x6e84
incq %rbp
jmp 0x6e44
subl %ebx, %r12d
subl %ebx, %ebp
leal -0x1(%r12), %edx
movq $0x0, 0x18(%rsp)
movq %rbx, %rdi
xorl %esi, %esi
callq 0x79a6
movq %rax, 0x10(%rsp)
movq 0x18(%rsp), %rax
leaq 0xc23e(%rip), %rcx      # 0x130f0
movq (%rcx,%rax,8), %r15
testq %r15, %r15
je 0x7409
incq %rax
movq %rax, 0x18(%rsp)
movq %rbx, %rdi
movq %r15, %rsi
callq 0x21b0
testq %rax, %rax
je 0x6ea6
movq %rax, %r14
cmpb $0x3d, 0x1(%rax)
je 0x6ea6
movq %rbx, %rdi
movq %r14, %rsi
movl %r13d, %edx
callq 0x7e2e
testb %al, %al
jne 0x6f04
movq %rbx, %rdi
movq %r14, %rsi
movl %r13d, %edx
callq 0x7e63
testb %al, %al
je 0x6f1c
incq %r14
movq %r14, %rdi
movq %r15, %rsi
callq 0x21b0
movq %rax, %r14
testq %rax, %rax
jne 0x6ee0
jmp 0x6ea6
movq 0x10(%rsp), %rdi
callq 0x2030
xorl %ebp, %ebp
movq 0x8(%rsp), %r12
leaq 0x797c(%rip), %rsi      # 0xe8b0
movq %r12, %rdi
callq 0x2110
testl %eax, %eax
jne 0x739c
movl %ebp, 0x10(%rsp)
movq $0x0, 0x18(%rsp)
movq 0x18(%rsp), %rax
cmpq $0x1e, %rax
je 0x706a
leaq 0xbcd9(%rip), %rcx      # 0x12c40
movq (%rcx,%rax,8), %r15
incq %rax
movq %rax, 0x18(%rsp)
movq %r15, %rdi
callq 0x20b0
movq %rax, %r14
movq %rbx, %rdi
movq %r15, %rsi
callq 0x21b0
testq %rax, %rax
je 0x6f51
movq %rax, %rbp
movq %rbx, %rdi
movq %rbp, %rsi
movl %r13d, %edx
callq 0x7e2e
testb %al, %al
jne 0x6fb5
movq %rbx, %rdi
movq %rbp, %rsi
movl %r13d, %edx
callq 0x7e63
testb %al, %al
je 0x6fcd
incq %rbp
movq %rbp, %rdi
movq %r15, %rsi
callq 0x21b0
movq %rax, %rbp
testq %rax, %rax
jne 0x6f91
jmp 0x6f51
movzbl (%r15), %eax
cmpl $0x26, %eax
movq %r14, 0x58(%rsp)
je 0x6fe4
cmpl $0x2a, %eax
jne 0x7073
cmpb $0x0, 0x1(%r15)
jne 0x7073
xorl %r14d, %r14d
movq 0x50(%rsp), %rax
movq 0x10(%rax), %rdi
cmpq 0x8(%rdi), %r14
jae 0x7017
movq %r14, %rsi
callq 0x6978
incq %r14
movl 0x4(%rsp), %ecx
cmpl %ecx, 0x28(%rax)
jne 0x6ff2
jmp 0x7059
movq %r12, 0x8(%rsp)
movslq 0x58(%rsp), %r12
movq %rbx, %r14
movq %r14, %rdi
movl %r13d, %esi
movq %rbp, %rdx
callq 0x75e7
testb %al, %al
je 0x7099
movq %rbp, %r14
addq %r12, %r14
movq %r14, %rdi
movq %r15, %rsi
callq 0x21b0
movq %rax, %rbp
testq %rax, %rax
jne 0x7024
movq 0x8(%rsp), %r12
jmp 0x6f51
movq %rbx, %rdi
callq 0x2030
movl 0x10(%rsp), %ebp
jmp 0x73a4
movl 0x10(%rsp), %ebp
jmp 0x739c
movq %r12, 0x8(%rsp)
movq %rbx, %rdi
movl %r13d, %esi
movq %rbp, %rdx
callq 0x75e7
testb %al, %al
je 0x7099
movq %rbx, %rdi
callq 0x2030
movq 0x8(%rsp), %r12
jmp 0x7061
movl %ebp, %r14d
subl %ebx, %r14d
movq %r15, %rdi
callq 0x20b0
leal (%rax,%r14), %r12d
movq %rbx, %rdi
xorl %esi, %esi
movl %r14d, %edx
callq 0x79a6
movq %rax, 0x18(%rsp)
subl %r12d, %r13d
movq %rbx, %rdi
movl %r12d, %esi
movl %r13d, %edx
callq 0x79a6
movq %rax, 0x50(%rsp)
movq 0x30(%rsp), %rax
movq 0x38(%rax), %r14
testq %r14, %r14
je 0x7117
cmpb $0x20, -0x1(%rbp)
jne 0x70f3
movslq 0x58(%rsp), %rax
cmpb $0x20, (%rbp,%rax)
je 0x7117
movq 0x50(%rsp), %rdi
movq %r15, %rsi
callq 0x2110
testl %eax, %eax
je 0x7117
movq %r15, %rdi
callq 0x794d
movq %r14, %rdi
movq %rax, %rsi
callq 0x68b5
movl 0x4(%rsp), %edi
movq 0x70(%rsp), %rsi
callq 0x83c6
testq %rax, %rax
je 0x7219
movq %rax, %r12
movq 0x8(%rax), %rax
testq %rax, %rax
je 0x7219
xorl %r15d, %r15d
movq 0x30(%rsp), %rbp
cmpq %rax, %r15
jae 0x7314
movq %r12, %rdi
movq %r15, %rsi
callq 0x6978
movq 0x8(%rax), %rdi
testq %rdi, %rdi
je 0x720c
movq %rax, %r13
movl 0x4(%rsp), %esi
movq 0x38(%rsp), %rdx
movq %rbp, %rcx
callq 0x6ce0
movq %rax, %r14
movq %rax, 0x20(%rsp)
movq %rdx, 0x28(%rsp)
movq %rax, %rdi
leaq 0x771e(%rip), %rsi      # 0xe8b0
callq 0x2110
testl %eax, %eax
jne 0x71bd
movq 0x8(%r13), %rdi
movl 0x4(%rsp), %esi
movq 0x38(%rsp), %rdx
movq %rbp, %rcx
callq 0xaf1c
movq %rax, %r14
movq %rax, 0x20(%rsp)
movq %rdx, 0x28(%rsp)
cmpq $0x0, 0x20(%rbp)
je 0x7202
movq %r14, %rdi
leaq 0x76e2(%rip), %rsi      # 0xe8b0
callq 0x2110
testl %eax, %eax
je 0x7202
addq $0x10, %r13
movq %r13, %rdi
leaq 0x20(%rsp), %rsi
callq 0x652a
testb %al, %al
jne 0x7202
movq 0x30(%rsp), %rax
movq 0x20(%rax), %rdi
movq %r13, %rsi
leaq 0x20(%rsp), %rdx
callq 0x7690
movq 0x20(%rsp), %rdi
callq 0x2030
incq %r15
movq 0x8(%r12), %rax
jmp 0x7146
movq 0x18(%rsp), %rdi
movl 0x4(%rsp), %ebp
movl %ebp, %esi
movq 0x38(%rsp), %r13
movq %r13, %rdx
movq 0x30(%rsp), %r14
movq %r14, %rcx
callq 0x7629
movq %rax, %r12
movq %rax, 0x20(%rsp)
movq %rdx, 0x28(%rsp)
movq 0x50(%rsp), %rdi
movl %ebp, %esi
movq %r13, %rdx
movq %r14, %rcx
callq 0x7629
movq %rax, %r14
movq %rax, 0x40(%rsp)
movq %rdx, 0x48(%rsp)
leaq 0x7644(%rip), %rsi      # 0xe8b0
movq %r12, %rdi
callq 0x2110
testl %eax, %eax
je 0x736b
leaq 0x762d(%rip), %rsi      # 0xe8b0
movq %r14, %rdi
callq 0x2110
testl %eax, %eax
movq 0x8(%rsp), %r12
je 0x7370
movq 0x30(%rsp), %rax
cmpq $0x0, 0x20(%rax)
je 0x72e2
leaq 0xbe45(%rip), %rsi      # 0x130f0
movq %r15, %rdi
callq 0x7761
testb %al, %al
je 0x72e2
leaq 0x20(%rsp), %rdi
leaq 0x40(%rsp), %rsi
callq 0x652a
testb %al, %al
jne 0x72e2
movq 0x30(%rsp), %rax
movq 0x20(%rax), %rdi
leaq 0x20(%rsp), %rsi
leaq 0x40(%rsp), %rdx
callq 0x7690
leaq 0xbe77(%rip), %rsi      # 0x13160
movq %r15, %rdi
callq 0x7761
testb %al, %al
je 0x73ba
movq %r12, %rdi
callq 0x2030
leaq 0x760b(%rip), %rdi      # 0xe913
callq 0x794d
movq %rax, %r12
xorl %ebp, %ebp
jmp 0x7374
movq 0x8(%rsp), %rdi
callq 0x2030
xorl %r14d, %r14d
movq %r12, %rdi
xorl %esi, %esi
callq 0x6978
movq 0x10(%rax), %rdi
callq 0x794d
movq %rax, %r15
movq %r12, %rdi
callq 0x6605
movq 0x38(%rsp), %rax
movq 0x18(%rax), %rdi
cmpq 0x8(%rdi), %r14
jae 0x7362
movq %r14, %rsi
callq 0x6978
incq %r14
movl 0x4(%rsp), %ecx
cmpl %ecx, 0x20(%rax)
jne 0x733f
movq %r15, %r12
movl 0x10(%rsp), %ebp
jmp 0x7388
movq 0x8(%rsp), %r12
movl 0x10(%rsp), %ebp
movq 0x40(%rsp), %rdi
callq 0x2030
movq 0x20(%rsp), %rdi
callq 0x2030
movq 0x18(%rsp), %rdi
callq 0x2030
movq 0x50(%rsp), %rdi
callq 0x2030
movq %rbx, %rdi
callq 0x2030
movzbl %bpl, %edx
movq %r12, %rax
addq $0x78, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movb 0x48(%rsp), %bpl
movb 0x28(%rsp), %r14b
movl %ebp, %eax
orb %r14b, %al
je 0x7527
movq %r12, %rdi
callq 0x2030
cmpb %r14b, %bpl
leaq 0x40(%rsp), %rax
leaq 0x20(%rsp), %rcx
cmovgq %rax, %rcx
movq (%rcx), %rdi
leaq 0x48(%rsp), %rax
leaq 0x28(%rsp), %r14
cmovgq %rax, %r14
callq 0x794d
movq %rax, %r12
movb (%r14), %bpl
jmp 0x7374
leal 0x1(%r12), %esi
notl %r12d
addl %ebp, %r12d
movq %rbx, %rdi
movl %r12d, %edx
callq 0x79a6
movq %rax, %r14
leal 0x1(%rbp), %esi
notl %ebp
addl %r13d, %ebp
movq %rbx, %rdi
movl %ebp, %edx
callq 0x79a6
movq %rax, %rbp
movq %r14, 0x18(%rsp)
movq %r14, %rdi
movl 0x4(%rsp), %r12d
movl %r12d, %esi
movq 0x38(%rsp), %r15
movq %r15, %rdx
movq 0x30(%rsp), %r14
movq %r14, %rcx
callq 0x7629
movq %rax, 0x20(%rsp)
movq %rdx, 0x68(%rsp)
movq %rdx, 0x28(%rsp)
movq %rbp, 0x58(%rsp)
movq %rbp, %rdi
movq %rax, %rbp
movl %r12d, %esi
movq %r15, %rdx
movq %r14, %rcx
callq 0x7629
movq %rax, %r15
movq %rdx, %r12
movq %rax, 0x40(%rsp)
movq %rdx, 0x48(%rsp)
leaq 0x7415(%rip), %rsi      # 0xe8b0
movq %rbp, %rdi
callq 0x2110
testl %eax, %eax
je 0x755c
leaq 0x73fe(%rip), %rsi      # 0xe8b0
movq %r15, %rdi
callq 0x2110
testl %eax, %eax
movq 0x10(%rsp), %r14
je 0x756a
movq %r14, %rdi
movl 0x4(%rsp), %esi
movq 0x38(%rsp), %rdx
movq 0x30(%rsp), %rcx
callq 0x7629
movq %rax, 0x60(%rsp)
movq %r15, %rdi
movq %rbp, %rsi
callq 0x7713
cmpl $-0x1, %eax
je 0x756e
movl %eax, %ebp
movq 0x8(%rsp), %rdi
callq 0x2030
movslq %ebp, %rax
leaq 0xb838(%rip), %rcx      # 0x12d40
movq (%rcx,%rax,8), %rdi
callq 0x794d
movq %rax, 0x8(%rsp)
movzbl %r12b, %eax
movzbl 0x68(%rsp), %ebp
cmpb %bpl, %al
cmovgl %eax, %ebp
jmp 0x7570
movq 0x40(%rsp), %rdi
movq 0x20(%rsp), %rsi
callq 0x7713
cmpl $-0x1, %eax
je 0x7370
movl %eax, %ebp
movq %r12, %rdi
callq 0x2030
movslq %ebp, %rax
leaq 0xb7ed(%rip), %rcx      # 0x12d40
movq (%rcx,%rax,8), %rdi
jmp 0x7308
xorl %ebp, %ebp
movq 0x8(%rsp), %r12
movq 0x10(%rsp), %r14
jmp 0x75b4
xorl %ebp, %ebp
jmp 0x75af
xorl %ebp, %ebp
leaq 0x20(%rsp), %rdi
leaq 0x40(%rsp), %rsi
callq 0x652a
testb %al, %al
jne 0x75a0
movq 0x30(%rsp), %rax
movq 0x30(%rax), %rdi
testq %rdi, %rdi
je 0x75a0
leaq 0x20(%rsp), %rsi
leaq 0x40(%rsp), %rdx
callq 0x7690
movq 0x60(%rsp), %rdi
callq 0x2030
movq 0x40(%rsp), %r15
movq 0x8(%rsp), %r12
movq %r15, %rdi
callq 0x2030
movq 0x20(%rsp), %rdi
callq 0x2030
movq %r14, %rdi
callq 0x2030
movq 0x18(%rsp), %rdi
callq 0x2030
movq 0x58(%rsp), %rdi
callq 0x2030
jmp 0x6f2d