// File: /workspace/github_cpp_makefile_star2_O3/ctSkennerton[P]fxtract/util/ssearch.c
// Function: ssearch_create
SSEARCH*
ssearch_create(const MEMREF strv[], int nstrs)
{
    int         i, j, cum, nsyms, nsuffixes, suflen;
    const char  *suffix;

    for (i = 0, suflen = 8 * sizeof(MASK); i < nstrs; ++i)
        if (suflen > (int)strv[i].len)
            suflen = strv[i].len;

    if (suflen < 2)
        return NULL;

    SSEARCH        *ssp = calloc(1, sizeof(*ssp));
    ssp->strv   = strv;
    ssp->nstrs  = nstrs;
    ssp->suflen = suflen;

    // Find all distinct bytevals that occur in suffixes
    for (i = nstrs; --i >= 0;)
        for (j = suflen + 1; --j > 0;)
            ssp->symv[(uint8_t)strv[i].ptr[strv[i].len - j]]=1;

    // Create a map from [0..255] to [NONSYM,0..nsyms-1]
    for (i = nsyms = 0; i < 256; ++i)
        ssp->symv[i] = ssp->symv[i] ? nsyms++ : NONSYM;

    // Calculate column count of mapv[][]: a power of 2
    for (ssp->symwid = 1; (1 << ssp->symwid) < nsyms;)
         ++ssp->symwid;

    // Set mapv[][] for each adj pair of bytes in suffixes
    const MASK bits        = (1 << (ssp->suflen - 1)) - 1;
    const int  mapmask  = (1 << 2*ssp->symwid) - 1;

    ssp->mapv   = calloc(nsyms << ssp->symwid, sizeof(MASK));
    for (i = 0 ; i < nstrs; ++i) {
        const char *cp = strv[i].ptr + strv[i].len;
        int            symsym = ssp->symv[(uint8_t)*--cp];
        MASK        mask;

        for (mask = 1; mask & bits; mask <<= 1) {
            int            sym = ssp->symv[(uint8_t)*--cp];
            symsym = ((symsym << ssp->symwid) | sym) & mapmask;
            ssp->mapv[symsym] |= mask;
        }
    }

        // Map each unique suffix to a set of strings

    // Count #(unique suffixes) and #(strings per suffix)
    ssp->suffixh = map_create( (map_diff*)memcmp, 
                                (map_hash*)fnv04, 
                                    VOIDP(ssp->suflen));
    int                *locp, *locv = calloc(nstrs, sizeof(int));
    for (i = nsuffixes = 0; i < nstrs; ++i) {
        suffix        = strv[i].ptr + strv[i].len - ssp->suflen;
        locp = map_get(ssp->suffixh, suffix);
        if (!locp) {
            locp = &locv[nsuffixes++];
            map_set(ssp->suffixh, suffix, locp);
        }
        ++*locp;
    }

    // Convert sublist lengths to sublist offsets in prefixv[].
    // Pre-mark list-ends.
    ssp->prefixv = calloc(nstrs + nsuffixes, sizeof(int));
    for (i = cum = 0; i < nsuffixes; ++i) {
        locv[i] = cum += locv[i] + 1;
        ssp->prefixv[--locv[i]] = NONSTR;
    }

    // Populate lists in prefixv[]
    for (i = nstrs; --i >= 0;) {
        suffix = strv[i].ptr + strv[i].len - ssp->suflen;
        locp = map_get(ssp->suffixh, suffix);
        ssp->prefixv[--*locp] = i;
    }

    // Convert map values from (list**) to (list*)
    map_start(ssp->suffixh); 
    while (map_next(ssp->suffixh, VOIDP(&suffix),
                        VOIDP(&locp))) {
        map_set(ssp->suffixh, suffix, &ssp->prefixv[*locp]);
    }

    free(locv);
    return    ssp;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
movl %esi, %r15d
movq %rdi, %r14
movl %esi, %r8d
testl %esi, %esi
jle 0x49ab
movq %r8, %rax
shlq $0x4, %rax
movl $0x10, %r13d
xorl %ecx, %ecx
movl %r13d, %edx
movl 0x8(%r14,%rcx), %r13d
cmpl %r13d, %edx
cmovll %edx, %r13d
addq $0x10, %rcx
cmpq %rcx, %rax
jne 0x4986
cmpl $0x2, %r13d
jge 0x49b1
xorl %ebx, %ebx
jmp 0x4d0c
movl $0x10, %r13d
movl $0x1, %edi
movl $0x230, %esi            # imm = 0x230
movq %r8, 0x8(%rsp)
callq 0x30f0
movq 0x8(%rsp), %rdx
movq %rax, %rbx
movq %r14, (%rax)
movl %r15d, 0x8(%rax)
movl %r13d, 0xc(%rax)
movl %r13d, %r10d
testl %r15d, %r15d
jle 0x4a24
leal 0x2(%r13), %eax
movq %r10, %rcx
negq %rcx
movq %rdx, %rsi
decq %rdx
movq %rdx, %r8
shlq $0x4, %r8
movq (%r14,%r8), %rdi
addq %rcx, %rdi
addq 0x8(%r14,%r8), %rdi
movl %eax, %r8d
movzbl (%rdi), %r9d
movw $0x1, 0x2c(%rbx,%r9,2)
decl %r8d
incq %rdi
cmpl $0x2, %r8d
jg 0x4a06
cmpq $0x1, %rsi
jg 0x49ea
xorl %edx, %edx
movl $0x16, %eax
movl %edx, %ecx
movzwl (%rbx,%rax,2), %esi
cmpw $0x1, %si
sbbl $-0x1, %edx
cmpw $0x1, %si
movl $0x0, %esi
sbbl %esi, %esi
orl %ecx, %esi
movw %si, (%rbx,%rax,2)
incq %rax
cmpq $0x116, %rax            # imm = 0x116
jne 0x4a2b
movq %r10, 0x10(%rsp)
movq %r15, 0x18(%rsp)
xorl %eax, %eax
xorl %ebp, %ebp
incl %ebp
movl $0x1, %esi
movl %ebp, %ecx
shll %cl, %esi
addl $0x2, %eax
cmpl %edx, %esi
jl 0x4a62
movl %ebp, 0x28(%rbx)
movl $0xffffffff, %r12d      # imm = 0xFFFFFFFF
movl $0xffffffff, %r15d      # imm = 0xFFFFFFFF
movl %eax, %ecx
shll %cl, %r15d
movl %ebp, %ecx
shll %cl, %edx
movslq %edx, %rdi
movl $0x2, %esi
callq 0x30f0
movq %rax, 0x10(%rbx)
cmpl $0x0, 0x18(%rsp)
movq 0x8(%rsp), %r11
jle 0x4b22
decb %r13b
movl %r13d, %ecx
shll %cl, %r12d
notl %r15d
notl %r12d
movzwl %r12w, %edx
xorl %esi, %esi
testb $0x1, %dl
je 0x4b1a
movq %rsi, %rcx
shlq $0x4, %rcx
movq (%r14,%rcx), %rdi
movq 0x8(%r14,%rcx), %rcx
addq %rcx, %rdi
addq $-0x2, %rdi
movzbl 0x1(%rdi), %ecx
movswl 0x2c(%rbx,%rcx,2), %r8d
movl $0x1, %r9d
movzbl (%rdi), %ecx
movswl 0x2c(%rbx,%rcx,2), %r10d
movl %ebp, %ecx
shll %cl, %r8d
orl %r10d, %r8d
andl %r15d, %r8d
orw %r9w, (%rax,%r8,2)
addl %r9d, %r9d
movl %r9d, %ecx
andl $0x1fffe, %ecx          # imm = 0x1FFFE
decq %rdi
testl %edx, %r9d
movl %ecx, %r9d
jne 0x4aea
incq %rsi
cmpq %r11, %rsi
jne 0x4abe
movq %r14, (%rsp)
movq 0x549b(%rip), %rdi      # 0x9fc8
leaq 0x6b4(%rip), %rsi       # 0x51e8
movq 0x10(%rsp), %r12
movq %r12, %rdx
callq 0x5370
movq %rax, %r13
movq %rax, 0x18(%rbx)
movq 0x18(%rsp), %r15
movslq %r15d, %rdi
movl $0x4, %esi
callq 0x30f0
movq %rax, 0x20(%rsp)
testl %r15d, %r15d
jle 0x4bd4
negq %r12
movq %r12, 0x40(%rsp)
movq 0x8(%rsp), %rax
shlq $0x4, %rax
movq %rax, 0x38(%rsp)
xorl %r12d, %r12d
xorl %r14d, %r14d
movq (%rsp), %rax
movq (%rax,%r12), %r15
addq 0x8(%rax,%r12), %r15
addq 0x40(%rsp), %r15
movq %r13, %rdi
movq %r15, %rsi
callq 0x554f
testq %rax, %rax
je 0x4ba7
movq %rax, %rbp
jmp 0x4bc4
movslq %r14d, %rax
incl %r14d
movq 0x20(%rsp), %rcx
leaq (%rcx,%rax,4), %rbp
movq %r13, %rdi
movq %r15, %rsi
movq %rbp, %rdx
callq 0x5724
incl (%rbp)
addq $0x10, %r12
cmpq %r12, 0x38(%rsp)
jne 0x4b80
jmp 0x4bd7
xorl %r14d, %r14d
movq 0x18(%rsp), %r12
leal (%r14,%r12), %eax
movslq %eax, %rdi
movl $0x4, %esi
callq 0x30f0
movq %rax, %r9
movq %rax, 0x20(%rbx)
testl %r14d, %r14d
movq 0x20(%rsp), %r8
jle 0x4c29
movl %r14d, %eax
xorl %ecx, %ecx
xorl %edx, %edx
movl (%r8,%rcx,4), %esi
leal (%rsi,%rdx), %edi
incl %edi
addl %edx, %esi
movl %esi, (%r8,%rcx,4)
movslq %esi, %rdx
movl $0xffffffff, (%r9,%rdx,4) # imm = 0xFFFFFFFF
incq %rcx
movl %edi, %edx
cmpq %rcx, %rax
jne 0x4c05
testl %r12d, %r12d
movq 0x8(%rsp), %r12
movq (%rsp), %rsi
jle 0x4ca0
movq 0x10(%rsp), %rdx
negq %rdx
movq %r12, %rax
shlq $0x4, %rax
leaq (%rax,%rsi), %r14
addq $-0x8, %r14
movq %r13, (%rsp)
movq %rdx, 0x10(%rsp)
leaq -0x1(%r12), %r13
movq -0x8(%r14), %r15
addq (%r14), %r15
addq %rdx, %r15
movq (%rsp), %rdi
movq %r15, %rsi
movq %r9, %rbp
callq 0x554f
movq %rbp, %r9
movq %rax, %rbp
movslq (%rax), %rax
leaq -0x1(%rax), %rcx
movl %ecx, (%rbp)
movl %r13d, -0x4(%r9,%rax,4)
addq $-0x10, %r14
cmpq $0x1, %r12
movq 0x10(%rsp), %rdx
movq %r13, %r12
ja 0x4c57
movq (%rsp), %r13
leaq 0x30(%rsp), %r14
movq %r15, (%r14)
leaq 0x28(%rsp), %r15
movq %rbp, (%r15)
movq %r13, %rdi
movq %r9, %r12
callq 0x57d5
movq %r13, %rdi
movq %r14, %rsi
movq %r15, %rdx
callq 0x557c
testl %eax, %eax
je 0x4d02
leaq 0x30(%rsp), %r14
leaq 0x28(%rsp), %r15
movq 0x30(%rsp), %rsi
movq 0x28(%rsp), %rax
movslq (%rax), %rax
leaq (%r12,%rax,4), %rdx
movq %r13, %rdi
callq 0x5724
movq %r13, %rdi
movq %r14, %rsi
movq %r15, %rdx
callq 0x557c
testl %eax, %eax
jne 0x4cd7
movq 0x20(%rsp), %rdi
callq 0x3200
movq %rbx, %rax
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq