// File: /workspace/github_c_makefile_star2_O1/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, %r12
movq %rsi, %r14
movq %rdi, %rbx
testb $0x1, 0x4c(%rdx)
je 0xa04e
cmpl $0x0, 0x54(%r12)
je 0xa04e
leaq 0x1d15d(%rip), %rdi     # 0x27192
leaq 0x1d168(%rip), %rdx     # 0x271a4
movl $0x2, %esi
xorl %eax, %eax
callq 0xdbeb
andb $-0x2, 0x48(%r12)
leaq 0x1d13d(%rip), %r15     # 0x27192
leaq 0x1cdc2(%rip), %rdx     # 0x26e1e
movq %r15, %rdi
movq %rbx, %rsi
callq 0xdf35
movq %rax, %r13
leaq 0x1f3be(%rip), %rdx     # 0x2942f
movq %r15, %rdi
movq %r14, %rsi
callq 0xdd8e
movq %rax, 0x18(%rsp)
testb $0x2, 0x4c(%r12)
jne 0xa094
movq $0x0, 0x8(%rsp)
jmp 0xa0f1
movq %rbx, %rdi
callq 0x3100
leaq 0x5(%rax), %rdi
leaq 0x1d02e(%rip), %rsi     # 0x270d5
leaq 0x1d0e4(%rip), %r14     # 0x27192
movl $0x224, %edx            # imm = 0x224
movq %r14, %rcx
callq 0x22d2b
movq %rax, %r15
leaq 0x1d11e(%rip), %rsi     # 0x271e3
movq %rax, %rdi
movq %rbx, %rdx
xorl %eax, %eax
callq 0x3070
leaq 0x1f356(%rip), %rdx     # 0x2942f
movq %r14, %rdi
movq %r15, %rsi
callq 0xdd8e
movq %rax, 0x8(%rsp)
movq %r15, %rdi
callq 0x3390
leaq 0x1d09a(%rip), %rdi     # 0x27192
leaq 0x1d0eb(%rip), %rdx     # 0x271ea
xorl %r15d, %r15d
movl $0x3, %esi
xorl %eax, %eax
callq 0xdbeb
movq %r13, 0x38(%rsp)
movq %r13, %rdi
callq 0xd53f
movq %rax, %r14
movq %rax, %rdi
callq 0xd61e
xorl %r13d, %r13d
testl %eax, %eax
js 0xa2a9
xorl %r15d, %r15d
movq %r12, 0x20(%rsp)
movq %r15, 0x10(%rsp)
movq 0x70(%r12), %rax
movl (%rax), %ebp
testl %ebp, %ebp
je 0xa291
movl $0x1, %eax
movq %rax, 0x40(%rsp)
movq %r13, 0x48(%rsp)
decl %ebp
movq 0x30(%r14), %rsi
movq 0x40(%r14), %rdi
movl %ebp, %edx
movq %r12, %rcx
leaq 0x30(%rsp), %r8
leaq 0x50(%rsp), %r9
callq 0x94d1
movq 0x50(%rsp), %rax
movq %rax, 0x28(%rsp)
testq %rax, %rax
je 0xa25d
movslq %ebp, %rax
movq 0x30(%rsp), %rbx
addq %rax, %rax
leaq (%rax,%rax,2), %r12
xorl %r15d, %r15d
movq 0x40(%r14), %rdi
movq %rbx, %rsi
movl %ebp, %r13d
movl %ebp, %edx
leaq 0x60(%rsp), %rcx
leaq 0x58(%rsp), %r8
callq 0x9002
movswq 0x14(%rbx), %r8
addq %r12, %r8
movq 0x10(%r14), %r9
movl 0x58(%rsp), %r10d
movq 0x60(%rsp), %rbp
movq 0x18(%rsp), %rdi
leaq 0x1d030(%rip), %rsi     # 0x2720c
movq 0x10(%rsp), %rdx
movq %r15, %rcx
xorl %eax, %eax
pushq %rbp
pushq %r10
callq 0x3500
addq $0x10, %rsp
movq %rbp, %rdi
callq 0x3390
movq 0x20(%rsp), %rax
testb $0x2, 0x4c(%rax)
je 0xa245
movswq 0x14(%rbx), %r8
addq %r12, %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 0x1cfde(%rip), %rsi     # 0x2720c
movq 0x10(%rsp), %rdx
movq %r15, %rcx
xorl %eax, %eax
pushq %r11
pushq %r10
callq 0x3500
addq $0x10, %rsp
incq %r15
addq $0x2018, %rbx           # imm = 0x2018
cmpq %r15, 0x28(%rsp)
movl %r13d, %ebp
jne 0xa19f
movq 0x30(%rsp), %rdi
callq 0x3390
movq 0x48(%rsp), %r13
addq 0x28(%rsp), %r13
movq 0x20(%rsp), %r12
movq 0x70(%r12), %rax
movq 0x40(%rsp), %rcx
movl (%rax,%rcx,4), %ebp
movq %rcx, %rax
incq %rax
testl %ebp, %ebp
jne 0xa152
movq 0x10(%rsp), %r15
incq %r15
movq %r14, %rdi
callq 0xd61e
testl %eax, %eax
jns 0xa139
movq 0x18(%rsp), %rbx
movq %rbx, %rdi
callq 0x3370
movq 0x38(%rsp), %rdi
callq 0xe4b9
movq %rbx, %rdi
callq 0xe490
movq %r14, %rdi
callq 0xd5c5
testb $0x2, 0x4c(%r12)
je 0xa2ed
movq 0x8(%rsp), %rbx
movq %rbx, %rdi
callq 0x3370
movq %rbx, %rdi
callq 0xe490
movabsq $-0x5555555555555555, %rcx # imm = 0xAAAAAAAAAAAAAAAB
movq %r13, %rax
mulq %rcx
shrq $0x2, %rdx
testb $0x1, 0x4c(%r12)
cmovneq %rdx, %r13
leaq 0x1ce80(%rip), %rdi     # 0x27192
leaq 0x1cf09(%rip), %rdx     # 0x27222
movl $0x3, %esi
movq %r13, %rcx
movq %r15, %r8
xorl %eax, %eax
callq 0xdbeb
xorl %eax, %eax
addq $0x68, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq