// File: /workspace/github_c_makefile_star2_O2/craigbarnes[P]lua-gumbo/lib/parser.c
// Function: adoption_agency_algorithm
static bool adoption_agency_algorithm (
  GumboParser* parser,
  GumboToken* token,
  GumboTag subject
) {
  GumboParserState* state = parser->_parser_state;
  gumbo_debug("Entering adoption agency algorithm.\n");
  // Step 1.
  GumboNode* current_node = get_current_node(parser);
  if (
    current_node->v.element.tag_namespace == GUMBO_NAMESPACE_HTML
    && current_node->v.element.tag == subject
    && -1 == gumbo_vector_index_of (
      &state->_active_formatting_elements,
      current_node
    )
  ) {
    pop_current_node(parser);
    return false;
  }
  // Steps 2-4 & 20:
  for (unsigned int i = 0; i < 8; ++i) {
    // Step 5.
    GumboNode* formatting_node = NULL;
    int formatting_node_in_open_elements = -1;
    for (int j = state->_active_formatting_elements.length; --j >= 0;) {
      GumboNode* current_node = state->_active_formatting_elements.data[j];
      if (current_node == &kActiveFormattingScopeMarker) {
        gumbo_debug("Broke on scope marker; aborting.\n");
        // Last scope marker; abort the algorithm.
        return false;
      }
      if (node_html_tag_is(current_node, subject)) {
        // Found it.
        formatting_node = current_node;
        formatting_node_in_open_elements = gumbo_vector_index_of (
          &state->_open_elements,
          formatting_node
        );
        gumbo_debug (
          "Formatting element of tag %s at %d.\n",
          gumbo_normalized_tagname(subject),
          formatting_node_in_open_elements
        );
        break;
      }
    }
    if (!formatting_node) {
      // No matching tag; not a parse error outright, but fall through to the
      // "any other end tag" clause (which may potentially add a parse error,
      // but not always).
      gumbo_debug("No active formatting elements; aborting.\n");
      return false;
    }

    // Step 6
    if (formatting_node_in_open_elements == -1) {
      gumbo_debug("Formatting node not on stack of open elements.\n");
      parser_add_parse_error(parser, token);
      gumbo_vector_remove (
        formatting_node,
        &state->_active_formatting_elements
      );
      return false;
    }

    // Step 7
    if (!has_an_element_in_scope(parser, formatting_node->v.element.tag)) {
      parser_add_parse_error(parser, token);
      gumbo_debug("Element not in scope.\n");
      return false;
    }

    // Step 8
    if (formatting_node != get_current_node(parser)) {
      parser_add_parse_error(parser, token);  // But continue onwards.
    }
    assert(formatting_node);
    assert(!node_html_tag_is(formatting_node, GUMBO_TAG_HTML));
    assert(!node_html_tag_is(formatting_node, GUMBO_TAG_BODY));

    // Step 9 & 10
    GumboNode* furthest_block = NULL;
    for (
      unsigned int j = formatting_node_in_open_elements;
      j < state->_open_elements.length;
      ++j
    ) {
      assert(j > 0);
      GumboNode* current = state->_open_elements.data[j];
      if (is_special_node(current)) {
        // Step 9.
        furthest_block = current;
        break;
      }
    }
    if (!furthest_block) {
      // Step 10.
      while (get_current_node(parser) != formatting_node) {
        pop_current_node(parser);
      }
      // And the formatting element itself.
      pop_current_node(parser);
      gumbo_vector_remove (
        formatting_node,
        &state->_active_formatting_elements
      );
      return false;
    }
    assert(!node_html_tag_is(furthest_block, GUMBO_TAG_HTML));
    assert(furthest_block);

    // Step 11.
    // Elements may be moved and reparented by this algorithm, so
    // common_ancestor is not necessarily the same as formatting_node->parent.
    GumboNode* common_ancestor = state->_open_elements.data [
      gumbo_vector_index_of(&state->_open_elements, formatting_node) - 1
    ];
    gumbo_debug (
      "Common ancestor tag = %s, furthest block tag = %s.\n",
      gumbo_normalized_tagname(common_ancestor->v.element.tag),
      gumbo_normalized_tagname(furthest_block->v.element.tag)
    );

    // Step 12.
    int bookmark = 1 + gumbo_vector_index_of (
      &state->_active_formatting_elements,
      formatting_node
    );
    gumbo_debug("Bookmark at %d.\n", bookmark);
    // Step 13.
    GumboNode* node = furthest_block;
    GumboNode* last_node = furthest_block;
    // Must be stored explicitly, in case node is removed from the stack of open
    // elements, to handle step 9.4.
    int saved_node_index = gumbo_vector_index_of(&state->_open_elements, node);
    assert(saved_node_index > 0);
    // Step 13.1.
    for (int j = 0;;) {
      // Step 13.2.
      ++j;
      // Step 13.3.
      int node_index = gumbo_vector_index_of(&state->_open_elements, node);
      gumbo_debug (
        "Current index: %d, last index: %d.\n",
        node_index,
        saved_node_index
      );
      if (node_index == -1) {
        node_index = saved_node_index;
      }
      saved_node_index = --node_index;
      assert(node_index > 0);
      assert((unsigned int) node_index < state->_open_elements.capacity);
      node = state->_open_elements.data[node_index];
      assert(node->parent);
      if (node == formatting_node) {
        // Step 13.4.
        break;
      }
      int formatting_index = gumbo_vector_index_of (
        &state->_active_formatting_elements,
        node
      );
      if (j > 3 && formatting_index != -1) {
        // Step 13.5.
        gumbo_debug("Removing formatting element at %d.\n", formatting_index);
        gumbo_vector_remove_at (
          formatting_index,
          &state->_active_formatting_elements
        );
        // Removing the element shifts all indices over by one, so we may need
        // to move the bookmark.
        if (formatting_index < bookmark) {
          --bookmark;
          gumbo_debug("Moving bookmark to %d.\n", bookmark);
        }
        continue;
      }
      if (formatting_index == -1) {
        // Step 13.6.
        gumbo_vector_remove_at(node_index, &state->_open_elements);
        continue;
      }
      // Step 13.7.
      // "common ancestor as the intended parent" doesn't actually mean insert
      // it into the common ancestor; that happens below.
      node = clone_node(node, GUMBO_INSERTION_ADOPTION_AGENCY_CLONED);
      assert(formatting_index >= 0);
      state->_active_formatting_elements.data[formatting_index] = node;
      assert(node_index >= 0);
      state->_open_elements.data[node_index] = node;
      // Step 13.8.
      if (last_node == furthest_block) {
        bookmark = formatting_index + 1;
        gumbo_debug("Bookmark moved to %d.\n", bookmark);
        assert((unsigned int) bookmark <= state->_active_formatting_elements.length);
      }
      // Step 13.9.
      last_node->parse_flags |= GUMBO_INSERTION_ADOPTION_AGENCY_MOVED;
      remove_from_parent(last_node);
      append_node(node, last_node);
      // Step 13.10.
      last_node = node;
    }  // Step 13.11.

    // Step 14.
    gumbo_debug (
      "Removing %s node from parent ",
      gumbo_normalized_tagname(last_node->v.element.tag)
    );
    remove_from_parent(last_node);
    last_node->parse_flags |= GUMBO_INSERTION_ADOPTION_AGENCY_MOVED;
    InsertionLocation location = get_appropriate_insertion_location (
      parser,
      common_ancestor
    );
    gumbo_debug (
      "and inserting it into %s.\n",
      gumbo_normalized_tagname(location.target->v.element.tag)
    );
    insert_node(last_node, location);

    // Step 15.
    GumboNode* new_formatting_node = clone_node (
      formatting_node,
      GUMBO_INSERTION_ADOPTION_AGENCY_CLONED
    );
    formatting_node->parse_flags |= GUMBO_INSERTION_IMPLICIT_END_TAG;

    // Step 16. Instead of appending nodes one-by-one, we swap the children
    // vector of furthest_block with the empty children of new_formatting_node,
    // reducing memory traffic and allocations. We still have to reset their
    // parent pointers, though.
    GumboVector temp = new_formatting_node->v.element.children;
    new_formatting_node->v.element.children = furthest_block->v.element.children;
    furthest_block->v.element.children = temp;

    temp = new_formatting_node->v.element.children;
    for (unsigned int i = 0; i < temp.length; ++i) {
      GumboNode* child = temp.data[i];
      child->parent = new_formatting_node;
    }

    // Step 17.
    append_node(furthest_block, new_formatting_node);

    // Step 18.
    // If the formatting node was before the bookmark, it may shift over all
    // indices after it, so we need to explicitly find the index and possibly
    // adjust the bookmark.
    int formatting_node_index = gumbo_vector_index_of (
      &state->_active_formatting_elements,
      formatting_node
    );
    assert(formatting_node_index != -1);
    if (formatting_node_index < bookmark) {
      gumbo_debug (
        "Formatting node at %d is before bookmark at %d; decrementing.\n",
        formatting_node_index, bookmark
      );
      --bookmark;
    }
    gumbo_vector_remove_at (
      formatting_node_index,
      &state->_active_formatting_elements
    );
    assert(bookmark >= 0);
    assert((unsigned int) bookmark <= state->_active_formatting_elements.length);
    gumbo_vector_insert_at (
      new_formatting_node,
      bookmark,
      &state->_active_formatting_elements
    );

    // Step 19.
    gumbo_vector_remove(formatting_node, &state->_open_elements);
    int insert_at = 1 + gumbo_vector_index_of (
      &state->_open_elements,
      furthest_block
    );
    assert(insert_at >= 0);
    assert((unsigned int) insert_at <= state->_open_elements.length);
    gumbo_vector_insert_at (
      new_formatting_node,
      insert_at,
      &state->_open_elements
    );
  }  // Step 20.
  return true;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x58, %rsp
movl %edx, %ebp
movq %rsi, 0x28(%rsp)
movq %rdi, %r15
movq 0x18(%rdi), %r14
callq 0x7913
cmpl $0x0, 0x2c(%rax)
jne 0xaea2
cmpl %ebp, 0x28(%rax)
jne 0xaea2
leaq 0x18(%r14), %rdi
movq %rax, %rsi
callq 0x77e1
cmpl $-0x1, %eax
je 0xb2e2
leaq 0x18(%r14), %rcx
leaq 0x8(%r14), %rax
movq %rax, 0x8(%rsp)
xorl %r13d, %r13d
movq %r14, 0x10(%rsp)
cmpl $0x8, %r13d
sete %bl
je 0xb2fd
movq %r13, 0x50(%rsp)
movl 0x20(%r14), %r14d
testl %r14d, %r14d
jle 0xb2ec
movq (%rcx), %rax
movq -0x8(%rax,%r14,8), %r13
leaq 0xcbb3(%rip), %rax      # 0x17a98
cmpq %rax, %r13
je 0xb2ea
movq %rcx, %r12
movq %r13, %rdi
movl %ebp, %esi
callq 0x82b7
movq %r12, %rcx
decq %r14
testb %al, %al
je 0xaecd
movq 0x8(%rsp), %rdi
movq %r13, %rsi
callq 0x77e1
movl %ebp, %edi
movl %eax, %ebp
movl %edi, 0x34(%rsp)
callq 0x730c
testq %r13, %r13
je 0xb2ec
cmpl $-0x1, %ebp
je 0xb301
movl 0x28(%r13), %esi
movq %r15, %rdi
callq 0xabe3
testb %al, %al
je 0xb310
movq %r15, %rdi
callq 0x7913
cmpq %rax, %r13
je 0xaf5f
movq %r15, %rdi
movq 0x28(%rsp), %rsi
callq 0x797d
movq %r13, %rdi
xorl %esi, %esi
callq 0x82b7
testb %al, %al
movq 0x10(%rsp), %r14
jne 0xb3ba
movq %r13, %rdi
pushq $0xa
popq %rsi
callq 0x82b7
testb %al, %al
jne 0xb39b
movl %ebp, %ebx
movl 0x10(%r14), %eax
cmpq %rax, %rbx
jae 0xb2bd
testq %rbx, %rbx
je 0xb31f
movq 0x8(%rsp), %rax
movq (%rax), %rax
movq (%rax,%rbx,8), %rbp
movq %rbp, %rdi
callq 0xb73e
incq %rbx
testb %al, %al
je 0xaf8b
testq %rbp, %rbp
je 0xb2bd
movq %rbp, %rdi
xorl %esi, %esi
callq 0x82b7
testb %al, %al
jne 0xb493
movq %r15, 0x48(%rsp)
movq 0x8(%rsp), %r15
movq (%r15), %rbx
movq %r15, %rdi
movq %r13, %rsi
callq 0x77e1
cltq
movq -0x8(%rbx,%rax,8), %rax
movq %rax, 0x40(%rsp)
movl 0x28(%rax), %edi
callq 0x730c
movl 0x28(%rbp), %edi
callq 0x730c
movq %r15, %rdi
movq %rbp, %rsi
callq 0x77e1
testl %eax, %eax
jle 0xb3d9
movq %rbp, %r14
movl %eax, %ebp
leaq 0x18(%r14), %rax
movq %rax, 0x38(%rsp)
movq %r12, %rdi
movq %r13, %rsi
callq 0x77e1
incl %eax
movl %eax, 0x4(%rsp)
movl $0x0, (%rsp)
movq %r14, 0x20(%rsp)
movq %r14, 0x18(%rsp)
movq %r15, %rdi
movq %r14, %rsi
callq 0x77e1
cmpl $-0x1, %eax
cmovnel %eax, %ebp
cmpl $0x1, %ebp
jle 0xb33e
decl %ebp
movq 0x10(%rsp), %rax
cmpl 0x14(%rax), %ebp
jae 0xb35d
movq (%r15), %rax
movl %ebp, %ebx
movq (%rax,%rbx,8), %r14
cmpq $0x0, 0x8(%r14)
je 0xb37c
cmpq %r13, %r14
je 0xb16f
movq %r12, %rdi
movq %r14, %rsi
callq 0x77e1
movl %eax, %r15d
cmpl $0x3, (%rsp)
jb 0xb0af
cmpl $-0x1, %r15d
jne 0xb0c9
cmpl $-0x1, %r15d
jne 0xb0f3
movl %ebp, %edi
movq 0x8(%rsp), %r15
movq %r15, %rsi
callq 0x7895
incl (%rsp)
jmp 0xb04e
movl %r15d, %edi
movq %r12, %rsi
callq 0x7895
xorl %eax, %eax
movl 0x4(%rsp), %ecx
cmpl %ecx, %r15d
setl %al
subl %eax, %ecx
movl %ecx, 0x4(%rsp)
incl (%rsp)
movq 0x8(%rsp), %r15
jmp 0xb04e
movq %r14, %rdi
movl $0x100, %esi            # imm = 0x100
callq 0xb79c
testl %r15d, %r15d
js 0xb4b2
movq %rax, %r14
movq (%r12), %rax
movl %r15d, %ecx
movq %r14, (%rax,%rcx,8)
movq 0x8(%rsp), %rax
movq (%rax), %rax
movq %r14, (%rax,%rbx,8)
movq 0x20(%rsp), %rbx
cmpq 0x18(%rsp), %rbx
jne 0xb146
movq 0x10(%rsp), %rax
cmpl 0x20(%rax), %r15d
jae 0xb4d1
incl %r15d
movl %r15d, 0x4(%rsp)
incl (%rsp)
orb $0x2, 0x15(%rbx)
movq %rbx, %rdi
callq 0xb8a6
movq %r14, %rdi
movq %rbx, %rsi
callq 0x82fd
movq %r14, 0x20(%rsp)
movq 0x8(%rsp), %r15
jmp 0xb04e
movq 0x20(%rsp), %rbx
movl 0x28(%rbx), %edi
callq 0x730c
movq %rbx, %rdi
callq 0xb8a6
orb $0x2, 0x15(%rbx)
movq 0x48(%rsp), %r15
movq %r15, %rdi
movq 0x40(%rsp), %rsi
callq 0x7fcf
movq %rax, %r14
movl %edx, %ebp
movl 0x28(%rax), %edi
callq 0x730c
movq %rbx, %rdi
movq %r14, %rsi
movl %ebp, %edx
callq 0x80dd
movq %r13, %rdi
movl $0x100, %esi            # imm = 0x100
callq 0xb79c
orb $0x2, 0x14(%r13)
movq %rax, %r14
movups 0x18(%rax), %xmm0
movq 0x38(%rsp), %rax
movups (%rax), %xmm1
movups %xmm1, 0x18(%r14)
movq 0x18(%rsp), %rax
movups %xmm0, 0x18(%rax)
movq 0x18(%r14), %rax
movl 0x20(%r14), %ecx
xorl %edx, %edx
movl 0x34(%rsp), %ebp
cmpq %rdx, %rcx
je 0xb203
movq (%rax,%rdx,8), %rsi
movq %r14, 0x8(%rsi)
incq %rdx
jmp 0xb1f1
movq 0x18(%rsp), %rdi
movq %r14, %rsi
callq 0x82fd
movq %r12, %rbx
movq %r12, %rdi
movq %r13, %rsi
callq 0x77e1
cmpl $-0x1, %eax
je 0xb474
xorl %ecx, %ecx
cmpl 0x4(%rsp), %eax
setl %cl
movl %ecx, (%rsp)
movl %eax, %edi
movq %rbx, %rsi
callq 0x7895
movl 0x4(%rsp), %esi
subl (%rsp), %esi
js 0xb3f8
movq 0x10(%rsp), %rax
cmpl 0x20(%rax), %esi
ja 0xb455
movq %r14, %rdi
movq %r12, %rdx
callq 0x77ff
movq %r13, %rdi
movq 0x8(%rsp), %rbx
movq %rbx, %rsi
callq 0x7874
movq %rbx, %rdi
movq 0x18(%rsp), %rsi
callq 0x77e1
cmpl $-0x2, %eax
jle 0xb417
incl %eax
movq 0x10(%rsp), %rcx
cmpl 0x10(%rcx), %eax
movq 0x50(%rsp), %r13
ja 0xb436
movq %r14, %rdi
movl %eax, %esi
movq 0x8(%rsp), %rdx
callq 0x77ff
incl %r13d
movq 0x10(%rsp), %r14
movq %r12, %rcx
jmp 0xaeb7
movq %r15, %rdi
callq 0x7913
movq %rax, %rbx
movq %r15, %rdi
callq 0xa620
cmpq %r13, %rbx
jne 0xb2bd
movq %r13, %rdi
movq %r12, %rsi
callq 0x7874
jmp 0xb2ea
movq %r15, %rdi
callq 0xa620
xorl %ebx, %ebx
movl %ebx, %eax
addq $0x58, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movb $0x1, %bl
jmp 0xb2ec
movq %r15, %rdi
movq 0x28(%rsp), %rsi
callq 0x797d
jmp 0xb2d5
movq %r15, %rdi
movq 0x28(%rsp), %rsi
callq 0x797d
jmp 0xb2ea
leaq 0xfcdb(%rip), %rdi      # 0x1b001
leaq 0xe573(%rip), %rsi      # 0x198a0
leaq 0xfc20(%rip), %rcx      # 0x1af54
movl $0x822, %edx            # imm = 0x822
callq 0x4100
leaq 0xfcfa(%rip), %rdi      # 0x1b03f
leaq 0xe554(%rip), %rsi      # 0x198a0
leaq 0xfc01(%rip), %rcx      # 0x1af54
movl $0x862, %edx            # imm = 0x862
callq 0x4100
leaq 0xfcea(%rip), %rdi      # 0x1b04e
leaq 0xe535(%rip), %rsi      # 0x198a0
leaq 0xfbe2(%rip), %rcx      # 0x1af54
movl $0x863, %edx            # imm = 0x863
callq 0x4100
leaq 0xfd06(%rip), %rdi      # 0x1b089
leaq 0xe516(%rip), %rsi      # 0x198a0
leaq 0xfbc3(%rip), %rcx      # 0x1af54
movl $0x865, %edx            # imm = 0x865
callq 0x4100
leaq 0xfc2c(%rip), %rdi      # 0x1afce
leaq 0xe4f7(%rip), %rsi      # 0x198a0
leaq 0xfba4(%rip), %rcx      # 0x1af54
movl $0x819, %edx            # imm = 0x819
callq 0x4100
leaq 0xfbda(%rip), %rdi      # 0x1af9b
leaq 0xe4d8(%rip), %rsi      # 0x198a0
leaq 0xfb85(%rip), %rcx      # 0x1af54
movl $0x818, %edx            # imm = 0x818
callq 0x4100
leaq 0xfc59(%rip), %rdi      # 0x1b039
leaq 0xe4b9(%rip), %rsi      # 0x198a0
leaq 0xfb66(%rip), %rcx      # 0x1af54
movl $0x852, %edx            # imm = 0x852
callq 0x4100
leaq 0xfd0e(%rip), %rdi      # 0x1b10d
leaq 0xe49a(%rip), %rsi      # 0x198a0
leaq 0xfb47(%rip), %rcx      # 0x1af54
movl $0x8d5, %edx            # imm = 0x8D5
callq 0x4100
leaq 0xfcfd(%rip), %rdi      # 0x1b11b
leaq 0xe47b(%rip), %rsi      # 0x198a0
leaq 0xfb28(%rip), %rcx      # 0x1af54
movl $0x8e3, %edx            # imm = 0x8E3
callq 0x4100
leaq 0xfced(%rip), %rdi      # 0x1b12a
leaq 0xe45c(%rip), %rsi      # 0x198a0
leaq 0xfb09(%rip), %rcx      # 0x1af54
movl $0x8e4, %edx            # imm = 0x8E4
callq 0x4100
leaq 0xfc50(%rip), %rdi      # 0x1b0ac
leaq 0xe43d(%rip), %rsi      # 0x198a0
leaq 0xfaea(%rip), %rcx      # 0x1af54
movl $0x8d6, %edx            # imm = 0x8D6
callq 0x4100
leaq 0xfc76(%rip), %rdi      # 0x1b0f1
leaq 0xe41e(%rip), %rsi      # 0x198a0
leaq 0xfacb(%rip), %rcx      # 0x1af54
movl $0x8c9, %edx            # imm = 0x8C9
callq 0x4100
leaq 0xfb6d(%rip), %rdi      # 0x1b007
leaq 0xe3ff(%rip), %rsi      # 0x198a0
leaq 0xfaac(%rip), %rcx      # 0x1af54
movl $0x837, %edx            # imm = 0x837
callq 0x4100
leaq 0xfbdd(%rip), %rdi      # 0x1b096
leaq 0xe3e0(%rip), %rsi      # 0x198a0
leaq 0xfa8d(%rip), %rcx      # 0x1af54
movl $0x886, %edx            # imm = 0x886
callq 0x4100
leaq 0xfbd4(%rip), %rdi      # 0x1b0ac
leaq 0xe3c1(%rip), %rsi      # 0x198a0
leaq 0xfa6e(%rip), %rcx      # 0x1af54
movl $0x88e, %edx            # imm = 0x88E
callq 0x4100