// File: /workspace/github_c_makefile_star2_O2/MaoKo[P]FGFX/fgfl/src/regex_node.c
// Function: remove_useless_epsilon
bool
remove_useless_epsilon(regex_node_t* root) {
    if (!root)
        { return (false); }

    switch (root->kind_ast) {
        case AST_DOT:
        case AST_SYMBOL:
        case AST_CLASS:
            return (false);

        case AST_EPSILON:
            return (true);

        case AST_UNION:
            if ((remove_useless_epsilon(root->left))
                    && (remove_useless_epsilon(root->right))) {

                del_regex_node(root->left);
                del_regex_node(root->right);

                root->kind_ast = AST_EPSILON;
                return (true);
            }
            else
                { return (false); }

        case AST_LOOK:
        case AST_CONCAT: ;
            bool left = remove_useless_epsilon(root->left);
            bool right = remove_useless_epsilon(root->right);

            if (left || right) {
                if (left)
                    { del_regex_node(root->left); }
                if (right)
                    { del_regex_node(root->right); }

                if (left && right) {
                    root->kind_ast = AST_EPSILON;
                    return (true);
                }
                else {
                    regex_node_t* src_node = NULL_NODE;
                    if (!left)
                        { src_node = root->left; }
                    else
                        { src_node = root->right; }
                    memcpy(root, src_node, sizeof(*src_node));
                    FREE(src_node);
                }
            }
            return (false);

        case AST_STAR:
        case AST_QUES:
        case AST_PLUS:
        case AST_TILDE:
        case AST_OPTION:
            if (remove_useless_epsilon(root->left)) {
                del_regex_node(root->left);
                root->kind_ast = AST_EPSILON;
                return (true);
            }
            else
                { return (false); }

        default:
            return (false);
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %rbx
pushq %rax
testq %rdi, %rdi
je 0x78e4
movq %rdi, %rbx
movl (%rdi), %ecx
xorl %eax, %eax
cmpq $0xb, %rcx
ja 0x78e6
leaq 0x4471(%rip), %rdx      # 0xbc98
movslq (%rdx,%rcx,4), %rcx
addq %rdx, %rcx
jmpq *%rcx
movq 0x10(%rbx), %rdi
callq 0x77fc
testb %al, %al
je 0x78e4
movq 0x10(%rbx), %rdi
callq 0x751f
movl $0xb, (%rbx)
movb $0x1, %al
jmp 0x78e6
movq 0x10(%rbx), %rdi
callq 0x77fc
movl %eax, %r14d
movq 0x18(%rbx), %rdi
callq 0x77fc
movl %eax, %r15d
movl %r14d, %eax
orb %r15b, %al
cmpb $0x1, %al
jne 0x78e4
testb %r14b, %r14b
je 0x7887
movq 0x10(%rbx), %rdi
callq 0x751f
testb %r15b, %r15b
je 0x789a
movq 0x18(%rbx), %rdi
callq 0x751f
testb %r14b, %r14b
jne 0x784a
movzbl %r14b, %eax
movq 0x10(%rbx,%rax,8), %rdi
movups (%rdi), %xmm0
movups 0x10(%rdi), %xmm1
movups %xmm1, 0x10(%rbx)
movups %xmm0, (%rbx)
callq 0x2040
jmp 0x78e4
movq 0x10(%rbx), %rdi
callq 0x77fc
testb %al, %al
je 0x78e4
movq 0x18(%rbx), %rdi
callq 0x77fc
testb %al, %al
je 0x78e4
movq 0x10(%rbx), %rdi
callq 0x751f
movq 0x18(%rbx), %rdi
jmp 0x7845
xorl %eax, %eax
addq $0x8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq