// File: /workspace/github_c_makefile_star2_O1/Yamsman[P]scc/src/lex.c
// Function: lex_num
void lex_num(lexer *lx, token *t) {
	char cur = lex_cur(lx);
	s_pos *loc = &lx->tgt->loc;

	//Read sign
	int sign = 1;
	if (cur == '-' || cur == '+') {
		sign = (cur == '-') ? -1 : 1;
		cur = lex_advc(lx);
	}

	//Read base prefix
	int base = 10;
	if (cur == '0' && isalnum(lex_peekc(lx))) {
		base = 8;
		char nextc = tolower(lex_peekc(lx));
		switch (nextc) {
			case 'x': case 'X':
				base = 16;
				lex_advc(lx);
				break;
			case 'b': case 'B':
				base = 2;
				lex_advc(lx);
				break;
			default:
				if (!isdigit(nextc)) {
					//invalid prefix ...
				}
				break;
		}
		lex_advc(lx);
	}

	//Read number
	int dec_state = S_NONE; 
	int exp_state = S_NONE;
	unsigned long long int_val = 0;
	unsigned long long frac_val = 0;
	unsigned long long exp_val = 0;
	unsigned long long *tgt_val = &int_val;
	for (;; cur = lex_advc(lx)) {
		char digit = tolower(cur);
		int dval = digit - '0';

		//Handle floating-point characters
		if (digit == '.') {
			if (dec_state != S_NONE) {
				c_error(loc, "Multiple decimal points in constant\n");
				goto n_end;
			}
			dec_state = S_INIT;
			tgt_val = &frac_val;
			continue;
		} else if (tolower(digit) == 'e' && base != 16) {
			if (exp_state != S_NONE) {
				c_error(loc, "Multiple exponents in constant\n");
				goto n_end;
			}
			exp_state = S_INIT;
			tgt_val = &exp_val;
			continue;
		}

		//Read digits
		//Cases fall through from top to bottom to verify input
		switch (digit) {
		case 'f': case 'e': case 'd':
		case 'c': case 'b': case 'a':
			if (base == 10)
				goto n_end;
			dval = 10 + (digit - 'a');
		case '9': case '8':
			if (base == 8) {
				c_error(loc, "Invalid digit in octal constant\n");
				goto n_end;
			}
		case '7': case '6': case '5':
		case '4': case '3': case '2':
			if (base == 2) {
				c_error(loc, "Invalid digit in binary constant\n");
				goto n_end;
			}
		case '1': case '0':
			if (dec_state == S_INIT) dec_state = S_DONE;
			if (exp_state == S_INIT) exp_state = S_DONE;
			*(tgt_val) *= base;
			*(tgt_val) += dval;
			break;

		default: goto n_end;
		}
	}
n_end:  if (dec_state != S_NONE && base != 10)
		c_error(loc, "Decimal point in non-base 10 constant\n");
	if (exp_state == S_INIT)
		c_error(loc, "Missing exponent in constant\n");

	//Determine kind
	s_type *ty = type_new(TYPE_INT);
	if (dec_state != S_NONE || exp_state == S_DONE)
		ty->kind = TYPE_FLOAT;
	ty->size = SIZE_LONG;
	ty->is_signed = 1;
	t->dtype = ty;

	//Read suffix
	s_pos suffix_loc = *loc;
	int l_count = 0, u_count = 0, f_count = 0;
	while (isalpha(cur)) {
		switch (tolower(cur)) {
			case 'l': //Long flag
				l_count++; 
				break;
			case 'u': //Unsigned flag
				u_count++;
				break;
			case 'f': //Float flag
				ty->kind = TYPE_FLOAT;
				f_count++;
				break;
			default: goto s_end;
		}
		cur = lex_advc(lx);
	}

	//Suffix verification
	if (f_count > 1) goto s_err;
	if (ty->kind == TYPE_INT) {
		if (u_count > 1) goto s_err;
		if (l_count > 2) goto s_err;
		if (l_count == 2) //Promote to long long
			ty->size = SIZE_LONG_LONG;
	} else {
		if (u_count > 0) goto s_err;
		if (l_count > 1) goto s_err;
		if (l_count != 0) //Promote to double
			ty->size = SIZE_LONG_LONG;
	}

	//Set token data
s_end:	if (ty->kind == TYPE_INT) {
		if (!ty->is_signed) {
			t->dat.uval = int_val;
		} else {
			t->dat.ival = int_val * sign;
		}
	} else {
		//Calculate value from integer, fraction, and exponent parts
		double dec = frac_val/pow(10, floor(log10(frac_val)+1));
		t->dat.fval = int_val;
		if (frac_val != 0) t->dat.fval += dec;
		t->dat.fval *= pow(10, exp_val);
	}
	return;

	//Suffix error handling
s_err:	c_error(&suffix_loc, "Invalid suffix on constant\n");
	goto s_end;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x68, %rsp
movq %rsi, 0x28(%rsp)
movq %rdi, %r14
movq (%rdi), %rax
cmpl $0x0, 0x2c(%rax)
jne 0x68bd
movq %r14, %rdi
callq 0x6776
movq (%r14), %rax
movq %rax, 0x10(%rsp)
movzbl 0x20(%rax), %ebx
cmpl $0x2d, %ebx
je 0x68d3
cmpl $0x2b, %ebx
jne 0x68f1
xorl %r15d, %r15d
cmpb $0x2d, %bl
setne %r15b
movq %r14, %rdi
callq 0x6776
movl %eax, %ebx
leaq -0x1(,%r15,2), %rax
jmp 0x68f6
movl $0x1, %eax
movq %rax, 0x30(%rsp)
movl $0xa, %ebp
cmpb $0x30, %bl
jne 0x698e
callq 0x3230
movq (%rax), %r15
movq %r14, %rdi
xorl %esi, %esi
xorl %edx, %edx
movl $0x1, %ecx
callq 0x5c73
movsbq %al, %rax
testb $0x8, (%r15,%rax,2)
je 0x698e
callq 0x3220
movq (%rax), %r15
movq %r14, %rdi
xorl %esi, %esi
xorl %edx, %edx
movl $0x1, %ecx
callq 0x5c73
movsbq %al, %rax
movsbl (%r15,%rax,4), %eax
movl $0x10, %r15d
movl $0x8, %ebp
cmpl $0x61, %eax
jg 0x696b
cmpl $0x42, %eax
je 0x6975
cmpl $0x58, %eax
je 0x697b
jmp 0x6986
cmpl $0x78, %eax
je 0x697b
cmpl $0x62, %eax
jne 0x6986
movl $0x2, %r15d
movq %r14, %rdi
callq 0x6776
movl %r15d, %ebp
movq %r14, %rdi
callq 0x6776
addq $0x28, 0x10(%rsp)
xorl %eax, %eax
leaq 0x48(%rsp), %rcx
movq %rcx, 0x8(%rsp)
movq %rax, (%rcx)
leaq 0x40(%rsp), %rcx
movq %rax, (%rcx)
leaq 0x38(%rsp), %rcx
movq %rax, (%rcx)
callq 0x3220
movq %rax, %r12
movl %ebp, %r13d
movl $0x0, 0x4(%rsp)
xorl %r15d, %r15d
movq (%r12), %rax
movsbq %bl, %rbp
movl (%rax,%rbp,4), %ecx
movl %ecx, %edx
shll $0x18, %edx
cmpl $0x2e000000, %edx       # imm = 0x2E000000
jne 0x69f8
testl %r15d, %r15d
je 0x6a6e
movq 0x10(%rsp), %rdi
leaq 0x725f(%rip), %rsi      # 0xdc55
jmp 0x6a1d
movsbl %cl, %ecx
cmpl $0x10, %r13d
je 0x6a2e
movslq %ecx, %rdx
cmpl $0x65, (%rax,%rdx,4)
jne 0x6a2e
cmpl $0x0, 0x4(%rsp)
je 0x6a80
movq 0x10(%rsp), %rdi
leaq 0x725d(%rip), %rsi      # 0xdc7a
xorl %eax, %eax
callq 0x3250
movl $0x6, %ebx
jmp 0x6b0c
leal -0x30(%rcx), %eax
movl $0x6, %ebx
leal -0x32(%rcx), %edx
cmpl $0x34, %edx
ja 0x6ad3
movl $0x3f, %esi
btq %rdx, %rsi
jb 0x6ab8
movabsq $0x1f800000000000, %rsi # imm = 0x1F800000000000
btq %rdx, %rsi
jae 0x6a99
cmpl $0xa, %r13d
je 0x6b0c
addl $-0x57, %ecx
movl %ecx, %eax
jmp 0x6aa4
movl $0x1, %r15d
movl $0x5, %ebx
leaq 0x40(%rsp), %rax
jmp 0x6a92
movl $0x1, 0x4(%rsp)
movl $0x5, %ebx
leaq 0x38(%rsp), %rax
movq %rax, 0x8(%rsp)
jmp 0x6b0c
movl $0xc0, %esi
btq %rdx, %rsi
jae 0x6ad3
cmpl $0x8, %r13d
jne 0x6ab8
movq 0x10(%rsp), %rdi
leaq 0x71e4(%rip), %rsi      # 0xdc9a
jmp 0x6aca
cmpl $0x2, %r13d
jne 0x6adb
movq 0x10(%rsp), %rdi
leaq 0x71f1(%rip), %rsi      # 0xdcbb
xorl %eax, %eax
callq 0x3250
jmp 0x6b0c
addl $-0x30, %ecx
cmpl $0x2, %ecx
jae 0x6b0c
cmpl $0x1, %r15d
movl $0x2, %edx
cmovel %edx, %r15d
movl 0x4(%rsp), %ecx
cmpl $0x1, %ecx
cmovel %edx, %ecx
movl %ecx, 0x4(%rsp)
movq 0x8(%rsp), %rdx
movq (%rdx), %rcx
imulq %r13, %rcx
cltq
addq %rcx, %rax
movq %rax, (%rdx)
xorl %ebx, %ebx
testl %ebx, %ebx
je 0x6b15
cmpl $0x5, %ebx
jne 0x6b24
movq %r14, %rdi
callq 0x6776
movl %eax, %ebx
jmp 0x69c9
cmpl $0x6, %ebx
jne 0x6d8c
testl %r15d, %r15d
sete %al
cmpl $0xa, %r13d
sete %cl
orb %al, %cl
jne 0x6b51
leaq 0x7198(%rip), %rsi      # 0xdcdd
movq 0x10(%rsp), %rdi
xorl %eax, %eax
callq 0x3250
cmpl $0x1, 0x4(%rsp)
jne 0x6b6b
leaq 0x71a5(%rip), %rsi      # 0xdd04
movq 0x10(%rsp), %rdi
xorl %eax, %eax
callq 0x3250
testl %r15d, %r15d
setne %bl
movl $0x6, %edi
callq 0xbfcd
movq %rax, %r13
cmpl $0x2, 0x4(%rsp)
sete %al
orb %bl, %al
cmpb $0x1, %al
jne 0x6b94
movl $0x7, (%r13)
movl $0x4, 0x4(%r13)
movl $0x1, 0xc(%r13)
movq 0x28(%rsp), %rax
movq %r13, 0x28(%rax)
movq 0x10(%rsp), %rcx
movq 0x10(%rcx), %rax
movq %rax, 0x60(%rsp)
movupd (%rcx), %xmm0
movapd %xmm0, 0x50(%rsp)
callq 0x3230
movq %rax, %r15
movq (%rax), %rax
movl $0x0, 0x10(%rsp)
testb $0x4, 0x1(%rax,%rbp,2)
movl $0x0, %ebx
movl $0x0, %eax
movq %r13, 0x8(%rsp)
je 0x6c4b
xorl %r13d, %r13d
xorl %ebx, %ebx
movl $0x0, 0x10(%rsp)
movq (%r12), %rax
movl (%rax,%rbp,4), %eax
cmpl $0x66, %eax
je 0x6c1b
cmpl $0x75, %eax
je 0x6c17
cmpl $0x6c, %eax
jne 0x6c66
incl 0x10(%rsp)
jmp 0x6c29
incl %ebx
jmp 0x6c29
movq 0x8(%rsp), %rax
movl $0x7, (%rax)
incl %r13d
movq %r14, %rdi
callq 0x6776
movq (%r15), %rcx
movsbq %al, %rbp
testb $0x4, 0x1(%rcx,%rbp,2)
jne 0x6bfb
cmpl $0x2, %r13d
setge %al
movq 0x8(%rsp), %r13
testb %al, %al
je 0x6d1c
leaq 0x70c8(%rip), %rsi      # 0xdd22
leaq 0x50(%rsp), %rdi
xorl %eax, %eax
callq 0x3250
movq 0x8(%rsp), %rax
cmpl $0x6, (%rax)
jne 0x6c8f
cmpl $0x0, 0xc(%rax)
movq 0x48(%rsp), %rax
je 0x6c81
imulq 0x30(%rsp), %rax
movq 0x28(%rsp), %rcx
movq %rax, 0x20(%rcx)
jmp 0x6d8c
movq 0x40(%rsp), %rbx
movq %rbx, %xmm1
punpckldq 0x6e4f(%rip), %xmm1 # xmm1 = xmm1[0],mem[0],xmm1[1],mem[1]
subpd 0x6e57(%rip), %xmm1     # 0xdb00
movapd %xmm1, %xmm0
unpckhpd %xmm1, %xmm0            # xmm0 = xmm0[1],xmm1[1]
addsd %xmm1, %xmm0
movapd %xmm0, 0x10(%rsp)
callq 0x3120
addsd 0x6e48(%rip), %xmm0     # 0xdb10
callq 0x3200
movapd %xmm0, %xmm1
movsd 0x6e3f(%rip), %xmm0     # 0xdb18
callq 0x3090
movapd 0x6e1a(%rip), %xmm4     # 0xdb00
movsd 0x6e02(%rip), %xmm3     # 0xdaf0
movsd 0x48(%rsp), %xmm2
unpcklps %xmm3, %xmm2            # xmm2 = xmm2[0],xmm3[0],xmm2[1],xmm3[1]
subpd %xmm4, %xmm2
movapd %xmm2, %xmm1
unpckhpd %xmm2, %xmm1            # xmm1 = xmm1[1],xmm2[1]
addsd %xmm2, %xmm1
testq %rbx, %rbx
je 0x6d46
movapd 0x10(%rsp), %xmm2
divsd %xmm0, %xmm2
movapd %xmm2, %xmm0
jmp 0x6d4e
cmpl $0x6, (%r13)
jne 0x6d9b
cmpl $0x2, %ebx
setge %al
cmpl $0x3, 0x10(%rsp)
setge %cl
orb %al, %cl
jne 0x6c53
cmpl $0x2, 0x10(%rsp)
jne 0x6c66
jmp 0x6dbb
movsd 0x6dd2(%rip), %xmm0     # 0xdb20
addsd %xmm1, %xmm0
movq 0x28(%rsp), %rbx
movsd %xmm0, 0x20(%rbx)
movsd 0x38(%rsp), %xmm0
unpcklps %xmm3, %xmm0            # xmm0 = xmm0[0],xmm3[0],xmm0[1],xmm3[1]
subpd %xmm4, %xmm0
movapd %xmm0, %xmm1
unpckhpd %xmm0, %xmm1            # xmm1 = xmm1[1],xmm0[1]
addsd %xmm0, %xmm1
movsd 0x6d9b(%rip), %xmm0     # 0xdb18
callq 0x3090
mulsd 0x20(%rbx), %xmm0
movsd %xmm0, 0x20(%rbx)
addq $0x68, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
testl %ebx, %ebx
setg %al
cmpl $0x2, 0x10(%rsp)
setge %cl
orb %al, %cl
jne 0x6c53
cmpl $0x0, 0x10(%rsp)
je 0x6c66
movq 0x8(%rsp), %rax
movl $0x8, 0x4(%rax)
jmp 0x6c66