// File: /workspace/github_c_makefile_star2_O2/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, %r15
movq %rsi, %rbx
movq %rdi, %r12
movq (%rsi), %r14
movb (%r14), %al
movzbl %al, %ecx
xorl %r13d, %r13d
leal -0x62(%rcx), %edx
cmpl $0x7, %edx
jbe 0x6d34
cmpl $0x26, %ecx
je 0x6ee7
cmpl $0x5b, %ecx
je 0x6cdf
cmpl $0x70, %ecx
je 0x6f0b
cmpl $0x73, %ecx
je 0x6e90
cmpl $0x7b, %ecx
jne 0x7056
movq %r12, -0x30(%rbp)
xorl %ecx, %ecx
pushq $0x1
popq %r12
movl %r12d, %edx
movl %r12d, %r12d
movl %ecx, %esi
testl %edx, %edx
je 0x6de9
cmpl $0xff, %ecx
jae 0x6f4d
movb (%r14,%r12), %dil
movzbl %dil, %r8d
orl $0x20, %r8d
cmpl $0x7b, %r8d
jne 0x6d19
incl %edx
cmpl $0x7d, %r8d
jne 0x6d21
decl %edx
testl %edx, %edx
jle 0x6cef
incl %r12d
incl %ecx
movb %dil, -0x150(%rbp,%rsi)
jmp 0x6cec
leaq 0x6491(%rip), %rax      # 0xd1cc
movslq (%rax,%rdx,4), %rcx
addq %rax, %rcx
jmpq *%rcx
pushq $0x1
popq %rsi
movq %r12, %rdi
callq 0x2fb8
movq %rax, %r13
movq (%r15), %rax
movb (%rax), %al
movb %al, 0x20(%r13)
incq (%r15)
jmp 0x7053
movq (%r15), %rax
addq $0x7, %rax
andq $-0x8, %rax
movq %rax, (%r15)
pushq $0x3
popq %rsi
movq %r12, %rdi
callq 0x2fb8
movq %rax, %r13
movq (%r15), %rax
movsd (%rax), %xmm0
movsd %xmm0, 0x20(%r13)
jmp 0x704f
callq 0x2270
movq (%rax), %rax
movsbq 0x1(%r14), %rcx
movzwl (%rax,%rcx,2), %esi
btl $0xb, %esi
jb 0x6f78
incq %r14
movq %r14, (%rbx)
jmp 0x6fb4
movq (%r15), %rax
addq $0x3, %rax
andq $-0x4, %rax
movq %rax, (%r15)
pushq $0x3
popq %rsi
movq %r12, %rdi
callq 0x2fb8
movq %rax, %r13
movq (%r15), %rax
cvtsi2sdl (%rax), %xmm0
movsd %xmm0, 0x20(%r13)
addq $0x4, (%r15)
jmp 0x7053
movb $0x0, -0x150(%rbp,%rsi)
leaq (%r14,%r12), %rcx
incq %rcx
movq %rcx, (%rbx)
leaq -0x150(%rbp), %rbx
movq %rbx, -0x38(%rbp)
cmpb $0x5b, %al
jne 0x6fd4
movq %r15, %rax
movq (%r15), %r15
addq $0x7, %r15
andq $-0x8, %r15
movq %r15, (%rax)
pushq $0x6
popq %rsi
movq -0x30(%rbp), %r12
movq %r12, %rdi
callq 0x2fb8
movq %rax, %rbx
movq %rax, -0x48(%rbp)
addq $0x20, %rbx
pushq $0x8
popq %rsi
movq %rbx, %rdi
callq 0xbf0c
xorl %r13d, %r13d
leaq -0x150(%rbp), %r14
cmpq %r13, 0x10(%r15)
jbe 0x7027
movq %r15, %rdi
movq %r13, %rsi
callq 0xc15c
movq %rax, -0x40(%rbp)
movq %r12, %rdi
leaq -0x38(%rbp), %rsi
leaq -0x40(%rbp), %rdx
callq 0x6c85
movq %rax, -0x50(%rbp)
movq %rbx, %rdi
leaq -0x50(%rbp), %rsi
callq 0xc1b9
movq %r14, -0x38(%rbp)
incq %r13
jmp 0x6e4e
movq (%r15), %rax
addq $0x7, %rax
andq $-0x8, %rax
movq %rax, (%r15)
movq (%rax), %r14
incq (%rbx)
testq %r14, %r14
je 0x70b5
pushq $0x4
popq %rsi
movq %r12, %rdi
callq 0x2fb8
movq %rax, %r13
movq %r14, %rdi
callq 0x20b0
movl %eax, 0x20(%r13)
leal 0x1(%rax), %edi
callq 0x325f
movq %rax, 0x28(%r13)
movq %rax, %rdi
movq %r14, %rsi
callq 0x2050
addq $0x8, (%r15)
jmp 0x7056
pushq $0x8
popq %rsi
movq %r12, %rdi
callq 0x2fb8
movq %rax, %r13
movq (%r15), %rax
movq %rax, 0x20(%r13)
xorpd %xmm0, %xmm0
movupd %xmm0, 0x28(%r13)
jmp 0x7053
movq (%r15), %rax
addq $0x7, %rax
andq $-0x8, %rax
cmpb $0x7b, 0x1(%r14)
movq %rax, (%r15)
jne 0x702d
incq (%rbx)
movq (%r15), %rax
testq %rax, %rax
je 0x70ae
movq (%rax), %rax
leaq -0x150(%rbp), %rdx
movq %rax, (%rdx)
movq %r12, %rdi
movq %rbx, %rsi
callq 0x6c85
jmp 0x6f70
leaq 0x8b35(%rip), %rdi      # 0xfa89
callq 0x2060
movq (%rbx), %rax
addq %r12, %rax
incq %rax
movq %rax, (%rbx)
movq -0x30(%rbp), %rdi
xorl %esi, %esi
callq 0x2fb8
movq %rax, %r13
jmp 0x7056
pushq $0x1
popq %rdx
xorl %r13d, %r13d
btl $0xb, %esi
jae 0x6fa2
movsbl %cl, %ecx
imull $0xa, %r13d, %esi
leal (%rsi,%rcx), %r13d
addl $-0x30, %r13d
movsbq 0x1(%r14,%rdx), %rcx
incq %rdx
movzwl (%rax,%rcx,2), %esi
jmp 0x6f7e
movl %edx, %eax
addq %rax, %r14
movq %r14, (%rbx)
cmpl $0x1, %r13d
jne 0x706b
pushq $0x2
popq %rsi
movq %r12, %rdi
callq 0x2fb8
movq %rax, %r13
movq (%r15), %rax
movb (%rax), %al
movb %al, 0x20(%r13)
pushq $0x1
popq %r14
jmp 0x70a9
pushq $0x7
popq %rsi
movq -0x30(%rbp), %rdi
callq 0x2fb8
movq %rax, %r14
movq %rax, -0x48(%rbp)
addq $0x20, %r14
pushq $0x8
popq %rsi
movq %r14, %rdi
callq 0xbf0c
leaq -0x38(%rbp), %r12
leaq -0x40(%rbp), %r13
cmpb $0x0, (%rbx)
je 0x7027
movq -0x30(%rbp), %rdi
movq %r12, %rsi
movq %r15, %rdx
callq 0x6c85
movq %rax, -0x40(%rbp)
movq %r14, %rdi
movq %r13, %rsi
callq 0xc1b9
movq -0x38(%rbp), %rbx
jmp 0x6ffe
movq -0x48(%rbp), %r13
jmp 0x7056
pushq $0x8
popq %rsi
movq %r12, %rdi
callq 0x2fb8
movq %rax, %r13
movq (%r15), %rax
movq (%rax), %rax
movq %rax, 0x20(%r13)
xorpd %xmm0, %xmm0
movupd %xmm0, 0x28(%r13)
addq $0x8, (%r15)
incq (%rbx)
movq %r13, %rax
addq $0x128, %rsp            # imm = 0x128
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jle 0x70d0
pushq $0x4
popq %rsi
movq %r12, %rdi
callq 0x2fb8
movq %rax, %r12
movq (%r15), %rbx
movq %rbx, %rdi
callq 0x20b0
movl %eax, 0x20(%r12)
movl %r13d, %r14d
movq %r12, %r13
movq %r14, %rdi
callq 0x325f
movq %rax, 0x28(%r12)
movq %rax, %rdi
movq %rbx, %rsi
callq 0x2050
addq %r14, (%r15)
jmp 0x7056
movq $0x8, (%r15)
movq %r12, %rdi
xorl %esi, %esi
addq $0x128, %rsp            # imm = 0x128
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x2fb8
leaq 0x6abd(%rip), %rdi      # 0xdb94
leaq 0x6ab8(%rip), %rsi      # 0xdb96
leaq 0x6aba(%rip), %rcx      # 0xdb9f
movl $0x10a7, %edx           # imm = 0x10A7
callq 0x2100