// File: /workspace/github_c_makefile_star2_O1/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 $0xb8, %rsp
movl %esi, 0xc(%rsp)
movq %rdi, 0x10(%rsp)
testl %ecx, %ecx
je 0x7b3f
movl %r9d, %r14d
movq %r8, %r13
movl %ecx, %ebx
movq %rdx, %r15
jle 0x7b46
movl %ebx, %eax
xorl %r12d, %r12d
cmpw $0x0, (%r15,%r12,2)
je 0x7b49
incq %r12
cmpq %r12, %rax
jne 0x7b2a
movl %eax, %r12d
jmp 0x7b49
xorl %eax, %eax
jmp 0x7e10
xorl %r12d, %r12d
leaq 0x18(%rsp), %rbp
movl $0x98, %edx
movq %rbp, %rdi
xorl %esi, %esi
callq 0x1110
movq %r13, (%rbp)
movl %r14d, 0xc(%rbp)
movq 0x10(%rsp), %rax
movq %rax, 0x18(%rbp)
movl 0xc(%rsp), %eax
movl %eax, 0x24(%rbp)
movq %r15, 0x10(%rbp)
movl %ebx, 0x20(%rbp)
movq 0x100(%rsp), %rax
movq %rax, 0x28(%rbp)
movq 0x108(%rsp), %rcx
movq %rcx, 0x30(%rbp)
testq %rax, %rax
setne %al
testq %rcx, %rcx
setne %cl
andb %al, %cl
movzbl %cl, %eax
movl %eax, 0x90(%rbp)
movl %r12d, %r14d
leaq 0x2(,%r14,2), %rdi
callq 0x1180
movq %rax, 0x38(%rbp)
testq %rax, %rax
je 0x7d8d
movq %rax, %rbx
movq %r14, 0xb0(%rsp)
incq %r14
leaq (%r14,%r14), %rdx
movq %rax, %rdi
movq %r15, %rsi
callq 0x1170
movl %r14d, %eax
movw $0x0, -0x2(%rbx,%rax,2)
movl %r12d, 0x5c(%rsp)
movl $0x0, 0x58(%rsp)
movq %r14, %rdi
callq 0x1180
movq %rax, 0x70(%rsp)
testq %rax, %rax
je 0x7da7
movq %rax, %rdi
xorl %esi, %esi
movq %r14, %rdx
callq 0x1110
movl %r12d, %eax
shrl %eax
cmpl $0x200, %r12d           # imm = 0x200
movl $0x100, %r15d           # imm = 0x100
cmovael %eax, %r15d
movl %r15d, 0x88(%rsp)
movl %r15d, 0x84(%rsp)
leal (%r15,%r15), %ebp
movq %rbp, %rdi
callq 0x1180
movq %rax, 0x78(%rsp)
testq %rax, %rax
je 0x7dc1
movq %rax, %rdi
xorl %esi, %esi
movq %rbp, %rdx
callq 0x1110
movq %r15, %rdi
callq 0x1180
movq %rax, 0x98(%rsp)
testq %rax, %rax
je 0x7dec
movq 0x110(%rsp), %rbp
movq %rax, %rdi
xorl %esi, %esi
movq %r15, %rdx
callq 0x1110
testq %rbp, %rbp
je 0x7ca9
movl (%rbp), %eax
movl %eax, 0xa0(%rsp)
cmpl $0x0, 0xa8(%rsp)
je 0x7d3d
leaq (,%r14,4), %r15
movq %r15, %rdi
callq 0x1180
movq %rax, 0x68(%rsp)
testq %rax, %rax
je 0x7e94
movl %r14d, %ecx
xorl %edx, %edx
movl %edx, (%rax,%rdx,4)
incq %rdx
cmpq %rdx, %rcx
jne 0x7cda
movq %r15, %rdi
callq 0x1180
movq %rax, 0x60(%rsp)
testq %rax, %rax
je 0x7ec7
movl %r14d, %ecx
xorl %edx, %edx
movl %edx, (%rax,%rdx,4)
incq %rdx
cmpq %rdx, %rcx
jne 0x7d00
movslq 0x84(%rsp), %r14
shlq $0x2, %r14
movq %r14, %rdi
callq 0x1180
movq %rax, 0x90(%rsp)
testq %rax, %rax
je 0x7f04
movq %rax, %rdi
xorl %esi, %esi
movq %r14, %rdx
callq 0x1110
movl 0xf8(%rsp), %eax
movq 0xf0(%rsp), %r14
cmpl $-0x1, %eax
je 0x7e22
cmpl $0x1, %eax
jne 0x806d
movslq 0x24(%rsp), %rax
movq -0x8(%r13,%rax,8), %rax
movl 0x18(%rax), %eax
cmpl $0x1, %eax
je 0x7f4b
xorl %ebx, %ebx
testl %eax, %eax
jne 0x7f57
leaq 0x18(%rsp), %rdi
callq 0xb38c
jmp 0x7f55
leaq 0xb460(%rip), %rsi      # 0x131f4
leaq 0xbc37(%rip), %rdx      # 0x139d2
movl $0x7, %edi
movl $0x1aa, %ecx            # imm = 0x1AA
jmp 0x7e04
leaq 0xb446(%rip), %rsi      # 0x131f4
leaq 0xbc1d(%rip), %rdx      # 0x139d2
movl $0x7, %edi
movl $0x1b4, %ecx            # imm = 0x1B4
jmp 0x7e04
leaq 0xb42c(%rip), %rsi      # 0x131f4
leaq 0xbc03(%rip), %rdx      # 0x139d2
movl $0x7, %edi
movl $0x1c1, %ecx            # imm = 0x1C1
xorl %eax, %eax
callq 0xa36c
movq 0x50(%rsp), %rdi
callq 0x1040
jmp 0x7e0b
leaq 0xb401(%rip), %rsi      # 0x131f4
leaq 0xbbd8(%rip), %rdx      # 0x139d2
movl $0x7, %edi
movl $0x1ca, %ecx            # imm = 0x1CA
xorl %eax, %eax
callq 0xa36c
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
addq $0xb8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
testq %r14, %r14
je 0x7e69
movslq 0x5c(%rsp), %rax
testq %rax, %rax
jle 0x7e69
xorl %ecx, %ecx
movzwl (%rbx,%rcx,2), %esi
xorl %edx, %edx
cmpw %si, 0x10(%r14,%rdx,2)
je 0x7e57
incq %rdx
cmpq $0x100, %rdx            # imm = 0x100
jne 0x7e39
movzwl 0x210(%r14), %edx
jmp 0x7e5d
addl $0x2800, %edx           # imm = 0x2800
movw %dx, (%rbx,%rcx,2)
incq %rcx
cmpq %rax, %rcx
jne 0x7e33
movslq 0x24(%rsp), %rax
movq -0x8(%r13,%rax,8), %rax
xorl %ebx, %ebx
cmpl $0x0, 0x18(%rax)
jne 0x7e87
leaq 0x18(%rsp), %rdi
callq 0xe4f8
movl %eax, %ebx
testl %ebx, %ebx
jg 0x7f71
jmp 0x7fef
leaq 0xb359(%rip), %rsi      # 0x131f4
leaq 0xbb30(%rip), %rdx      # 0x139d2
movl $0x7, %edi
movl $0x1dc, %ecx            # imm = 0x1DC
xorl %eax, %eax
callq 0xa36c
movq 0x50(%rsp), %rdi
callq 0x1040
movq 0x78(%rsp), %rdi
jmp 0x7de5
leaq 0xb326(%rip), %rsi      # 0x131f4
leaq 0xbafd(%rip), %rdx      # 0x139d2
movl $0x7, %edi
movl $0x1e7, %ecx            # imm = 0x1E7
xorl %eax, %eax
callq 0xa36c
movq 0x50(%rsp), %rdi
callq 0x1040
movq 0x78(%rsp), %rdi
callq 0x1040
movq 0x68(%rsp), %rdi
jmp 0x7de5
leaq 0xb2e9(%rip), %rsi      # 0x131f4
leaq 0xbac0(%rip), %rdx      # 0x139d2
movl $0x7, %edi
movl $0x1f5, %ecx            # imm = 0x1F5
xorl %eax, %eax
callq 0xa36c
movq 0x50(%rsp), %rdi
callq 0x1040
movq 0x78(%rsp), %rdi
callq 0x1040
movq 0x68(%rsp), %rdi
callq 0x1040
movq 0x60(%rsp), %rdi
jmp 0x7de5
leaq 0x18(%rsp), %rdi
callq 0xf6dc
movl %eax, %ebx
testl %ebx, %ebx
jle 0x7fef
testq %r14, %r14
je 0x7f71
leaq 0x18(%rsp), %rdi
movq %r14, %rsi
callq 0x8072
movslq 0x80(%rsp), %rbx
movq 0x78(%rsp), %rsi
cmpl 0x3c(%rsp), %ebx
jle 0x7f89
movslq 0xc(%rsp), %rbx
leaq (%rbx,%rbx), %rdx
movq 0x10(%rsp), %rdi
callq 0x1170
movq 0x108(%rsp), %rdi
testq %rdi, %rdi
movq 0x100(%rsp), %r14
je 0x7fc0
movq 0x90(%rsp), %rsi
shlq $0x2, %rbx
movq %rbx, %rdx
callq 0x1170
testq %r14, %r14
je 0x7fde
movq 0x60(%rsp), %rsi
movq 0xb0(%rsp), %rdx
shlq $0x2, %rdx
movq %r14, %rdi
callq 0x1170
testq %rbp, %rbp
je 0x800b
movl 0xa0(%rsp), %eax
movl %eax, (%rbp)
jmp 0x800b
jne 0x8004
leaq 0xb9ed(%rip), %rsi      # 0x139e5
movl $0x5, %edi
xorl %eax, %eax
callq 0xa36c
movl %ebx, 0x80(%rsp)
movq 0x50(%rsp), %rdi
callq 0x1040
movq 0x78(%rsp), %rdi
callq 0x1040
movq 0x70(%rsp), %rdi
callq 0x1040
movq 0x98(%rsp), %rdi
callq 0x1040
cmpl $0x0, 0xa8(%rsp)
je 0x8061
movq 0x68(%rsp), %rdi
callq 0x1040
movq 0x60(%rsp), %rdi
callq 0x1040
movq 0x90(%rsp), %rdi
callq 0x1040
movl 0x80(%rsp), %eax
jmp 0x7e10
callq 0x1060