// File: /workspace/github_c_makefile_star2_O3/genometools[P]genometools/src/external/tre/lib/tre-compile.c
// Function: tre_expand_ast
static reg_errcode_t
tre_expand_ast(tre_mem_t mem, tre_stack_t *stack, tre_ast_node_t *ast,
	       int *position, tre_tag_direction_t *tag_directions,
	       int *max_depth)
{
  reg_errcode_t status = REG_OK;
  int bottom = tre_stack_num_objects(stack);
  int pos_add = 0;
  int pos_add_total = 0;
  int max_pos = 0;
  /* Current approximate matching parameters. */
  int params[TRE_PARAM_LAST];
  /* Approximate parameter nesting level. */
  int params_depth = 0;
  int iter_depth = 0;
  int i;

  for (i = 0; i < TRE_PARAM_LAST; i++)
    params[i] = TRE_PARAM_DEFAULT;

  STACK_PUSHR(stack, voidptr, ast);
  STACK_PUSHR(stack, int, EXPAND_RECURSE);
  while (status == REG_OK && tre_stack_num_objects(stack) > bottom)
    {
      tre_ast_node_t *node;
      tre_expand_ast_symbol_t symbol;

      if (status != REG_OK)
	break;

      DPRINT(("pos_add %d\n", pos_add));

      symbol = (tre_expand_ast_symbol_t)tre_stack_pop_int(stack);
      node = tre_stack_pop_voidptr(stack);
      switch (symbol)
	{
	case EXPAND_RECURSE:
	  switch (node->type)
	    {
	    case LITERAL:
	      {
		tre_literal_t *lit= node->obj;
		if (!(IS_SPECIAL(lit)) || IS_BACKREF(lit))
		  {
		    lit->position += pos_add;
		    if (lit->position > max_pos)
		      max_pos = lit->position;
		  }
		break;
	      }
	    case UNION:
	      {
		tre_union_t *uni = node->obj;
		STACK_PUSHX(stack, voidptr, uni->right);
		STACK_PUSHX(stack, int, EXPAND_RECURSE);
		STACK_PUSHX(stack, voidptr, uni->left);
		STACK_PUSHX(stack, int, EXPAND_RECURSE);
		break;
	      }
	    case CATENATION:
	      {
		tre_catenation_t *cat = node->obj;
		STACK_PUSHX(stack, voidptr, cat->right);
		STACK_PUSHX(stack, int, EXPAND_RECURSE);
		STACK_PUSHX(stack, voidptr, cat->left);
		STACK_PUSHX(stack, int, EXPAND_RECURSE);
		break;
	      }
	    case ITERATION:
	      {
		tre_iteration_t *iter = node->obj;
		STACK_PUSHX(stack, int, pos_add);
		STACK_PUSHX(stack, voidptr, node);
		STACK_PUSHX(stack, int, EXPAND_AFTER_ITER);
		STACK_PUSHX(stack, voidptr, iter->arg);
		STACK_PUSHX(stack, int, EXPAND_RECURSE);
		/* If we are going to expand this node at EXPAND_AFTER_ITER
		   then don't increase the `pos' fields of the nodes now, it
		   will get done when expanding. */
		if (iter->min > 1 || iter->max > 1)
		  pos_add = 0;
		iter_depth++;
		DPRINT(("iter\n"));
		break;
	      }
	    default:
	      assert(0);
	      break;
	    }
	  break;
	case EXPAND_AFTER_ITER:
	  {
	    tre_iteration_t *iter = node->obj;
	    int pos_add_last;
	    pos_add = tre_stack_pop_int(stack);
	    pos_add_last = pos_add;
	    if (iter->min > 1 || iter->max > 1)
	      {
		tre_ast_node_t *seq1 = NULL, *seq2 = NULL;
		int j;
		int pos_add_save = pos_add;

		/* Create a catenated sequence of copies of the node. */
		for (j = 0; j < iter->min; j++)
		  {
		    tre_ast_node_t *copy;
		    /* Remove tags from all but the last copy. */
		    int flags = ((j + 1 < iter->min)
				 ? COPY_REMOVE_TAGS
				 : COPY_MAXIMIZE_FIRST_TAG);
		    DPRINT(("  pos_add %d\n", pos_add));
		    pos_add_save = pos_add;
		    status = tre_copy_ast(mem, stack, iter->arg, flags,
					  &pos_add, tag_directions, &copy,
					  &max_pos);
		    if (status != REG_OK)
		      return status;
		    if (seq1 != NULL)
		      seq1 = tre_ast_new_catenation(mem, seq1, copy);
		    else
		      seq1 = copy;
		    if (seq1 == NULL)
		      return REG_ESPACE;
		  }

		if (iter->max == -1)
		  {
		    /* No upper limit. */
		    pos_add_save = pos_add;
		    status = tre_copy_ast(mem, stack, iter->arg, 0,
					  &pos_add, NULL, &seq2, &max_pos);
		    if (status != REG_OK)
		      return status;
		    seq2 = tre_ast_new_iter(mem, seq2, 0, -1, 0);
		    if (seq2 == NULL)
		      return REG_ESPACE;
		  }
		else
		  {
		    for (j = iter->min; j < iter->max; j++)
		      {
			tre_ast_node_t *tmp, *copy;
			pos_add_save = pos_add;
			status = tre_copy_ast(mem, stack, iter->arg, 0,
					      &pos_add, NULL, &copy, &max_pos);
			if (status != REG_OK)
			  return status;
			if (seq2 != NULL)
			  seq2 = tre_ast_new_catenation(mem, copy, seq2);
			else
			  seq2 = copy;
			if (seq2 == NULL)
			  return REG_ESPACE;
			tmp = tre_ast_new_literal(mem, EMPTY, -1, -1);
			if (tmp == NULL)
			  return REG_ESPACE;
			seq2 = tre_ast_new_union(mem, tmp, seq2);
			if (seq2 == NULL)
			  return REG_ESPACE;
		      }
		  }

		pos_add = pos_add_save;
		if (seq1 == NULL)
		  seq1 = seq2;
		else if (seq2 != NULL)
		  seq1 = tre_ast_new_catenation(mem, seq1, seq2);
		if (seq1 == NULL)
		  return REG_ESPACE;
		node->obj = seq1->obj;
		node->type = seq1->type;
	      }

	    iter_depth--;
	    pos_add_total += pos_add - pos_add_last;
	    if (iter_depth == 0)
	      pos_add = pos_add_total;

	    /* If approximate parameters are specified, surround the result
	       with two parameter setting nodes.  The one on the left sets
	       the specified parameters, and the one on the right restores
	       the old parameters. */
	    if (iter->params)
	      {
		tre_ast_node_t *tmp_l, *tmp_r, *tmp_node, *node_copy;
		int *old_params;

		tmp_l = tre_ast_new_literal(mem, PARAMETER, 0, -1);
		if (!tmp_l)
		  return REG_ESPACE;
		((tre_literal_t *)tmp_l->obj)->u.params = iter->params;
		iter->params[TRE_PARAM_DEPTH] = params_depth + 1;
		tmp_r = tre_ast_new_literal(mem, PARAMETER, 0, -1);
		if (!tmp_r)
		  return REG_ESPACE;
		old_params = tre_mem_alloc(mem, sizeof(*old_params)
					   * TRE_PARAM_LAST);
		if (!old_params)
		  return REG_ESPACE;
		for (i = 0; i < TRE_PARAM_LAST; i++)
		  old_params[i] = params[i];
		((tre_literal_t *)tmp_r->obj)->u.params = old_params;
		old_params[TRE_PARAM_DEPTH] = params_depth;
		/* XXX - this is the only place where ast_new_node is
		   needed -- should be moved inside AST module. */
		node_copy = tre_ast_new_node(mem, ITERATION,
					     sizeof(tre_iteration_t));
		if (!node_copy)
		  return REG_ESPACE;
		node_copy->obj = node->obj;
		tmp_node = tre_ast_new_catenation(mem, tmp_l, node_copy);
		if (!tmp_node)
		  return REG_ESPACE;
		tmp_node = tre_ast_new_catenation(mem, tmp_node, tmp_r);
		if (!tmp_node)
		  return REG_ESPACE;
		/* Replace the contents of `node' with `tmp_node'. */
		memcpy(node, tmp_node, sizeof(*node));
		node->obj = tmp_node->obj;
		node->type = tmp_node->type;
		params_depth++;
		if (params_depth > *max_depth)
		  *max_depth = params_depth;
	      }
	    break;
	  }
	default:
	  assert(0);
	  break;
	}
    }

  *position += pos_add_total;

  /* `max_pos' should never be larger than `*position' if the above
     code works, but just an extra safeguard let's make sure
     `*position' is set large enough so enough memory will be
     allocated for the transition table. */
  if (max_pos > *position)
    *position = max_pos;

#ifdef TRE_DEBUG
  DPRINT(("Expanded AST:\n"));
  tre_ast_print(ast);
  DPRINT(("*position %d, max_pos %d\n", *position, max_pos));
#endif

  return status;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xa8, %rsp
movq %r9, %r13
movq %r8, 0x40(%rsp)
movq %rcx, %r15
movq %rdx, %rbx
movq %rsi, %r12
movq %rdi, %r14
movq %rsi, %rdi
callq 0x970a3
movl %eax, %ebp
movl $0x0, 0x14(%rsp)
movdqa 0x5c432(%rip), %xmm0    # 0xed0f0
movl $0x1, %eax
movdqa 0x5c435(%rip), %xmm1    # 0xed100
movdqa 0x6638d(%rip), %xmm2    # 0xf7060
pshufd $0xf5, %xmm2, %xmm3     # xmm3 = xmm2[1,1,3,3]
movdqa 0x5c450(%rip), %xmm4    # 0xed130
movdqa %xmm0, %xmm5
pxor %xmm1, %xmm5
movdqa %xmm2, %xmm6
pcmpgtd %xmm5, %xmm6
pshufd $0xf5, %xmm5, %xmm5     # xmm5 = xmm5[1,1,3,3]
pcmpeqd %xmm3, %xmm5
pand %xmm6, %xmm5
movd %xmm5, %ecx
testb $0x1, %cl
je 0x90d0e
movl $0xfffffffe, 0x7c(%rsp,%rax,4) # imm = 0xFFFFFFFE
pextrw $0x4, %xmm5, %ecx
testb $0x1, %cl
je 0x90d23
movl $0xfffffffe, 0x80(%rsp,%rax,4) # imm = 0xFFFFFFFE
paddq %xmm4, %xmm0
addq $0x2, %rax
cmpq $0xb, %rax
jne 0x90ce0
movq %r14, 0x28(%rsp)
movq %r12, %rdi
movq %rbx, %rsi
callq 0x97147
testl %eax, %eax
jne 0x90d55
xorl %ebx, %ebx
movq %r12, %rdi
xorl %esi, %esi
callq 0x970a7
testl %eax, %eax
je 0x90d6d
movl %eax, %r14d
movl %r14d, %eax
addq $0xa8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl %ebp, 0x6c(%rsp)
movq %r15, 0x70(%rsp)
movl $0x0, 0x18(%rsp)
movl $0x0, 0x34(%rsp)
movq $0x0, 0x50(%rsp)
movl $0x0, 0x3c(%rsp)
movq 0x40(%rsp), %r15
movq 0x28(%rsp), %r14
movq %r13, 0x78(%rsp)
movq %r12, 0x20(%rsp)
movq %r12, %rdi
callq 0x970a3
cmpl 0x6c(%rsp), %eax
jle 0x9136a
movq %rbx, 0x8(%rsp)
movq %r12, %rdi
callq 0x9714c
movl %eax, %ebx
movq %r12, %rdi
callq 0x97160
movq %rax, %rbp
cmpl $0x1, %ebx
je 0x90e4f
testl %ebx, %ebx
jne 0x9138a
movl (%rbp), %eax
cmpq $0x3, %rax
ja 0x913a9
leaq 0x661e8(%rip), %rcx     # 0xf6fe0
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq 0x8(%rbp), %rbx
movq 0x8(%rbx), %rsi
movq %r12, %rdi
callq 0x97147
testl %eax, %eax
jne 0x91366
movq %r12, %rdi
xorl %esi, %esi
callq 0x970a7
testl %eax, %eax
jne 0x91366
movq (%rbx), %rsi
movq %r12, %rdi
callq 0x97147
testl %eax, %eax
jne 0x91366
movq %r12, %rdi
xorl %esi, %esi
callq 0x970a7
movl %eax, %ebp
jmp 0x910ec
movq 0x8(%rbp), %rbx
movq %r12, %rdi
callq 0x9714c
movq %rbx, %rdx
movl %eax, %r13d
movl %eax, 0x4(%rsp)
movl 0x8(%rbx), %r12d
cmpl $0x2, %r12d
movq %rbx, 0x18(%rsp)
movq %rbp, 0x58(%rsp)
jl 0x90f10
movq $0x0, 0x48(%rsp)
movl %r13d, 0x8(%rsp)
xorl %ebx, %ebx
xorl %ebp, %ebp
incl %ebx
xorl %ecx, %ecx
cmpl %r12d, %ebx
setge %cl
incl %ecx
movl 0x4(%rsp), %r13d
movq (%rdx), %rdx
movq %r14, %rdi
movq 0x20(%rsp), %rsi
leaq 0x4(%rsp), %r8
movq %r15, %r9
leaq 0x14(%rsp), %rax
pushq %rax
leaq 0x68(%rsp), %rax
pushq %rax
callq 0x91e94
addq $0x10, %rsp
testl %eax, %eax
jne 0x90d55
movq 0x60(%rsp), %rdx
testq %rbp, %rbp
je 0x90eef
movq 0x28(%rsp), %r14
movq %r14, %rdi
movq %rbp, %rsi
callq 0xb1dba
movq %rax, %rbp
jmp 0x90ef7
movq %rdx, %rbp
movq 0x28(%rsp), %r14
testq %rbp, %rbp
movq 0x18(%rsp), %rdx
je 0x9135b
movl 0x8(%rdx), %r12d
cmpl %r12d, %ebx
jl 0x90e8f
jmp 0x90f34
cmpl $0x2, 0xc(%rdx)
jl 0x91012
movq $0x0, 0x48(%rsp)
cmpl $0x1, %r12d
je 0x90e86
xorl %ebp, %ebp
movl %r13d, 0x8(%rsp)
movl 0xc(%rdx), %eax
cmpl $-0x1, %eax
je 0x910f6
xorl %r15d, %r15d
cmpl %eax, %r12d
jge 0x91003
movl 0x4(%rsp), %r13d
movq (%rdx), %rdx
movq %r14, %rdi
movq 0x20(%rsp), %rsi
xorl %ecx, %ecx
leaq 0x4(%rsp), %r8
xorl %r9d, %r9d
leaq 0x14(%rsp), %rax
pushq %rax
leaq 0x68(%rsp), %rax
pushq %rax
callq 0x91e94
addq $0x10, %rsp
testl %eax, %eax
jne 0x90d55
movq 0x60(%rsp), %rbx
testq %r15, %r15
je 0x90fa0
movq 0x28(%rsp), %rdi
movq %rbx, %rsi
movq %r15, %rdx
callq 0xb1dba
movq %rax, %rbx
movl $0xc, %r14d
testq %rbx, %rbx
je 0x90d58
movq 0x28(%rsp), %r15
movq %r15, %rdi
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
movl $0xffffffff, %ecx       # imm = 0xFFFFFFFF
callq 0xb1cf6
testq %rax, %rax
je 0x90d58
movq %r15, %rdi
movq %rax, %rsi
movq %rbx, %rdx
callq 0xb1d7f
testq %rax, %rax
je 0x9135b
movq %r15, %r14
incl %r12d
movq 0x18(%rsp), %rdx
cmpl 0xc(%rdx), %r12d
movq %rax, %r15
jl 0x90f4c
movq %r15, 0x48(%rsp)
movq 0x20(%rsp), %r12
jmp 0x91158
movl %r13d, %ebx
movq 0x20(%rsp), %r12
jmp 0x911ae
movq 0x8(%rbp), %rax
movq (%rax), %rcx
testq %rcx, %rcx
sets %dl
cmpq $-0x4, %rcx
setne %cl
xorl %ebp, %ebp
testb %cl, %dl
jne 0x910ec
movl 0x10(%rax), %ecx
movq 0x8(%rsp), %rbx
addl %ebx, %ecx
movl %ecx, 0x10(%rax)
movl 0x14(%rsp), %eax
cmpl %eax, %ecx
cmovlel %eax, %ecx
movl %ecx, 0x14(%rsp)
jmp 0x91324
movq 0x8(%rbp), %rbx
movq %r12, %rdi
movl 0x18(%rsp), %esi
callq 0x970a7
testl %eax, %eax
jne 0x91366
movq %rbp, %rsi
movq %r12, %rdi
callq 0x97147
testl %eax, %eax
jne 0x91366
movq %r12, %rdi
movl $0x1, %esi
callq 0x970a7
testl %eax, %eax
jne 0x91366
movq (%rbx), %rsi
movq %r12, %rdi
callq 0x97147
testl %eax, %eax
jne 0x91366
movq %r12, %rdi
xorl %esi, %esi
callq 0x970a7
testl %eax, %eax
jne 0x91366
cmpl $0x1, 0x8(%rbx)
jg 0x910cd
cmpl $0x2, 0xc(%rbx)
jl 0x910e6
movl $0x0, 0x4(%rsp)
movq $0x0, 0x8(%rsp)
movl $0x0, 0x18(%rsp)
incl 0x3c(%rsp)
xorl %ebp, %ebp
movq 0x8(%rsp), %rbx
jmp 0x91351
movl 0x4(%rsp), %r13d
movq (%rdx), %rdx
movq %r14, %rdi
movq 0x20(%rsp), %r12
movq %r12, %rsi
xorl %ecx, %ecx
leaq 0x4(%rsp), %r8
xorl %r9d, %r9d
leaq 0x14(%rsp), %rax
pushq %rax
leaq 0x50(%rsp), %rax
pushq %rax
callq 0x91e94
addq $0x10, %rsp
testl %eax, %eax
jne 0x90d55
movq 0x48(%rsp), %rsi
movq %r14, %rdi
xorl %edx, %edx
movl $0xffffffff, %ecx       # imm = 0xFFFFFFFF
xorl %r8d, %r8d
callq 0xb1d2b
movq %rax, %r15
testq %rax, %rax
movq 0x18(%rsp), %rdx
je 0x9135b
movq %r13, %rbx
movl %ebx, 0x4(%rsp)
testq %rbp, %rbp
je 0x91186
testq %r15, %r15
movl 0x8(%rsp), %r13d
je 0x91197
movq %r14, %rdi
movq %rbp, %rsi
movq %r15, %rdx
callq 0xb1dba
movq 0x18(%rsp), %rdx
movq %rax, %r15
jmp 0x9118b
movl 0x8(%rsp), %r13d
movq %r15, %rbp
testq %r15, %r15
je 0x9135b
movq 0x8(%rbp), %rax
movq 0x58(%rsp), %rcx
movq %rax, 0x8(%rcx)
movl (%rbp), %eax
movl %eax, (%rcx)
movq 0x40(%rsp), %r15
movl %ebx, %eax
subl %r13d, %eax
movl 0x34(%rsp), %ecx
addl %eax, %ecx
decl 0x3c(%rsp)
movl %ecx, 0x34(%rsp)
cmovel %ecx, %ebx
movl %ebx, 0x4(%rsp)
xorl %ebp, %ebp
cmpq $0x0, 0x18(%rdx)
je 0x91324
movq %r14, %rdi
movl $0xfffffffb, %esi       # imm = 0xFFFFFFFB
xorl %edx, %edx
movl $0xffffffff, %ecx       # imm = 0xFFFFFFFF
callq 0xb1cf6
movq %r14, %r12
movl $0xc, %r14d
testq %rax, %rax
je 0x90d58
movq %rax, %r15
movq %rbx, 0x8(%rsp)
movq 0x18(%rsp), %rax
movq 0x18(%rax), %rax
movq 0x8(%r15), %rcx
movq %rax, 0x18(%rcx)
movq 0x50(%rsp), %r13
leal 0x1(%r13), %ecx
movl %ecx, 0x38(%rsp)
movl %ecx, 0x20(%rax)
movq %r12, %rdi
movl $0xfffffffb, %esi       # imm = 0xFFFFFFFB
xorl %edx, %edx
movl $0xffffffff, %ecx       # imm = 0xFFFFFFFF
callq 0xb1cf6
testq %rax, %rax
je 0x90d58
movq %rax, %rbx
movl $0x24, %r8d
movq %r12, %rdi
xorl %esi, %esi
xorl %edx, %edx
xorl %ecx, %ecx
callq 0x95072
testq %rax, %rax
je 0x90d58
movaps 0x80(%rsp), %xmm0
movaps 0x90(%rsp), %xmm1
movups %xmm1, 0x10(%rax)
movups %xmm0, (%rax)
movq 0x8(%rbx), %rcx
movq %rax, 0x18(%rcx)
movl %r13d, 0x20(%rax)
movl $0x20, %edx
movq %r12, %rdi
movl $0x2, %esi
callq 0xb1c88
testq %rax, %rax
je 0x90d58
movq 0x58(%rsp), %rcx
movq 0x8(%rcx), %rcx
movq %rcx, 0x8(%rax)
movq %r12, %rdi
movq %r15, %rsi
movq %rax, %rdx
callq 0xb1dba
testq %rax, %rax
je 0x90d58
movq %r12, %rdi
movq %rax, %rsi
movq %rbx, %rdx
callq 0xb1dba
testq %rax, %rax
je 0x90d58
movdqu (%rax), %xmm0
movdqu 0x10(%rax), %xmm1
movdqu 0x20(%rax), %xmm2
movq 0x58(%rsp), %rdx
movdqu %xmm2, 0x20(%rdx)
movdqu %xmm1, 0x10(%rdx)
movdqu %xmm0, (%rdx)
movq 0x8(%rax), %rcx
movq %rcx, 0x8(%rdx)
movl (%rax), %eax
movl %eax, (%rdx)
movq %r13, %rax
movq 0x78(%rsp), %r13
cmpl (%r13), %eax
jge 0x9132a
movq 0x8(%rsp), %rbx
movl %ebx, 0x18(%rsp)
movl 0x38(%rsp), %eax
jmp 0x9133d
movl %ebx, 0x18(%rsp)
jmp 0x91351
movl 0x38(%rsp), %ecx
movl %ecx, (%r13)
movq 0x8(%rsp), %rbx
movl %ebx, 0x18(%rsp)
movl %ecx, %eax
movq %rax, 0x50(%rsp)
movq 0x40(%rsp), %r15
movq 0x20(%rsp), %r12
movq 0x28(%rsp), %r14
testl %ebp, %ebp
je 0x90dab
jmp 0x9136c
movl $0xc, %r14d
jmp 0x90d58
movl %eax, %ebp
jmp 0x9136c
xorl %ebp, %ebp
movq 0x70(%rsp), %rcx
movl 0x34(%rsp), %edx
addl (%rcx), %edx
movl 0x14(%rsp), %eax
cmpl %edx, %eax
cmovgl %eax, %edx
movl %edx, (%rcx)
movl %ebp, %r14d
jmp 0x90d58
leaq 0x60f4b(%rip), %rdi     # 0xf22dc
leaq 0x65ceb(%rip), %rsi     # 0xf7083
leaq 0x65d86(%rip), %rcx     # 0xf7125
movl $0x403, %edx            # imm = 0x403
callq 0xb400
leaq 0x60f2c(%rip), %rdi     # 0xf22dc
leaq 0x65ccc(%rip), %rsi     # 0xf7083
leaq 0x65d67(%rip), %rcx     # 0xf7125
movl $0x376, %edx            # imm = 0x376
callq 0xb400