// File: /workspace/github_c_makefile_star2_O1/michaelforney[P]cproc/decl.c
// Function: declaratortypes
static void
declaratortypes(struct scope *s, struct list *result, char **name, struct scope **funcscope, bool allowabstract)
{
	struct list *ptr, *prev;
	struct type *t;
	struct decl *d, **paramend;
	struct expr *e;
	enum typequal tq;
	bool allowattr;

	while (consume(TMUL)) {
		attr(NULL, 0);
		tq = QUALNONE;
		while (typequal(&tq))
			;
		t = mkpointertype(NULL, tq);
		listinsert(result, &t->link);
	}
	if (name)
		*name = NULL;
	ptr = result->next;
	prev = ptr->prev;
	switch (tok.kind) {
	case TLPAREN:
		next();
		if (allowabstract) {
			switch (tok.kind) {
			case TMUL:
			case TLPAREN:
				break;
			case TIDENT:
				if (!istypename(s, tok.lit))
					break;
				/* fallthrough */
			default:
				allowattr = true;
				goto func;
			}
		}
		declaratortypes(s, result, name, funcscope, allowabstract);
		expect(TRPAREN, "after parenthesized declarator");
		allowattr = false;
		break;
	case TIDENT:
		if (!name)
			error(&tok.loc, "identifier not allowed in abstract declarator");
		*name = tok.lit;
		next();
		allowattr = true;
		break;
	default:
		if (!allowabstract)
			error(&tok.loc, "expected '(' or identifier");
		allowattr = true;
	}
	for (;;) {
		switch (tok.kind) {
		case TLPAREN:  /* function declarator */
			next();
		func:
			t = mktype(TYPEFUNC, 0);
			t->qual = QUALNONE;
			t->u.func.isvararg = false;
			t->u.func.params = NULL;
			t->u.func.nparam = 0;
			paramend = &t->u.func.params;
			s = mkscope(s);
			d = NULL;
			do {
				if (consume(TELLIPSIS)) {
					t->u.func.isvararg = true;
					break;
				}
				if (tok.kind == TRPAREN)
					break;
				d = parameter(s);
				if (d->name)
					scopeputdecl(s, d);
				*paramend = d;
				paramend = &d->next;
				++t->u.func.nparam;
			} while (consume(TCOMMA));
			expect(TRPAREN, "to close function declarator");
			if (funcscope && ptr->prev == prev) {
				/* we may need to re-open the scope later if this is a function definition */
				*funcscope = s;
				s = s->parent;
			} else {
				s = delscope(s);
			}
			if (t->u.func.nparam == 1 && !t->u.func.isvararg && d->type->kind == TYPEVOID && !d->name) {
				t->u.func.params = NULL;
				t->u.func.nparam = 0;
			}
			listinsert(ptr->prev, &t->link);
			allowattr = true;
			break;
		case TLBRACK:  /* array declarator */
			if (allowattr && attr(NULL, 0))
				goto attr;
			next();
			t = mkarraytype(NULL, QUALNONE, 0);
			while (consume(TSTATIC) || typequal(&t->u.array.ptrqual))
				;
			if (tok.kind == TMUL && peek(TRBRACK)) {
				t->prop |= PROPVM;
				t->incomplete = false;
			} else if (!consume(TRBRACK)) {
				e = assignexpr(s);
				if (!(e->type->prop & PROPINT))
					error(&tok.loc, "array length expression must have integer type");
				t->u.array.length = e;
				t->incomplete = false;
				expect(TRBRACK, "after array length");
			}
			listinsert(ptr->prev, &t->link);
			allowattr = true;
			break;
		case T__ATTRIBUTE__:
			if (!allowattr)
				error(&tok.loc, "attribute not allowed after parenthesized declarator");
			/* attribute applies to identifier if ptr->prev == result, otherwise type ptr->prev */
			gnuattr(NULL, 0);
		attr:
			break;
		default:
			return;
		}
	}
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x98, %rsp
movl %r8d, %ebp
movq %rcx, 0x28(%rsp)
movq %rdx, %rbx
movq %rsi, %r15
movq %rdi, %r14
movl $0x4b, %edi
callq 0xb099
testb %al, %al
je 0x5d49
leaq 0x24(%rsp), %r12
xorl %edi, %edi
xorl %esi, %esi
callq 0x33ec
movl $0x0, 0x24(%rsp)
movq %r12, %rdi
callq 0x58c2
testl %eax, %eax
jne 0x5d18
movl 0x24(%rsp), %esi
xorl %edi, %edi
callq 0xd80f
leaq 0x28(%rax), %rsi
movq %r15, %rdi
callq 0xe272
movl $0x4b, %edi
callq 0xb099
testb %al, %al
jne 0x5d07
testq %rbx, %rbx
je 0x5d55
movq $0x0, (%rbx)
movq 0x8(%r15), %rax
movq %rax, 0x30(%rsp)
movq (%rax), %rax
movq %rax, 0x68(%rsp)
leaq 0x1639b(%rip), %r13     # 0x1c108
movl (%r13), %eax
cmpl $0x4, %eax
je 0x5dec
cmpl $0x42, %eax
jne 0x5e11
callq 0xa9d0
testb %bpl, %bpl
je 0x5dc0
movl (%r13), %eax
cmpl $0x4b, %eax
je 0x5dc0
cmpl $0x42, %eax
je 0x5dc0
cmpl $0x4, %eax
jne 0x5f54
movq 0x20(%r13), %rsi
movq %r14, %rdi
movl $0x1, %edx
callq 0xc6f9
testq %rax, %rax
je 0x5dc0
cmpl $0x0, 0x8(%rax)
je 0x5f54
movzbl %bpl, %r8d
movq %r14, %rdi
movq %r15, %rsi
movq %rbx, %rdx
movq 0x28(%rsp), %rcx
callq 0x5cd2
leaq 0xcfec(%rip), %rsi      # 0x12dca
movl $0x43, %edi
callq 0xb07a
xorl %ebx, %ebx
jmp 0x5e2e
testq %rbx, %rbx
jne 0x5e03
leaq 0x8(%r13), %rdi
leaq 0xcf10(%rip), %rsi      # 0x12d0c
xorl %eax, %eax
callq 0xd56a
movq 0x20(%r13), %rax
movq %rax, (%rbx)
callq 0xa9d0
jmp 0x5e2c
movb $0x1, %bl
testb %bpl, %bpl
jne 0x5e2e
leaq 0x8(%r13), %rdi
leaq 0xcf17(%rip), %rsi      # 0x12d3a
xorl %eax, %eax
callq 0xd56a
jmp 0x5e2e
movb $0x1, %bl
leaq 0x8(%r13), %r15
leaq 0xcf7b(%rip), %r12      # 0x12db4
leaq 0xcf61(%rip), %rbp      # 0x12da1
movl (%r13), %eax
cmpl $0x3f, %eax
je 0x5ebb
cmpl $0x40, %eax
jne 0x5f46
testb $0x1, %bl
je 0x5e64
xorl %edi, %edi
xorl %esi, %esi
callq 0x33ec
testb %al, %al
jne 0x5e40
callq 0xa9d0
xorl %edi, %edi
xorl %esi, %esi
xorl %edx, %edx
callq 0xd86a
movq %rax, %rbx
leaq 0x48(%rax), %r13
movl $0x27, %edi
callq 0xb099
testb %al, %al
jne 0x5e7b
movq %r13, %rdi
callq 0x58c2
testl %eax, %eax
jne 0x5e7b
leaq 0x1626c(%rip), %r13     # 0x1c108
cmpl $0x4b, (%r13)
jne 0x5edb
movl $0x41, %edi
callq 0xafb3
testb %al, %al
je 0x5edb
orb $0x40, 0x4(%rbx)
movb $0x0, 0x3c(%rbx)
jmp 0x5f2b
testb $0x1, %bl
jne 0x5ecd
movq %r15, %rdi
movq %r12, %rsi
xorl %eax, %eax
callq 0xd56a
xorl %edi, %edi
xorl %esi, %esi
callq 0x3483
jmp 0x5e40
movl $0x41, %edi
callq 0xb099
testb %al, %al
jne 0x5f2b
movq %r14, %rdi
callq 0x7520
movq %rax, %r13
movq 0x8(%rax), %rax
testb $0x2, 0x4(%rax)
jne 0x5f0f
movq %r15, %rdi
leaq 0xce6a(%rip), %rsi      # 0x12d72
xorl %eax, %eax
callq 0xd56a
movq %r13, 0x40(%rbx)
movb $0x0, 0x3c(%rbx)
movl $0x41, %edi
movq %rbp, %rsi
callq 0xb07a
leaq 0x161dd(%rip), %r13     # 0x1c108
movq 0x30(%rsp), %rax
movq (%rax), %rdi
addq $0x28, %rbx
movq %rbx, %rsi
callq 0xe272
movb $0x1, %bl
jmp 0x5e40
cmpl $0x42, %eax
jne 0x612c
callq 0xa9d0
movl $0xe, %edi
xorl %esi, %esi
callq 0xd7e4
movq %rax, %rbx
movl $0x0, 0x38(%rax)
movb $0x0, 0x40(%rax)
leaq 0x48(%rax), %r15
xorps %xmm0, %xmm0
movups %xmm0, 0x48(%rax)
movq %r14, %rdi
callq 0xc684
movq %rax, %r12
leaq 0x78(%rsp), %r14
leaq 0x8(%r13), %rax
movq %rax, 0x58(%rsp)
xorl %ebp, %ebp
movq %r15, 0x60(%rsp)
movq %r15, %r13
movq %rbx, 0x70(%rsp)
movl $0x62, %edi
callq 0xb099
testb %al, %al
jne 0x613e
leaq 0x1614e(%rip), %rax     # 0x1c108
cmpl $0x43, (%rax)
je 0x6142
xorl %edi, %edi
xorl %esi, %esi
callq 0x33ec
movq %r14, %rdi
movq %r12, %rsi
leaq 0x3c(%rsp), %rdx
xorl %ecx, %ecx
xorl %r8d, %r8d
callq 0x3912
movq 0x88(%rsp), %rax
movq %rax, 0x50(%rsp)
movups 0x78(%rsp), %xmm0
movaps %xmm0, 0x40(%rsp)
cmpq $0x0, 0x40(%rsp)
jne 0x6013
movq 0x58(%rsp), %rdi
leaq 0xcddd(%rip), %rsi      # 0x12de9
xorl %eax, %eax
callq 0xd56a
testl $0xffffffdf, 0x3c(%rsp) # imm = 0xFFFFFFDF
je 0x6030
movq 0x58(%rsp), %rdi
leaq 0xcde1(%rip), %rsi      # 0x12e0a
xorl %eax, %eax
callq 0xd56a
movq 0x50(%rsp), %rax
movq %rax, 0x10(%rsp)
movaps 0x40(%rsp), %xmm0
movups %xmm0, (%rsp)
movq %r14, %rdi
movq %r12, %r14
movq %r12, %rsi
leaq 0x90(%rsp), %rdx
xorl %ecx, %ecx
movl $0x1, %r8d
callq 0x4ab2
movq 0x88(%rsp), %rax
movq %rax, 0x50(%rsp)
movups 0x78(%rsp), %xmm0
movaps %xmm0, 0x40(%rsp)
movq 0x40(%rsp), %rdi
leaq 0x48(%rsp), %rsi
callq 0xdc0b
movq %rax, %r12
movq %rax, 0x40(%rsp)
movq 0x90(%rsp), %rbx
movl 0x48(%rsp), %r15d
movl $0x48, %edi
callq 0xe13e
movq %rax, %rbp
xorps %xmm0, %xmm0
movups %xmm0, (%rax)
movups %xmm0, 0x10(%rax)
movups %xmm0, 0x20(%rax)
movups %xmm0, 0x30(%rax)
movq $0x0, 0x40(%rax)
movq %rbx, (%rax)
movq $0x1, 0x8(%rax)
movq %r12, 0x10(%rax)
movl %r15d, 0x18(%rax)
testq %r12, %r12
je 0x60e3
movl 0x8(%r12), %eax
movl %eax, 0x40(%rbp)
movl $0x2, 0x44(%rbp)
cmpq $0x0, (%rbp)
movq 0x70(%rsp), %rbx
movq %r14, %r12
je 0x6104
movq %r12, %rdi
movq %rbp, %rsi
callq 0xc628
movq %rbp, (%r13)
movq %rbp, %r13
addq $0x38, %r13
incq 0x50(%rbx)
movl $0x6e, %edi
callq 0xb099
testb %al, %al
leaq 0x78(%rsp), %r14
jne 0x5fa1
jmp 0x6142
addq $0x98, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movb $0x1, 0x40(%rbx)
leaq 0xcc0c(%rip), %rsi      # 0x12d55
movl $0x43, %edi
callq 0xb07a
cmpq $0x0, 0x28(%rsp)
je 0x616a
movq 0x30(%rsp), %rax
movq 0x68(%rsp), %rcx
cmpq %rcx, (%rax)
je 0x6177
movq %r12, %rdi
callq 0xc6b9
movq %rax, %r14
jmp 0x6184
movq 0x28(%rsp), %rax
movq %r12, (%rax)
movq 0x58(%r12), %r14
leaq 0x15f7d(%rip), %r13     # 0x1c108
cmpq $0x1, 0x50(%rbx)
jne 0x61b3
cmpb $0x0, 0x40(%rbx)
jne 0x61b3
movq 0x10(%rbp), %rax
cmpl $0x1, (%rax)
jne 0x61b3
cmpq $0x0, (%rbp)
jne 0x61b3
xorps %xmm0, %xmm0
movq 0x60(%rsp), %rax
movups %xmm0, (%rax)
movq 0x30(%rsp), %rax
movq (%rax), %rdi
addq $0x28, %rbx
movq %rbx, %rsi
callq 0xe272
jmp 0x5e2c