// File: /workspace/github_c_makefile_star2_O3/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
cmpl %ecx, %edi
sete %dl
orb %sil, %dl
cmpb $0x1, %dl
movl %ecx, 0xc(%rsp)
jne 0x8378
cmpl $0x2, %eax
setae %al
leal (%rbp,%r13), %esi
cmpl $0x6, %esi
setge %dl
testb %dl, %al
jne 0x8386
jmp 0x84f9
cmpl $-0x1, %edi
je 0x84cf
leal (%rbp,%r13), %esi
movl %esi, 0x1c(%rsp)
movq %rbp, 0x10(%rsp)
movq %r13, 0x20(%rsp)
movl $0x1b, %esi
movl %edi, %ebp
movq %r15, %rdi
callq *%r12
movl $0x25, %esi
movq %r15, %rdi
callq *%r12
movl $0x2f, %esi
movq %r15, %rdi
callq *%r12
movl %ebp, %eax
leaq (%rax,%rax,2), %r13
leaq 0x9f4fc(%rip), %rbp     # 0xa78c0
movsbq 0x8(%rbp,%r13,8), %rsi
addq $0x30, %rsi
movq %r15, %rdi
callq *%r12
movq (%rbp,%r13,8), %r13
movq %r13, %rdi
callq 0x6040
movq %rax, %rbp
addl 0x1c(%rsp), %ebp
cmpl $0x4000, %ebp           # imm = 0x4000
jge 0x8623
movl %ebp, %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, %ebp
movl $0xff, %eax
andl %eax, %ebp
movq %r15, %rdi
movq %rbp, %rsi
callq *%r12
movb (%r13), %al
testb %al, %al
je 0x8444
incq %r13
movsbq %al, %rsi
movq %r15, %rdi
callq *%r12
movb (%r13), %al
incq %r13
testb %al, %al
jne 0x842f
cmpl $0x0, 0x10(%rsp)
je 0x8491
movq 0x10(%rsp), %rax
leal (,%rax,8), %ebp
movl $0x20, %r13d
cmpq $0x20, %r13
jne 0x846a
movzbl 0x8(%r14), %eax
jmp 0x8473
movq (%r14), %rax
movl %r13d, %ecx
shrq %cl, %rax
movzbl %al, %esi
movq %r15, %rdi
callq *%r12
leaq -0x8(,%r13), %rax
addq %rbp, %rax
addq $-0x8, %r13
cmpq $0x20, %rax
jne 0x845d
movl $0xfffffffe, %edi       # imm = 0xFFFFFFFE
movq 0x20(%rsp), %rax
testl %eax, %eax
jle 0x84c1
movl %eax, %r13d
xorl %ebp, %ebp
movsbq (%rbx,%rbp), %rsi
movq %r15, %rdi
callq *%r12
incq %rbp
cmpq %rbp, %r13
jne 0x84a4
xorl %r13d, %r13d
movq 0x10(%rsp), %rbp
jmp 0x84f0
xorl %r13d, %r13d
movq 0x10(%rsp), %rbp
movl 0xc(%rsp), %ecx
jmp 0x84f9
movl $0x1b, %esi
movq %r15, %rdi
callq *%r12
movl $0x25, %esi
movq %r15, %rdi
callq *%r12
movl $0x40, %esi
movq %r15, %rdi
callq *%r12
movl 0xc(%rsp), %ecx
movl $0xfffffffe, %edi       # imm = 0xFFFFFFFE
cmpl %ecx, %edi
je 0x856c
cmpl $-0x1, %ecx
je 0x8547
cmpl $-0x2, %ecx
je 0x8680
movq $0x0, (%r14)
movq $-0x1f900, %rdx         # imm = 0xFFFE0700
andq 0x8(%r14), %rdx
movq %rdx, 0x8(%r14)
xorl %ebp, %ebp
cmpl $0x6, %ecx
jb 0x8577
leaq 0x54778(%rip), %rdi     # 0x5cca7
leaq 0x544b7(%rip), %rsi     # 0x5c9ed
leaq 0x5470d(%rip), %rcx     # 0x5cc4a
movl $0x39f, %edx            # imm = 0x39F
callq 0x6060
movl $0x1b, %esi
movq %r15, %rdi
callq *%r12
movl $0x25, %esi
movq %r15, %rdi
callq *%r12
movl $0x47, %esi
movq %r15, %rdi
callq *%r12
movl 0xc(%rsp), %ecx
movq $-0x1c001, %rdx         # imm = 0xFFFE3FFF
andq 0x8(%r14), %rdx
movl %ecx, %eax
shll $0xe, %eax
addl $0x8000, %eax           # imm = 0x8000
orq %rdx, %rax
movq %rax, 0x8(%r14)
testl %r13d, %r13d
jle 0x8614
cmpl $-0x1, %ecx
je 0x85fb
cmpl $0x2, %ecx
je 0x8642
leal (%rbp,%r13), %edx
cmpl $0x5, %edx
jg 0x8661
movl %ebp, %esi
movl %r13d, %edi
shll $0x3, %ebp
movl $0x20, %ecx
subl %ebp, %ecx
negq %rsi
xorl %r8d, %r8d
movzbl (%rbx,%r8), %r9d
cmpq %r8, %rsi
jne 0x85d5
orq %r9, %rax
movq %rax, 0x8(%r14)
jmp 0x85de
shll %cl, %r9d
movslq %r9d, %r9
orq %r9, (%r14)
incq %r8
addl $-0x8, %ecx
cmpq %r8, %rdi
jne 0x85c2
andq $-0x3801, %rax          # imm = 0xC7FF
shll $0xb, %edx
orq %rax, %rdx
movq %rdx, 0x8(%r14)
jmp 0x8614
movl %r13d, %r14d
xorl %r13d, %r13d
movsbq (%rbx,%r13), %rsi
movq %r15, %rdi
callq *%r12
incq %r13
cmpq %r13, %r14
jne 0x8601
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x54610(%rip), %rdi     # 0x5cc3a
leaq 0x543bc(%rip), %rsi     # 0x5c9ed
leaq 0x54612(%rip), %rcx     # 0x5cc4a
movl $0x372, %edx            # imm = 0x372
callq 0x6060
leaq 0x5467c(%rip), %rdi     # 0x5ccc5
leaq 0x5439d(%rip), %rsi     # 0x5c9ed
leaq 0x545f3(%rip), %rcx     # 0x5cc4a
movl $0x3a7, %edx            # imm = 0x3A7
callq 0x6060
leaq 0x54667(%rip), %rdi     # 0x5cccf
leaq 0x5437e(%rip), %rsi     # 0x5c9ed
leaq 0x545d4(%rip), %rcx     # 0x5cc4a
movl $0x3b4, %edx            # imm = 0x3B4
callq 0x6060
leaq 0x54615(%rip), %rdi     # 0x5cc9c
leaq 0x5435f(%rip), %rsi     # 0x5c9ed
leaq 0x545b5(%rip), %rcx     # 0x5cc4a
movl $0x38b, %edx            # imm = 0x38B
callq 0x6060