// File: /workspace/github_c_makefile_star2_O0/mloar[P]charset/utf7.c
// Function: read_utf7
static void read_utf7(charset_spec const *charset, long int input_chr,
		      charset_state *state,
		      void (*emit)(void *ctx, long int output), void *emitctx)
{
    long int hw;

    UNUSEDARG(charset);

    /*
     * state->s0 is used to handle the conversion of the UTF-7
     * transport format into a stream of halfwords. Its layout is:
     * 
     *  - In normal ASCII mode, it is zero.
     * 
     * 	- Otherwise, it holds a leading 1 followed by all the bits
     * 	  so far accumulated in base64 digits.
     * 
     * 	- Special case: when we have only just seen the initial `+'
     * 	  which enters base64 mode, it is set to 2 rather than 1
     * 	  (this is an otherwise unused value since base64 always
     * 	  accumulates an even number of bits at a time), so that
     * 	  the special sequence `+-' can be made to encode `+'
     * 	  easily.
     * 
     * state->s1 is used to handle the conversion of those
     * halfwords into Unicode values. It contains a high surrogate
     * value if we've just seen one, and 0 otherwise.
     */

    if (!state->s0) {
	if (input_chr == '+')
	    state->s0 = 2;
	else
	    emit(emitctx, input_chr);
	return;
    } else {
	if (!SET_B(input_chr)) {
	    /*
	     * base64 mode ends here. Emit the character we have,
	     * unless it's a minus in which case we should swallow
	     * it.
	     */
	    if (input_chr != '-')
		emit(emitctx, input_chr);
	    else if (state->s0 == 2)
		emit(emitctx, '+');    /* special case */
	    state->s0 = 0;
	    return;
	}

	/*
	 * Now we have a base64 character, so add it to our state,
	 * first correcting the special case value of s0.
	 */
	if (state->s0 == 2)
	    state->s0 = 1;
	state->s0 = (state->s0 << 6) | base64_value(input_chr);
    }

    /*
     * If we don't have a whole halfword at this point, bale out.
     */
    if (!(state->s0 & 0xFFFF0000))
	return;

    /*
     * Otherwise, extract the halfword. There are three
     * possibilities for where the top set bit might be.
     */
    if (state->s0 & 0x00100000) {
	hw = (state->s0 >> 4) & 0xFFFF;
	state->s0 = (state->s0 & 0xF) | 0x10;
    } else if (state->s0 & 0x00040000) {
	hw = (state->s0 >> 2) & 0xFFFF;
	state->s0 = (state->s0 & 3) | 4;
    } else {
	hw = state->s0 & 0xFFFF;
	state->s0 = 1;
    }

    /*
     * Now what reaches this point should be a stream of halfwords
     * in sensible numeric form. So now we process surrogates.
     */
    if (state->s1) {
	/*
	 * We have already seen a high surrogate, so we expect a
	 * low surrogate. Whinge if we didn't get it.
	 */
	if (hw < 0xDC00 || hw >= 0xE000) {
	    emit(emitctx, ERROR);
	} else {
	    hw &= 0x3FF;
	    hw |= (state->s1 & 0x3FF) << 10;
	    emit(emitctx, hw + 0x10000);
	}
	state->s1 = 0;
    } else {
	/*
	 * Any low surrogate is an error.
	 */
	if (hw >= 0xDC00 && hw < 0xE000) {
	    emit(emitctx, ERROR);
	    return;
	}

	/*
	 * Any high surrogate is simply stored until we see the
	 * next halfword.
	 */
	if (hw >= 0xD800 && hw < 0xDC00) {
	    state->s1 = hw;
	    return;
	}

	/*
	 * Anything else we simply output.
	 */
	emit(emitctx, hw);
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x50, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movq %r8, -0x28(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x8(%rbp)
movq -0x18(%rbp), %rax
cmpq $0x0, (%rax)
jne 0xbb95
cmpq $0x2b, -0x10(%rbp)
jne 0xbb82
movq -0x18(%rbp), %rax
movq $0x2, (%rax)
jmp 0xbb90
movq -0x20(%rbp), %rax
movq -0x28(%rbp), %rdi
movq -0x10(%rbp), %rsi
callq *%rax
jmp 0xbe46
cmpq $0x0, -0x10(%rbp)
jl 0xbbbd
cmpq $0x80, -0x10(%rbp)
jge 0xbbbd
movq -0x10(%rbp), %rcx
leaq 0x9a24f(%rip), %rax     # 0xa5e00
movzbl (%rax,%rcx), %eax
andl $0x4, %eax
cmpl $0x0, %eax
jne 0xbbff
cmpq $0x2d, -0x10(%rbp)
je 0xbbd4
movq -0x20(%rbp), %rax
movq -0x28(%rbp), %rdi
movq -0x10(%rbp), %rsi
callq *%rax
jmp 0xbbef
movq -0x18(%rbp), %rax
cmpq $0x2, (%rax)
jne 0xbbed
movq -0x20(%rbp), %rax
movq -0x28(%rbp), %rdi
movl $0x2b, %esi
callq *%rax
jmp 0xbbef
movq -0x18(%rbp), %rax
movq $0x0, (%rax)
jmp 0xbe46
movq -0x18(%rbp), %rax
cmpq $0x2, (%rax)
jne 0xbc14
movq -0x18(%rbp), %rax
movq $0x1, (%rax)
movq -0x18(%rbp), %rax
movq (%rax), %rax
shlq $0x6, %rax
movq %rax, -0x38(%rbp)
cmpq $0x41, -0x10(%rbp)
jl 0xbc3f
cmpq $0x5a, -0x10(%rbp)
jg 0xbc3f
movq -0x10(%rbp), %rax
subq $0x41, %rax
movq %rax, -0x40(%rbp)
jmp 0xbcaa
cmpq $0x61, -0x10(%rbp)
jl 0xbc5f
cmpq $0x7a, -0x10(%rbp)
jg 0xbc5f
movq -0x10(%rbp), %rax
subq $0x61, %rax
addq $0x1a, %rax
movq %rax, -0x48(%rbp)
jmp 0xbca2
cmpq $0x30, -0x10(%rbp)
jl 0xbc7f
cmpq $0x39, -0x10(%rbp)
jg 0xbc7f
movq -0x10(%rbp), %rax
subq $0x30, %rax
addq $0x34, %rax
movq %rax, -0x50(%rbp)
jmp 0xbc9a
movq -0x10(%rbp), %rdx
movl $0x3f, %eax
movl $0x3e, %ecx
cmpq $0x2b, %rdx
cmovel %ecx, %eax
cltq
movq %rax, -0x50(%rbp)
movq -0x50(%rbp), %rax
movq %rax, -0x48(%rbp)
movq -0x48(%rbp), %rax
movq %rax, -0x40(%rbp)
movq -0x38(%rbp), %rcx
movq -0x40(%rbp), %rax
orq %rax, %rcx
movq -0x18(%rbp), %rax
movq %rcx, (%rax)
movq -0x18(%rbp), %rcx
movabsq $0xffff0000, %rax       # imm = 0xFFFF0000
andq (%rcx), %rax
cmpq $0x0, %rax
jne 0xbcd8
jmp 0xbe46
movq -0x18(%rbp), %rax
movq (%rax), %rax
andq $0x100000, %rax         # imm = 0x100000
cmpq $0x0, %rax
je 0xbd18
movq -0x18(%rbp), %rax
movq (%rax), %rax
shrq $0x4, %rax
andq $0xffff, %rax           # imm = 0xFFFF
movq %rax, -0x30(%rbp)
movq -0x18(%rbp), %rax
movq (%rax), %rcx
andq $0xf, %rcx
orq $0x10, %rcx
movq -0x18(%rbp), %rax
movq %rcx, (%rax)
jmp 0xbd76
movq -0x18(%rbp), %rax
movq (%rax), %rax
andq $0x40000, %rax          # imm = 0x40000
cmpq $0x0, %rax
je 0xbd58
movq -0x18(%rbp), %rax
movq (%rax), %rax
shrq $0x2, %rax
andq $0xffff, %rax           # imm = 0xFFFF
movq %rax, -0x30(%rbp)
movq -0x18(%rbp), %rax
movq (%rax), %rcx
andq $0x3, %rcx
orq $0x4, %rcx
movq -0x18(%rbp), %rax
movq %rcx, (%rax)
jmp 0xbd74
movq -0x18(%rbp), %rax
movq (%rax), %rax
andq $0xffff, %rax           # imm = 0xFFFF
movq %rax, -0x30(%rbp)
movq -0x18(%rbp), %rax
movq $0x1, (%rax)
jmp 0xbd76
movq -0x18(%rbp), %rax
cmpq $0x0, 0x8(%rax)
je 0xbdf1
cmpq $0xdc00, -0x30(%rbp)    # imm = 0xDC00
jl 0xbd95
cmpq $0xe000, -0x30(%rbp)    # imm = 0xE000
jl 0xbda6
movq -0x20(%rbp), %rax
movq -0x28(%rbp), %rdi
movl $0xffff, %esi           # imm = 0xFFFF
callq *%rax
jmp 0xbde3
movq -0x30(%rbp), %rax
andq $0x3ff, %rax            # imm = 0x3FF
movq %rax, -0x30(%rbp)
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rax
andq $0x3ff, %rax            # imm = 0x3FF
shlq $0xa, %rax
orq -0x30(%rbp), %rax
movq %rax, -0x30(%rbp)
movq -0x20(%rbp), %rax
movq -0x28(%rbp), %rdi
movq -0x30(%rbp), %rsi
addq $0x10000, %rsi          # imm = 0x10000
callq *%rax
movq -0x18(%rbp), %rax
movq $0x0, 0x8(%rax)
jmp 0xbe46
cmpq $0xdc00, -0x30(%rbp)    # imm = 0xDC00
jl 0xbe16
cmpq $0xe000, -0x30(%rbp)    # imm = 0xE000
jge 0xbe16
movq -0x20(%rbp), %rax
movq -0x28(%rbp), %rdi
movl $0xffff, %esi           # imm = 0xFFFF
callq *%rax
jmp 0xbe46
cmpq $0xd800, -0x30(%rbp)    # imm = 0xD800
jl 0xbe38
cmpq $0xdc00, -0x30(%rbp)    # imm = 0xDC00
jge 0xbe38
movq -0x30(%rbp), %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x8(%rax)
jmp 0xbe46
movq -0x20(%rbp), %rax
movq -0x28(%rbp), %rdi
movq -0x30(%rbp), %rsi
callq *%rax
addq $0x50, %rsp
popq %rbp
retq
nopl (%rax)