multimerge

repo: umbrant/extsort

original_code:
void multimerge(run_t** runs, char* input_prefix, int num_runs, int output_fd, int base)
{
    int run_offsets[num_runs];
    char filename[20];
    if(base == 0) {
        ;
        for(int i=0; i<num_runs; i++) {
            runs[i] = (run_t*)calloc(1, sizeof(run_t));
            runs[i]->items = (int*)calloc(1, IO_BUF_PAGES*(4*(1<<10)));
            snprintf(filename, 20, "%s%d.dat", input_prefix, i);
            int fd = open(filename, 00);
            int bytes = read(fd, runs[i]->items, IO_BUF_PAGES*(4*(1<<10)));
            close(fd);
            runs[i]->length = bytes/sizeof(int);
            run_offsets[i] = bytes;
        }
    }
    int idx[num_runs];
    int skip[num_runs];
    int* output = (int*)malloc(IO_BUF_PAGES*(4*(1<<10)));
    int output_idx = 0;
    int live_runs = num_runs;
    for(int i=0; i<num_runs; i++) {
        idx[i] = 0;
        if(runs[i]->length > 0) {
            skip[i] = 0;
        } else {
            skip[i] = 1;
            live_runs--;
        }
    }
    while(live_runs > 0) {
        int init = 0;
        int min = -13;
        int min_run = -1;
        for(int j=0; j<num_runs; j++) {
            if(!skip[j]) {
                if(!init || runs[j]->items[idx[j]] < min) {
                    min_run = j;
                    min = runs[j]->items[idx[j]];
                    init = 1;
                }
            }
        }
        output[output_idx] = runs[min_run]->items[idx[min_run]];
        idx[min_run]++;
        if(!skip[min_run] && idx[min_run] == runs[min_run]->length) {
            if(base) {
                skip[min_run] = 1;
                live_runs--;
            } else {
                snprintf(filename, 20, "%s%d.dat", input_prefix, min_run);
                int fd = open(filename, 00);
                lseek(fd, run_offsets[min_run], 0);
                int bytes = read(fd, runs[min_run]->items, IO_BUF_PAGES*(4*(1<<10)));
                if(bytes > 0) {
                    idx[min_run] = 0;
                    runs[min_run]->length = bytes / sizeof(int);
                } else {
                    skip[min_run] = 1;
                    live_runs--;
                }
                close(fd);
                run_offsets[min_run] += bytes;
            }
        }
        output_idx++;
        if(output_idx == IO_BUF_PAGES*(4*(1<<10))/sizeof(int)) {
            int check = output[0];
            for(int j=1; j<IO_BUF_PAGES*(4*(1<<10))/sizeof(int); j++) {
                if(output[j] < check) {
                    printf("Error at index %d\n", j);
                }
                check = output[j];
            }
            int rv = write(output_fd, output, IO_BUF_PAGES*(4*(1<<10)));
            if(rv != IO_BUF_PAGES*(4*(1<<10))) {
                perror("Write size mismatch!\n");
            }
            output_idx = 0;
        }
    }
    int bytes = write(output_fd, output, output_idx*sizeof(int));
    if(bytes != output_idx*sizeof(int)) {
        perror("Write size mismatch!\n");
    }
    if(base == 0) {
        for(int i=0; i<num_runs; i++) {
            free(runs[i]->items);
            free(runs[i]);
        }
    }
    free(output);
}

canonical_original_code:
void multimerge(struct run_t **runs, char *input_prefix, int num_runs, int output_fd, int base)
{
    int run_offsets[-1];
    char filename[20];
    if(base == 0) {
        ;
        for(int i = 0; i<num_runs; i++) {
            runs[i] = (struct run_t *)calloc(1, sizeof(run_t));
            runs[i]->items = (int *)calloc(1, IO_BUF_PAGES*(4*(1<<10)));
            snprintf(filename, 20, "%s%d.dat", input_prefix, i);
            int fd = open(filename, 00);
            int bytes = read(fd, runs[i]->items, IO_BUF_PAGES*(4*(1<<10)));
            close(fd);
            runs[i]->length = bytes/sizeof(int);
            run_offsets[i] = bytes;
        }
    }
    int idx[-1];
    int skip[-1];
    int *output = (int*)malloc(IO_BUF_PAGES*(4*(1<<10)));
    int output_idx = 0;
    int live_runs = num_runs;
    for(int i = 0; i<num_runs; i++) {
        idx[i] = 0;
        if(runs[i]->length > 0) {
            skip[i] = 0;
        } else {
            skip[i] = 1;
            live_runs--;
        }
    }
    while(live_runs > 0) {
        int init = 0;
        int min = -13;
        int min_run = -1;
        for(int j = 0; j<num_runs; j++) {
            if(!skip[j]) {
                if(!init || runs[j]->items[idx[j]] < min) {
                    min_run = j;
                    min = runs[j]->items[idx[j]];
                    init = 1;
                }
            }
        }
        output[output_idx] = runs[min_run]->items[idx[min_run]];
        idx[min_run]++;
        if(!skip[min_run] && idx[min_run] == runs[min_run]->length) {
            if(base) {
                skip[min_run] = 1;
                live_runs--;
            } else {
                snprintf(filename, 20, "%s%d.dat", input_prefix, min_run);
                int fd = open(filename, 00);
                lseek(fd, run_offsets[min_run], 0);
                int bytes = read(fd, runs[min_run]->items, IO_BUF_PAGES*(4*(1<<10)));
                if(bytes > 0) {
                    idx[min_run] = 0;
                    runs[min_run]->length = bytes / sizeof(int);
                } else {
                    skip[min_run] = 1;
                    live_runs--;
                }
                close(fd);
                run_offsets[min_run] += bytes;
            }
        }
        output_idx++;
        if(output_idx == IO_BUF_PAGES*(4*(1<<10))/sizeof(int)) {
            int check = output[0];
            for(int j = 1; j<IO_BUF_PAGES*(4*(1<<10))/sizeof(int); j++) {
                if(output[j] < check) {
                    printf("Error at index %d\n", j);
                }
                check = output[j];
            }
            int rv = write(output_fd, output, IO_BUF_PAGES*(4*(1<<10)));
            if(rv != IO_BUF_PAGES*(4*(1<<10))) {
                perror("Write size mismatch!\n");
            }
            output_idx = 0;
        }
    }
    int bytes = write(output_fd, output, output_idx*sizeof(int));
    if(bytes != output_idx*sizeof(int)) {
        perror("Write size mismatch!\n");
    }
    if(base == 0) {
        for(int i = 0; i<num_runs; i++) {
            free(runs[i]->items);
            free(runs[i]);
        }
    }
    free(output);
}

variable_types: struct run_t { int length; int *items; } **

variable_types: base int

variable_types:
filename
char [20]

variable_types: fd int

variable_types: bytes int

variable_types:
idx
int [-1]

variable_types:
skip
int [-1]

variable_types:
output
int *

variable_types: init int

variable_types: min int

variable_types: j int

variable_types: check int

variable_types: rv int


usage

decompiled_code:
void __noreturn usage()
{
puts("extsort <filename> <buffer_size_mb> <io_buf_pages>");
puts("\tfilename: filename of file to be sorted");
puts("\tbuffer_size_mb: MBs of buffer to use for sorting");
puts("\tio_buf_pages: number of 4k pages to use for per-run IO buffering");
exit(1);
}

canonical_decompiled_code:
void __noreturn func1()
{
puts("extsort <filename> <buffer_size_mb> <io_buf_pages>");
puts("\tfilename: filename of file to be sorted");
puts("\tbuffer_size_mb: MBs of buffer to use for sorting");
puts("\tio_buf_pages: number of 4k pages to use for per-run IO buffering");
exit(1);
}

original_code:
void usage()
{
    printf("extsort <filename> <buffer_size_mb> <io_buf_pages>\n");
    printf("\tfilename: filename of file to be sorted\n");
    printf("\tbuffer_size_mb: MBs of buffer to use for sorting\n");
    printf("\tio_buf_pages: number of 4k pages to use for per-run IO buffering\n");
    exit(1);
}

return_type: void


error

decompiled_code:
void __fastcall __noreturn error(const char *a1)
{
perror(a1);
exit(-1);
}

canonical_decompiled_code:
void __fastcall __noreturn func2(const char *a1)
{
perror(a1);
exit(-1);
}

original_code:
void error(const char* msg)
{
    perror(msg);
    exit(-1);
}

canonical_original_code:
void error(char *msg)
{
    perror(msg);
    exit(-1);
}

variable_types:
msg
char *


verify

decompiled_code:
void __fastcall verify(char *file)
{
int v1; // er14
int v2; // ebx
signed __int64 v3; // r13
int v4; // er15
char *v5; // r12
int v6; // ebp
int v7; // er15
unsigned __int64 v8; // rax
unsigned __int64 v9; // rsi
char *v10; // rdx
char *v11; // rcx
int v12; // eax
int v13; // [rsp+4h] [rbp-D4h]
__int64 v14; // [rsp+8h] [rbp-D0h]
struct stat buf; // [rsp+10h] [rbp-C8h] BYREF

printf("Verifying sort (%s)...\n", file);
v1 = open(file, 0);
if ( fstat(v1, &buf) )
error("Could not fstat file!");
v2 = 0;
v3 = IO_BUF_PAGES << 12;
v4 = buf.st_size / v3 - ((buf.st_size % v3 == 0) - 1);
v13 = v4;
v5 = (char *)calloc(1uLL, v3);
if ( v4 <= 0 )
{
v14 = 0LL;
LABEL_16:
printf("Correctly sorted! %lu ints.\n", v14);
goto LABEL_14;
}
v14 = 0LL;
v6 = 0;
v7 = 0;
do
{
v8 = (unsigned __int64)(int)read(v1, v5, v3) >> 2;
v9 = v8;
if ( v8 )
{
v10 = v5;
v11 = &v5[4 * v8];
do
{
v12 = v2;
v2 = *(_DWORD *)v10;
if ( v7 && v12 > v2 )
v6 = v7;
v10 += 4;
v7 = 1;
}
while ( v11 != v10 );
v14 += v9;
}
--v13;
}
while ( v13 );
if ( !v6 )
goto LABEL_16;
printf("Incorrect sort of %lu ints.\n", v14);
LABEL_14:
free(v5);
}

canonical_decompiled_code:
void __fastcall func3(char *file)
{
int v1; // er14
int v2; // ebx
signed __int64 v3; // r13
int v4; // er15
char *v5; // r12
int v6; // ebp
int v7; // er15
unsigned __int64 v8; // rax
unsigned __int64 v9; // rsi
char *v10; // rdx
char *v11; // rcx
int v12; // eax
int v13; // [rsp+4h] [rbp-D4h]
__int64 v14; // [rsp+8h] [rbp-D0h]
struct stat buf; // [rsp+10h] [rbp-C8h] BYREF

printf("Verifying sort (%s)...\n", file);
v1 = open(file, 0);
if ( fstat(v1, &buf) )
func2("Could not fstat file!");
v2 = 0;
v3 = IO_BUF_PAGES << 12;
v4 = buf.st_size / v3 - ((buf.st_size % v3 == 0) - 1);
v13 = v4;
v5 = (char *)calloc(1uLL, v3);
if ( v4 <= 0 )
{
v14 = 0LL;
LABEL_16:
printf("Correctly sorted! %lu ints.\n", v14);
goto LABEL_14;
}
v14 = 0LL;
v6 = 0;
v7 = 0;
do
{
v8 = (unsigned __int64)(int)read(v1, v5, v3) >> 2;
v9 = v8;
if ( v8 )
{
v10 = v5;
v11 = &v5[4 * v8];
do
{
v12 = v2;
v2 = *(_DWORD *)v10;
if ( v7 && v12 > v2 )
v6 = v7;
v10 += 4;
v7 = 1;
}
while ( v11 != v10 );
v14 += v9;
}
--v13;
}
while ( v13 );
if ( !v6 )
goto LABEL_16;
printf("Incorrect sort of %lu ints.\n", v14);
LABEL_14:
free(v5);
}

original_code:
void verify(char* filename)
{
    printf("Verifying sort (%s)...\n", filename);
    int input_fd = open(filename, 00);
    struct stat s;
    int rv = fstat(input_fd, &s);
    if(rv) {
        error("Could not fstat file!");
    }
    int buf_size = IO_BUF_PAGES*(4*(1<<10));
    int num_runs = s.st_size / (buf_size);
    if(s.st_size % buf_size) {
        num_runs++;
    }
    int* buf = (int*)calloc(1, buf_size);
    int current = 0;
    int init = 0;
    int error = 0;
    unsigned long count = 0;
    while(num_runs > 0) {
        int bytes = read(input_fd, buf, buf_size);
        for(int i=0; i<bytes/sizeof(int); i++) {
            if(!init) {
                current = buf[i];
                init = 1;
            }
            if(buf[i] < current) {
                error = 1;
            }
            current = buf[i];
            count++;
        }
        num_runs--;
    }
    if(error) {
        printf("Incorrect sort of %lu ints.\n", count);
    } else {
        printf("Correctly sorted! %lu ints.\n", count);
    }
    free(buf);
}

canonical_original_code:
void verify(char *filename)
{
    printf("Verifying sort (%s)...\n", filename);
    int input_fd = open(filename, 00);
    struct stat s;
    int rv = fstat(input_fd, &s);
    if(rv) {
        error("Could not fstat file!");
    }
    int buf_size = IO_BUF_PAGES*(4*(1<<10));
    int num_runs = s.st_size / (buf_size);
    if(s.st_size % buf_size) {
        num_runs++;
    }
    int *buf = (int*)calloc(1, buf_size);
    int current = 0;
    int init = 0;
    int error = 0;
    unsigned long count = 0;
    while(num_runs > 0) {
        int bytes = read(input_fd, buf, buf_size);
        for(int i = 0; i<bytes/sizeof(int); i++) {
            if(!init) {
                current = buf[i];
                init = 1;
            }
            if(buf[i] < current) {
                error = 1;
            }
            current = buf[i];
            count++;
        }
        num_runs--;
    }
    if(error) {
        printf("Incorrect sort of %lu ints.\n", count);
    } else {
        printf("Correctly sorted! %lu ints.\n", count);
    }
    free(buf);
}

variable_types:
filename
char *

variable_types: struct stat { unsigned long st_dev; unsigned long st_ino; unsigned long st_nlink; unsigned int st_mode; unsigned int st_uid; unsigned int st_gid; int __pad0; unsigned long st_rdev; long st_size; long st_blksize; long st_blocks; struct timespec { long tv_sec; long tv_nsec; } st_atim; struct timespec st_mtim; struct timespec st_ctim; long __glibc_reserved[3]; }

variable_types:
buf
int *

variable_types: current int

variable_types: error int

variable_types:
count
unsigned long

variable_types: i int

user_defined_types: struct stat { unsigned long st_dev; unsigned long st_ino; unsigned long st_nlink; unsigned int st_mode; unsigned int st_uid; unsigned int st_gid; int __pad0; unsigned long st_rdev; long st_size; long st_blksize; long st_blocks; struct timespec st_atim; struct timespec st_mtim; struct timespec st_ctim; long __glibc_reserved[3]; }


decompiled_code:
__suseconds_t get_time_usecs()
{
struct timezone tz; // [rsp+8h] [rbp-20h] BYREF
struct timeval tv; // [rsp+10h] [rbp-18h] BYREF

tz = 0LL;
gettimeofday(&tv, &tz);
return tv.tv_usec + 1000000 * tv.tv_sec;
}

canonical_decompiled_code:
__suseconds_t func4()
{
struct timezone tz; // [rsp+8h] [rbp-20h] BYREF
struct timeval tv; // [rsp+10h] [rbp-18h] BYREF

tz = 0LL;
gettimeofday(&tv, &tz);
return tv.tv_usec + 1000000 * tv.tv_sec;
}

original_code:
long get_time_usecs()
{
    struct timeval time;
    struct timezone tz;
    memset(&tz, '\0', sizeof(timezone));
    gettimeofday(&time, &tz);
    long usecs = time.tv_sec*1000000 + time.tv_usec;
    return usecs;
}

variable_types: struct timeval { long tv_sec; long tv_usec; }

variable_types: struct timezone { int tz_minuteswest; int tz_dsttime; }

variable_types: usecs long

return_type: long


main

canonical_name: main

decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
const char *v3; // rbp
const char *v4; // rdi
int v5; // eax
const char *v6; // rdi
unsigned __int64 v7; // rbx
char *v8; // r14
char *v9; // r15
unsigned __int64 v10; // rax
unsigned __int64 v11; // rax
unsigned __int64 v12; // rt2
size_t v13; // rbx
size_t v14; // r13
size_t v15; // rbp
size_t v16; // r8
int v17; // er14
char *v18; // rbx
int v19; // ebx
__int64 *v21; // rbx
_QWORD *v22; // rax
_QWORD *v23; // rbp
void *v24; // rax
int v25; // eax
__int64 *v26; // rbp
__int64 v27; // rax
int v28; // ebp
char *v29; // rbx
unsigned __int64 v30; // [rsp+0h] [rbp-138h]
__int64 *ptr; // [rsp+8h] [rbp-130h]
unsigned __int64 v32; // [rsp+10h] [rbp-128h]
int v33; // [rsp+1Ch] [rbp-11Ch]
size_t nmemb; // [rsp+20h] [rbp-118h]
size_t v35; // [rsp+28h] [rbp-110h]
size_t v36; // [rsp+30h] [rbp-108h]
size_t v37; // [rsp+38h] [rbp-100h]
int v38; // [rsp+50h] [rbp-E8h]
int fd; // [rsp+54h] [rbp-E4h]
int v40; // [rsp+58h] [rbp-E0h]
char dest[5]; // [rsp+66h] [rbp-D2h] BYREF
char src[5]; // [rsp+6Bh] [rbp-CDh] BYREF
struct stat buf; // [rsp+70h] [rbp-C8h] BYREF

if ( argc != 4 )
{
printf("Invalid number of arguments (%d)\n", (unsigned int)argc);
usage();
}
v4 = argv[2];
DATA_FILENAME = (char *)argv[1];
v3 = DATA_FILENAME;
v5 = atoi(v4);
v6 = argv[3];
BUF_SIZE = v5 << 20;
IO_BUF_PAGES = atoi(v6);
fd = open(v3, 0);
if ( fd < 0 )
error("Could not open sort_fd!");
if ( fstat(fd, &buf) )
{
puts(DATA_FILENAME);
error("Could not fstat file!");
}
v7 = buf.st_size;
v8 = (char *)calloc(1uLL, 0x64uLL);
v32 = (v7 >> 12) - (((v7 & 0xFFF) == 0) - 1LL);
printf("Sorting %lu ints (%.02f MB)...\n", v32 << 12 >> 2, (double)(int)v32 * 4096.0 * 0.00000095367431640625);
strcpy(dest, "foo_");
strcpy(src, "bar_");
v38 = 1;
v40 = get_time_usecs();
if ( v32 > 1 )
{
v9 = v8;
while ( 1 )
{
printf("Iterate: %lu runs left\n", v32);
v10 = ((unsigned __int64)BUF_SIZE >> 12) / (unsigned int)IO_BUF_PAGES - 1;
if ( v10 > v32 )
v10 = v32;
nmemb = v10;
v12 = v32 % v10;
v11 = v32 / v10;
v35 = v12;
if ( v12 )
{
v32 = v11 + 1;
}
else
{
if ( nmemb > v32 )
{
v8 = v9;
v29 = stpcpy(v9, src);
strcpy(src, dest);
memcpy(dest, v9, v29 - v9 + 1);
break;
}
v32 = v11;
}
v30 = 0LL;
v13 = 0LL;
v36 = nmemb * v11;
do
{
printf("Merge %d of %lu (%lu ways)\n", (unsigned int)(v30 + 1), v32, nmemb);
v14 = v35;
if ( v36 > v13 )
v14 = nmemb;
ptr = (__int64 *)calloc(v14, 8uLL);
if ( v38 == 1 )
{
v13 += v14;
if ( v14 )
{
v37 = v13;
v21 = ptr;
do
{
v22 = calloc(1uLL, 0x10uLL);
*v21 = (__int64)v22;
v23 = v22;
v24 = calloc(1uLL, 0x1000uLL);
v23[1] = v24;
v25 = read(fd, v24, 0x1000uLL);
*(_DWORD *)*v21 = (unsigned __int64)v25 >> 2;
if ( !v25 )
break;
++v21;
}
while ( v21 != &ptr[v14] );
v13 = v37;
v26 = ptr;
parallel_qsort(ptr, (unsigned int)v14);
snprintf(v9, 0x64uLL, "%s%d.dat", src, (unsigned int)v30);
v33 = open(v9, 577, 504LL);
multimerge(ptr, dest, v14, v33, 1);
close(v33);
do
{
v27 = *v26++;
free(*(void **)(v27 + 8));
free((void *)*(v26 - 1));
}
while ( v26 != &ptr[v14] );
}
else
{
parallel_qsort(ptr, 0LL);
snprintf(v9, 0x64uLL, "%s%d.dat", src, (unsigned int)v30);
v28 = open(v9, 577, 504LL);
multimerge(ptr, dest, 0, v28, 1);
close(v28);
}
}
else
{
v15 = v14 + v13;
if ( v14 )
{
do
{
v16 = v13++;
snprintf(v9, 0x64uLL, "%s%lu.dat", dest, v16);
}
while ( v13 != v15 );
}
else
{
v15 = v13;
}
v13 = v15;
snprintf(v9, 0x64uLL, "%s%d.dat", src, (unsigned int)v30);
v17 = open(v9, 577, 504LL);
multimerge(ptr, dest, v14, v17, 0);
close(v17);
}
free(ptr);
++v30;
}
while ( v30 < v32 );
v18 = stpcpy(v9, src);
strcpy(src, dest);
memcpy(dest, v9, v18 - v9 + 1);
v38 *= (_DWORD)nmemb;
if ( v32 <= 1 )
{
v8 = v9;
break;
}
}
}
v19 = get_time_usecs();
puts("Done sorting.");
printf("Sorting took %.02f seconds.\n", (double)(v19 - v40) / 1000000.0);
free(v8);
return 0;
}

canonical_decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
const char *v3; // rbp
const char *v4; // rdi
int v5; // eax
const char *v6; // rdi
unsigned __int64 v7; // rbx
char *v8; // r14
char *v9; // r15
unsigned __int64 v10; // rax
unsigned __int64 v11; // rax
unsigned __int64 v12; // rt2
size_t v13; // rbx
size_t v14; // r13
size_t v15; // rbp
size_t v16; // r8
int v17; // er14
char *v18; // rbx
int v19; // ebx
__int64 *v21; // rbx
_QWORD *v22; // rax
_QWORD *v23; // rbp
void *v24; // rax
int v25; // eax
__int64 *v26; // rbp
__int64 v27; // rax
int v28; // ebp
char *v29; // rbx
unsigned __int64 v30; // [rsp+0h] [rbp-138h]
__int64 *ptr; // [rsp+8h] [rbp-130h]
unsigned __int64 v32; // [rsp+10h] [rbp-128h]
int v33; // [rsp+1Ch] [rbp-11Ch]
size_t nmemb; // [rsp+20h] [rbp-118h]
size_t v35; // [rsp+28h] [rbp-110h]
size_t v36; // [rsp+30h] [rbp-108h]
size_t v37; // [rsp+38h] [rbp-100h]
int v38; // [rsp+50h] [rbp-E8h]
int fd; // [rsp+54h] [rbp-E4h]
int v40; // [rsp+58h] [rbp-E0h]
char dest[5]; // [rsp+66h] [rbp-D2h] BYREF
char src[5]; // [rsp+6Bh] [rbp-CDh] BYREF
struct stat buf; // [rsp+70h] [rbp-C8h] BYREF

if ( argc != 4 )
{
printf("Invalid number of arguments (%d)\n", (unsigned int)argc);
func1();
}
v4 = argv[2];
DATA_FILENAME = (char *)argv[1];
v3 = DATA_FILENAME;
v5 = atoi(v4);
v6 = argv[3];
BUF_SIZE = v5 << 20;
IO_BUF_PAGES = atoi(v6);
fd = open(v3, 0);
if ( fd < 0 )
func2("Could not open sort_fd!");
if ( fstat(fd, &buf) )
{
puts(DATA_FILENAME);
func2("Could not fstat file!");
}
v7 = buf.st_size;
v8 = (char *)calloc(1uLL, 0x64uLL);
v32 = (v7 >> 12) - (((v7 & 0xFFF) == 0) - 1LL);
printf("Sorting %lu ints (%.02f MB)...\n", v32 << 12 >> 2, (double)(int)v32 * 4096.0 * 0.00000095367431640625);
strcpy(dest, "foo_");
strcpy(src, "bar_");
v38 = 1;
v40 = func4();
if ( v32 > 1 )
{
v9 = v8;
while ( 1 )
{
printf("Iterate: %lu runs left\n", v32);
v10 = ((unsigned __int64)BUF_SIZE >> 12) / (unsigned int)IO_BUF_PAGES - 1;
if ( v10 > v32 )
v10 = v32;
nmemb = v10;
v12 = v32 % v10;
v11 = v32 / v10;
v35 = v12;
if ( v12 )
{
v32 = v11 + 1;
}
else
{
if ( nmemb > v32 )
{
v8 = v9;
v29 = stpcpy(v9, src);
strcpy(src, dest);
memcpy(dest, v9, v29 - v9 + 1);
break;
}
v32 = v11;
}
v30 = 0LL;
v13 = 0LL;
v36 = nmemb * v11;
do
{
printf("Merge %d of %lu (%lu ways)\n", (unsigned int)(v30 + 1), v32, nmemb);
v14 = v35;
if ( v36 > v13 )
v14 = nmemb;
ptr = (__int64 *)calloc(v14, 8uLL);
if ( v38 == 1 )
{
v13 += v14;
if ( v14 )
{
v37 = v13;
v21 = ptr;
do
{
v22 = calloc(1uLL, 0x10uLL);
*v21 = (__int64)v22;
v23 = v22;
v24 = calloc(1uLL, 0x1000uLL);
v23[1] = v24;
v25 = read(fd, v24, 0x1000uLL);
*(_DWORD *)*v21 = (unsigned __int64)v25 >> 2;
if ( !v25 )
break;
++v21;
}
while ( v21 != &ptr[v14] );
v13 = v37;
v26 = ptr;
parallel_qsort(ptr, (unsigned int)v14);
snprintf(v9, 0x64uLL, "%s%d.dat", src, (unsigned int)v30);
v33 = open(v9, 577, 504LL);
func0(ptr, dest, v14, v33, 1);
close(v33);
do
{
v27 = *v26++;
free(*(void **)(v27 + 8));
free((void *)*(v26 - 1));
}
while ( v26 != &ptr[v14] );
}
else
{
parallel_qsort(ptr, 0LL);
snprintf(v9, 0x64uLL, "%s%d.dat", src, (unsigned int)v30);
v28 = open(v9, 577, 504LL);
func0(ptr, dest, 0, v28, 1);
close(v28);
}
}
else
{
v15 = v14 + v13;
if ( v14 )
{
do
{
v16 = v13++;
snprintf(v9, 0x64uLL, "%s%lu.dat", dest, v16);
}
while ( v13 != v15 );
}
else
{
v15 = v13;
}
v13 = v15;
snprintf(v9, 0x64uLL, "%s%d.dat", src, (unsigned int)v30);
v17 = open(v9, 577, 504LL);
func0(ptr, dest, v14, v17, 0);
close(v17);
}
free(ptr);
++v30;
}
while ( v30 < v32 );
v18 = stpcpy(v9, src);
strcpy(src, dest);
memcpy(dest, v9, v18 - v9 + 1);
v38 *= (_DWORD)nmemb;
if ( v32 <= 1 )
{
v8 = v9;
break;
}
}
}
v19 = func4();
puts("Done sorting.");
printf("Sorting took %.02f seconds.\n", (double)(v19 - v40) / 1000000.0);
free(v8);
return 0;
}

original_code:
int main(int argc, char* argv[])
{
    if(argc != 4) {
        printf("Invalid number of arguments (%d)\n", argc);
        usage();
    }
    DATA_FILENAME = argv[1];
    BUF_SIZE = atoi(argv[2])*(1<<20);
    IO_BUF_PAGES = atoi(argv[3]);
    int sort_fd = open(DATA_FILENAME, 00);
    if(sort_fd < 0) {
        error("Could not open sort_fd!");
    }
    struct stat s;
    int rv = fstat(sort_fd, &s);
    if(rv) {
        printf("%s\n", DATA_FILENAME);
        error("Could not fstat file!");
    }
    DATA_SIZE = s.st_size;
    char* filename = (char*)calloc(1, 100);
    int run_length = 1;
    unsigned long num_runs = DATA_SIZE / (4*(1<<10));
    if(DATA_SIZE % (4*(1<<10))) {
        num_runs++;
    }
    printf("Sorting %lu ints (%.02f MB)...\n",
            num_runs*(4*(1<<10))/sizeof(int),
            (double)num_runs*(4*(1<<10)) / (1<<20));
    char input_prefix[] = "foo_";
    char output_prefix[] = "bar_";
    long start_usecs = get_time_usecs();
    while(num_runs > 1) {
        printf("Iterate: %lu runs left\n", num_runs);
        unsigned long num_ways = ((BUF_SIZE / (4*(1<<10))) / IO_BUF_PAGES) - 1;
        if(num_ways > num_runs) {
            num_ways = num_runs;
        }
        unsigned long num_merges = num_runs / num_ways;
        if(num_runs % num_ways) {
            num_merges++;
        }
        unsigned long run_counter = 0;
        for(int i=0; i<num_merges; i++) {
            printf("Merge %d of %lu (%lu ways)\n", i+1, num_merges, num_ways);
            unsigned long num_runs_in_merge = num_ways;
            if(run_counter >= (num_runs/num_ways)*num_ways) {
                num_runs_in_merge = num_runs % num_ways;
            }
            run_t** runs = (run_t**)calloc(num_runs_in_merge, sizeof(run_t*));
            if(run_length == 1) {
                ;
                for(int i=0; i<num_runs_in_merge; i++) {
                    runs[i] = (run_t*)calloc(1, sizeof(run_t));
                    runs[i]->items = (int*)calloc(1, (4*(1<<10)));
                    int bytes = read(sort_fd, runs[i]->items, (4*(1<<10)));
                    runs[i]->length = bytes/sizeof(int);
                    if(bytes == 0) {
                        break;
                    }
                }
                run_counter += num_runs_in_merge;
                ;
                parallel_qsort(runs, num_runs_in_merge);
                ;
            }
            else {
                for(int i=0; i<num_runs_in_merge; i++) {
                    snprintf(filename, 100, "%s%lu.dat", input_prefix, run_counter);
                    ;
                    run_counter++;
                }
            }
            snprintf(filename, 100, "%s%d.dat", output_prefix, i);
            ;
            int output_fd = open(filename, 0100|01|01000,
                    (0400|0200|0100)|((0400|0200|0100) >> 3));
            int base = 0;
            if(run_length == 1) {
                base = 1;
            }
            multimerge(runs, input_prefix, num_runs_in_merge, output_fd, base);
            close(output_fd);
            if(base == 1) {
                for(int i=0; i<num_runs_in_merge; i++) {
                    free(runs[i]->items);
                    free(runs[i]);
                }
            }
            free(runs);
        }
        strcpy(filename, output_prefix);
        strcpy(output_prefix, input_prefix);
        strcpy(input_prefix, filename);
        run_length *= num_ways;
        num_runs = num_merges;
    }
    long end_usecs = get_time_usecs();
    double secs = (double)(end_usecs - start_usecs) / (double)1000000;
    printf("Done sorting.\n");
    printf("Sorting took %.02f seconds.\n", secs);
    free(filename);
    return 0;
}

canonical_original_code:
int main(int argc, char *argv[])
{
    if(argc != 4) {
        printf("Invalid number of arguments (%d)\n", argc);
        usage();
    }
    DATA_FILENAME = argv[1];
    BUF_SIZE = atoi(argv[2])*(1<<20);
    IO_BUF_PAGES = atoi(argv[3]);
    int sort_fd = open(DATA_FILENAME, 00);
    if(sort_fd < 0) {
        error("Could not open sort_fd!");
    }
    struct stat s;
    int rv = fstat(sort_fd, &s);
    if(rv) {
        printf("%s\n", DATA_FILENAME);
        error("Could not fstat file!");
    }
    DATA_SIZE = s.st_size;
    char *filename = (char*)calloc(1, 100);
    int run_length = 1;
    unsigned long num_runs = DATA_SIZE / (4*(1<<10));
    if(DATA_SIZE % (4*(1<<10))) {
        num_runs++;
    }
    printf("Sorting %lu ints (%.02f MB)...\n",
            num_runs*(4*(1<<10))/sizeof(int),
            (double)num_runs*(4*(1<<10)) / (1<<20));
    char input_prefix[] = "foo_";
    char output_prefix[] = "bar_";
    long start_usecs = get_time_usecs();
    while(num_runs > 1) {
        printf("Iterate: %lu runs left\n", num_runs);
        unsigned long num_ways = ((BUF_SIZE / (4*(1<<10))) / IO_BUF_PAGES) - 1;
        if(num_ways > num_runs) {
            num_ways = num_runs;
        }
        unsigned long num_merges = num_runs / num_ways;
        if(num_runs % num_ways) {
            num_merges++;
        }
        unsigned long run_counter = 0;
        for(int i = 0; i<num_merges; i++) {
            printf("Merge %d of %lu (%lu ways)\n", i+1, num_merges, num_ways);
            unsigned long num_runs_in_merge = num_ways;
            if(run_counter >= (num_runs/num_ways)*num_ways) {
                num_runs_in_merge = num_runs % num_ways;
            }
            struct run_t **runs = (run_t**)calloc(num_runs_in_merge, sizeof(run_t*));
            if(run_length == 1) {
                ;
                for(int i = 0; i<num_runs_in_merge; i++) {
                    runs[i] = (struct run_t *)calloc(1, sizeof(run_t));
                    runs[i]->items = (int *)calloc(1, (4*(1<<10)));
                    int bytes = read(sort_fd, runs[i]->items, (4*(1<<10)));
                    runs[i]->length = bytes/sizeof(int);
                    if(bytes == 0) {
                        break;
                    }
                }
                run_counter += num_runs_in_merge;
                ;
                parallel_qsort(runs, num_runs_in_merge);
                ;
            }
            else {
                for(int i = 0; i<num_runs_in_merge; i++) {
                    snprintf(filename, 100, "%s%lu.dat", input_prefix, run_counter);
                    ;
                    run_counter++;
                }
            }
            snprintf(filename, 100, "%s%d.dat", output_prefix, i);
            ;
            int output_fd = open(filename, 0100|01|01000,
                    (0400|0200|0100)|((0400|0200|0100) >> 3));
            int base = 0;
            if(run_length == 1) {
                base = 1;
            }
            multimerge(runs, input_prefix, num_runs_in_merge, output_fd, base);
            close(output_fd);
            if(base == 1) {
                for(int i = 0; i<num_runs_in_merge; i++) {
                    free(runs[i]->items);
                    free(runs[i]);
                }
            }
            free(runs);
        }
        strcpy(filename, output_prefix);
        strcpy(output_prefix, input_prefix);
        strcpy(input_prefix, filename);
        run_length *= num_ways;
        num_runs = num_merges;
    }
    long end_usecs = get_time_usecs();
    double secs = (double)(end_usecs - start_usecs) / (double)1000000;
    printf("Done sorting.\n");
    printf("Sorting took %.02f seconds.\n", secs);
    free(filename);
    return 0;
}

variable_types: argc int

variable_types:
argv
char *[]

variable_types: struct run_t { int length; int *items; } **

variable_types: bytes int

variable_types: base int

variable_types: secs double

return_type: int

user_defined_types: struct timespec { long tv_sec; long tv_nsec; }


bubble

decompiled_code:
__int64 __fastcall bubble(__int64 a1, int a2, int a3)
{
int v5; // er10
int v6; // er12
__int64 v7; // rbp
__int64 v9; // r9
int i; // er8
__int64 v11; // rdi
int v12; // esi
int v13; // eax
__int64 result; // rax

if ( a3 != a2 && a3 >= a2 )
{
v5 = a3 - 1;
v6 = a2 + a3 - 1;
v7 = 4LL * a2;
do
{
v9 = v7;
for ( i = a2; v5 >= i; swap_isra_0(v11, v12, i) )
{
while ( 1 )
{
v11 = *(_QWORD *)(a1 + 8);
v12 = i++;
v13 = *(_DWORD *)(v11 + v9);
v9 += 4LL;
if ( v13 > *(_DWORD *)(v11 + v9) )
break;
if ( v5 < i )
goto LABEL_9;
}
}
LABEL_9:
--v5;
result = (unsigned int)(v6 - v5);
}
while ( (int)result <= a3 );
}
return result;
}

original_code:
static void bubble(run_t* data_ptr, int left, int right)
{
    int i,j;
    if(right == left) {
        return;
    }
    for(i=left; i<=right; i++) {
        for(j=left; j<=right-1-(i-left); j++) {
            if(data_ptr->items[j] > data_ptr->items[j+1]) {
                swap(data_ptr, j, j+1);
            }
        }
    }
}

canonical_original_code:
static void bubble(struct run_t *data_ptr, int left, int right)
{
    int i; int j;
    if(right == left) {
        return;
    }
    for(i=left; i<=right; i++) {
        for(j=left; j<=right-1-(i-left); j++) {
            if(data_ptr->items[j] > data_ptr->items[j+1]) {
                swap(data_ptr, j, j+1);
            }
        }
    }
}

variable_types: struct run_t { int length; int *items; } *

variable_types: left int

variable_types: right int

variable_types: j int


partition

original_code:
static int partition(run_t* data_ptr, int left, int right, int pivot_index)
{
    int pivot_value = data_ptr->items[pivot_index];
    swap(data_ptr, pivot_index, right);
    int store_index = left;
    int i;
    for(i=left; i<right; i++) {
        if(data_ptr->items[i] <= pivot_value) {
            swap(data_ptr, store_index, i);
            store_index++;
        }
        for(int i=0; i<data_ptr->length; i++) {
        }
    }
    swap(data_ptr, store_index, right);
    return store_index;
}

canonical_original_code:
static int partition(struct run_t *data_ptr, int left, int right, int pivot_index)
{
    int pivot_value = data_ptr->items[pivot_index];
    swap(data_ptr, pivot_index, right);
    int store_index = left;
    int i;
    for(i=left; i<right; i++) {
        if(data_ptr->items[i] <= pivot_value) {
            swap(data_ptr, store_index, i);
            store_index++;
        }
        for(int i = 0; i<data_ptr->length; i++) {
        }
    }
    swap(data_ptr, store_index, right);
    return store_index;
}

user_defined_types: struct run_t { int length; int *items; }


decompiled_code:
void __fastcall qsort_recurse(__int64 a1, signed int a2, int a3)
{
int v3; // er12
unsigned int v4; // ebp
unsigned int v5; // eax
signed int v6; // er14
int v7; // er13
__int64 v8; // rsi
__int64 v9; // rdx

if ( a3 > a2 )
{
v3 = a3;
v4 = a2;
while ( (int)(v3 - v4) > 4 )
{
v5 = partition(a1, v4, v3, (int)(v3 + v4) / 2);
v6 = v5 - 1;
v7 = v5;
if ( (int)(v5 - 1 - v4) >= (int)(v3 - v5) )
{
v9 = (unsigned int)v3;
v3 = v5 - 1;
qsort_recurse(a1, v5, v9);
if ( v6 <= (int)v4 )
return;
}
else
{
v8 = v4;
v4 = v5;
qsort_recurse(a1, v8, (unsigned int)v6);
if ( v3 <= v7 )
return;
}
}
bubble(a1, v4, v3);
}
}

canonical_decompiled_code:
void __fastcall func3(__int64 a1, signed int a2, int a3)
{
int v3; // er12
unsigned int v4; // ebp
unsigned int v5; // eax
signed int v6; // er14
int v7; // er13
__int64 v8; // rsi
__int64 v9; // rdx

if ( a3 > a2 )
{
v3 = a3;
v4 = a2;
while ( (int)(v3 - v4) > 4 )
{
v5 = func2(a1, v4, v3, (int)(v3 + v4) / 2);
v6 = v5 - 1;
v7 = v5;
if ( (int)(v5 - 1 - v4) >= (int)(v3 - v5) )
{
v9 = (unsigned int)v3;
v3 = v5 - 1;
func3(a1, v5, v9);
if ( v6 <= (int)v4 )
return;
}
else
{
v8 = v4;
v4 = v5;
func3(a1, v8, (unsigned int)v6);
if ( v3 <= v7 )
return;
}
}
func1(a1, v4, v3);
}
}

original_code:
static void qsort_recurse(run_t* data_ptr, int left, int right)
{
    if(right > left)
    {
        if(right-left < 5) {
            return bubble(data_ptr, left, right);
        }
        int pivot_index = (right+left)/2;
        int new_pivot_index = partition(data_ptr, left, right, pivot_index);
        if(new_pivot_index-1-left < right-new_pivot_index) {
            qsort_recurse(data_ptr, left, new_pivot_index-1);
            return qsort_recurse(data_ptr, new_pivot_index, right);
        } else {
            qsort_recurse(data_ptr, new_pivot_index, right);
            return qsort_recurse(data_ptr, left, new_pivot_index-1);
        }
    }
}

canonical_original_code:
static void qsort_recurse(struct run_t *data_ptr, int left, int right)
{
    if(right > left)
    {
        if(right-left < 5) {
            return bubble(data_ptr, left, right);
        }
        int pivot_index = (right+left)/2;
        int new_pivot_index = partition(data_ptr, left, right, pivot_index);
        if(new_pivot_index-1-left < right-new_pivot_index) {
            qsort_recurse(data_ptr, left, new_pivot_index-1);
            return qsort_recurse(data_ptr, new_pivot_index, right);
        } else {
            qsort_recurse(data_ptr, new_pivot_index, right);
            return qsort_recurse(data_ptr, left, new_pivot_index-1);
        }
    }
}


decompiled_code:
void __fastcall ext_qsort(_DWORD *a1)
{
qsort_recurse((__int64)a1, 0, *a1 - 1);
}

canonical_decompiled_code:
void __fastcall func4(_DWORD *a1)
{
func3((__int64)a1, 0, *a1 - 1);
}

original_code:
void ext_qsort(run_t* data_ptr)
{
    qsort_recurse(data_ptr, 0, data_ptr->length-1);
}

canonical_original_code:
void ext_qsort(struct run_t *data_ptr)
{
    qsort_recurse(data_ptr, 0, data_ptr->length-1);
}


original_code:
static void* qsort_worker(void *worker_ptr)
{
    worker_data_t* data = (worker_data_t*)worker_ptr;
    for(int i=data->offset; i<data->offset+data->length; i++) {
        ext_qsort(data->runs[i]);
    }
    return ((void *)0);
}

canonical_original_code:
static void *qsort_worker(void *worker_ptr)
{
    struct worker_data *data = (worker_data_t*)worker_ptr;
    for(int i = data->offset; i<data->offset+data->length; i++) {
        ext_qsort(data->runs[i]);
    }
    return ((void *)0);
}

variable_types: struct worker_data { int offset; int length; struct run_t { int length; int *items; } **runs; } *

return_type: void *

user_defined_types: struct worker_data { int offset; int length; struct run_t **runs; }


original_code:
void parallel_qsort(run_t** runs, int num_runs)
{
    worker_data_t** runs_per_thread;
    runs_per_thread = (worker_data_t**)calloc(1, 8*sizeof(worker_data_t*));
    int remainder = num_runs % 8;
    int offset = 0;
    for(int i=0; i<8; i++) {
        runs_per_thread[i] = (worker_data_t*)calloc(1, sizeof(worker_data_t));
        runs_per_thread[i]->offset = offset;
        runs_per_thread[i]->length = num_runs / 8;
        runs_per_thread[i]->runs = runs;
        if(remainder) {
            runs_per_thread[i]->length++;
            remainder--;
        }
        offset += runs_per_thread[i]->length;
    }
    pthread_t workers[8];
    for(int i=0; i<8; i++) {
        pthread_create(&workers[i], ((void *)0), qsort_worker,
                runs_per_thread[i]);
    }
    for(int i=0; i<8; i++) {
        pthread_join(workers[i], ((void *)0));
    }
    for(int i=0; i<8; i++) {
        free(runs_per_thread[i]);
    }
    free(runs_per_thread);
}

canonical_original_code:
void parallel_qsort(struct run_t **runs, int num_runs)
{
    struct worker_data **runs_per_thread;
    runs_per_thread = (struct worker_data **)calloc(1, 8*sizeof(struct worker_data *));
    int remainder = num_runs % 8;
    int offset = 0;
    for(int i = 0; i<8; i++) {
        runs_per_thread[i] = (struct worker_data *)calloc(1, sizeof(worker_data_t));
        runs_per_thread[i]->offset = offset;
        runs_per_thread[i]->length = num_runs / 8;
        runs_per_thread[i]->runs = runs;
        if(remainder) {
            runs_per_thread[i]->length++;
            remainder--;
        }
        offset += runs_per_thread[i]->length;
    }
    unsigned long workers[8];
    for(int i = 0; i<8; i++) {
        pthread_create(&workers[i], ((void *)0), qsort_worker,
                runs_per_thread[i]);
    }
    for(int i = 0; i<8; i++) {
        pthread_join(workers[i], ((void *)0));
    }
    for(int i = 0; i<8; i++) {
        free(runs_per_thread[i]);
    }
    free(runs_per_thread);
}

variable_types: struct worker_data { int offset; int length; struct run_t { int length; int *items; } **runs; } **

variable_types: remainder int

variable_types: offset int

variable_types:
workers
unsigned long [8]


repo: umegaya/pfm

original_code:
void rbtree_insert_fixup(util_rbtree_t *rbtree, util_rbtree_node_t *node)
{
    util_rbtree_node_t *p, *u;
    while(((node->parent)->color == 0))
    {
        p = node->parent;
        if(p == p->parent->left)
        {
            u = p->parent->right;
            if(((u)->color == 0))
            {
                ((u)->color = 1);
                ((p)->color = 1);
                ((p->parent)->color = 0);
                node = p->parent;
            }
            else
            {
                if(node == p->right)
                {
                    node = p;
                    rbtree_left_rotate(rbtree, node);
                    p = node->parent;
                }
                ((p)->color = 1);
                ((p->parent)->color = 0);
                rbtree_right_rotate(rbtree, p->parent);
            }
        }
        else
        {
            u = p->parent->left;
   if(((u)->color == 0))
   {
    ((u)->color = 1);
    ((p)->color = 1);
    ((p->parent)->color = 0);
                node = p->parent;
   }
   else
   {
    if(p->left == node)
    {
     node = p;
     rbtree_right_rotate(rbtree, node);
     p = node->parent;
    }
    ((p)->color = 1);
    ((p->parent)->color = 0);
    rbtree_left_rotate(rbtree, p->parent);
   }
        }
    }
    ((rbtree->root)->color = 1);
}

canonical_original_code:
void rbtree_insert_fixup(struct util_rbtree_s *rbtree, struct util_rbtree_node_s *node)
{
    struct util_rbtree_node_s *p; struct util_rbtree_node_s *u;
    while(((node->parent)->color == 0))
    {
        p = node->parent;
        if(p == p->parent->left)
        {
            u = p->parent->right;
            if(((u)->color == 0))
            {
                ((u)->color = 1);
                ((p)->color = 1);
                ((p->parent)->color = 0);
                node = p->parent;
            }
            else
            {
                if(node == p->right)
                {
                    node = p;
                    rbtree_left_rotate(rbtree, node);
                    p = node->parent;
                }
                ((p)->color = 1);
                ((p->parent)->color = 0);
                rbtree_right_rotate(rbtree, p->parent);
            }
        }
        else
        {
            u = p->parent->left;
   if(((u)->color == 0))
   {
    ((u)->color = 1);
    ((p)->color = 1);
    ((p->parent)->color = 0);
                node = p->parent;
   }
   else
   {
    if(p->left == node)
    {
     node = p;
     rbtree_right_rotate(rbtree, node);
     p = node->parent;
    }
    ((p)->color = 1);
    ((p->parent)->color = 0);
    rbtree_left_rotate(rbtree, p->parent);
   }
        }
    }
    ((rbtree->root)->color = 1);
}

variable_types: struct util_rbtree_s { struct util_rbtree_node_s { long key; struct util_rbtree_node_s *parent; struct util_rbtree_node_s *right; struct util_rbtree_node_s *left; int color; void *data; } *root; struct util_rbtree_node_s null; unsigned int size; } *

variable_types:
node
struct util_rbtree_node_s *

user_defined_types: struct util_rbtree_s { struct util_rbtree_node_s *root; struct util_rbtree_node_s null; unsigned int size; }


original_code:
void rbtree_delete_fixup(util_rbtree_t *rbtree, util_rbtree_node_t *node)
{
    int h = 0;
    util_rbtree_node_t *w;
 while((node != rbtree->root) && ((node)->color == 1))
 {
        h++;
        if(node == node->parent->left)
        {
            w = node->parent->right;
            if(((w)->color == 0))
            {
                ((w)->color = 1);
                ((node->parent)->color = 0);
                rbtree_left_rotate(rbtree, node->parent);
                w = node->parent->right;
            }
            if(((w->left)->color == 1) && ((w->right)->color == 1))
            {
                ((w)->color = 0);
                node = node->parent;
            }
            else
            {
                if(((w->right)->color == 1))
                {
                    ((w->left)->color = 1);
                    ((w)->color = 0);
                    rbtree_right_rotate(rbtree, w);
                    w = node->parent->right;
                }
                w->color = node->parent->color;
                ((node->parent)->color = 1);
                ((w->right)->color = 1);
                rbtree_left_rotate(rbtree, node->parent);
                node = rbtree->root;
            }
        }
        else
        {
            w = node->parent->left;
            if(w == 0)
            {
                int t = 4;
            }
            if(((w)->color == 0))
            {
                ((w)->color = 1);
                ((node->parent)->color = 0);
                rbtree_right_rotate(rbtree, node->parent);
                w = node->parent->left;
            }
            if(((w->left)->color == 1) && ((w->right)->color == 1))
            {
                ((w)->color = 0);
                node = node->parent;
            }
            else
            {
                if(((w->left)->color == 1))
                {
                    ((w->right)->color = 1);
                    ((w)->color = 0);
                    rbtree_left_rotate(rbtree, w);
                    w = node->parent->left;
                }
                w->color = node->parent->color;
                ((node->parent)->color = 1);
                ((w->left)->color = 1);
                rbtree_right_rotate(rbtree, node->parent);
                node = rbtree->root;
            }
        }
 }
    ((node)->color = 1);
}

canonical_original_code:
void rbtree_delete_fixup(struct util_rbtree_s *rbtree, struct util_rbtree_node_s *node)
{
    int h = 0;
    struct util_rbtree_node_s *w;
 while((node != rbtree->root) && ((node)->color == 1))
 {
        h++;
        if(node == node->parent->left)
        {
            w = node->parent->right;
            if(((w)->color == 0))
            {
                ((w)->color = 1);
                ((node->parent)->color = 0);
                rbtree_left_rotate(rbtree, node->parent);
                w = node->parent->right;
            }
            if(((w->left)->color == 1) && ((w->right)->color == 1))
            {
                ((w)->color = 0);
                node = node->parent;
            }
            else
            {
                if(((w->right)->color == 1))
                {
                    ((w->left)->color = 1);
                    ((w)->color = 0);
                    rbtree_right_rotate(rbtree, w);
                    w = node->parent->right;
                }
                w->color = node->parent->color;
                ((node->parent)->color = 1);
                ((w->right)->color = 1);
                rbtree_left_rotate(rbtree, node->parent);
                node = rbtree->root;
            }
        }
        else
        {
            w = node->parent->left;
            if(w == 0)
            {
                int t = 4;
            }
            if(((w)->color == 0))
            {
                ((w)->color = 1);
                ((node->parent)->color = 0);
                rbtree_right_rotate(rbtree, node->parent);
                w = node->parent->left;
            }
            if(((w->left)->color == 1) && ((w->right)->color == 1))
            {
                ((w)->color = 0);
                node = node->parent;
            }
            else
            {
                if(((w->left)->color == 1))
                {
                    ((w->right)->color = 1);
                    ((w)->color = 0);
                    rbtree_left_rotate(rbtree, w);
                    w = node->parent->left;
                }
                w->color = node->parent->color;
                ((node->parent)->color = 1);
                ((w->left)->color = 1);
                rbtree_right_rotate(rbtree, node->parent);
                node = rbtree->root;
            }
        }
 }
    ((node)->color = 1);
}

variable_types: h int

variable_types: struct util_rbtree_node_s { long key; struct util_rbtree_node_s *parent; struct util_rbtree_node_s *right; struct util_rbtree_node_s *left; int color; void *data; } *

variable_types: t int


original_code:
static void rbtree_check_subtree(const util_rbtree_node_t *node, rbtree_check_t *check,
                         int level, int curheight)
{
    if(check->fini)
    {
        return;
    }
    if(((node)->color == 1))
    {
        curheight++;
    }
    else if(!((node)->color == 0))
    {
        check->fini = 2;
        return;
    }
    if(node->left != check->null)
    {
        if(((node)->color == 0) && ((node->left)->color == 0))
        {
            check->fini = 4;
            return;
        }
        if(node->key < node->left->key)
        {
            check->fini = 5;
            return;
        }
        rbtree_check_subtree(node->left, check, level+1, curheight);
    }
    else
    {
        goto __check_rb_height;
    }
    if(node->right != check->null)
    {
        if(((node)->color == 0) && ((node->right)->color == 0))
        {
            check->fini = 4;
            return;
        }
        if(node->key > node->right->key)
        {
            check->fini = 5;
            return;
        }
        rbtree_check_subtree(node->right, check, level+1, curheight);
    }
    else
    {
        goto __check_rb_height;
    }
    return;
__check_rb_height:
    if(check->rbh == 0)
    {
        check->rbh = curheight;
    }
    if(check->maxd < level)
    {
        check->maxd = level;
    }
    if(check->rbh != curheight)
    {
        check->fini = 3;
    }
}

canonical_original_code:
static void rbtree_check_subtree(struct util_rbtree_node_s *node, struct rbtree_check_s *check, int level, int curheight)
{
    if(check->fini)
    {
        return;
    }
    if(((node)->color == 1))
    {
        curheight++;
    }
    else if(!((node)->color == 0))
    {
        check->fini = 2;
        return;
    }
    if(node->left != check->null)
    {
        if(((node)->color == 0) && ((node->left)->color == 0))
        {
            check->fini = 4;
            return;
        }
        if(node->key < node->left->key)
        {
            check->fini = 5;
            return;
        }
        rbtree_check_subtree(node->left, check, level+1, curheight);
    }
    else
    {
        goto __check_rb_height;
    }
    if(node->right != check->null)
    {
        if(((node)->color == 0) && ((node->right)->color == 0))
        {
            check->fini = 4;
            return;
        }
        if(node->key > node->right->key)
        {
            check->fini = 5;
            return;
        }
        rbtree_check_subtree(node->right, check, level+1, curheight);
    }
    else
    {
        goto __check_rb_height;
    }
    return;
__check_rb_height:
    if(check->rbh == 0)
    {
        check->rbh = curheight;
    }
    if(check->maxd < level)
    {
        check->maxd = level;
    }
    if(check->rbh != curheight)
    {
        check->fini = 3;
    }
}

variable_types: struct rbtree_check_s { short rbh; short maxd; int fini; struct util_rbtree_node_s *null; } *

variable_types: level int

variable_types: curheight int

user_defined_types: struct util_rbtree_node_s { long key; struct util_rbtree_node_s *parent; struct util_rbtree_node_s *right; struct util_rbtree_node_s *left; int color; void *data; }


decompiled_code:
__int64 __fastcall rbtree_mid_travel(__int64 a1, __int64 a2, __int64 (__fastcall *a3)(__int64, __int64), __int64 a4)
{
__int64 v7; // rdi
__int64 result; // rax

do
{
v7 = *(_QWORD *)(a1 + 24);
if ( v7 != a2 )
rbtree_mid_travel(v7, a2, a3, a4);
result = a3(a1, a4);
a1 = *(_QWORD *)(a1 + 16);
}
while ( a1 != a2 );
return result;
}

original_code:
static void rbtree_mid_travel(util_rbtree_node_t *node, util_rbtree_node_t *sentinel,
                         void(*opera)(util_rbtree_node_t *, void *), void *data)
{
    if(node->left != sentinel)
    {
        rbtree_mid_travel(node->left, sentinel, opera, data);
    }
    opera(node, data);
    if(node->right != sentinel)
    {
        rbtree_mid_travel(node->right, sentinel, opera, data);
    }
}

canonical_original_code:
static void rbtree_mid_travel(struct util_rbtree_node_s *node, struct util_rbtree_node_s *sentinel, void (*opera)(struct util_rbtree_node_s *, void *), void *data)
{
    if(node->left != sentinel)
    {
        rbtree_mid_travel(node->left, sentinel, opera, data);
    }
    opera(node, data);
    if(node->right != sentinel)
    {
        rbtree_mid_travel(node->right, sentinel, opera, data);
    }
}

variable_types:
sentinel
struct util_rbtree_node_s *

variable_types: void (*)(struct util_rbtree_node_s *, void *)

variable_types:
data
void *


decompiled_code:
__int64 __fastcall util_rbtree_init(__int64 a1)
{
__int64 result; // rax

if ( a1 )
{
result = a1 + 8;
*(_DWORD *)(a1 + 40) = 1;
*(_QWORD *)a1 = a1 + 8;
*(_DWORD *)(a1 + 56) = 0;
}
return result;
}

original_code:
void util_rbtree_init(util_rbtree_t *rbtree)
{
 if(rbtree != ((void *)0))
 {
  (((&((rbtree)->null)))->color = 1);
  rbtree->root = (&((rbtree)->null));
  rbtree->size = 0;
 }
}

canonical_original_code:
void util_rbtree_init(struct util_rbtree_s *rbtree)
{
 if(rbtree != ((void *)0))
 {
  (((&((rbtree)->null)))->color = 1);
  rbtree->root = (&((rbtree)->null));
  rbtree->size = 0;
 }
}


decompiled_code:
__int64 __fastcall util_rbsubtree_min(__int64 a1, __int64 a2)
{
__int64 result; // rax

if ( a1 == a2 )
return 0LL;
do
{
result = a1;
a1 = *(_QWORD *)(a1 + 24);
}
while ( a1 != a2 );
return result;
}

canonical_decompiled_code:
__int64 __fastcall func7(__int64 a1, __int64 a2)
{
__int64 result; // rax

if ( a1 == a2 )
return 0LL;
do
{
result = a1;
a1 = *(_QWORD *)(a1 + 24);
}
while ( a1 != a2 );
return result;
}

original_code:
util_rbtree_node_t* util_rbsubtree_min(util_rbtree_node_t *node, util_rbtree_node_t *sentinel)
{
    if(node == sentinel) return ((void *)0);
    while(node->left != sentinel) node = node->left;
    return node;
}

canonical_original_code:
struct util_rbtree_node_s *util_rbsubtree_min(struct util_rbtree_node_s *node, struct util_rbtree_node_s *sentinel)
{
    if(node == sentinel) return ((void *)0);
    while(node->left != sentinel) node = node->left;
    return node;
}

return_type: struct util_rbtree_node_s { long key; struct util_rbtree_node_s *parent; struct util_rbtree_node_s *right; struct util_rbtree_node_s *left; int color; void *data; } *


decompiled_code:
__int64 __fastcall util_rbsubtree_max(__int64 a1, __int64 a2)
{
__int64 result; // rax

if ( a1 == a2 )
return 0LL;
do
{
result = a1;
a1 = *(_QWORD *)(a1 + 16);
}
while ( a1 != a2 );
return result;
}

canonical_decompiled_code:
__int64 __fastcall func8(__int64 a1, __int64 a2)
{
__int64 result; // rax

if ( a1 == a2 )
return 0LL;
do
{
result = a1;
a1 = *(_QWORD *)(a1 + 16);
}
while ( a1 != a2 );
return result;
}

original_code:
util_rbtree_node_t* util_rbsubtree_max(util_rbtree_node_t *node, util_rbtree_node_t *sentinel)
{
    if(node == sentinel) return ((void *)0);
    while(node->right != sentinel) node = node->right;
    return node;
}

canonical_original_code:
struct util_rbtree_node_s *util_rbsubtree_max(struct util_rbtree_node_s *node, struct util_rbtree_node_s *sentinel)
{
    if(node == sentinel) return ((void *)0);
    while(node->right != sentinel) node = node->right;
    return node;
}


original_code:
void util_rbtree_insert(util_rbtree_t *rbtree, util_rbtree_node_t *node)
{
    util_rbtree_node_t *x, *y;
 if((rbtree==((void *)0)) || (node==((void *)0)) || (node==(&((rbtree)->null))))
 {
  return;
 }
    if(rbtree->root == (&((rbtree)->null)))
    {
        rbtree->root = node;
        node->parent = (&((rbtree)->null));
    }
    else
    {
        x = rbtree->root;
        while(x != (&((rbtree)->null)))
        {
            y = x;
            if(node->key < x->key) x = x->left;
            else x = x->right;
        }
        node->parent = y;
        if(node->key < y->key) y->left = node;
        else y->right = node;
    }
    node->left = (&((rbtree)->null));
    node->right = (&((rbtree)->null));
    ((node)->color = 0);
    rbtree_insert_fixup(rbtree, node);
 rbtree->size++;
}

canonical_original_code:
void util_rbtree_insert(struct util_rbtree_s *rbtree, struct util_rbtree_node_s *node)
{
    struct util_rbtree_node_s *x; struct util_rbtree_node_s *y;
 if((rbtree==((void *)0)) || (node==((void *)0)) || (node==(&((rbtree)->null))))
 {
  return;
 }
    if(rbtree->root == (&((rbtree)->null)))
    {
        rbtree->root = node;
        node->parent = (&((rbtree)->null));
    }
    else
    {
        x = rbtree->root;
        while(x != (&((rbtree)->null)))
        {
            y = x;
            if(node->key < x->key) x = x->left;
            else x = x->right;
        }
        node->parent = y;
        if(node->key < y->key) y->left = node;
        else y->right = node;
    }
    node->left = (&((rbtree)->null));
    node->right = (&((rbtree)->null));
    ((node)->color = 0);
    rbtree_insert_fixup(rbtree, node);
 rbtree->size++;
}


original_code:
void util_rbtree_delete(util_rbtree_t *rbtree, util_rbtree_node_t *node)
{
 int isblack;
 util_rbtree_node_t *temp, *subst;
 if((rbtree==((void *)0)) || (node==((void *)0)) || (node==(&((rbtree)->null))))
 {
  return;
 }
 rbtree->size--;
 if(node->left == (&((rbtree)->null)))
 {
  temp = node;
  subst = node->right;
 }
 else if(node->right == (&((rbtree)->null)))
 {
  temp = node;
  subst = node->left;
 }
 else
 {
  temp = util_rbsubtree_min(node->right, (&((rbtree)->null)));
  if(temp->left != (&((rbtree)->null)))
  {
   subst = temp->left;
  }
  else
  {
   subst = temp->right;
  }
 }
 if(temp == rbtree->root)
 {
  rbtree->root = subst;
  ((subst)->color = 1);
  do{ temp->left = ((void *)0); temp->right = ((void *)0); temp->parent = ((void *)0); }while(0);
  return;
 }
 isblack = ((temp)->color == 1);
    if(temp->parent == node)
    {
        subst->parent = temp;
    }
    else
    {
        subst->parent = temp->parent;
    }
 if(temp == temp->parent->left)
 {
  temp->parent->left = subst;
 }
 else
 {
  temp->parent->right = subst;
 }
 if(temp != node)
 {
  temp->parent = node->parent;
  if(node == rbtree->root)
  {
   rbtree->root = temp;
  }
  else
        {
   if(node->parent->left == node)
   {
    node->parent->left = temp;
   }
   else
   {
    node->parent->right = temp;
   }
  }
  temp->right = node->right;
  temp->left = node->left;
  if(temp->left != (&((rbtree)->null)))
  {
   temp->left->parent = temp;
  }
  if(temp->right != (&((rbtree)->null)))
  {
   temp->right->parent = temp;
  }
  temp->color = node->color;
 }
 do{ node->left = ((void *)0); node->right = ((void *)0); node->parent = ((void *)0); }while(0);
 if(isblack)
 {
  rbtree_delete_fixup(rbtree, subst);
 }
}

canonical_original_code:
void util_rbtree_delete(struct util_rbtree_s *rbtree, struct util_rbtree_node_s *node)
{
 int isblack;
 struct util_rbtree_node_s *temp; struct util_rbtree_node_s *subst;
 if((rbtree==((void *)0)) || (node==((void *)0)) || (node==(&((rbtree)->null))))
 {
  return;
 }
 rbtree->size--;
 if(node->left == (&((rbtree)->null)))
 {
  temp = node;
  subst = node->right;
 }
 else if(node->right == (&((rbtree)->null)))
 {
  temp = node;
  subst = node->left;
 }
 else
 {
  temp = util_rbsubtree_min(node->right, (&((rbtree)->null)));
  if(temp->left != (&((rbtree)->null)))
  {
   subst = temp->left;
  }
  else
  {
   subst = temp->right;
  }
 }
 if(temp == rbtree->root)
 {
  rbtree->root = subst;
  ((subst)->color = 1);
  do{ temp->left = ((void *)0); temp->right = ((void *)0); temp->parent = ((void *)0); }while(0);
  return;
 }
 isblack = ((temp)->color == 1);
    if(temp->parent == node)
    {
        subst->parent = temp;
    }
    else
    {
        subst->parent = temp->parent;
    }
 if(temp == temp->parent->left)
 {
  temp->parent->left = subst;
 }
 else
 {
  temp->parent->right = subst;
 }
 if(temp != node)
 {
  temp->parent = node->parent;
  if(node == rbtree->root)
  {
   rbtree->root = temp;
  }
  else
        {
   if(node->parent->left == node)
   {
    node->parent->left = temp;
   }
   else
   {
    node->parent->right = temp;
   }
  }
  temp->right = node->right;
  temp->left = node->left;
  if(temp->left != (&((rbtree)->null)))
  {
   temp->left->parent = temp;
  }
  if(temp->right != (&((rbtree)->null)))
  {
   temp->right->parent = temp;
  }
  temp->color = node->color;
 }
 do{ node->left = ((void *)0); node->right = ((void *)0); node->parent = ((void *)0); }while(0);
 if(isblack)
 {
  rbtree_delete_fixup(rbtree, subst);
 }
}

variable_types: isblack int


decompiled_code:
__int64 __fastcall util_rbtree_check(__int64 *a1)
{
__int64 v1; // r10
__int64 v2; // rdi
__int64 result; // rax
_DWORD *v4; // r8
_DWORD *v5; // r9
__int64 v6[3]; // [rsp+0h] [rbp-18h] BYREF

v1 = *a1;
v2 = (__int64)(a1 + 1);
if ( v1 == v2 )
return 0LL;
result = 1LL;
if ( *(_DWORD *)(v1 + 32) == 1 )
{
v6[1] = v2;
v6[0] = 0LL;
rbtree_check_subtree(v1, (__int16 *)v6, 1, 0);
if ( v5 )
*v5 = SLOWORD(v6[0]);
if ( v4 )
*v4 = SWORD1(v6[0]);
result = HIDWORD(v6[0]);
}
return result;
}

original_code:
int util_rbtree_check(const util_rbtree_t *rbtree, int *blackheight, int *maxdepth)
{
    rbtree_check_t check;
    if(rbtree->root == (&((rbtree)->null)))
    {
        return 0;
    }
    if(!((rbtree->root)->color == 1))
    {
        return 1;
    }
    check.fini = check.maxd = check.rbh = 0;
    check.null = (&((rbtree)->null));
    rbtree_check_subtree(rbtree->root, &check, 1, 0);
    if(blackheight)
    {
        *blackheight = check.rbh;
    }
    if(maxdepth)
    {
        *maxdepth = check.maxd;
    }
    return check.fini;
}

canonical_original_code:
int util_rbtree_check(struct util_rbtree_s *rbtree, int *blackheight, int *maxdepth)
{
    struct rbtree_check_s check;
    if(rbtree->root == (&((rbtree)->null)))
    {
        return 0;
    }
    if(!((rbtree->root)->color == 1))
    {
        return 1;
    }
    check.fini = check.maxd = check.rbh = 0;
    check.null = (&((rbtree)->null));
    rbtree_check_subtree(rbtree->root, &check, 1, 0);
    if(blackheight)
    {
        *blackheight = check.rbh;
    }
    if(maxdepth)
    {
        *maxdepth = check.maxd;
    }
    return check.fini;
}

variable_types:
blackheight
int *

variable_types:
maxdepth
int *

variable_types: struct rbtree_check_s { short rbh; short maxd; int fini; struct util_rbtree_node_s { long key; struct util_rbtree_node_s *parent; struct util_rbtree_node_s *right; struct util_rbtree_node_s *left; int color; void *data; } *null; }

user_defined_types: struct rbtree_check_s { short rbh; short maxd; int fini; struct util_rbtree_node_s *null; }


decompiled_code:
__int64 __fastcall util_rbtree_mid_travel(__int64 *a1, __int64 (__fastcall *a2)(__int64, __int64), __int64 a3)
{
__int64 result; // rax

if ( a1 )
{
if ( (__int64 *)*a1 != a1 + 1 )
result = rbtree_mid_travel(*a1, (__int64)(a1 + 1), a2, a3);
}
return result;
}

original_code:
void util_rbtree_mid_travel(util_rbtree_t *rbtree,
                            void(*opera)(util_rbtree_node_t *, void *), void *data)
{
    if((rbtree!=((void *)0)) && !((rbtree)->root == &(rbtree)->null))
    {
        rbtree_mid_travel(rbtree->root, (&((rbtree)->null)), opera, data);
    }
}

canonical_original_code:
void util_rbtree_mid_travel(struct util_rbtree_s *rbtree, void (*opera)(struct util_rbtree_node_s *, void *), void *data)
{
    if((rbtree!=((void *)0)) && !((rbtree)->root == &(rbtree)->null))
    {
        rbtree_mid_travel(rbtree->root, (&((rbtree)->null)), opera, data);
    }
}


decompiled_code:
void __fastcall nbr_conhash_fin(void *ptr)
{
__int64 i; // r12

if ( ptr )
{
for ( i = *(_QWORD *)ptr; *(void **)ptr != (char *)ptr + 8; i = *(_QWORD *)ptr )
{
util_rbtree_delete(ptr, i);
_conhash_del_rbnode(ptr, i);
}
if ( *((_QWORD *)ptr + 9) )
{
nbr_array_destroy();
*((_QWORD *)ptr + 9) = 0LL;
}
if ( *((_QWORD *)ptr + 10) )
{
nbr_array_destroy();
*((_QWORD *)ptr + 10) = 0LL;
}
if ( *((_QWORD *)ptr + 12) )
nbr_rwlock_destroy();
free(ptr);
}
}

canonical_decompiled_code:
void __fastcall func0(void *ptr)
{
__int64 i; // r12

if ( ptr )
{
for ( i = *(_QWORD *)ptr; *(void **)ptr != (char *)ptr + 8; i = *(_QWORD *)ptr )
{
util_rbtree_delete(ptr, i);
_conhash_del_rbnode(ptr, i);
}
if ( *((_QWORD *)ptr + 9) )
{
nbr_array_destroy();
*((_QWORD *)ptr + 9) = 0LL;
}
if ( *((_QWORD *)ptr + 10) )
{
nbr_array_destroy();
*((_QWORD *)ptr + 10) = 0LL;
}
if ( *((_QWORD *)ptr + 12) )
nbr_rwlock_destroy();
free(ptr);
}
}

original_code:
extern
void nbr_conhash_fin(CONHASH ch)
{
 struct conhash_s *conhash = (struct conhash_s *)ch;
 if(conhash != ((void *)0))
 {
        while(!((&(conhash->vnode_tree))->root == &(&(conhash->vnode_tree))->null))
        {
            util_rbtree_node_t *rbnode = conhash->vnode_tree.root;
            util_rbtree_delete(&(conhash->vnode_tree), rbnode);
            __conhash_del_rbnode(conhash, rbnode);
        }
  if (conhash->vnode_a) {
   nbr_array_destroy(conhash->vnode_a);
   conhash->vnode_a = ((void *)0);
  }
  if (conhash->rbnode_a) {
   nbr_array_destroy(conhash->rbnode_a);
   conhash->rbnode_a = ((void *)0);
  }
  if (conhash->lock) {
   nbr_rwlock_destroy(conhash->lock);
   conhash->lock = ((void *)0);
  }
  free(conhash);
 }
}

canonical_original_code:
extern void nbr_conhash_fin(void *ch)
{
 struct conhash_s *conhash = (struct conhash_s *)ch;
 if(conhash != ((void *)0))
 {
        while(!((&(conhash->vnode_tree))->root == &(&(conhash->vnode_tree))->null))
        {
            struct util_rbtree_node_s *rbnode = conhash->vnode_tree.root;
            util_rbtree_delete(&(conhash->vnode_tree), rbnode);
            __conhash_del_rbnode(conhash, rbnode);
        }
  if (conhash->vnode_a) {
   nbr_array_destroy(conhash->vnode_a);
   conhash->vnode_a = ((void *)0);
  }
  if (conhash->rbnode_a) {
   nbr_array_destroy(conhash->rbnode_a);
   conhash->rbnode_a = ((void *)0);
  }
  if (conhash->lock) {
   nbr_rwlock_destroy(conhash->lock);
   conhash->lock = ((void *)0);
  }
  free(conhash);
 }
}

variable_types:
ch
void *

variable_types: struct conhash_s { struct util_rbtree_s { struct util_rbtree_node_s { long key; struct util_rbtree_node_s *parent; struct util_rbtree_node_s *right; struct util_rbtree_node_s *left; int color; void *data; } *root; struct util_rbtree_node_s null; unsigned int size; } vnode_tree; unsigned int ivnodes; void *vnode_a; void *lock; long (*cb_hashfunc)(char *, unsigned long); } *

user_defined_types: struct conhash_s { struct util_rbtree_s vnode_tree; unsigned int ivnodes; void *vnode_a; void *lock; long (*cb_hashfunc)(char *, unsigned long); }


decompiled_code:
__int64 __fastcall nbr_conhash_set_node(char *a1, const char *a2, __int16 a3)
{
char *v4; // rax
char *v5; // rdi
__int64 result; // rax

v4 = strncpy(a1, a2, 0x1BuLL);
*((_WORD *)v4 + 14) = a3;
v5 = v4;
result = 1LL;
*((_WORD *)v5 + 15) = 1;
return result;
}

canonical_decompiled_code:
__int64 __fastcall func1(char *a1, const char *a2, __int16 a3)
{
char *v4; // rax
char *v5; // rdi
__int64 result; // rax

v4 = strncpy(a1, a2, 0x1BuLL);
*((_WORD *)v4 + 14) = a3;
v5 = v4;
result = 1LL;
*((_WORD *)v5 + 15) = 1;
return result;
}

original_code:
extern
void nbr_conhash_set_node(struct node_s *node, const char *iden, u_int replica)
{
    strncpy(node->iden, iden, sizeof(node->iden)-1);
    node->replicas = replica;
    node->flag = 0x01;
}

canonical_original_code:
extern void nbr_conhash_set_node(struct node_s *node, char *iden, unsigned int replica)
{
    strncpy(node->iden, iden, sizeof(node->iden)-1);
    node->replicas = replica;
    node->flag = 0x01;
}

variable_types: struct node_s { char iden[28]; unsigned short replicas; unsigned short flag; } *

variable_types:
iden
char *

variable_types:
replica
unsigned int


decompiled_code:
__int64 __fastcall nbr_conhash_node_registered(__int64 a1)
{
return *(_WORD *)(a1 + 30) & 1;
}

canonical_decompiled_code:
__int64 __fastcall func2(__int64 a1)
{
return *(_WORD *)(a1 + 30) & 1;
}

original_code:
extern int
nbr_conhash_node_registered(const CHNODE *node)
{
 return (node->flag&(0x01 | 0x02)
   == (0x01 | 0x02));
}

canonical_original_code:
extern int nbr_conhash_node_registered(struct node_s *node)
{
 return (node->flag&(0x01 | 0x02)
   == (0x01 | 0x02));
}

user_defined_types: struct node_s { char iden[28]; unsigned short replicas; unsigned short flag; }


decompiled_code:
// attributes: thunk
__int64 __fastcall nbr_conhash_node_fault(__int64 a1)
{
return nbr_conhash_node_registered(a1);
}

canonical_decompiled_code:
__int64 __fastcall func3(__int64 a1)
{
return func2(a1);
}

original_code:
extern int
nbr_conhash_node_fault(const CHNODE *node)
{
 return (node->flag&(0x01 | 0x04)
   == (0x01 | 0x04));
}

canonical_original_code:
extern int nbr_conhash_node_fault(struct node_s *node)
{
 return (node->flag&(0x01 | 0x04)
   == (0x01 | 0x04));
}


decompiled_code:
__int64 __fastcall nbr_conhash_node_set_fault(__int64 a1)
{
if ( !(unsigned int)nbr_conhash_node_registered(a1) )
return 4294967290LL;
*(_WORD *)(a1 + 30) |= 4u;
return 0LL;
}

canonical_decompiled_code:
__int64 __fastcall func4(__int64 a1)
{
if ( !(unsigned int)func2(a1) )
return 4294967290LL;
*(_WORD *)(a1 + 30) |= 4u;
return 0LL;
}

original_code:
extern int
nbr_conhash_node_set_fault(CHNODE *node)
{
 if (nbr_conhash_node_registered(node)) {
  node->flag |= 0x04;
  return NBR_OK;
 }
 return NBR_EINVAL;
}

canonical_original_code:
extern int nbr_conhash_node_set_fault(struct node_s *node)
{
 if (nbr_conhash_node_registered(node)) {
  node->flag |= 0x04;
  return NBR_OK;
 }
 return NBR_EINVAL;
}


decompiled_code:
__int64 __fastcall nbr_conhash_add_node(__int64 a1, __int64 a2)
{
__int64 v3; // rdi

if ( !a1 )
return 4294967290LL;
if ( !a2 )
return 4294967290LL;
if ( (*(_WORD *)(a2 + 30) & 3) != 1 )
return 4294967291LL;
v3 = *(_QWORD *)(a1 + 96);
*(_WORD *)(a2 + 30) |= 2u;
nbr_rwlock_wrlock(v3);
_conhash_add_replicas(a1, a2);
nbr_rwlock_unlock(*(_QWORD *)(a1 + 96));
return 0LL;
}

original_code:
extern
int nbr_conhash_add_node(CONHASH ch, struct node_s *node)
{
 ;
 struct conhash_s *conhash = (struct conhash_s *)ch;
    if((conhash==((void *)0)) || (node==((void *)0)))
    {
        return NBR_EINVAL;
    }
    if(!(node->flag&0x01) || (node->flag&0x02))
    {
        return NBR_EALREADY;
    }
    node->flag |= 0x02;
    nbr_rwlock_wrlock(conhash->lock);
    __conhash_add_replicas(conhash, node);
    nbr_rwlock_unlock(conhash->lock);
    return NBR_OK;
}

canonical_original_code:
extern int nbr_conhash_add_node(void *ch, struct node_s *node)
{
 ;
 struct conhash_s *conhash = (struct conhash_s *)ch;
    if((conhash==((void *)0)) || (node==((void *)0)))
    {
        return NBR_EINVAL;
    }
    if(!(node->flag&0x01) || (node->flag&0x02))
    {
        return NBR_EALREADY;
    }
    node->flag |= 0x02;
    nbr_rwlock_wrlock(conhash->lock);
    __conhash_add_replicas(conhash, node);
    nbr_rwlock_unlock(conhash->lock);
    return NBR_OK;
}


decompiled_code:
__int64 __fastcall nbr_conhash_del_node(__int64 a1, __int64 a2)
{
__int64 v3; // rdi

if ( !a1 )
return 4294967290LL;
if ( !a2 )
return 4294967290LL;
if ( (*(_WORD *)(a2 + 30) & 3) != 3 )
return 4294967291LL;
v3 = *(_QWORD *)(a1 + 96);
*(_WORD *)(a2 + 30) &= 0xFFFDu;
nbr_rwlock_wrlock(v3);
_conhash_del_replicas(a1, a2);
nbr_rwlock_unlock(*(_QWORD *)(a1 + 96));
return 0LL;
}

original_code:
extern
int nbr_conhash_del_node(CONHASH ch, struct node_s *node)
{
 ;
 struct conhash_s *conhash = (struct conhash_s *)ch;
   if((conhash==((void *)0)) || (node==((void *)0)))
    {
        return NBR_EINVAL;
    }
    if(!(node->flag&0x01) || !(node->flag&0x02))
    {
        return NBR_EALREADY;
    }
    node->flag &= (~0x02);
    nbr_rwlock_wrlock(conhash->lock);
    __conhash_del_replicas(conhash, node);
    nbr_rwlock_unlock(conhash->lock);
    return NBR_OK;
}

canonical_original_code:
extern int nbr_conhash_del_node(void *ch, struct node_s *node)
{
 ;
 struct conhash_s *conhash = (struct conhash_s *)ch;
   if((conhash==((void *)0)) || (node==((void *)0)))
    {
        return NBR_EINVAL;
    }
    if(!(node->flag&0x01) || !(node->flag&0x02))
    {
        return NBR_EALREADY;
    }
    node->flag &= (~0x02);
    nbr_rwlock_wrlock(conhash->lock);
    __conhash_del_replicas(conhash, node);
    nbr_rwlock_unlock(conhash->lock);
    return NBR_OK;
}


decompiled_code:
__int64 __fastcall nbr_conhash_lookup(__int64 a1, __int64 a2, __int64 a3)
{
__int64 v3; // rbp
__int64 v4; // rbp
__int64 result; // rax

if ( a1
&& *(_DWORD *)(a1 + 64)
&& a2
&& (v3 = (*(__int64 (__fastcall **)(__int64, __int64))(a1 + 104))(a2, a3),
nbr_rwlock_rdlock(*(_QWORD *)(a1 + 96)),
v4 = util_rbtree_lookup(a1, v3),
nbr_rwlock_unlock(*(_QWORD *)(a1 + 96)),
v4) )
{
result = *(_QWORD *)(*(_QWORD *)(v4 + 40) + 8LL);
}
else
{
result = 0LL;
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func7(__int64 a1, __int64 a2, __int64 a3)
{
__int64 v3; // rbp
__int64 v4; // rbp
__int64 result; // rax

if ( a1
&& *(_DWORD *)(a1 + 64)
&& a2
&& (v3 = (*(__int64 (__fastcall **)(__int64, __int64))(a1 + 104))(a2, a3),
nbr_rwlock_rdlock(*(_QWORD *)(a1 + 96)),
v4 = util_rbtree_lookup(a1, v3),
nbr_rwlock_unlock(*(_QWORD *)(a1 + 96)),
v4) )
{
result = *(_QWORD *)(*(_QWORD *)(v4 + 40) + 8LL);
}
else
{
result = 0LL;
}
return result;
}

original_code:
extern
CHNODE *nbr_conhash_lookup(CONHASH ch, const char *object, size_t sz)
{
 ;
 struct conhash_s *conhash = (struct conhash_s *)ch;
    long hash;
    const util_rbtree_node_t *rbnode;
    if((conhash==((void *)0)) || (conhash->ivnodes==0) || (object==((void *)0)))
    {
        return ((void *)0);
    }
    hash = conhash->cb_hashfunc(object, sz);
    ;
    nbr_rwlock_rdlock(conhash->lock);
    rbnode = util_rbtree_lookup(&(conhash->vnode_tree), hash);
    nbr_rwlock_unlock(conhash->lock);
    if(rbnode != ((void *)0))
    {
        struct virtual_node_s *vnode = rbnode->data;
        return (CHNODE *)vnode->node;
    }
    return ((void *)0);
}

canonical_original_code:
extern struct node_s *nbr_conhash_lookup(void *ch, char *object, unsigned long sz)
{
 ;
 struct conhash_s *conhash = (struct conhash_s *)ch;
    long hash;
    struct util_rbtree_node_s *rbnode;
    if((conhash==((void *)0)) || (conhash->ivnodes==0) || (object==((void *)0)))
    {
        return ((void *)0);
    }
    hash = conhash->cb_hashfunc(object, sz);
    ;
    nbr_rwlock_rdlock(conhash->lock);
    rbnode = util_rbtree_lookup(&(conhash->vnode_tree), hash);
    nbr_rwlock_unlock(conhash->lock);
    if(rbnode != ((void *)0))
    {
        struct virtual_node_s *vnode = rbnode->data;
        return (struct node_s *)vnode->node;
    }
    return ((void *)0);
}

variable_types:
object
char *

variable_types:
sz
unsigned long

variable_types: hash long

variable_types: struct util_rbtree_node_s { long key; struct util_rbtree_node_s *parent; struct util_rbtree_node_s *right; struct util_rbtree_node_s *left; int color; void *data; } *

variable_types: struct virtual_node_s { long hash; struct node_s { char iden[28]; unsigned short replicas; unsigned short flag; } *node; } *

user_defined_types: struct virtual_node_s { long hash; struct node_s *node; }


decompiled_code:
__int64 __fastcall conhash_md5_digest(__int64 a1, unsigned int a2, __int64 a3)
{
_BYTE v5[120]; // [rsp+0h] [rbp-78h] BYREF

md5_init(v5);
md5_append(v5, a1, a2);
return md5_finish(v5, a3);
}

canonical_decompiled_code:
__int64 __fastcall func1(__int64 a1, unsigned int a2, __int64 a3)
{
_BYTE v5[120]; // [rsp+0h] [rbp-78h] BYREF

md5_init(v5);
md5_append(v5, a1, a2);
return md5_finish(v5, a3);
}

original_code:
void conhash_md5_digest(const u_char *instr, size_t sz, u_char digest[16])
{
    md5_state_t md5state;
    md5_init(&md5state);
    md5_append(&md5state, instr, sz);
    md5_finish(&md5state, digest);
}

canonical_original_code:
void conhash_md5_digest(unsigned char *instr, unsigned long sz, unsigned char digest[16])
{
    struct md5_state_s md5state;
    md5_init(&md5state);
    md5_append(&md5state, instr, sz);
    md5_finish(&md5state, digest);
}

variable_types:
instr
unsigned char *

variable_types:
digest
unsigned char [16]

variable_types: struct md5_state_s { unsigned int count[2]; unsigned int abcd[4]; unsigned char buf[64]; }


decompiled_code:
char __fastcall nbr_conhash_get_vnodes(__int64 a1, __int64 a2, int a3)
{
char result; // al
__int64 v4[5]; // [rsp+0h] [rbp-28h] BYREF

result = a3 <= 0;
if ( a3 > 0 && a2 != 0 )
{
if ( a1 )
{
v4[0] = a2;
v4[1] = a3;
v4[2] = 0LL;
result = util_rbtree_mid_travel(a1, _get_vnodes, v4);
}
}
return result;
}

canonical_decompiled_code:
char __fastcall func2(__int64 a1, __int64 a2, int a3)
{
char result; // al
__int64 v4[5]; // [rsp+0h] [rbp-28h] BYREF

result = a3 <= 0;
if ( a3 > 0 && a2 != 0 )
{
if ( a1 )
{
v4[0] = a2;
v4[1] = a3;
v4[2] = 0LL;
result = util_rbtree_mid_travel(a1, _get_vnodes, v4);
}
}
return result;
}

original_code:
void nbr_conhash_get_vnodes(CONHASH ch, long *values, int size)
{
    struct __get_vnodes_s vnodes;
 struct conhash_s *conhash = (struct conhash_s *)ch;
    if((conhash==((void *)0)) || (values==((void *)0)) || (size<=0))
    {
        return;
    }
    vnodes.values = values;
    vnodes.size = size;
    vnodes.cur = 0;
    util_rbtree_mid_travel((util_rbtree_t *)&(conhash->vnode_tree), __get_vnodes, &vnodes);
}

canonical_original_code:
void nbr_conhash_get_vnodes(void *ch, long *values, int size)
{
    struct __get_vnodes_s vnodes;
 struct conhash_s *conhash = (struct conhash_s *)ch;
    if((conhash==((void *)0)) || (values==((void *)0)) || (size<=0))
    {
        return;
    }
    vnodes.values = values;
    vnodes.size = size;
    vnodes.cur = 0;
    util_rbtree_mid_travel((struct util_rbtree_s *)&(conhash->vnode_tree), __get_vnodes, &vnodes);
}

variable_types:
values
long *

variable_types: size int

variable_types: struct __get_vnodes_s { long *values; long size; }


decompiled_code:
__int64 __fastcall nbr_conhash_get_vnodes_num(__int64 a1)
{
__int64 result; // rax

if ( a1 )
result = *(unsigned int *)(a1 + 64);
else
result = 0LL;
return result;
}

canonical_decompiled_code:
__int64 __fastcall func3(__int64 a1)
{
__int64 result; // rax

if ( a1 )
result = *(unsigned int *)(a1 + 64);
else
result = 0LL;
return result;
}

original_code:
U32 nbr_conhash_get_vnodes_num(CONHASH ch)
{
 struct conhash_s *conhash = (struct conhash_s *)ch;
    if(conhash == ((void *)0))
    {
        return 0;
    }
    return conhash->ivnodes;
}

canonical_original_code:
unsigned int nbr_conhash_get_vnodes_num(void *ch)
{
 struct conhash_s *conhash = (struct conhash_s *)ch;
    if(conhash == ((void *)0))
    {
        return 0;
    }
    return conhash->ivnodes;
}

return_type: unsigned int


original_code:
void
md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
{
    const md5_byte_t *p = data;
    int left = nbytes;
    int offset = (pms->count[0] >> 3) & 63;
    md5_word_t nbits = (md5_word_t)(nbytes << 3);
    if (nbytes <= 0)
 return;
    pms->count[1] += nbytes >> 29;
    pms->count[0] += nbits;
    if (pms->count[0] < nbits)
 pms->count[1]++;
    if (offset) {
 int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
 memcpy(pms->buf + offset, p, copy);
 if (offset + copy < 64)
     return;
 p += copy;
 left -= copy;
 md5_process(pms, pms->buf);
    }
    for (; left >= 64; p += 64, left -= 64)
 md5_process(pms, p);
    if (left)
 memcpy(pms->buf, p, left);
}

canonical_original_code:
void md5_append(struct md5_state_s *pms, unsigned char *data, int nbytes)
{
    unsigned char *p = data;
    int left = nbytes;
    int offset = (pms->count[0] >> 3) & 63;
    unsigned int nbits = (md5_word_t)(nbytes << 3);
    if (nbytes <= 0)
 return;
    pms->count[1] += nbytes >> 29;
    pms->count[0] += nbits;
    if (pms->count[0] < nbits)
 pms->count[1]++;
    if (offset) {
 int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
 memcpy(pms->buf + offset, p, copy);
 if (offset + copy < 64)
     return;
 p += copy;
 left -= copy;
 md5_process(pms, pms->buf);
    }
    for (; left >= 64; p += 64, left -= 64)
 md5_process(pms, p);
    if (left)
 memcpy(pms->buf, p, left);
}

variable_types: struct md5_state_s { unsigned int count[2]; unsigned int abcd[4]; unsigned char buf[64]; } *

variable_types:
data
unsigned char *

variable_types: nbytes int

variable_types:
p
unsigned char *

variable_types: left int

variable_types: offset int

variable_types:
nbits
unsigned int

variable_types: copy int


tstp

decompiled_code:
void tstp()
{
int v0; // ebx
int v1; // eax
int v2; // edx

v0 = lines();
v1 = cols();
mvcur(0, v1 - 1, v0 - 1, 0);
endwin();
fflush(stdout);
kill(0, 20);
signal(20, tstp);
cbreak();
noecho();
clearok(curscr, 1);
v2 = -1;
if ( cw )
v2 = cw->_maxy + 1;
wtouchln(cw, 0, v2, 1);
wrefresh(cw);
raw();
noraw();
}

canonical_decompiled_code:
void func0()
{
int v0; // ebx
int v1; // eax
int v2; // edx

v0 = lines();
v1 = cols();
mvcur(0, v1 - 1, v0 - 1, 0);
endwin();
fflush(stdout);
kill(0, 20);
signal(20, tstp);
cbreak();
noecho();
clearok(curscr, 1);
v2 = -1;
if ( cw )
v2 = cw->_maxy + 1;
wtouchln(cw, 0, v2, 1);
wrefresh(cw);
raw();
noraw();
}

original_code:
void tstp()
{
    mvcur(0, cols() - 1, lines() - 1, 0);
    endwin();
    fflush(stdout);
    kill(0, 20);
    signal(20, tstp);
    cbreak();
    noecho();
    clearok(curscr, 1);
    wtouchln((cw), 0, ((0 != (const void *)((cw))) ? ((cw)->_maxy + 1) : (-1)), 1);
    wrefresh(cw);
    raw();
    noraw();
}

canonical_original_code:
void tstp()
{
    mvcur(0, cols() - 1, lines() - 1, 0);
    endwin();
    fflush(stdout);
    kill(0, 20);
    signal(20, tstp);
    cbreak();
    noecho();
    clearok(curscr, 1);
    wtouchln((cw), 0, ((0 != (void *)((cw))) ? ((cw)->_maxy + 1) : (-1)), 1);
    wrefresh(cw);
    raw();
    noraw();
}


decompiled_code:
__int64 run_all_tests()
{
unsigned int v0; // er12
__int64 v1; // rbx
const char *v2; // rsi

v0 = 0;
if ( test_list )
{
v1 = *(_QWORD *)(test_list + 16);
if ( v1 )
{
do
{
current_test_result = 1;
(*(void (**)(void))(v1 + 8))();
v2 = "FAIL";
if ( current_test_result )
v2 = " OK ";
printf("[%s] %s\n", v2, *(_QWORD *)v1);
v1 = *(_QWORD *)(v1 + 24);
v0 += current_test_result == 0;
}
while ( v1 );
if ( v0 )
printf("%d tests failed!", v0);
}
}
return v0;
}

canonical_decompiled_code:
__int64 func1()
{
unsigned int v0; // er12
__int64 v1; // rbx
const char *v2; // rsi

v0 = 0;
if ( test_list )
{
v1 = *(_QWORD *)(test_list + 16);
if ( v1 )
{
do
{
current_test_result = 1;
(*(void (**)(void))(v1 + 8))();
v2 = "FAIL";
if ( current_test_result )
v2 = " OK ";
printf("[%s] %s\n", v2, *(_QWORD *)v1);
v1 = *(_QWORD *)(v1 + 24);
v0 += current_test_result == 0;
}
while ( v1 );
if ( v0 )
printf("%d tests failed!", v0);
}
}
return v0;
}

original_code:
int run_all_tests()
{
 struct TestNode * current_test = test_list == ((void *)0) ? test_list : test_list->start;
 int failed = 0;
 while(current_test != ((void *)0)) {
  current_test_result = 1;
  current_test->test_case();
  printf("[%s] %s\n", current_test_result ? " OK " : "FAIL", current_test->test_name);
  if(!current_test_result) {
   ++failed;
  }
  current_test = current_test->next_test;
 }
 if(failed > 0) {
  printf("%d tests failed!", failed);
 }
 return failed;
}

canonical_original_code:
int run_all_tests()
{
 struct TestNode *current_test = test_list == ((void *)0) ? test_list : test_list->start;
 int failed = 0;
 while(current_test != ((void *)0)) {
  current_test_result = 1;
  current_test->test_case();
  printf("[%s] %s\n", current_test_result ? " OK " : "FAIL", current_test->test_name);
  if(!current_test_result) {
   ++failed;
  }
  current_test = current_test->next_test;
 }
 if(failed > 0) {
  printf("%d tests failed!", failed);
 }
 return failed;
}

variable_types: struct TestNode { char *test_name; void (*test_case)(); struct TestNode *start; struct TestNode *next_test; } *

variable_types: failed int


endit

decompiled_code:
void __noreturn endit()
{
fatal("Ok, if you want to exit that badly, I'll have to allow it\n");
}

canonical_decompiled_code:
void __noreturn func3()
{
func2("Ok, if you want to exit that badly, I'll have to allow it\n");
}

original_code:
void endit()
{
    fatal("Ok, if you want to exit that badly, I'll have to allow it\n");
}


addmsg

decompiled_code:
size_t addmsg(char *format, ...)
{
size_t result; // rax
gcc_va_list arg; // [rsp+8h] [rbp-D0h] BYREF

va_start(arg, format);
vsprintf(&msgbuf[newpos], format, arg);
result = strlen(msgbuf);
newpos = result;
return result;
}

canonical_decompiled_code:
size_t func2(char *format, ...)
{
size_t result; // rax
gcc_va_list arg; // [rsp+8h] [rbp-D0h] BYREF

va_start(arg, format);
vsprintf(&msgbuf[newpos], format, arg);
result = strlen(msgbuf);
newpos = result;
return result;
}

original_code:
void addmsg(const char * fmt, ...)
{
 va_list args;
 __builtin_va_start(args,fmt);
 vsprintf(&msgbuf[newpos], fmt, args);
 __builtin_va_end(args);
    newpos = strlen(msgbuf);
}

canonical_original_code:
void addmsg(char *fmt, ...)
{
 __builtin_va_list args;
 __builtin_va_start(args,fmt);
 vsprintf(&msgbuf[newpos], fmt, args);
 __builtin_va_end(args);
    newpos = strlen(msgbuf);
}

variable_types:
fmt
char *


msg

decompiled_code:
int msg(char *format, ...)
{
int result; // eax
gcc_va_list arg; // [rsp+8h] [rbp-D0h] BYREF

if ( *format )
{
va_start(arg, format);
vsprintf(&msgbuf[newpos], format, arg);
newpos = strlen(msgbuf);
result = endmsg();
}
else
{
wmove(cw, 0, 0);
result = wclrtoeol(cw);
mpos = 0;
}
return result;
}

canonical_decompiled_code:
int func8(char *format, ...)
{
int result; // eax
gcc_va_list arg; // [rsp+8h] [rbp-D0h] BYREF

if ( *format )
{
va_start(arg, format);
vsprintf(&msgbuf[newpos], format, arg);
newpos = strlen(msgbuf);
result = func7();
}
else
{
wmove(cw, 0, 0);
result = wclrtoeol(cw);
mpos = 0;
}
return result;
}

original_code:
void msg(const char * fmt, ...)
{
    if (*fmt == '\0')
    {
 wmove(cw, 0, 0);
 wclrtoeol(cw);
 mpos = 0;
 return;
    }
 va_list args;
 __builtin_va_start(args,fmt);
 vsprintf(&msgbuf[newpos], fmt, args);
 __builtin_va_end(args);
    newpos = strlen(msgbuf);
    endmsg();
}

canonical_original_code:
void msg(char *fmt, ...)
{
    if (*fmt == '\0')
    {
 wmove(cw, 0, 0);
 wclrtoeol(cw);
 mpos = 0;
 return;
    }
 __builtin_va_list args;
 __builtin_va_start(args,fmt);
 vsprintf(&msgbuf[newpos], fmt, args);
 __builtin_va_end(args);
    newpos = strlen(msgbuf);
    endmsg();
}


quit

decompiled_code:
void quit()
{
int v0; // eax

if ( signal(2, quit) )
mpos = 0;
msg("Really quit?");
wrefresh(cw);
if ( (unsigned int)readchar() == 121 )
{
wclear(stdscr);
v0 = lines();
wmove(stdscr, v0 - 1, 0);
wrefresh(stdscr);
score((unsigned int)purse, 1LL);
exit(0);
}
signal(2, quit);
wmove(cw, 0, 0);
wclrtoeol(cw);
status();
wrefresh(cw);
mpos = 0;
count = 0;
}

canonical_decompiled_code:
void func0()
{
int v0; // eax

if ( signal(2, quit) )
mpos = 0;
msg("Really quit?");
wrefresh(cw);
if ( (unsigned int)readchar() == 121 )
{
wclear(stdscr);
v0 = lines();
wmove(stdscr, v0 - 1, 0);
wrefresh(stdscr);
score((unsigned int)purse, 1LL);
exit(0);
}
signal(2, quit);
wmove(cw, 0, 0);
wclrtoeol(cw);
status();
wrefresh(cw);
mpos = 0;
count = 0;
}

original_code:
void quit()
{
    if (signal(2, quit) != quit)
 mpos = 0;
    msg("Really quit?");
    wrefresh(cw);
    if (readchar() == 'y')
    {
 wclear(stdscr);
 wmove(stdscr,(lines()-1),(0));
 wrefresh(stdscr);
 score(purse, 1);
 exit(0);
    }
    else
    {
 signal(2, quit);
 wmove(cw, 0, 0);
 wclrtoeol(cw);
 status();
 wrefresh(cw);
 mpos = 0;
 count = 0;
    }
}


decompiled_code:
char *d_slot()
{
char *v0; // r12

v0 = (char *)&d_list;
do
{
if ( !*(_DWORD *)v0 )
return v0;
v0 += 24;
}
while ( v0 != (char *)&d_list + 480 );
v0 = 0LL;
if ( !wizard )
return v0;
msg("Ran out of fuse slots");
return 0LL;
}

canonical_decompiled_code:
char *func0()
{
char *v0; // r12

v0 = (char *)&d_list;
do
{
if ( !*(_DWORD *)v0 )
return v0;
v0 += 24;
}
while ( v0 != (char *)&d_list + 480 );
v0 = 0LL;
if ( !wizard )
return v0;
msg("Ran out of fuse slots");
return 0LL;
}

original_code:
struct delayed_action *
d_slot()
{
    register int i;
    register struct delayed_action *dev;
    for (i = 0, dev = d_list; i < 20; i++, dev++)
 if (dev->d_type == 0)
     return dev;
    if (wizard) msg("Ran out of fuse slots");
    return ((void *)0);
}

canonical_original_code:
struct delayed_action *d_slot()
{
    register int i;
    register struct delayed_action *dev;
    for (i = 0, dev = d_list; i < 20; i++, dev++)
 if (dev->d_type == 0)
     return dev;
    if (wizard) msg("Ran out of fuse slots");
    return ((void *)0);
}

variable_types: i int

variable_types: struct delayed_action { int d_type; int (*d_func)(); int d_arg; int d_time; } *


repo: unenemy/helios-course

decompiled_code:
__int64 __fastcall compare_int(int a1, int a2)
{
__int64 result; // rax

result = a1 > a2;
if ( a1 < a2 )
result = 0xFFFFFFFFLL;
return result;
}

canonical_decompiled_code:
__int64 __fastcall func0(int a1, int a2)
{
__int64 result; // rax

result = a1 > a2;
if ( a1 < a2 )
result = 0xFFFFFFFFLL;
return result;
}

original_code:
int compare_int(void* leftp, void* rightp){
    int left = (int)leftp;
    int right = (int)rightp;
    if(left < right)
        return -1;
    else if(left > right)
        return 1;
    else
        return 0;
}

canonical_original_code:
int compare_int(void *leftp, void *rightp){
    int left = (int)leftp;
    int right = (int)rightp;
    if(left < right)
        return -1;
    else if(left > right)
        return 1;
    else
        return 0;
}

variable_types:
leftp
void *

variable_types:
rightp
void *

variable_types: right int


decompiled_code:
__int64 __fastcall get_key(unsigned int *a1)
{
__int64 result; // rax

result = 0LL;
if ( a1 )
result = *a1;
return result;
}

canonical_decompiled_code:
__int64 __fastcall func1(unsigned int *a1)
{
__int64 result; // rax

result = 0LL;
if ( a1 )
result = *a1;
return result;
}

original_code:
int get_key(bbst_node n){
    return n == ((void *)0) ? 0 : (int)n->key;
}

canonical_original_code:
int get_key(struct bbst_node_t *n){
    return n == ((void *)0) ? 0 : (int)n->key;
}

variable_types: struct bbst_node_t { void *key; void *value; struct bbst_node_t *left; struct bbst_node_t *right; struct bbst_node_t *parent; enum bbst_node_color { RED=0, BLACK=1 } color; } *

user_defined_types: struct bbst_node_t { void *key; void *value; struct bbst_node_t *left; struct bbst_node_t *right; struct bbst_node_t *parent; enum bbst_node_color color; }


decompiled_code:
int __fastcall print_tree(__int64 a1)
{
unsigned int v2; // eax
__int64 v3; // rdx
unsigned int v4; // eax
__int64 v5; // rdx
int result; // eax

do
{
get_key((unsigned int *)a1);
v2 = get_key(*(unsigned int **)(a1 + 16));
printf("%d left to %d\n", v2, v3);
get_key((unsigned int *)a1);
v4 = get_key(*(unsigned int **)(a1 + 24));
result = printf("%d right to %d\n", v4, v5);
if ( *(_QWORD *)(a1 + 16) )
result = print_tree();
a1 = *(_QWORD *)(a1 + 24);
}
while ( a1 );
return result;
}

canonical_decompiled_code:
int __fastcall func2(__int64 a1)
{
unsigned int v2; // eax
__int64 v3; // rdx
unsigned int v4; // eax
__int64 v5; // rdx
int result; // eax

do
{
func1((unsigned int *)a1);
v2 = func1(*(unsigned int **)(a1 + 16));
printf("%d left to %d\n", v2, v3);
func1((unsigned int *)a1);
v4 = func1(*(unsigned int **)(a1 + 24));
result = printf("%d right to %d\n", v4, v5);
if ( *(_QWORD *)(a1 + 16) )
result = func2();
a1 = *(_QWORD *)(a1 + 24);
}
while ( a1 );
return result;
}

original_code:
void print_tree(bbst_node n){
    printf("%d left to %d\n", get_key(n->left), get_key(n));
    printf("%d right to %d\n", get_key(n->right), get_key(n));
    if(n->left != ((void *)0)) print_tree(n->left);
    if(n->right != ((void *)0)) print_tree(n->right);
}

canonical_original_code:
void print_tree(struct bbst_node_t *n){
    printf("%d left to %d\n", get_key(n->left), get_key(n));
    printf("%d right to %d\n", get_key(n->right), get_key(n));
    if(n->left != ((void *)0)) print_tree(n->left);
    if(n->right != ((void *)0)) print_tree(n->right);
}


decompiled_code:
__int64 __fastcall get_value(__int64 a1)
{
__int64 result; // rax

result = 0LL;
if ( a1 )
result = *(unsigned int *)(a1 + 8);
return result;
}

canonical_decompiled_code:
__int64 __fastcall func3(__int64 a1)
{
__int64 result; // rax

result = 0LL;
if ( a1 )
result = *(unsigned int *)(a1 + 8);
return result;
}

original_code:
int get_value(bbst_node n){
    return n == ((void *)0) ? 0 : (int)n->value;
}

canonical_original_code:
int get_value(struct bbst_node_t *n){
    return n == ((void *)0) ? 0 : (int)n->value;
}


main

decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v3; // er13
__int64 *v4; // rbx
int v5; // ebp
__int64 v6; // r12
int v7; // er12
__int64 v8; // rbp

v3 = 10;
v4 = (__int64 *)bbst_create(argc, argv, envp);
do
{
v5 = rand() % 100;
v6 = rand() % 100;
bbst_insert(v4, v5, v6, compare_int);
printf("\ninsetring %d(%d)\n", (unsigned int)v5, (unsigned int)v6);
print_tree(*v4);
--v3;
}
while ( v3 );
v7 = 10;
do
{
v8 = rand() % 100;
bbst_delete(v4, v8, compare_int);
printf("\nremoving %d\n", (unsigned int)v8);
print_tree(*v4);
--v7;
}
while ( v7 );
return 0;
}

canonical_decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v3; // er13
__int64 *v4; // rbx
int v5; // ebp
__int64 v6; // r12
int v7; // er12
__int64 v8; // rbp

v3 = 10;
v4 = (__int64 *)bbst_create(argc, argv, envp);
do
{
v5 = rand() % 100;
v6 = rand() % 100;
bbst_insert(v4, v5, v6, compare_int);
printf("\ninsetring %d(%d)\n", (unsigned int)v5, (unsigned int)v6);
func2(*v4);
--v3;
}
while ( v3 );
v7 = 10;
do
{
v8 = rand() % 100;
bbst_delete(v4, v8, compare_int);
printf("\nremoving %d\n", (unsigned int)v8);
func2(*v4);
--v7;
}
while ( v7 );
return 0;
}

original_code:
int main()
{
    int i;
    bbst tree = bbst_create();
    for (i = 0; i < 10; i++) {
        int x = rand() % 100;
        int y = rand() % 100;
        bbst_insert(tree, (void*)x, (void*)y, compare_int);
        printf("\ninsetring %d(%d)\n", x, y);
        print_tree(tree->root);
    }
    for (i = 0; i < 10; i++) {
        int x = rand() % 100;
        bbst_delete(tree, (void*)x, compare_int);
        printf("\nremoving %d\n", x);
        print_tree(tree->root);
    }
    return 0;
}

canonical_original_code:
int main()
{
    int i;
    struct bbst_t *tree = bbst_create();
    for (i = 0; i < 10; i++) {
        int x = rand() % 100;
        int y = rand() % 100;
        bbst_insert(tree, (void *)x, (void *)y, compare_int);
        printf("\ninsetring %d(%d)\n", x, y);
        print_tree(tree->root);
    }
    for (i = 0; i < 10; i++) {
        int x = rand() % 100;
        bbst_delete(tree, (void *)x, compare_int);
        printf("\nremoving %d\n", x);
        print_tree(tree->root);
    }
    return 0;
}

variable_types: struct bbst_t { struct bbst_node_t { void *key; void *value; struct bbst_node_t *left; struct bbst_node_t *right; struct bbst_node_t *parent; enum bbst_node_color { RED=0, BLACK=1 } color; } *root; } *

variable_types: x int

variable_types: y int

user_defined_types: struct bbst_t { struct bbst_node_t *root; }


decompiled_code:
__int64 __fastcall node_color(__int64 a1)
{
__int64 result; // rax

result = 1LL;
if ( a1 )
result = *(unsigned int *)(a1 + 40);
return result;
}

canonical_decompiled_code:
__int64 __fastcall func6(__int64 a1)
{
__int64 result; // rax

result = 1LL;
if ( a1 )
result = *(unsigned int *)(a1 + 40);
return result;
}

original_code:
color node_color(node n){
    return n == ((void *)0) ? BLACK : n->color;
}

canonical_original_code:
enum bbst_node_color node_color(struct bbst_node_t *n){
    return n == ((void *)0) ? BLACK : n->color;
}

return_type: enum bbst_node_color { RED=0, BLACK=1 }


decompiled_code:
__int64 __fastcall rotate_left(_QWORD *a1, __int64 a2)
{
__int64 v2; // rdx
__int64 result; // rax

replace_node(a1, a2, *(_QWORD *)(a2 + 24));
result = *(_QWORD *)(v2 + 16);
*(_QWORD *)(a2 + 24) = result;
if ( result )
*(_QWORD *)(result + 32) = a2;
*(_QWORD *)(v2 + 16) = a2;
*(_QWORD *)(a2 + 32) = v2;
return result;
}

canonical_decompiled_code:
__int64 __fastcall func8(_QWORD *a1, __int64 a2)
{
__int64 v2; // rdx
__int64 result; // rax

func7(a1, a2, *(_QWORD *)(a2 + 24));
result = *(_QWORD *)(v2 + 16);
*(_QWORD *)(a2 + 24) = result;
if ( result )
*(_QWORD *)(result + 32) = a2;
*(_QWORD *)(v2 + 16) = a2;
*(_QWORD *)(a2 + 32) = v2;
return result;
}

original_code:
void rotate_left(bbst tree, node n){
    node pivot = n->right;
    replace_node(tree, n, pivot);
    n->right = pivot->left;
    if(pivot->left != ((void *)0)){
        pivot->left->parent = n;
    }
    pivot->left = n;
    n->parent = pivot;
}

canonical_original_code:
void rotate_left(struct bbst_t *tree, struct bbst_node_t *n){
    struct bbst_node_t *pivot = n->right;
    replace_node(tree, n, pivot);
    n->right = pivot->left;
    if(pivot->left != ((void *)0)){
        pivot->left->parent = n;
    }
    pivot->left = n;
    n->parent = pivot;
}

variable_types:
n
struct bbst_node_t *


decompiled_code:
__int64 __fastcall rotate_right(_QWORD *a1, __int64 a2)
{
__int64 v2; // rdx
__int64 result; // rax

replace_node(a1, a2, *(_QWORD *)(a2 + 16));
result = *(_QWORD *)(v2 + 24);
*(_QWORD *)(a2 + 16) = result;
if ( result )
*(_QWORD *)(result + 32) = a2;
*(_QWORD *)(v2 + 24) = a2;
*(_QWORD *)(a2 + 32) = v2;
return result;
}

canonical_decompiled_code:
__int64 __fastcall func9(_QWORD *a1, __int64 a2)
{
__int64 v2; // rdx
__int64 result; // rax

func7(a1, a2, *(_QWORD *)(a2 + 16));
result = *(_QWORD *)(v2 + 24);
*(_QWORD *)(a2 + 16) = result;
if ( result )
*(_QWORD *)(result + 32) = a2;
*(_QWORD *)(v2 + 24) = a2;
*(_QWORD *)(a2 + 32) = v2;
return result;
}

original_code:
void rotate_right(bbst tree, node n){
    node pivot = n->left;
    replace_node(tree, n, pivot);
    n->left = pivot->right;
    if(pivot->right != ((void *)0)){
        pivot->right->parent = n;
    }
    pivot->right = n;
    n->parent = pivot;
}

canonical_original_code:
void rotate_right(struct bbst_t *tree, struct bbst_node_t *n){
    struct bbst_node_t *pivot = n->left;
    replace_node(tree, n, pivot);
    n->left = pivot->right;
    if(pivot->right != ((void *)0)){
        pivot->right->parent = n;
    }
    pivot->right = n;
    n->parent = pivot;
}


sibling

decompiled_code:
__int64 __fastcall sibling(__int64 a1)
{
__int64 v1; // rdx
__int64 result; // rax

if ( !a1 )
__assert_fail("n != NULL", "bbst.c", 0x26u, "sibling");
v1 = *(_QWORD *)(a1 + 32);
if ( !v1 )
__assert_fail("n->parent != NULL", "bbst.c", 0x27u, "sibling");
result = *(_QWORD *)(v1 + 16);
if ( result == a1 )
result = *(_QWORD *)(v1 + 24);
return result;
}

canonical_decompiled_code:
__int64 __fastcall func10(__int64 a1)
{
__int64 v1; // rdx
__int64 result; // rax

if ( !a1 )
__assert_fail("n != NULL", "bbst.c", 0x26u, "sibling");
v1 = *(_QWORD *)(a1 + 32);
if ( !v1 )
__assert_fail("n->parent != NULL", "bbst.c", 0x27u, "sibling");
result = *(_QWORD *)(v1 + 16);
if ( result == a1 )
result = *(_QWORD *)(v1 + 24);
return result;
}

original_code:
node sibling(node n){
    ((void) sizeof ((n != ((void *)0)) ? 1 : 0), __extension__ ({ if (n != ((void *)0)) ; else __assert_fail ("n != NULL", "bbst.c", 38, __extension__ __PRETTY_FUNCTION__); }));
    ((void) sizeof ((n->parent != ((void *)0)) ? 1 : 0), __extension__ ({ if (n->parent != ((void *)0)) ; else __assert_fail ("n->parent != NULL", "bbst.c", 39, __extension__ __PRETTY_FUNCTION__); }));
    if(n->parent->left == n){
        return n->parent->right;
    }else {
        return n->parent->left;
    }
}

canonical_original_code:
struct bbst_node_t *sibling(struct bbst_node_t *n){
    ((void) sizeof ((n != ((void *)0)) ? 1 : 0), __extension__ ({ if (n != ((void *)0)) ; else __assert_fail ("n != NULL", "bbst.c", 38, __extension__ __PRETTY_FUNCTION__); }));
    ((void) sizeof ((n->parent != ((void *)0)) ? 1 : 0), __extension__ ({ if (n->parent != ((void *)0)) ; else __assert_fail ("n->parent != NULL", "bbst.c", 39, __extension__ __PRETTY_FUNCTION__); }));
    if(n->parent->left == n){
        return n->parent->right;
    }else {
        return n->parent->left;
    }
}

return_type: struct bbst_node_t { void *key; void *value; struct bbst_node_t *left; struct bbst_node_t *right; struct bbst_node_t *parent; enum bbst_node_color { RED=0, BLACK=1 } color; } *