// File: /workspace/github_c_makefile_star2_O0/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
movq %rsp, %rbp
subq $0x130, %rsp            # imm = 0x130
movq %rdi, -0x18(%rbp)
movl %esi, -0x1c(%rbp)
movq %rdx, -0x28(%rbp)
movq %rcx, -0x30(%rbp)
movq -0x28(%rbp), %rdi
callq 0x8290
movq %rax, -0x60(%rbp)
movq -0x18(%rbp), %rdi
callq 0xa2b0
movq %rax, -0x68(%rbp)
movq $0x0, -0x70(%rbp)
movq $0x0, -0x78(%rbp)
movq $0x0, -0x80(%rbp)
movq $0x0, -0x88(%rbp)
movq $0x0, -0x90(%rbp)
movq $0x0, -0x98(%rbp)
movq $0x0, -0xa0(%rbp)
movl $0x0, -0xa4(%rbp)
movl $0xffffffff, -0xa8(%rbp) # imm = 0xFFFFFFFF
movl $0xffffffff, -0xac(%rbp) # imm = 0xFFFFFFFF
movq -0x68(%rbp), %rdi
callq 0x2090
movl %eax, -0xb0(%rbp)
movl $0xffffffff, -0xb4(%rbp) # imm = 0xFFFFFFFF
movl $0xffffffff, -0xb8(%rbp) # imm = 0xFFFFFFFF
movl $0x0, -0xbc(%rbp)
movb $0x0, -0xbd(%rbp)
leaq 0xb7ef(%rip), %rdi      # 0x148a0
callq 0xa550
movq %rax, -0x10(%rbp)
movb $0x0, -0x8(%rbp)
movb $0x0, -0x7(%rbp)
movq -0x68(%rbp), %rdi
movl -0xb0(%rbp), %esi
callq 0xb090
movq %rax, -0xa0(%rbp)
cmpq $0x0, -0xa0(%rbp)
je 0x9105
movq -0x68(%rbp), %rdi
callq 0x2030
movq -0xa0(%rbp), %rax
movq %rax, -0x68(%rbp)
movq -0x68(%rbp), %rdi
callq 0x2090
movl %eax, -0xb0(%rbp)
jmp 0x9107
movq -0x68(%rbp), %rdi
movslq -0xbc(%rbp), %rax
addq %rax, %rdi
addq $0x1, %rdi
movl $0x3a, %esi
callq 0xa8d0
movl %eax, -0xbc(%rbp)
cmpl $-0x1, %eax
je 0x915a
movq -0x68(%rbp), %rdi
movq -0x68(%rbp), %rsi
movslq -0xbc(%rbp), %rax
addq %rax, %rsi
movl -0xb0(%rbp), %edx
callq 0xae60
cmpb $0x0, %al
jne 0x9158
movb $0x1, -0xbd(%rbp)
jmp 0x915a
jmp 0x9107
cmpb $0x0, -0xbd(%rbp)
je 0x91c6
movq -0x68(%rbp), %rdi
movl -0xb0(%rbp), %esi
movl -0x1c(%rbp), %edx
movq -0x28(%rbp), %rcx
movq -0x30(%rbp), %r8
callq 0x97c0
movq %rax, -0xd0(%rbp)
movq %rdx, -0xc8(%rbp)
movq -0xd0(%rbp), %rax
movq %rax, -0x10(%rbp)
movq -0xc8(%rbp), %rax
movq %rax, -0x8(%rbp)
movq -0x10(%rbp), %rdi
leaq 0xb6f4(%rip), %rsi      # 0x148a0
callq 0x20f0
cmpl $0x0, %eax
je 0x91c4
movq -0x68(%rbp), %rdi
callq 0x2030
jmp 0x97a4
jmp 0x91e9
movq -0x68(%rbp), %rdi
movl -0xb0(%rbp), %esi
callq 0x9c90
cmpb $0x0, %al
je 0x91e7
movq -0x68(%rbp), %rdi
callq 0x2030
jmp 0x97a4
jmp 0x91e9
jmp 0x91eb
movl -0xa4(%rbp), %eax
movl %eax, %ecx
addl $0x1, %ecx
movl %ecx, -0xa4(%rbp)
movslq %eax, %rcx
leaq 0xf04a(%rip), %rax      # 0x18250
movq (%rax,%rcx,8), %rax
movq %rax, -0x90(%rbp)
cmpq $0x0, %rax
je 0x979b
movq -0x68(%rbp), %rax
movq %rax, -0x78(%rbp)
movq -0x90(%rbp), %rdi
callq 0x2090
movl %eax, -0xb4(%rbp)
movq -0x68(%rbp), %rdi
movq -0x90(%rbp), %rsi
callq 0x2190
movq %rax, -0x98(%rbp)
cmpq $0x0, -0x98(%rbp)
je 0x9796
jmp 0x925c
movq -0x68(%rbp), %rdi
movq -0x98(%rbp), %rsi
movl -0xb0(%rbp), %edx
callq 0xae60
movzbl %al, %ecx
movb $0x1, %al
cmpl $0x0, %ecx
movb %al, -0x109(%rbp)
jne 0x92a7
movq -0x68(%rbp), %rdi
movq -0x98(%rbp), %rsi
movl -0xb0(%rbp), %edx
callq 0xaf00
movzbl %al, %eax
cmpl $0x0, %eax
setne %al
movb %al, -0x109(%rbp)
movb -0x109(%rbp), %al
testb $0x1, %al
jne 0x92b3
jmp 0x92e2
movq -0x98(%rbp), %rdi
addq $0x1, %rdi
movq -0x90(%rbp), %rsi
callq 0x2190
movq %rax, -0x98(%rbp)
cmpq $0x0, -0x98(%rbp)
jne 0x92dd
jmp 0x92e2
jmp 0x925c
cmpq $0x0, -0x98(%rbp)
jne 0x92f1
jmp 0x91eb
movq -0x90(%rbp), %rdi
leaq 0xab00(%rip), %rsi      # 0x13dff
callq 0x20f0
cmpl $0x0, %eax
je 0x9325
movq -0x90(%rbp), %rdi
leaq 0xb5c1(%rip), %rsi      # 0x148d8
callq 0x20f0
cmpl $0x0, %eax
jne 0x93dd
movq $0x0, -0xd8(%rbp)
movq -0xd8(%rbp), %rax
movq -0x60(%rbp), %rcx
movq 0x10(%rcx), %rcx
cmpq 0x8(%rcx), %rax
jae 0x9385
movq -0x60(%rbp), %rax
movq 0x10(%rax), %rdi
movq -0xd8(%rbp), %rsi
callq 0x8890
movl 0x28(%rax), %eax
cmpl -0x1c(%rbp), %eax
jne 0x936f
movq -0x68(%rbp), %rdi
callq 0x2030
jmp 0x97a4
jmp 0x9371
movq -0xd8(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xd8(%rbp)
jmp 0x9330
jmp 0x9387
movq -0x78(%rbp), %rdi
movl -0xb0(%rbp), %esi
movq -0x98(%rbp), %rdx
callq 0x9d20
cmpb $0x0, %al
je 0x93db
movq -0x98(%rbp), %rax
movslq -0xb4(%rbp), %rcx
addq %rcx, %rax
movq %rax, -0x78(%rbp)
movq -0x78(%rbp), %rdi
movq -0x90(%rbp), %rsi
callq 0x2190
movq %rax, -0x98(%rbp)
cmpq $0x0, -0x98(%rbp)
jne 0x93d9
jmp 0x93db
jmp 0x9387
jmp 0x9407
movq -0x78(%rbp), %rdi
movl -0xb0(%rbp), %esi
movq -0x98(%rbp), %rdx
callq 0x9d20
cmpb $0x0, %al
je 0x9405
movq -0x68(%rbp), %rdi
callq 0x2030
jmp 0x97a4
jmp 0x9407
cmpq $0x0, -0x98(%rbp)
jne 0x9416
jmp 0x91eb
movq -0x98(%rbp), %rax
movq -0x68(%rbp), %rcx
subq %rcx, %rax
movl %eax, -0xa8(%rbp)
movslq -0xa8(%rbp), %rax
movq %rax, -0x118(%rbp)
movq -0x90(%rbp), %rdi
callq 0x2090
movq %rax, %rcx
movq -0x118(%rbp), %rax
addq %rcx, %rax
movl %eax, -0xac(%rbp)
movq -0x68(%rbp), %rdi
movl -0xa8(%rbp), %edx
xorl %esi, %esi
callq 0xa5e0
movq %rax, -0x80(%rbp)
movq -0x68(%rbp), %rdi
movl -0xac(%rbp), %esi
movl -0xb0(%rbp), %edx
subl -0xac(%rbp), %edx
callq 0xa5e0
movq %rax, -0x88(%rbp)
movq -0x30(%rbp), %rax
cmpq $0x0, 0x38(%rax)
je 0x9504
movq -0x98(%rbp), %rax
movsbl -0x1(%rax), %eax
cmpl $0x20, %eax
jne 0x94c0
movq -0x98(%rbp), %rax
movslq -0xb4(%rbp), %rcx
movsbl (%rax,%rcx), %eax
cmpl $0x20, %eax
je 0x9502
movq -0x88(%rbp), %rdi
movq -0x90(%rbp), %rsi
callq 0x20f0
cmpl $0x0, %eax
je 0x9502
movq -0x30(%rbp), %rax
movq 0x38(%rax), %rax
movq %rax, -0x120(%rbp)
movq -0x90(%rbp), %rdi
callq 0xa550
movq -0x120(%rbp), %rdi
movq %rax, %rsi
callq 0x8730
jmp 0x9504
movl -0x1c(%rbp), %edi
movq -0x18(%rbp), %rsi
callq 0xb980
movq %rax, -0x70(%rbp)
cmpq $0x0, -0x70(%rbp)
je 0x959f
movq -0x70(%rbp), %rax
cmpq $0x0, 0x8(%rax)
jbe 0x959f
movq -0x70(%rbp), %rdi
movq -0x28(%rbp), %rsi
movl -0x1c(%rbp), %edx
movq -0x30(%rbp), %rcx
callq 0x9da0
movq -0x10(%rbp), %rdi
callq 0x2030
movq -0x70(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x8890
movq 0x10(%rax), %rdi
callq 0xa550
movq %rax, -0x10(%rbp)
movq -0x70(%rbp), %rdi
callq 0x81d0
movq -0x28(%rbp), %rdi
movl -0x1c(%rbp), %esi
callq 0x9ee0
movq %rax, -0xe8(%rbp)
movq %rdx, -0xe0(%rbp)
movq -0xe8(%rbp), %rax
movq %rax, -0x40(%rbp)
movq -0xe0(%rbp), %rax
movq %rax, -0x38(%rbp)
jmp 0x977f
movq -0x80(%rbp), %rdi
movl -0x1c(%rbp), %esi
movq -0x28(%rbp), %rdx
movq -0x30(%rbp), %rcx
callq 0x9f90
movq %rax, -0xf8(%rbp)
movq %rdx, -0xf0(%rbp)
movq -0xf8(%rbp), %rax
movq %rax, -0x40(%rbp)
movq -0xf0(%rbp), %rax
movq %rax, -0x38(%rbp)
movq -0x88(%rbp), %rdi
movl -0x1c(%rbp), %esi
movq -0x28(%rbp), %rdx
movq -0x30(%rbp), %rcx
callq 0x9f90
movq %rax, -0x108(%rbp)
movq %rdx, -0x100(%rbp)
movq -0x108(%rbp), %rax
movq %rax, -0x50(%rbp)
movq -0x100(%rbp), %rax
movq %rax, -0x48(%rbp)
movq -0x40(%rbp), %rdi
leaq 0xb283(%rip), %rsi      # 0x148a0
callq 0x20f0
cmpl $0x0, %eax
je 0x976d
movq -0x50(%rbp), %rdi
leaq 0xb26a(%rip), %rsi      # 0x148a0
callq 0x20f0
cmpl $0x0, %eax
je 0x976d
movq -0x30(%rbp), %rax
cmpq $0x0, 0x20(%rax)
je 0x9689
movq -0x90(%rbp), %rdi
callq 0xa020
movzbl %al, %eax
cmpl $0x0, %eax
je 0x9689
leaq -0x40(%rbp), %rdi
leaq -0x50(%rbp), %rsi
callq 0x8080
cmpb $0x0, %al
jne 0x9689
movq -0x30(%rbp), %rax
movq 0x20(%rax), %rdi
leaq -0x40(%rbp), %rsi
leaq -0x50(%rbp), %rdx
callq 0xa050
movq -0x90(%rbp), %rdi
callq 0xa110
cmpb $0x0, %al
je 0x96bb
movq -0x10(%rbp), %rdi
callq 0x2030
leaq 0xb25c(%rip), %rdi      # 0x14905
callq 0xa550
movq %rax, -0x10(%rbp)
movb $0x0, -0x8(%rbp)
jmp 0x976b
movsbl -0x48(%rbp), %eax
cmpl $0x0, %eax
jne 0x96cd
movsbl -0x38(%rbp), %eax
cmpl $0x0, %eax
je 0x9723
movsbl -0x48(%rbp), %eax
movsbl -0x38(%rbp), %ecx
cmpl %ecx, %eax
jle 0x96e6
leaq -0x50(%rbp), %rax
movq %rax, -0x128(%rbp)
jmp 0x96f3
leaq -0x40(%rbp), %rax
movq %rax, -0x128(%rbp)
jmp 0x96f3
movq -0x128(%rbp), %rax
movq %rax, -0x58(%rbp)
movq -0x10(%rbp), %rdi
callq 0x2030
movq -0x58(%rbp), %rax
movq (%rax), %rdi
callq 0xa550
movq %rax, -0x10(%rbp)
movq -0x58(%rbp), %rax
movb 0x8(%rax), %al
movb %al, -0x8(%rbp)
jmp 0x9769
movq -0x50(%rbp), %rdi
movq -0x40(%rbp), %rsi
callq 0xa140
movl %eax, -0xb8(%rbp)
cmpl $-0x1, -0xb8(%rbp)
je 0x9767
movq -0x10(%rbp), %rdi
callq 0x2030
movslq -0xb8(%rbp), %rcx
leaq 0xebfa(%rip), %rax      # 0x18350
movq (%rax,%rcx,8), %rdi
callq 0xa550
movq %rax, -0x10(%rbp)
movb $0x0, -0x8(%rbp)
jmp 0x9769
jmp 0x976b
jmp 0x976d
movq -0x50(%rbp), %rdi
callq 0x2030
movq -0x40(%rbp), %rdi
callq 0x2030
movq -0x80(%rbp), %rdi
callq 0x2030
movq -0x88(%rbp), %rdi
callq 0x2030
jmp 0x979b
jmp 0x91eb
movq -0x68(%rbp), %rdi
callq 0x2030
movq -0x10(%rbp), %rax
movq -0x8(%rbp), %rdx
addq $0x130, %rsp            # imm = 0x130
popq %rbp
retq
nopw %cs:(%rax,%rax)