// File: /workspace/github_c_makefile_star2_O0/Yamsman[P]scc/src/parse.c
// Function: parse_decl_spec
s_type *parse_decl_spec(lexer *lx) {
	s_type *type = type_new(TYPE_UNDEF);

	/*
	 * Loop and process specifiers
	 */
	int from_typedef = 0;
	int is_long = 0, is_signed = 0, is_unsigned = 0;
	s_pos begin = lex_peek(lx).loc;
	for (;;) {
		token t = lex_peek(lx);

		//Check for conflicts
		switch (t.type) {
			case TOK_KW_VOID: case TOK_KW_CHAR: case TOK_KW_SHORT:
			case TOK_KW_INT: case TOK_KW_FLOAT: case TOK_KW_DOUBLE:
			case TOK_KW_STRUCT: case TOK_KW_UNION: case TOK_KW_ENUM:
				if (type->kind != TYPE_UNDEF) {
					c_error(&t.loc, "Multiple data types in declaration\n");
				}
				break;
			case TOK_KW_EXTERN: case TOK_KW_STATIC: case TOK_KW_AUTO:
			case TOK_KW_REGISTER: case TOK_KW_TYPEDEF:
				if (type->s_class != CLASS_UNDEF) {
					c_error(&t.loc, "Multiple storage classes in declaration\n");
				}
				break;
			case TOK_KW_SIGNED:
				if (is_signed > 0)
					c_error(&t.loc, "Duplicate 'signed' qualifier\n");
				break;
			case TOK_KW_UNSIGNED:
				if (is_unsigned > 0)
					c_error(&t.loc, "Duplicate 'unsigned' qualifier\n");
				break;
			case TOK_KW_CONST:
				if (type->is_const == 1)
					c_error(&t.loc, "Duplicate 'const' qualifier\n");
				break;
			case TOK_KW_VOLATILE:
				if (type->is_volatile == 1)
					c_error(&t.loc, "Duplicate 'volatile' qualifier\n");
				break;
		} 

		//Check for a user defined type
		if (t.type == TOK_IDENT) {
			symbol *td = symtable_search(lx->stb, t.dat.sval);
			if (type->kind != TYPE_UNDEF) goto ts_end;
			if (td == NULL || td->btype->s_class != CLASS_TYPEDEF) goto ts_end;

			//Clone the predefined type
			s_type *usr_type = type_clone(td->type);
			s_type *usr_btype = usr_type;
			while (usr_btype->ref != NULL)
				usr_btype = usr_btype->ref;
			usr_btype->s_class = CLASS_UNDEF;

			//Copy over class/qualifiers if needed
			usr_btype->s_class = type->s_class;
			usr_btype->is_const = type->is_const;
			usr_btype->is_volatile = type->is_volatile;
			
			type_del(type);
			type = usr_type;
			lex_adv(lx);
			continue;
		} 

		//Process specifier
		s_type *su_type;
		switch (t.type) {
			case TOK_KW_VOID: 	type->kind = TYPE_VOID; break;
			case TOK_KW_CHAR: 	type->kind = TYPE_INT; type->size = 1; break;
			case TOK_KW_SHORT: 	type->kind = TYPE_INT; type->size = 2; break;
			case TOK_KW_FLOAT:	type->kind = TYPE_FLOAT; type->size = 4; break;
			case TOK_KW_TYPEDEF:	type->s_class = CLASS_TYPEDEF;	break;
			case TOK_KW_EXTERN:	type->s_class = CLASS_EXTERN;	break;
			case TOK_KW_STATIC:	type->s_class = CLASS_STATIC;	break;
			case TOK_KW_AUTO:	type->s_class = CLASS_AUTO; 	break;
			case TOK_KW_REGISTER:	type->s_class = CLASS_REGISTER;	break;
			case TOK_KW_SIGNED:	type->is_signed = 1;		break;
			case TOK_KW_UNSIGNED:	type->is_signed = 0;		break;
			case TOK_KW_CONST:	type->is_const = 1;		break;
			case TOK_KW_VOLATILE:	type->is_volatile = 1;		break;
			case TOK_KW_INT: 	
				if (is_long == 0 || is_long == 1)
					type->size = 4;
				else if (is_long == 2)
					type->size = 8;
				else
					c_error(&t.loc, "Too many 'long' for data type 'int'\n");
				type->kind = TYPE_INT;
				break;
			case TOK_KW_DOUBLE:
				if (is_long == 0)
					type->size = 8;
				else if (is_long == 1)
					type->size = 16;
				else
					c_error(&t.loc, "Too many 'long' for data type 'double'\n");
				type->kind = TYPE_FLOAT;
				break;
			case TOK_KW_LONG:
				//Either set the data type to int, or modify the current type
				if (type->kind == TYPE_UNDEF) {
					type->size = 4;
					if (is_long > 0)
						type->size = 8;
				} else if (type->kind == TYPE_INT) {
					if (is_long == 1)
						type->size = 8;
					else if (is_long > 1)
						c_error(&t.loc,
							"Too many 'long' for data type 'int'\n");
				} else if (type->kind == TYPE_FLOAT && type->size == 8) {
					if (is_long == 0)
						type->size = 16;
					else if (is_long > 0)
						c_error(&t.loc,
							"Too many 'long' for data type 'double'\n");
				} else {
					c_error(&t.loc, "Invalid use of 'long'\n");
				}
				is_long++;
				break;
			case TOK_KW_STRUCT:
			case TOK_KW_UNION:
				//Read struct/union type
				su_type = parse_sdef(lx);
				lex_unget(lx, make_tok_node(lex_peek(lx)));
				if (su_type == NULL) break;

				//Merge with current type
				su_type->s_class = type->s_class;
				su_type->is_const = type->is_const;
				su_type->is_volatile = type->is_volatile;
				type_del(type);
				type = su_type; 
				break;
			case TOK_KW_ENUM:
				parse_edef(lx);
				break;
			default:
				goto ts_end;
		}
		lex_adv(lx);
	}

	/*
	 * Error checking
	 */
	//Warning for no specified data type (unless 'long' is specified)
ts_end:	if (type->kind == TYPE_UNDEF) {
		if (is_long == 0)
			c_warn(&begin, "Declaration defaults to 'int'\n");
		if (is_long > 2)
			c_error(&begin, "Too many 'long' for data type 'int'\n");
		type->kind = TYPE_INT;
	}

	//Ensure signed/unsigned is only used with integer data types
	if (is_signed == 1 && type->kind != TYPE_INT)
		c_error(&begin, "Improper usage of 'signed' qualifier\n");
	if (is_unsigned == 1 && type->kind != TYPE_INT)
		c_error(&begin, "Improper usage of 'unsigned' qualifier\n");

	return type;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x130, %rsp            # imm = 0x130
movq %rdi, -0x8(%rbp)
xorl %edi, %edi
callq 0xf720
movq %rax, -0x10(%rbp)
movl $0x0, -0x14(%rbp)
movl $0x0, -0x18(%rbp)
movl $0x0, -0x1c(%rbp)
movl $0x0, -0x20(%rbp)
movq -0x8(%rbp), %rsi
leaq -0x68(%rbp), %rdi
callq 0x9790
movq -0x60(%rbp), %rax
movq %rax, -0x38(%rbp)
movq -0x58(%rbp), %rax
movq %rax, -0x30(%rbp)
movq -0x50(%rbp), %rax
movq %rax, -0x28(%rbp)
movq -0x8(%rbp), %rsi
leaq -0x98(%rbp), %rdi
callq 0x9790
movl -0x98(%rbp), %eax
addl $-0x42, %eax
movl %eax, %ecx
movq %rcx, -0xf0(%rbp)
subl $0x12, %eax
ja 0xa848
movq -0xf0(%rbp), %rax
leaq 0x8198(%rip), %rcx      # 0x128fc
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x10(%rbp), %rax
cmpl $0x0, (%rax)
je 0xa78f
leaq -0x98(%rbp), %rdi
addq $0x8, %rdi
leaq 0x8476(%rip), %rsi      # 0x12bfe
movb $0x0, %al
callq 0x3880
jmp 0xa848
movq -0x10(%rbp), %rax
cmpl $0x0, 0x8(%rax)
je 0xa7b7
leaq -0x98(%rbp), %rdi
addq $0x8, %rdi
leaq 0x8472(%rip), %rsi      # 0x12c22
movb $0x0, %al
callq 0x3880
jmp 0xa848
cmpl $0x0, -0x1c(%rbp)
jle 0xa7db
leaq -0x98(%rbp), %rdi
addq $0x8, %rdi
leaq 0x8477(%rip), %rsi      # 0x12c4b
movb $0x0, %al
callq 0x3880
jmp 0xa848
cmpl $0x0, -0x20(%rbp)
jle 0xa7fc
leaq -0x98(%rbp), %rdi
addq $0x8, %rdi
leaq 0x8474(%rip), %rsi      # 0x12c69
movb $0x0, %al
callq 0x3880
jmp 0xa848
movq -0x10(%rbp), %rax
cmpl $0x1, 0x10(%rax)
jne 0xa821
leaq -0x98(%rbp), %rdi
addq $0x8, %rdi
leaq 0x846f(%rip), %rsi      # 0x12c89
movb $0x0, %al
callq 0x3880
jmp 0xa848
movq -0x10(%rbp), %rax
cmpl $0x1, 0x14(%rax)
jne 0xa846
leaq -0x98(%rbp), %rdi
addq $0x8, %rdi
leaq 0x8467(%rip), %rsi      # 0x12ca6
movb $0x0, %al
callq 0x3880
jmp 0xa848
cmpl $0x35, -0x98(%rbp)
jne 0xa945
movq -0x8(%rbp), %rax
movq 0x60(%rax), %rdi
movq -0x78(%rbp), %rsi
callq 0xfb60
movq %rax, -0xa0(%rbp)
movq -0x10(%rbp), %rax
cmpl $0x0, (%rax)
je 0xa87b
jmp 0xacb9
cmpq $0x0, -0xa0(%rbp)
je 0xa896
movq -0xa0(%rbp), %rax
movq 0x10(%rax), %rax
cmpl $0x1, 0x8(%rax)
je 0xa89b
jmp 0xacb9
movq -0xa0(%rbp), %rax
movq 0x8(%rax), %rdi
callq 0xfdc0
movq %rax, -0xa8(%rbp)
movq -0xa8(%rbp), %rax
movq %rax, -0xb0(%rbp)
movq -0xb0(%rbp), %rax
cmpq $0x0, 0x18(%rax)
je 0xa8e2
movq -0xb0(%rbp), %rax
movq 0x18(%rax), %rax
movq %rax, -0xb0(%rbp)
jmp 0xa8c0
movq -0xb0(%rbp), %rax
movl $0x0, 0x8(%rax)
movq -0x10(%rbp), %rax
movl 0x8(%rax), %ecx
movq -0xb0(%rbp), %rax
movl %ecx, 0x8(%rax)
movq -0x10(%rbp), %rax
movl 0x10(%rax), %ecx
movq -0xb0(%rbp), %rax
movl %ecx, 0x10(%rax)
movq -0x10(%rbp), %rax
movl 0x14(%rax), %ecx
movq -0xb0(%rbp), %rax
movl %ecx, 0x14(%rax)
movq -0x10(%rbp), %rdi
callq 0xfca0
movq -0xa8(%rbp), %rax
movq %rax, -0x10(%rbp)
movq -0x8(%rbp), %rdi
callq 0x97e0
jmp 0xa72b
movl -0x98(%rbp), %eax
addl $-0x42, %eax
movl %eax, %ecx
movq %rcx, -0xf8(%rbp)
subl $0x12, %eax
ja 0xaca9
movq -0xf8(%rbp), %rax
leaq 0x7fda(%rip), %rcx      # 0x12948
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x10(%rbp), %rax
movl $0x5, (%rax)
jmp 0xacab
movq -0x10(%rbp), %rax
movl $0x6, (%rax)
movq -0x10(%rbp), %rax
movl $0x1, 0x4(%rax)
jmp 0xacab
movq -0x10(%rbp), %rax
movl $0x6, (%rax)
movq -0x10(%rbp), %rax
movl $0x2, 0x4(%rax)
jmp 0xacab
movq -0x10(%rbp), %rax
movl $0x7, (%rax)
movq -0x10(%rbp), %rax
movl $0x4, 0x4(%rax)
jmp 0xacab
movq -0x10(%rbp), %rax
movl $0x1, 0x8(%rax)
jmp 0xacab
movq -0x10(%rbp), %rax
movl $0x2, 0x8(%rax)
jmp 0xacab
movq -0x10(%rbp), %rax
movl $0x3, 0x8(%rax)
jmp 0xacab
movq -0x10(%rbp), %rax
movl $0x4, 0x8(%rax)
jmp 0xacab
movq -0x10(%rbp), %rax
movl $0x5, 0x8(%rax)
jmp 0xacab
movq -0x10(%rbp), %rax
movl $0x1, 0xc(%rax)
jmp 0xacab
movq -0x10(%rbp), %rax
movl $0x0, 0xc(%rax)
jmp 0xacab
movq -0x10(%rbp), %rax
movl $0x1, 0x10(%rax)
jmp 0xacab
movq -0x10(%rbp), %rax
movl $0x1, 0x14(%rax)
jmp 0xacab
cmpl $0x0, -0x18(%rbp)
je 0xaa70
cmpl $0x1, -0x18(%rbp)
jne 0xaa7d
movq -0x10(%rbp), %rax
movl $0x4, 0x4(%rax)
jmp 0xaaab
cmpl $0x2, -0x18(%rbp)
jne 0xaa90
movq -0x10(%rbp), %rax
movl $0x8, 0x4(%rax)
jmp 0xaaa9
leaq -0x98(%rbp), %rdi
addq $0x8, %rdi
leaq 0x8224(%rip), %rsi      # 0x12cc6
movb $0x0, %al
callq 0x3880
jmp 0xaaab
movq -0x10(%rbp), %rax
movl $0x6, (%rax)
jmp 0xacab
cmpl $0x0, -0x18(%rbp)
jne 0xaacd
movq -0x10(%rbp), %rax
movl $0x8, 0x4(%rax)
jmp 0xaafb
cmpl $0x1, -0x18(%rbp)
jne 0xaae0
movq -0x10(%rbp), %rax
movl $0x10, 0x4(%rax)
jmp 0xaaf9
leaq -0x98(%rbp), %rdi
addq $0x8, %rdi
leaq 0x81f9(%rip), %rsi      # 0x12ceb
movb $0x0, %al
callq 0x3880
jmp 0xaafb
movq -0x10(%rbp), %rax
movl $0x7, (%rax)
jmp 0xacab
movq -0x10(%rbp), %rax
cmpl $0x0, (%rax)
jne 0xab34
movq -0x10(%rbp), %rax
movl $0x4, 0x4(%rax)
cmpl $0x0, -0x18(%rbp)
jle 0xab2f
movq -0x10(%rbp), %rax
movl $0x8, 0x4(%rax)
jmp 0xabd9
movq -0x10(%rbp), %rax
cmpl $0x6, (%rax)
jne 0xab73
cmpl $0x1, -0x18(%rbp)
jne 0xab50
movq -0x10(%rbp), %rax
movl $0x8, 0x4(%rax)
jmp 0xab71
cmpl $0x1, -0x18(%rbp)
jle 0xab6f
leaq -0x98(%rbp), %rdi
addq $0x8, %rdi
leaq 0x815e(%rip), %rsi      # 0x12cc6
movb $0x0, %al
callq 0x3880
jmp 0xab71
jmp 0xabd7
movq -0x10(%rbp), %rax
cmpl $0x7, (%rax)
jne 0xabbc
movq -0x10(%rbp), %rax
cmpl $0x8, 0x4(%rax)
jne 0xabbc
cmpl $0x0, -0x18(%rbp)
jne 0xab99
movq -0x10(%rbp), %rax
movl $0x10, 0x4(%rax)
jmp 0xabba
cmpl $0x0, -0x18(%rbp)
jle 0xabb8
leaq -0x98(%rbp), %rdi
addq $0x8, %rdi
leaq 0x813a(%rip), %rsi      # 0x12ceb
movb $0x0, %al
callq 0x3880
jmp 0xabba
jmp 0xabd5
leaq -0x98(%rbp), %rdi
addq $0x8, %rdi
leaq 0x8145(%rip), %rsi      # 0x12d13
movb $0x0, %al
callq 0x3880
jmp 0xabd7
jmp 0xabd9
movl -0x18(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x18(%rbp)
jmp 0xacab
movq -0x8(%rbp), %rdi
callq 0xaeb0
movq %rax, -0xb8(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x100(%rbp)
movq -0x8(%rbp), %rsi
leaq -0xe8(%rbp), %rdi
callq 0x9790
movups -0xe8(%rbp), %xmm0
movups -0xd8(%rbp), %xmm1
movups -0xc8(%rbp), %xmm2
movq %rsp, %rax
movups %xmm2, 0x20(%rax)
movups %xmm1, 0x10(%rax)
movups %xmm0, (%rax)
callq 0x9aa0
movq -0x100(%rbp), %rdi
movq %rax, %rsi
callq 0x99d0
cmpq $0x0, -0xb8(%rbp)
jne 0xac55
jmp 0xacab
movq -0x10(%rbp), %rax
movl 0x8(%rax), %ecx
movq -0xb8(%rbp), %rax
movl %ecx, 0x8(%rax)
movq -0x10(%rbp), %rax
movl 0x10(%rax), %ecx
movq -0xb8(%rbp), %rax
movl %ecx, 0x10(%rax)
movq -0x10(%rbp), %rax
movl 0x14(%rax), %ecx
movq -0xb8(%rbp), %rax
movl %ecx, 0x14(%rax)
movq -0x10(%rbp), %rdi
callq 0xfca0
movq -0xb8(%rbp), %rax
movq %rax, -0x10(%rbp)
jmp 0xacab
movq -0x8(%rbp), %rdi
callq 0xb150
jmp 0xacab
jmp 0xacb9
movq -0x8(%rbp), %rdi
callq 0x97e0
jmp 0xa72b
movq -0x10(%rbp), %rax
cmpl $0x0, (%rax)
jne 0xacfc
cmpl $0x0, -0x18(%rbp)
jne 0xacda
leaq -0x38(%rbp), %rdi
leaq 0x8057(%rip), %rsi      # 0x12d2a
movb $0x0, %al
callq 0x3980
cmpl $0x2, -0x18(%rbp)
jle 0xacf2
leaq -0x38(%rbp), %rdi
leaq 0x7fdb(%rip), %rsi      # 0x12cc6
movb $0x0, %al
callq 0x3880
movq -0x10(%rbp), %rax
movl $0x6, (%rax)
cmpl $0x1, -0x1c(%rbp)
jne 0xad1d
movq -0x10(%rbp), %rax
cmpl $0x6, (%rax)
je 0xad1d
leaq -0x38(%rbp), %rdi
leaq 0x8033(%rip), %rsi      # 0x12d49
movb $0x0, %al
callq 0x3880
cmpl $0x1, -0x20(%rbp)
jne 0xad3e
movq -0x10(%rbp), %rax
cmpl $0x6, (%rax)
je 0xad3e
leaq -0x38(%rbp), %rdi
leaq 0x8038(%rip), %rsi      # 0x12d6f
movb $0x0, %al
callq 0x3880
movq -0x10(%rbp), %rax
addq $0x130, %rsp            # imm = 0x130
popq %rbp
retq
nopl (%rax,%rax)