// File: /workspace/github_c_makefile_star2_O2/mloar[P]charset/iso2022.c
// Function: docs_char
static void docs_char(charset_state *state,
		      void (*emit)(void *ctx, long int output),
		      void *emitctx, int cset, char *data, int datalen)
{
    int curr_cset, currlen, i;

    /*
     * cset is the index into ctext_encodings[]. It can also be -1
     * to mean DOCS UTF-8, or -2 to mean no DOCS (ordinary 2022).
     * In the latter case, `chr' is ignored.
     */

    /*
     * First, terminate a DOCS segment if necessary. We always have
     * to terminate a DOCS segment if one is active and we're about
     * to switch to a different one; we might also have to
     * terminate a length-encoded DOCS segment if we've run out of
     * storage space to accumulate characters in it.
     */
    curr_cset = ((state->s1 >> 14) & 7) - 2;
    currlen = ((state->s1 >> 11) & 7);
    if ((curr_cset != -2 && curr_cset != cset) ||
	(curr_cset >= 0 && currlen + datalen > 5)) {
	if (curr_cset == -1) {
	    /*
	     * Terminating DOCS UTF-8 is easy.
	     */
	    emit(emitctx, ESC);
	    emit(emitctx, '%');
	    emit(emitctx, '@');
	} else {
	    int len;

	    /*
	     * To terminate a length-encoded DOCS segment we must
	     * actually output the whole thing.
	     */
	    emit(emitctx, ESC);
	    emit(emitctx, '%');
	    emit(emitctx, '/');
	    emit(emitctx, '0' + ctext_encodings[curr_cset].octets_per_char);
	    len = currlen + datalen +
		strlen(ctext_encodings[curr_cset].name);
	    assert(len < (1 << 14));
	    emit(emitctx, 0x80 | ((len >> 7) & 0x7F));
	    emit(emitctx, 0x80 | ((len     ) & 0x7F));
	    /* The name stored in ctext_encodings[] includes the trailing \2 */
	    for (i = 0; ctext_encodings[curr_cset].name[i]; i++)
		emit(emitctx, ctext_encodings[curr_cset].name[i]);
	    for (i = 0; i < currlen; i++)
		emit(emitctx,
		     (i == 0 ? state->s1 : state->s0 >> (8*(4-i))) & 0xFF);
	    for (i = 0; i < datalen; i++)
		emit(emitctx, data[i]);

	    /*
	     * We've now dealt with the input data, so clear it so
	     * we don't try to do so again below.
	     */
	    datalen = 0;
	}
	curr_cset = -2;
    }

    /*
     * Now, start a DOCS segment if necessary.
     */
    if (curr_cset != cset) {
	assert(cset != -2);
	if (cset == -1) {
	    /*
	     * Start DOCS UTF-8.
	     */
	    emit(emitctx, ESC);
	    emit(emitctx, '%');
	    emit(emitctx, 'G');
	} else {
	    /*
	     * Starting a length-encoded DOCS segment is simply a
	     * matter of setting our stored length counter to zero.
	     */
	    currlen = 0;
	    state->s1 &= ~(7 << 11);
	    state->s1 &= ~0xFF;
	    state->s0 = 0;
	}
    }
    state->s1 &= ~(7 << 14);
    assert((cset+2) >= 0 && (cset+2) < 8);
    state->s1 |= ((cset+2) << 14);

    /*
     * Now we're in the right DOCS state. Actually deal with the
     * input data, if we haven't already done so above.
     */
    if (datalen > 0) {
	assert(cset != 2);
	if (cset == -1) {
	    /*
	     * In DOCS UTF-8, we output data as soon as we get it.
	     */
	    for (i = 0; i < datalen; i++)
		emit(emitctx, data[i]);
	} else {
	    /*
	     * In length-encoded DOCS, we just store our data and
	     * bide our time. It'll all be output when we fill up
	     * or switch to another character set.
	     */
	    assert(currlen + datalen <= 5);   /* overflow handled already */
	    for (i = 0; i < datalen; i++) {
		if (currlen + i == 0)
		    state->s1 |= data[i] & 0xFF;
		else
		    state->s0 |= (data[i] & 0xFF) << (8*(4-(currlen+i)));
	    }
	    currlen += datalen;
	    assert(currlen >= 0 && currlen < 8);
	    state->s1 &= ~(7 << 11);
	    state->s1 |= (currlen << 11);
	}
    }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x28, %rsp
movl %r9d, %r13d
movq %r8, %rbx
movq %rdx, %r15
movq %rsi, %r12
movq %rdi, %r14
movl 0x8(%rdi), %ebp
movl %ebp, %eax
shrl $0xe, %eax
andl $0x7, %eax
leal -0x2(%rax), %edi
shrl $0xb, %ebp
andl $0x7, %ebp
testl %eax, %eax
sete %sil
movq %rcx, 0x8(%rsp)
cmpl %ecx, %edi
sete %dl
orb %sil, %dl
cmpb $0x1, %dl
jne 0x8235
movl %edi, 0x4(%rsp)
cmpl $0x2, %eax
setae %al
leal (%rbp,%r13), %edx
cmpl $0x6, %edx
setge %cl
testb %cl, %al
jne 0x8247
jmp 0x8399
cmpl $-0x1, %edi
je 0x8377
movl %edi, 0x4(%rsp)
leal (%rbp,%r13), %edx
movl %edx, 0x14(%rsp)
movq %rbp, 0x18(%rsp)
movq %r13, 0x20(%rsp)
pushq $0x1b
popq %rsi
movq %r15, %rdi
callq *%r12
pushq $0x25
popq %rsi
movq %r15, %rdi
callq *%r12
pushq $0x2f
popq %rsi
movq %r15, %rdi
callq *%r12
movl 0x4(%rsp), %eax
imulq $0x18, %rax, %r13
leaq 0x9e641(%rip), %rbp     # 0xa68c0
movsbq 0x8(%r13,%rbp), %rsi
addq $0x30, %rsi
movq %r15, %rdi
callq *%r12
movq (%r13,%rbp), %rbp
movq %rbp, %rdi
callq 0x6040
movq %rax, %r13
addl 0x14(%rsp), %r13d
cmpl $0x4000, %r13d          # imm = 0x4000
jge 0x84c8
movl %r13d, %esi
shrl $0x7, %esi
movl $0x80, %eax
orl %eax, %esi
movl $0xff, %eax
andl %eax, %esi
movq %r15, %rdi
callq *%r12
movl $0x80, %eax
orl %eax, %r13d
movl $0xff, %eax
andl %eax, %r13d
movq %r15, %rdi
movq %r13, %rsi
callq *%r12
movsbq (%rbp), %rsi
testq %rsi, %rsi
je 0x82f9
movq %r15, %rdi
callq *%r12
incq %rbp
jmp 0x82e4
movq 0x18(%rsp), %rax
leal (,%rax,8), %r13d
pushq $0x20
popq %rbp
movq %r13, %rax
addq %rbp, %rax
cmpq $0x20, %rax
je 0x8339
cmpq $0x20, %rbp
jne 0x8322
movzbl 0x8(%r14), %eax
jmp 0x832a
movq (%r14), %rax
movl %ebp, %ecx
shrq %cl, %rax
movzbl %al, %esi
movq %r15, %rdi
callq *%r12
addq $-0x8, %rbp
jmp 0x8309
xorl %r13d, %r13d
movq 0x20(%rsp), %rbp
testl %ebp, %ebp
cmovlel %r13d, %ebp
pushq $-0x2
popq %rax
movl %eax, 0x4(%rsp)
movq 0x8(%rsp), %rax
cmpq %r13, %rbp
je 0x836d
movsbq (%rbx,%r13), %rsi
movq %r15, %rdi
callq *%r12
movq 0x8(%rsp), %rax
incq %r13
jmp 0x8353
xorl %r13d, %r13d
movq 0x18(%rsp), %rbp
jmp 0x839e
pushq $0x1b
popq %rsi
movq %r15, %rdi
callq *%r12
pushq $0x25
popq %rsi
movq %r15, %rdi
callq *%r12
pushq $0x40
popq %rsi
movq %r15, %rdi
callq *%r12
pushq $-0x2
popq %rax
movl %eax, 0x4(%rsp)
movq 0x8(%rsp), %rax
cmpl %eax, 0x4(%rsp)
je 0x83dc
cmpl $-0x1, %eax
je 0x83c1
cmpl $-0x2, %eax
je 0x8525
andw $0xc700, 0x8(%r14)      # imm = 0xC700
andq $0x0, (%r14)
xorl %ebp, %ebp
jmp 0x83dc
pushq $0x1b
popq %rsi
movq %r15, %rdi
callq *%r12
pushq $0x25
popq %rsi
movq %r15, %rdi
callq *%r12
pushq $0x47
popq %rsi
movq %r15, %rdi
callq *%r12
movq $-0x1c001, %rax         # imm = 0xFFFE3FFF
andq 0x8(%r14), %rax
movq %rax, 0x8(%r14)
movq 0x8(%rsp), %rdx
leal 0x2(%rdx), %ecx
cmpl $0x8, %ecx
jae 0x84a9
movl %edx, %ecx
shll $0xe, %ecx
addl $0x8000, %ecx           # imm = 0x8000
orq %rcx, %rax
movq %rax, 0x8(%r14)
testl %r13d, %r13d
jle 0x849a
cmpl $-0x1, %edx
je 0x846f
cmpl $0x2, %edx
je 0x84e7
leal (%rbp,%r13), %edx
cmpl $0x5, %edx
jg 0x8506
movl %ebp, %esi
movl %r13d, %edi
shll $0x3, %ebp
pushq $0x20
popq %rcx
subl %ebp, %ecx
negq %rsi
xorl %r8d, %r8d
cmpq %r8, %rdi
je 0x848a
movzbl (%rbx,%r8), %r9d
cmpq %r8, %rsi
jne 0x845e
orq %r9, %rax
movq %rax, 0x8(%r14)
jmp 0x8467
shll %cl, %r9d
movslq %r9d, %r9
orq %r9, (%r14)
incq %r8
addl $-0x8, %ecx
jmp 0x8446
movl %r13d, %r14d
xorl %r13d, %r13d
cmpq %r13, %r14
je 0x849a
movsbq (%rbx,%r13), %rsi
movq %r15, %rdi
callq *%r12
incq %r13
jmp 0x8475
andq $-0x3801, %rax          # imm = 0xC7FF
shll $0xb, %edx
orq %rax, %rdx
movq %rdx, 0x8(%r14)
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x537f7(%rip), %rdi     # 0x5bca7
leaq 0x53536(%rip), %rsi     # 0x5b9ed
leaq 0x5378c(%rip), %rcx     # 0x5bc4a
movl $0x39f, %edx            # imm = 0x39F
callq 0x6060
leaq 0x5376b(%rip), %rdi     # 0x5bc3a
leaq 0x53517(%rip), %rsi     # 0x5b9ed
leaq 0x5376d(%rip), %rcx     # 0x5bc4a
movl $0x372, %edx            # imm = 0x372
callq 0x6060
leaq 0x537d7(%rip), %rdi     # 0x5bcc5
leaq 0x534f8(%rip), %rsi     # 0x5b9ed
leaq 0x5374e(%rip), %rcx     # 0x5bc4a
movl $0x3a7, %edx            # imm = 0x3A7
callq 0x6060
leaq 0x537c2(%rip), %rdi     # 0x5bccf
leaq 0x534d9(%rip), %rsi     # 0x5b9ed
leaq 0x5372f(%rip), %rcx     # 0x5bc4a
movl $0x3b4, %edx            # imm = 0x3B4
callq 0x6060
leaq 0x53770(%rip), %rdi     # 0x5bc9c
leaq 0x534ba(%rip), %rsi     # 0x5b9ed
leaq 0x53710(%rip), %rcx     # 0x5bc4a
movl $0x38b, %edx            # imm = 0x38B
callq 0x6060