// File: /workspace/github_c_makefile_star2_O2/Yamsman[P]scc/src/lex.c
// Function: lex_next
void lex_next(lexer *lx) {
	token t = {-1, -1, lx->tgt->loc, 0, NULL};
	lex_target *tgt = lx->tgt;
	s_pos loc = tgt->loc;

	//Use ungotten tokens
	token_n *pre = lx->pre;
	if (pre != NULL) {
		lx->ahead = pre->t;
		lx->pre = pre->next;
		free(pre);
		return;
	}

	//Skip whitespace
	//Count the beginning of a file as a newline
	//When the lexer is reset (when a new context is created) it begins from here
	int nline = (tgt->pos == tgt->buf && tgt->type == TGT_FILE);
reset:	nline |= lex_wspace(lx);
	tgt = lx->tgt;
	t.nline = nline;
	loc = tgt->loc;

	//Process the next character
	t.loc = tgt->loc;
	int noadvc = 0;
	switch (lex_cur(lx)) {
		case '\0':
			//End of stream
			t.type = TOK_END;
			lx->ahead = t;
			return;
		case ';': 	t.type = TOK_SEM; 	break;
		case ':':	t.type = TOK_COL;	break;
		case ',':	t.type = TOK_CMM; 	break;
		case '.':
			if (isdigit(lex_peekc(lx))) goto num_case;
			t.type = TOK_PRD; 
			break;
		case '{':	t.type = TOK_LBR; 	break;
		case '}':	t.type = TOK_RBR; 	break;
		case '(':	t.type = TOK_LPR; 	break;
		case ')':	t.type = TOK_RPR; 	break;
		case '[':	t.type = TOK_LBK;	break;
		case ']':	t.type = TOK_RBK;	break;
		case '"':
			lex_str(lx, &t);
			noadvc = 1;
			break;
		case '\'':
			//Character literal
			lex_advc(lx);

			//Process escape character
			char val = lex_cur(lx);
			if (val == '\\') {
				lex_advc(lx);
				val = lex_eschar(lx);
			} else {
				lex_advc(lx);
			}

			//Check for closing '
			if (lex_cur(lx) == '\'') {
				lex_advc(lx);
			} else {
				c_error(&loc, "Multiple characters in character literal\n");
			}

			//Make integer type
			s_type *ty = type_new(TYPE_INT);
			ty->size = SIZE_CHAR;
			ty->is_signed = 1;
			t.dtype = ty;

			t.dat.ival = val;
			t.type = TOK_CONST;
			noadvc = 1;
			break;
		case '#':
			t.type = TOK_SNS;
			lx->m_exp = 0;
			if (lex_peekc(lx) == '#') {
				lex_advc(lx);
				t.type = TOK_DNS;
				c_error(&loc, "Stray '##' in source\n");
			} else if (!nline && loc.col != 1) {
				c_error(&loc, "Stray '#' in source\n");
			}
			lex_advc(lx); //Advance manually; do not attempt to expand directive
			noadvc = 1;
			lx->m_exp = 1;
			break;
		case '?': 	t.type = TOK_QMK; 	break;
		case '+':
			//if (isdigit(*cur)) goto num_case;
			t.type = TOK_ADD;
			if (lex_peekc(lx) == '=') {
				t.type = TOK_ASSIGN_ADD;
				lex_advc(lx);
			} else if (lex_peekc(lx) == '+') {
				t.type = TOK_INC;
				lex_advc(lx);
			}
			break;
		case '-':
			//if (isdigit(*cur)) goto num_case;
			t.type = TOK_SUB;
			if (lex_peekc(lx) == '=') {
				t.type = TOK_ASSIGN_SUB;
				lex_advc(lx);
			} else if (lex_peekc(lx) == '-') {
				t.type = TOK_DEC;
				lex_advc(lx);
			} else if (lex_peekc(lx) == '>') {
				t.type = TOK_PTR;
				lex_advc(lx);
			}
			break;
		case '*':
			t.type = TOK_ASR;
			if (lex_peekc(lx) == '=') {
				t.type = TOK_ASSIGN_MUL;
				lex_advc(lx);
			}
			break;
		case '/': 
			t.type = TOK_DIV;
			if (lex_peekc(lx) == '=') {
				t.type = TOK_ASSIGN_DIV;
				lex_advc(lx);
			}
			break;
		case '%':
			t.type = TOK_MOD;
			if (lex_peekc(lx) == '=') {
				t.type = TOK_ASSIGN_MOD;
				lex_advc(lx);
			}
			break;
		case '&':
			t.type = TOK_AND;
			if (lex_peekc(lx) == '=') {
				t.type = TOK_ASSIGN_AND;
				lex_advc(lx);
			} else if (lex_peekc(lx) == '&') {
				t.type = TOK_LOGIC_AND;
				lex_advc(lx);
			}
			break;
		case '|':
			t.type = TOK_OR;
			if (lex_peekc(lx) == '=') {
				t.type = TOK_ASSIGN_OR;
				lex_advc(lx);
			} else if (lex_peekc(lx) == '|') {
				t.type = TOK_LOGIC_OR;
				lex_advc(lx);
			}
			break;
		case '^':
			t.type = TOK_XOR;
			if (lex_peekc(lx) == '=') {
				t.type = TOK_ASSIGN_XOR;
				lex_advc(lx);
			}
			break;
		case '~':
			t.type = TOK_TLD;
			break;
		case '=':
			t.type = TOK_ASSIGN;
			if (lex_peekc(lx) == '=')
				t.type = TOK_EQ;
			lex_advc(lx);
			break;
		case '!':
			t.type = TOK_NOT;
			if (lex_peekc(lx) == '=') {
				t.type = TOK_NEQ;
				lex_advc(lx);
			}
			break;
		case '<':
			t.type = TOK_LTH;
			if (lex_peekc(lx) == '=') {
				t.type = TOK_LEQ;
				lex_advc(lx);
			} else if (lex_peekc(lx) == '<') {
				t.type = TOK_LSHIFT;
				lex_advc(lx);
				if (lex_peekc(lx) == '=') {
					t.type = TOK_ASSIGN_LSHIFT;
					lex_advc(lx);
				}
			}
			break;
		case '>':
			t.type = TOK_GTH;
			if (lex_peekc(lx) == '=') {
				t.type = TOK_GEQ;
				lex_advc(lx);
			} else if (lex_peekc(lx) == '<') {
				t.type = TOK_RSHIFT;
				lex_advc(lx);
				if (lex_peekc(lx) == '=') {
					t.type = TOK_ASSIGN_RSHIFT;
					lex_advc(lx);
				}
			}
			break;
		case 'a': case 'b': case 'c': case 'd': case 'e':
		case 'f': case 'g': case 'h': case 'i': case 'j':
		case 'k': case 'l': case 'm': case 'n': case 'o':
		case 'p': case 'q': case 'r': case 's': case 't':
		case 'u': case 'v': case 'w': case 'x': case 'y':
		case 'z':
		case 'A': case 'B': case 'C': case 'D': case 'E':
		case 'F': case 'G': case 'H': case 'I': case 'J':
		case 'K': case 'L': case 'M': case 'N': case 'O':
		case 'P': case 'Q': case 'R': case 'S': case 'T':
		case 'U': case 'V': case 'W': case 'X': case 'Y':
		case 'Z': case '_': {
			//Read identifier
			lex_ident(lx, &t);

			//Check if matches keyword
			//String is not freed yet; could be used as macro name
			int kw_id = (long long)map_get(&kw_table, t.dat.sval); 
			if (kw_id > 0)
				t.type = kw_id;

			//If the token is an identifier, free the string
			if (kw_id != 0) {
				free(t.dat.sval);
				t.dat.sval = NULL;
			}
			noadvc = 1;
			} break;
		case '0': case '1': case '2': case '3': case '4':
		case '5': case '6': case '7': case '8': case '9':
			//Read number
num_case:		lex_num(lx, &t);
			t.type = TOK_CONST;
			noadvc = 1;
			break;
		default: 
			//illegal char
			t.type = TOK_END;
			break;
	}
	//Unless the specific case handled it manually, advance to the next char
end:	if (!noadvc)
		lex_advc(lx);
	lx->ahead = t;
	return;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %rbx
subq $0x48, %rsp
movq %rdi, %rbx
orl $-0x1, (%rsp)
movq (%rdi), %rax
xorps %xmm0, %xmm0
movups %xmm0, 0x20(%rsp)
movq 0x8(%rdi), %rdi
testq %rdi, %rdi
je 0x6dfb
movups (%rdi), %xmm0
movups 0x10(%rdi), %xmm1
movups 0x20(%rdi), %xmm2
movups %xmm2, 0x30(%rbx)
movups %xmm1, 0x20(%rbx)
movups %xmm0, 0x10(%rbx)
movq 0x30(%rdi), %rax
movq %rax, 0x8(%rbx)
addq $0x48, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
jmp 0x3030
leaq 0x8(%rsp), %r14
movq 0x18(%rax), %rcx
xorl %r15d, %r15d
cmpq 0x10(%rax), %rcx
jne 0x6e18
xorl %r15d, %r15d
cmpl $0x0, 0x8(%rax)
sete %r15b
movq %rbx, %rdi
callq 0x7370
movl %eax, %ebp
orl %r15d, %ebp
movq (%rbx), %rax
movl %ebp, 0x4(%rsp)
movq 0x38(%rax), %rcx
movq %rcx, 0x40(%rsp)
movups 0x28(%rax), %xmm0
movaps %xmm0, 0x30(%rsp)
movq 0x38(%rax), %rcx
movq %rcx, 0x10(%r14)
movups 0x28(%rax), %xmm0
movups %xmm0, (%r14)
movq %rbx, %rdi
callq 0x6493
cmpb $0x7e, %al
ja 0x71ce
movzbl %al, %eax
leaq 0x5a60(%rip), %rcx      # 0xc8c8
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq %rsp, %r14
movq %rbx, %rdi
movq %r14, %rsi
callq 0x650a
movq 0x20(%r14), %r14
leaq 0xc5f6(%rip), %rdi      # 0x13480
movq %r14, %rsi
callq 0xbd22
testl %eax, %eax
jle 0x6e9b
movl %eax, (%rsp)
jmp 0x6ea1
je 0x7334
movq %r14, %rdi
callq 0x3030
andq $0x0, 0x20(%rsp)
jmp 0x7334
movl $0x17, (%rsp)
movq %rbx, %rdi
callq 0x64fe
cmpb $0x3d, %al
jne 0x732c
movl $0x2f, (%rsp)
jmp 0x7324
movl $0x2, (%rsp)
jmp 0x732c
movl $0xf, (%rsp)
jmp 0x732c
callq 0x3230
movq (%rax), %r14
movq %rbx, %rdi
callq 0x64fe
movsbq %al, %rax
testb $0x8, 0x1(%r14,%rax,2)
jne 0x6f17
movl $0x4, (%rsp)
jmp 0x732c
movq %rsp, %r14
movq %rbx, %rdi
movq %r14, %rsi
callq 0x65aa
movl $0x33, (%r14)
jmp 0x7334
movl $0xa, (%rsp)
jmp 0x732c
movl $0x13, (%rsp)
movq %rbx, %rdi
callq 0x64fe
cmpb $0x3d, %al
jne 0x732c
movl $0x2b, (%rsp)
jmp 0x7324
movl $0x12, (%rsp)
movq %rbx, %rdi
callq 0x64fe
cmpb $0x3d, %al
jne 0x732c
movl $0x2a, (%rsp)
jmp 0x7324
movl $0x18, (%rsp)
jmp 0x732c
movl $0x7, (%rsp)
jmp 0x732c
movl $0x10, (%rsp)
movq %rbx, %rdi
callq 0x64fe
cmpb $0x3d, %al
jne 0x71d7
movl $0x28, (%rsp)
jmp 0x7324
movl $0x8, (%rsp)
jmp 0x732c
movl $0x15, (%rsp)
movq %rbx, %rdi
callq 0x64fe
cmpb $0x3d, %al
jne 0x71f3
movl $0x2d, (%rsp)
jmp 0x7324
movq %rbx, %rdi
callq 0x64ad
movq %rbx, %rdi
callq 0x6493
movl %eax, %ebp
movq %rbx, %rdi
callq 0x64ad
cmpb $0x5c, %bpl
jne 0x7017
movq %rbx, %rdi
callq 0x6a27
movl %eax, %ebp
movq %rbx, %rdi
callq 0x6493
cmpb $0x27, %al
jne 0x720f
movq %rbx, %rdi
callq 0x64ad
jmp 0x7222
movl $0x19, (%rsp)
movq %rbx, %rdi
callq 0x64fe
cmpb $0x3d, %al
jne 0x724d
movl $0x1b, (%rsp)
jmp 0x7324
movl $0xd, (%rsp)
andl $0x0, 0x68(%rbx)
movq %rbx, %rdi
callq 0x64fe
cmpb $0x23, %al
jne 0x7288
movq %rbx, %rdi
callq 0x64ad
movl $0xe, (%rsp)
leaq 0x5d56(%rip), %rsi      # 0xcdde
jmp 0x729a
movl $0x21, (%rsp)
movq %rbx, %rdi
callq 0x64fe
cmpb $0x3d, %al
jne 0x732c
movl $0x1e, (%rsp)
jmp 0x7324
movl $0x14, (%rsp)
movq %rbx, %rdi
callq 0x64fe
cmpb $0x3d, %al
jne 0x732c
movl $0x2c, (%rsp)
jmp 0x7324
movl $0x11, (%rsp)
movq %rbx, %rdi
callq 0x64fe
cmpb $0x3d, %al
jne 0x72b7
movl $0x29, (%rsp)
jmp 0x7324
movl $0x3, (%rsp)
jmp 0x732c
andl $0x0, (%rsp)
movups 0x10(%rsp), %xmm0
movups 0x20(%rsp), %xmm1
movups %xmm1, 0x30(%rbx)
movups %xmm0, 0x20(%rbx)
movups (%rsp), %xmm0
movups %xmm0, 0x10(%rbx)
jmp 0x7365
movl $0x1, (%rsp)
jmp 0x732c
movq %rsp, %rsi
movq %rbx, %rdi
callq 0x6c97
jmp 0x7334
movl $0x16, (%rsp)
movq %rbx, %rdi
callq 0x64fe
cmpb $0x3d, %al
jne 0x72cc
movl $0x2e, (%rsp)
jmp 0x7324
movl $0x27, (%rsp)
movq %rbx, %rdi
callq 0x64fe
cmpb $0x3d, %al
jne 0x7324
movl $0x1d, (%rsp)
jmp 0x7324
movl $0x1a, (%rsp)
movq %rbx, %rdi
callq 0x64fe
cmpb $0x3d, %al
jne 0x72e1
movl $0x1c, (%rsp)
jmp 0x7324
movl $0x9, (%rsp)
jmp 0x732c
movl $0x5, (%rsp)
jmp 0x732c
movl $0x6, (%rsp)
jmp 0x732c
andl $0x0, (%rsp)
jmp 0x732c
movq %rbx, %rdi
callq 0x64fe
cmpb $0x2b, %al
jne 0x732c
movl $0x22, (%rsp)
jmp 0x7324
movq %rbx, %rdi
callq 0x64fe
cmpb $0x26, %al
jne 0x732c
movl $0x20, (%rsp)
jmp 0x7324
leaq 0x5b9e(%rip), %rsi      # 0xcdb4
leaq 0x30(%rsp), %rdi
xorl %eax, %eax
callq 0x35e4
pushq $0x6
popq %rdi
callq 0xb5ed
pushq $0x1
popq %rcx
movl %ecx, 0x4(%rax)
movl %ecx, 0xc(%rax)
movq %rax, 0x28(%rsp)
movsbq %bpl, %rax
movq %rax, 0x20(%rsp)
movl $0x33, (%rsp)
jmp 0x7334
movq %rbx, %rdi
callq 0x64fe
cmpb $0x3c, %al
jne 0x732c
movl $0x25, (%rsp)
movq %rbx, %rdi
callq 0x64ad
movq %rbx, %rdi
callq 0x64fe
cmpb $0x3d, %al
jne 0x732c
movl $0x30, (%rsp)
jmp 0x7324
testl %ebp, %ebp
jne 0x72a6
cmpl $0x1, 0x34(%rsp)
je 0x72a6
leaq 0x5b5a(%rip), %rsi      # 0xcdf4
leaq 0x30(%rsp), %rdi
xorl %eax, %eax
callq 0x35e4
movq %rbx, %rdi
callq 0x64ad
movl $0x1, 0x68(%rbx)
jmp 0x7334
movq %rbx, %rdi
callq 0x64fe
cmpb $0x2d, %al
jne 0x7311
movl $0x23, (%rsp)
jmp 0x7324
movq %rbx, %rdi
callq 0x64fe
cmpb $0x7c, %al
jne 0x732c
movl $0x1f, (%rsp)
jmp 0x7324
movq %rbx, %rdi
callq 0x64fe
cmpb $0x3c, %al
jne 0x732c
movl $0x26, (%rsp)
movq %rbx, %rdi
callq 0x64ad
movq %rbx, %rdi
callq 0x64fe
cmpb $0x3d, %al
jne 0x732c
movl $0x31, (%rsp)
jmp 0x7324
movq %rbx, %rdi
callq 0x64fe
cmpb $0x3e, %al
jne 0x732c
movl $0x24, (%rsp)
movq %rbx, %rdi
callq 0x64ad
movq %rbx, %rdi
callq 0x64ad
movl (%rsp), %eax
movq 0x4(%rsp), %rcx
movl 0xc(%rsp), %edx
movups 0x10(%rsp), %xmm0
movq 0x20(%rsp), %rsi
movq %rsi, 0x30(%rbx)
movq 0x28(%rsp), %rsi
movq %rsi, 0x38(%rbx)
movups %xmm0, 0x20(%rbx)
movl %eax, 0x10(%rbx)
movq %rcx, 0x14(%rbx)
movl %edx, 0x1c(%rbx)
addq $0x48, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq