// File: /workspace/github_c_makefile_star2_O3/MikeGray-APH[P]LibLouisAPH/source/translate.c
// Function: translate_start
int translate_start(unichar *dots,
                    const int dots_len,
                    const unichar *chars,
                    const int chars_len,
                    const struct table *const*tables,
                    const int table_cnt,
                    const struct conversion *conversion,
                    const enum rule_direction direction,
                    int *chars_to_dots_map,
                    int *dots_to_chars_map,
                    int *cursor)
{
	struct translate translate_auto;
	int input_len, i, status;

	/*   nothing to translate   */
	if(chars_len == 0)
		return 0;

	/*   get true chars_len   */
	for(input_len = 0; input_len < chars_len; input_len++)
	if(!chars[input_len])
		break;

	memset(&translate_auto, 0, sizeof(struct translate));

	translate_auto.tables = tables;
	translate_auto.table_cnt = table_cnt;
	translate_auto.dots = dots;
	translate_auto.dots_len = dots_len;
	translate_auto.chars = chars;
	translate_auto.chars_len = chars_len;
	translate_auto.chars_to_dots_map = chars_to_dots_map;
	translate_auto.dots_to_chars_map = dots_to_chars_map;

	if(chars_to_dots_map == NULL || dots_to_chars_map == NULL)
		translate_auto.maps_use = 0;
	else
		translate_auto.maps_use = 1;

	/*   initialize input/output   */

	translate_auto.input = MALLOC((input_len + 1) * sizeof(unichar));
	if(!translate_auto.input)
	{
		LOG_ALLOCATE_FAIL
		return -1;
	}
	utf16_copy(translate_auto.input, chars, (input_len + 1));
	translate_auto.input_len = input_len;
	translate_auto.input_crs = 0;

	translate_auto.input_mask = MALLOC(input_len + 1);
	if(!translate_auto.input_mask)
	{
		LOG_ALLOCATE_FAIL
		return -1;
	}
	memset(translate_auto.input_mask, 0, input_len + 1);

	translate_auto.output_max = input_len;
	translate_auto.output_inc = ((translate_auto.output_max * 3) / 2) - translate_auto.output_max;
	if(translate_auto.output_inc < 0x100)
		translate_auto.output_inc = 0x100;
	translate_auto.output_max += translate_auto.output_inc - input_len;
	translate_auto.output = MALLOC(translate_auto.output_max * sizeof(unichar));
	if(!translate_auto.output)
	{
		LOG_ALLOCATE_FAIL
		FREE(translate_auto.input);
		return -1;
	}
	DB_MEMSET(translate_auto.output, 0, translate_auto.output_max * sizeof(unichar));

	translate_auto.output_mask = MALLOC(translate_auto.output_max);
	if(!translate_auto.output_mask)
	{
		LOG_ALLOCATE_FAIL
		return -1;
	}
	memset(translate_auto.output_mask, 0, translate_auto.output_max);

	if(cursor)
		translate_auto.cursor_pos = *cursor;

#ifndef CHECK_FOR_CHANGE
	utf16_copy(translate_auto.output, chars, (input_len + 1));
	translate_auto.output_len = input_len;
#endif

	if(translate_auto.maps_use)
	{
		translate_auto.input_map = MALLOC((input_len + 1) * sizeof(int));
		if(!translate_auto.input_map)
		{
			LOG_ALLOCATE_FAIL
			FREE(translate_auto.input);
			FREE(translate_auto.output);
			return -1;
		}
		for(i = 0; i <= input_len; i++)
			translate_auto.input_map[i] = i;

		translate_auto.input_to_output_map = MALLOC((input_len + 1) * sizeof(int));
		if(!translate_auto.input_to_output_map)
		{
			LOG_ALLOCATE_FAIL
			FREE(translate_auto.input);
			FREE(translate_auto.output);
			FREE(translate_auto.input_map);
			return -1;
		}

		/*   prevent input block mappings   */
		for(i = 0; i <= input_len; i++)
			translate_auto.input_to_output_map[i] = i;

		translate_auto.output_to_input_map = MALLOC(translate_auto.output_max * sizeof(int));
		if(!translate_auto.output_to_input_map)
		{
			LOG_ALLOCATE_FAIL
			FREE(translate_auto.input);
			FREE(translate_auto.output);
			FREE(translate_auto.input_map);
			FREE(translate_auto.input_to_output_map);
			return -1;
		}
		DB_MEMSET(translate_auto.output_to_input_map, 0, translate_auto.output_max * sizeof(int));

#ifndef CHECK_FOR_CHANGE
		ASSERT(translate_auto.output_max >= input_len + 1)
		memcpy(translate_auto.output_to_input_map, translate_auto.input_map, (input_len + 1) * sizeof(int));
#endif
	}

	/*   start processing   */
	if(direction == FORWARD)
	{
		/*   only process from last table in tables   */
		switch(translate_auto.tables[translate_auto.table_cnt - 1]->process)
		{
		case PROCESS_GENERIC:     status = translate_generic_forward(&translate_auto);  break;
		case PROCESS_NEMETH_UEB:  status = translate_nemeth_forward(&translate_auto);   break;
		default:                  status = 0;
		}
		if(status < 1)
		{
			if(status == 0)
				log_message(LOG_WARNING, "no processing done");
			translate_auto.output_len = status;
			goto free_and_return;
		}

		if(conversion)
			convert_output(&translate_auto, conversion);
	}
	else
	{
		ASSERT(direction == BACKWARD)

		if(conversion)
			convert_input(&translate_auto, conversion);

		/*   only process from last table in tables   */
		switch(translate_auto.tables[translate_auto.table_cnt - 1]->process)
		{
		case PROCESS_GENERIC:  status = translate_generic_backward(&translate_auto);  break;
		default:               status = 0;
		}
		if(status < 1)
		{
			if(status == 0)
				log_message(LOG_WARNING, "no processing done");
			translate_auto.output_len = status;
			goto free_and_return;
		}
	}

	/*   copy input/output   */

	if(translate_auto.output_len > translate_auto.dots_len)
	{
		//log_message(LOG_WARNING, "output exceeded dots_len:  %d > %d", translate_auto.output_len, translate_auto.dots_len);
		memcpy(dots, translate_auto.output, dots_len * sizeof(unichar));
		if(dots_to_chars_map)
			memcpy(dots_to_chars_map, translate_auto.output_to_input_map, dots_len * sizeof(int));
	}
	else
	{
		memcpy(dots, translate_auto.output, translate_auto.output_len * sizeof(unichar));
		if(dots_to_chars_map)
			memcpy(dots_to_chars_map, translate_auto.output_to_input_map, translate_auto.output_len * sizeof(int));
	}
	if(chars_to_dots_map)
		memcpy(chars_to_dots_map, translate_auto.input_to_output_map, input_len * sizeof(int));
	if(cursor)
		*cursor = translate_auto.cursor_pos;

	/*   finalize input/output   */

	free_and_return:

	FREE(translate_auto.input);
	FREE(translate_auto.output);
	FREE(translate_auto.input_mask);
	FREE(translate_auto.output_mask);
	if(translate_auto.maps_use)
	{
		FREE(translate_auto.input_map);
		FREE(translate_auto.input_to_output_map);
		FREE(translate_auto.output_to_input_map);
	}

	return translate_auto.output_len;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xe8, %rsp
movl %r9d, 0xc(%rsp)
movq %r8, 0x28(%rsp)
movl %esi, 0x1c(%rsp)
movq %rdi, 0x20(%rsp)
testl %ecx, %ecx
je 0x7944
movl %ecx, %ebp
movq %rdx, %rbx
movq 0x138(%rsp), %r13
movq 0x130(%rsp), %r14
jle 0x794b
movl %ebp, %eax
xorl %r12d, %r12d
cmpw $0x0, (%rbx,%r12,2)
je 0x794e
incq %r12
cmpq %r12, %rax
jne 0x792f
movl %eax, %r12d
jmp 0x794e
xorl %eax, %eax
jmp 0x7d17
xorl %r12d, %r12d
leaq 0x40(%rsp), %r15
movl $0x90, %edx
movq %r15, %rdi
xorl %esi, %esi
callq 0x1110
movq 0x28(%rsp), %rax
movq %rax, -0x8(%r15)
movl 0xc(%rsp), %eax
movl %eax, 0x4(%r15)
movq 0x20(%rsp), %rax
movq %rax, 0x10(%r15)
movl 0x1c(%rsp), %eax
movl %eax, 0x1c(%r15)
movq %rbx, 0x8(%r15)
movl %ebp, 0x18(%r15)
movq %r14, 0x20(%r15)
movq %r13, 0x28(%r15)
testq %r14, %r14
setne %al
testq %r13, %r13
setne %bpl
andb %al, %bpl
movzbl %bpl, %eax
movl %eax, 0x88(%r15)
movl %r12d, %r14d
leaq 0x2(,%r14,2), %r13
movq %r13, %rdi
callq 0x1190
movq %rax, 0x30(%r15)
testq %rax, %rax
je 0x7c94
movq %r14, 0x30(%rsp)
leaq 0x1(%r14), %r15
movq %rax, %r14
movq %rax, %rdi
movq %rbx, %rsi
movq %r13, %rdx
callq 0x1180
movq %r14, 0x10(%rsp)
movw $0x0, -0x2(%r14,%r15,2)
movl %r12d, 0x7c(%rsp)
movl $0x0, 0x78(%rsp)
movl $0x1, %edi
movq %r15, %rsi
callq 0x1150
movq %rax, 0x90(%rsp)
testq %rax, %rax
je 0x7cae
movl %r12d, %eax
shrl %eax
cmpl $0x200, %r12d           # imm = 0x200
movl $0x100, %r13d           # imm = 0x100
cmovael %eax, %r13d
movl %r13d, 0xa8(%rsp)
movl %r13d, 0xa4(%rsp)
leal (,%r13,2), %esi
movl $0x1, %edi
callq 0x1150
movq %rax, 0x98(%rsp)
testq %rax, %rax
je 0x7cc8
movq %rax, %r14
movl $0x1, %edi
movq %r13, %rsi
callq 0x1150
movq %rax, 0xb8(%rsp)
testq %rax, %rax
je 0x7cf3
movq 0x140(%rsp), %rdi
testq %rdi, %rdi
je 0x7aa1
movl (%rdi), %eax
movl %eax, 0xc0(%rsp)
testb %bpl, %bpl
je 0x7c29
leaq (,%r15,4), %rbx
movq %rbx, %rdi
callq 0x1190
movq %rax, 0x88(%rsp)
testq %rax, %rax
je 0x7dbd
movq %rax, %rbp
movabsq $0x1fffffffe, %rax      # imm = 0x1FFFFFFFE
incq %r15
andq %rax, %r15
movd %r12d, %xmm0
pshufd $0x44, %xmm0, %xmm5     # xmm5 = xmm0[0,1,0,1]
movdqa 0xbf80(%rip), %xmm0     # 0x13a70
xorl %eax, %eax
movdqa 0xbf86(%rip), %xmm6     # 0x13a80
pxor %xmm6, %xmm5
pcmpeqd %xmm1, %xmm1
movdqa %xmm0, %xmm2
pxor %xmm6, %xmm2
movdqa %xmm2, %xmm3
pcmpgtd %xmm5, %xmm3
pcmpeqd %xmm5, %xmm2
pshufd $0xf5, %xmm2, %xmm4     # xmm4 = xmm2[1,1,3,3]
pand %xmm3, %xmm4
pshufd $0xf5, %xmm3, %xmm2     # xmm2 = xmm3[1,1,3,3]
por %xmm4, %xmm2
movd %xmm2, %ecx
notl %ecx
testb $0x1, %cl
je 0x7b37
movl %eax, (%rbp,%rax,4)
pxor %xmm1, %xmm2
pextrw $0x4, %xmm2, %ecx
testb $0x1, %cl
je 0x7b4c
leal 0x1(%rax), %ecx
movl %ecx, 0x4(%rbp,%rax,4)
addq $0x2, %rax
paddq 0xbf38(%rip), %xmm0     # 0x13a90
cmpq %rax, %r15
jne 0x7b02
movdqa %xmm5, 0xd0(%rsp)
movq %rbx, %rdi
callq 0x1190
movq %rax, 0x80(%rsp)
testq %rax, %rax
je 0x7dee
movq %rax, %rbx
movdqa 0xbee6(%rip), %xmm0     # 0x13a70
xorl %eax, %eax
pcmpeqd %xmm1, %xmm1
movdqa 0xd0(%rsp), %xmm5
movdqa 0xbedf(%rip), %xmm6     # 0x13a80
movdqa 0xbee7(%rip), %xmm7     # 0x13a90
movdqa %xmm0, %xmm2
pxor %xmm6, %xmm2
movdqa %xmm2, %xmm3
pcmpgtd %xmm5, %xmm3
pcmpeqd %xmm5, %xmm2
pshufd $0xf5, %xmm2, %xmm4     # xmm4 = xmm2[1,1,3,3]
pand %xmm3, %xmm4
pshufd $0xf5, %xmm3, %xmm2     # xmm2 = xmm3[1,1,3,3]
por %xmm4, %xmm2
movd %xmm2, %ecx
notl %ecx
testb $0x1, %cl
je 0x7bdd
movl %eax, (%rbx,%rax,4)
pxor %xmm1, %xmm2
pextrw $0x4, %xmm2, %ecx
testb $0x1, %cl
je 0x7bf2
leal 0x1(%rax), %ecx
movl %ecx, 0x4(%rbx,%rax,4)
addq $0x2, %rax
paddq %xmm7, %xmm0
cmpq %rax, %r15
jne 0x7ba9
shlq $0x2, %r13
movl $0x1, %edi
movq %r13, %rsi
callq 0x1150
movq %rax, 0xb0(%rsp)
testq %rax, %rax
movq 0x140(%rsp), %rdi
je 0x7f99
movl 0x128(%rsp), %eax
movq 0x120(%rsp), %r15
cmpl $-0x1, %eax
je 0x7d29
cmpl $0x1, %eax
movq 0x138(%rsp), %r12
movq 0x30(%rsp), %r13
jne 0x7fda
movq %rdi, %rbp
movslq 0xc(%rsp), %rax
movq 0x28(%rsp), %rcx
movq -0x8(%rcx,%rax,8), %rax
movl 0x18(%rax), %eax
cmpl $0x1, %eax
movq 0x130(%rsp), %r14
je 0x7e47
testl %eax, %eax
jne 0x7d9c
leaq 0x38(%rsp), %rdi
callq 0xb2ac
jmp 0x7e51
leaq 0xb5a1(%rip), %rsi      # 0x1323c
leaq 0xbdfe(%rip), %rdx      # 0x13aa0
movl $0x7, %edi
movl $0x1aa, %ecx            # imm = 0x1AA
jmp 0x7d0b
leaq 0xb587(%rip), %rsi      # 0x1323c
leaq 0xbde4(%rip), %rdx      # 0x13aa0
movl $0x7, %edi
movl $0x1b4, %ecx            # imm = 0x1B4
jmp 0x7d0b
leaq 0xb56d(%rip), %rsi      # 0x1323c
leaq 0xbdca(%rip), %rdx      # 0x13aa0
movl $0x7, %edi
movl $0x1c1, %ecx            # imm = 0x1C1
xorl %eax, %eax
callq 0xa278
movq 0x10(%rsp), %rdi
callq 0x1040
jmp 0x7d12
leaq 0xb542(%rip), %rsi      # 0x1323c
leaq 0xbd9f(%rip), %rdx      # 0x13aa0
movl $0x7, %edi
movl $0x1ca, %ecx            # imm = 0x1CA
xorl %eax, %eax
callq 0xa278
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
addq $0xe8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
testq %r15, %r15
sete %al
testl %r12d, %r12d
setle %cl
orb %al, %cl
movq 0x138(%rsp), %r12
movq 0x30(%rsp), %r13
movq 0x10(%rsp), %rsi
jne 0x7d83
xorl %eax, %eax
movzwl (%rsi,%rax,2), %edx
xorl %ecx, %ecx
cmpw %dx, 0x10(%r15,%rcx,2)
je 0x7d71
incq %rcx
cmpq $0x100, %rcx            # imm = 0x100
jne 0x7d53
movzwl 0x210(%r15), %ecx
jmp 0x7d77
addl $0x2800, %ecx           # imm = 0x2800
movw %cx, (%rsi,%rax,2)
incq %rax
cmpq %r13, %rax
jne 0x7d4d
movslq 0xc(%rsp), %rax
movq 0x28(%rsp), %rcx
movq -0x8(%rcx,%rax,8), %rax
cmpl $0x0, 0x18(%rax)
je 0x7e27
leaq 0xbd10(%rip), %rsi      # 0x13ab3
xorl %ebx, %ebx
movl $0x5, %edi
xorl %eax, %eax
callq 0xa278
movl %ebx, 0xa0(%rsp)
jmp 0x7f20
leaq 0xb478(%rip), %rsi      # 0x1323c
leaq 0xbcd5(%rip), %rdx      # 0x13aa0
movl $0x7, %edi
movl $0x1dc, %ecx            # imm = 0x1DC
xorl %eax, %eax
callq 0xa278
movq 0x10(%rsp), %rdi
callq 0x1040
movq %r14, %rdi
jmp 0x7cec
leaq 0xb447(%rip), %rsi      # 0x1323c
leaq 0xbca4(%rip), %rdx      # 0x13aa0
movl $0x7, %edi
movl $0x1e7, %ecx            # imm = 0x1E7
xorl %eax, %eax
callq 0xa278
movq 0x10(%rsp), %rdi
callq 0x1040
movq %r14, %rdi
callq 0x1040
movq %rbp, %rdi
jmp 0x7cec
movq %rdi, %rbp
leaq 0x38(%rsp), %rdi
callq 0xe378
testl %eax, %eax
movq 0x130(%rsp), %r14
jg 0x7eb0
movl %eax, %ebx
jmp 0x7f8e
leaq 0x38(%rsp), %rdi
callq 0xf598
movl %eax, %ebx
testl %eax, %eax
jle 0x7f8e
testq %r15, %r15
je 0x7eb0
movslq 0xa0(%rsp), %rax
testq %rax, %rax
jle 0x7eb0
movq 0x98(%rsp), %rcx
xorl %edx, %edx
movzwl (%rcx,%rdx,2), %esi
movl %esi, %edi
andl $0xff00, %edi           # imm = 0xFF00
cmpl $0x2800, %edi           # imm = 0x2800
jne 0x7e97
movzbl %sil, %esi
movzwl 0x10(%r15,%rsi,2), %esi
jmp 0x7ea4
movzwl 0x210(%r15), %esi
testw %si, %si
je 0x7ea8
movw %si, (%rcx,%rdx,2)
incq %rdx
cmpq %rdx, %rax
jne 0x7e77
movslq 0xa0(%rsp), %rbx
movq 0x98(%rsp), %rsi
cmpl 0x5c(%rsp), %ebx
jle 0x7ecb
movslq 0x1c(%rsp), %rbx
leaq (%rbx,%rbx), %rdx
movq 0x20(%rsp), %rdi
callq 0x1180
testq %r12, %r12
je 0x7ef5
movq 0xb0(%rsp), %rsi
shlq $0x2, %rbx
movq %r12, %rdi
movq %rbx, %rdx
callq 0x1180
testq %r14, %r14
je 0x7f11
movq 0x80(%rsp), %rsi
shlq $0x2, %r13
movq %r14, %rdi
movq %r13, %rdx
callq 0x1180
testq %rbp, %rbp
je 0x7f20
movl 0xc0(%rsp), %eax
movl %eax, (%rbp)
movq 0x70(%rsp), %rdi
callq 0x1040
movq 0x98(%rsp), %rdi
callq 0x1040
movq 0x90(%rsp), %rdi
callq 0x1040
movq 0xb8(%rsp), %rdi
callq 0x1040
cmpl $0x0, 0xc8(%rsp)
je 0x7f82
movq 0x88(%rsp), %rdi
callq 0x1040
movq 0x80(%rsp), %rdi
callq 0x1040
movq 0xb0(%rsp), %rdi
callq 0x1040
movl 0xa0(%rsp), %eax
jmp 0x7d17
jne 0x7db1
jmp 0x7d9c
leaq 0xb29c(%rip), %rsi      # 0x1323c
leaq 0xbaf9(%rip), %rdx      # 0x13aa0
movl $0x7, %edi
movl $0x1f5, %ecx            # imm = 0x1F5
xorl %eax, %eax
callq 0xa278
movq 0x10(%rsp), %rdi
callq 0x1040
movq %r14, %rdi
callq 0x1040
movq %rbp, %rdi
callq 0x1040
movq %rbx, %rdi
jmp 0x7cec
callq 0x1060
nop