// File: /workspace/github_c_makefile_star2_O3/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, %r15
movq %rdi, 0x10(%rsp)
movq (%rdi), %r12
cmpl $0x0, 0x2c(%r12)
jne 0x68f0
movq 0x10(%rsp), %rbx
movq %rbx, %rdi
callq 0x6798
movq (%rbx), %r12
movzbl 0x20(%r12), %ebp
cmpl $0x2d, %ebp
je 0x6905
movl $0x1, %eax
cmpl $0x2b, %ebp
jne 0x6922
xorl %ebx, %ebx
cmpb $0x2d, %bpl
setne %bl
movq 0x10(%rsp), %rdi
callq 0x6798
movl %eax, %ebp
leaq -0x1(,%rbx,2), %rax
movl $0xa, %r14d
cmpb $0x30, %bpl
movq %rax, 0x48(%rsp)
jne 0x69c1
callq 0x3230
movq (%rax), %rbx
movq 0x10(%rsp), %rdi
xorl %esi, %esi
xorl %edx, %edx
movl $0x1, %ecx
callq 0x5cf0
movsbq %al, %rax
testb $0x8, (%rbx,%rax,2)
je 0x69c1
callq 0x3220
movq (%rax), %rbx
movq 0x10(%rsp), %rdi
xorl %esi, %esi
xorl %edx, %edx
movl $0x1, %ecx
callq 0x5cf0
movsbq %al, %rax
movsbl (%rbx,%rax,4), %eax
movl $0x10, %ebx
movl $0x8, %r14d
cmpl $0x61, %eax
jg 0x699b
cmpl $0x42, %eax
je 0x69a5
cmpl $0x58, %eax
je 0x69aa
jmp 0x69b7
cmpl $0x78, %eax
je 0x69aa
cmpl $0x62, %eax
jne 0x69b7
movl $0x2, %ebx
movq 0x10(%rsp), %rdi
callq 0x6798
movl %ebx, %r14d
movq 0x10(%rsp), %rdi
callq 0x6798
movq %r15, 0x8(%rsp)
addq $0x28, %r12
movq %r12, 0x20(%rsp)
xorl %ebx, %ebx
leaq 0x40(%rsp), %r15
movq %rbx, (%r15)
leaq 0x38(%rsp), %rax
movq %rbx, (%rax)
leaq 0x30(%rsp), %rax
movq %rbx, (%rax)
callq 0x3220
movq %rax, 0x28(%rsp)
movl %r14d, %r13d
xorl %r12d, %r12d
movq 0x28(%rsp), %rax
movq (%rax), %rax
movsbq %bpl, %rbp
movl (%rax,%rbp,4), %ecx
movl %ecx, %edx
shll $0x18, %edx
cmpl $0x2e000000, %edx       # imm = 0x2E000000
jne 0x6a2e
movl $0x1, %r14d
testl %r12d, %r12d
jne 0x6ae5
leaq 0x38(%rsp), %r15
jmp 0x6ac7
movsbl %cl, %ecx
cmpl $0x10, %r13d
je 0x6a54
movslq %ecx, %rdx
cmpl $0x65, (%rax,%rdx,4)
jne 0x6a54
testl %ebx, %ebx
jne 0x6aee
leaq 0x30(%rsp), %r15
movl $0x1, %ebx
jmp 0x6ac4
leal -0x30(%rcx), %eax
leal -0x32(%rcx), %edx
cmpl $0x34, %edx
ja 0x6adb
movl $0x3f, %esi
btq %rdx, %rsi
jb 0x6a9c
movabsq $0x1f800000000000, %rsi # imm = 0x1F800000000000
btq %rdx, %rsi
jae 0x6a8b
cmpl $0xa, %r13d
je 0x6d85
addl $-0x57, %ecx
movl %ecx, %eax
jmp 0x6a96
movl $0xc0, %esi
btq %rdx, %rsi
jae 0x6adb
cmpl $0x8, %r13d
je 0x6b00
cmpl $0x2, %r13d
je 0x6af7
cmpl $0x1, %r12d
movl $0x2, %ecx
cmovel %ecx, %r12d
cmpl $0x1, %ebx
cmovel %ecx, %ebx
movq (%r15), %rcx
imulq %r13, %rcx
movl %eax, %eax
addq %rcx, %rax
movq %rax, (%r15)
movl %r12d, %r14d
movq 0x10(%rsp), %rdi
callq 0x6798
movl %eax, %ebp
movl %r14d, %r12d
jmp 0x69f9
addl $-0x30, %ecx
cmpl $0x2, %ecx
jb 0x6aa2
jmp 0x6b13
leaq 0x7169(%rip), %rsi      # 0xdc55
jmp 0x6b07
leaq 0x7185(%rip), %rsi      # 0xdc7a
jmp 0x6b07
leaq 0x71bd(%rip), %rsi      # 0xdcbb
jmp 0x6b07
leaq 0x7193(%rip), %rsi      # 0xdc9a
movq 0x20(%rsp), %rdi
xorl %eax, %eax
callq 0x3250
testl %r12d, %r12d
setne %r14b
sete %al
cmpl $0xa, %r13d
sete %cl
orb %al, %cl
movq 0x20(%rsp), %r15
jne 0x6b41
leaq 0x71a9(%rip), %rsi      # 0xdcdd
movq %r15, %rdi
xorl %eax, %eax
callq 0x3250
movb $0x1, %r14b
cmpl $0x1, %ebx
movq 0x8(%rsp), %r12
jne 0x6b5c
leaq 0x71b2(%rip), %rsi      # 0xdd04
movq %r15, %rdi
xorl %eax, %eax
callq 0x3250
movl $0x6, %edi
callq 0xbf35
movq %rax, %r13
cmpl $0x2, %ebx
sete %al
orb %al, %r14b
cmpb $0x1, %r14b
jne 0x6b80
movl $0x7, (%r13)
movl $0x4, 0x4(%r13)
movl $0x1, 0xc(%r13)
movq %r13, 0x28(%r12)
movq 0x10(%r15), %rax
movq %rax, 0x60(%rsp)
movupd (%r15), %xmm0
movapd %xmm0, 0x50(%rsp)
callq 0x3230
movq %rax, %r15
movq (%rax), %rax
xorl %r14d, %r14d
testb $0x4, 0x1(%rax,%rbp,2)
movl $0x0, %ebx
je 0x6c21
movq %r13, %r12
xorl %r13d, %r13d
xorl %r14d, %r14d
xorl %ebx, %ebx
movq 0x28(%rsp), %rax
movq (%rax), %rax
movl (%rax,%rbp,4), %eax
cmpl $0x66, %eax
je 0x6bf5
cmpl $0x75, %eax
je 0x6bf0
cmpl $0x6c, %eax
jne 0x6c7b
incl %ebx
jmp 0x6c00
incl %r14d
jmp 0x6c00
movl $0x7, (%r12)
incl %r13d
movq 0x10(%rsp), %rdi
callq 0x6798
movq (%r15), %rcx
movsbq %al, %rbp
testb $0x4, 0x1(%rcx,%rbp,2)
jne 0x6bce
cmpl $0x1, %r13d
movq %r12, %r13
jg 0x6c53
cmpl $0x6, (%r13)
jne 0x6c43
cmpl $0x2, %r14d
setge %al
cmpl $0x3, %ebx
setge %cl
orb %al, %cl
jne 0x6c53
movq %r13, %r12
cmpl $0x2, %ebx
je 0x6c72
jmp 0x6c7b
testl %r14d, %r14d
setg %al
cmpl $0x2, %ebx
setge %cl
orb %al, %cl
je 0x6c6b
movq %r13, %r12
leaq 0x70c5(%rip), %rsi      # 0xdd22
leaq 0x50(%rsp), %rdi
xorl %eax, %eax
callq 0x3250
jmp 0x6c7b
movq %r13, %r12
testl %ebx, %ebx
je 0x6c7b
movl $0x8, 0x4(%r12)
cmpl $0x6, (%r12)
jne 0x6ca3
cmpl $0x0, 0xc(%r12)
movq 0x40(%rsp), %rax
je 0x6c95
imulq 0x48(%rsp), %rax
movq 0x8(%rsp), %rcx
movq %rax, 0x20(%rcx)
jmp 0x6d76
movq 0x38(%rsp), %rbx
movq %rbx, %xmm1
punpckldq 0x6e3b(%rip), %xmm1 # xmm1 = xmm1[0],mem[0],xmm1[1],mem[1]
subpd 0x6e43(%rip), %xmm1     # 0xdb00
movapd %xmm1, %xmm0
unpckhpd %xmm1, %xmm0            # xmm0 = xmm0[1],xmm1[1]
addsd %xmm1, %xmm0
movapd %xmm0, 0x10(%rsp)
callq 0x3120
addsd 0x6e34(%rip), %xmm0     # 0xdb10
callq 0x3200
movapd %xmm0, %xmm1
movsd 0x6e2b(%rip), %xmm0     # 0xdb18
callq 0x3090
movapd 0x6e06(%rip), %xmm4     # 0xdb00
movsd 0x6dee(%rip), %xmm3     # 0xdaf0
movsd 0x40(%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 0x6d30
movapd 0x10(%rsp), %xmm2
divsd %xmm0, %xmm2
movapd %xmm2, %xmm0
jmp 0x6d38
movsd 0x6de8(%rip), %xmm0     # 0xdb20
movq 0x8(%rsp), %rbx
addsd %xmm1, %xmm0
movsd %xmm0, 0x20(%rbx)
movsd 0x30(%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 0x6db1(%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 %r12d, %r12d
setne %r14b
movq 0x20(%rsp), %r15
jmp 0x6b41