// File: /workspace/github_c_makefile_star2_O3/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 $0x68, %rsp
movl %edx, %ebp
movq %rsi, 0x30(%rsp)
movq %rdi, %r14
movq 0x18(%rdi), %r13
callq 0x7d33
cmpl $0x0, 0x2c(%rax)
jne 0xb9e2
cmpl %ebp, 0x28(%rax)
jne 0xb9e2
leaq 0x18(%r13), %rdi
movq %rax, %rsi
callq 0x7bea
cmpl $-0x1, %eax
je 0xbe58
leaq 0x18(%r13), %r15
leaq 0x8(%r13), %rax
movq %rax, (%rsp)
xorl %r12d, %r12d
movq %r13, 0x10(%rsp)
movq %r12, 0x60(%rsp)
movl 0x20(%r13), %ebx
leaq 0xe122(%rip), %r12      # 0x19b28
testl %ebx, %ebx
jle 0xbe60
movq (%r15), %rax
movq -0x8(%rax,%rbx,8), %r13
cmpq %r12, %r13
je 0xbe60
movq %r13, %rdi
xorl %esi, %esi
movl %ebp, %edx
callq 0x8739
decq %rbx
testb %al, %al
je 0xba06
movq (%rsp), %rdi
movq %r13, %rsi
callq 0x7bea
movl %eax, %ebx
movl %ebp, %edi
callq 0x7694
testq %r13, %r13
setne %al
je 0xbe60
cmpl $-0x1, %ebx
je 0xbe71
movl %eax, 0x40(%rsp)
movl 0x28(%r13), %eax
movq 0x18(%r14), %rdi
movl %eax, 0x44(%rsp)
movl $0x1, %esi
leaq 0x44(%rsp), %rdx
xorl %ecx, %ecx
leaq 0xec11(%rip), %r8       # 0x1a690
callq 0xb40a
testb %al, %al
je 0xbe80
movq %r14, %rdi
callq 0x7d33
cmpq %rax, %r13
je 0xbaa6
movq %r14, %rdi
movq 0x30(%rsp), %rsi
callq 0x7d9d
movq %r13, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x8739
testb %al, %al
jne 0xbf68
movq %r13, %rdi
xorl %esi, %esi
movl $0xa, %edx
callq 0x8739
testb %al, %al
jne 0xbf49
movq 0x10(%rsp), %rax
cmpl 0x10(%rax), %ebx
jae 0xbe36
movl %ebx, %ebx
testq %rbx, %rbx
je 0xbe8f
movq (%rsp), %rax
movq (%rax), %rax
movq (%rax,%rbx,8), %r12
movq %r12, %rdi
callq 0xc299
testb %al, %al
jne 0xbb16
incq %rbx
movq 0x10(%rsp), %rax
movl 0x10(%rax), %eax
cmpq %rax, %rbx
jb 0xbae1
jmp 0xbe36
testq %r12, %r12
je 0xbe36
movl %ebp, 0x3c(%rsp)
movq %r12, %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x8739
testb %al, %al
jne 0xbfa6
movq %r15, 0x18(%rsp)
movq %r14, 0x58(%rsp)
movq (%rsp), %r14
movq (%r14), %rbx
movq %r14, %rdi
movq %r13, %rsi
callq 0x7bea
cltq
movq -0x8(%rbx,%rax,8), %rbx
movl 0x28(%rbx), %edi
callq 0x7694
movl 0x28(%r12), %edi
callq 0x7694
movq %r14, %rdi
movq %r12, 0x20(%rsp)
movq %r12, %rsi
callq 0x7bea
testl %eax, %eax
jle 0xbf87
movl %eax, %ebp
movq %rbx, 0x50(%rsp)
cmpl $0x1, %eax
je 0xbeec
movq 0x20(%rsp), %rbx
leaq 0x18(%rbx), %rax
movq %rax, 0x48(%rsp)
movq 0x18(%rsp), %rdi
movq %r13, %rsi
callq 0x7bea
incl %eax
movl %eax, 0xc(%rsp)
xorl %r12d, %r12d
movq %rbx, 0x28(%rsp)
decl %ebp
movq 0x10(%rsp), %rax
cmpl 0x14(%rax), %ebp
jae 0xbeae
movq (%rsp), %rax
movq (%rax), %rax
movl %ebp, %r15d
movq (%rax,%r15,8), %rbx
cmpq $0x0, 0x8(%rbx)
je 0xbecd
cmpq %r13, %rbx
je 0xbcdc
movq 0x18(%rsp), %rdi
movq %rbx, %rsi
callq 0x7bea
movl %eax, %r14d
cmpl $0x3, %r12d
jb 0xbc2f
cmpl $-0x1, %r14d
je 0xbc2f
movl %r14d, %edi
movq 0x18(%rsp), %rsi
callq 0x7cb4
xorl %eax, %eax
movl 0xc(%rsp), %ecx
cmpl %ecx, %r14d
setl %al
subl %eax, %ecx
movl %ecx, 0xc(%rsp)
jmp 0xbcb9
cmpl $-0x1, %r14d
je 0xbcae
movq %rbx, %rdi
movl $0x100, %esi            # imm = 0x100
callq 0xc2dd
testl %r14d, %r14d
js 0xbf0b
movq %rax, %rbx
movq 0x18(%rsp), %rax
movq (%rax), %rax
movl %r14d, %ecx
movq %rbx, (%rax,%rcx,8)
movq (%rsp), %rax
movq (%rax), %rax
movq %rbx, (%rax,%r15,8)
movq 0x28(%rsp), %rdi
cmpq 0x20(%rsp), %rdi
jne 0xbc90
movq 0x10(%rsp), %rax
cmpl 0x20(%rax), %r14d
jae 0xbf2a
incl %r14d
movl %r14d, 0xc(%rsp)
movq 0x28(%rsp), %rdi
orb $0x2, 0x15(%rdi)
movq %rdi, %r14
callq 0xc3f6
movq %rbx, %rdi
movq %r14, %rsi
callq 0x8779
movq %rbx, 0x28(%rsp)
jmp 0xbcb9
movl %ebp, %edi
movq (%rsp), %rsi
callq 0x7cb4
movq (%rsp), %rdi
movq %rbx, %rsi
callq 0x7bea
cmpl $-0x1, %eax
cmovnel %eax, %ebp
incl %r12d
cmpl $0x1, %ebp
jg 0xbbbd
jmp 0xbeec
movq 0x28(%rsp), %r15
movl 0x28(%r15), %edi
callq 0x7694
movq %r15, %rdi
callq 0xc3f6
orb $0x2, 0x15(%r15)
movq 0x58(%rsp), %r14
movq %r14, %rdi
movq 0x50(%rsp), %rsi
callq 0x8437
movq %rax, %rbx
movl %edx, %ebp
movl 0x28(%rax), %edi
callq 0x7694
movq %r15, %rdi
movq %rbx, %rsi
movl %ebp, %edx
callq 0x854d
movq %r13, %rdi
movl $0x100, %esi            # imm = 0x100
callq 0xc2dd
orb $0x2, 0x14(%r13)
movq %rax, %rbx
movups 0x18(%rax), %xmm0
movq 0x48(%rsp), %rax
movups (%rax), %xmm1
movups %xmm1, 0x18(%rbx)
movq 0x20(%rsp), %rdi
movups %xmm0, 0x18(%rdi)
movl 0x20(%rbx), %eax
testq %rax, %rax
je 0xbd6f
movq 0x18(%rbx), %rcx
xorl %edx, %edx
movq (%rcx,%rdx,8), %rsi
movq %rbx, 0x8(%rsi)
incq %rdx
cmpq %rdx, %rax
jne 0xbd5f
movq %rbx, %rsi
callq 0x8779
movq 0x18(%rsp), %r15
movq %r15, %rdi
movq %r13, %rsi
callq 0x7bea
cmpl $-0x1, %eax
je 0xc041
xorl %ebp, %ebp
movl 0xc(%rsp), %r12d
cmpl %r12d, %eax
setl %bpl
movl %eax, %edi
movq %r15, %rsi
callq 0x7cb4
subl %ebp, %r12d
js 0xbfc5
movq 0x10(%rsp), %rax
cmpl 0x20(%rax), %r12d
movl 0x3c(%rsp), %ebp
ja 0xc022
movq %rbx, %rdi
movl %r12d, %esi
movq %r15, %rdx
callq 0x7c0e
movq %r13, %rdi
movq (%rsp), %r13
movq %r13, %rsi
callq 0x7c85
movq %r13, %rdi
movq 0x20(%rsp), %rsi
callq 0x7bea
cmpl $-0x2, %eax
jle 0xbfe4
incl %eax
movq 0x10(%rsp), %r13
cmpl 0x10(%r13), %eax
movq 0x60(%rsp), %r12
ja 0xc003
movq %rbx, %rdi
movl %eax, %esi
movq (%rsp), %rdx
callq 0x7c0e
incl %r12d
cmpl $0x8, %r12d
movl 0x40(%rsp), %eax
jne 0xb9f6
jmp 0xbe62
movq %r14, %rdi
callq 0xaffb
movq %r14, %rdi
callq 0x7d33
cmpq %r13, %rax
jne 0xbe2e
movq %r14, %rdi
callq 0xaffb
movq %r13, %rdi
movq %r15, %rsi
callq 0x7c85
jmp 0xbe60
movq %r14, %rdi
callq 0xaffb
xorl %eax, %eax
addq $0x68, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %r14, %rdi
movq 0x30(%rsp), %rsi
callq 0x7d9d
jmp 0xbe4b
movq %r14, %rdi
movq 0x30(%rsp), %rsi
callq 0x7d9d
jmp 0xbe60
leaq 0x111fb(%rip), %rdi     # 0x1d091
leaq 0xfa93(%rip), %rsi      # 0x1b930
leaq 0x11140(%rip), %rcx     # 0x1cfe4
movl $0x822, %edx            # imm = 0x822
callq 0x4100
leaq 0x11229(%rip), %rdi     # 0x1d0de
leaq 0xfa74(%rip), %rsi      # 0x1b930
leaq 0x11121(%rip), %rcx     # 0x1cfe4
movl $0x863, %edx            # imm = 0x863
callq 0x4100
leaq 0x11245(%rip), %rdi     # 0x1d119
leaq 0xfa55(%rip), %rsi      # 0x1b930
leaq 0x11102(%rip), %rcx     # 0x1cfe4
movl $0x865, %edx            # imm = 0x865
callq 0x4100
leaq 0x111dc(%rip), %rdi     # 0x1d0cf
leaq 0xfa36(%rip), %rsi      # 0x1b930
leaq 0x110e3(%rip), %rcx     # 0x1cfe4
movl $0x862, %edx            # imm = 0x862
callq 0x4100
leaq 0x11214(%rip), %rdi     # 0x1d126
leaq 0xfa17(%rip), %rsi      # 0x1b930
leaq 0x110c4(%rip), %rcx     # 0x1cfe4
movl $0x886, %edx            # imm = 0x886
callq 0x4100
leaq 0x1120b(%rip), %rdi     # 0x1d13c
leaq 0xf9f8(%rip), %rsi      # 0x1b930
leaq 0x110a5(%rip), %rcx     # 0x1cfe4
movl $0x88e, %edx            # imm = 0x88E
callq 0x4100
leaq 0x1110e(%rip), %rdi     # 0x1d05e
leaq 0xf9d9(%rip), %rsi      # 0x1b930
leaq 0x11086(%rip), %rcx     # 0x1cfe4
movl $0x819, %edx            # imm = 0x819
callq 0x4100
leaq 0x110bc(%rip), %rdi     # 0x1d02b
leaq 0xf9ba(%rip), %rsi      # 0x1b930
leaq 0x11067(%rip), %rcx     # 0x1cfe4
movl $0x818, %edx            # imm = 0x818
callq 0x4100
leaq 0x1113b(%rip), %rdi     # 0x1d0c9
leaq 0xf99b(%rip), %rsi      # 0x1b930
leaq 0x11048(%rip), %rcx     # 0x1cfe4
movl $0x852, %edx            # imm = 0x852
callq 0x4100
leaq 0x110ea(%rip), %rdi     # 0x1d097
leaq 0xf97c(%rip), %rsi      # 0x1b930
leaq 0x11029(%rip), %rcx     # 0x1cfe4
movl $0x837, %edx            # imm = 0x837
callq 0x4100
leaq 0x111d1(%rip), %rdi     # 0x1d19d
leaq 0xf95d(%rip), %rsi      # 0x1b930
leaq 0x1100a(%rip), %rcx     # 0x1cfe4
movl $0x8d5, %edx            # imm = 0x8D5
callq 0x4100
leaq 0x111c0(%rip), %rdi     # 0x1d1ab
leaq 0xf93e(%rip), %rsi      # 0x1b930
leaq 0x10feb(%rip), %rcx     # 0x1cfe4
movl $0x8e3, %edx            # imm = 0x8E3
callq 0x4100
leaq 0x111b0(%rip), %rdi     # 0x1d1ba
leaq 0xf91f(%rip), %rsi      # 0x1b930
leaq 0x10fcc(%rip), %rcx     # 0x1cfe4
movl $0x8e4, %edx            # imm = 0x8E4
callq 0x4100
leaq 0x11113(%rip), %rdi     # 0x1d13c
leaq 0xf900(%rip), %rsi      # 0x1b930
leaq 0x10fad(%rip), %rcx     # 0x1cfe4
movl $0x8d6, %edx            # imm = 0x8D6
callq 0x4100
leaq 0x11139(%rip), %rdi     # 0x1d181
leaq 0xf8e1(%rip), %rsi      # 0x1b930
leaq 0x10f8e(%rip), %rcx     # 0x1cfe4
movl $0x8c9, %edx            # imm = 0x8C9
callq 0x4100