// File: /workspace/github_c_makefile_star2_O3/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 0x814d
movq %rsi, %r12
testq %rsi, %rsi
je 0x816c
movq %rdi, %r15
movq (%rdi), %rax
xorl %ebx, %ebx
testq %rax, %rax
je 0x8140
xorl %r13d, %r13d
movq %rax, %r14
movq (%rax), %rsi
movq %r12, %rdi
callq *0x8(%r15)
testl %eax, %eax
js 0x80b7
movl $0x10, %eax
jne 0x80bc
jmp 0x80ca
movl $0x8, %eax
movq (%r14,%rax), %rax
movq %r14, %r13
testq %rax, %rax
jne 0x809d
jmp 0x8140
movq (%r14), %rbx
movq 0x8(%r14), %rax
testq %rax, %rax
je 0x80f9
movq 0x10(%r14), %rcx
testq %rcx, %rcx
je 0x8111
movq %r14, %rax
movq %rax, %r13
movq %rcx, %rax
movq 0x8(%rcx), %rcx
testq %rcx, %rcx
jne 0x80e2
movq (%rax), %rcx
movq %rcx, (%r14)
jmp 0x8101
testq %r13, %r13
je 0x8131
movq %r14, %rax
movq 0x10(%rax), %rcx
cmpq %rax, 0x8(%r13)
je 0x8128
movq %rcx, 0x10(%r13)
jmp 0x812c
testq %r13, %r13
je 0x8135
leaq 0x8(%r13), %rcx
leaq 0x10(%r13), %r15
cmpq %r14, 0x8(%r13)
cmoveq %rcx, %r15
jmp 0x8135
movq %rcx, 0x8(%r13)
movq %rax, %r14
jmp 0x8138
movq 0x10(%r14), %rax
movq %rax, (%r15)
movq %r14, %rdi
callq 0x1120
movq %rbx, %rax
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
retq
leaq 0x612f(%rip), %rdi      # 0xe283
leaq 0x60b2(%rip), %rsi      # 0xe20d
leaq 0x6309(%rip), %rcx      # 0xe46b
movl $0x223, %edx            # imm = 0x223
callq 0x1080
leaq 0x618f(%rip), %rdi      # 0xe302
leaq 0x6093(%rip), %rsi      # 0xe20d
leaq 0x62ea(%rip), %rcx      # 0xe46b
movl $0x224, %edx            # imm = 0x224
callq 0x1080