// File: /workspace/github_c_makefile_star2_O1/CarlosLunaMota[P]BinaryTrees/BinaryTrees.c
// Function: bs_tree_remove
void *bs_tree_remove(bs_tree *tree, const void *data) {

    bs_node *parent;
    bs_node *node;
    bs_node *old_node;
    void    *old_data;
    int      comp;

    // Sanity Checks:
    assert(tree != NULL);
    assert(data != NULL);

    // Search the node to delete:
    parent   = NULL;
    node     = tree->root;
    while (node != NULL) {

        // Compare data:
        comp = (tree->comp)(data, node->data);

        // Data is smaller:
        if (comp < 0) {
            parent = node;
            node   = node->left;
        }

        // Data is bigger:
        else if (comp > 0) {
            parent = node;
            node   = node->right;
        }

        // We have found the node:
        else {

            old_data = node->data;

            // If node has both subtrees we must do some extra work:
            if (node->left != NULL && node->right != NULL) {

                // Remember the place and keep going down to find the successor
                old_node = node;                // Here we are looking for the
                parent   = node;                // inorder successor of node
                node     = node->right;         // but if we exchange left for
                while (node->left != NULL) {    // right (and viceversa) on
                    parent = node;              // thisblock of code we could
                    node   = node->left;        // implement the equaly valid
                }                               // predecesor version of remove

                // Once we find the "succesor" of "old_node"
                // we just move the data pointer and remove
                // the current "node":
                old_node->data = node->data;
            }

            // At this point we are sure that "node" has, at least,
            // one empty subtree, which greatly simplifies the removal:

            // Easy case 1: node->left is NULL
            if (node->left == NULL) {
                if      (parent       == NULL) { tree->root    = node->right; }
                else if (parent->left == node) { parent->left  = node->right; }
                else                           { parent->right = node->right; }
                free(node);
                return old_data;
            }

            // Easy case 2: node->right is NULL
            else {
                if      (parent       == NULL) { tree->root    = node->left; }
                else if (parent->left == node) { parent->left  = node->left; }
                else                           { parent->right = node->left; }
                free(node);
                return old_data;
            }
        }
    }
    return NULL;
}

// Assembly:
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
testq %rdi, %rdi
je 0x8053
movq %rsi, %r15
testq %rsi, %rsi
je 0x8072
movq %rdi, %r14
movq (%rdi), %rax
xorl %ebx, %ebx
testq %rax, %rax
je 0x803f
xorl %r12d, %r12d
movq %rax, %r13
movq (%rax), %rsi
movq %r15, %rdi
callq *0x8(%r14)
testl %eax, %eax
js 0x7fb3
movl $0x10, %eax
jne 0x7fb8
jmp 0x7fc7
movl $0x8, %eax
movq (%r13,%rax), %rax
movq %r13, %r12
testq %rax, %rax
jne 0x7f99
jmp 0x803f
movq (%r13), %rbx
cmpq $0x0, 0x8(%r13)
je 0x7ff6
movq 0x10(%r13), %rax
testq %rax, %rax
je 0x7ff6
movq %r13, %rdi
movq %rdi, %r12
movq %rax, %rdi
movq 0x8(%rax), %rax
testq %rax, %rax
jne 0x7fde
movq (%rdi), %rax
movq %rax, (%r13)
jmp 0x7ff9
movq %r13, %rdi
movq 0x8(%rdi), %rax
testq %rax, %rax
je 0x801c
testq %r12, %r12
je 0x8037
leaq 0x8(%r12), %rcx
leaq 0x10(%r12), %r14
cmpq %rdi, 0x8(%r12)
cmoveq %rcx, %r14
jmp 0x8037
testq %r12, %r12
je 0x8033
movq 0x10(%rdi), %rax
cmpq %rdi, 0x8(%r12)
je 0x804c
movq %rax, 0x10(%r12)
jmp 0x803a
movq 0x10(%rdi), %rax
movq %rax, (%r14)
callq 0x1120
movq %rbx, %rax
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
retq
movq %rax, 0x8(%r12)
jmp 0x803a
leaq 0x6229(%rip), %rdi      # 0xe283
leaq 0x61ac(%rip), %rsi      # 0xe20d
leaq 0x6403(%rip), %rcx      # 0xe46b
movl $0x223, %edx            # imm = 0x223
callq 0x1080
leaq 0x6289(%rip), %rdi      # 0xe302
leaq 0x618d(%rip), %rsi      # 0xe20d
leaq 0x63e4(%rip), %rcx      # 0xe46b
movl $0x224, %edx            # imm = 0x224
callq 0x1080