// File: /workspace/github_c_makefile_star2_O2/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, 0x10(%rsp)
movq %rdi, %r15
callq 0x6493
movl %eax, %ebp
movq (%r15), %r12
cmpb $0x2d, %al
je 0x65d7
movzbl %bpl, %eax
cmpl $0x2b, %eax
jne 0x65f4
xorl %ebx, %ebx
cmpb $0x2d, %bpl
setne %bl
movq %r15, %rdi
callq 0x64ad
movl %eax, %ebp
leaq -0x1(,%rbx,2), %rax
jmp 0x65f7
pushq $0x1
popq %rax
movq %rax, 0x20(%rsp)
pushq $0xa
popq %rbx
cmpb $0x30, %bpl
jne 0x6666
callq 0x3230
movq (%rax), %r14
movq %r15, %rdi
callq 0x64fe
movsbq %al, %rax
testb $0x8, (%r14,%rax,2)
je 0x6666
callq 0x3220
movq (%rax), %rbx
movq %r15, %rdi
callq 0x64fe
movsbq %al, %rax
movsbl (%rbx,%rax,4), %eax
cmpl $0x42, %eax
je 0x6653
pushq $0x10
popq %rbx
cmpl $0x58, %eax
je 0x6656
cmpl $0x78, %eax
je 0x6656
cmpl $0x62, %eax
jne 0x6a1f
pushq $0x2
popq %rbx
movq %r15, %rdi
callq 0x64ad
movq %r15, %rdi
callq 0x64ad
movq %r15, 0x40(%rsp)
addq $0x28, %r12
movq %r12, 0x18(%rsp)
leaq 0x38(%rsp), %r14
andq $0x0, (%r14)
leaq 0x30(%rsp), %rax
andq $0x0, (%rax)
leaq 0x28(%rsp), %rax
andq $0x0, (%rax)
callq 0x3220
movq %rax, %r12
movl %ebx, %r13d
xorl %r15d, %r15d
xorl %ebx, %ebx
movq (%r12), %rax
movsbq %bpl, %rcx
movl (%rax,%rcx,4), %ecx
movl %ecx, %edx
shll $0x18, %edx
cmpl $0x2e000000, %edx       # imm = 0x2E000000
jne 0x66cc
testl %ebx, %ebx
jne 0x6779
leaq 0x30(%rsp), %r14
pushq $0x1
popq %rbx
jmp 0x675e
movsbl %cl, %ecx
cmpl $0x10, %r13d
je 0x66f2
movslq %ecx, %rdx
cmpl $0x65, (%rax,%rdx,4)
jne 0x66f2
testl %r15d, %r15d
jne 0x6782
leaq 0x28(%rsp), %r14
pushq $0x1
popq %r15
jmp 0x675e
leal -0x30(%rcx), %eax
leal -0x32(%rcx), %edx
cmpl $0x34, %edx
ja 0x676f
pushq $0x3f
popq %rsi
btq %rdx, %rsi
jb 0x6738
movabsq $0x1f800000000000, %rsi # imm = 0x1F800000000000
btq %rdx, %rsi
jae 0x6727
cmpl $0xa, %r13d
je 0x6a10
addl $-0x57, %ecx
movl %ecx, %eax
jmp 0x6732
movl $0xc0, %esi
btq %rdx, %rsi
jae 0x676f
cmpl $0x8, %r13d
je 0x6794
cmpl $0x2, %r13d
je 0x678b
cmpl $0x1, %ebx
pushq $0x2
popq %rcx
cmovel %ecx, %ebx
cmpl $0x1, %r15d
cmovel %ecx, %r15d
movq (%r14), %rcx
imulq %r13, %rcx
movl %eax, %eax
addq %rcx, %rax
movq %rax, (%r14)
movq 0x40(%rsp), %rdi
callq 0x64ad
movl %eax, %ebp
jmp 0x669f
addl $-0x30, %ecx
cmpl $0x2, %ecx
jb 0x673e
jmp 0x67a7
leaq 0x64d5(%rip), %rsi      # 0xcc55
jmp 0x679b
leaq 0x64f1(%rip), %rsi      # 0xcc7a
jmp 0x679b
leaq 0x6529(%rip), %rsi      # 0xccbb
jmp 0x679b
leaq 0x64ff(%rip), %rsi      # 0xcc9a
movq 0x18(%rsp), %rdi
xorl %eax, %eax
callq 0x35e4
testl %ebx, %ebx
setne %bl
sete %al
cmpl $0xa, %r13d
sete %cl
orb %al, %cl
movq 0x18(%rsp), %r14
jne 0x67d2
leaq 0x6517(%rip), %rsi      # 0xccdd
movq %r14, %rdi
xorl %eax, %eax
callq 0x35e4
movb $0x1, %bl
cmpl $0x1, %r15d
jne 0x67e9
leaq 0x6525(%rip), %rsi      # 0xcd04
movq %r14, %rdi
xorl %eax, %eax
callq 0x35e4
pushq $0x6
popq %rdi
callq 0xb5ed
movq %rax, %rcx
cmpl $0x2, %r15d
sete %al
orb %al, %bl
cmpb $0x1, %bl
jne 0x6808
movl $0x7, (%rcx)
movl $0x4, 0x4(%rcx)
movl $0x1, 0xc(%rcx)
movq 0x10(%rsp), %rax
movq %rcx, 0x8(%rsp)
movq %rcx, 0x28(%rax)
movq 0x10(%r14), %rax
movq %rax, 0x60(%rsp)
movupd (%r14), %xmm0
movapd %xmm0, 0x50(%rsp)
xorl %ebx, %ebx
callq 0x3230
movq %rax, %r15
xorl %r14d, %r14d
xorl %r13d, %r13d
movq (%r15), %rcx
movsbq %bpl, %rax
testb $0x4, 0x1(%rcx,%rax,2)
je 0x6891
movq (%r12), %rcx
movl (%rcx,%rax,4), %eax
cmpl $0x66, %eax
je 0x6875
cmpl $0x75, %eax
je 0x6870
cmpl $0x6c, %eax
jne 0x68ae
incl %ebx
jmp 0x6883
incl %r14d
jmp 0x6883
movq 0x8(%rsp), %rax
movl $0x7, (%rax)
incl %r13d
movq 0x40(%rsp), %rdi
callq 0x64ad
movl %eax, %ebp
jmp 0x6848
cmpl $0x1, %r13d
jle 0x6964
leaq 0x6480(%rip), %rsi      # 0xcd22
leaq 0x50(%rsp), %rdi
xorl %eax, %eax
callq 0x35e4
movq 0x8(%rsp), %rax
cmpl $0x6, (%rax)
jne 0x68d7
cmpl $0x0, 0xc(%rax)
movq 0x38(%rsp), %rax
je 0x68c9
imulq 0x20(%rsp), %rax
movq 0x10(%rsp), %rcx
movq %rax, 0x20(%rcx)
jmp 0x69d4
movq 0x30(%rsp), %rbx
movq %rbx, %xmm1
punpckldq 0x6207(%rip), %xmm1 # xmm1 = xmm1[0],mem[0],xmm1[1],mem[1]
subpd 0x620f(%rip), %xmm1     # 0xcb00
movapd %xmm1, %xmm0
unpckhpd %xmm1, %xmm0            # xmm0 = xmm0[1],xmm1[1]
addsd %xmm1, %xmm0
movapd %xmm0, 0x40(%rsp)
callq 0x3120
addsd 0x6200(%rip), %xmm0     # 0xcb10
callq 0x3200
movapd %xmm0, %xmm1
movsd 0x61f7(%rip), %xmm0     # 0xcb18
callq 0x3090
movapd 0x61d2(%rip), %xmm4     # 0xcb00
movsd 0x61ba(%rip), %xmm3     # 0xcaf0
movsd 0x38(%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 0x698e
movapd 0x40(%rsp), %xmm2
divsd %xmm0, %xmm2
movapd %xmm2, %xmm0
jmp 0x6996
movq 0x8(%rsp), %rax
cmpl $0x6, (%rax)
jne 0x69e3
cmpl $0x2, %r14d
setge %al
cmpl $0x3, %ebx
setge %cl
orb %al, %cl
jne 0x689b
cmpl $0x2, %ebx
jne 0x68ae
jmp 0x69ff
movsd 0x618a(%rip), %xmm0     # 0xcb20
addsd %xmm1, %xmm0
movq 0x10(%rsp), %rbx
movsd %xmm0, 0x20(%rbx)
movsd 0x28(%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 0x6153(%rip), %xmm0     # 0xcb18
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 %r14d, %r14d
setg %al
cmpl $0x2, %ebx
setge %cl
orb %al, %cl
jne 0x689b
testl %ebx, %ebx
je 0x68ae
movq 0x8(%rsp), %rax
movl $0x8, 0x4(%rax)
jmp 0x68ae
testl %ebx, %ebx
setne %bl
movq 0x18(%rsp), %r14
jmp 0x67d2
pushq $0x8
popq %rbx
jmp 0x665e