// File: /workspace/github_c_makefile_star2_O0/ToniWestbrook[P]paladin/bwtindex.c
// Function: command_index
int command_index(int argc, char *argv[]) {
	bwt_t *bwt;
	char * prefix, * proName, * pacName, * bwtName, * saName;
	gzFile fp;
	char c;
	int indexType, valid;
	IndexHeader indexHeader;
	clock_t t;

	// Parse arguments
	valid = 1;
	indexType = -1;
	memset(&indexHeader, 0, sizeof(indexHeader));

	while ((c = getopt(argc, argv, "fr:p:")) >= 0) {
		if (c == 'f') indexHeader.multiFrame = 1;
		if (c == 'p') indexHeader.referenceType = atoi(optarg);
		if (c == 'r') indexType = atoi(optarg);
		if (c == '?') valid = 0;
	}

	// Check for valid combinations
	if (valid) {
		valid = 0;
		if ((indexType == 1) && (argc - optind == 2)) valid = 1;
		if ((indexType == 2) && (argc - optind == 1)) valid = 1;
		if ((indexType == 3) && (argc - optind == 1)) valid = 1;
		if ((indexType == 4) && (argc - optind == 1)) valid = 1;
	}

	if (!valid) {
		fprintf(stderr, "\n");
		fprintf(stderr, "Usage: paladin index [options] <reference.fasta> [annotation.gff]\n\n");
		fprintf(stderr, "Options:\n\n");
		fprintf(stderr, "    -f     Enable indexing all frames in nucleotide references\n");
		fprintf(stderr, "    -r<#>  Reference type:\n");
		fprintf(stderr, "              1: Reference contains nucleotide sequences (requires corresponding .gff annotation)\n");
		fprintf(stderr, "              2: Reference contains nucleotide sequences (coding only, eg curated transcriptome)\n");
		fprintf(stderr, "              3: Reference contains protein sequences (UniProt or other source)\n");
		fprintf(stderr, "              4: Development tests\n\n");
		fprintf(stderr, "Examples:\n\n");
		fprintf(stderr, "   paladin index -r1 reference.fasta reference.gff\n");
		fprintf(stderr, "   paladin index -r3 uniprot_sprot.fasta.gz\n");
		fprintf(stderr, "\n");
		return 1;
	}    
   
	// Setup filenames
	prefix = malloc(strlen(argv[optind]) + 1);
	proName = malloc(strlen(argv[optind]) + 5);
	pacName = malloc(strlen(argv[optind]) + 5);
	bwtName = malloc(strlen(argv[optind]) + 5);
	saName = malloc(strlen(argv[optind]) + 5);

	sprintf(prefix, "%s", argv[optind]);
	sprintf(proName, "%s.pro", argv[optind]);
	sprintf(pacName, "%s.pac", argv[optind]);
	sprintf(bwtName, "%s.bwt", argv[optind]);
	sprintf(saName, "%s.sa", argv[optind]);

	// Create Protein Sequence
	t = clock();
	logMessage(__func__, LOG_LEVEL_MESSAGE, "Translating protein sequence...");

	switch (indexType) {
		case 1:
			// Nucleotide sequence and annotation
			writeIndexProtein(prefix, proName, argv[optind+1], indexHeader); break;
		case 2:
			// Nucleotide sequence, coding only
			writeIndexCodingProtein(prefix, proName, indexHeader); break;
		case 3:
			// Protein sequence
			writeIndexDirectProtein(prefix, proName, indexHeader);
			sprintf(proName, "%s", argv[optind]);
			break;
		case 4:
			// Testing
			writeIndexTestProtein(prefix, proName); break;
	}

	logMessageRaw(LOG_LEVEL_MESSAGE, "%.2f sec\n", (float)(clock() - t) / CLOCKS_PER_SEC);

	// Pack FASTA
	fp = xzopen(proName, "r");
	t = clock();
	logMessage(__func__, LOG_LEVEL_MESSAGE, "Packing protein sequence... ");
	bns_fasta2bntseq(fp, prefix, 0);
	logMessageRaw(LOG_LEVEL_MESSAGE, "%.2f sec\n", (float)(clock() - t) / CLOCKS_PER_SEC);
	err_gzclose(fp);

	// Construct BWT
	t = clock();
	logMessage(__func__, LOG_LEVEL_MESSAGE, "Constructing BWT for the packed sequence... ");
	bwt = bwt_pac2bwt(pacName);
	bwt_dump_bwt(bwtName, bwt);
	bwt_destroy(bwt);
	logMessageRaw(LOG_LEVEL_MESSAGE, "%.2f sec\n", (float)(clock() - t) / CLOCKS_PER_SEC);

	// Update BWT
	t = clock();
	logMessage(__func__, LOG_LEVEL_MESSAGE, "Updating BWT... ");
	bwt = bwt_restore_bwt(bwtName);
	bwt_bwtupdate_core(bwt);
	bwt_dump_bwt(bwtName, bwt);
	bwt_destroy(bwt);
	logMessageRaw(LOG_LEVEL_MESSAGE, "%.2f sec\n", (float)(clock() - t) / CLOCKS_PER_SEC);

	// Pack Forward-Only FASTA
	fp = xzopen(proName, "r");
	t = clock();
	logMessage(__func__, LOG_LEVEL_MESSAGE, "Packing forward-only protein squence... ");
	bns_fasta2bntseq(fp, prefix, 1);
	logMessageRaw(LOG_LEVEL_MESSAGE, "%.2f sec\n", (float)(clock() - t) / CLOCKS_PER_SEC);
	err_gzclose(fp);

	// Construct Suffix Array from FM-Index and Occurrences
	t = clock();
	logMessage(__func__, LOG_LEVEL_MESSAGE, "Constructing suffix array... ");
	bwt = bwt_restore_bwt(bwtName);
	bwt_cal_sa(bwt, 32);
	bwt_dump_sa(saName, bwt);
	bwt_destroy(bwt);
	logMessageRaw(LOG_LEVEL_MESSAGE, "%.2f sec\n", (float)(clock() - t) / CLOCKS_PER_SEC);

	free(prefix);
	free(proName);
	free(pacName);
	free(bwtName);
	free(saName);

	return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xc0, %rsp
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movl $0x1, -0x54(%rbp)
movl $0xffffffff, -0x50(%rbp) # imm = 0xFFFFFFFF
leaq -0x70(%rbp), %rdi
xorl %esi, %esi
movl $0x18, %edx
callq 0x3130
movl -0x8(%rbp), %edi
movq -0x10(%rbp), %rsi
leaq 0x31b26(%rip), %rdx     # 0x37194
callq 0x3090
movb %al, -0x49(%rbp)
movsbl %al, %eax
cmpl $0x0, %eax
jl 0x56d6
movsbl -0x49(%rbp), %eax
cmpl $0x66, %eax
jne 0x568e
movl $0x1, -0x6c(%rbp)
movsbl -0x49(%rbp), %eax
cmpl $0x70, %eax
jne 0x56a9
movq 0x3a922(%rip), %rax     # 0x3ffc0
movq (%rax), %rdi
callq 0x3590
movl %eax, -0x68(%rbp)
movsbl -0x49(%rbp), %eax
cmpl $0x72, %eax
jne 0x56c4
movq 0x3a907(%rip), %rax     # 0x3ffc0
movq (%rax), %rdi
callq 0x3590
movl %eax, -0x50(%rbp)
movsbl -0x49(%rbp), %eax
cmpl $0x3f, %eax
jne 0x56d4
movl $0x0, -0x54(%rbp)
jmp 0x5660
cmpl $0x0, -0x54(%rbp)
je 0x5761
movl $0x0, -0x54(%rbp)
cmpl $0x1, -0x50(%rbp)
jne 0x5705
movl -0x8(%rbp), %eax
movq 0x3a8e9(%rip), %rcx     # 0x3ffe0
subl (%rcx), %eax
cmpl $0x2, %eax
jne 0x5705
movl $0x1, -0x54(%rbp)
cmpl $0x2, -0x50(%rbp)
jne 0x5723
movl -0x8(%rbp), %eax
movq 0x3a8cb(%rip), %rcx     # 0x3ffe0
subl (%rcx), %eax
cmpl $0x1, %eax
jne 0x5723
movl $0x1, -0x54(%rbp)
cmpl $0x3, -0x50(%rbp)
jne 0x5741
movl -0x8(%rbp), %eax
movq 0x3a8ad(%rip), %rcx     # 0x3ffe0
subl (%rcx), %eax
cmpl $0x1, %eax
jne 0x5741
movl $0x1, -0x54(%rbp)
cmpl $0x4, -0x50(%rbp)
jne 0x575f
movl -0x8(%rbp), %eax
movq 0x3a88f(%rip), %rcx     # 0x3ffe0
subl (%rcx), %eax
cmpl $0x1, %eax
jne 0x575f
movl $0x1, -0x54(%rbp)
jmp 0x5761
cmpl $0x0, -0x54(%rbp)
jne 0x58af
movq 0x3a866(%rip), %rax     # 0x3ffd8
movq (%rax), %rdi
leaq 0x31e35(%rip), %rsi     # 0x375b1
movb $0x0, %al
callq 0x34e0
movq 0x3a84e(%rip), %rax     # 0x3ffd8
movq (%rax), %rdi
leaq 0x31a06(%rip), %rsi     # 0x3719a
movb $0x0, %al
callq 0x34e0
movq 0x3a836(%rip), %rax     # 0x3ffd8
movq (%rax), %rdi
leaq 0x31a32(%rip), %rsi     # 0x371de
movb $0x0, %al
callq 0x34e0
movq 0x3a81e(%rip), %rax     # 0x3ffd8
movq (%rax), %rdi
leaq 0x31a25(%rip), %rsi     # 0x371e9
movb $0x0, %al
callq 0x34e0
movq 0x3a806(%rip), %rax     # 0x3ffd8
movq (%rax), %rdi
leaq 0x31a4d(%rip), %rsi     # 0x37229
movb $0x0, %al
callq 0x34e0
movq 0x3a7ee(%rip), %rax     # 0x3ffd8
movq (%rax), %rdi
leaq 0x31a51(%rip), %rsi     # 0x37245
movb $0x0, %al
callq 0x34e0
movq 0x3a7d6(%rip), %rax     # 0x3ffd8
movq (%rax), %rdi
leaq 0x31a9c(%rip), %rsi     # 0x372a8
movb $0x0, %al
callq 0x34e0
movq 0x3a7be(%rip), %rax     # 0x3ffd8
movq (%rax), %rdi
leaq 0x31ae6(%rip), %rsi     # 0x3730a
movb $0x0, %al
callq 0x34e0
movq 0x3a7a6(%rip), %rax     # 0x3ffd8
movq (%rax), %rdi
leaq 0x31b1f(%rip), %rsi     # 0x3735b
movb $0x0, %al
callq 0x34e0
movq 0x3a78e(%rip), %rax     # 0x3ffd8
movq (%rax), %rdi
leaq 0x31b2c(%rip), %rsi     # 0x37380
movb $0x0, %al
callq 0x34e0
movq 0x3a776(%rip), %rax     # 0x3ffd8
movq (%rax), %rdi
leaq 0x31b20(%rip), %rsi     # 0x3738c
movb $0x0, %al
callq 0x34e0
movq 0x3a75e(%rip), %rax     # 0x3ffd8
movq (%rax), %rdi
leaq 0x31b3c(%rip), %rsi     # 0x373c0
movb $0x0, %al
callq 0x34e0
movq 0x3a746(%rip), %rax     # 0x3ffd8
movq (%rax), %rdi
leaq 0x31d15(%rip), %rsi     # 0x375b1
movb $0x0, %al
callq 0x34e0
movl $0x1, -0x4(%rbp)
jmp 0x5ec2
movq -0x10(%rbp), %rax
movq 0x3a726(%rip), %rcx     # 0x3ffe0
movq %rcx, -0x98(%rbp)
movslq (%rcx), %rcx
movq (%rax,%rcx,8), %rdi
callq 0x30f0
movq %rax, %rdi
incq %rdi
leaq 0x317fa(%rip), %rsi     # 0x370d4
movq %rsi, -0xa0(%rbp)
leaq 0x31b05(%rip), %rcx     # 0x373ed
movq %rcx, -0x90(%rbp)
movl $0x130, %edx            # imm = 0x130
callq 0x31ca0
movq -0x98(%rbp), %rcx
movq %rax, -0x20(%rbp)
movq -0x10(%rbp), %rax
movslq (%rcx), %rcx
movq (%rax,%rcx,8), %rdi
callq 0x30f0
movq -0xa0(%rbp), %rsi
movq -0x90(%rbp), %rcx
movq %rax, %rdi
addq $0x5, %rdi
movl $0x131, %edx            # imm = 0x131
callq 0x31ca0
movq -0x98(%rbp), %rcx
movq %rax, -0x28(%rbp)
movq -0x10(%rbp), %rax
movslq (%rcx), %rcx
movq (%rax,%rcx,8), %rdi
callq 0x30f0
movq -0xa0(%rbp), %rsi
movq -0x90(%rbp), %rcx
movq %rax, %rdi
addq $0x5, %rdi
movl $0x132, %edx            # imm = 0x132
callq 0x31ca0
movq -0x98(%rbp), %rcx
movq %rax, -0x30(%rbp)
movq -0x10(%rbp), %rax
movslq (%rcx), %rcx
movq (%rax,%rcx,8), %rdi
callq 0x30f0
movq -0xa0(%rbp), %rsi
movq -0x90(%rbp), %rcx
movq %rax, %rdi
addq $0x5, %rdi
movl $0x133, %edx            # imm = 0x133
callq 0x31ca0
movq -0x98(%rbp), %rcx
movq %rax, -0x38(%rbp)
movq -0x10(%rbp), %rax
movslq (%rcx), %rcx
movq (%rax,%rcx,8), %rdi
callq 0x30f0
movq -0xa0(%rbp), %rsi
movq -0x90(%rbp), %rcx
movq %rax, %rdi
addq $0x5, %rdi
movl $0x134, %edx            # imm = 0x134
callq 0x31ca0
movq -0x98(%rbp), %rcx
movq %rax, -0x40(%rbp)
movq -0x20(%rbp), %rdi
movq -0x10(%rbp), %rax
movslq (%rcx), %rcx
movq (%rax,%rcx,8), %rdx
leaq 0x34528(%rip), %rsi     # 0x39f2a
xorl %eax, %eax
movb %al, -0x81(%rbp)
callq 0x3070
movq -0x98(%rbp), %rdx
movb -0x81(%rbp), %al
movq -0x28(%rbp), %rdi
movq -0x10(%rbp), %rcx
movslq (%rdx), %rdx
movq (%rcx,%rdx,8), %rdx
leaq 0x319c9(%rip), %rsi     # 0x373fb
callq 0x3070
movq -0x98(%rbp), %rdx
movb -0x81(%rbp), %al
movq -0x30(%rbp), %rdi
movq -0x10(%rbp), %rcx
movslq (%rdx), %rdx
movq (%rcx,%rdx,8), %rdx
leaq 0x319a8(%rip), %rsi     # 0x37402
callq 0x3070
movq -0x98(%rbp), %rdx
movb -0x81(%rbp), %al
movq -0x38(%rbp), %rdi
movq -0x10(%rbp), %rcx
movslq (%rdx), %rdx
movq (%rcx,%rdx,8), %rdx
leaq 0x31987(%rip), %rsi     # 0x37409
callq 0x3070
movq -0x98(%rbp), %rdx
movb -0x81(%rbp), %al
movq -0x40(%rbp), %rdi
movq -0x10(%rbp), %rcx
movslq (%rdx), %rdx
movq (%rcx,%rdx,8), %rdx
leaq 0x31966(%rip), %rsi     # 0x37410
callq 0x3070
callq 0x31b0
movq -0x90(%rbp), %rdi
movq %rax, %rcx
movb -0x81(%rbp), %al
movq %rcx, -0x78(%rbp)
leaq 0x31947(%rip), %rdx     # 0x37416
movl $0x3, %esi
callq 0x12510
movl -0x50(%rbp), %eax
decl %eax
movl %eax, %ecx
movq %rcx, -0x80(%rbp)
subl $0x3, %eax
ja 0x5bd0
movq -0x80(%rbp), %rax
leaq 0x31528(%rip), %rcx     # 0x37020
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x20(%rbp), %rdi
movq -0x28(%rbp), %rsi
movq -0x10(%rbp), %rax
movq 0x3a4cc(%rip), %rcx     # 0x3ffe0
movl (%rcx), %ecx
addl $0x1, %ecx
movslq %ecx, %rcx
movq (%rax,%rcx,8), %rdx
leaq -0x70(%rbp), %rax
movq (%rax), %rcx
movq %rcx, (%rsp)
movq 0x8(%rax), %rcx
movq %rcx, 0x8(%rsp)
movq 0x10(%rax), %rax
movq %rax, 0x10(%rsp)
callq 0xb1e0
jmp 0x5bd0
movq -0x20(%rbp), %rdi
movq -0x28(%rbp), %rsi
leaq -0x70(%rbp), %rax
movq (%rax), %rcx
movq %rcx, (%rsp)
movq 0x8(%rax), %rcx
movq %rcx, 0x8(%rsp)
movq 0x10(%rax), %rax
movq %rax, 0x10(%rsp)
callq 0xb420
jmp 0x5bd0
movq -0x20(%rbp), %rdi
movq -0x28(%rbp), %rsi
leaq -0x70(%rbp), %rax
movq (%rax), %rcx
movq %rcx, (%rsp)
movq 0x8(%rax), %rcx
movq %rcx, 0x8(%rsp)
movq 0x10(%rax), %rax
movq %rax, 0x10(%rsp)
callq 0xb6b0
movq -0x28(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x3a434(%rip), %rcx     # 0x3ffe0
movslq (%rcx), %rcx
movq (%rax,%rcx,8), %rdx
leaq 0x34370(%rip), %rsi     # 0x39f2a
movb $0x0, %al
callq 0x3070
jmp 0x5bd0
movq -0x20(%rbp), %rdi
movq -0x28(%rbp), %rsi
callq 0xb730
callq 0x31b0
subq -0x78(%rbp), %rax
cvtsi2ss %rax, %xmm0
movss 0x31436(%rip), %xmm1    # 0x3701c
divss %xmm1, %xmm0
cvtss2sd %xmm0, %xmm0
movl $0x3, %edi
leaq 0x3183c(%rip), %rsi     # 0x37436
movb $0x1, %al
callq 0x12650
movq -0x28(%rbp), %rsi
leaq 0x317e1(%rip), %rdi     # 0x373ed
leaq 0x330ef(%rip), %rdx     # 0x38d02
callq 0x12990
movq %rax, -0x48(%rbp)
callq 0x31b0
movq %rax, -0x78(%rbp)
leaq 0x317c1(%rip), %rdi     # 0x373ed
movl $0x3, %esi
leaq 0x31808(%rip), %rdx     # 0x37440
movb $0x0, %al
callq 0x12510
movq -0x48(%rbp), %rdi
movq -0x20(%rbp), %rsi
xorl %edx, %edx
callq 0x17520
callq 0x31b0
subq -0x78(%rbp), %rax
cvtsi2ss %rax, %xmm0
movss 0x313b8(%rip), %xmm1    # 0x3701c
divss %xmm1, %xmm0
cvtss2sd %xmm0, %xmm0
movl $0x3, %edi
leaq 0x317be(%rip), %rsi     # 0x37436
movb $0x1, %al
callq 0x12650
movq -0x48(%rbp), %rdi
callq 0x13200
callq 0x31b0
movq %rax, -0x78(%rbp)
leaq 0x31755(%rip), %rdi     # 0x373ed
movl $0x3, %esi
leaq 0x317b9(%rip), %rdx     # 0x3745d
movb $0x0, %al
callq 0x12510
movq -0x30(%rbp), %rdi
callq 0x4f60
movq %rax, -0x18(%rbp)
movq -0x38(%rbp), %rdi
movq -0x18(%rbp), %rsi
callq 0x15a40
movq -0x18(%rbp), %rdi
callq 0x15f90
callq 0x31b0
subq -0x78(%rbp), %rax
cvtsi2ss %rax, %xmm0
movss 0x31338(%rip), %xmm1    # 0x3701c
divss %xmm1, %xmm0
cvtss2sd %xmm0, %xmm0
movl $0x3, %edi
leaq 0x3173e(%rip), %rsi     # 0x37436
movb $0x1, %al
callq 0x12650
callq 0x31b0
movq %rax, -0x78(%rbp)
leaq 0x316de(%rip), %rdi     # 0x373ed
movl $0x3, %esi
leaq 0x3176f(%rip), %rdx     # 0x3748a
movb $0x0, %al
callq 0x12510
movq -0x38(%rbp), %rdi
callq 0x15e40
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rdi
callq 0x5290
movq -0x38(%rbp), %rdi
movq -0x18(%rbp), %rsi
callq 0x15a40
movq -0x18(%rbp), %rdi
callq 0x15f90
callq 0x31b0
subq -0x78(%rbp), %rax
cvtsi2ss %rax, %xmm0
movss 0x312b8(%rip), %xmm1    # 0x3701c
divss %xmm1, %xmm0
cvtss2sd %xmm0, %xmm0
movl $0x3, %edi
leaq 0x316be(%rip), %rsi     # 0x37436
movb $0x1, %al
callq 0x12650
movq -0x28(%rbp), %rsi
leaq 0x31663(%rip), %rdi     # 0x373ed
leaq 0x32f71(%rip), %rdx     # 0x38d02
callq 0x12990
movq %rax, -0x48(%rbp)
callq 0x31b0
movq %rax, -0x78(%rbp)
leaq 0x31643(%rip), %rdi     # 0x373ed
movl $0x3, %esi
leaq 0x316e5(%rip), %rdx     # 0x3749b
movb $0x0, %al
callq 0x12510
movq -0x48(%rbp), %rdi
movq -0x20(%rbp), %rsi
movl $0x1, %edx
callq 0x17520
callq 0x31b0
subq -0x78(%rbp), %rax
cvtsi2ss %rax, %xmm0
movss 0x31237(%rip), %xmm1    # 0x3701c
divss %xmm1, %xmm0
cvtss2sd %xmm0, %xmm0
movl $0x3, %edi
leaq 0x3163d(%rip), %rsi     # 0x37436
movb $0x1, %al
callq 0x12650
movq -0x48(%rbp), %rdi
callq 0x13200
callq 0x31b0
movq %rax, -0x78(%rbp)
leaq 0x315d4(%rip), %rdi     # 0x373ed
movl $0x3, %esi
leaq 0x3169f(%rip), %rdx     # 0x374c4
movb $0x0, %al
callq 0x12510
movq -0x38(%rbp), %rdi
callq 0x15e40
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rdi
movl $0x20, %esi
callq 0x13d10
movq -0x40(%rbp), %rdi
movq -0x18(%rbp), %rsi
callq 0x15ae0
movq -0x18(%rbp), %rdi
callq 0x15f90
callq 0x31b0
subq -0x78(%rbp), %rax
cvtsi2ss %rax, %xmm0
movss 0x311a9(%rip), %xmm1    # 0x3701c
divss %xmm1, %xmm0
cvtss2sd %xmm0, %xmm0
movl $0x3, %edi
leaq 0x315af(%rip), %rsi     # 0x37436
movb $0x1, %al
callq 0x12650
movq -0x20(%rbp), %rdi
callq 0x3380
movq -0x28(%rbp), %rdi
callq 0x3380
movq -0x30(%rbp), %rdi
callq 0x3380
movq -0x38(%rbp), %rdi
callq 0x3380
movq -0x40(%rbp), %rdi
callq 0x3380
movl $0x0, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0xc0, %rsp
popq %rbp
retq
nop