decompiled_code:
__int64 __fastcall do_crawler(_QWORD **a1)
{
int *v2; // r13
int v3; // ebp
size_t v4; // rbx
void *v5; // rdi
void *v6; // rdi
int v8; // eax
int v9; // ebx
__int64 v10; // [rsp+0h] [rbp-C6F8h] BYREF
void *dest; // [rsp+8h] [rbp-C6F0h]
char v12[32]; // [rsp+10h] [rbp-C6E8h] BYREF
char v13[46752]; // [rsp+30h] [rbp-C6C8h] BYREF
char s[4136]; // [rsp+B6D0h] [rbp-1028h] BYREF

v2 = (int *)a1[1];
find_vertex(&webgraph, v2 + 1);
bzero(s, 0x1000uLL);
memcpy(s, v2 + 1, *v2);
v3 = 3;
while ( 1 )
{
list_init(v12);
printf("---------$$$$$threadID: %d(%lu) crawler url: %s---------------\n", *((unsigned int *)*a1 + 24), **a1, s);
v8 = crawler_crawl(v13, s, v12);
v9 = v8;
if ( !v8 )
break;
if ( v8 == 6 )
{
printf(
"---------threadID: %d(%lu) crawler url: %s timeout, retry times: %d---------------\n",
*((unsigned int *)*a1 + 24),
**a1,
s,
(unsigned int)--v3);
fprintf(stderr, "Error: crawler url '%s' failed.\n", s);
list_destroy(v12);
}
else
{
--v3;
printf("---------threadID: %d(%lu) crawler url: %s failed---------------\n", *((unsigned int *)*a1 + 24), **a1, s);
fprintf(stderr, "Error: crawler url '%s' failed.\n", s);
list_destroy(v12);
if ( ((v9 - 6) & 0xFFFFFFFD) != 0 && ((v9 - 2) & 0xFFFFFFFD) != 0 )
goto LABEL_7;
}
if ( v3 <= 0 )
goto LABEL_7;
}
v4 = *v2 + 1;
v5 = malloc(v4);
dest = v5;
if ( v5 && (bzero(v5, v4), memcpy(dest, v2 + 1, *v2), v6 = malloc(0x20uLL), (v10 = (__int64)v6) != 0) )
{
list_init(v6);
if ( (unsigned int)filter((__int64)v12, v10) )
{
ts_queue_push(&urlqueue, &v10, 16LL);
thread_counter_increase(&global_lock);
sem_post(&work_sem);
printf(
"---------threadID: %d(%lu) crawler url: %s success---------------\n",
*((unsigned int *)*a1 + 24),
**a1,
s);
}
else
{
printf(
"---------threadID: %d(%lu) crawler url: %s link_list is zero---------------\n",
*((unsigned int *)*a1 + 24),
**a1,
s);
}
}
else
{
printf("---------threadID: %d(%lu) crawler url: %s failed---------------\n", *((unsigned int *)*a1 + 24), **a1, s);
fwrite("Error, allocate memory failed in func 'do_crawler'.\n", 1uLL, 0x34uLL, stderr);
}
list_destroy(v12);
LABEL_7:
puts("================================send post job============================");
free(v2);
thread_counter_decrease(&global_lock);
sem_post(&work_sem);
puts("================================send check job============================");
return 0LL;
}

canonical_decompiled_code:
__int64 __fastcall func3(_QWORD **a1)
{
int *v2; // r13
int v3; // ebp
size_t v4; // rbx
void *v5; // rdi
void *v6; // rdi
int v8; // eax
int v9; // ebx
__int64 v10; // [rsp+0h] [rbp-C6F8h] BYREF
void *dest; // [rsp+8h] [rbp-C6F0h]
char v12[32]; // [rsp+10h] [rbp-C6E8h] BYREF
char v13[46752]; // [rsp+30h] [rbp-C6C8h] BYREF
char s[4136]; // [rsp+B6D0h] [rbp-1028h] BYREF

v2 = (int *)a1[1];
find_vertex(&webgraph, v2 + 1);
bzero(s, 0x1000uLL);
memcpy(s, v2 + 1, *v2);
v3 = 3;
while ( 1 )
{
list_init(v12);
printf("---------$$$$$threadID: %d(%lu) crawler url: %s---------------\n", *((unsigned int *)*a1 + 24), **a1, s);
v8 = crawler_crawl(v13, s, v12);
v9 = v8;
if ( !v8 )
break;
if ( v8 == 6 )
{
printf(
"---------threadID: %d(%lu) crawler url: %s timeout, retry times: %d---------------\n",
*((unsigned int *)*a1 + 24),
**a1,
s,
(unsigned int)--v3);
fprintf(stderr, "Error: crawler url '%s' failed.\n", s);
list_destroy(v12);
}
else
{
--v3;
printf("---------threadID: %d(%lu) crawler url: %s failed---------------\n", *((unsigned int *)*a1 + 24), **a1, s);
fprintf(stderr, "Error: crawler url '%s' failed.\n", s);
list_destroy(v12);
if ( ((v9 - 6) & 0xFFFFFFFD) != 0 && ((v9 - 2) & 0xFFFFFFFD) != 0 )
goto LABEL_7;
}
if ( v3 <= 0 )
goto LABEL_7;
}
v4 = *v2 + 1;
v5 = malloc(v4);
dest = v5;
if ( v5 && (bzero(v5, v4), memcpy(dest, v2 + 1, *v2), v6 = malloc(0x20uLL), (v10 = (__int64)v6) != 0) )
{
list_init(v6);
if ( (unsigned int)func2((__int64)v12, v10) )
{
ts_queue_push(&urlqueue, &v10, 16LL);
thread_counter_increase(&global_lock);
sem_post(&work_sem);
printf(
"---------threadID: %d(%lu) crawler url: %s success---------------\n",
*((unsigned int *)*a1 + 24),
**a1,
s);
}
else
{
printf(
"---------threadID: %d(%lu) crawler url: %s link_list is zero---------------\n",
*((unsigned int *)*a1 + 24),
**a1,
s);
}
}
else
{
printf("---------threadID: %d(%lu) crawler url: %s failed---------------\n", *((unsigned int *)*a1 + 24), **a1, s);
fwrite("Error, allocate memory failed in func 'do_crawler'.\n", 1uLL, 0x34uLL, stderr);
}
list_destroy(v12);
LABEL_7:
puts("================================send post job============================");
free(v2);
thread_counter_decrease(&global_lock);
sem_post(&work_sem);
puts("================================send check job============================");
return 0LL;
}

original_code:
void *do_crawler(void *arg)
{
    job_arg_t *thread_arg = (job_arg_t *)arg;
    sds_t *job_arg = (sds_t *)thread_arg->arg;
    vertex_t *vertex;
    vertex = find_vertex(&webgraph, job_arg->buffer);
    char url[4096];
    bzero(url, 4096);
    memcpy(url, job_arg->buffer, job_arg->len);
    int timeout = 3;
    int retval;
    link_crawler_t crawler;
    list_t link_list;
    do {
        list_init(&link_list);
        printf("---------$$$$$threadID: %d(%lu) crawler url: %s---------------\n", thread_arg->thread_item->id, thread_arg->thread_item->threadinfo, url);
 retval = crawler_crawl(&crawler, url, &link_list);
        if(retval == 0) {
         link_info_t link_info;
            int len = job_arg->len + 1;
            if((link_info.url = (char *)malloc(len)) != ((void *)0)) {
                bzero(link_info.url, len);
                memcpy(link_info.url, job_arg->buffer, job_arg->len);
                if((link_info.link_url = (list_t *)malloc(sizeof(list_t))) != ((void *)0)) {
                    list_init(link_info.link_url);
                    if(filter(&link_list, link_info.link_url)) {
                     ts_queue_push(&urlqueue, &link_info, sizeof(link_info_t));
       thread_counter_increase(&global_lock);
       sem_post(&work_sem);
              printf("---------threadID: %d(%lu) crawler url: %s success---------------\n",
                    thread_arg->thread_item->id, thread_arg->thread_item->threadinfo, url);
                    } else {
              printf("---------threadID: %d(%lu) crawler url: %s link_list is zero---------------\n",
               thread_arg->thread_item->id, thread_arg->thread_item->threadinfo, url);
             }
                } else {
          printf("---------threadID: %d(%lu) crawler url: %s failed---------------\n",
               thread_arg->thread_item->id, thread_arg->thread_item->threadinfo, url);
                 fprintf(stderr, "Error, allocate memory failed in func 'do_crawler'.\n");
                }
            } else {
             printf("---------threadID: %d(%lu) crawler url: %s failed---------------\n",
               thread_arg->thread_item->id, thread_arg->thread_item->threadinfo, url);
                fprintf(stderr, "Error, allocate memory failed in func 'do_crawler'.\n");
            }
        } else if(retval == 6) {
     timeout--;
            printf("---------threadID: %d(%lu) crawler url: %s timeout, retry times: %d---------------\n",
               thread_arg->thread_item->id, thread_arg->thread_item->threadinfo, url, timeout);
            fprintf(stderr, "Error: crawler url '%s' failed.\n", url);
 } else {
     timeout--;
         printf("---------threadID: %d(%lu) crawler url: %s failed---------------\n",
               thread_arg->thread_item->id, thread_arg->thread_item->threadinfo, url);
            fprintf(stderr, "Error: crawler url '%s' failed.\n", url);
        }
        list_destroy(&link_list);
    } while((retval == 6 || retval == 8 || retval == 2 || retval == 4) && timeout > 0);
    printf("================================send post job============================\n");
    if(job_arg != ((void *)0)) { free(job_arg); }
    thread_counter_decrease(&global_lock);
    sem_post(&work_sem);
    printf("================================send check job============================\n");
    return 0;
}

canonical_original_code:
void *do_crawler(void *arg)
{
    struct _job_arg *thread_arg = (job_arg_t *)arg;
    struct _sds *job_arg = (sds_t *)thread_arg->arg;
    struct _vertex *vertex;
    vertex = find_vertex(&webgraph, job_arg->buffer);
    char url[4096];
    bzero(url, 4096);
    memcpy(url, job_arg->buffer, job_arg->len);
    int timeout = 3;
    int retval;
    struct _link_crawler crawler;
    struct _list link_list;
    do {
        list_init(&link_list);
        printf("---------$$$$$threadID: %d(%lu) crawler url: %s---------------\n", thread_arg->thread_item->id, thread_arg->thread_item->threadinfo, url);
 retval = crawler_crawl(&crawler, url, &link_list);
        if(retval == 0) {
         struct _link_info link_info;
            int len = job_arg->len + 1;
            if((link_info.url = (char *)malloc(len)) != ((void *)0)) {
                bzero(link_info.url, len);
                memcpy(link_info.url, job_arg->buffer, job_arg->len);
                if((link_info.link_url = (struct _list *)malloc(sizeof(list_t))) != ((void *)0)) {
                    list_init(link_info.link_url);
                    if(filter(&link_list, link_info.link_url)) {
                     ts_queue_push(&urlqueue, &link_info, sizeof(link_info_t));
       thread_counter_increase(&global_lock);
       sem_post(&work_sem);
              printf("---------threadID: %d(%lu) crawler url: %s success---------------\n",
                    thread_arg->thread_item->id, thread_arg->thread_item->threadinfo, url);
                    } else {
              printf("---------threadID: %d(%lu) crawler url: %s link_list is zero---------------\n",
               thread_arg->thread_item->id, thread_arg->thread_item->threadinfo, url);
             }
                } else {
          printf("---------threadID: %d(%lu) crawler url: %s failed---------------\n",
               thread_arg->thread_item->id, thread_arg->thread_item->threadinfo, url);
                 fprintf(stderr, "Error, allocate memory failed in func 'do_crawler'.\n");
                }
            } else {
             printf("---------threadID: %d(%lu) crawler url: %s failed---------------\n",
               thread_arg->thread_item->id, thread_arg->thread_item->threadinfo, url);
                fprintf(stderr, "Error, allocate memory failed in func 'do_crawler'.\n");
            }
        } else if(retval == 6) {
     timeout--;
            printf("---------threadID: %d(%lu) crawler url: %s timeout, retry times: %d---------------\n",
               thread_arg->thread_item->id, thread_arg->thread_item->threadinfo, url, timeout);
            fprintf(stderr, "Error: crawler url '%s' failed.\n", url);
 } else {
     timeout--;
         printf("---------threadID: %d(%lu) crawler url: %s failed---------------\n",
               thread_arg->thread_item->id, thread_arg->thread_item->threadinfo, url);
            fprintf(stderr, "Error: crawler url '%s' failed.\n", url);
        }
        list_destroy(&link_list);
    } while((retval == 6 || retval == 8 || retval == 2 || retval == 4) && timeout > 0);
    printf("================================send post job============================\n");
    if(job_arg != ((void *)0)) { free(job_arg); }
    thread_counter_decrease(&global_lock);
    sem_post(&work_sem);
    printf("================================send check job============================\n");
    return 0;
}

variable_types: struct _sds { int len; char buffer[]; } *

variable_types: struct _vertex { struct _vertex_index { int vid; struct _vertex_info { int vid; int in; struct _sds { int len; char buffer[]; } url; } *addr; } index; int ind; int outd; double pr; struct _list { struct _elem { struct _elem *next; int len; char buffer[]; } meta; struct _elem *head; struct _elem *tail; } edge; } *

variable_types:
url
char [4096]

variable_types: timeout int

variable_types: retval int

variable_types: struct _link_crawler { struct _http_client { struct _network { int socketfd; char host[256]; int port; int len; char buffer[-1]; } connection; struct _http_request { struct _http_request_line { char method[8]; char request_uri[4096]; char http_version[16]; } req_line; struct _http_general_header { char date[128]; } gen_header; struct _http_request_header { char user_agent[128]; char host[128]; char accept[128]; } req_header; struct _http_entity_header { char content_length[128]; char content_type[128]; } enti_header; struct _http_entity_body { int used; int len; char *buffer; } enti_body; } request; struct _http_response { struct _http_response_line { char http_version[16]; char status_code[8]; char reason_phrase[64]; } res_line; struct _http_general_header gen_header; struct _http_response_header { char server[128]; } res_header; struct _http_entity_header enti_header; struct _http_entity_body enti_body; } response; } http_client; }

variable_types: struct _link_info { struct _list { struct _elem { struct _elem *next; int len; char buffer[]; } meta; struct _elem *head; struct _elem *tail; } *link_url; char *url; }

user_defined_types: struct _link_info { struct _list *link_url; char *url; }

user_defined_types: struct _vertex { struct _vertex_index index; int ind; int outd; double pr; struct _list edge; }

user_defined_types: struct _vertex_index { int vid; struct _vertex_info *addr; }

user_defined_types: struct _thread_count { int count; union pthread_mutex_t lock; }

user_defined_types: struct _vertex_info { int vid; int in; struct _sds url; }

user_defined_types: struct __pthread_internal_list { struct __pthread_internal_list *__prev; struct __pthread_internal_list *__next; }


printThreadInfo

repo: yanshuyuan/siteanalyzer

decompiled_code:
int printThreadInfo()
{
__int64 v0; // rbp
unsigned __int64 v1; // rbx
unsigned int v2; // eax

puts("=========thread info=========================");
if ( thread_pool[1] )
{
v0 = 0LL;
v1 = 0LL;
do
{
v2 = thread_counter_get(thread_pool[0] + v0 + 48);
printf("thread[%d].job_done: %d\n", (unsigned int)v1++, v2);
v0 += 104LL;
}
while ( thread_pool[1] > v1 );
}
return puts("=========thread info end==========================");
}

canonical_decompiled_code:
int func4()
{
__int64 v0; // rbp
unsigned __int64 v1; // rbx
unsigned int v2; // eax

puts("=========thread info=========================");
if ( thread_pool[1] )
{
v0 = 0LL;
v1 = 0LL;
do
{
v2 = thread_counter_get(thread_pool[0] + v0 + 48);
printf("thread[%d].job_done: %d\n", (unsigned int)v1++, v2);
v0 += 104LL;
}
while ( thread_pool[1] > v1 );
}
return puts("=========thread info end==========================");
}

original_code:
void printThreadInfo()
{
    printf("=========thread info=========================\n");
    int i;
    for(i = 0; i < thread_pool.thread_count; i++) {
 printf("thread[%d].job_done: %d\n", i, thread_counter_get(&thread_pool.thread_items[i].job_done));
    }
    printf("=========thread info end==========================\n");
}

variable_types: i int

return_type: void


decompiled_code:
__int64 do_work()
{
int v0; // er12
void *v1; // rbx
__int64 i; // rbx
__int64 v3; // rbp
_DWORD *v4; // r14
unsigned int v5; // eax
unsigned int v6; // eax
unsigned int v7; // eax
unsigned int v8; // eax
unsigned int v9; // eax
unsigned __int64 v10; // rbx
void *v12; // [rsp+0h] [rbp-68h]
int v13; // [rsp+Ch] [rbp-5Ch]
void *v14; // [rsp+10h] [rbp-58h] BYREF
_DWORD *v15; // [rsp+18h] [rbp-50h]
void *v16; // [rsp+20h] [rbp-48h] BYREF
void *ptr; // [rsp+28h] [rbp-40h]

puts("=====================do_work start================================");
v0 = 0;
while ( (unsigned int)thread_counter_get(&global_lock) && *((int *)&webgraph + 1) <= 199999 )
{
sem_wait(&work_sem);
puts("=========get work=================");
if ( (int)ts_queue_size(&urlqueue) > 0 )
{
ts_queue_top(&urlqueue, &v16);
v1 = v16;
v12 = v16;
insert_edge(&webgraph, ptr, v16);
puts("=====================create job=========================");
for ( i = list_first(v1); i != list_end(v12); i = list_next(i) )
{
v3 = find_vertex_info(&webgraph, i + 12);
if ( !*(_DWORD *)(v3 + 4) )
{
v14 = do_crawler;
v13 = *(_DWORD *)(i + 8);
v4 = malloc(v13 + 4LL);
if ( v4 )
{
*v4 = v13;
memcpy(v4 + 1, (const void *)(i + 12), *(int *)(i + 8));
v15 = v4;
thread_pool_set_job(thread_pool, &v14);
*(_DWORD *)(v3 + 4) = 1;
thread_counter_increase(&global_lock);
thread_pool_post_job_semaphare(thread_pool);
}
else
{
fwrite("Error, allocate memory failed in func 'do_work'.\n", 1uLL, 0x31uLL, stderr);
}
}
}
puts("=====================create job over=========================");
free(ptr);
list_destroy(v16);
free(v16);
puts("=========get work end=================");
thread_counter_decrease(&global_lock);
puts("=====================do work over=========================");
}
else
{
puts("=========check over=================");
}
v5 = ts_queue_size((unsigned int)((_DWORD)thread_pool + 144));
printf("==========job queue size: %d===============================\n", v5);
v6 = ts_queue_size(&urlqueue);
printf("==========urlqueue size: %d===============================\n", v6);
v7 = thread_counter_get((unsigned int)((_DWORD)thread_pool + 48));
printf("==========job done: %d===============================\n", v7);
printf("==========vertex size: %d===============================\n", *((unsigned int *)&webgraph + 1));
v8 = thread_counter_get((unsigned int)((_DWORD)thread_pool + 96));
printf("==========idle thread: %d===============================\n", v8);
v9 = thread_counter_get(&global_lock);
printf("=========global_lock count: %d====================================\n", v9);
if ( v0 % 100 == 99 )
printThreadInfo();
++v0;
}
puts("-------------------do work post exit-----------------------------");
if ( thread_pool[1] )
{
v10 = 0LL;
do
{
v14 = do_exit;
v15 = 0LL;
thread_pool_set_job(thread_pool, &v14);
thread_pool_post_job_semaphare(thread_pool);
++v10;
}
while ( thread_pool[1] > v10 );
}
printWebg(&webgraph);
puts("-------------------do work run over-----------------------------");
return 0LL;
}

canonical_decompiled_code:
__int64 func5()
{
int v0; // er12
void *v1; // rbx
__int64 i; // rbx
__int64 v3; // rbp
_DWORD *v4; // r14
unsigned int v5; // eax
unsigned int v6; // eax
unsigned int v7; // eax
unsigned int v8; // eax
unsigned int v9; // eax
unsigned __int64 v10; // rbx
void *v12; // [rsp+0h] [rbp-68h]
int v13; // [rsp+Ch] [rbp-5Ch]
void *v14; // [rsp+10h] [rbp-58h] BYREF
_DWORD *v15; // [rsp+18h] [rbp-50h]
void *v16; // [rsp+20h] [rbp-48h] BYREF
void *ptr; // [rsp+28h] [rbp-40h]

puts("=====================do_work start================================");
v0 = 0;
while ( (unsigned int)thread_counter_get(&global_lock) && *((int *)&webgraph + 1) <= 199999 )
{
sem_wait(&work_sem);
puts("=========get work=================");
if ( (int)ts_queue_size(&urlqueue) > 0 )
{
ts_queue_top(&urlqueue, &v16);
v1 = v16;
v12 = v16;
insert_edge(&webgraph, ptr, v16);
puts("=====================create job=========================");
for ( i = list_first(v1); i != list_end(v12); i = list_next(i) )
{
v3 = find_vertex_info(&webgraph, i + 12);
if ( !*(_DWORD *)(v3 + 4) )
{
v14 = do_crawler;
v13 = *(_DWORD *)(i + 8);
v4 = malloc(v13 + 4LL);
if ( v4 )
{
*v4 = v13;
memcpy(v4 + 1, (const void *)(i + 12), *(int *)(i + 8));
v15 = v4;
thread_pool_set_job(thread_pool, &v14);
*(_DWORD *)(v3 + 4) = 1;
thread_counter_increase(&global_lock);
thread_pool_post_job_semaphare(thread_pool);
}
else
{
fwrite("Error, allocate memory failed in func 'do_work'.\n", 1uLL, 0x31uLL, stderr);
}
}
}
puts("=====================create job over=========================");
free(ptr);
list_destroy(v16);
free(v16);
puts("=========get work end=================");
thread_counter_decrease(&global_lock);
puts("=====================do work over=========================");
}
else
{
puts("=========check over=================");
}
v5 = ts_queue_size((unsigned int)((_DWORD)thread_pool + 144));
printf("==========job queue size: %d===============================\n", v5);
v6 = ts_queue_size(&urlqueue);
printf("==========urlqueue size: %d===============================\n", v6);
v7 = thread_counter_get((unsigned int)((_DWORD)thread_pool + 48));
printf("==========job done: %d===============================\n", v7);
printf("==========vertex size: %d===============================\n", *((unsigned int *)&webgraph + 1));
v8 = thread_counter_get((unsigned int)((_DWORD)thread_pool + 96));
printf("==========idle thread: %d===============================\n", v8);
v9 = thread_counter_get(&global_lock);
printf("=========global_lock count: %d====================================\n", v9);
if ( v0 % 100 == 99 )
func4();
++v0;
}
puts("-------------------do work post exit-----------------------------");
if ( thread_pool[1] )
{
v10 = 0LL;
do
{
v14 = do_exit;
v15 = 0LL;
thread_pool_set_job(thread_pool, &v14);
thread_pool_post_job_semaphare(thread_pool);
++v10;
}
while ( thread_pool[1] > v10 );
}
printWebg(&webgraph);
puts("-------------------do work run over-----------------------------");
return 0LL;
}

original_code:
void *do_work(void *arg)
{
    printf("=====================do_work start================================\n");
    int report = 0;
    link_info_t link_info;
    while(thread_counter_get(&global_lock) != 0 && webgraph.vertex_size < 200000) {
 sem_wait(&work_sem);
     printf("=========get work=================\n");
 if(ts_queue_size(&urlqueue) > 0) {
     ts_queue_top(&urlqueue, &link_info);
     char *url = link_info.url;
     list_t *link_url = link_info.link_url;
     insert_edge(&webgraph, url, link_url);
     elem_t *iter;
     vertex_info_t *vertex_info;
     printf("=====================create job=========================\n");
     for(iter = list_first(link_url); iter != list_end(link_url); iter = list_next(iter)) {
         vertex_info = find_vertex_info(&webgraph, iter->buffer);
         if(!vertex_info->in) {
             job_t job;
                    job.run = do_crawler;
                    sds_t *job_arg;
                    if((job_arg = (sds_t *)malloc(sizeof(sds_t) + iter->len)) != ((void *)0)) {
                        job_arg->len = iter->len;
                        memcpy(job_arg->buffer, iter->buffer, iter->len);
                        job.arg = (void *)job_arg;
                     thread_pool_set_job(&thread_pool, &job);
              vertex_info->in = 1;
       thread_counter_increase(&global_lock);
                        thread_pool_post_job_semaphare(&thread_pool);
             } else {
           fprintf(stderr, "Error, allocate memory failed in func 'do_work'.\n");
             }
         }
     }
     printf("=====================create job over=========================\n");
     free(link_info.url);
     list_destroy(link_info.link_url);
     free(link_info.link_url);
         printf("=========get work end=================\n");
     thread_counter_decrease(&global_lock);
     printf("=====================do work over=========================\n");
 } else {
         printf("=========check over=================\n");
 }
        printf("==========job queue size: %d===============================\n", ts_queue_size(&thread_pool.job_queue));
        printf("==========urlqueue size: %d===============================\n", ts_queue_size(&urlqueue));
        printf("==========job done: %d===============================\n", thread_counter_get(&thread_pool.job_done));
        printf("==========vertex size: %d===============================\n", webgraph.vertex_size);
        printf("==========idle thread: %d===============================\n", thread_counter_get(&thread_pool.thread_idle));
     printf("=========global_lock count: %d====================================\n", thread_counter_get(&global_lock));
        if(report++ % 100 == 99) {
            printThreadInfo();
        }
    }
    printf("-------------------do work post exit-----------------------------\n");
    int i;
    for(i = 0; i < thread_pool.thread_count; i++) {
 job_t exit_job;
 exit_job.run = do_exit;
 exit_job.arg = ((void *)0);
 thread_pool_set_job(&thread_pool, &exit_job);
        thread_pool_post_job_semaphare(&thread_pool);
    }
    printWebg(&webgraph);
    printf("-------------------do work run over-----------------------------\n");
    return 0;
}

canonical_original_code:
void *do_work(void *arg)
{
    printf("=====================do_work start================================\n");
    int report = 0;
    struct _link_info link_info;
    while(thread_counter_get(&global_lock) != 0 && webgraph.vertex_size < 200000) {
 sem_wait(&work_sem);
     printf("=========get work=================\n");
 if(ts_queue_size(&urlqueue) > 0) {
     ts_queue_top(&urlqueue, &link_info);
     char *url = link_info.url;
     struct _list *link_url = link_info.link_url;
     insert_edge(&webgraph, url, link_url);
     struct _elem *iter;
     struct _vertex_info *vertex_info;
     printf("=====================create job=========================\n");
     for(iter = list_first(link_url); iter != list_end(link_url); iter = list_next(iter)) {
         vertex_info = find_vertex_info(&webgraph, iter->buffer);
         if(!vertex_info->in) {
             struct _job job;
                    job.run = do_crawler;
                    struct _sds *job_arg;
                    if((job_arg = (struct _sds *)malloc(sizeof(sds_t) + iter->len)) != ((void *)0)) {
                        job_arg->len = iter->len;
                        memcpy(job_arg->buffer, iter->buffer, iter->len);
                        job.arg = (void *)job_arg;
                     thread_pool_set_job(&thread_pool, &job);
              vertex_info->in = 1;
       thread_counter_increase(&global_lock);
                        thread_pool_post_job_semaphare(&thread_pool);
             } else {
           fprintf(stderr, "Error, allocate memory failed in func 'do_work'.\n");
             }
         }
     }
     printf("=====================create job over=========================\n");
     free(link_info.url);
     list_destroy(link_info.link_url);
     free(link_info.link_url);
         printf("=========get work end=================\n");
     thread_counter_decrease(&global_lock);
     printf("=====================do work over=========================\n");
 } else {
         printf("=========check over=================\n");
 }
        printf("==========job queue size: %d===============================\n", ts_queue_size(&thread_pool.job_queue));
        printf("==========urlqueue size: %d===============================\n", ts_queue_size(&urlqueue));
        printf("==========job done: %d===============================\n", thread_counter_get(&thread_pool.job_done));
        printf("==========vertex size: %d===============================\n", webgraph.vertex_size);
        printf("==========idle thread: %d===============================\n", thread_counter_get(&thread_pool.thread_idle));
     printf("=========global_lock count: %d====================================\n", thread_counter_get(&global_lock));
        if(report++ % 100 == 99) {
            printThreadInfo();
        }
    }
    printf("-------------------do work post exit-----------------------------\n");
    int i;
    for(i = 0; i < thread_pool.thread_count; i++) {
 struct _job exit_job;
 exit_job.run = do_exit;
 exit_job.arg = ((void *)0);
 thread_pool_set_job(&thread_pool, &exit_job);
        thread_pool_post_job_semaphare(&thread_pool);
    }
    printWebg(&webgraph);
    printf("-------------------do work run over-----------------------------\n");
    return 0;
}

variable_types:
arg
void *

variable_types: report int

variable_types:
url
char *

variable_types: struct _list { struct _elem { struct _elem *next; int len; char buffer[]; } meta; struct _elem *head; struct _elem *tail; } *

variable_types: struct _elem { struct _elem *next; int len; char buffer[]; } *

variable_types: struct _vertex_info { int vid; int in; struct _sds { int len; char buffer[]; } url; } *

variable_types: struct _job { void *(*run)(void *); void *arg; }

return_type: void *

user_defined_types: struct _list { struct _elem meta; struct _elem *head; struct _elem *tail; }


decompiled_code:
__int64 __fastcall extract_absolute_link_s(unsigned __int8 *a1, __int64 a2, const char *a3)
{
unsigned __int8 *v4; // rbp
char *v5; // r13
int v6; // edx
int v7; // ebp
int v8; // er14
int v9; // ebp
int v10; // er15
int v11; // er14
__int64 result; // rax
char s[4096]; // [rsp+20h] [rbp-1048h] BYREF
int v15; // [rsp+1020h] [rbp-48h] BYREF
int v16; // [rsp+1024h] [rbp-44h]
int v17; // [rsp+1028h] [rbp-40h]
int v18; // [rsp+102Ch] [rbp-3Ch]

v4 = 0LL;
v5 = 0LL;
v6 = 0;
while ( 1 )
{
result = *a1;
LABEL_81:
if ( !(_BYTE)result )
return result;
switch ( v6 )
{
case 0:
if ( (_BYTE)result == 60 )
{
v6 = 1;
}
else if ( (_BYTE)result == 10 )
{
v6 = 12;
}
++a1;
continue;
case 1:
if ( (_BYTE)result == 97 )
{
v6 = 2;
LABEL_12:
++a1;
continue;
}
if ( (_BYTE)result != 62 )
{
if ( (_BYTE)result != 9 && (_BYTE)result != 32 )
v6 = 12;
goto LABEL_12;
}
v6 = 11;
break;
case 2:
if ( (_BYTE)result == 9 || (_BYTE)result == 32 )
{
v6 = 3;
goto LABEL_19;
}
if ( (_BYTE)result != 62 )
{
v6 = 12;
LABEL_19:
++a1;
continue;
}
v6 = 11;
continue;
case 3:
if ( (_BYTE)result == 62 )
{
v6 = 11;
}
else
{
if ( (_BYTE)result == 10 )
{
v6 = 12;
}
else if ( (_BYTE)result == 104 )
{
v6 = 4;
}
++a1;
}
continue;
case 4:
if ( (_BYTE)result == 62 )
{
v6 = 11;
}
else
{
v6 = 12;
if ( (_BYTE)result != 10 )
v6 = 2 * ((_BYTE)result == 114) + 3;
++a1;
}
continue;
case 5:
if ( (_BYTE)result == 62 )
{
v6 = 11;
}
else
{
v6 = 12;
if ( (_BYTE)result != 10 )
v6 = 3 * ((_BYTE)result == 101) + 3;
++a1;
}
continue;
case 6:
if ( (_BYTE)result == 62 )
{
v6 = 11;
}
else
{
v6 = 12;
if ( (_BYTE)result != 10 )
v6 = 4 * ((_BYTE)result == 102) + 3;
++a1;
}
continue;
case 7:
if ( (_BYTE)result == 62 )
{
v6 = 11;
}
else
{
if ( (_BYTE)result == 10 )
{
v6 = 12;
}
else if ( (_BYTE)result == 61 )
{
v6 = 8;
}
else if ( (_BYTE)result != 9 && (_BYTE)result != 32 )
{
v6 = 3;
}
++a1;
}
continue;
case 8:
if ( (_BYTE)result == 62 )
{
v6 = 11;
}
else
{
if ( (_BYTE)result == 10 )
{
v6 = 12;
}
else if ( (_BYTE)result == 34 || (_BYTE)result == 39 )
{
v5 = (char *)(a1 + 1);
v6 = 9;
}
else if ( (_BYTE)result != 9 && (_BYTE)result != 32 )
{
v6 = 3;
}
++a1;
}
continue;
case 9:
if ( (_BYTE)result == 62 )
{
v6 = 11;
}
else
{
if ( (_BYTE)result == 10 )
{
v6 = 12;
}
else if ( (_BYTE)result == 34 || (_BYTE)result == 39 )
{
v4 = a1 - 1;
v6 = 10;
}
++a1;
}
continue;
case 10:
if ( (_BYTE)result == 62 )
{
v6 = 11;
}
else
{
if ( (_BYTE)result == 10 )
v6 = 12;
++a1;
}
continue;
case 11:
if ( v5 && v4 )
{
bzero(s, 0x1000uLL);
v7 = (_DWORD)v4 - (_DWORD)v5;
v8 = v7 + 1;
if ( (unsigned int)search_root(v5, v7 + 1, a3, &v15) )
{
if ( v8 > 0 )
{
memcpy(s, v5, v8);
list_push_back(a2, s, v7 + 2);
}
}
else
{
v9 = v16 - v15;
v10 = v17;
v11 = v18 - v17;
if ( v16 - v15 > 0 && v11 > 0 )
{
memcpy(s, &a3[v15], v9);
memcpy(&s[v9], &v5[v10], v11);
list_push_back(a2, s, v9 + v11 + 1);
}
}
}
++a1;
v4 = 0LL;
v5 = 0LL;
v6 = 0;
continue;
case 12:
v4 = 0LL;
v5 = 0LL;
v6 = 0;
continue;
default:
goto LABEL_81;
}
}
}

canonical_decompiled_code:
__int64 __fastcall func1(unsigned __int8 *a1, __int64 a2, const char *a3)
{
unsigned __int8 *v4; // rbp
char *v5; // r13
int v6; // edx
int v7; // ebp
int v8; // er14
int v9; // ebp
int v10; // er15
int v11; // er14
__int64 result; // rax
char s[4096]; // [rsp+20h] [rbp-1048h] BYREF
int v15; // [rsp+1020h] [rbp-48h] BYREF
int v16; // [rsp+1024h] [rbp-44h]
int v17; // [rsp+1028h] [rbp-40h]
int v18; // [rsp+102Ch] [rbp-3Ch]

v4 = 0LL;
v5 = 0LL;
v6 = 0;
while ( 1 )
{
result = *a1;
LABEL_81:
if ( !(_BYTE)result )
return result;
switch ( v6 )
{
case 0:
if ( (_BYTE)result == 60 )
{
v6 = 1;
}
else if ( (_BYTE)result == 10 )
{
v6 = 12;
}
++a1;
continue;
case 1:
if ( (_BYTE)result == 97 )
{
v6 = 2;
LABEL_12:
++a1;
continue;
}
if ( (_BYTE)result != 62 )
{
if ( (_BYTE)result != 9 && (_BYTE)result != 32 )
v6 = 12;
goto LABEL_12;
}
v6 = 11;
break;
case 2:
if ( (_BYTE)result == 9 || (_BYTE)result == 32 )
{
v6 = 3;
goto LABEL_19;
}
if ( (_BYTE)result != 62 )
{
v6 = 12;
LABEL_19:
++a1;
continue;
}
v6 = 11;
continue;
case 3:
if ( (_BYTE)result == 62 )
{
v6 = 11;
}
else
{
if ( (_BYTE)result == 10 )
{
v6 = 12;
}
else if ( (_BYTE)result == 104 )
{
v6 = 4;
}
++a1;
}
continue;
case 4:
if ( (_BYTE)result == 62 )
{
v6 = 11;
}
else
{
v6 = 12;
if ( (_BYTE)result != 10 )
v6 = 2 * ((_BYTE)result == 114) + 3;
++a1;
}
continue;
case 5:
if ( (_BYTE)result == 62 )
{
v6 = 11;
}
else
{
v6 = 12;
if ( (_BYTE)result != 10 )
v6 = 3 * ((_BYTE)result == 101) + 3;
++a1;
}
continue;
case 6:
if ( (_BYTE)result == 62 )
{
v6 = 11;
}
else
{
v6 = 12;
if ( (_BYTE)result != 10 )
v6 = 4 * ((_BYTE)result == 102) + 3;
++a1;
}
continue;
case 7:
if ( (_BYTE)result == 62 )
{
v6 = 11;
}
else
{
if ( (_BYTE)result == 10 )
{
v6 = 12;
}
else if ( (_BYTE)result == 61 )
{
v6 = 8;
}
else if ( (_BYTE)result != 9 && (_BYTE)result != 32 )
{
v6 = 3;
}
++a1;
}
continue;
case 8:
if ( (_BYTE)result == 62 )
{
v6 = 11;
}
else
{
if ( (_BYTE)result == 10 )
{
v6 = 12;
}
else if ( (_BYTE)result == 34 || (_BYTE)result == 39 )
{
v5 = (char *)(a1 + 1);
v6 = 9;
}
else if ( (_BYTE)result != 9 && (_BYTE)result != 32 )
{
v6 = 3;
}
++a1;
}
continue;
case 9:
if ( (_BYTE)result == 62 )
{
v6 = 11;
}
else
{
if ( (_BYTE)result == 10 )
{
v6 = 12;
}
else if ( (_BYTE)result == 34 || (_BYTE)result == 39 )
{
v4 = a1 - 1;
v6 = 10;
}
++a1;
}
continue;
case 10:
if ( (_BYTE)result == 62 )
{
v6 = 11;
}
else
{
if ( (_BYTE)result == 10 )
v6 = 12;
++a1;
}
continue;
case 11:
if ( v5 && v4 )
{
bzero(s, 0x1000uLL);
v7 = (_DWORD)v4 - (_DWORD)v5;
v8 = v7 + 1;
if ( (unsigned int)func0(v5, v7 + 1, a3, &v15) )
{
if ( v8 > 0 )
{
memcpy(s, v5, v8);
list_push_back(a2, s, v7 + 2);
}
}
else
{
v9 = v16 - v15;
v10 = v17;
v11 = v18 - v17;
if ( v16 - v15 > 0 && v11 > 0 )
{
memcpy(s, &a3[v15], v9);
memcpy(&s[v9], &v5[v10], v11);
list_push_back(a2, s, v9 + v11 + 1);
}
}
}
++a1;
v4 = 0LL;
v5 = 0LL;
v6 = 0;
continue;
case 12:
v4 = 0LL;
v5 = 0LL;
v6 = 0;
continue;
default:
goto LABEL_81;
}
}
}

original_code:
void extract_absolute_link_s(const char *htmltxt, list_t *urllist, char *url)
{
    enum {S_START, S_LEFT, S_A, S_BLANK, S_H, S_R, S_E, S_F, S_EQ, S_LQ, S_RQ, S_RIGHT, S_END};
    const char *ch = htmltxt;
    int status = S_START;
    const char *as = ((void *)0), *ae = ((void *)0), *ls = ((void *)0), *le = ((void *)0);
    link_offset_t link_offset;
    char link[4096];
    int prefix_size, path_size, link_size;
    int k = 0;
    while(*ch) {
 switch(status) {
 case S_START:
     if(*ch == '<') {
  status = S_LEFT;
  as = ch;
     } else if(*ch == '\n') {
  status = S_END;
     }
     k++;
     ch++;
 break;
 case S_LEFT:
     if(*ch == 'a') {
  status = S_A;
     } else if(*ch == '>') {
  ae = ch;
  status = S_RIGHT;
  continue;
     } else if(!(*ch == '\t' || *ch == ' ')) {
  status = S_END;
     }
     k++;
     ch++;
 break;
 case S_A:
     if(*ch == '\t' || *ch == ' ') {
  status = S_BLANK;
     } else if(*ch == '>') {
  status = S_RIGHT;
  ae = ch;
  continue;
     } else if(*ch == '\n') {
  status = S_END;
     } else {
  status = S_END;
     }
     k++;
     ch++;
 break;
 case S_BLANK:
     if(*ch == '>') {
         status = S_RIGHT;
  ae = ch;
  continue;
     } else if(*ch == '\n') {
         status = S_END;
     } else if(*ch == 'h') {
         status = S_H;
     }
     k++;
     ch++;
 break;
 case S_H:
     if(*ch == '>') {
         status = S_RIGHT;
  ae = ch;
  continue;
     } else if(*ch == '\n') {
          status = S_END;
     } else if(*ch == 'r') {
          status = S_R;
     } else {
          status = S_BLANK;
     }
     k++;
     ch++;
 break;
 case S_R:
     if(*ch == '>') {
  status = S_RIGHT;
  ae = ch;
  continue;
     } else if(*ch == '\n') {
  status = S_END;
     } else if(*ch == 'e') {
  status = S_E;
     } else {
  status = S_BLANK;
     }
     k++;
     ch++;
 break;
 case S_E:
     if(*ch == '>') {
  status = S_RIGHT;
  ae = ch;
  continue;
     } else if(*ch == '\n') {
  status = S_END;
     } else if(*ch == 'f') {
  status = S_F;
     } else {
  status = S_BLANK;
     }
     k++;
     ch++;
 break;
 case S_F:
     if(*ch == '>') {
  status = S_RIGHT;
  ae = ch;
  continue;
     } else if(*ch == '\n') {
  status = S_END;
     } else if(*ch == '=') {
  status = S_EQ;
     } else if(!(*ch == '\t' || *ch == ' ')) {
  status = S_BLANK;
     }
     k++;
     ch++;
 break;
 case S_EQ:
     if(*ch == '>') {
  status = S_RIGHT;
  ae = ch;
  continue;
     } else if(*ch == '\n') {
  status = S_END;
     } else if(*ch == '"' || *ch == '\'') {
  ls = ch + 1;
  status = S_LQ;
     } else if(!(*ch == '\t' || *ch == ' ')) {
  status = S_BLANK;
     }
     k++;
     ch++;
 break;
 case S_LQ:
     if(*ch == '>') {
  status = S_RIGHT;
  ae = ch;
  continue;
     } else if(*ch == '\n') {
  status = S_END;
     } else if(*ch == '"' || *ch == '\'') {
  le = ch - 1 ;
  status = S_RQ;
     }
     k++;
     ch++;
 break;
 case S_RQ:
     if(*ch == '>') {
  status = S_RIGHT;
  ae = ch;
  continue;
     } else if(*ch == '\n') {
  status = S_END;
     }
     k++;
     ch++;
 break;
 case S_RIGHT:
     status = S_START;
     if(!(ls == ((void *)0) || le == ((void *)0))) {
  bzero(link, 4096);
  link_size = le - ls + 1;
         if(!_search_root(ls, link_size, url, &link_offset)) {
             prefix_size = link_offset.pre_eo - link_offset.pre_so;
             path_size = link_offset.path_eo - link_offset.path_so;
      if(prefix_size > 0 && path_size > 0) {
                 memcpy(link, url + link_offset.pre_so, prefix_size);
                 memcpy(link + prefix_size, ls + link_offset.path_so, path_size);
                 list_push_back(urllist, link, prefix_size + path_size + 1);
      }
                } else {
      if(link_size > 0) {
                 memcpy(link, ls, link_size);
                 list_push_back(urllist, link, link_size + 1);
      }
         }
     }
     as = ae = ls = le = ((void *)0);
     k++;
     ch++;
 break;
 case S_END:
     status = S_START;
     as = ae = ls = le = ((void *)0);
 break;
 }
    }
}

canonical_original_code:
void extract_absolute_link_s(char *htmltxt, struct _list *urllist, char *url)
{
    enum {S_START, S_LEFT, S_A, S_BLANK, S_H, S_R, S_E, S_F, S_EQ, S_LQ, S_RQ, S_RIGHT, S_END};
    char *ch = htmltxt;
    int status = S_START;
    char *as = ((void *)0); char *ae = ((void *)0); char *ls = ((void *)0); char *le = ((void *)0);
    struct _link_offset link_offset;
    char link[4096];
    int prefix_size; int path_size; int link_size;
    int k = 0;
    while(*ch) {
 switch(status) {
 case S_START:
     if(*ch == '<') {
  status = S_LEFT;
  as = ch;
     } else if(*ch == '\n') {
  status = S_END;
     }
     k++;
     ch++;
 break;
 case S_LEFT:
     if(*ch == 'a') {
  status = S_A;
     } else if(*ch == '>') {
  ae = ch;
  status = S_RIGHT;
  continue;
     } else if(!(*ch == '\t' || *ch == ' ')) {
  status = S_END;
     }
     k++;
     ch++;
 break;
 case S_A:
     if(*ch == '\t' || *ch == ' ') {
  status = S_BLANK;
     } else if(*ch == '>') {
  status = S_RIGHT;
  ae = ch;
  continue;
     } else if(*ch == '\n') {
  status = S_END;
     } else {
  status = S_END;
     }
     k++;
     ch++;
 break;
 case S_BLANK:
     if(*ch == '>') {
         status = S_RIGHT;
  ae = ch;
  continue;
     } else if(*ch == '\n') {
         status = S_END;
     } else if(*ch == 'h') {
         status = S_H;
     }
     k++;
     ch++;
 break;
 case S_H:
     if(*ch == '>') {
         status = S_RIGHT;
  ae = ch;
  continue;
     } else if(*ch == '\n') {
          status = S_END;
     } else if(*ch == 'r') {
          status = S_R;
     } else {
          status = S_BLANK;
     }
     k++;
     ch++;
 break;
 case S_R:
     if(*ch == '>') {
  status = S_RIGHT;
  ae = ch;
  continue;
     } else if(*ch == '\n') {
  status = S_END;
     } else if(*ch == 'e') {
  status = S_E;
     } else {
  status = S_BLANK;
     }
     k++;
     ch++;
 break;
 case S_E:
     if(*ch == '>') {
  status = S_RIGHT;
  ae = ch;
  continue;
     } else if(*ch == '\n') {
  status = S_END;
     } else if(*ch == 'f') {
  status = S_F;
     } else {
  status = S_BLANK;
     }
     k++;
     ch++;
 break;
 case S_F:
     if(*ch == '>') {
  status = S_RIGHT;
  ae = ch;
  continue;
     } else if(*ch == '\n') {
  status = S_END;
     } else if(*ch == '=') {
  status = S_EQ;
     } else if(!(*ch == '\t' || *ch == ' ')) {
  status = S_BLANK;
     }
     k++;
     ch++;
 break;
 case S_EQ:
     if(*ch == '>') {
  status = S_RIGHT;
  ae = ch;
  continue;
     } else if(*ch == '\n') {
  status = S_END;
     } else if(*ch == '"' || *ch == '\'') {
  ls = ch + 1;
  status = S_LQ;
     } else if(!(*ch == '\t' || *ch == ' ')) {
  status = S_BLANK;
     }
     k++;
     ch++;
 break;
 case S_LQ:
     if(*ch == '>') {
  status = S_RIGHT;
  ae = ch;
  continue;
     } else if(*ch == '\n') {
  status = S_END;
     } else if(*ch == '"' || *ch == '\'') {
  le = ch - 1 ;
  status = S_RQ;
     }
     k++;
     ch++;
 break;
 case S_RQ:
     if(*ch == '>') {
  status = S_RIGHT;
  ae = ch;
  continue;
     } else if(*ch == '\n') {
  status = S_END;
     }
     k++;
     ch++;
 break;
 case S_RIGHT:
     status = S_START;
     if(!(ls == ((void *)0) || le == ((void *)0))) {
  bzero(link, 4096);
  link_size = le - ls + 1;
         if(!_search_root(ls, link_size, url, &link_offset)) {
             prefix_size = link_offset.pre_eo - link_offset.pre_so;
             path_size = link_offset.path_eo - link_offset.path_so;
      if(prefix_size > 0 && path_size > 0) {
                 memcpy(link, url + link_offset.pre_so, prefix_size);
                 memcpy(link + prefix_size, ls + link_offset.path_so, path_size);
                 list_push_back(urllist, link, prefix_size + path_size + 1);
      }
                } else {
      if(link_size > 0) {
                 memcpy(link, ls, link_size);
                 list_push_back(urllist, link, link_size + 1);
      }
         }
     }
     as = ae = ls = le = ((void *)0);
     k++;
     ch++;
 break;
 case S_END:
     status = S_START;
     as = ae = ls = le = ((void *)0);
 break;
 }
    }
}

variable_types:
htmltxt
char *

variable_types:
ch
char *

variable_types: status int

variable_types:
as
char *

variable_types:
ae
char *

variable_types:
ls
char *

variable_types:
le
char *

variable_types: struct _link_offset { int pre_so; int pre_eo; int path_so; int path_eo; }

variable_types:
link
char [4096]

variable_types: k int

user_defined_types: struct _elem { struct _elem *next; int len; char buffer[]; }


main

canonical_name: main

decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
const char *v3; // r13
const char *v4; // r12
int v5; // ebp
_DWORD *v6; // rax
__int64 v7; // rbx
void *v8; // r14
unsigned int v9; // eax
int v10; // ebx
__int64 v12[2]; // [rsp+0h] [rbp-1218h] BYREF
char v13[112]; // [rsp+10h] [rbp-1208h] BYREF
char v14[16]; // [rsp+80h] [rbp-1198h] BYREF
char src[4488]; // [rsp+90h] [rbp-1188h] BYREF

if ( argc <= 2 )
{
fwrite("too few argument, 3 arguments expected.\n", 1uLL, 0x28uLL, stderr);
v10 = 1;
}
else
{
v3 = argv[1];
v4 = argv[2];
http_url_parse_s(v14, v3, envp);
if ( v14[0] )
sprintf(domain, "%s://", v14);
strcat(domain, src);
init_webg(&webgraph);
sem_init(&work_sem, 0, 0);
ts_queue_init(&urlqueue);
thread_pool_init(&thread_pool, 300LL);
thread_pool_run(&thread_pool);
v5 = strlen(v3);
v6 = malloc(v5 + 1 + 4LL);
v7 = (__int64)v6;
if ( v6 )
{
*v6 = v5 + 1;
v8 = v6 + 1;
bzero(v6 + 1, v5 + 1);
memcpy(v8, v3, v5);
v12[0] = (__int64)&do_crawler;
v12[1] = v7;
thread_pool_set_job(&thread_pool, v12);
thread_counter_increase(&global_lock);
thread_pool_post_job_semaphare(&thread_pool);
}
thread_init(v13);
v9 = thread_create(v13, 0LL, &do_work, 0LL);
v10 = v9;
if ( v9 )
{
fprintf(stderr, "thread_create work faild, retval: %d.\n", v9);
}
else
{
thread_join(v13);
thread_pool_join(&thread_pool);
thread_destroy(v13);
thread_pool_destroy(&thread_pool);
puts("$$$$$$$$$$$$$$$$ start calc $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$");
calc_pagerank(&webgraph);
gen_ind_cdf(&webgraph);
gen_graphviz(&webgraph);
gen_ind_pagerank(&webgraph, v4);
gen_top(&webgraph);
thread_counter_destroy(&global_lock);
ts_queue_destroy(&urlqueue);
sem_destroy(&work_sem);
destroy_webg(&webgraph);
puts("===============================program over============================");
}
}
return v10;
}

original_code:
int main(int argc, char **argv)
{
    if(argc < 3) {
 fprintf(stderr, "too few argument, 3 arguments expected.\n");
 return 1;
    }
    char *url = argv[1];
    char *path = argv[2];
    http_url_t http_url;
    http_url_parse_s(&http_url, url);
    if(strlen(http_url.protocol) != 0) sprintf(domain, "%s://", http_url.protocol);
    strcat(domain, http_url.host);
    init_webg(&webgraph);
    sem_init(&work_sem, 0, 0);
    ts_queue_init(&urlqueue);
    thread_pool_init(&thread_pool, 300);
    thread_pool_run(&thread_pool);
    int slen = strlen(url);
    int len = slen + 1;
    sds_t *crawl_job_arg = (sds_t *)malloc(len + sizeof(sds_t));
    if(crawl_job_arg != ((void *)0)) {
        crawl_job_arg->len = len;
 bzero(crawl_job_arg->buffer, len);
        memcpy(crawl_job_arg->buffer, url, slen);
        job_t crawl_job;
        crawl_job.run = do_crawler;
        crawl_job.arg = (void *)crawl_job_arg;
        thread_pool_set_job(&thread_pool, &crawl_job);
 thread_counter_increase(&global_lock);
        thread_pool_post_job_semaphare(&thread_pool);
    }
    thread_t work_thread;
    thread_init(&work_thread);
    int ret = thread_create(&work_thread, ((void *)0), do_work, ((void *)0));
    if(ret != 0) {
 fprintf(stderr, "thread_create work faild, retval: %d.\n", ret);
 return ret;
    }
    thread_join(&work_thread);
    thread_pool_join(&thread_pool);
    thread_destroy(&work_thread);
    thread_pool_destroy(&thread_pool);
    printf("$$$$$$$$$$$$$$$$ start calc $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n");
    calc_pagerank(&webgraph);
    gen_ind_cdf(&webgraph);
    gen_graphviz(&webgraph);
    gen_ind_pagerank(&webgraph, path);
    gen_top(&webgraph);
    thread_counter_destroy(&global_lock);
    ts_queue_destroy(&urlqueue);
    sem_destroy(&work_sem);
    destroy_webg(&webgraph);
    printf("===============================program over============================\n");
    return 0;
}

canonical_original_code:
int main(int argc, char **argv)
{
    if(argc < 3) {
 fprintf(stderr, "too few argument, 3 arguments expected.\n");
 return 1;
    }
    char *url = argv[1];
    char *path = argv[2];
    struct _http_url http_url;
    http_url_parse_s(&http_url, url);
    if(strlen(http_url.protocol) != 0) sprintf(domain, "%s://", http_url.protocol);
    strcat(domain, http_url.host);
    init_webg(&webgraph);
    sem_init(&work_sem, 0, 0);
    ts_queue_init(&urlqueue);
    thread_pool_init(&thread_pool, 300);
    thread_pool_run(&thread_pool);
    int slen = strlen(url);
    int len = slen + 1;
    struct _sds *crawl_job_arg = (sds_t *)malloc(len + sizeof(sds_t));
    if(crawl_job_arg != ((void *)0)) {
        crawl_job_arg->len = len;
 bzero(crawl_job_arg->buffer, len);
        memcpy(crawl_job_arg->buffer, url, slen);
        struct _job crawl_job;
        crawl_job.run = do_crawler;
        crawl_job.arg = (void *)crawl_job_arg;
        thread_pool_set_job(&thread_pool, &crawl_job);
 thread_counter_increase(&global_lock);
        thread_pool_post_job_semaphare(&thread_pool);
    }
    struct _thread work_thread;
    thread_init(&work_thread);
    int ret = thread_create(&work_thread, ((void *)0), do_work, ((void *)0));
    if(ret != 0) {
 fprintf(stderr, "thread_create work faild, retval: %d.\n", ret);
 return ret;
    }
    thread_join(&work_thread);
    thread_pool_join(&thread_pool);
    thread_destroy(&work_thread);
    thread_pool_destroy(&thread_pool);
    printf("$$$$$$$$$$$$$$$$ start calc $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n");
    calc_pagerank(&webgraph);
    gen_ind_cdf(&webgraph);
    gen_graphviz(&webgraph);
    gen_ind_pagerank(&webgraph, path);
    gen_top(&webgraph);
    thread_counter_destroy(&global_lock);
    ts_queue_destroy(&urlqueue);
    sem_destroy(&work_sem);
    destroy_webg(&webgraph);
    printf("===============================program over============================\n");
    return 0;
}

variable_types: argc int

variable_types:
argv
char **

variable_types:
path
char *

variable_types: struct _http_url { char protocol[16]; char host[64]; char port[8]; char path[256]; char search[4096]; }

variable_types: slen int

variable_types: len int

variable_types: struct _sds { int len; char buffer[]; } *

variable_types: struct _thread { unsigned long threadinfo; union pthread_mutex_t { struct __pthread_mutex_s { int __lock; unsigned int __count; int __owner; unsigned int __nusers; int __kind; short __spins; short __elision; struct __pthread_internal_list { struct __pthread_internal_list *__prev; struct __pthread_internal_list *__next; } __list; } __data; char __size[40]; long __align; } waitlock; struct _thread_count { int count; union pthread_mutex_t lock; } job_done; int id; int idle; }

variable_types: ret int

return_type: int

user_defined_types: struct _job { void *(*run)(void *); void *arg; }

user_defined_types: struct _thread { unsigned long threadinfo; union pthread_mutex_t waitlock; struct _thread_count job_done; int id; int idle; }

user_defined_types: union pthread_mutex_t { struct __pthread_mutex_s __data; char __size[40]; long __align; }

user_defined_types: struct __pthread_mutex_s { int __lock; unsigned int __count; int __owner; unsigned int __nusers; int __kind; short __spins; short __elision; struct __pthread_internal_list __list; }


decompiled_code:
__int64 __fastcall http_url_parse_s(void *dest, void *src)
{
size_t v2; // r13
char *v3; // rax
char *v4; // rbx
size_t v5; // r14
__int64 result; // rax
char *v7; // rbx
char *v8; // rbp
char *v9; // rax
char *v10; // r14
size_t v11; // r13
int v12; // edx
char *v13; // r14
char *v14; // r15
int v15; // edx
char *v16; // rax
char *v17; // rbx
size_t v18; // rbp
int v19; // edx
int v20; // edx
int v21; // eax
int v22; // edx

bzero(dest, 0x1158uLL);
v2 = strlen((const char *)src);
v3 = strstr((const char *)src, "://");
if ( v3 )
{
v4 = v3;
v5 = v3 - (_BYTE *)src;
result = check_protocol((char *)src, (int)v3 - (int)src);
if ( !(_DWORD)result )
return result;
memcpy(dest, src, v5);
v7 = v4 + 3;
}
else
{
v7 = (char *)src;
}
v8 = (char *)src + v2;
v9 = strchr(v7, 58);
v10 = v9;
if ( v9 )
{
v11 = v9 - v7;
v12 = check_host(v7, (int)v9 - (int)v7);
result = 1LL;
if ( v12 )
{
memcpy((char *)dest + 16, v7, v11);
v13 = v10 + 1;
v14 = strchr(v13, 47);
if ( !v14 )
v14 = v8;
v15 = check_port(v13, (int)v14 - (int)v13);
result = 2LL;
if ( v15 )
{
memcpy((char *)dest + 80, v13, v14 - v13);
goto LABEL_11;
}
}
}
else
{
v14 = strchr(v7, 47);
if ( !v14 )
v14 = (char *)src + v2;
v20 = check_host(v7, (int)v14 - (int)v7);
result = 1LL;
if ( v20 )
{
memcpy((char *)dest + 16, v7, v14 - v7);
LABEL_11:
v16 = strchr(v14, 63);
v17 = v16;
if ( v16 )
{
v18 = v16 - v14;
v19 = check_path(v14, (int)v16 - (int)v14);
result = 3LL;
if ( v19 )
{
memcpy((char *)dest + 88, v14, v18);
strcpy((char *)dest + 344, v17 + 1);
result = 6LL;
}
}
else
{
v21 = strlen(v14);
v22 = check_path(v14, v21);
result = 3LL;
if ( v22 )
{
strcpy((char *)dest + 88, v14);
result = 6LL;
}
}
return result;
}
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func4(void *dest, void *src)
{
size_t v2; // r13
char *v3; // rax
char *v4; // rbx
size_t v5; // r14
__int64 result; // rax
char *v7; // rbx
char *v8; // rbp
char *v9; // rax
char *v10; // r14
size_t v11; // r13
int v12; // edx
char *v13; // r14
char *v14; // r15
int v15; // edx
char *v16; // rax
char *v17; // rbx
size_t v18; // rbp
int v19; // edx
int v20; // edx
int v21; // eax
int v22; // edx

bzero(dest, 0x1158uLL);
v2 = strlen((const char *)src);
v3 = strstr((const char *)src, "://");
if ( v3 )
{
v4 = v3;
v5 = v3 - (_BYTE *)src;
result = func0((char *)src, (int)v3 - (int)src);
if ( !(_DWORD)result )
return result;
memcpy(dest, src, v5);
v7 = v4 + 3;
}
else
{
v7 = (char *)src;
}
v8 = (char *)src + v2;
v9 = strchr(v7, 58);
v10 = v9;
if ( v9 )
{
v11 = v9 - v7;
v12 = func1(v7, (int)v9 - (int)v7);
result = 1LL;
if ( v12 )
{
memcpy((char *)dest + 16, v7, v11);
v13 = v10 + 1;
v14 = strchr(v13, 47);
if ( !v14 )
v14 = v8;
v15 = func2(v13, (int)v14 - (int)v13);
result = 2LL;
if ( v15 )
{
memcpy((char *)dest + 80, v13, v14 - v13);
goto LABEL_11;
}
}
}
else
{
v14 = strchr(v7, 47);
if ( !v14 )
v14 = (char *)src + v2;
v20 = func1(v7, (int)v14 - (int)v7);
result = 1LL;
if ( v20 )
{
memcpy((char *)dest + 16, v7, v14 - v7);
LABEL_11:
v16 = strchr(v14, 63);
v17 = v16;
if ( v16 )
{
v18 = v16 - v14;
v19 = func3(v14, (int)v16 - (int)v14);
result = 3LL;
if ( v19 )
{
memcpy((char *)dest + 88, v14, v18);
strcpy((char *)dest + 344, v17 + 1);
result = 6LL;
}
}
else
{
v21 = strlen(v14);
v22 = func3(v14, v21);
result = 3LL;
if ( v22 )
{
strcpy((char *)dest + 88, v14);
result = 6LL;
}
}
return result;
}
}
return result;
}

original_code:
int http_url_parse_s(http_url_t *http_url, char *url)
{
    bzero(http_url, sizeof(http_url_t));
    char *str, *cstr = url;
    char *estr = url + strlen(url);
    str = strstr(url, "://");
    if(str != ((void *)0)) {
 if(_check_protocol(cstr, str - cstr)) {
            memcpy(http_url->protocol, cstr, str - cstr);
         cstr = str + 3;
 } else {
     return URL_PROTO_UNRECOGNIZED;
 }
    }
    str = strchr(cstr, ':');
    if(str != ((void *)0)) {
 if( _check_host(cstr, str - cstr)) {
     memcpy(http_url->host, cstr, str - cstr);
     cstr = str + 1;
     str = strchr(cstr, '/');
     str = str != ((void *)0) ? str : estr;
     if(_check_port(cstr, str - cstr)) {
         memcpy(http_url->port, cstr, str - cstr);
     } else {
         return URL_PORT_UNRECOGNIZED;
     }
     cstr = str;
 } else {
     return URL_HOST_UNRECOGNIZED;
 }
    } else {
 str = strchr(cstr, '/');
 str = str != ((void *)0) ? str : estr;
 if(_check_host(cstr, str - cstr)) {
     memcpy(http_url->host, cstr, str - cstr);
     cstr = str;
 } else {
     return URL_HOST_UNRECOGNIZED;
 }
    }
    str = strchr(cstr, '?');
    if(str != ((void *)0)) {
 if(_check_path(cstr, str - cstr)) {
            memcpy(http_url->path, cstr, str - cstr);
            cstr = str + 1;
     strcpy(http_url->search, cstr);
 } else {
     return URL_PATH_UNRECOGNIZED;
 }
    } else {
 if(_check_path(cstr, strlen(cstr))) {
     strcpy(http_url->path, cstr);
 } else {
     return URL_PATH_UNRECOGNIZED;
 }
    }
    return URL_RECOGNIZED;
}

canonical_original_code:
int http_url_parse_s(struct _http_url *http_url, char *url)
{
    bzero(http_url, sizeof(http_url_t));
    char *str; char *cstr = url;
    char *estr = url + strlen(url);
    str = strstr(url, "://");
    if(str != ((void *)0)) {
 if(_check_protocol(cstr, str - cstr)) {
            memcpy(http_url->protocol, cstr, str - cstr);
         cstr = str + 3;
 } else {
     return URL_PROTO_UNRECOGNIZED;
 }
    }
    str = strchr(cstr, ':');
    if(str != ((void *)0)) {
 if( _check_host(cstr, str - cstr)) {
     memcpy(http_url->host, cstr, str - cstr);
     cstr = str + 1;
     str = strchr(cstr, '/');
     str = str != ((void *)0) ? str : estr;
     if(_check_port(cstr, str - cstr)) {
         memcpy(http_url->port, cstr, str - cstr);
     } else {
         return URL_PORT_UNRECOGNIZED;
     }
     cstr = str;
 } else {
     return URL_HOST_UNRECOGNIZED;
 }
    } else {
 str = strchr(cstr, '/');
 str = str != ((void *)0) ? str : estr;
 if(_check_host(cstr, str - cstr)) {
     memcpy(http_url->host, cstr, str - cstr);
     cstr = str;
 } else {
     return URL_HOST_UNRECOGNIZED;
 }
    }
    str = strchr(cstr, '?');
    if(str != ((void *)0)) {
 if(_check_path(cstr, str - cstr)) {
            memcpy(http_url->path, cstr, str - cstr);
            cstr = str + 1;
     strcpy(http_url->search, cstr);
 } else {
     return URL_PATH_UNRECOGNIZED;
 }
    } else {
 if(_check_path(cstr, strlen(cstr))) {
     strcpy(http_url->path, cstr);
 } else {
     return URL_PATH_UNRECOGNIZED;
 }
    }
    return URL_RECOGNIZED;
}

variable_types: struct _http_url { char protocol[16]; char host[64]; char port[8]; char path[256]; char search[4096]; } *

variable_types:
url
char *

variable_types:
str
char *

variable_types:
cstr
char *

variable_types:
estr
char *


repo: yaroslavchuvaev/daemon

decompiled_code:
__int64 unset_pid()
{
unlink(PID_FILE);
return 0LL;
}

canonical_decompiled_code:
__int64 func9()
{
unlink(PID_FILE);
return 0LL;
}

original_code:
int unset_pid() {
 unlink(PID_FILE);
 return 0;
}


decompiled_code:
void __fastcall __noreturn d_exit(int status)
{
unset_pid();
exit(status);
}

canonical_decompiled_code:
void __fastcall __noreturn func11(int status)
{
func9();
exit(status);
}

original_code:
void d_exit(int status) {
 unset_pid();
 exit(status);
}

variable_types: status int


hash

decompiled_code:
void *__fastcall hash(char *src)
{
void *v1; // r12
int v2; // ebx
const char *v3; // r14
int v4; // eax
char *v5; // rbp

v1 = malloc(0x10uLL);
v2 = strlen(src);
v3 = key;
v4 = strlen(key);
v5 = (char *)malloc(v4 + v2 + 1);
strcpy(v5, src);
strcat(v5, v3);
MD5();
free(v5);
return v1;
}

canonical_decompiled_code:
void *__fastcall func12(char *src)
{
void *v1; // r12
int v2; // ebx
const char *v3; // r14
int v4; // eax
char *v5; // rbp

v1 = malloc(0x10uLL);
v2 = strlen(src);
v3 = key;
v4 = strlen(key);
v5 = (char *)malloc(v4 + v2 + 1);
strcpy(v5, src);
strcat(v5, v3);
MD5();
free(v5);
return v1;
}

original_code:
char *hash(char *input) {
 unsigned char *digest = malloc(16);
 int len = strlen(input)+strlen(key);
 char *str = malloc(len+1);
 strcpy(str,input);
 strcat(str,key);
 MD5(str,len,digest);
 free (str);
 return digest;
}

variable_types:
input
char *

variable_types:
digest
unsigned char *

return_type: char *


authdaemon

decompiled_code:
void __noreturn authdaemon()
{
int v0; // eax
int v1; // er15
int v2; // eax
char *v3; // r14
int v4; // eax
unsigned __int8 *v5; // rbp
char *v6; // rbx
int v7; // er12
unsigned __int8 *ptr; // [rsp+8h] [rbp-B0h]
struct sockaddr addr; // [rsp+10h] [rbp-A8h] BYREF

v0 = socket(1, 1, 0);
if ( v0 >= 0 )
{
v1 = v0;
addr.sa_family = 1;
strcpy(addr.sa_data, socket_file);
v2 = strlen(addr.sa_data);
if ( bind(v1, &addr, v2 + 2) < 0 )
{
write_log("socket bind error");
d_exit(1);
}
listen(v1, QUERY_LENGTH);
while ( 1 )
{
v7 = accept(v1, 0LL, 0LL);
if ( v7 >= 0 )
{
v3 = (char *)malloc(0x800uLL);
v4 = recv(v7, v3, 0x800uLL, 0);
if ( v4 <= 0 )
{
free(v3);
write_log("socket read error");
}
else
{
v3[v4] = 0;
ptr = (unsigned __int8 *)hash(v3);
v5 = ptr;
v6 = v3;
do
{
sprintf(v6, "%02x", *v5++);
v6 += 2;
}
while ( v6 != v3 + 32 );
send(v7, v3, 0x20uLL, 0);
free(v3);
free(ptr);
close(v7);
}
}
else
{
write_log("socket accept error");
}
}
}
write_log("socket error");
d_exit(1);
}

canonical_decompiled_code:
void __noreturn func13()
{
int v0; // eax
int v1; // er15
int v2; // eax
char *v3; // r14
int v4; // eax
unsigned __int8 *v5; // rbp
char *v6; // rbx
int v7; // er12
unsigned __int8 *ptr; // [rsp+8h] [rbp-B0h]
struct sockaddr addr; // [rsp+10h] [rbp-A8h] BYREF

v0 = socket(1, 1, 0);
if ( v0 >= 0 )
{
v1 = v0;
addr.sa_family = 1;
strcpy(addr.sa_data, socket_file);
v2 = strlen(addr.sa_data);
if ( bind(v1, &addr, v2 + 2) < 0 )
{
func10("socket bind error");
func11(1);
}
listen(v1, QUERY_LENGTH);
while ( 1 )
{
v7 = accept(v1, 0LL, 0LL);
if ( v7 >= 0 )
{
v3 = (char *)malloc(0x800uLL);
v4 = recv(v7, v3, 0x800uLL, 0);
if ( v4 <= 0 )
{
free(v3);
func10("socket read error");
}
else
{
v3[v4] = 0;
ptr = (unsigned __int8 *)func12(v3);
v5 = ptr;
v6 = v3;
do
{
sprintf(v6, "%02x", *v5++);
v6 += 2;
}
while ( v6 != v3 + 32 );
send(v7, v3, 0x20uLL, 0);
free(v3);
free(ptr);
close(v7);
}
}
else
{
func10("socket accept error");
}
}
}
func10("socket error");
func11(1);
}

original_code:
void authdaemon(void) {
 int sock = socket(1,SOCK_STREAM,0);
 if(sock < 0) {
  write_log("socket error");
  d_exit(1);
 }
 struct sockaddr_un sa;
 sa.sun_family = 1;
 strcpy(sa.sun_path,socket_file);
 int res = bind(sock,&sa,
  strlen(sa.sun_path) + sizeof(sa.sun_family));
 if(res<0){
  write_log("socket bind error");
  d_exit(1);
 }
 listen(sock,QUERY_LENGTH);
 while(1){
  int current_socket = accept(sock,((void *)0),((void *)0));
  if(current_socket<0){
   write_log("socket accept error");
   continue;
  }
  char *buffer = malloc(2048);
  int bytes_read = recv(current_socket,buffer,2048,0);
  if(bytes_read <=0) {
   free(buffer);
   write_log("socket read error");
   continue;
  }
  buffer[bytes_read] = '\0';
  unsigned char *digest = hash(buffer);
  int i= 0;
  for(; i < 16; i++)
      sprintf(&buffer[2*i], "%02x", digest[i]);
  send(current_socket,buffer,16*2,0);
  free(buffer);
  free(digest);
  close(current_socket);
 }
}

canonical_original_code:
void authdaemon() {
 int sock = socket(1,SOCK_STREAM,0);
 if(sock < 0) {
  write_log("socket error");
  d_exit(1);
 }
 struct sockaddr_un sa;
 sa.sun_family = 1;
 strcpy(sa.sun_path,socket_file);
 int res = bind(sock,&sa,
  strlen(sa.sun_path) + sizeof(sa.sun_family));
 if(res<0){
  write_log("socket bind error");
  d_exit(1);
 }
 listen(sock,QUERY_LENGTH);
 while(1){
  int current_socket = accept(sock,((void *)0),((void *)0));
  if(current_socket<0){
   write_log("socket accept error");
   continue;
  }
  char *buffer = malloc(2048);
  int bytes_read = recv(current_socket,buffer,2048,0);
  if(bytes_read <=0) {
   free(buffer);
   write_log("socket read error");
   continue;
  }
  buffer[bytes_read] = '\0';
  unsigned char *digest = hash(buffer);
  int i = 0;
  for(; i < 16; i++)
      sprintf(&buffer[2*i], "%02x", digest[i]);
  send(current_socket,buffer,16*2,0);
  free(buffer);
  free(digest);
  close(current_socket);
 }
}

variable_types: sock int

variable_types: struct sockaddr_un { unsigned short sun_family; char sun_path[108]; }

variable_types: res int

variable_types:
buffer
char *

variable_types: i int


decompiled_code:
int print_help()
{
printf("\n%s\n", "Help");
puts("Use next options:");
puts("--start\t\t-\tto launch");
puts("--stop\t\t-\tto stop");
puts("--status\t-\tto view status");
return putchar(10);
}

canonical_decompiled_code:
int func14()
{
printf("\n%s\n", "Help");
puts("Use next options:");
puts("--start\t\t-\tto launch");
puts("--stop\t\t-\tto stop");
puts("--status\t-\tto view status");
return putchar(10);
}

original_code:
void print_help() {
 printf("\n%s\n", "Help");
 printf("%s\n", "Use next options:");
 printf("%s\n", "--start\t\t-\tto launch");
 printf("%s\n", "--stop\t\t-\tto stop");
 printf("%s\n", "--status\t-\tto view status");
 printf("\n");
}


decompiled_code:
int __fastcall print_error(const char *a1)
{
return printf("[ERROR]\t%s\n", a1);
}

canonical_decompiled_code:
int __fastcall func15(const char *a1)
{
return printf("[ERROR]\t%s\n", a1);
}

original_code:
void print_error(char *error) {
 printf("[ERROR]\t%s\n",error);
}

variable_types:
error
char *


main

decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v3; // ebp
const char *v5; // rbx
__pid_t v6; // eax
__int64 v7; // rbx

if ( getuid() )
{
print_error("You should run daemon as root");
v3 = 1;
}
else if ( argc == 1 )
{
print_help();
v3 = 0;
}
else
{
v3 = 0;
if ( argc == 2 )
{
v5 = argv[1];
v3 = strcmp(v5, "--help");
if ( v3 )
{
v3 = strcmp(v5, "--stop");
if ( v3 )
{
v3 = strcmp(v5, "--start");
if ( v3 )
{
v3 = 0;
}
else if ( (unsigned int)get_pid() )
{
print_error("Daemon is already running.");
}
else
{
unlink(socket_file);
v7 = (unsigned int)daemon(1, 1);
set_pid(v7);
if ( (_DWORD)v7 != -1 )
authdaemon();
puts("Fork failed");
v3 = 1;
}
}
else
{
v6 = get_pid();
if ( v6 )
{
kill(v6, 15);
puts("stop");
}
unset_pid();
unlink(socket_file);
}
}
else
{
print_help();
}
}
}
return v3;
}

canonical_decompiled_code:
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v3; // ebp
const char *v5; // rbx
__pid_t v6; // eax
__int64 v7; // rbx

if ( getuid() )
{
func15("You should run daemon as root");
v3 = 1;
}
else if ( argc == 1 )
{
func14();
v3 = 0;
}
else
{
v3 = 0;
if ( argc == 2 )
{
v5 = argv[1];
v3 = strcmp(v5, "--help");
if ( v3 )
{
v3 = strcmp(v5, "--stop");
if ( v3 )
{
v3 = strcmp(v5, "--start");
if ( v3 )
{
v3 = 0;
}
else if ( (unsigned int)func8() )
{
func15("Daemon is already running.");
}
else
{
unlink(socket_file);
v7 = (unsigned int)daemon(1, 1);
func7(v7);
if ( (_DWORD)v7 != -1 )
func13();
puts("Fork failed");
v3 = 1;
}
}
else
{
v6 = func8();
if ( v6 )
{
kill(v6, 15);
puts("stop");
}
func9();
unlink(socket_file);
}
}
else
{
func14();
}
}
}
return v3;
}

original_code:
int main(int argc, char* argv[]) {
 if(getuid() != 0){
  print_error("You should run daemon as root");
  return 1;
 }
 if(argc==1){
  print_help();
  return 0;
 }
 if(argc==2) {
  if( strcmp(argv[1],"--help") == 0 ) {
   print_help();
   return 0;
  }
  else if( strcmp(argv[1],"--stop") == 0) {
   unsigned int pid = get_pid();
   if(pid>0){
    kill(pid, 15);
    printf("%s\n", "stop");
   }
   unset_pid();
   unlink(socket_file);
  }
  else if( strcmp(argv[1],"--start") == 0 ) {
   unsigned int pid;
   if( get_pid() != 0) {
    print_error("Daemon is already running.");
    return 0;
   }
   unlink(socket_file);
   pid = daemon(1,1);
   set_pid(pid);
   if(pid == -1) {
    printf("%s\n","Fork failed" );
    return 1;
   }
   authdaemon();
   unset_pid();
   }
 }
 return 0;
}

canonical_original_code:
int main(int argc, char *argv[]) {
 if(getuid() != 0){
  print_error("You should run daemon as root");
  return 1;
 }
 if(argc==1){
  print_help();
  return 0;
 }
 if(argc==2) {
  if( strcmp(argv[1],"--help") == 0 ) {
   print_help();
   return 0;
  }
  else if( strcmp(argv[1],"--stop") == 0) {
   unsigned int pid = get_pid();
   if(pid>0){
    kill(pid, 15);
    printf("%s\n", "stop");
   }
   unset_pid();
   unlink(socket_file);
  }
  else if( strcmp(argv[1],"--start") == 0 ) {
   unsigned int pid;
   if( get_pid() != 0) {
    print_error("Daemon is already running.");
    return 0;
   }
   unlink(socket_file);
   pid = daemon(1,1);
   set_pid(pid);
   if(pid == -1) {
    printf("%s\n","Fork failed" );
    return 1;
   }
   authdaemon();
   unset_pid();
   }
 }
 return 0;
}

variable_types: argc int

variable_types:
argv
char *[]

variable_types:
pid
unsigned int


decompiled_code:
void maybe_init_rates()
{
if ( !rates )
rates = create_hash(&compare_pair, &hash_pair);
}

canonical_decompiled_code:
void func0()
{
if ( !rates )
rates = create_hash(&compare_pair, &hash_pair);
}

original_code:
static void
maybe_init_rates() {
  if ( rates == ((void *)0) ) {
    rates = create_hash( compare_pair, hash_pair );
  }
}


reduce

original_code:
Money *
reduce( Expression *source, Currency to ) {
  return source->reduce( source, to );
}

canonical_original_code:
struct Money *reduce(struct Expression *source, enum Currency to) {
  return source->reduce( source, to );
}

variable_types: struct Expression { void *value; struct Money *(*reduce)(struct Expression *exp, enum Currency { USD=0, CHF=1 } to); } *

variable_types:
to
enum Currency { USD=0, CHF=1 }

return_type: struct Money {  } *

user_defined_types: struct Expression { void *value; struct Money *(*reduce)(struct Expression *exp, enum Currency to); }


rate

decompiled_code:
__int64 __fastcall rate(unsigned int a1, unsigned int a2)
{
void *v2; // rbp
__int64 v3; // rax
unsigned int v4; // ebx

maybe_init_rates();
if ( a1 == a2 )
return 1LL;
v2 = (void *)create_pair(a1, a2);
v3 = lookup_hash_entry(rates, v2);
v4 = v3;
if ( !v3 )
_assert_fail("rate != NULL", "bank.c", 0x23u, "rate");
free(v2);
return v4;
}

canonical_decompiled_code:
__int64 __fastcall func2(unsigned int a1, unsigned int a2)
{
void *v2; // rbp
__int64 v3; // rax
unsigned int v4; // ebx

func0();
if ( a1 == a2 )
return 1LL;
v2 = (void *)create_pair(a1, a2);
v3 = lookup_hash_entry(rates, v2);
v4 = v3;
if ( !v3 )
_assert_fail("rate != NULL", "bank.c", 0x23u, "rate");
free(v2);
return v4;
}

original_code:
unsigned int
rate( Currency from, Currency to ) {
  maybe_init_rates();
  if ( from == to ) {
    return 1;
  }
  Pair *pair = create_pair( from, to );
  void *rate = lookup_hash_entry( rates, pair );
  ((void) sizeof ((rate != ((void *)0)) ? 1 : 0), __extension__ ({ if (rate != ((void *)0)) ; else __assert_fail ("rate != NULL", "bank.c", 35, __extension__ __PRETTY_FUNCTION__); }));
  free( pair );
  return ( unsigned int ) ( uintptr_t ) rate;
}

canonical_original_code:
unsigned int rate(enum Currency from, enum Currency to) {
  maybe_init_rates();
  if ( from == to ) {
    return 1;
  }
  struct Pair *pair = create_pair( from, to );
  void *rate = lookup_hash_entry( rates, pair );
  ((void) sizeof ((rate != ((void *)0)) ? 1 : 0), __extension__ ({ if (rate != ((void *)0)) ; else __assert_fail ("rate != NULL", "bank.c", 35, __extension__ __PRETTY_FUNCTION__); }));
  free( pair );
  return ( unsigned int ) ( unsigned long ) rate;
}

variable_types:
from
enum Currency { USD=0, CHF=1 }

variable_types: struct Pair { enum Currency { USD=0, CHF=1 } from; enum Currency { USD=0, CHF=1 } to; } *

variable_types:
rate
void *

return_type: unsigned int

user_defined_types: struct Pair { enum Currency from; enum Currency to; }


decompiled_code:
__int64 __fastcall add_rate(unsigned int a1, unsigned int a2, unsigned int a3)
{
__int64 v4; // rax

maybe_init_rates();
v4 = create_pair(a1, a2);
return insert_hash_entry(rates, v4, a3);
}

canonical_decompiled_code:
__int64 __fastcall func3(unsigned int a1, unsigned int a2, unsigned int a3)
{
__int64 v4; // rax

func0();
v4 = create_pair(a1, a2);
return insert_hash_entry(rates, v4, a3);
}

original_code:
void
add_rate( Currency from, Currency to, unsigned int rate ) {
  maybe_init_rates();
  Pair *pair = create_pair( from, to );
  insert_hash_entry( rates, pair, ( void * ) ( uintptr_t ) rate );
}

canonical_original_code:
void add_rate(enum Currency from, enum Currency to, unsigned int rate) {
  maybe_init_rates();
  struct Pair *pair = create_pair( from, to );
  insert_hash_entry( rates, pair, ( void * ) ( unsigned long ) rate );
}

variable_types:
rate
unsigned int


decompiled_code:
__int64 delete_all_rates()
{
__int64 result; // rax

if ( rates )
{
result = delete_hash();
rates = 0LL;
}
return result;
}

canonical_decompiled_code:
__int64 func4()
{
__int64 result; // rax

if ( rates )
{
result = delete_hash();
rates = 0LL;
}
return result;
}

original_code:
void
delete_all_rates() {
  if ( rates != ((void *)0) ) {
    delete_hash(rates);
    rates = ((void *)0);
  }
}


decompiled_code:
bool __fastcall compare_atom(__int64 a1, __int64 a2)
{
return a2 == a1;
}

canonical_decompiled_code:
bool __fastcall func0(__int64 a1, __int64 a2)
{
return a2 == a1;
}

original_code:
_Bool
compare_atom( const void *x, const void *y ) {
  return x == y;
}

canonical_original_code:
_Bool compare_atom(void *x, void *y) {
  return x == y;
}

variable_types:
x
void *

variable_types:
y
void *


decompiled_code:
unsigned __int64 __fastcall hash_atom(unsigned __int64 a1)
{
return a1 >> 2;
}

canonical_decompiled_code:
unsigned __int64 __fastcall func1(unsigned __int64 a1)
{
return a1 >> 2;
}

original_code:
unsigned int
hash_atom( const void *key ) {
  return ( unsigned int ) ( ( unsigned long ) key >> 2 );
}

canonical_original_code:
unsigned int hash_atom(void *key) {
  return ( unsigned int ) ( ( unsigned long ) key >> 2 );
}

variable_types:
key
void *


decompiled_code:
__int64 __fastcall get_bucket_index(__int64 a1, __int64 a2)
{
if ( !a1 )
_assert_fail("table != NULL", "hash_table.c", 0x49u, "get_bucket_index");
if ( !a2 )
_assert_fail("key != NULL", "hash_table.c", 0x4Au, "get_bucket_index");
return (*(unsigned int (__fastcall **)(__int64))(a1 + 16))(a2) % *(_DWORD *)a1;
}

canonical_decompiled_code:
__int64 __fastcall func2(__int64 a1, __int64 a2)
{
if ( !a1 )
_assert_fail("table != NULL", "hash_table.c", 0x49u, "get_bucket_index");
if ( !a2 )
_assert_fail("key != NULL", "hash_table.c", 0x4Au, "get_bucket_index");
return (*(unsigned int (__fastcall **)(__int64))(a1 + 16))(a2) % *(_DWORD *)a1;
}

original_code:
static unsigned int
get_bucket_index( const hash_table *table, const void *key ) {
  ((void) sizeof ((table != ((void *)0)) ? 1 : 0), __extension__ ({ if (table != ((void *)0)) ; else __assert_fail ("table != NULL", "hash_table.c", 73, __extension__ __PRETTY_FUNCTION__); }));
  ((void) sizeof ((key != ((void *)0)) ? 1 : 0), __extension__ ({ if (key != ((void *)0)) ; else __assert_fail ("key != NULL", "hash_table.c", 74, __extension__ __PRETTY_FUNCTION__); }));
  return ( *table->hash )( key ) % table->number_of_buckets;
}

canonical_original_code:
static unsigned int get_bucket_index(struct hash_table *table, void *key) {
  ((void) sizeof ((table != ((void *)0)) ? 1 : 0), __extension__ ({ if (table != ((void *)0)) ; else __assert_fail ("table != NULL", "hash_table.c", 73, __extension__ __PRETTY_FUNCTION__); }));
  ((void) sizeof ((key != ((void *)0)) ? 1 : 0), __extension__ ({ if (key != ((void *)0)) ; else __assert_fail ("key != NULL", "hash_table.c", 74, __extension__ __PRETTY_FUNCTION__); }));
  return ( *table->hash )( key ) % table->number_of_buckets;
}

variable_types: struct hash_table { unsigned int number_of_buckets; _Bool (*compare)(void *x, void *y); unsigned int (*hash)(void *key); unsigned int length; struct list_element { struct list_element *next; void *data; } **buckets; struct list_element *nonempty_bucket_index; } *

user_defined_types: struct hash_table { unsigned int number_of_buckets; _Bool (*compare)(void *x, void *y); unsigned int (*hash)(void *key); unsigned int length; struct list_element **buckets; struct list_element *nonempty_bucket_index; }


decompiled_code:
__int64 __fastcall foreach_hash(__int64 a1, __int64 (__fastcall *a2)(_QWORD, _QWORD, __int64), __int64 a3)
{
unsigned int i; // er13
__int64 result; // rax
_QWORD *j; // rbx
_QWORD *v7; // rax

if ( !a1 )
_assert_fail("table != NULL", "hash_table.c", 0xB0u, "foreach_hash");
for ( i = 0; *(_DWORD *)a1 > i; ++i )
{
result = i;
for ( j = *(_QWORD **)(*(_QWORD *)(a1 + 32) + 8LL * i); j; result = a2(*v7, v7[1], a3) )
{
v7 = (_QWORD *)j[1];
j = (_QWORD *)*j;
}
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func4(__int64 a1, __int64 (__fastcall *a2)(_QWORD, _QWORD, __int64), __int64 a3)
{
unsigned int i; // er13
__int64 result; // rax
_QWORD *j; // rbx
_QWORD *v7; // rax

if ( !a1 )
_assert_fail("table != NULL", "hash_table.c", 0xB0u, "foreach_hash");
for ( i = 0; *(_DWORD *)a1 > i; ++i )
{
result = i;
for ( j = *(_QWORD **)(*(_QWORD *)(a1 + 32) + 8LL * i); j; result = a2(*v7, v7[1], a3) )
{
v7 = (_QWORD *)j[1];
j = (_QWORD *)*j;
}
}
return result;
}

original_code:
void
foreach_hash( hash_table *table, void function( void *key, void *value, void *user_data ), void *user_data ) {
  ((void) sizeof ((table != ((void *)0)) ? 1 : 0), __extension__ ({ if (table != ((void *)0)) ; else __assert_fail ("table != NULL", "hash_table.c", 176, __extension__ __PRETTY_FUNCTION__); }));
  unsigned int i;
  for ( i = 0; i < table->number_of_buckets; i++ ) {
    list_element *e = ((void *)0);
    for ( e = table->buckets[ i ]; e; ) {
      hash_entry *he = e->data;
      e = e->next;
      function( he->key, he->value, user_data );
    }
  }
}

canonical_original_code:
void foreach_hash(struct hash_table *table, void function(void *key, void *value, void *user_data), void *user_data) {
  ((void) sizeof ((table != ((void *)0)) ? 1 : 0), __extension__ ({ if (table != ((void *)0)) ; else __assert_fail ("table != NULL", "hash_table.c", 176, __extension__ __PRETTY_FUNCTION__); }));
  unsigned int i;
  for ( i = 0; i < table->number_of_buckets; i++ ) {
    struct list_element *e = ((void *)0);
    for ( e = table->buckets[ i ]; e; ) {
      struct hash_entry *he = e->data;
      e = e->next;
      function( he->key, he->value, user_data );
    }
  }
}

variable_types: void (void *key, void *value, void *user_data)

variable_types:
i
unsigned int

variable_types: struct list_element { struct list_element *next; void *data; } *

variable_types: struct hash_entry { void *key; void *value; } *


decompiled_code:
__int64 __fastcall iterate_hash_next(_QWORD *a1)
{
__int64 result; // rax
_QWORD *v2; // rax

if ( !a1 )
_assert_fail("iter != NULL", "hash_table.c", 0xD2u, "iterate_hash_next");
result = a1[1];
if ( result )
{
while ( 1 )
{
v2 = (_QWORD *)a1[3];
if ( v2 )
break;
result = a1[2];
if ( !result )
return result;
a1[1] = result;
a1[2] = *(_QWORD *)result;
a1[3] = *(_QWORD *)(*a1 + 8LL * *(int *)(result + 8));
}
a1[3] = *v2;
result = v2[1];
}
return result;
}

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

if ( !a1 )
_assert_fail("iter != NULL", "hash_table.c", 0xD2u, "iterate_hash_next");
result = a1[1];
if ( result )
{
while ( 1 )
{
v2 = (_QWORD *)a1[3];
if ( v2 )
break;
result = a1[2];
if ( !result )
return result;
a1[1] = result;
a1[2] = *(_QWORD *)result;
a1[3] = *(_QWORD *)(*a1 + 8LL * *(int *)(result + 8));
}
a1[3] = *v2;
result = v2[1];
}
return result;
}

original_code:
hash_entry *
iterate_hash_next( hash_iterator *iter ) {
  ((void) sizeof ((iter != ((void *)0)) ? 1 : 0), __extension__ ({ if (iter != ((void *)0)) ; else __assert_fail ("iter != NULL", "hash_table.c", 210, __extension__ __PRETTY_FUNCTION__); }));
  for ( ;; ) {
    if ( iter->bucket_index == ((void *)0) ) {
      return ((void *)0);
    }
    list_element *e = iter->element;
    if ( e == ((void *)0) ) {
      if ( iter->next_bucket_index != ((void *)0) ) {
        iter->bucket_index = iter->next_bucket_index;
        iter->next_bucket_index = iter->next_bucket_index->next;
        iter->element = iter->buckets[ ( int ) ( unsigned long ) iter->bucket_index->data ];
      }
      else {
        return ((void *)0);
      }
    }
    else {
      iter->element = e->next;
      return e->data;
    }
  }
}

canonical_original_code:
struct hash_entry *iterate_hash_next(struct hash_iterator *iter) {
  ((void) sizeof ((iter != ((void *)0)) ? 1 : 0), __extension__ ({ if (iter != ((void *)0)) ; else __assert_fail ("iter != NULL", "hash_table.c", 210, __extension__ __PRETTY_FUNCTION__); }));
  for ( ;; ) {
    if ( iter->bucket_index == ((void *)0) ) {
      return ((void *)0);
    }
    struct list_element *e = iter->element;
    if ( e == ((void *)0) ) {
      if ( iter->next_bucket_index != ((void *)0) ) {
        iter->bucket_index = iter->next_bucket_index;
        iter->next_bucket_index = iter->next_bucket_index->next;
        iter->element = iter->buckets[ ( int ) ( unsigned long ) iter->bucket_index->data ];
      }
      else {
        return ((void *)0);
      }
    }
    else {
      iter->element = e->next;
      return e->data;
    }
  }
}

variable_types: struct hash_iterator { struct list_element { struct list_element *next; void *data; } **buckets; struct list_element *bucket_index; struct list_element *next_bucket_index; struct list_element *element; } *

return_type: struct hash_entry { void *key; void *value; } *

user_defined_types: struct hash_iterator { struct list_element **buckets; struct list_element *bucket_index; struct list_element *next_bucket_index; struct list_element *element; }


decompiled_code:
void __fastcall delete_hash(void *ptr)
{
unsigned int v1; // ebp
_QWORD *v2; // rbx
_QWORD *v3; // rax

if ( !ptr )
_assert_fail("table != NULL", "hash_table.c", 0xEEu, "delete_hash");
if ( *((_DWORD *)ptr + 6) && *(_DWORD *)ptr )
{
v1 = 0;
do
{
v2 = *(_QWORD **)(*((_QWORD *)ptr + 4) + 8LL * v1);
while ( v2 )
{
v3 = v2;
v2 = (_QWORD *)*v2;
free((void *)v3[1]);
}
if ( !(unsigned __int8)delete_list(*(_QWORD *)(*((_QWORD *)ptr + 4) + 8LL * v1)) )
_assert_fail("list_deleted == true", "hash_table.c", 0xFCu, "delete_hash");
++v1;
}
while ( *(_DWORD *)ptr > v1 );
}
free(*((void **)ptr + 4));
if ( !(unsigned __int8)delete_list(*((_QWORD *)ptr + 5)) )
_assert_fail("list_deleted == true", "hash_table.c", 0x102u, "delete_hash");
free(ptr);
}

canonical_decompiled_code:
void __fastcall func7(void *ptr)
{
unsigned int v1; // ebp
_QWORD *v2; // rbx
_QWORD *v3; // rax

if ( !ptr )
_assert_fail("table != NULL", "hash_table.c", 0xEEu, "delete_hash");
if ( *((_DWORD *)ptr + 6) && *(_DWORD *)ptr )
{
v1 = 0;
do
{
v2 = *(_QWORD **)(*((_QWORD *)ptr + 4) + 8LL * v1);
while ( v2 )
{
v3 = v2;
v2 = (_QWORD *)*v2;
free((void *)v3[1]);
}
if ( !(unsigned __int8)delete_list(*(_QWORD *)(*((_QWORD *)ptr + 4) + 8LL * v1)) )
_assert_fail("list_deleted == true", "hash_table.c", 0xFCu, "delete_hash");
++v1;
}
while ( *(_DWORD *)ptr > v1 );
}
free(*((void **)ptr + 4));
if ( !(unsigned __int8)delete_list(*((_QWORD *)ptr + 5)) )
_assert_fail("list_deleted == true", "hash_table.c", 0x102u, "delete_hash");
free(ptr);
}

original_code:
void
delete_hash( hash_table *table ) {
  ((void) sizeof ((table != ((void *)0)) ? 1 : 0), __extension__ ({ if (table != ((void *)0)) ; else __assert_fail ("table != NULL", "hash_table.c", 238, __extension__ __PRETTY_FUNCTION__); }));
  _Bool list_deleted = 0;
  if ( table->length > 0 ) {
    unsigned int i;
    for ( i = 0; i < table->number_of_buckets; i++ ) {
      list_element *e = ((void *)0);
      for ( e = table->buckets[ i ]; e != ((void *)0); ) {
        list_element *delete_me = e;
        e = e->next;
        free( delete_me->data );
      }
      list_deleted = delete_list( table->buckets[ i ] );
      ((void) sizeof ((list_deleted == 1) ? 1 : 0), __extension__ ({ if (list_deleted == 1) ; else __assert_fail ("list_deleted == true", "hash_table.c", 252, __extension__ __PRETTY_FUNCTION__); }));
    }
  }
  free( table->buckets );
  list_deleted = delete_list( table->nonempty_bucket_index );
  ((void) sizeof ((list_deleted == 1) ? 1 : 0), __extension__ ({ if (list_deleted == 1) ; else __assert_fail ("list_deleted == true", "hash_table.c", 258, __extension__ __PRETTY_FUNCTION__); }));
  free( table );
}

canonical_original_code:
void delete_hash(struct hash_table *table) {
  ((void) sizeof ((table != ((void *)0)) ? 1 : 0), __extension__ ({ if (table != ((void *)0)) ; else __assert_fail ("table != NULL", "hash_table.c", 238, __extension__ __PRETTY_FUNCTION__); }));
  _Bool list_deleted = 0;
  if ( table->length > 0 ) {
    unsigned int i;
    for ( i = 0; i < table->number_of_buckets; i++ ) {
      struct list_element *e = ((void *)0);
      for ( e = table->buckets[ i ]; e != ((void *)0); ) {
        struct list_element *delete_me = e;
        e = e->next;
        free( delete_me->data );
      }
      list_deleted = delete_list( table->buckets[ i ] );
      ((void) sizeof ((list_deleted == 1) ? 1 : 0), __extension__ ({ if (list_deleted == 1) ; else __assert_fail ("list_deleted == true", "hash_table.c", 252, __extension__ __PRETTY_FUNCTION__); }));
    }
  }
  free( table->buckets );
  list_deleted = delete_list( table->nonempty_bucket_index );
  ((void) sizeof ((list_deleted == 1) ? 1 : 0), __extension__ ({ if (list_deleted == 1) ; else __assert_fail ("list_deleted == true", "hash_table.c", 258, __extension__ __PRETTY_FUNCTION__); }));
  free( table );
}

user_defined_types: struct list_element { struct list_element *next; void *data; }


plus

decompiled_code:
__int64 plus()
{
return create_sum();
}

canonical_decompiled_code:
__int64 func0()
{
return create_sum();
}

original_code:
Expression *
plus( const Expression *augend, const Expression *addend ) {
  return create_sum( augend, addend );
}

canonical_original_code:
struct Expression *plus(struct Expression *augend, struct Expression *addend) {
  return create_sum( augend, addend );
}

variable_types:
augend
struct Expression *

variable_types:
addend
struct Expression *

return_type: struct Expression { void *value; struct Money {  } *(*reduce)(struct Expression *exp, enum Currency { USD=0, CHF=1 } to); } *


multiply

decompiled_code:
__int64 multiply()
{
return create_mul();
}

canonical_decompiled_code:
__int64 func1()
{
return create_mul();
}

original_code:
Expression *
multiply( const Expression *multiplicand, unsigned int multiplier ) {
  return create_mul( multiplicand, multiplier );
}

canonical_original_code:
struct Expression *multiply(struct Expression *multiplicand, unsigned int multiplier) {
  return create_mul( multiplicand, multiplier );
}

variable_types:
multiplicand
struct Expression *

variable_types:
multiplier
unsigned int


decompiled_code:
__int64 __fastcall currency_of(__int64 a1)
{
return *(unsigned int *)(a1 + 4);
}

canonical_decompiled_code:
__int64 __fastcall func2(__int64 a1)
{
return *(unsigned int *)(a1 + 4);
}

original_code:
Currency
currency_of( const Money *money ) {
  return ( ( MoneyProtected * ) money )->currency;
}

canonical_original_code:
enum Currency currency_of(struct Money *money) {
  return ( ( struct MoneyProtected * ) money )->currency;
}

variable_types:
money
struct Money {  } *

return_type: enum Currency { USD=0, CHF=1 }

user_defined_types: struct MoneyProtected { unsigned int amount; enum Currency currency; }


equal

decompiled_code:
_BOOL8 __fastcall equal(_DWORD *a1, _DWORD *a2)
{
bool v2; // al

v2 = 0;
if ( *a1 == *a2 )
v2 = a1[1] == a2[1];
return v2;
}

canonical_decompiled_code:
_BOOL8 __fastcall func3(_DWORD *a1, _DWORD *a2)
{
bool v2; // al

v2 = 0;
if ( *a1 == *a2 )
v2 = a1[1] == a2[1];
return v2;
}

original_code:
_Bool
equal( const void *money, const void *other ) {
  MoneyProtected *moneyp = ( MoneyProtected * ) money;
  MoneyProtected *otherp = ( MoneyProtected * ) other;
  return moneyp->amount == otherp->amount && moneyp->currency == otherp->currency;
}

canonical_original_code:
_Bool equal(void *money, void *other) {
  struct MoneyProtected *moneyp = ( MoneyProtected * ) money;
  struct MoneyProtected *otherp = ( MoneyProtected * ) other;
  return moneyp->amount == otherp->amount && moneyp->currency == otherp->currency;
}

variable_types:
money
void *

variable_types:
other
void *

variable_types: struct MoneyProtected { unsigned int amount; enum Currency { USD=0, CHF=1 } currency; } *


decompiled_code:
__int64 __fastcall money_from(__int64 a1)
{
return *(_QWORD *)a1;
}

canonical_decompiled_code:
__int64 __fastcall func4(__int64 a1)
{
return *(_QWORD *)a1;
}

original_code:
Money *
money_from( const Expression *exp ) {
  return ( Money * ) exp->value;
}

canonical_original_code:
struct Money *money_from(struct Expression *exp) {
  return ( struct Money * ) exp->value;
}

variable_types: struct Expression { void *value; struct Money *(*reduce)(struct Expression *exp, enum Currency { USD=0, CHF=1 } to); } *


decompiled_code:
void __fastcall free_expression(void *ptr)
{
free(*(void **)ptr);
free(ptr);
}

canonical_decompiled_code:
void __fastcall func5(void *ptr)
{
free(*(void **)ptr);
free(ptr);
}

original_code:
void
free_expression( Expression *exp ) {
  free( exp->value );
  free( exp );
}

canonical_original_code:
void free_expression(struct Expression *exp) {
  free( exp->value );
  free( exp );
}

variable_types: struct Expression { void *value; struct Money {  } *(*reduce)(struct Expression *exp, enum Currency { USD=0, CHF=1 } to); } *


decompiled_code:
void __fastcall free_money(void *a1)
{
free(a1);
}

canonical_decompiled_code:
void __fastcall func6(void *a1)
{
free(a1);
}

original_code:
void
free_money( Money *money ) {
  free( ( MoneyProtected * ) money );
}

canonical_original_code:
void free_money(struct Money *money) {
  free( ( struct MoneyProtected * ) money );
}


decompiled_code:
__int64 __fastcall create_list(_QWORD *a1)
{
if ( !a1 )
_assert_fail("list != NULL", "linked_list.c", 0x1Cu, "create_list");
*a1 = 0LL;
return 1LL;
}

canonical_decompiled_code:
__int64 __fastcall func0(_QWORD *a1)
{
if ( !a1 )
_assert_fail("list != NULL", "linked_list.c", 0x1Cu, "create_list");
*a1 = 0LL;
return 1LL;
}

original_code:
_Bool
create_list( list_element **list ) {
  ((void) sizeof ((list != ((void *)0)) ? 1 : 0), __extension__ ({ if (list != ((void *)0)) ; else __assert_fail ("list != NULL", "linked_list.c", 28, __extension__ __PRETTY_FUNCTION__); }));
  *list = ((void *)0);
  return 1;
}

canonical_original_code:
_Bool create_list(struct list_element **list) {
  ((void) sizeof ((list != ((void *)0)) ? 1 : 0), __extension__ ({ if (list != ((void *)0)) ; else __assert_fail ("list != NULL", "linked_list.c", 28, __extension__ __PRETTY_FUNCTION__); }));
  *list = ((void *)0);
  return 1;
}

variable_types: struct list_element { struct list_element *next; void *data; } **


decompiled_code:
__int64 __fastcall insert_in_front(__int64 *a1, __int64 a2)
{
__int64 v2; // r12
_QWORD *v3; // rax

if ( !a1 )
_assert_fail("head != NULL", "linked_list.c", 0x25u, "insert_in_front");
v2 = *a1;
v3 = malloc(0x10uLL);
v3[1] = a2;
*a1 = (__int64)v3;
*v3 = v2;
return 1LL;
}

canonical_decompiled_code:
__int64 __fastcall func1(__int64 *a1, __int64 a2)
{
__int64 v2; // r12
_QWORD *v3; // rax

if ( !a1 )
_assert_fail("head != NULL", "linked_list.c", 0x25u, "insert_in_front");
v2 = *a1;
v3 = malloc(0x10uLL);
v3[1] = a2;
*a1 = (__int64)v3;
*v3 = v2;
return 1LL;
}

original_code:
_Bool
insert_in_front( list_element **head, void *data ) {
  ((void) sizeof ((head != ((void *)0)) ? 1 : 0), __extension__ ({ if (head != ((void *)0)) ; else __assert_fail ("head != NULL", "linked_list.c", 37, __extension__ __PRETTY_FUNCTION__); }));
  list_element *old_head = *head;
  list_element *new_head = malloc( sizeof( list_element ) );
  new_head->data = data;
  *head = new_head;
  ( *head )->next = old_head;
  return 1;
}

canonical_original_code:
_Bool insert_in_front(struct list_element **head, void *data) {
  ((void) sizeof ((head != ((void *)0)) ? 1 : 0), __extension__ ({ if (head != ((void *)0)) ; else __assert_fail ("head != NULL", "linked_list.c", 37, __extension__ __PRETTY_FUNCTION__); }));
  struct list_element *old_head = *head;
  struct list_element *new_head = malloc( sizeof( list_element ) );
  new_head->data = data;
  *head = new_head;
  ( *head )->next = old_head;
  return 1;
}

variable_types:
data
void *


decompiled_code:
__int64 __fastcall insert_before(_QWORD *a1, __int64 a2, __int64 a3)
{
_QWORD *v4; // rbx
_QWORD *v5; // rbp
_QWORD *v6; // rax

if ( !a1 )
_assert_fail("head != NULL", "linked_list.c", 0x33u, "insert_before");
v4 = (_QWORD *)*a1;
while ( 1 )
{
v5 = v4;
v4 = (_QWORD *)*v4;
if ( !v4 )
break;
if ( v4[1] == a2 )
{
v6 = malloc(0x10uLL);
*v6 = v4;
v6[1] = a3;
*v5 = v6;
return 1LL;
}
}
return 0LL;
}

canonical_decompiled_code:
__int64 __fastcall func2(_QWORD *a1, __int64 a2, __int64 a3)
{
_QWORD *v4; // rbx
_QWORD *v5; // rbp
_QWORD *v6; // rax

if ( !a1 )
_assert_fail("head != NULL", "linked_list.c", 0x33u, "insert_before");
v4 = (_QWORD *)*a1;
while ( 1 )
{
v5 = v4;
v4 = (_QWORD *)*v4;
if ( !v4 )
break;
if ( v4[1] == a2 )
{
v6 = malloc(0x10uLL);
*v6 = v4;
v6[1] = a3;
*v5 = v6;
return 1LL;
}
}
return 0LL;
}

original_code:
_Bool
insert_before( list_element **head, const void *sibling, void *data ) {
  ((void) sizeof ((head != ((void *)0)) ? 1 : 0), __extension__ ({ if (head != ((void *)0)) ; else __assert_fail ("head != NULL", "linked_list.c", 51, __extension__ __PRETTY_FUNCTION__); }));
  list_element *e;
  list_element *new_element;
  for ( e = *head; e->next != ((void *)0); e = e->next ) {
    if ( e->next->data == sibling ) {
      new_element = malloc( sizeof( list_element ) );
      new_element->next = e->next;
      new_element->data = data;
      e->next = new_element;
      return 1;
    }
  }
  return 0;
}

canonical_original_code:
_Bool insert_before(struct list_element **head, void *sibling, void *data) {
  ((void) sizeof ((head != ((void *)0)) ? 1 : 0), __extension__ ({ if (head != ((void *)0)) ; else __assert_fail ("head != NULL", "linked_list.c", 51, __extension__ __PRETTY_FUNCTION__); }));
  struct list_element *e;
  struct list_element *new_element;
  for ( e = *head; e->next != ((void *)0); e = e->next ) {
    if ( e->next->data == sibling ) {
      new_element = malloc( sizeof( list_element ) );
      new_element->next = e->next;
      new_element->data = data;
      e->next = new_element;
      return 1;
    }
  }
  return 0;
}

variable_types:
sibling
void *


decompiled_code:
__int64 __fastcall append_to_tail(_QWORD **a1, __int64 a2)
{
_QWORD *v2; // rcx
_QWORD *v3; // rax
_QWORD *v4; // rdx

if ( !a1 )
_assert_fail("head != NULL", "linked_list.c", 0x48u, "append_to_tail");
v2 = malloc(0x10uLL);
v2[1] = a2;
*v2 = 0LL;
v3 = *a1;
if ( *a1 )
{
do
{
v4 = v3;
v3 = (_QWORD *)*v3;
}
while ( v3 );
*v4 = v2;
}
else
{
*a1 = v2;
}
return 1LL;
}

canonical_decompiled_code:
__int64 __fastcall func3(_QWORD **a1, __int64 a2)
{
_QWORD *v2; // rcx
_QWORD *v3; // rax
_QWORD *v4; // rdx

if ( !a1 )
_assert_fail("head != NULL", "linked_list.c", 0x48u, "append_to_tail");
v2 = malloc(0x10uLL);
v2[1] = a2;
*v2 = 0LL;
v3 = *a1;
if ( *a1 )
{
do
{
v4 = v3;
v3 = (_QWORD *)*v3;
}
while ( v3 );
*v4 = v2;
}
else
{
*a1 = v2;
}
return 1LL;
}

original_code:
_Bool
append_to_tail( list_element **head, void *data ) {
  ((void) sizeof ((head != ((void *)0)) ? 1 : 0), __extension__ ({ if (head != ((void *)0)) ; else __assert_fail ("head != NULL", "linked_list.c", 72, __extension__ __PRETTY_FUNCTION__); }));
  list_element *e;
  list_element *new_tail = malloc( sizeof( list_element ) );
  new_tail->data = data;
  new_tail->next = ((void *)0);
  if ( *head == ((void *)0) ) {
    *head = new_tail;
    return 1;
  }
  for ( e = *head; e->next != ((void *)0); e = e->next );
  e->next = new_tail;
  return 1;
}

canonical_original_code:
_Bool append_to_tail(struct list_element **head, void *data) {
  ((void) sizeof ((head != ((void *)0)) ? 1 : 0), __extension__ ({ if (head != ((void *)0)) ; else __assert_fail ("head != NULL", "linked_list.c", 72, __extension__ __PRETTY_FUNCTION__); }));
  struct list_element *e;
  struct list_element *new_tail = malloc( sizeof( list_element ) );
  new_tail->data = data;
  new_tail->next = ((void *)0);
  if ( *head == ((void *)0) ) {
    *head = new_tail;
    return 1;
  }
  for ( e = *head; e->next != ((void *)0); e = e->next );
  e->next = new_tail;
  return 1;
}


decompiled_code:
__int64 __fastcall list_length_of(_QWORD **a1)
{
_QWORD *v1; // rax
unsigned int v2; // edx

if ( !a1 )
return 0;
v1 = *a1;
if ( !*a1 )
return 1;
v2 = 1;
do
{
v1 = (_QWORD *)*v1;
++v2;
}
while ( v1 );
return v2;
}

canonical_decompiled_code:
__int64 __fastcall func4(_QWORD **a1)
{
_QWORD *v1; // rax
unsigned int v2; // edx

if ( !a1 )
return 0;
v1 = *a1;
if ( !*a1 )
return 1;
v2 = 1;
do
{
v1 = (_QWORD *)*v1;
++v2;
}
while ( v1 );
return v2;
}

original_code:
unsigned int
list_length_of( const list_element *head ) {
  if ( head == ((void *)0) ) {
    return 0;
  }
  unsigned int length = 1;
  for ( list_element *e = head->next; e; e = e->next, length++ );
  return length;
}

canonical_original_code:
unsigned int list_length_of(struct list_element *head) {
  if ( head == ((void *)0) ) {
    return 0;
  }
  unsigned int length = 1;
  for ( struct list_element *e = head->next; e; e = e->next, length++ );
  return length;
}

variable_types:
length
unsigned int


decompiled_code:
__int64 __fastcall delete_element(_QWORD **a1, __int64 a2)
{
_QWORD *v2; // rax
_QWORD *v3; // rdi
__int64 result; // rax

if ( !a1 )
_assert_fail("head != NULL", "linked_list.c", 0x68u, "delete_element");
v2 = a1;
v3 = *a1;
if ( v3[1] == a2 )
{
LABEL_5:
*v2 = *v3;
free(v3);
result = 1LL;
}
else
{
while ( 1 )
{
v2 = v3;
v3 = (_QWORD *)*v3;
if ( !v3 )
break;
if ( v3[1] == a2 )
goto LABEL_5;
}
result = 0LL;
}
return result;
}

canonical_decompiled_code:
__int64 __fastcall func5(_QWORD **a1, __int64 a2)
{
_QWORD *v2; // rax
_QWORD *v3; // rdi
__int64 result; // rax

if ( !a1 )
_assert_fail("head != NULL", "linked_list.c", 0x68u, "delete_element");
v2 = a1;
v3 = *a1;
if ( v3[1] == a2 )
{
LABEL_5:
*v2 = *v3;
free(v3);
result = 1LL;
}
else
{
while ( 1 )
{
v2 = v3;
v3 = (_QWORD *)*v3;
if ( !v3 )
break;
if ( v3[1] == a2 )
goto LABEL_5;
}
result = 0LL;
}
return result;
}

original_code:
_Bool
delete_element( list_element **head, const void *data ) {
  ((void) sizeof ((head != ((void *)0)) ? 1 : 0), __extension__ ({ if (head != ((void *)0)) ; else __assert_fail ("head != NULL", "linked_list.c", 104, __extension__ __PRETTY_FUNCTION__); }));
  list_element *e = *head;
  list_element *delete_me;
  if ( e->data == data ) {
    *head = e->next;
    free( e );
    return 1;
  }
  for ( ; e->next != ((void *)0); e = e->next ) {
    if ( e->next->data == data ) {
      delete_me = e->next;
      e->next = e->next->next;
      free( delete_me );
      return 1;
    }
  }
  return 0;
}

canonical_original_code:
_Bool delete_element(struct list_element **head, void *data) {
  ((void) sizeof ((head != ((void *)0)) ? 1 : 0), __extension__ ({ if (head != ((void *)0)) ; else __assert_fail ("head != NULL", "linked_list.c", 104, __extension__ __PRETTY_FUNCTION__); }));
  struct list_element *e = *head;
  struct list_element *delete_me;
  if ( e->data == data ) {
    *head = e->next;
    free( e );
    return 1;
  }
  for ( ; e->next != ((void *)0); e = e->next ) {
    if ( e->next->data == data ) {
      delete_me = e->next;
      e->next = e->next->next;
      free( delete_me );
      return 1;
    }
  }
  return 0;
}

variable_types: struct list_element { struct list_element *next; void *data; } *


decompiled_code:
__int64 __fastcall delete_list(void *ptr)
{
_QWORD *v1; // rbx
void *v2; // rdi

v1 = ptr;
if ( ptr )
{
do
{
v2 = v1;
v1 = (_QWORD *)*v1;
free(v2);
}
while ( v1 );
}
return 1LL;
}

canonical_decompiled_code:
__int64 __fastcall func6(void *ptr)
{
_QWORD *v1; // rbx
void *v2; // rdi

v1 = ptr;
if ( ptr )
{
do
{
v2 = v1;
v1 = (_QWORD *)*v1;
free(v2);
}
while ( v1 );
}
return 1LL;
}

original_code:
_Bool
delete_list( list_element *head ) {
  list_element *e;
  list_element *delete_me;
  for ( e = head; e != ((void *)0); ) {
    delete_me = e;
    e = e->next;
    free( delete_me );
  }
  return 1;
}

canonical_original_code:
_Bool delete_list(struct list_element *head) {
  struct list_element *e;
  struct list_element *delete_me;
  for ( e = head; e != ((void *)0); ) {
    delete_me = e;
    e = e->next;
    free( delete_me );
  }
  return 1;
}