// File: /workspace/github_c_makefile_star2_O0/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:
subq $0x128, %rsp            # imm = 0x128
movq %rdi, 0x120(%rsp)
movq %rsi, 0x118(%rsp)
movq %rdx, 0x110(%rsp)
movq $0x0, 0xf8(%rsp)
movl $0x0, 0xf4(%rsp)
callq 0x307770
movq %rax, %rdi
movq 0x120(%rsp), %rsi
callq 0x1b2350
movq %rax, 0x108(%rsp)
cmpq $0x0, 0x108(%rsp)
jne 0x307856
movq 0x33477b(%rip), %rax    # 0x63bfa0
movq (%rax), %rdi
leaq 0x20e7e4(%rip), %rsi    # 0x516013
leaq 0x28b84c(%rip), %rdx    # 0x593082
leaq 0x28be17(%rip), %rcx    # 0x593654
leaq 0x28bcb5(%rip), %r8     # 0x5934f9
movl $0x356, %r9d            # imm = 0x356
movb $0x0, %al
callq 0x199f0
callq 0x19370
jmp 0x307858
jmp 0x30785a
cmpq $0x0, 0x110(%rsp)
je 0x3078b0
movq 0x110(%rsp), %rdi
callq 0xd8a60
testb $0x1, %al
jne 0x307878
jmp 0x3078b0
movq 0x334721(%rip), %rax    # 0x63bfa0
movq (%rax), %rdi
leaq 0x20e78a(%rip), %rsi    # 0x516013
leaq 0x20e92f(%rip), %rdx    # 0x5161bf
leaq 0x28bdbd(%rip), %rcx    # 0x593654
leaq 0x28bc5b(%rip), %r8     # 0x5934f9
movl $0x357, %r9d            # imm = 0x357
movb $0x0, %al
callq 0x199f0
callq 0x19370
jmp 0x3078b2
movq 0x118(%rsp), %rdi
callq 0x170b00
movq %rax, 0x100(%rsp)
xorl %eax, %eax
cmpl $0x0, 0xf4(%rsp)
movb %al, 0x3f(%rsp)
jne 0x3078f7
movq 0x100(%rsp), %rdi
callq 0x170e30
movq %rax, 0xf8(%rsp)
cmpq $0x0, %rax
setne %al
movb %al, 0x3f(%rsp)
movb 0x3f(%rsp), %al
testb $0x1, %al
jne 0x307901
jmp 0x307940
movq 0xf8(%rsp), %rdi
callq 0x16d430
movq %rax, %rdi
movq 0x108(%rsp), %rax
movq 0xa0(%rax), %rsi
callq 0x19980
cmpl $0x0, %eax
jne 0x30793e
movq 0xf8(%rsp), %rcx
movq 0x108(%rsp), %rax
movq %rcx, 0x28(%rax)
jmp 0x3078c7
movq 0x100(%rsp), %rdi
callq 0x170f50
cmpl $0x0, 0xf4(%rsp)
jne 0x30803b
movq 0x108(%rsp), %rax
cmpq $0x0, 0x28(%rax)
je 0x30803b
callq 0x11d4a0
movq %rax, 0x88(%rsp)
movq 0x108(%rsp), %rax
movq 0x28(%rax), %rdi
callq 0x171cc0
movq %rax, 0x78(%rsp)
movq %rdx, 0x80(%rsp)
movq 0x78(%rsp), %rax
movq %rax, 0xe0(%rsp)
movq 0x80(%rsp), %rax
movq %rax, 0xe8(%rsp)
movq 0xe0(%rsp), %rcx
subq $0x1, %rcx
movq 0x108(%rsp), %rax
movq %rcx, 0x68(%rax)
movq 0xe8(%rsp), %rcx
subq $0x1, %rcx
movq 0x108(%rsp), %rax
movq %rcx, 0x70(%rax)
leaq 0xe0(%rsp), %rdi
callq 0x107320
movq %rax, 0xb8(%rsp)
movq 0x88(%rsp), %rdi
movq 0x108(%rsp), %rax
movq 0x28(%rax), %rsi
movq 0x108(%rsp), %rax
movq 0xa0(%rax), %rdx
movq 0x108(%rsp), %rax
movq 0x18(%rax), %r10
movq 0x110(%rsp), %rax
xorl %ecx, %ecx
xorl %r8d, %r8d
movl %r8d, %r9d
movq %r9, %r8
movq %r10, (%rsp)
movq %rax, 0x8(%rsp)
callq 0x48f4f0
movl %eax, 0xf4(%rsp)
cmpl $0x0, 0xf4(%rsp)
jne 0x308039
movq 0x88(%rsp), %rdi
callq 0x11dfa0
cmpq $0x9, %rax
jb 0x307f9f
movq $0x0, 0xd8(%rsp)
cmpq $0x3, 0xd8(%rsp)
jae 0x307ad8
movq 0x108(%rsp), %rax
movq 0xd8(%rsp), %rcx
movq 0x30(%rax,%rcx,8), %rdi
callq 0x11e110
movq 0x108(%rsp), %rax
movq 0xd8(%rsp), %rcx
movq 0x48(%rax,%rcx,8), %rdi
callq 0x11e110
movq 0xd8(%rsp), %rax
addq $0x1, %rax
movq %rax, 0xd8(%rsp)
jmp 0x307a83
movq 0x88(%rsp), %rdi
callq 0x11dee0
movq %rax, %rdi
movq 0xb8(%rsp), %rsi
xorl %eax, %eax
movl %eax, %edx
callq 0xa07e0
movq %rax, 0xd0(%rsp)
cmpq $0x0, 0xd0(%rsp)
jne 0x307b44
movq 0x33448d(%rip), %rax    # 0x63bfa0
movq (%rax), %rdi
leaq 0x20e4f6(%rip), %rsi    # 0x516013
leaq 0x23df84(%rip), %rdx    # 0x545aa8
leaq 0x28bb29(%rip), %rcx    # 0x593654
leaq 0x28b9c7(%rip), %r8     # 0x5934f9
movl $0x382, %r9d            # imm = 0x382
movb $0x0, %al
callq 0x199f0
callq 0x19370
jmp 0x307b46
movq 0xd0(%rsp), %rdi
callq 0x124e10
movq %rax, 0xc8(%rsp)
movq 0xc8(%rsp), %rdi
movq 0x110(%rsp), %rcx
leaq 0xb7(%rsp), %rsi
leaq 0x90(%rsp), %rdx
callq 0x125540
movl %eax, 0xc4(%rsp)
xorl %eax, %eax
cmpl $0x0, 0xc4(%rsp)
movb %al, 0x3e(%rsp)
jne 0x307ba9
movsbl 0xb7(%rsp), %eax
cmpl $0x0, %eax
setne %al
movb %al, 0x3e(%rsp)
movb 0x3e(%rsp), %al
testb $0x1, %al
jne 0x307bb3
jmp 0x307bfe
movq 0x108(%rsp), %rax
movl 0x90(%rsp), %ecx
movq 0x30(%rax,%rcx,8), %rdi
movsbl 0xb7(%rsp), %esi
callq 0x11da70
movq 0xc8(%rsp), %rdi
leaq 0xb7(%rsp), %rsi
leaq 0x90(%rsp), %rdx
xorl %eax, %eax
movl %eax, %ecx
callq 0x125540
movl %eax, 0xc4(%rsp)
jmp 0x307b87
cmpl $-0x2, 0xc4(%rsp)
jne 0x307c13
movl $0xffffffff, 0xf4(%rsp) # imm = 0xFFFFFFFF
cmpl $0x0, 0xf4(%rsp)
jne 0x307da6
movq 0xb8(%rsp), %rdi
shlq $0x0, %rdi
leaq 0x28b8c5(%rip), %rsi    # 0x5934f9
movl $0x38c, %edx            # imm = 0x38C
callq 0xe80f0
movq %rax, 0xa8(%rsp)
movq 0xa8(%rsp), %rax
movq %rax, 0x30(%rsp)
movq 0x88(%rsp), %rdi
callq 0x11dee0
movq 0x30(%rsp), %rdi
movq %rax, %rsi
movq 0xb8(%rsp), %rdx
shlq $0x0, %rdx
callq 0x19330
movq 0xa8(%rsp), %rdi
movq 0xb8(%rsp), %rsi
xorl %eax, %eax
movl %eax, %edx
callq 0x1cb4f0
movq 0xd0(%rsp), %rdi
callq 0x9f800
movq 0xa8(%rsp), %rdi
movq 0xb8(%rsp), %rsi
xorl %eax, %eax
movl %eax, %edx
callq 0xa07e0
movq %rax, 0xd0(%rsp)
movq 0xc8(%rsp), %rdi
movq 0xd0(%rsp), %rsi
callq 0x124f00
movq 0xc8(%rsp), %rdi
movq 0x110(%rsp), %rcx
leaq 0xb7(%rsp), %rsi
leaq 0x90(%rsp), %rdx
callq 0x125540
movl %eax, 0xc4(%rsp)
xorl %eax, %eax
cmpl $0x0, 0xc4(%rsp)
movb %al, 0x2f(%rsp)
jne 0x307d23
movsbl 0xb7(%rsp), %eax
cmpl $0x0, %eax
setne %al
movb %al, 0x2f(%rsp)
movb 0x2f(%rsp), %al
testb $0x1, %al
jne 0x307d2d
jmp 0x307d78
movq 0x108(%rsp), %rax
movl 0x90(%rsp), %ecx
movq 0x48(%rax,%rcx,8), %rdi
movsbl 0xb7(%rsp), %esi
callq 0x11da70
movq 0xc8(%rsp), %rdi
leaq 0xb7(%rsp), %rsi
leaq 0x90(%rsp), %rdx
xorl %eax, %eax
movl %eax, %ecx
callq 0x125540
movl %eax, 0xc4(%rsp)
jmp 0x307d01
cmpl $-0x2, 0xc4(%rsp)
jne 0x307d8d
movl $0xffffffff, 0xf4(%rsp) # imm = 0xFFFFFFFF
movq 0xa8(%rsp), %rdi
leaq 0x28b75d(%rip), %rsi    # 0x5934f9
movl $0x399, %edx            # imm = 0x399
callq 0xe88c0
movq 0xd0(%rsp), %rdi
callq 0x9f800
movq 0xc8(%rsp), %rdi
callq 0x125770
cmpl $0x0, 0xf4(%rsp)
jne 0x307de6
leaq 0x9c(%rsp), %rdi
movq 0x110(%rsp), %rsi
callq 0x308500
movl %eax, 0xf4(%rsp)
cmpl $0x0, 0xf4(%rsp)
jne 0x307e0c
leaq 0x94(%rsp), %rdi
movq 0x110(%rsp), %rsi
callq 0x308500
movl %eax, 0xf4(%rsp)
cmpl $0x0, 0xf4(%rsp)
jne 0x307f9d
leaq 0x9c(%rsp), %rax
movq %rax, 0x50(%rsp)
leaq 0x94(%rsp), %rax
movq %rax, 0x58(%rsp)
movl $0x0, 0x60(%rsp)
movq 0x108(%rsp), %rax
movq %rax, 0x68(%rsp)
movq 0x110(%rsp), %rax
movq %rax, 0x70(%rsp)
callq 0x19190
movl %eax, 0xa4(%rsp)
movl %eax, %ecx
movl %ecx, 0x28(%rsp)
subl $-0x1, %eax
je 0x307e7c
jmp 0x307e6f
movl 0x28(%rsp), %eax
testl %eax, %eax
je 0x307ea2
jmp 0x307f2c
movq 0x110(%rsp), %rdi
leaq 0x28b7f0(%rip), %rsi    # 0x59367b
movb $0x0, %al
callq 0xd88c0
movl $0xffffffff, 0xf4(%rsp) # imm = 0xFFFFFFFF
jmp 0x307f9b
movl $0x1, %edi
callq 0x19ec0
movl 0x98(%rsp), %edi
callq 0x308570
xorl %edi, %edi
callq 0x19ec0
movl 0x9c(%rsp), %edi
callq 0x308570
movl 0x9c(%rsp), %edi
callq 0x19ec0
movl 0xa0(%rsp), %edi
callq 0x19ec0
movl 0x94(%rsp), %edi
callq 0x19ec0
movl 0x98(%rsp), %edi
callq 0x19ec0
movq 0x108(%rsp), %rax
movq 0x98(%rax), %rsi
leaq 0x28b798(%rip), %rdi    # 0x5936a9
callq 0x19560
leaq 0x28b77b(%rip), %rdi    # 0x593698
callq 0x19640
movl $0x1, %edi
callq 0x19890
movq 0x110(%rsp), %rdx
leaq 0x665(%rip), %rdi       # 0x3085a0
leaq 0x50(%rsp), %rsi
callq 0x120b50
movq %rax, 0x48(%rsp)
movq 0x110(%rsp), %rdx
leaq 0x817(%rip), %rdi       # 0x308770
leaq 0x50(%rsp), %rsi
callq 0x120b50
movq %rax, 0x40(%rsp)
movq 0x40(%rsp), %rdi
callq 0x120ca0
movq 0x48(%rsp), %rdi
callq 0x120ca0
movq 0x40(%rsp), %rdi
callq 0x121310
movq 0x48(%rsp), %rdi
callq 0x121310
movl 0x60(%rsp), %eax
movl %eax, 0xf4(%rsp)
jmp 0x307f9d
jmp 0x30800c
movq 0x108(%rsp), %rax
movq 0x28(%rax), %rdi
callq 0x16d430
movq %rax, 0x10(%rsp)
movq 0x108(%rsp), %rax
movq 0x28(%rax), %rdi
callq 0x171a90
movq %rax, 0x18(%rsp)
movq 0x108(%rsp), %rax
movq 0x28(%rax), %rdi
callq 0x171b20
movl %eax, 0x24(%rsp)
movq 0x88(%rsp), %rdi
callq 0x11dfa0
movq 0x10(%rsp), %rsi
movq 0x18(%rsp), %rdx
movl 0x24(%rsp), %ecx
movq %rax, %r8
leaq 0x28b6ac(%rip), %rdi    # 0x5936b1
movb $0x0, %al
callq 0x1267d0
movq 0x88(%rsp), %rdi
callq 0x11f560
cmpl $0x0, 0xf4(%rsp)
jne 0x308037
movq 0x108(%rsp), %rdi
callq 0x308860
movl %eax, 0xf4(%rsp)
jmp 0x308039
jmp 0x30803b
movl 0xf4(%rsp), %eax
addq $0x128, %rsp            # imm = 0x128
retq
nopw (%rax,%rax)