// File: /workspace/github_c_makefile_star2_O2/ToniWestbrook[P]paladin/protein.c
// Function: writeReadsProtein
int writeReadsProtein(const char * passPrefix, const char * passProName, mem_opt_t * passOptions) {
	CDS * orfList;
	gzFile inputSeqPtr;
	FILE * outputProPtr, * outputNTPtr;
	char * outputProBuffer, * outputNTName;
	kseq_t * seq;
	unsigned long seqIdx, transIdx, transTable, outputSize, orfCount, orfTotal, orfIdx;

	// Check for incompatible combinations
	if ((passOptions->proteinFlag & ALIGN_FLAG_BRUTE_ORF) && passOptions->indexInfo.multiFrame) {
		logMessage(__func__, LOG_LEVEL_WARNING, "Brute force ORF detection redundant to MF index, disabling...\n");
		passOptions->flag &= ~ALIGN_FLAG_BRUTE_ORF;
	}

	// Prepare file handles
	inputSeqPtr = xzopen(passPrefix, "r");
	outputProPtr = err_xopen_core(__func__, passProName, "w");
	outputNTPtr = 0;

	if (passOptions->proteinFlag & ALIGN_FLAG_GEN_NT) {
		outputNTName = malloc(strlen(passPrefix) + 5);
		sprintf(outputNTName, "%s.orf", passPrefix);
		outputNTPtr = err_xopen_core(__func__, outputNTName, "w");
		free(outputNTName);
	}

	logMessage(__func__, LOG_LEVEL_MESSAGE, "Detecting open reading frames...\n");

	// Iterate through each read
	orfTotal = 0;
	seqIdx = 0;
	seq = kseq_init(inputSeqPtr);

	while(kseq_read(seq) >= 0) {
        transIdx = 0;

        while((passOptions->translations)[transIdx++] != 0) {
            // Lookup current translation table
            transTable = (passOptions->translations)[transIdx - 1] - 1;

            // Search for ORFs
            getSequenceORF(seq->seq.s, seq->seq.l, transTable, passOptions, &orfList, &orfCount);

            // Write out the corresponding protein sequence for each ORF
            for (orfIdx = 0 ; orfIdx < orfCount ; orfIdx++) {
                convertToAA(seq->seq.s, orfList+orfIdx, transTable, &outputProBuffer, &outputSize);

                // Sequence ID : ORF Index per Sequence : Relative Frame per Sequence : Sequence Header
                fprintf(outputProPtr, ">%lu:%lu:%lu:%s\n%.*s\n", 
                        seqIdx, orfIdx, transTable * 6 + orfList[orfIdx].relFrame, seq->name.s, (int) outputSize, outputProBuffer);
                free(outputProBuffer);

                if (passOptions->proteinFlag & ALIGN_FLAG_GEN_NT) {
                    // Sequence ID : ORF Index per Sequence : Relative Frame per Sequence : Sequence Header
                    fprintf(outputNTPtr, ">%lu:%lu:%lu:%s\n%.*s\n", 
                            seqIdx, orfIdx, transTable * 6 + orfList[orfIdx].relFrame, seq->name.s, (int) (orfList[orfIdx].endIdx - orfList[orfIdx].startIdx + 1), seq->seq.s + orfList[orfIdx].startIdx);

                }
            }

            free(orfList);
            orfTotal += orfCount;
        }
        seqIdx++;
	}

	// Close files
	fflush(outputProPtr);
	err_gzclose(inputSeqPtr);
	err_fclose(outputProPtr);
	kseq_destroy(seq);

	if (passOptions->proteinFlag & ALIGN_FLAG_GEN_NT) {
		fflush(outputNTPtr);
		err_fclose(outputNTPtr);
	}

	if (passOptions->proteinFlag & ALIGN_FLAG_BRUTE_ORF) orfTotal /= 6;
	logMessage(__func__, LOG_LEVEL_MESSAGE, "Detected and translated %d open reading frames in %d sequences\n", orfTotal, seqIdx);

	return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x68, %rsp
movq %rdx, %rbp
movq %rsi, %r14
movq %rdi, %rbx
testb $0x1, 0x4c(%rdx)
je 0x8b9d
cmpl $0x0, 0x54(%rbp)
je 0x8b9d
leaq 0x19625(%rip), %rdi     # 0x221ad
leaq 0x19630(%rip), %rdx     # 0x221bf
pushq $0x2
popq %rsi
xorl %eax, %eax
callq 0xc78e
andb $-0x2, 0x48(%rbp)
leaq 0x19609(%rip), %r15     # 0x221ad
leaq 0x19273(%rip), %rdx     # 0x21e1e
movq %r15, %rdi
movq %rbx, %rsi
callq 0xcacc
movq %rax, 0x10(%rsp)
leaq 0x1b91d(%rip), %rdx     # 0x244df
movq %r15, %rdi
movq %r14, %rsi
callq 0xc931
movq %rax, 0x18(%rsp)
testb $0x2, 0x4c(%rbp)
jne 0x8be3
movq $0x0, 0x8(%rsp)
jmp 0x8c40
movq %rbx, %rdi
callq 0x3100
leaq 0x5(%rax), %rdi
leaq 0x194fa(%rip), %rsi     # 0x220f0
leaq 0x195b0(%rip), %r14     # 0x221ad
movl $0x224, %edx            # imm = 0x224
movq %r14, %rcx
callq 0x1e045
movq %rax, %r15
leaq 0x195ea(%rip), %rsi     # 0x221fe
movq %rax, %rdi
movq %rbx, %rdx
xorl %eax, %eax
callq 0x3070
leaq 0x1b8b7(%rip), %rdx     # 0x244df
movq %r14, %rdi
movq %r15, %rsi
callq 0xc931
movq %rax, 0x8(%rsp)
movq %r15, %rdi
callq 0x3390
leaq 0x19566(%rip), %rdi     # 0x221ad
leaq 0x195b7(%rip), %rdx     # 0x22205
pushq $0x3
popq %rsi
xorl %eax, %eax
callq 0xc78e
movq 0x10(%rsp), %rdi
callq 0xc1ce
movq %rax, %r14
movq $0x0, (%rsp)
xorl %r15d, %r15d
movq %r14, %rdi
callq 0xc2aa
testl %eax, %eax
js 0x8dcc
xorl %ecx, %ecx
movq 0x70(%rbp), %rax
movslq (%rax,%rcx,4), %r12
testq %r12, %r12
je 0x8dc3
movq %r15, 0x40(%rsp)
incq %rcx
movq %rcx, 0x38(%rsp)
decq %r12
movq 0x30(%r14), %rsi
movq 0x40(%r14), %rdi
movl %r12d, %edx
movq %rbp, %rcx
leaq 0x60(%rsp), %r8
leaq 0x48(%rsp), %r9
callq 0x8228
movq 0x48(%rsp), %rax
movq %rax, 0x20(%rsp)
movq 0x60(%rsp), %rbx
imulq $0x6, %r12, %rax
movq %rax, 0x28(%rsp)
movq %rbx, 0x30(%rsp)
xorl %r15d, %r15d
cmpq %r15, 0x20(%rsp)
je 0x8da5
movq 0x40(%r14), %rdi
movq %rbx, %rsi
movq %r12, %r13
movl %r12d, %edx
leaq 0x58(%rsp), %rcx
leaq 0x50(%rsp), %r8
callq 0x7f00
movswq 0x14(%rbx), %r8
addq 0x28(%rsp), %r8
movq 0x10(%r14), %r9
movl 0x50(%rsp), %r10d
movq %rbp, %r12
movq 0x58(%rsp), %rbp
movq 0x18(%rsp), %rdi
leaq 0x194f9(%rip), %rsi     # 0x22227
movq (%rsp), %rdx
movq %r15, %rcx
xorl %eax, %eax
pushq %rbp
pushq %r10
callq 0x3500
popq %rcx
popq %rdx
movq %rbp, %rdi
movq %r12, %rbp
callq 0x3390
testb $0x2, 0x4c(%r12)
je 0x8d93
movswq 0x14(%rbx), %r8
addq 0x28(%rsp), %r8
movq 0x10(%r14), %r9
movl 0x8(%rbx), %r10d
movq (%rbx), %r11
subl %r11d, %r10d
incl %r10d
addq 0x40(%r14), %r11
movq 0x8(%rsp), %rdi
leaq 0x194a8(%rip), %rsi     # 0x22227
movq (%rsp), %rdx
movq %r15, %rcx
xorl %eax, %eax
pushq %r11
pushq %r10
callq 0x3500
popq %rcx
popq %rdx
incq %r15
addq $0x2018, %rbx           # imm = 0x2018
movq %r13, %r12
jmp 0x8ce0
movq 0x30(%rsp), %rdi
callq 0x3390
movq 0x40(%rsp), %r15
addq 0x20(%rsp), %r15
movq 0x38(%rsp), %rcx
jmp 0x8c82
incq (%rsp)
jmp 0x8c70
movq 0x18(%rsp), %rbx
movq %rbx, %rdi
callq 0x3370
movq 0x10(%rsp), %rdi
callq 0xd044
movq %rbx, %rdi
callq 0xd01b
movq %r14, %rdi
callq 0xc251
movl 0x4c(%rbp), %ecx
testb $0x2, %cl
je 0x8e13
movq 0x8(%rsp), %rbx
movq %rbx, %rdi
callq 0x3370
movq %rbx, %rdi
callq 0xd01b
movl 0x4c(%rbp), %ecx
pushq $0x6
popq %rsi
movq %r15, %rax
xorl %edx, %edx
divq %rsi
testb $0x1, %cl
cmovneq %rax, %r15
leaq 0x19381(%rip), %rdi     # 0x221ad
leaq 0x1940a(%rip), %rdx     # 0x2223d
pushq $0x3
popq %rsi
movq %r15, %rcx
movq (%rsp), %r8
xorl %eax, %eax
callq 0xc78e
xorl %eax, %eax
addq $0x68, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nopl (%rax)