// File: /workspace/github_c_makefile_star2_O2/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 $0x78, %rsp
movq %rdx, %rbp
movq %rsi, %r14
movq %rdi, %rbx
callq 0x1c02c6
movq %rax, %rdi
movq %rbx, %rsi
callq 0x102dfe
testq %rax, %rax
je 0x1c08ba
movq %rax, %rbx
testq %rbp, %rbp
je 0x1c034d
movq %rbp, %rdi
callq 0x89eb7
testb %al, %al
jne 0x1c08e8
movq %r14, %rdi
callq 0xdc6f0
movq %rax, %r14
movq %r14, %rdi
callq 0xdc92e
testq %rax, %rax
je 0x1c0389
movq %rax, %r15
movq %rax, %rdi
callq 0xda338
movq 0xa0(%rbx), %rsi
movq %rax, %rdi
callq 0x179e0
testl %eax, %eax
jne 0x1c0358
movq %r15, 0x28(%rbx)
jmp 0x1c0358
movq %r14, %rdi
callq 0xdc9f1
cmpq $0x0, 0x28(%rbx)
je 0x1c0891
callq 0xacb84
movq %rax, %r13
movq 0x28(%rbx), %rdi
callq 0xdd1f4
leaq 0x68(%rsp), %rdi
movq %rax, (%rdi)
movq %rdx, 0x8(%rdi)
decq %rax
movq %rax, 0x68(%rbx)
decq %rdx
movq %rdx, 0x70(%rbx)
callq 0xa31ee
movq %rax, %r12
movq 0x28(%rbx), %rsi
movq 0xa0(%rbx), %rdx
movq %r13, %rdi
xorl %ecx, %ecx
xorl %r8d, %r8d
xorl %r9d, %r9d
pushq %rbp
pushq 0x18(%rbx)
callq 0x29a8d0
popq %rcx
popq %rdx
movq %rbp, %rcx
movl %eax, %ebp
testl %eax, %eax
jne 0x1c0893
movq %rcx, 0x10(%rsp)
movq %r13, %rdi
callq 0xad289
cmpq $0x9, %rax
jb 0x1c0432
pushq $0x6
popq %r14
cmpq $0x9, %r14
je 0x1c047f
movq (%rbx,%r14,8), %rdi
callq 0xad357
movq 0x18(%rbx,%r14,8), %rdi
callq 0xad357
incq %r14
jmp 0x1c0414
movq 0x28(%rbx), %rdi
callq 0xda338
movq %rax, %r14
movq 0x28(%rbx), %rdi
callq 0xdd0b5
movq %rax, %r15
movq 0x28(%rbx), %rdi
callq 0xdd108
movl %eax, %r12d
movq %r13, %rdi
callq 0xad289
leaq 0x1a0435(%rip), %rdi    # 0x36089a
xorl %ebp, %ebp
movq %r14, %rsi
movq %r15, %rdx
movl %r12d, %ecx
movq %rax, %r8
xorl %eax, %eax
callq 0xb2cd0
jmp 0x1c05e9
movq %r13, 0x8(%rsp)
movq %r13, %rdi
callq 0xad1fa
movq %rax, %rdi
movq %r12, %rsi
xorl %edx, %edx
callq 0x6ad4b
testq %rax, %rax
je 0x1c0920
movq %rax, %r15
movq %rax, %rdi
callq 0xb1af2
movq %rax, %r13
leaq 0x7(%rsp), %rbp
leaq 0x1c(%rsp), %r14
movq 0x10(%rsp), %rcx
movq %r13, %rdi
movq %rbp, %rsi
movq %r14, %rdx
callq 0xb2013
testl %eax, %eax
jne 0x1c04ee
movb 0x7(%rsp), %cl
testb %cl, %cl
je 0x1c04ee
movl 0x1c(%rsp), %eax
movq 0x30(%rbx,%rax,8), %rdi
movsbl %cl, %esi
callq 0xaced9
xorl %ecx, %ecx
jmp 0x1c04bf
pushq $-0x1
popq %rbp
cmpl $-0x2, %eax
jne 0x1c050b
movq %r15, %rdi
callq 0x6a21c
movq %r13, %rdi
callq 0xb217a
jmp 0x1c05e4
leaq 0x1a01d0(%rip), %rsi    # 0x3606e2
movq %r12, %rdi
movl $0x38c, %edx            # imm = 0x38C
callq 0x93160
movq %rax, %r14
movq 0x8(%rsp), %rdi
callq 0xad1fa
movq %r14, %rdi
movq %rax, %rsi
movq %r12, %rdx
callq 0x17350
movq %r14, %rdi
movq %r12, %rsi
xorl %edx, %edx
callq 0x111ab8
movq %r15, %rdi
callq 0x6a21c
movq %r14, 0x20(%rsp)
movq %r14, %rdi
movq %r12, %rsi
xorl %edx, %edx
callq 0x6ad4b
movq %r13, %rdi
movq %rax, 0x38(%rsp)
movq %rax, %rsi
callq 0xb1b8f
leaq 0x7(%rsp), %r14
leaq 0x1c(%rsp), %r12
movq 0x10(%rsp), %rcx
movq %r13, %rdi
movq %r14, %rsi
movq %r12, %rdx
callq 0xb2013
movl %eax, %r15d
testl %eax, %eax
jne 0x1c05b2
movb 0x7(%rsp), %al
testb %al, %al
je 0x1c05b2
movl 0x1c(%rsp), %ecx
movq 0x48(%rbx,%rcx,8), %rdi
movsbl %al, %esi
callq 0xaced9
xorl %ecx, %ecx
jmp 0x1c0580
leaq 0x1a0129(%rip), %rsi    # 0x3606e2
movq 0x20(%rsp), %rdi
movl $0x399, %edx            # imm = 0x399
callq 0x936f9
movq 0x38(%rsp), %rdi
callq 0x6a21c
movq %r13, %rdi
callq 0xb217a
cmpl $-0x2, %r15d
jne 0x1c076d
movq 0x8(%rsp), %r13
movq %r13, %rdi
callq 0xae103
testl %ebp, %ebp
jne 0x1c0893
movq 0x28(%rbx), %rdi
callq 0xdc6f0
movq %rax, %r14
xorps %xmm0, %xmm0
movsd %xmm0, 0x8(%rsp)
movl $0x0, 0x10(%rsp)
leaq 0x160a0c(%rip), %r15    # 0x321029
movsd %xmm0, 0x20(%rsp)
xorl %r13d, %r13d
movq %r14, %rdi
callq 0xdc92e
testq %rax, %rax
je 0x1c06a3
movq %rax, %r12
movq %rax, %rdi
callq 0xda338
movq %rax, %rdi
movq %r15, %rsi
callq 0x179e0
testl %eax, %eax
jne 0x1c0626
movq %r12, %rdi
callq 0xd9d99
movl %eax, %ebp
movq %r12, %rdi
callq 0xdaa3e
cvtss2sd %xmm0, %xmm0
cmpl $0x1, %ebp
je 0x1c0689
testl %ebp, %ebp
jne 0x1c0626
callq 0x175e0
movsd 0x20(%rsp), %xmm1
addsd %xmm0, %xmm1
movsd %xmm1, 0x20(%rsp)
movb $0x1, %al
movl %eax, 0x10(%rsp)
jmp 0x1c0626
callq 0x175e0
movsd 0x8(%rsp), %xmm1
addsd %xmm0, %xmm1
movsd %xmm1, 0x8(%rsp)
movb $0x1, %r13b
jmp 0x1c0626
andq $0x0, 0x40(%rsp)
movq %r14, %rdi
callq 0xdc9f1
testb $0x1, %r13b
je 0x1c0757
testb $0x1, 0x10(%rsp)
je 0x1c0833
movsd 0x20(%rsp), %xmm0
movsd 0x8(%rsp), %xmm1
callq 0x955a7
movl %eax, %ebp
notl %ebp
shrl $0x1f, %ebp
movq 0x28(%rbx), %rdi
movl %ebp, %esi
callq 0xdab34
pushq $0x8
popq %rdi
callq 0x5809c
movq %rax, %r14
movq 0x28(%rbx), %rdi
callq 0xdc6f0
movq %rax, %r12
leaq 0x160922(%rip), %r13    # 0x321029
leaq 0x40(%rsp), %r15
movq %r12, %rdi
callq 0xdc92e
movq %rax, 0x40(%rsp)
testq %rax, %rax
je 0x1c0841
movq %rax, %rdi
callq 0xda338
movq %rax, %rdi
movq %r13, %rsi
callq 0x179e0
testl %eax, %eax
jne 0x1c070c
movq 0x40(%rsp), %rdi
callq 0xd9d99
cmpl %ebp, %eax
je 0x1c070c
movq %r14, %rdi
movq %r15, %rsi
pushq $0x8
popq %rdx
callq 0x5851d
jmp 0x1c070c
testb $0x1, 0x10(%rsp)
je 0x1c0891
movq 0x28(%rbx), %rdi
xorl %esi, %esi
jmp 0x1c083a
leaq 0x30(%rsp), %r14
movq %r14, %rdi
movq 0x10(%rsp), %r12
movq %r12, %rsi
callq 0x1c0d14
testl %eax, %eax
movq 0x8(%rsp), %r13
jne 0x1c05e9
leaq 0x28(%rsp), %r15
movq %r15, %rdi
movq %r12, %rsi
callq 0x1c0d14
testl %eax, %eax
jne 0x1c05e9
movq %r14, 0x40(%rsp)
movq %r15, 0x48(%rsp)
andl $0x0, 0x50(%rsp)
movq %rbx, 0x58(%rsp)
movq %r12, 0x60(%rsp)
callq 0x171b0
cmpl $-0x1, %eax
je 0x1c08a4
testl %eax, %eax
je 0x1c097c
leaq 0x58e(%rip), %rdi       # 0x1c0d6b
leaq 0x40(%rsp), %r14
movq %r14, %rsi
movq 0x10(%rsp), %r12
movq %r12, %rdx
callq 0xaeee8
movq %rax, %r15
leaq 0x69c(%rip), %rdi       # 0x1c0e98
movq %r14, %rsi
movq %r12, %rdx
callq 0xaeee8
movq %rax, %r12
movq %rax, %rdi
callq 0xaefdb
movq %r15, %rdi
callq 0xaefdb
movq %r12, %rdi
callq 0xaf45e
movq %r15, %rdi
callq 0xaf45e
movl 0x10(%r14), %ebp
jmp 0x1c05e9
movq 0x28(%rbx), %rdi
pushq $0x1
popq %rsi
callq 0xdab34
jmp 0x1c0891
movq %r12, %rdi
callq 0xdc9f1
movq %r14, %rdi
callq 0x586a4
testq %rax, %rax
je 0x1c094e
xorl %r15d, %r15d
movq %r14, %rdi
callq 0x586a4
cmpq %rax, %r15
jae 0x1c0889
movq 0x28(%rbx), %r12
movq %r14, %rdi
movq %r15, %rsi
callq 0x581aa
movq (%rax), %rsi
movq %r12, %rdi
callq 0xdbdf7
incq %r15
jmp 0x1c085d
movq %r14, %rdi
callq 0x58eb9
xorl %ebp, %ebp
movl %ebp, %eax
addq $0x78, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x19ffb9(%rip), %rsi    # 0x360864
movq %r12, %rdi
xorl %eax, %eax
callq 0x89dbb
jmp 0x1c05e9
movq 0x2776a7(%rip), %rax    # 0x437f68
movq (%rax), %rdi
leaq 0x124748(%rip), %rsi    # 0x2e5013
leaq 0x19fa6f(%rip), %rdx    # 0x360341
leaq 0x19ff64(%rip), %rcx    # 0x36083d
leaq 0x19fe02(%rip), %r8     # 0x3606e2
movl $0x356, %r9d            # imm = 0x356
jmp 0x1c0914
movq 0x277679(%rip), %rax    # 0x437f68
movq (%rax), %rdi
leaq 0x12471a(%rip), %rsi    # 0x2e5013
leaq 0x1248bf(%rip), %rdx    # 0x2e51bf
leaq 0x19ff36(%rip), %rcx    # 0x36083d
leaq 0x19fdd4(%rip), %r8     # 0x3606e2
movl $0x357, %r9d            # imm = 0x357
xorl %eax, %eax
callq 0x17a50
callq 0x17390
movq 0x277641(%rip), %rax    # 0x437f68
movq (%rax), %rdi
leaq 0x1246e2(%rip), %rsi    # 0x2e5013
leaq 0x153254(%rip), %rdx    # 0x313b8c
leaq 0x19fefe(%rip), %rcx    # 0x36083d
leaq 0x19fd9c(%rip), %r8     # 0x3606e2
movl $0x382, %r9d            # imm = 0x382
jmp 0x1c0914
movq 0x277613(%rip), %rax    # 0x437f68
movq (%rax), %rdi
leaq 0x1246b4(%rip), %rsi    # 0x2e5013
leaq 0x1a052d(%rip), %rdx    # 0x360e93
leaq 0x1a04fe(%rip), %rcx    # 0x360e6b
leaq 0x19fd6e(%rip), %r8     # 0x3606e2
movl $0x2f8, %r9d            # imm = 0x2F8
jmp 0x1c0914
pushq $0x1
popq %rbp
movl %ebp, %edi
callq 0x17f20
movl 0x2c(%rsp), %edi
callq 0x1c0d4a
xorl %edi, %edi
callq 0x17f20
movl 0x30(%rsp), %edi
callq 0x1c0d4a
movl 0x30(%rsp), %edi
callq 0x17f20
movl 0x34(%rsp), %edi
callq 0x17f20
movl 0x28(%rsp), %edi
callq 0x17f20
movl 0x2c(%rsp), %edi
callq 0x17f20
movq 0x98(%rbx), %rsi
leaq 0x19fec1(%rip), %rdi    # 0x360892
callq 0x17580
leaq 0x19fea4(%rip), %rdi    # 0x360881
callq 0x17660
movl %ebp, %edi
callq 0x178f0