// File: /workspace/github_c_makefile_star2_O3/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 0xa256
cmpl $0x0, 0x54(%r12)
je 0xa256
leaq 0x1cfc0(%rip), %rdi     # 0x271fd
leaq 0x1cfcb(%rip), %rdx     # 0x2720f
movl $0x2, %esi
xorl %eax, %eax
callq 0xde80
andb $-0x2, 0x48(%r12)
leaq 0x1cfa0(%rip), %r15     # 0x271fd
leaq 0x1cc06(%rip), %rdx     # 0x26e6a
movq %r15, %rdi
movq %rbx, %rsi
callq 0xe1c4
movq %rax, %r13
leaq 0x1f2e6(%rip), %rdx     # 0x2955f
movq %r15, %rdi
movq %r14, %rsi
callq 0xe023
movq %rax, 0x18(%rsp)
testb $0x2, 0x4c(%r12)
jne 0xa29b
movq $0x0, (%rsp)
jmp 0xa2f7
movq %rbx, %rdi
callq 0x3100
leaq 0x5(%rax), %rdi
leaq 0x1ce92(%rip), %rsi     # 0x27140
leaq 0x1cf48(%rip), %r14     # 0x271fd
movl $0x224, %edx            # imm = 0x224
movq %r14, %rcx
callq 0x23213
movq %rax, %r15
leaq 0x1cf82(%rip), %rsi     # 0x2724e
movq %rax, %rdi
movq %rbx, %rdx
xorl %eax, %eax
callq 0x3070
leaq 0x1f27f(%rip), %rdx     # 0x2955f
movq %r14, %rdi
movq %r15, %rsi
callq 0xe023
movq %rax, (%rsp)
movq %r15, %rdi
callq 0x3390
leaq 0x1ceff(%rip), %rdi     # 0x271fd
leaq 0x1cf50(%rip), %rdx     # 0x27255
xorl %r15d, %r15d
movl $0x3, %esi
xorl %eax, %eax
callq 0xde80
movq %r13, 0x30(%rsp)
movq %r13, %rdi
callq 0xd7c8
movq %rax, %r14
movq %rax, %rdi
callq 0xd8a7
xorl %r13d, %r13d
testl %eax, %eax
js 0xa4b8
xorl %r15d, %r15d
movq %r12, 0x20(%rsp)
movq %r15, 0x8(%rsp)
movq 0x70(%r12), %rax
movl (%rax), %ebp
testl %ebp, %ebp
je 0xa4a0
movl $0x1, %eax
movq %rax, 0x38(%rsp)
movq %r13, 0x40(%rsp)
decl %ebp
movq 0x30(%r14), %rsi
movq 0x40(%r14), %rdi
movl %ebp, %edx
movq %r12, %rcx
leaq 0x60(%rsp), %r8
leaq 0x48(%rsp), %r9
callq 0x974a
movq 0x48(%rsp), %rax
movq 0x60(%rsp), %rcx
movq %rcx, 0x10(%rsp)
movq %rax, 0x28(%rsp)
testq %rax, %rax
je 0xa46c
movslq %ebp, %rax
addq %rax, %rax
leaq (%rax,%rax,2), %r13
movq 0x10(%rsp), %rbx
xorl %r15d, %r15d
movq 0x40(%r14), %rdi
movq %rbx, %rsi
movl %ebp, %r12d
movl %ebp, %edx
leaq 0x58(%rsp), %rcx
leaq 0x50(%rsp), %r8
callq 0x91ea
movswq 0x14(%rbx), %r8
addq %r13, %r8
movq 0x10(%r14), %r9
movl 0x50(%rsp), %r10d
movq 0x58(%rsp), %rbp
movq 0x18(%rsp), %rdi
leaq 0x1ce8b(%rip), %rsi     # 0x27277
movq 0x8(%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 0xa454
movswq 0x14(%rbx), %r8
addq %r13, %r8
movq 0x10(%r14), %r9
movl 0x8(%rbx), %r10d
movq (%rbx), %r11
subl %r11d, %r10d
incl %r10d
addq 0x40(%r14), %r11
movq (%rsp), %rdi
leaq 0x1ce3a(%rip), %rsi     # 0x27277
movq 0x8(%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 %r12d, %ebp
jne 0xa3af
movq 0x10(%rsp), %rdi
callq 0x3390
movq 0x40(%rsp), %r13
addq 0x28(%rsp), %r13
movq 0x20(%rsp), %r12
movq 0x70(%r12), %rax
movq 0x38(%rsp), %rcx
movl (%rax,%rcx,4), %ebp
movq %rcx, %rax
incq %rax
testl %ebp, %ebp
jne 0xa358
movq 0x8(%rsp), %r15
incq %r15
movq %r14, %rdi
callq 0xd8a7
testl %eax, %eax
jns 0xa33f
movq 0x18(%rsp), %rbx
movq %rbx, %rdi
callq 0x3370
movq 0x30(%rsp), %rdi
callq 0xe747
movq %rbx, %rdi
callq 0xe71e
movq %r14, %rdi
callq 0xd84e
movl 0x4c(%r12), %ecx
testb $0x2, %cl
je 0xa502
movq (%rsp), %rbx
movq %rbx, %rdi
callq 0x3370
movq %rbx, %rdi
callq 0xe71e
movl 0x4c(%r12), %ecx
movabsq $-0x5555555555555555, %rdx # imm = 0xAAAAAAAAAAAAAAAB
movq %r13, %rax
mulq %rdx
shrq $0x2, %rdx
testb $0x1, %cl
cmovneq %rdx, %r13
leaq 0x1ccd9(%rip), %rdi     # 0x271fd
leaq 0x1cd62(%rip), %rdx     # 0x2728d
movl $0x3, %esi
movq %r13, %rcx
movq %r15, %r8
xorl %eax, %eax
callq 0xde80
xorl %eax, %eax
addq $0x68, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nop