// File: /workspace/github_c_makefile_star2_O2/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 $0xc8, %rsp
movl %r9d, 0x8(%rsp)
movq %r8, 0x20(%rsp)
movl %esi, 0xc(%rsp)
movq %rdi, 0x18(%rsp)
testl %ecx, %ecx
je 0x6e99
movl %ecx, %ebp
movq %rdx, %r15
movq 0x118(%rsp), %r14
movq 0x110(%rsp), %rbx
xorl %eax, %eax
testl %ecx, %ecx
movl $0x0, %r13d
cmovgl %ecx, %r13d
cmpq %rax, %r13
je 0x6ea3
cmpw $0x0, (%r15,%rax,2)
je 0x6ea0
incq %rax
jmp 0x6e87
xorl %eax, %eax
jmp 0x70aa
movl %eax, %r13d
leaq 0x38(%rsp), %r12
movl $0x90, %edx
movq %r12, %rdi
xorl %esi, %esi
callq 0x1110
movq 0x20(%rsp), %rax
movq %rax, -0x8(%r12)
movl 0x8(%rsp), %eax
movl %eax, 0x4(%r12)
movq 0x18(%rsp), %rax
movq %rax, 0x10(%r12)
movl 0xc(%rsp), %eax
movl %eax, 0x1c(%r12)
movq %r15, 0x8(%r12)
movl %ebp, 0x18(%r12)
movq %rbx, 0x20(%r12)
movq %r14, 0x28(%r12)
testq %rbx, %rbx
setne %al
testq %r14, %r14
setne %bl
andb %al, %bl
movzbl %bl, %eax
movl %eax, 0x88(%r12)
movl %r13d, %ebp
leaq 0x2(,%rbp,2), %rdi
callq 0x1190
movq %rax, 0x30(%r12)
testq %rax, %rax
je 0x7033
movq %rax, %r14
movq %rbp, 0x28(%rsp)
incq %rbp
xorl %eax, %eax
cmpq %rax, %rbp
je 0x6f49
movzwl (%r15,%rax,2), %ecx
movw %cx, (%r14,%rax,2)
incq %rax
jmp 0x6f35
andw $0x0, -0x2(%r14,%rbp,2)
movl %r13d, 0x74(%rsp)
andl $0x0, 0x70(%rsp)
pushq $0x1
popq %rdi
movq %rbp, %rsi
callq 0x1150
movq %rax, 0x88(%rsp)
testq %rax, %rax
je 0x704b
movl %r13d, %eax
shrl %eax
cmpl $0x200, %r13d           # imm = 0x200
movl $0x100, %r15d           # imm = 0x100
cmovael %eax, %r15d
movl %r15d, 0xa0(%rsp)
movl %r15d, 0x9c(%rsp)
leal (%r15,%r15), %esi
pushq $0x1
popq %rdi
callq 0x1150
movq %rax, 0x90(%rsp)
testq %rax, %rax
je 0x7063
movq %rax, %r12
pushq $0x1
popq %rdi
movq %r15, %rsi
callq 0x1150
movq %rax, 0xb0(%rsp)
testq %rax, %rax
je 0x708a
movq %r12, 0x10(%rsp)
movq 0x120(%rsp), %rax
testq %rax, %rax
je 0x6ff3
movl (%rax), %eax
movl %eax, 0xb8(%rsp)
testb %bl, %bl
je 0x7104
leaq (,%rbp,4), %rbx
movq %rbx, %rdi
callq 0x1190
movq %rax, 0x80(%rsp)
testq %rax, %rax
je 0x71e8
movq %rax, %r12
xorl %eax, %eax
cmpq %rax, %rbp
je 0x70bc
movl %eax, (%r12,%rax,4)
incq %rax
jmp 0x7021
leaq 0xa202(%rip), %rsi      # 0x1123c
leaq 0xa9cf(%rip), %rdx      # 0x11a10
pushq $0x7
popq %rdi
movl $0x1aa, %ecx            # imm = 0x1AA
jmp 0x70a0
leaq 0xa1ea(%rip), %rsi      # 0x1123c
leaq 0xa9b7(%rip), %rdx      # 0x11a10
pushq $0x7
popq %rdi
movl $0x1b4, %ecx            # imm = 0x1B4
jmp 0x70a0
leaq 0xa1d2(%rip), %rsi      # 0x1123c
leaq 0xa99f(%rip), %rdx      # 0x11a10
pushq $0x7
popq %rdi
movl $0x1c1, %ecx            # imm = 0x1C1
xorl %eax, %eax
callq 0x9174
movq %r14, %rdi
callq 0x1040
jmp 0x70a7
leaq 0xa1ab(%rip), %rsi      # 0x1123c
leaq 0xa978(%rip), %rdx      # 0x11a10
pushq $0x7
popq %rdi
movl $0x1ca, %ecx            # imm = 0x1CA
xorl %eax, %eax
callq 0x9174
pushq $-0x1
popq %rax
addq $0xc8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rbx, %rdi
callq 0x1190
movq %rax, 0x78(%rsp)
testq %rax, %rax
je 0x7217
movq %rax, %rbx
xorl %eax, %eax
cmpq %rax, %rbp
je 0x70e4
movl %eax, (%rbx,%rax,4)
incq %rax
jmp 0x70d7
shlq $0x2, %r15
pushq $0x1
popq %rdi
movq %r15, %rsi
callq 0x1150
movq %rax, 0xa8(%rsp)
testq %rax, %rax
je 0x73df
movl 0x108(%rsp), %eax
cmpl $-0x1, %eax
je 0x715b
cmpl $0x1, %eax
movq 0x100(%rsp), %rbx
jne 0x741e
movslq 0x8(%rsp), %rax
movq 0x20(%rsp), %rcx
movq -0x8(%rcx,%rax,8), %rax
movl 0x18(%rax), %eax
cmpl $0x1, %eax
movq 0x118(%rsp), %r14
je 0x7271
testl %eax, %eax
jne 0x735a
leaq 0x30(%rsp), %rdi
callq 0x9fe0
jmp 0x727b
movq 0x100(%rsp), %rsi
testq %rsi, %rsi
movq 0x28(%rsp), %r15
je 0x71b0
xorl %eax, %eax
testl %r13d, %r13d
cmovlel %eax, %r13d
cmpq %r13, %rax
je 0x71b0
movzwl (%r14,%rax,2), %edx
xorl %ecx, %ecx
cmpq $0x100, %rcx            # imm = 0x100
je 0x7197
cmpw %dx, 0x10(%rsi,%rcx,2)
je 0x71a0
incq %rcx
jmp 0x7182
movzwl 0x210(%rsi), %ecx
jmp 0x71a6
addl $0x2800, %ecx           # imm = 0x2800
movw %cx, (%r14,%rax,2)
incq %rax
jmp 0x7176
movslq 0x8(%rsp), %rax
movq 0x20(%rsp), %rcx
movq -0x8(%rcx,%rax,8), %rax
cmpl $0x0, 0x18(%rax)
je 0x724e
leaq 0xa853(%rip), %rsi      # 0x11a23
xorl %ebx, %ebx
pushq $0x5
popq %rdi
xorl %eax, %eax
callq 0x9174
movl %ebx, 0x98(%rsp)
jmp 0x7374
leaq 0xa04d(%rip), %rsi      # 0x1123c
leaq 0xa81a(%rip), %rdx      # 0x11a10
pushq $0x7
popq %rdi
movl $0x1dc, %ecx            # imm = 0x1DC
xorl %eax, %eax
callq 0x9174
movq %r14, %rdi
callq 0x1040
movq 0x10(%rsp), %rdi
jmp 0x7083
leaq 0xa01e(%rip), %rsi      # 0x1123c
leaq 0xa7eb(%rip), %rdx      # 0x11a10
pushq $0x7
popq %rdi
movl $0x1e7, %ecx            # imm = 0x1E7
xorl %eax, %eax
callq 0x9174
movq %r14, %rdi
callq 0x1040
movq 0x10(%rsp), %rdi
callq 0x1040
movq %r12, %rdi
jmp 0x7083
leaq 0x30(%rsp), %rdi
callq 0xcd54
testl %eax, %eax
movq 0x118(%rsp), %r14
jg 0x72dd
movl %eax, %ebx
jne 0x71dc
jmp 0x71c9
leaq 0x30(%rsp), %rdi
callq 0xdd20
movl %eax, %ebp
testl %eax, %eax
jle 0x7358
testq %rbx, %rbx
movq 0x28(%rsp), %r15
je 0x72dd
movl 0x98(%rsp), %eax
movq 0x90(%rsp), %rcx
xorl %edx, %edx
testl %eax, %eax
cmovlel %edx, %eax
cmpq %rdx, %rax
je 0x72dd
movzwl (%rcx,%rdx,2), %esi
movl %esi, %edi
andl $0xff00, %edi           # imm = 0xFF00
cmpw $0x2800, %di            # imm = 0x2800
jne 0x72c8
movzbl %sil, %esi
movzwl 0x10(%rbx,%rsi,2), %esi
jmp 0x72d4
movzwl 0x210(%rbx), %esi
testw %si, %si
je 0x72d8
movw %si, (%rcx,%rdx,2)
incq %rdx
jmp 0x72a5
movslq 0x98(%rsp), %rbx
movq 0x90(%rsp), %rsi
cmpl 0x54(%rsp), %ebx
jle 0x72f8
movslq 0xc(%rsp), %rbx
leaq (%rbx,%rbx), %rdx
movq 0x18(%rsp), %rdi
callq 0x1180
testq %r14, %r14
je 0x7322
movq 0xa8(%rsp), %rsi
shlq $0x2, %rbx
movq %r14, %rdi
movq %rbx, %rdx
callq 0x1180
movq 0x110(%rsp), %rdi
testq %rdi, %rdi
je 0x7340
movq 0x78(%rsp), %rsi
shlq $0x2, %r15
movq %r15, %rdx
callq 0x1180
movq 0x120(%rsp), %rcx
testq %rcx, %rcx
je 0x7374
movl 0xb8(%rsp), %eax
movl %eax, (%rcx)
jmp 0x7374
jne 0x736d
leaq 0xa6c2(%rip), %rsi      # 0x11a23
xorl %ebp, %ebp
pushq $0x5
popq %rdi
xorl %eax, %eax
callq 0x9174
movl %ebp, 0x98(%rsp)
movq 0x68(%rsp), %rdi
callq 0x1040
movq 0x90(%rsp), %rdi
callq 0x1040
movq 0x88(%rsp), %rdi
callq 0x1040
movq 0xb0(%rsp), %rdi
callq 0x1040
cmpl $0x0, 0xc0(%rsp)
je 0x73d3
movq 0x80(%rsp), %rdi
callq 0x1040
movq 0x78(%rsp), %rdi
callq 0x1040
movq 0xa8(%rsp), %rdi
callq 0x1040
movl 0x98(%rsp), %eax
jmp 0x70aa
leaq 0x9e56(%rip), %rsi      # 0x1123c
leaq 0xa623(%rip), %rdx      # 0x11a10
pushq $0x7
popq %rdi
movl $0x1f5, %ecx            # imm = 0x1F5
xorl %eax, %eax
callq 0x9174
movq %r14, %rdi
callq 0x1040
movq 0x10(%rsp), %rdi
callq 0x1040
movq %r12, %rdi
callq 0x1040
movq %rbx, %rdi
jmp 0x7083
callq 0x1060
nop