// File: /workspace/github_c_makefile_star2_O1/genometools[P]genometools/src/ltr/ltrdigest_pdom_visitor.c
// Function: gt_ltrdigest_pdom_visitor_feature_node
static int gt_ltrdigest_pdom_visitor_feature_node(GtNodeVisitor *nv,
                                                  GtFeatureNode *fn,
                                                  GtError *err)
{
  GtLTRdigestPdomVisitor *lv;
  GtFeatureNodeIterator *fni;
  GtFeatureNode *curnode = NULL;
  int had_err = 0;
  GtRange rng;
  GtUword i;
  lv = gt_ltrdigest_pdom_visitor_cast(nv);
  gt_assert(lv);
  gt_error_check(err);

  /* traverse annotation subgraph and find LTR element */
  fni = gt_feature_node_iterator_new(fn);
  while (!had_err && (curnode = gt_feature_node_iterator_next(fni))) {
    if (strcmp(gt_feature_node_get_type(curnode), lv->root_type) == 0) {
      lv->ltr_retrotrans = curnode;
    }
  }
  gt_feature_node_iterator_delete(fni);

  if (!had_err && lv->ltr_retrotrans != NULL) {
    GtCodonIterator *ci;
    GtTranslator *tr;
    GtTranslatorStatus status;
    GtUword seqlen;
    char translated, *rev_seq;
#ifndef _WIN32
    int pid, pc[2], cp[2];
#endif
    unsigned int frame;
    GtStr *seq;

    seq = gt_str_new();
    rng = gt_genome_node_get_range((GtGenomeNode*) lv->ltr_retrotrans);
    lv->leftLTR_5 = rng.start - 1;
    lv->rightLTR_3 = rng.end - 1;
    seqlen = gt_range_length(&rng);

    had_err = gt_extract_feature_sequence(seq,
                                          (GtGenomeNode*) lv->ltr_retrotrans,
                                          lv->root_type,
                                          false, NULL, NULL, lv->rmap, err);

    if (!had_err) {
      if (gt_str_length(seq) >= (GtUword) (3*GT_CODON_LENGTH)) {
        for (i = 0UL; i < 3UL; i++) {
          gt_str_reset(lv->fwd[i]);
          gt_str_reset(lv->rev[i]);
        }

        /* create translations */
        ci = gt_codon_iterator_simple_new(gt_str_get(seq), seqlen, NULL);
        gt_assert(ci);
        tr = gt_translator_new(ci);
        status = gt_translator_next(tr, &translated, &frame, err);
        while (status == GT_TRANSLATOR_OK && translated) {
          gt_str_append_char(lv->fwd[frame], translated);
          status = gt_translator_next(tr, &translated, &frame, NULL);
        }
        if (status == GT_TRANSLATOR_ERROR)
          had_err = -1;
        if (!had_err) {
          rev_seq = gt_malloc((size_t) seqlen * sizeof (char));
          strncpy(rev_seq, gt_str_get(seq), (size_t) seqlen * sizeof (char));
          (void) gt_reverse_complement(rev_seq, seqlen, NULL);
          gt_codon_iterator_delete(ci);
          ci = gt_codon_iterator_simple_new(rev_seq, seqlen, NULL);
          gt_translator_set_codon_iterator(tr, ci);
          status = gt_translator_next(tr, &translated, &frame, err);
          while (status == GT_TRANSLATOR_OK && translated) {
            gt_str_append_char(lv->rev[frame], translated);
            status = gt_translator_next(tr, &translated, &frame, NULL);
          }
          if (status == GT_TRANSLATOR_ERROR)
            had_err = -1;
          gt_free(rev_seq);
        }
        gt_codon_iterator_delete(ci);
        gt_translator_delete(tr);

        /* run HMMER and handle results */
        if (!had_err) {
    #ifndef _WIN32
          had_err = gt_ltrdigest_checkpipe(pc, err);
        }
        if (!had_err) {
          had_err = gt_ltrdigest_checkpipe(cp,err);
        }
        if (!had_err) {
          GtLTRdigestHMMscanThreadData td = {
                pc, cp, 0,
                lv, err
              };
          switch ((pid = (int) fork())) {
            case -1:
              gt_error_set(err, "can't fork new HMMER process");
              had_err = -1;
              break;
            case 0:    /* child */
              (void) close(1);    /* close current stdout. */
              gt_ltrdigest_checkdup(cp[1]);  /* make stdout go to
                                                    write end of pipe. */
              (void) close(0);    /* close current stdin. */
              gt_ltrdigest_checkdup(pc[0]);  /* make stdin come from
                                                    read end of pipe. */
              (void) close(pc[0]);
              (void) close(pc[1]);
              (void) close(cp[0]);
              (void) close(cp[1]);
              (void) execvp("hmmscan", lv->args); /* XXX: read path from env */
              perror("couldn't execute hmmscan");
              exit(EXIT_FAILURE);
            default:    /* parent */
            {
              GtThread *st, *rt;
              st = gt_thread_new(gt_ltrdigest_hmmscan_send_thread, &td, err);
              rt = gt_thread_new(gt_ltrdigest_hmmscan_recv_thread, &td, err);
              gt_thread_join(rt);
              gt_thread_join(st);
              gt_thread_delete(rt);
              gt_thread_delete(st);
              had_err = td.had_err;
            }
          }
    #else
          /* XXX */
          gt_error_set(err, "HMMER call not implemented on Windows\n");
          had_err = -1;
    #endif
        }
      } else {
        gt_warning("%s (%s, line %u) is too short to be "
                  "translated (" GT_WU " nt), skipped domain search",
              gt_feature_node_get_type(lv->ltr_retrotrans),
              gt_genome_node_get_filename((GtGenomeNode*) lv->ltr_retrotrans),
              gt_genome_node_get_line_number((GtGenomeNode*)
                                                            lv->ltr_retrotrans),
              gt_str_length(seq));
      }
      gt_str_delete(seq);
      if (!had_err)
        had_err = gt_ltrdigest_pdom_visitor_choose_strand(lv);
    }
  }
  return had_err;
}

void gt_ltrdigest_pdom_visitor_free(GtNodeVisitor *nv)
{
  GtLTRdigestPdomVisitor *lv;
  GtUword i;
  if (!nv) return;
  lv = gt_ltrdigest_pdom_visitor_cast(nv);
  for (i = 0UL; i < 3UL; i++) {
    gt_str_delete(lv->fwd[i]);
    gt_str_delete(lv->rev[i]);
  }
  gt_str_delete(lv->cmdline);
  gt_str_delete(lv->tag);
  gt_cstr_array_delete(lv->args);
}

const GtNodeVisitorClass* gt_ltrdigest_pdom_visitor_class(void)
{
  static const GtNodeVisitorClass *nvc = NULL;
  if (!nvc) {
    nvc = gt_node_visitor_class_new(sizeof (GtLTRdigestPdomVisitor),
                                   gt_ltrdigest_pdom_visitor_free,
                                   NULL,
                                   gt_ltrdigest_pdom_visitor_feature_node,
                                   NULL,
                                   NULL,
                                   NULL);
  }
  return nvc;
}

void gt_ltrdigest_pdom_visitor_output_all_chains(GtLTRdigestPdomVisitor *lv)
{
  gt_assert(lv);
  lv->output_all_chains = true;
}

void gt_ltrdigest_pdom_visitor_set_root_type(GtLTRdigestPdomVisitor *lv,
                                             const char *type)
{
  gt_assert(lv && type);
  lv->root_type = gt_symbol(type);
}

void gt_ltrdigest_pdom_visitor_set_source_tag(GtLTRdigestPdomVisitor *lv,
                                              const char *tag)
{
  gt_assert(lv && tag && lv->tag);
  gt_str_reset(lv->tag);
  gt_str_append_cstr(lv->tag, tag);
}

GtNodeVisitor* gt_ltrdigest_pdom_visitor_new(GtPdomModelSet *model,
                                             double eval_cutoff,
                                             unsigned int chain_max_gap_length,
                                             GtPdomCutoff cutoff,
                                             GtRegionMapping *rmap,
                                             GtError *err)
{
  GtNodeVisitor *nv;
  GtLTRdigestPdomVisitor *lv;
  GtStr *cmd;
  int had_err = 0, i, rval;
  gt_assert(model && rmap);

  rval = system("hmmscan -h > /dev/null");
  if (rval == -1) {
    gt_error_set(err, "error executing system(hmmscan)");
    return NULL;
  }
#ifndef _WIN32
  if (WEXITSTATUS(rval) != 0) {
    gt_error_set(err, "cannot find the hmmscan executable in PATH");
    return NULL;
  }
#else
  /* XXX */
  gt_error_set(err, "hmmscan for Windows not implemented");
  return NULL;
#endif

  nv = gt_node_visitor_create(gt_ltrdigest_pdom_visitor_class());
  lv = gt_ltrdigest_pdom_visitor_cast(nv);
  lv->eval_cutoff = eval_cutoff;
  lv->cutoff = cutoff;
  lv->chain_max_gap_length = chain_max_gap_length;
  lv->rmap = rmap;
  lv->output_all_chains = false;
  lv->tag = gt_str_new_cstr("GenomeTools");
  lv->root_type = gt_symbol(gt_ft_LTR_retrotransposon);

  for (i = 0; i < 3; i++) {
    lv->fwd[i] = gt_str_new();
    lv->rev[i] = gt_str_new();
  }

  if (!had_err) {
    cmd = gt_str_new_cstr("hmmscan --cpu ");
    gt_str_append_uint(cmd, gt_jobs);
    gt_str_append_cstr(cmd, " ");
    switch (cutoff) {
      case GT_PHMM_CUTOFF_GA:
        gt_str_append_cstr(cmd, "--cut_ga");
        break;
      case GT_PHMM_CUTOFF_TC:
        gt_str_append_cstr(cmd, "--cut_tc");
        break;
      case GT_PHMM_CUTOFF_NONE:
        gt_str_append_cstr(cmd, "--domE ");
        gt_str_append_double(cmd, eval_cutoff, 50);
        break;
    }
    gt_str_append_cstr(cmd, " ");
    gt_str_append_cstr(cmd, gt_pdom_model_set_get_filename(model));
    gt_str_append_cstr(cmd, " -"); /* stdin */
    lv->cmdline = cmd;
    lv->args = gt_cstr_split(gt_str_get(lv->cmdline), ' ');
    gt_log_log("HMMER cmdline: %s", gt_str_get(cmd));
  }
  return nv;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x68, %rsp
movq %rdx, %r14
movq %rsi, %r15
movq %rdi, %rbx
callq 0x2153dc
movq %rax, %rdi
movq %rbx, %rsi
callq 0x16af21
testq %rax, %rax
je 0x215a81
movq %rax, %rbx
testq %r14, %r14
je 0x21546a
movq %r14, %rdi
callq 0x101a9a
testb %al, %al
jne 0x215a86
movq %r15, %rdi
callq 0x14b1a8
movq %rax, %r15
movq %rax, %rdi
callq 0x14b33e
testq %rax, %rax
je 0x2154b4
movq %rax, %r12
movq %r12, %rdi
callq 0x149bb2
movq 0xa0(%rbx), %rsi
movq %rax, %rdi
callq 0x17a40
testl %eax, %eax
jne 0x2154a4
movq %r12, 0x28(%rbx)
movq %r15, %rdi
callq 0x14b33e
movq %rax, %r12
testq %rax, %rax
jne 0x215485
movq %r15, %rdi
callq 0x14b3d0
cmpq $0x0, 0x28(%rbx)
je 0x215a6e
callq 0x1208f8
movq %rax, %r12
movq 0x28(%rbx), %rdi
callq 0x14b8df
leaq 0x58(%rsp), %rdi
movq %rax, (%rdi)
movq %rdx, 0x8(%rdi)
decq %rax
movq %rax, 0x68(%rbx)
decq %rdx
movq %rdx, 0x70(%rbx)
callq 0x117813
movq %rax, %r13
movq 0x28(%rbx), %rsi
movq 0xa0(%rbx), %rdx
movq %r12, %rdi
xorl %ecx, %ecx
xorl %r8d, %r8d
xorl %r9d, %r9d
pushq %r14
pushq 0x18(%rbx)
callq 0x307764
addq $0x10, %rsp
movl %eax, %ebp
testl %eax, %eax
jne 0x215a70
movq %r12, %rdi
callq 0x120d4c
cmpq $0x9, %rax
jb 0x215616
movl $0x6, %r15d
movq (%rbx,%r15,8), %rdi
callq 0x120db4
movq 0x18(%rbx,%r15,8), %rdi
callq 0x120db4
incq %r15
cmpq $0x9, %r15
jne 0x215540
movq %r12, 0x10(%rsp)
movq %r12, %rdi
callq 0x120d23
movq %rax, %rdi
movq %r13, %rsi
xorl %edx, %edx
callq 0xe74a9
testq %rax, %rax
je 0x215a8b
movq %rax, 0x8(%rsp)
movq %rax, %rdi
callq 0x124477
movq %rax, %r12
leaq 0x3(%rsp), %r15
leaq 0x4(%rsp), %rdx
movq %rax, %rdi
movq %r15, %rsi
movq %r14, %rcx
callq 0x1247fd
testl %eax, %eax
sete %dl
movb (%r15), %cl
testb %cl, %cl
setne %sil
andb %dl, %sil
cmpb $0x1, %sil
jne 0x2155f5
leaq 0x3(%rsp), %rbp
leaq 0x4(%rsp), %r15
movl 0x4(%rsp), %eax
movq 0x30(%rbx,%rax,8), %rdi
movsbl %cl, %esi
callq 0x120ba5
movq %r12, %rdi
movq %rbp, %rsi
movq %r15, %rdx
xorl %ecx, %ecx
callq 0x1247fd
testl %eax, %eax
jne 0x2155f5
movb 0x3(%rsp), %cl
testb %cl, %cl
jne 0x2155c8
cmpl $-0x2, %eax
jne 0x215666
movq 0x8(%rsp), %rdi
callq 0xe6b9a
movq %r12, %rdi
callq 0x1248e1
movl $0xffffffff, %ebp       # imm = 0xFFFFFFFF
jmp 0x215779
movq 0x28(%rbx), %rdi
callq 0x149bb2
movq %rax, %r14
movq 0x28(%rbx), %rdi
callq 0x14b86c
movq %rax, %r15
movq 0x28(%rbx), %rdi
callq 0x14b88c
movq %r12, %r13
movl %eax, %r12d
movq %r13, %rdi
callq 0x120d4c
leaq 0x1b44c8(%rip), %rdi    # 0x3c9b14
xorl %ebp, %ebp
movq %r14, %rsi
movq %r15, %rdx
movl %r12d, %ecx
movq %rax, %r8
xorl %eax, %eax
callq 0x125448
jmp 0x215842
leaq 0x1b42ef(%rip), %rsi    # 0x3c995c
movq %r13, %rdi
movl $0x38c, %edx            # imm = 0x38C
callq 0x1092b2
movq %rax, %r15
movq 0x10(%rsp), %rdi
callq 0x120d23
movq %r15, %rdi
movq %rax, %rsi
movq %r13, %rdx
callq 0x17370
movq %r15, %rdi
movq %r13, %rsi
xorl %edx, %edx
callq 0x177290
movq 0x8(%rsp), %rdi
callq 0xe6b9a
movq %r15, 0x8(%rsp)
movq %r15, %rdi
movq %r13, %rsi
xorl %edx, %edx
callq 0xe74a9
movq %r12, %rdi
movq %rax, 0x50(%rsp)
movq %rax, %rsi
callq 0x1244b2
leaq 0x3(%rsp), %r15
leaq 0x4(%rsp), %rdx
movq %r12, %rdi
movq %r15, %rsi
movq %r14, %rcx
callq 0x1247fd
movl %eax, %r13d
testl %eax, %eax
sete %cl
movb (%r15), %al
testb %al, %al
setne %dl
andb %cl, %dl
cmpb $0x1, %dl
jne 0x215737
leaq 0x3(%rsp), %rbp
leaq 0x4(%rsp), %r15
movl 0x4(%rsp), %ecx
movq 0x48(%rbx,%rcx,8), %rdi
movsbl %al, %esi
callq 0x120ba5
movq %r12, %rdi
movq %rbp, %rsi
movq %r15, %rdx
xorl %ecx, %ecx
callq 0x1247fd
movl %eax, %r13d
testl %eax, %eax
jne 0x215737
movb 0x3(%rsp), %al
testb %al, %al
jne 0x215707
leaq 0x1b421e(%rip), %rsi    # 0x3c995c
movq 0x8(%rsp), %rdi
movl $0x399, %edx            # imm = 0x399
callq 0x109670
movq 0x50(%rsp), %rdi
callq 0xe6b9a
movq %r12, %rdi
callq 0x1248e1
movl $0xffffffff, %ebp       # imm = 0xFFFFFFFF
cmpl $-0x2, %r13d
je 0x215779
leaq 0x48(%rsp), %rdi
movq %r14, %rsi
callq 0x215d0d
movl %eax, %ebp
testl %ebp, %ebp
movq 0x10(%rsp), %r13
jne 0x215791
leaq 0x40(%rsp), %rdi
movq %r14, %rsi
callq 0x215d0d
movl %eax, %ebp
testl %ebp, %ebp
jne 0x215842
leaq 0x48(%rsp), %rax
movq %rax, 0x18(%rsp)
leaq 0x40(%rsp), %rax
movq %rax, 0x20(%rsp)
movl $0x0, 0x28(%rsp)
movq %rbx, 0x30(%rsp)
movq %r14, 0x38(%rsp)
callq 0x171d0
cmpl $-0x1, %eax
je 0x21582c
testl %eax, %eax
je 0x215a95
leaq 0x57f(%rip), %rdi       # 0x215d57
leaq 0x18(%rsp), %r12
movq %r12, %rsi
movq %r14, %rdx
callq 0x122488
movq %rax, %r15
leaq 0x68c(%rip), %rdi       # 0x215e7e
movq %r12, %rsi
movq %r14, %rdx
callq 0x122488
movq %rax, %r14
movq %rax, %rdi
callq 0x122527
movq %r15, %rdi
callq 0x122527
movq %r14, %rdi
callq 0x12268d
movq %r15, %rdi
callq 0x12268d
movl 0x10(%r12), %ebp
movq 0x10(%rsp), %r13
jmp 0x215842
leaq 0x1b42ab(%rip), %rsi    # 0x3c9ade
movq %r14, %rdi
xorl %eax, %eax
callq 0x1019cf
movl $0xffffffff, %ebp       # imm = 0xFFFFFFFF
movq %r13, %rdi
callq 0x121b03
testl %ebp, %ebp
jne 0x215a70
movq $0x0, 0x18(%rsp)
movq 0x28(%rbx), %rdi
callq 0x14b1a8
movq %rax, %r14
movq %rax, %rdi
callq 0x14b33e
movq %rax, 0x18(%rsp)
xorps %xmm0, %xmm0
testq %rax, %rax
je 0x21591b
movsd %xmm0, 0x10(%rsp)
xorl %r13d, %r13d
leaq 0x174747(%rip), %r15    # 0x389fd7
xorl %r12d, %r12d
movsd %xmm0, 0x8(%rsp)
movq %rax, %rdi
callq 0x149bb2
movq %rax, %rdi
movq %r15, %rsi
callq 0x17a40
testl %eax, %eax
je 0x2158c4
movq %r14, %rdi
callq 0x14b33e
movq %rax, 0x18(%rsp)
testq %rax, %rax
jne 0x215899
jmp 0x21592d
movq 0x18(%rsp), %rdi
callq 0x14970e
movl %eax, %ebp
movq 0x18(%rsp), %rdi
callq 0x149ef0
cvtss2sd %xmm0, %xmm0
cmpl $0x1, %ebp
je 0x215901
testl %ebp, %ebp
jne 0x2158b0
callq 0x17610
movsd 0x10(%rsp), %xmm1
addsd %xmm0, %xmm1
movsd %xmm1, 0x10(%rsp)
movb $0x1, %r12b
jmp 0x2158b0
callq 0x17610
movsd 0x8(%rsp), %xmm1
addsd %xmm0, %xmm1
movsd %xmm1, 0x8(%rsp)
movb $0x1, %r13b
jmp 0x2158b0
movsd %xmm0, 0x8(%rsp)
xorl %r12d, %r12d
movsd %xmm0, 0x10(%rsp)
xorl %r13d, %r13d
movq %r14, %rdi
callq 0x14b3d0
testb $0x1, %r13b
je 0x21594c
testb $0x1, %r12b
jne 0x215976
movq 0x28(%rbx), %rdi
movl $0x1, %esi
jmp 0x215958
testb $0x1, %r12b
je 0x215962
movq 0x28(%rbx), %rdi
xorl %esi, %esi
callq 0x149f2e
jmp 0x215a6e
testb $0x1, %r13b
je 0x215a6e
testb $0x1, %r12b
je 0x215aa7
movsd 0x10(%rsp), %xmm0
movsd 0x8(%rsp), %xmm1
callq 0x10acd4
movl %eax, %ebp
notl %ebp
shrl $0x1f, %ebp
movq 0x28(%rbx), %rdi
movl %ebp, %esi
callq 0x149f2e
movl $0x8, %edi
callq 0xd46fc
movq %rax, %r14
movq 0x28(%rbx), %rdi
callq 0x14b1a8
movq %rax, %r15
movq %rax, %rdi
callq 0x14b33e
movq %rax, 0x18(%rsp)
testq %rax, %rax
je 0x215a17
leaq 0x17460c(%rip), %r12    # 0x389fd7
leaq 0x18(%rsp), %r13
movq %rax, %rdi
callq 0x149bb2
movq %rax, %rdi
movq %r12, %rsi
callq 0x17a40
testl %eax, %eax
jne 0x215a05
movq 0x18(%rsp), %rdi
callq 0x14970e
cmpl %ebp, %eax
je 0x215a05
movl $0x8, %edx
movq %r14, %rdi
movq %r13, %rsi
callq 0xd49ce
movq %r15, %rdi
callq 0x14b33e
movq %rax, 0x18(%rsp)
testq %rax, %rax
jne 0x2159d0
movq %r15, %rdi
callq 0x14b3d0
movq %r14, %rdi
callq 0xd4a9a
testq %rax, %rax
je 0x215a90
movq %r14, %rdi
callq 0xd4a9a
testq %rax, %rax
je 0x215a66
xorl %r15d, %r15d
movq 0x28(%rbx), %r12
movq %r14, %rdi
movq %r15, %rsi
callq 0xd47ba
movq (%rax), %rsi
movq %r12, %rdi
callq 0x14ac1c
incq %r15
movq %r14, %rdi
callq 0xd4a9a
cmpq %rax, %r15
jb 0x215a3c
movq %r14, %rdi
callq 0xd4ef4
xorl %ebp, %ebp
movl %ebp, %eax
addq $0x68, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
callq 0x82db9
callq 0x82c57
callq 0x82d80
callq 0x82d47
leaq 0x40(%rsp), %rdi
leaq 0x48(%rsp), %rsi
movq %rbx, %rdx
callq 0x82c90
callq 0x82d0e