// File: /workspace/github_c_makefile_star2_O2/OhYee[P]computer_application_programming_experiment/utils/ac_automaton/test/test_ac_automaton.c
// Function: main
int main() {
    boolean pass = T;
    mp_init(1 << 20, mp_exit);

    char *         string = "aababbcabcaacca";
    char *         patterns[] = {"a", "ab", "bab", "bc", "bca", "c", "caa"};
    int            want[] = {7, 3, 1, 2, 2, 4, 1};
    int            length = sizeof(patterns) / sizeof(char *);
    ac_tree_node **nodes = mp_new(length * sizeof(ac_tree_node *));

    ac_automaton *ac = ac_init();
    for (int i = 0; i < length; ++i) {
        nodes[i] = ac_add(ac, patterns[i]);
    }
    ac_build(ac);

    // ac_print(ac);
    pass &= judge(ac->root,  ac->root);

    pass &= judge(ac->root->children['a'], ac->root);
    pass &=
        judge(ac->root->children['a']->children['b'], ac->root->children['b']);

    pass &= judge(ac->root->children['b'], ac->root);
    pass &=
        judge(ac->root->children['b']->children['a'], ac->root->children['a']);
    pass &= judge(ac->root->children['b']->children['a']->children['b'],
                  ac->root->children['a']->children['b']);

    pass &=
        judge(ac->root->children['b']->children['c'], ac->root->children['c']);
    pass &= judge(ac->root->children['b']->children['c']->children['a'],
                  ac->root->children['c']->children['a']);

    pass &= judge(ac->root->children['c'], ac->root);
    pass &=
        judge(ac->root->children['c']->children['a'], ac->root->children['a']);
    pass &= judge(ac->root->children['c']->children['a']->children['a'],
                  ac->root->children['a']);

    char *c = string;
    while (*c != '\0') {
        ac_match_char(ac, *c);
        ++c;
    }

    for (int i = 0; i < length; ++i) {
        if (want[i] != nodes[i]->match_number) {
            print_err("'%s' matchs %d times, but want %d times\n", patterns[i],
                      nodes[i]->match_number, want[i]);
            pass = F;
        }
    }

    if (pass) {
        print_ok("All testcases passed\n");
    } else {
        print_err("Some errors!\n");
    }
    return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
leaq 0x5c1(%rip), %rax       # 0x2028
movl (%rax), %eax
movl %eax, 0x34(%rsp)
leaq -0x3dc(%rip), %rsi      # 0x1698
movl $0x100000, %edi         # imm = 0x100000
callq 0x16a1
pushq $0x38
popq %rdi
callq 0x188d
movq %rax, %rbx
xorl %r15d, %r15d
xorl %eax, %eax
callq 0x1199
movq %rax, %r14
leaq 0x2313(%rip), %rbp      # 0x3db0
cmpq $0x38, %r15
je 0x1ab9
movq (%r15,%rbp), %rsi
movq %r14, %rdi
callq 0x11fc
movq %rax, (%rbx,%r15)
addq $0x8, %r15
jmp 0x1a9d
movq %r14, %rdi
callq 0x1282
movq (%r14), %rdi
movq %rdi, %rsi
callq 0x1a20
movl %eax, 0x30(%rsp)
movq (%r14), %rsi
movq (%rsi), %rax
movq 0x308(%rax), %rdi
callq 0x1a20
movl %eax, 0x2c(%rsp)
movq (%r14), %rax
movq (%rax), %rax
movq 0x308(%rax), %rcx
movq 0x310(%rax), %rsi
movq (%rcx), %rax
movq 0x310(%rax), %rdi
callq 0x1a20
movl %eax, 0x24(%rsp)
movq (%r14), %rsi
movq (%rsi), %rax
movq 0x310(%rax), %rdi
callq 0x1a20
movl %eax, 0x28(%rsp)
movq (%r14), %rax
movq (%rax), %rax
movq 0x308(%rax), %rsi
movq 0x310(%rax), %rax
movq (%rax), %rax
movq 0x308(%rax), %rdi
callq 0x1a20
movl %eax, 0x20(%rsp)
movq (%r14), %rax
movq (%rax), %rax
movq 0x308(%rax), %rcx
movq 0x310(%rax), %rax
movq (%rax), %rax
movq 0x308(%rax), %rax
movq (%rax), %rax
movq 0x310(%rax), %rdi
movq (%rcx), %rax
movq 0x310(%rax), %rsi
callq 0x1a20
movl %eax, 0x1c(%rsp)
movq (%r14), %rax
movq (%rax), %rax
movq 0x310(%rax), %rcx
movq 0x318(%rax), %rsi
movq (%rcx), %rax
movq 0x318(%rax), %rdi
callq 0x1a20
movl %eax, %r13d
movq (%r14), %rax
movq (%rax), %rax
movq 0x310(%rax), %rcx
movq 0x318(%rax), %rax
movq (%rcx), %rcx
movq 0x318(%rcx), %rcx
movq (%rcx), %rcx
movq 0x308(%rcx), %rdi
movq (%rax), %rax
movq 0x308(%rax), %rsi
callq 0x1a20
movl %eax, 0x18(%rsp)
movq (%r14), %rsi
movq (%rsi), %rax
movq 0x318(%rax), %rdi
callq 0x1a20
movl %eax, 0x14(%rsp)
movq (%r14), %rax
movq (%rax), %rax
movq 0x308(%rax), %rsi
movq 0x318(%rax), %rax
movq (%rax), %rax
movq 0x308(%rax), %rdi
callq 0x1a20
movl %eax, 0x10(%rsp)
movq (%r14), %rax
movq (%rax), %rax
movq 0x308(%rax), %rsi
movq 0x318(%rax), %rax
movq (%rax), %rax
movq 0x308(%rax), %rax
movq (%rax), %rax
movq 0x308(%rax), %rdi
callq 0x1a20
movl %eax, 0xc(%rsp)
xorl %r15d, %r15d
leaq 0x540(%rip), %r12       # 0x219e
cmpq $0xf, %r15
je 0x1c76
movsbl (%r15,%r12), %esi
movq %r14, %rdi
callq 0x1336
incq %r15
jmp 0x1c5e
movl 0x30(%rsp), %eax
andl 0x34(%rsp), %eax
movl 0x2c(%rsp), %ecx
andl 0x24(%rsp), %ecx
andl %eax, %ecx
movl 0x28(%rsp), %eax
andl 0x20(%rsp), %eax
andl 0x1c(%rsp), %eax
andl %ecx, %eax
andl 0x18(%rsp), %r13d
andl 0x14(%rsp), %r13d
andl 0x10(%rsp), %r13d
andl %eax, %r13d
andl 0xc(%rsp), %r13d
leaq 0x378(%rip), %rax       # 0x202c
movl (%rax), %r15d
leaq 0x552(%rip), %r12       # 0x2210
xorl %r14d, %r14d
cmpq $0x1c, %r14
je 0x1cf5
movl (%r14,%r12), %ecx
movq (%rbx,%r14,2), %rax
movl 0x1c(%rax), %edx
cmpl %edx, %ecx
je 0x1ceb
movq (%rbp), %rsi
leaq 0x4dc(%rip), %rdi       # 0x21bd
xorl %eax, %eax
callq 0x14c8
movl %r15d, %r13d
addq $0x4, %r14
addq $0x8, %rbp
jmp 0x1cc1
testl %r13d, %r13d
je 0x1d0a
leaq 0x4e5(%rip), %rdi       # 0x21e6
xorl %eax, %eax
callq 0x1580
jmp 0x1d18
leaq 0x4eb(%rip), %rdi       # 0x21fc
xorl %eax, %eax
callq 0x14c8
xorl %eax, %eax
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq