// File: /workspace/github_c_makefile_star2_O3/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 0x20ba30
movq %rax, %rdi
movq %rbx, %rsi
callq 0x1630b1
testq %rax, %rax
je 0x20c0b4
movq %rax, %rbx
testq %r14, %r14
je 0x20baba
movq %r14, %rdi
callq 0xfcc32
testb %al, %al
jne 0x20c0b9
movq %r15, %rdi
callq 0x143f54
movq %rax, %r15
movq %rax, %rdi
callq 0x1440ea
testq %rax, %rax
je 0x20bb04
movq %rax, %r12
movq %r12, %rdi
callq 0x142988
movq 0xa0(%rbx), %rsi
movq %rax, %rdi
callq 0x17a40
testl %eax, %eax
jne 0x20baf4
movq %r12, 0x28(%rbx)
movq %r15, %rdi
callq 0x1440ea
movq %rax, %r12
testq %rax, %rax
jne 0x20bad5
movq %r15, %rdi
callq 0x14417c
cmpq $0x0, 0x28(%rbx)
je 0x20c07f
callq 0x11ac6c
movq %rax, %r12
movq 0x28(%rbx), %rdi
callq 0x144679
leaq 0x58(%rsp), %rdi
movq %rax, (%rdi)
movq %rdx, 0x8(%rdi)
decq %rax
movq %rax, 0x68(%rbx)
decq %rdx
movq %rdx, 0x70(%rbx)
callq 0x112233
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 0x2fda60
addq $0x10, %rsp
movl %eax, %ebp
testl %eax, %eax
jne 0x20c081
movq %r12, %rdi
callq 0x11b0ca
cmpq $0x9, %rax
jb 0x20bc65
movl $0x6, %r15d
movq (%rbx,%r15,8), %rdi
callq 0x11b132
movq 0x18(%rbx,%r15,8), %rdi
callq 0x11b132
incq %r15
cmpq $0x9, %r15
jne 0x20bb90
movq %r12, 0x10(%rsp)
movq %r12, %rdi
callq 0x11b0a1
movq %rax, %rdi
movq %r13, %rsi
xorl %edx, %edx
callq 0xe2fdd
testq %rax, %rax
je 0x20c0be
movq %rax, 0x8(%rsp)
movq %rax, %rdi
callq 0x11e737
movq %rax, %r12
leaq 0x3(%rsp), %r15
leaq 0x4(%rsp), %rdx
movq %rax, %rdi
movq %r15, %rsi
movq %r14, %rcx
callq 0x11ea96
testl %eax, %eax
sete %dl
movb (%r15), %cl
testb %cl, %cl
setne %sil
andb %dl, %sil
cmpb $0x1, %sil
jne 0x20bc45
leaq 0x3(%rsp), %rbp
leaq 0x4(%rsp), %r15
movl 0x4(%rsp), %eax
movq 0x30(%rbx,%rax,8), %rdi
movsbl %cl, %esi
callq 0x11af23
movq %r12, %rdi
movq %rbp, %rsi
movq %r15, %rdx
xorl %ecx, %ecx
callq 0x11ea96
testl %eax, %eax
jne 0x20bc45
movb 0x3(%rsp), %cl
testb %cl, %cl
jne 0x20bc18
cmpl $-0x2, %eax
jne 0x20be8f
movq 0x8(%rsp), %rdi
callq 0xe26c6
movq %r12, %rdi
callq 0x11eb7a
jmp 0x20c0a3
movq 0x28(%rbx), %rdi
callq 0x142988
movq %rax, %r14
movq 0x28(%rbx), %rdi
callq 0x144606
movq %rax, %r15
movq 0x28(%rbx), %rdi
callq 0x144626
movl %eax, %ebp
movq %r12, %rdi
callq 0x11b0ca
leaq 0x1b47ed(%rip), %rdi    # 0x3c0484
movq %r14, %rsi
movq %r15, %rdx
movl %ebp, %ecx
movq %rax, %r8
xorl %eax, %eax
callq 0x11f68c
movq %r12, %rdi
callq 0x11bdbf
movq 0x28(%rbx), %rdi
callq 0x143f54
movq %rax, %r14
movq %rax, %rdi
callq 0x1440ea
testq %rax, %rax
je 0x20c058
movq %rax, %r12
xorps %xmm0, %xmm0
movsd %xmm0, 0x10(%rsp)
xorl %r13d, %r13d
leaq 0x174f35(%rip), %r15    # 0x380c19
movl $0x0, 0x18(%rsp)
movsd %xmm0, 0x8(%rsp)
movq %r12, %rdi
callq 0x142988
movq %rax, %rdi
movq %r15, %rsi
callq 0x17a40
testl %eax, %eax
je 0x20bd1b
movq %r14, %rdi
callq 0x1440ea
movq %rax, %r12
testq %rax, %rax
jne 0x20bcf2
jmp 0x20bd71
movq %r12, %rdi
callq 0x1424d6
movl %eax, %ebp
movq %r12, %rdi
callq 0x142cc3
cvtss2sd %xmm0, %xmm0
cmpl $0x1, %ebp
je 0x20bd57
testl %ebp, %ebp
jne 0x20bd09
callq 0x17610
movsd 0x10(%rsp), %xmm1
addsd %xmm0, %xmm1
movsd %xmm1, 0x10(%rsp)
movb $0x1, %al
movl %eax, 0x18(%rsp)
jmp 0x20bd09
callq 0x17610
movsd 0x8(%rsp), %xmm1
addsd %xmm0, %xmm1
movsd %xmm1, 0x8(%rsp)
movb $0x1, %r13b
jmp 0x20bd09
movq %r14, %rdi
callq 0x14417c
testb $0x1, %r13b
je 0x20c062
testb $0x1, 0x18(%rsp)
je 0x20c071
movsd 0x10(%rsp), %xmm0
movsd 0x8(%rsp), %xmm1
callq 0x105c1c
movl %eax, %ebp
notl %ebp
shrl $0x1f, %ebp
movq 0x28(%rbx), %rdi
movl %ebp, %esi
callq 0x142d01
movl $0x8, %edi
callq 0xd214c
movq %rax, %r14
movq 0x28(%rbx), %rdi
callq 0x143f54
movq %rax, %r15
movq %rax, %rdi
callq 0x1440ea
movq %rax, 0x20(%rsp)
testq %rax, %rax
je 0x20be2f
leaq 0x174e36(%rip), %r12    # 0x380c19
leaq 0x20(%rsp), %r13
movq %rax, %rdi
callq 0x142988
movq %rax, %rdi
movq %r12, %rsi
callq 0x17a40
testl %eax, %eax
jne 0x20be1d
movq 0x20(%rsp), %rdi
callq 0x1424d6
cmpl %ebp, %eax
je 0x20be1d
movl $0x8, %edx
movq %r14, %rdi
movq %r13, %rsi
callq 0xd2410
movq %r15, %rdi
callq 0x1440ea
movq %rax, 0x20(%rsp)
testq %rax, %rax
jne 0x20bde8
movq %r15, %rdi
callq 0x14417c
movq %r14, %rdi
callq 0xd24e0
testq %rax, %rax
je 0x20c0c3
movq %r14, %rdi
callq 0xd24e0
testq %rax, %rax
je 0x20be82
xorl %r15d, %r15d
movq 0x28(%rbx), %r12
movq %r14, %rdi
movq %r15, %rsi
callq 0xd2207
movq (%rax), %rsi
movq %r12, %rdi
callq 0x1439cb
incq %r15
movq %r14, %rdi
callq 0xd24e0
cmpq %rax, %r15
jb 0x20be58
movq %r14, %rdi
callq 0xd2938
jmp 0x20c07f
leaq 0x1b4436(%rip), %rsi    # 0x3c02cc
movq %r13, %rdi
movl $0x38c, %edx            # imm = 0x38C
callq 0x104226
movq %rax, %r15
movq 0x10(%rsp), %rdi
callq 0x11b0a1
movq %r15, %rdi
movq %rax, %rsi
movq %r13, %rdx
callq 0x17370
movq %r15, %rdi
movq %r13, %rsi
xorl %edx, %edx
callq 0x16eef8
movq 0x8(%rsp), %rdi
callq 0xe26c6
movq %r15, 0x8(%rsp)
movq %r15, %rdi
movq %r13, %rsi
xorl %edx, %edx
callq 0xe2fdd
movq %r12, %rdi
movq %rax, 0x18(%rsp)
movq %rax, %rsi
callq 0x11e772
leaq 0x3(%rsp), %r15
leaq 0x4(%rsp), %rdx
movq %r12, %rdi
movq %r15, %rsi
movq %r14, %rcx
callq 0x11ea96
movl %eax, %ebp
testl %eax, %eax
sete %cl
movb (%r15), %al
testb %al, %al
setne %dl
andb %cl, %dl
cmpb $0x1, %dl
jne 0x20bf5e
leaq 0x3(%rsp), %r13
leaq 0x4(%rsp), %r15
movl 0x4(%rsp), %ecx
movq 0x48(%rbx,%rcx,8), %rdi
movsbl %al, %esi
callq 0x11af23
movq %r12, %rdi
movq %r13, %rsi
movq %r15, %rdx
xorl %ecx, %ecx
callq 0x11ea96
movl %eax, %ebp
testl %eax, %eax
jne 0x20bf5e
movb 0x3(%rsp), %al
testb %al, %al
jne 0x20bf2f
leaq 0x1b4367(%rip), %rsi    # 0x3c02cc
movq 0x8(%rsp), %rdi
movl $0x399, %edx            # imm = 0x399
callq 0x1045eb
movq 0x18(%rsp), %rdi
callq 0xe26c6
movq %r12, %rdi
callq 0x11eb7a
cmpl $-0x2, %ebp
je 0x20c0a3
leaq 0x50(%rsp), %r15
movq %r15, %rdi
movq %r14, %rsi
callq 0x20c33b
testl %eax, %eax
jne 0x20c0a3
leaq 0x48(%rsp), %r12
movq %r12, %rdi
movq %r14, %rsi
callq 0x20c33b
testl %eax, %eax
jne 0x20c0a3
movq %r15, 0x20(%rsp)
movq %r12, 0x28(%rsp)
movl $0x0, 0x30(%rsp)
movq %rbx, 0x38(%rsp)
movq %r14, 0x40(%rsp)
callq 0x171d0
cmpl $-0x1, %eax
je 0x20c092
testl %eax, %eax
je 0x20c0c8
leaq 0x38d(%rip), %rdi       # 0x20c385
leaq 0x20(%rsp), %r12
movq %r12, %rsi
movq %r14, %rdx
callq 0x11c738
movq %rax, %r15
leaq 0x49a(%rip), %rdi       # 0x20c4ac
movq %r12, %rsi
movq %r14, %rdx
callq 0x11c738
movq %rax, %r14
movq %rax, %rdi
callq 0x11c7d7
movq %r15, %rdi
callq 0x11c7d7
movq %r14, %rdi
callq 0x11c93d
movq %r15, %rdi
callq 0x11c93d
movl 0x10(%r12), %ebp
movq 0x10(%rsp), %rdi
callq 0x11bdbf
testl %ebp, %ebp
jne 0x20c081
jmp 0x20bcb1
movq %r14, %rdi
callq 0x14417c
jmp 0x20c07f
testb $0x1, 0x18(%rsp)
je 0x20c07f
movq 0x28(%rbx), %rdi
xorl %esi, %esi
jmp 0x20c07a
movq 0x28(%rbx), %rdi
movl $0x1, %esi
callq 0x142d01
xorl %ebp, %ebp
movl %ebp, %eax
addq $0x68, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x1b43b5(%rip), %rsi    # 0x3c044e
movq %r14, %rdi
xorl %eax, %eax
callq 0xfcb67
movq 0x10(%rsp), %rdi
callq 0x11bdbf
movl $0xffffffff, %ebp       # imm = 0xFFFFFFFF
jmp 0x20c081
callq 0x80e22
callq 0x80cf9
callq 0x80de9
callq 0x80db0
leaq 0x48(%rsp), %rdi
leaq 0x50(%rsp), %rsi
movq %rbx, %rdx
callq 0x80d32