// File: /workspace/github_c_makefile_star2_O2/koendv[P]stm32duino-raspberrypi/Arduino_Tools/src/stm32flash/parsers/hex.c
// Function: hex_open
parser_err_t hex_open(void *storage, const char *filename, const char write) {
	hex_t *st = storage;
	if (write) {
		return PARSER_ERR_RDONLY;
	} else {
		char mark;
		int fd;
		uint8_t checksum;
		unsigned int c, i;
		uint32_t base = 0;
		unsigned int last_address = 0x0;

		fd = open(filename, O_RDONLY);
		if (fd < 0)
			return PARSER_ERR_SYSTEM;

		/* read in the file */

		while(read(fd, &mark, 1) != 0) {
			if (mark == '\n' || mark == '\r') continue;
			if (mark != ':')
				return PARSER_ERR_INVALID_FILE;

			char buffer[9];
			unsigned int reclen, address, type;
			uint8_t *record = NULL;

			/* get the reclen, address, and type */
			buffer[8] = 0;
			if (read(fd, &buffer, 8) != 8) return PARSER_ERR_INVALID_FILE;
			if (sscanf(buffer, "%2x%4x%2x", &reclen, &address, &type) != 3) {
				close(fd);
				return PARSER_ERR_INVALID_FILE;
			}

			/* setup the checksum */
			checksum =
				reclen +
				((address & 0xFF00) >> 8) +
				((address & 0x00FF) >> 0) +
				type;

			switch(type) {
				/* data record */
				case 0:
					c = address - last_address;
					st->data = realloc(st->data, st->data_len + c + reclen);

					/* if there is a gap, set it to 0xff and increment the length */
					if (c > 0) {
						memset(&st->data[st->data_len], 0xff, c);
						st->data_len += c;
					}

					last_address = address + reclen;
					record = &st->data[st->data_len];
					st->data_len += reclen;
					break;

				/* extended segment address record */
				case 2:
					base = 0;
					break;

				/* extended linear address record */
				case 4:
					base = 0;
					break;
			}

			buffer[2] = 0;
			for(i = 0; i < reclen; ++i) {
				if (read(fd, &buffer, 2) != 2 || sscanf(buffer, "%2x", &c) != 1) {
					close(fd);
					return PARSER_ERR_INVALID_FILE;
				}

				/* add the byte to the checksum */
				checksum += c;

				switch(type) {
					case 0:
						if (record != NULL) {
							record[i] = c;
						} else {
							return PARSER_ERR_INVALID_FILE;
						}
						break;

					case 2:
					case 4:
						base = (base << 8) | c;
						break;
				}
			}

			/* read, scan, and verify the checksum */
			if (
				read(fd, &buffer, 2 ) != 2 ||
				sscanf(buffer, "%2x", &c) != 1 ||
				(uint8_t)(checksum + c) != 0x00
			) {
				close(fd);
				return PARSER_ERR_INVALID_FILE;
			}

			switch(type) {
				/* EOF */
				case 1:
					close(fd);
					return PARSER_ERR_OK;

				/* address record */
				case 4:	base = base << 12;
					/* fall-through */
				case 2: base = base << 4;
					/* Reset last_address since our base changed */
					last_address = 0;

					/* Only assign the program's base address once, and only
					 * do so if we haven't seen any data records yet.
					 * If there are any data records before address records,
					 * the program's base address must be zero.
					 */
					if (st->base == 0 && st->data_len == 0) {
						st->base = base;
						break;
					}

					/* we cant cope with files out of order */
					if (base < st->base) {
						close(fd);
						return PARSER_ERR_INVALID_FILE;
					}

					/* if there is a gap, enlarge and fill with 0xff */
					unsigned int len = base - st->base;
					if (len > st->data_len) {
						st->data = realloc(st->data, len);
						memset(&st->data[st->data_len], 0xff, len - st->data_len);
						st->data_len = len;
					}
					break;
			}
		}

		close(fd);
		return PARSER_ERR_OK;
	}
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x58, %rsp
testb %dl, %dl
je 0x6515
pushq $0x4
popq %rbx
movl %ebx, %eax
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rdi, %r13
movq %rsi, %rdi
xorl %esi, %esi
xorl %eax, %eax
callq 0x2230
testl %eax, %eax
js 0x6812
movl %eax, %ebp
leaq 0xb(%rsp), %r15
pushq $0x1
popq %r12
leaq 0x2f(%rsp), %r14
pushq $0x2
popq %rbx
movq $0x0, 0x10(%rsp)
movl $0x0, 0x38(%rsp)
movl %ebp, %edi
movq %r15, %rsi
movq %r12, %rdx
callq 0x2140
testq %rax, %rax
je 0x6819
movzbl 0xb(%rsp), %eax
cmpl $0xa, %eax
je 0x6550
cmpl $0xd, %eax
je 0x6550
cmpl $0x3a, %eax
jne 0x6827
movb $0x0, 0x37(%rsp)
movl %ebp, %edi
movq %r14, %rsi
pushq $0x8
popq %rdx
callq 0x2140
cmpq $0x8, %rax
jne 0x6504
movq %r14, %rdi
leaq 0x2cf3(%rip), %rsi      # 0x9297
leaq 0x28(%rsp), %rdx
leaq 0x44(%rsp), %rcx
leaq 0x24(%rsp), %r8
xorl %eax, %eax
callq 0x21e0
cmpl $0x3, %eax
jne 0x6831
movl 0x28(%rsp), %r14d
movl 0x44(%rsp), %esi
movl 0x24(%rsp), %edx
cmpl $0x4, %edx
movq %r13, 0x48(%rsp)
je 0x6634
cmpl $0x2, %edx
je 0x6634
testl %edx, %edx
jne 0x663d
movl %edx, 0x54(%rsp)
movl %esi, 0x50(%rsp)
subl 0x38(%rsp), %esi
movl %esi, 0xc(%rsp)
movq 0x10(%r13), %rdi
addq %r14, %rsi
addq (%r13), %rsi
callq 0x21f0
movq %rax, 0x10(%r13)
movl 0xc(%rsp), %ecx
movq (%r13), %r13
testq %rcx, %rcx
je 0x664b
leaq (%rax,%r13), %rdi
movl $0xff, %esi
movq %rcx, %rdx
movq %rcx, 0x38(%rsp)
movq %rax, %rbx
callq 0x2100
addq 0x38(%rsp), %r13
jmp 0x664e
movq $0x0, 0x10(%rsp)
movl %r14d, %eax
movq $0x0, 0x18(%rsp)
jmp 0x6677
movq %rax, %rbx
movl 0x28(%rsp), %eax
movl 0x44(%rsp), %ecx
addl %eax, %ecx
movl %ecx, 0x38(%rsp)
addq %r13, %rbx
movq %rbx, 0x18(%rsp)
addq %rax, %r13
movq 0x48(%rsp), %rcx
movq %r13, (%rcx)
movl 0x54(%rsp), %edx
movl 0x50(%rsp), %esi
movl %esi, %ecx
shrl $0x8, %ecx
addl %esi, %r14d
addl %ecx, %r14d
addl %edx, %r14d
movb $0x0, 0x31(%rsp)
xorl %r13d, %r13d
movl %eax, %ebx
movl %ebp, %edi
leaq 0x2f(%rsp), %rsi
pushq $0x2
popq %rdx
callq 0x2140
cmpq %rbx, %r13
jae 0x6716
cmpq $0x2, %rax
jne 0x682e
leaq 0x2f(%rsp), %rdi
leaq 0x23db(%rip), %rsi      # 0x8a94
leaq 0xc(%rsp), %rdx
xorl %eax, %eax
callq 0x21e0
cmpl $0x1, %eax
jne 0x682e
movl 0xc(%rsp), %eax
movl 0x24(%rsp), %ecx
cmpl $0x4, %ecx
je 0x66f8
cmpl $0x2, %ecx
je 0x66f8
testl %ecx, %ecx
jne 0x6707
movq 0x18(%rsp), %rcx
testq %rcx, %rcx
je 0x6827
movb %al, (%rcx,%r13)
jmp 0x6707
movq 0x10(%rsp), %rcx
shll $0x8, %ecx
orl %eax, %ecx
movq %rcx, 0x10(%rsp)
addl %eax, %r14d
incq %r13
movl 0x28(%rsp), %eax
jmp 0x668d
cmpq $0x2, %rax
jne 0x682e
leaq 0x2f(%rsp), %rdi
leaq 0x2368(%rip), %rsi      # 0x8a94
leaq 0xc(%rsp), %rdx
xorl %eax, %eax
callq 0x21e0
cmpl $0x1, %eax
jne 0x682e
addb 0xc(%rsp), %r14b
jne 0x682e
movl 0x24(%rsp), %eax
cmpl $0x2, %eax
pushq $0x2
popq %rbx
je 0x677f
cmpl $0x4, %eax
movq 0x48(%rsp), %r13
leaq 0x2f(%rsp), %r14
movq 0x10(%rsp), %rcx
je 0x677a
cmpl $0x1, %eax
jne 0x6808
jmp 0x683d
shll $0xc, %ecx
jmp 0x678e
movq 0x48(%rsp), %r13
leaq 0x2f(%rsp), %r14
movq 0x10(%rsp), %rcx
shll $0x4, %ecx
movl 0x18(%r13), %eax
testl %eax, %eax
jne 0x67a0
cmpq $0x0, (%r13)
je 0x67fc
movl %ecx, %edx
subl %eax, %edx
jb 0x6831
movl $0x0, 0x38(%rsp)
cmpq %rdx, (%r13)
jae 0x6808
movq 0x10(%r13), %rdi
movq %rdx, %rsi
movq %rdx, 0x18(%rsp)
movq %rcx, 0x10(%rsp)
callq 0x21f0
movq %rax, 0x10(%r13)
movq (%r13), %rcx
leaq (%rax,%rcx), %rdi
movq 0x18(%rsp), %rdx
subq %rcx, %rdx
movl $0xff, %esi
callq 0x2100
movq 0x10(%rsp), %rcx
movq 0x18(%rsp), %rax
movq %rax, (%r13)
jmp 0x6808
movl %ecx, 0x18(%r13)
movl $0x0, 0x38(%rsp)
movq %rcx, 0x10(%rsp)
jmp 0x6550
pushq $0x1
jmp 0x6503
movl %ebp, %edi
callq 0x2120
xorl %ebx, %ebx
jmp 0x6504
pushq $0x2
jmp 0x6503
pushq $0x2
popq %rbx
movl %ebp, %edi
callq 0x2120
jmp 0x6504
xorl %ebx, %ebx
jmp 0x6831