// File: /workspace/github_c_makefile_star2_O3/goodpaul6[P]generic/script.c
// Function: unmarshal
static script_value_t* unmarshal(script_t* script, const char** pdesc, char** pmem)
{
#define ALIGN(m, type) (*m = (char*)((intptr_t)(*m) + (ALIGNOF(type) - 1) & -ALIGNOF(type)))
#define ALIGNOF(type) ((size_t)&((struct { char c; type d; } *)0)->d)
	
	const char* desc = *pdesc;
	
	switch (*desc)
	{
		case 'b':
		{
			ALIGN(pmem, char);
				
			script_value_t* val = new_value(script, VAL_BOOL);

			val->boolean = (char)*(char*)(*pmem);

			*pmem += sizeof(char);
			*pdesc += 1;

			return val;
		} break;
			
		case 'i':
		{
			ALIGN(pmem, int);

			script_value_t* val = new_value(script, VAL_NUMBER);
			val->number = (double)*(int*)(*pmem);

			*pmem += sizeof(int);
			*pdesc += 1;

			return val;
		} break;

		case 'g':
		{
			ALIGN(pmem, double);

			script_value_t* val = new_value(script, VAL_NUMBER);
			val->number = *(double*)(*pmem);

			*pmem += sizeof(double);
			*pdesc += 1;

			return val;
		} break;

		case 's':
		{
			ALIGN(pmem, const char*);

			const char* str = *(const char**)(*pmem);

			*pdesc += 1;

			if (!str)
				return new_value(script, VAL_NULL);
			else
			{
				script_value_t* val = new_value(script, VAL_STRING);

				val->string.length = strlen(str);
				val->string.data = emalloc(val->string.length + 1);

				strcpy(val->string.data, str);

				*pmem += sizeof(const char*);

				return val;
			}
		} break;

		case 'c':
		{
			int n = 1;
			int i = 1;

			if (isdigit(desc[i]))
			{
				n = 0;
				while (isdigit(desc[i]))
				{
					n = n * 10 + (desc[i] - '0');
					++i;
				}
			}
			*pdesc += i;

			if (n == 1)
			{
				script_value_t* val = new_value(script, VAL_CHAR);
				val->code = *(char*)(*pmem);

				*pmem += 1;

				return val;
			}
			else if (n > 1)
			{
				script_value_t* val = new_value(script, VAL_STRING);

				// TODO: Maybe check for buffer overflow etc
				const char* str = (const char*)(*pmem);

				val->string.length = strlen(str);
				val->string.data = emalloc(n);

				strcpy(val->string.data, str);

				*pmem += n;

				return val;
			}

			assert(0);
		} break;

		case 'p':
		{
			if (desc[1] == '{')
			{
				ALIGN(pmem, char*);

				*pdesc += 1;
				if (*pmem)
				{
					char* mem = *(char**)(*pmem);
					script_value_t* val = unmarshal(script, pdesc, &mem);
					return val;
				}

				*pmem += sizeof(char*);

				return new_value(script, VAL_NULL);
			}
			else
			{
				ALIGN(pmem, void*);

				script_value_t* val = new_value(script, VAL_NATIVE);

				val->nat.value = *(void**)(*pmem);
				val->nat.on_mark = val->nat.on_delete = NULL;
					
				*pmem += sizeof(void*);
				*pdesc += 1;

				return val;
			}
		} break;

		case '{':
		case '[':
		{
			char is_array = desc[0] == '[';

			int i = 1;
			int dp = 0;
			char nestedDesc[256];
			
			int bracket_count = 1;

			while (bracket_count)
			{
				if (dp >= 255)
				{
					printf("'unmarshal' exceeded maximum description length.\n");
					*pdesc += i + 1;
					return new_value(script, VAL_NULL);
				}
				
				if (desc[i] == '{' || desc[i] == '[')
					++bracket_count;

				if (desc[i] == '}' || desc[i] == ']')
					--bracket_count;

				if(bracket_count > 0)
					nestedDesc[dp++] = desc[i++];
			}
			nestedDesc[dp] = '\0';

			*pdesc += i + 1;

			char* ndp = nestedDesc;

			if (!is_array)
			{
				script_value_t* result = new_value(script, VAL_STRUCT_INSTANCE);
				vec_init(&result->ds.members, sizeof(script_value_t*));

				while(*ndp)
				{
					script_value_t* val = unmarshal(script, &ndp, pmem);
					vec_push_back(&result->ds.members, &val);
				}

				return result;
			}
			else
			{
				ALIGN(pmem, vector_t);

				vector_t* vec = (vector_t*)(*pmem);

				script_value_t* result = new_value(script, VAL_ARRAY);
				vec_init(&result->array, sizeof(script_value_t*));

				for(int i = 0; i < vec->length; ++i)
				{
					void* mem = vec_get(vec, i);

					script_value_t* val = unmarshal(script, &ndp, &mem);
					vec_push_back(&result->array, &val);

					ndp = nestedDesc;
				}

				return result;
			}
		} break;

		case '&':
		{
			script_value_t* val = new_value(script, VAL_NATIVE);

			val->nat.value = *pmem;
			val->nat.on_mark = val->nat.on_delete = NULL;

			*pdesc += 1;

			return val;
		} break;
	}

#undef ALIGNOF
#undef ALIGN

	return NULL;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x128, %rsp            # imm = 0x128
movq %rdx, %r13
movq %rsi, %r15
movq %rdi, %r14
movq (%rsi), %rbx
movb (%rbx), %al
movzbl %al, %ecx
xorl %r12d, %r12d
cmpl $0x6f, %ecx
jg 0x7acb
leal -0x62(%rcx), %edx
cmpl $0x7, %edx
ja 0x7ae7
leaq 0x776e(%rip), %rax      # 0xf20c
movslq (%rax,%rdx,4), %rcx
addq %rax, %rcx
jmpq *%rcx
movq %r14, %rdi
movl $0x1, %esi
callq 0x3322
movq %rax, %r12
movq (%r13), %rax
movb (%rax), %al
movb %al, 0x20(%r12)
incq (%r13)
jmp 0x7e2e
cmpl $0x70, %ecx
je 0x7c99
cmpl $0x73, %ecx
je 0x7ce0
cmpl $0x7b, %ecx
je 0x7af9
jmp 0x7e31
cmpl $0x26, %ecx
je 0x7d76
cmpl $0x5b, %ecx
jne 0x7e31
xorl %ecx, %ecx
movl $0x1, %edx
movl $0x1, %r12d
cmpl $0xff, %ecx
jge 0x7d49
movslq %r12d, %rsi
movb (%rbx,%rsi), %sil
movzbl %sil, %edi
orl $0x20, %edi
cmpl $0x7b, %edi
jne 0x7b27
incl %edx
cmpl $0x7d, %edi
jne 0x7b2e
decl %edx
testl %edx, %edx
jle 0x7b42
incl %r12d
movslq %ecx, %rdi
incl %ecx
movb %sil, -0x150(%rbp,%rdi)
testl %edx, %edx
jne 0x7b06
movslq %ecx, %rcx
movb $0x0, -0x150(%rbp,%rcx)
movslq %r12d, %rcx
addq %rbx, %rcx
incq %rcx
movq %rcx, (%r15)
leaq -0x150(%rbp), %rcx
movq %rcx, -0x38(%rbp)
cmpb $0x5b, %al
jne 0x7e46
movq (%r13), %r15
addq $0x7, %r15
andq $-0x8, %r15
movq %r15, (%r13)
movq %r14, %rdi
movl $0x6, %esi
callq 0x3322
movq %rax, %r12
movq %rax, %rbx
addq $0x20, %rbx
movl $0x8, %esi
movq %rbx, %rdi
callq 0xda7c
cmpq $0x0, 0x10(%r15)
je 0x7e31
movq %r12, -0x30(%rbp)
xorl %r13d, %r13d
movq %r14, %r12
leaq -0x150(%rbp), %r14
movq %r15, %rdi
movq %r13, %rsi
callq 0xdcf3
movq %rax, -0x40(%rbp)
movq %r12, %rdi
leaq -0x38(%rbp), %rsi
leaq -0x40(%rbp), %rdx
callq 0x7a62
movq %rax, -0x48(%rbp)
movq %rbx, %rdi
leaq -0x48(%rbp), %rsi
callq 0xdd50
movq %r14, -0x38(%rbp)
incq %r13
cmpq %r13, 0x10(%r15)
ja 0x7bc0
movq -0x30(%rbp), %r12
jmp 0x7e31
movq (%r13), %rax
addq $0x3, %rax
andq $-0x4, %rax
movq %rax, (%r13)
movq %r14, %rdi
movl $0x3, %esi
callq 0x3322
movq %rax, %r12
movq (%r13), %rax
cvtsi2sdl (%rax), %xmm0
movsd %xmm0, 0x20(%r12)
addq $0x4, (%r13)
jmp 0x7e2e
movq %r13, -0x30(%rbp)
callq 0x2270
movq (%rax), %rax
movsbq 0x1(%rbx), %rdx
testb $0x8, 0x1(%rax,%rdx,2)
jne 0x7d9f
incq %rbx
movq %rbx, (%r15)
jmp 0x7dd9
movq (%r13), %rax
addq $0x7, %rax
andq $-0x8, %rax
movq %rax, (%r13)
movq %r14, %rdi
movl $0x3, %esi
callq 0x3322
movq %rax, %r12
movq (%r13), %rax
movsd (%rax), %xmm0
movsd %xmm0, 0x20(%r12)
jmp 0x7e29
movq (%r13), %rax
addq $0x7, %rax
andq $-0x8, %rax
cmpb $0x7b, 0x1(%rbx)
movq %rax, (%r13)
jne 0x7e02
incq (%r15)
movq (%r13), %rax
testq %rax, %rax
je 0x7ef6
movq (%rax), %rax
leaq -0x150(%rbp), %rdx
movq %rax, (%rdx)
movq %r14, %rdi
movq %r15, %rsi
callq 0x7a62
jmp 0x7d6e
movq (%r13), %rax
addq $0x7, %rax
andq $-0x8, %rax
movq %r13, %rbx
movq %rax, (%r13)
movq (%rax), %r13
incq (%r15)
testq %r13, %r13
je 0x7efe
movq %r14, %rdi
movl $0x4, %esi
callq 0x3322
movq %rax, %r12
movq %r13, %rdi
callq 0x20b0
movl %eax, 0x20(%r12)
leal 0x1(%rax), %edi
callq 0x21c0
testq %rax, %rax
je 0x7f19
movq %rax, 0x28(%r12)
movq %rax, %rdi
movq %r13, %rsi
callq 0x2050
addq $0x8, (%rbx)
jmp 0x7e31
leaq 0x9d31(%rip), %rdi      # 0x11a81
callq 0x2060
movq (%r15), %rax
movslq %r12d, %rcx
addq %rcx, %rax
incq %rax
movq %rax, (%r15)
movq %r14, %rdi
xorl %esi, %esi
callq 0x3322
movq %rax, %r12
jmp 0x7e31
movq %r14, %rdi
movl $0x8, %esi
callq 0x3322
movq %rax, %r12
movq (%r13), %rax
movq %rax, 0x20(%r12)
xorpd %xmm0, %xmm0
movupd %xmm0, 0x28(%r12)
jmp 0x7e2e
xorl %r13d, %r13d
movl $0x1, %ecx
movsbl %dl, %edx
leal (%r13,%r13,4), %esi
leal (%rdx,%rsi,2), %r13d
addl $-0x30, %r13d
movsbq 0x1(%rbx,%rcx), %rdx
incq %rcx
testb $0x8, 0x1(%rax,%rdx,2)
jne 0x7da7
movl %ecx, %eax
addq %rax, %rbx
movq %rbx, (%r15)
cmpl $0x1, %r13d
jne 0x7ea0
movq %r14, %rdi
movl $0x2, %esi
callq 0x3322
movq %rax, %r12
movq -0x30(%rbp), %rcx
movq (%rcx), %rax
movb (%rax), %al
movb %al, 0x20(%r12)
movl $0x1, %r14d
jmp 0x7eee
movq %r14, %rdi
movl $0x8, %esi
callq 0x3322
movq %rax, %r12
movq (%r13), %rax
movq (%rax), %rax
movq %rax, 0x20(%r12)
xorpd %xmm0, %xmm0
movupd %xmm0, 0x28(%r12)
addq $0x8, (%r13)
incq (%r15)
movq %r12, %rax
addq $0x128, %rsp            # imm = 0x128
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %r14, %rdi
movl $0x7, %esi
callq 0x3322
movq %rax, %r12
movq %rax, %r15
addq $0x20, %r15
movl $0x8, %esi
movq %r15, %rdi
callq 0xda7c
cmpb $0x0, -0x150(%rbp)
je 0x7e31
leaq -0x40(%rbp), %rbx
movq %r14, %rdi
leaq -0x38(%rbp), %rsi
movq %r13, %rdx
callq 0x7a62
movq %rax, -0x40(%rbp)
movq %r15, %rdi
movq %rbx, %rsi
callq 0xdd50
movq -0x38(%rbp), %rax
cmpb $0x0, (%rax)
jne 0x7e77
jmp 0x7e31
jle 0x7f27
movq %r14, %rdi
movl $0x4, %esi
callq 0x3322
movq %rax, %r12
movq -0x30(%rbp), %rax
movq (%rax), %r15
movq %r15, %rdi
callq 0x20b0
movl %eax, 0x20(%r12)
movl %r13d, %r14d
movq %r14, %rdi
callq 0x21c0
testq %rax, %rax
je 0x7f19
movq %rax, 0x28(%r12)
movq %rax, %rdi
movq %r15, %rsi
callq 0x2050
movq -0x30(%rbp), %rcx
addq %r14, (%rcx)
jmp 0x7e31
movq $0x8, (%r13)
movq %r14, %rdi
xorl %esi, %esi
addq $0x128, %rsp            # imm = 0x128
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x3322
leaq 0x9d77(%rip), %rdi      # 0x11c97
xorl %eax, %eax
callq 0x388c
leaq 0x7c5e(%rip), %rdi      # 0xfb8c
leaq 0x7c59(%rip), %rsi      # 0xfb8e
leaq 0x7c5b(%rip), %rcx      # 0xfb97
movl $0x10a7, %edx           # imm = 0x10A7
callq 0x2100