// File: /workspace/github_c_makefile_star2_O0/lucvoo[P]sparse-dev/parse.c
// Function: external_declaration
struct token *external_declaration(struct token *token, struct symbol_list **list,
		validate_decl_t validate_decl)
{
	struct ident *ident = NULL;
	struct symbol *decl;
	struct decl_state ctx = { .ident = &ident };
	struct ctype saved;
	struct symbol *base_type;
	unsigned long mod;
	int is_typedef;

	/* Top-level inline asm or static assertion? */
	if (token_type(token) == TOKEN_IDENT) {
		struct symbol *s = lookup_keyword(token->ident, NS_KEYWORD);
		if (s && s->op->toplevel)
			return s->op->toplevel(token, list);
	}

	/* Parse declaration-specifiers, if any */
	token = declaration_specifiers(token, &ctx);
	mod = decl_modifiers(&ctx);
	decl = alloc_symbol(token->pos, SYM_NODE);
	/* Just a type declaration? */
	if (match_op(token, ';')) {
		apply_modifiers(token->pos, &ctx);
		return token->next;
	}

	saved = ctx.ctype;
	token = declarator(token, &ctx);
	token = handle_asm_name(token, &ctx);
	token = handle_attributes(token, &ctx);
	apply_modifiers(token->pos, &ctx);

	decl->ctype = ctx.ctype;
	decl->ctype.modifiers |= mod;
	decl->cleanup = ctx.cleanup;
	decl->endpos = token->pos;

	/* Just a type declaration? */
	if (!ident) {
		warning(token->pos, "missing identifier in declaration");
		return expect(token, ';', "at the end of type declaration");
	}

	/* type define declaration? */
	is_typedef = ctx.storage_class == MOD_USERTYPE;

	/* Typedefs don't have meaningful storage */
	if (is_typedef)
		decl->ctype.modifiers |= MOD_USERTYPE;

	bind_symbol(decl, ident, is_typedef ? NS_TYPEDEF: NS_SYMBOL);

	base_type = decl->ctype.base_type;

	if (is_typedef) {
		if (base_type && !base_type->ident) {
			switch (base_type->type) {
			case SYM_STRUCT:
			case SYM_UNION:
			case SYM_ENUM:
			case SYM_RESTRICT:
				base_type->ident = ident;
				break;
			default:
				break;
			}
		}
	} else if (base_type && base_type->type == SYM_FN) {
		if (base_type->ctype.base_type == &autotype_ctype) {
			sparse_error(decl->pos, "'%s()' has __auto_type return type",
				show_ident(decl->ident));
			base_type->ctype.base_type = &int_ctype;
		}
		if (base_type->ctype.base_type == &incomplete_ctype) {
			warning(decl->pos, "'%s()' has implicit return type",
				show_ident(decl->ident));
			base_type->ctype.base_type = &int_ctype;
		}
		/* apply attributes placed after the declarator */
		decl->ctype.modifiers |= ctx.f_modifiers;

		/* K&R argument declaration? */
		if (lookup_type(token))
			return parse_k_r_arguments(token, decl, list);
		if (match_op(token, '{'))
			return parse_function_body(token, decl, list);

		if (!(decl->ctype.modifiers & MOD_STATIC))
			decl->ctype.modifiers |= MOD_EXTERN;
	} else if (base_type == &void_ctype && !(decl->ctype.modifiers & MOD_EXTERN)) {
		sparse_error(token->pos, "void declaration");
	}
	if (base_type == &incomplete_ctype) {
		warning(decl->pos, "'%s' has implicit type", show_ident(decl->ident));
		decl->ctype.base_type = &int_ctype;;
	}

	for (;;) {
		if (!is_typedef && match_op(token, '=')) {
			struct token *next = token->next;
			token = initializer(&decl->initializer, next);
			if (token == next)
				sparse_error(token->pos, "expression expected before '%s'", show_token(token));
		}
		if (!is_typedef) {
			if (validate_decl)
				validate_decl(decl);

			if (decl->initializer && decl->ctype.modifiers & MOD_EXTERN) {
				warning(decl->pos, "symbol with external linkage has initializer");
				decl->ctype.modifiers &= ~MOD_EXTERN;
			}

			if (!(decl->ctype.modifiers & (MOD_EXTERN | MOD_INLINE))) {
				add_symbol(list, decl);
				fn_local_symbol(decl);
			}
		}
		check_declaration(decl);
		if (decl->same_symbol) {
			decl->definition = decl->same_symbol->definition;
			decl->op = decl->same_symbol->op;
			if (is_typedef) {
				// TODO: handle -std=c89 --pedantic
				check_duplicates(decl);
			}
		}

		if (ctx.autotype) {
			const char *msg = NULL;
			if (decl->ctype.base_type != &autotype_ctype)
				msg = "on non-identifier";
			else if (match_op(token, ','))
				msg = "on declaration list";
			else if (!decl->initializer)
				msg = "without initializer";
			else if (decl->initializer->type == EXPR_SYMBOL &&
				 decl->initializer->symbol == decl)
				msg = "on self-init var";
			if (msg) {
				sparse_error(decl->pos, "__auto_type %s", msg);
				decl->ctype.base_type = &bad_ctype;
			}
		}

		if (!match_op(token, ','))
			break;

		token = token->next;
		ident = NULL;
		decl = alloc_symbol(token->pos, SYM_NODE);
		ctx.ctype = saved;
		ctx.cleanup = NULL;
		token = handle_attributes(token, &ctx);
		token = declarator(token, &ctx);
		token = handle_asm_name(token, &ctx);
		token = handle_attributes(token, &ctx);
		apply_modifiers(token->pos, &ctx);
		decl->ctype = ctx.ctype;
		decl->ctype.modifiers |= mod;
		decl->cleanup = ctx.cleanup;
		decl->endpos = token->pos;
		if (!ident) {
			sparse_error(token->pos, "expected identifier name in type definition");
			return token;
		}

		if (is_typedef)
			decl->ctype.modifiers |= MOD_USERTYPE;

		bind_symbol(decl, ident, is_typedef ? NS_TYPEDEF: NS_SYMBOL);

		/* Function declarations are automatically extern unless specifically static */
		base_type = decl->ctype.base_type;
		if (!is_typedef && base_type && base_type->type == SYM_FN) {
			if (!(decl->ctype.modifiers & MOD_STATIC))
				decl->ctype.modifiers |= MOD_EXTERN;
		}
	}
	return expect(token, ';', "at end of declaration");
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x110, %rsp            # imm = 0x110
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movq $0x0, -0x28(%rbp)
leaq -0x88(%rbp), %rdi
xorl %esi, %esi
movl $0x58, %edx
callq 0x11130
leaq -0x28(%rbp), %rax
movq %rax, -0x60(%rbp)
movq -0x10(%rbp), %rax
movq (%rax), %rax
andq $0x3f, %rax
cmpl $0x3, %eax
jne 0x23c43
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rdi
movl $0x100, %esi            # imm = 0x100
callq 0x244c0
movq %rax, -0xd0(%rbp)
cmpq $0x0, -0xd0(%rbp)
je 0x23c41
movq -0xd0(%rbp), %rax
movq 0x40(%rax), %rax
cmpq $0x0, 0x38(%rax)
je 0x23c41
movq -0xd0(%rbp), %rax
movq 0x40(%rax), %rax
movq 0x38(%rax), %rax
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
callq *%rax
movq %rax, -0x8(%rbp)
jmp 0x244a9
jmp 0x23c43
movq -0x10(%rbp), %rdi
leaq -0x88(%rbp), %rsi
callq 0x23280
movq %rax, -0x10(%rbp)
leaq -0x88(%rbp), %rdi
callq 0x24510
movq %rax, -0xc0(%rbp)
movq -0x10(%rbp), %rax
movq (%rax), %rdi
movl $0x3, %esi
callq 0x3f4d0
movq %rax, -0x30(%rbp)
movq -0x10(%rbp), %rdi
movl $0x3b, %esi
callq 0x22f80
cmpl $0x0, %eax
je 0x23cb6
movq -0x10(%rbp), %rax
movq (%rax), %rdi
leaq -0x88(%rbp), %rsi
callq 0x23660
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x8(%rbp)
jmp 0x244a9
leaq -0x88(%rbp), %rsi
leaq -0xb0(%rbp), %rdi
movl $0x28, %edx
callq 0x111d0
movq -0x10(%rbp), %rdi
leaq -0x88(%rbp), %rsi
callq 0x23620
movq %rax, -0x10(%rbp)
movq -0x10(%rbp), %rdi
leaq -0x88(%rbp), %rsi
callq 0x24550
movq %rax, -0x10(%rbp)
movq -0x10(%rbp), %rdi
leaq -0x88(%rbp), %rsi
callq 0x24630
movq %rax, -0x10(%rbp)
movq -0x10(%rbp), %rax
movq (%rax), %rdi
leaq -0x88(%rbp), %rsi
callq 0x23660
movq -0x30(%rbp), %rdi
addq $0x48, %rdi
addq $0x18, %rdi
leaq -0x88(%rbp), %rsi
movl $0x28, %edx
callq 0x111d0
movq -0xc0(%rbp), %rcx
movq -0x30(%rbp), %rax
orq 0x68(%rax), %rcx
movq %rcx, 0x68(%rax)
movq -0x50(%rbp), %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0xb8(%rax)
movq -0x30(%rbp), %rax
movq -0x10(%rbp), %rcx
movq (%rcx), %rcx
movq %rcx, 0xc(%rax)
cmpq $0x0, -0x28(%rbp)
jne 0x23da5
movq -0x10(%rbp), %rax
movq (%rax), %rdi
leaq 0x40bb3(%rip), %rsi     # 0x64933
movb $0x0, %al
callq 0x16d80
movq -0x10(%rbp), %rdi
movl $0x3b, %esi
leaq 0x40bbe(%rip), %rdx     # 0x64955
callq 0x22eb0
movq %rax, -0x8(%rbp)
jmp 0x244a9
cmpq $0x20000, -0x40(%rbp)   # imm = 0x20000
sete %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, -0xc4(%rbp)
cmpl $0x0, -0xc4(%rbp)
je 0x23dd7
movq -0x30(%rbp), %rax
movq 0x68(%rax), %rcx
orq $0x20000, %rcx          # imm = 0x20000
movq %rcx, 0x68(%rax)
movq -0x30(%rbp), %rdi
movq -0x28(%rbp), %rsi
movl -0xc4(%rbp), %ecx
movl $0x10, %edx
movl $0x2, %eax
cmpl $0x0, %ecx
cmovnel %eax, %edx
callq 0x40a40
movq -0x30(%rbp), %rax
movq 0x60(%rax), %rax
movq %rax, -0xb8(%rbp)
cmpl $0x0, -0xc4(%rbp)
je 0x23e6b
cmpq $0x0, -0xb8(%rbp)
je 0x23e66
movq -0xb8(%rbp), %rax
cmpq $0x0, 0x18(%rax)
jne 0x23e66
movq -0xb8(%rbp), %rax
movzbl (%rax), %eax
movl %eax, -0xe4(%rbp)
addl $-0x7, %eax
subl $0x3, %eax
jb 0x23e51
jmp 0x23e44
movl -0xe4(%rbp), %eax
subl $0xd, %eax
jne 0x23e62
jmp 0x23e51
movq -0x28(%rbp), %rcx
movq -0xb8(%rbp), %rax
movq %rcx, 0x18(%rax)
jmp 0x23e64
jmp 0x23e64
jmp 0x23e66
jmp 0x24008
cmpq $0x0, -0xb8(%rbp)
je 0x23fcd
movq -0xb8(%rbp), %rax
movl (%rax), %eax
andl $0xff, %eax
cmpl $0x5, %eax
jne 0x23fcd
movq -0xb8(%rbp), %rax
leaq 0x6efba(%rip), %rcx     # 0x92e58
cmpq %rcx, 0x60(%rax)
jne 0x23eea
movq -0x30(%rbp), %rax
movq %rax, -0xf0(%rbp)
movq -0x30(%rbp), %rax
movq 0x18(%rax), %rdi
callq 0x44150
movq %rax, %rdx
movq -0xf0(%rbp), %rax
movq 0x4(%rax), %rdi
leaq 0x40aa3(%rip), %rsi     # 0x64974
movb $0x0, %al
callq 0x16f90
movq -0xb8(%rbp), %rax
leaq 0x6dc32(%rip), %rcx     # 0x91b18
movq %rcx, 0x60(%rax)
movq -0xb8(%rbp), %rax
leaq 0x6ebe0(%rip), %rcx     # 0x92ad8
cmpq %rcx, 0x60(%rax)
jne 0x23f44
movq -0x30(%rbp), %rax
movq %rax, -0xf8(%rbp)
movq -0x30(%rbp), %rax
movq 0x18(%rax), %rdi
callq 0x44150
movq %rax, %rdx
movq -0xf8(%rbp), %rax
movq 0x4(%rax), %rdi
leaq 0x40a6c(%rip), %rsi     # 0x64997
movb $0x0, %al
callq 0x16d80
movq -0xb8(%rbp), %rax
leaq 0x6dbd8(%rip), %rcx     # 0x91b18
movq %rcx, 0x60(%rax)
movq -0x48(%rbp), %rcx
movq -0x30(%rbp), %rax
orq 0x68(%rax), %rcx
movq %rcx, 0x68(%rax)
movq -0x10(%rbp), %rdi
callq 0x24680
cmpl $0x0, %eax
je 0x23f7c
movq -0x10(%rbp), %rdi
movq -0x30(%rbp), %rsi
movq -0x18(%rbp), %rdx
callq 0x24700
movq %rax, -0x8(%rbp)
jmp 0x244a9
movq -0x10(%rbp), %rdi
movl $0x7b, %esi
callq 0x22f80
cmpl $0x0, %eax
je 0x23fa9
movq -0x10(%rbp), %rdi
movq -0x30(%rbp), %rsi
movq -0x18(%rbp), %rdx
callq 0x24810
movq %rax, -0x8(%rbp)
jmp 0x244a9
movq -0x30(%rbp), %rax
movq 0x68(%rax), %rax
andq $0x4, %rax
cmpq $0x0, %rax
jne 0x23fcb
movq -0x30(%rbp), %rax
movq 0x68(%rax), %rcx
orq $0x8, %rcx
movq %rcx, 0x68(%rax)
jmp 0x24006
leaq 0x6d524(%rip), %rax     # 0x914f8
cmpq %rax, -0xb8(%rbp)
jne 0x24004
movq -0x30(%rbp), %rax
movq 0x68(%rax), %rax
andq $0x8, %rax
cmpq $0x0, %rax
jne 0x24004
movq -0x10(%rbp), %rax
movq (%rax), %rdi
leaq 0x409ba(%rip), %rsi     # 0x649b7
movb $0x0, %al
callq 0x16f90
jmp 0x24006
jmp 0x24008
leaq 0x6eac9(%rip), %rax     # 0x92ad8
cmpq %rax, -0xb8(%rbp)
jne 0x2405b
movq -0x30(%rbp), %rax
movq %rax, -0x100(%rbp)
movq -0x30(%rbp), %rax
movq 0x18(%rax), %rdi
callq 0x44150
movq %rax, %rdx
movq -0x100(%rbp), %rax
movq 0x4(%rax), %rdi
leaq 0x40983(%rip), %rsi     # 0x649c8
movb $0x0, %al
callq 0x16d80
movq -0x30(%rbp), %rax
leaq 0x6dac1(%rip), %rcx     # 0x91b18
movq %rcx, 0x60(%rax)
jmp 0x2405d
cmpl $0x0, -0xc4(%rbp)
jne 0x240e2
movq -0x10(%rbp), %rdi
movl $0x3d, %esi
callq 0x22f80
cmpl $0x0, %eax
je 0x240e2
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0xd8(%rbp)
movq -0x30(%rbp), %rdi
addq $0x48, %rdi
addq $0x68, %rdi
movq -0xd8(%rbp), %rsi
callq 0x23980
movq %rax, -0x10(%rbp)
movq -0x10(%rbp), %rax
cmpq -0xd8(%rbp), %rax
jne 0x240e0
movq -0x10(%rbp), %rax
movq %rax, -0x108(%rbp)
movq -0x10(%rbp), %rdi
callq 0x44420
movq %rax, %rdx
movq -0x108(%rbp), %rax
movq (%rax), %rdi
leaq 0x40906(%rip), %rsi     # 0x649df
movb $0x0, %al
callq 0x16f90
jmp 0x240e2
cmpl $0x0, -0xc4(%rbp)
jne 0x24170
cmpq $0x0, -0x20(%rbp)
je 0x24100
movq -0x20(%rbp), %rax
movq -0x30(%rbp), %rdi
callq *%rax
movq -0x30(%rbp), %rax
cmpq $0x0, 0xb0(%rax)
je 0x24146
movq -0x30(%rbp), %rax
movq 0x68(%rax), %rax
andq $0x8, %rax
cmpq $0x0, %rax
je 0x24146
movq -0x30(%rbp), %rax
movq 0x4(%rax), %rdi
leaq 0x408d0(%rip), %rsi     # 0x649ff
movb $0x0, %al
callq 0x16d80
movq -0x30(%rbp), %rax
movq 0x68(%rax), %rcx
andq $-0x9, %rcx
movq %rcx, 0x68(%rax)
movq -0x30(%rbp), %rax
movq 0x68(%rax), %rax
andq $0x48, %rax
cmpq $0x0, %rax
jne 0x2416e
movq -0x18(%rbp), %rdi
movq -0x30(%rbp), %rsi
callq 0x22cc0
movq -0x30(%rbp), %rdi
callq 0x230f0
jmp 0x24170
movq -0x30(%rbp), %rdi
callq 0x40580
movq -0x30(%rbp), %rax
cmpq $0x0, 0x38(%rax)
je 0x241c6
movq -0x30(%rbp), %rax
movq 0x38(%rax), %rax
movq 0xc8(%rax), %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0xc8(%rax)
movq -0x30(%rbp), %rax
movq 0x38(%rax), %rax
movq 0x40(%rax), %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0x40(%rax)
cmpl $0x0, -0xc4(%rbp)
je 0x241c4
movq -0x30(%rbp), %rdi
callq 0x4fcf0
jmp 0x241c6
cmpb $0x0, -0x37(%rbp)
je 0x242b8
movq $0x0, -0xe0(%rbp)
movq -0x30(%rbp), %rax
leaq 0x6ec72(%rip), %rcx     # 0x92e58
cmpq %rcx, 0x60(%rax)
je 0x241ff
leaq 0x40839(%rip), %rax     # 0x64a2c
movq %rax, -0xe0(%rbp)
jmp 0x24280
movq -0x10(%rbp), %rdi
movl $0x2c, %esi
callq 0x22f80
cmpl $0x0, %eax
je 0x24222
leaq 0x40825(%rip), %rax     # 0x64a3e
movq %rax, -0xe0(%rbp)
jmp 0x2427e
movq -0x30(%rbp), %rax
cmpq $0x0, 0xb0(%rax)
jne 0x24240
leaq 0x4081b(%rip), %rax     # 0x64a52
movq %rax, -0xe0(%rbp)
jmp 0x2427c
movq -0x30(%rbp), %rax
movq 0xb0(%rax), %rax
movl (%rax), %eax
andl $0xff, %eax
cmpl $0x3, %eax
jne 0x2427a
movq -0x30(%rbp), %rax
movq 0xb0(%rax), %rax
movq 0x20(%rax), %rax
cmpq -0x30(%rbp), %rax
jne 0x2427a
leaq 0x407f3(%rip), %rax     # 0x64a66
movq %rax, -0xe0(%rbp)
jmp 0x2427c
jmp 0x2427e
jmp 0x24280
cmpq $0x0, -0xe0(%rbp)
je 0x242b6
movq -0x30(%rbp), %rax
movq -0xe0(%rbp), %rdx
movq 0x4(%rax), %rdi
leaq 0x407d7(%rip), %rsi     # 0x64a77
movb $0x0, %al
callq 0x16f90
movq -0x30(%rbp), %rax
leaq 0x6e9e6(%rip), %rcx     # 0x92c98
movq %rcx, 0x60(%rax)
jmp 0x242b8
movq -0x10(%rbp), %rdi
movl $0x2c, %esi
callq 0x22f80
cmpl $0x0, %eax
jne 0x242d0
jmp 0x24490
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x10(%rbp)
movq $0x0, -0x28(%rbp)
movq -0x10(%rbp), %rax
movq (%rax), %rdi
movl $0x3, %esi
callq 0x3f4d0
movq %rax, -0x30(%rbp)
leaq -0x88(%rbp), %rdi
leaq -0xb0(%rbp), %rsi
movl $0x28, %edx
callq 0x111d0
movq $0x0, -0x50(%rbp)
movq -0x10(%rbp), %rdi
leaq -0x88(%rbp), %rsi
callq 0x24630
movq %rax, -0x10(%rbp)
movq -0x10(%rbp), %rdi
leaq -0x88(%rbp), %rsi
callq 0x23620
movq %rax, -0x10(%rbp)
movq -0x10(%rbp), %rdi
leaq -0x88(%rbp), %rsi
callq 0x24550
movq %rax, -0x10(%rbp)
movq -0x10(%rbp), %rdi
leaq -0x88(%rbp), %rsi
callq 0x24630
movq %rax, -0x10(%rbp)
movq -0x10(%rbp), %rax
movq (%rax), %rdi
leaq -0x88(%rbp), %rsi
callq 0x23660
movq -0x30(%rbp), %rdi
addq $0x48, %rdi
addq $0x18, %rdi
leaq -0x88(%rbp), %rsi
movl $0x28, %edx
callq 0x111d0
movq -0xc0(%rbp), %rcx
movq -0x30(%rbp), %rax
orq 0x68(%rax), %rcx
movq %rcx, 0x68(%rax)
movq -0x50(%rbp), %rcx
movq -0x30(%rbp), %rax
movq %rcx, 0xb8(%rax)
movq -0x30(%rbp), %rax
movq -0x10(%rbp), %rcx
movq (%rcx), %rcx
movq %rcx, 0xc(%rax)
cmpq $0x0, -0x28(%rbp)
jne 0x243f3
movq -0x10(%rbp), %rax
movq (%rax), %rdi
leaq 0x406a7(%rip), %rsi     # 0x64a86
movb $0x0, %al
callq 0x16f90
movq -0x10(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x244a9
cmpl $0x0, -0xc4(%rbp)
je 0x2440f
movq -0x30(%rbp), %rax
movq 0x68(%rax), %rcx
orq $0x20000, %rcx          # imm = 0x20000
movq %rcx, 0x68(%rax)
movq -0x30(%rbp), %rdi
movq -0x28(%rbp), %rsi
movl -0xc4(%rbp), %ecx
movl $0x10, %edx
movl $0x2, %eax
cmpl $0x0, %ecx
cmovnel %eax, %edx
callq 0x40a40
movq -0x30(%rbp), %rax
movq 0x60(%rax), %rax
movq %rax, -0xb8(%rbp)
cmpl $0x0, -0xc4(%rbp)
jne 0x2448b
cmpq $0x0, -0xb8(%rbp)
je 0x2448b
movq -0xb8(%rbp), %rax
movl (%rax), %eax
andl $0xff, %eax
cmpl $0x5, %eax
jne 0x2448b
movq -0x30(%rbp), %rax
movq 0x68(%rax), %rax
andq $0x4, %rax
cmpq $0x0, %rax
jne 0x24489
movq -0x30(%rbp), %rax
movq 0x68(%rax), %rcx
orq $0x8, %rcx
movq %rcx, 0x68(%rax)
jmp 0x2448b
jmp 0x2405d
movq -0x10(%rbp), %rdi
movl $0x3b, %esi
leaq 0x40900(%rip), %rdx     # 0x64da0
callq 0x22eb0
movq %rax, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0x110, %rsp            # imm = 0x110
popq %rbp
retq
nopw %cs:(%rax,%rax)