// File: /workspace/github_c_makefile_star2_O0/kevinp89[P]Operating-System-EXT2-file-system-with-commands/ext2_ln.c
// Function: main
int main(int argc, char **argv){
    //arguments check
    if(argc < 4){
        fprintf(stderr, "Usage: %s ./ext2_ln [disk] [Src Path] [target "
                        "path]\n",
                argv[0]);
        exit(1);
    }

    /* get args */
    char *disk_img = NULL; //disk img path
    char *src_path = NULL; //src path in virtual disk
    char *target_path = NULL; //target path in virtual disk
    int s_link_flag=0; //symlink flag

    /* get the args and store in vars */
    int c;
    if ((c = getopt(argc, argv, "s")) != -1) {
            if (c == 's') {
                s_link_flag = 1;
            }
        int a;
        for(a=optind; a<argc; a++){

            switch (a) {
                case 2:
                    disk_img = argv[a];
                    break;
                case 3:
                    src_path = argv[a];
                    break;
                case 4:
                    target_path = argv[a];
                    break;
                default:
                    break;
            }
        }
    } else {
        disk_img = argv[1];
        src_path = argv[2];
        target_path = argv[3];
    }


    //opening the disk
    int fd = open(disk_img, O_RDWR);
    if(!fd){
        fprintf(stderr, "Disk image '%s' not found\n", argv[1]);
        exit(1);
    }

    /**check if paths are absolute */
    //check if virtual path 1 is valid
    int check = check_path(src_path);
    if(check == 1){
        fprintf(stderr, "Please provide absolute path for virtual path 1");
        exit(1);
    }

    //check virtual path 2 is absolute or not.
    int check2 = check_path(target_path);
    if(check2 == 1){
        fprintf(stderr, "Please provide absolute path for virtual path");
        exit(1);
    }

    // mmap the disk
    disk = mmap(NULL, 128*1024, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if (disk == MAP_FAILED) {
        perror("mmap");
        exit(1);
    }

    // Grabbing super block and block descriptor
    sb = (struct ext2_super_block *)(disk + 1024);
    desc = (struct ext2_group_desc *)(disk + 2*1024);

    unsigned char *bmap = (unsigned char *)(disk + 1024 * desc->bg_block_bitmap);

    //check if the file paths exists, if so get the parent
    int parent_index_1 = check_parent(disk, src_path);
    if(parent_index_1 == -1){
        fprintf(stderr, "'%s' No such file or directory\n", src_path);
        exit(ENOENT);
    }
    //get the parent inode
    struct ext2_inode *parent_node1 = (struct ext2_inode *) (
            (disk+EXT2_BLOCK_SIZE * desc->bg_inode_table) +
            (sb->s_inode_size * parent_index_1));


    int parent_index_2 = check_parent(disk, target_path);
    if(parent_index_2 == -1){
        fprintf(stderr, "No such file or directory");
        exit(ENOENT);
    }

    /** get the last names from both files */

    char *file_name1 = get_last_file_name(src_path);
    char *file_name2 = get_last_file_name(target_path);

    //check if first file is a directory or not
    int check_file = search_directories(disk, parent_node1, file_name1, 1);
    if(check_file != -1){
        fprintf(stderr, "Give file: '%s' is a directory", file_name1);
        exit(EISDIR);
    }

    //for second one, get parent to check if file exists
    //get the parent node
    struct ext2_inode *parent_node2 = (struct ext2_inode *) (
            (disk+EXT2_BLOCK_SIZE * desc->bg_inode_table) +
            (sb->s_inode_size * parent_index_2));

    int check_dir_exists = search_directories(disk,parent_node2, file_name2, 1);
    if(check_dir_exists != -1){
        fprintf(stderr, "File: '%s' already exists", file_name2);
        exit(EEXIST);
    }

    int check_file_exists = search_directories(disk,parent_node2, file_name2, 0);
    if(check_file_exists != -1){
        fprintf(stderr, "File: '%s' already exists", file_name2);
        exit(EEXIST);
    }

    //get the inode for first file name
    unsigned int inode_indx1 = search_directories(disk, parent_node1,
                                                  file_name1, 0);
    struct ext2_inode *inode1 = (struct ext2_inode *) ((disk +
            EXT2_BLOCK_SIZE * desc->bg_inode_bitmap) +
            (sb->s_inode_size * inode_indx1));

    /* if -s is provided, create new inode */
    int inode;
    struct ext2_inode *new_inode;
    if(s_link_flag){
        // Finding a free inode and allocating (set to 1)
        unsigned char *imap = (unsigned char *)(disk + 1024 *
                                                       desc->bg_inode_bitmap);

        for (inode = 11; inode < sb->s_inodes_count; inode++) {
            if (check_node(inode, imap) == 0) {
                break;
            }
        }
        if (inode == sb->s_inodes_count) { // Maximum reached, no more inodes
            fprintf(stderr, "No more inodes available.");
            exit(1);
        }
        // Finding a free block and allocating (set to 1)
        int bnode;
        for (bnode = 22; bnode < sb->s_blocks_count; bnode++) {
            if (check_node(bnode, bmap) == 0) {
                break;
            }
        }
        if (bnode == sb->s_blocks_count) {
            fprintf(stderr, "No more blocks available.");
            exit(1);
        }
        char *data_block;
        // Actual allocation.
        set_node(inode, imap);
        set_node(bnode, bmap);

        adjust_free_blocks(-1, sb, desc);
        adjust_free_inodes(-1, sb, desc);
        // Writing data to the ext2_inode struct in the inode index.
        new_inode = (struct ext2_inode *)((disk + 1024 * desc->bg_inode_table)
                                                             + (sb->s_inode_size * (inode)));
        new_inode->i_mode = EXT2_S_IFLNK;
        new_inode->i_uid = 0;
        new_inode->i_size = strlen(src_path); //size is the same as src node
        new_inode->i_ctime = (unsigned int) time(0);
        new_inode->i_dtime = 0;
        new_inode->i_gid = 0;
        new_inode->i_blocks = 2;
        new_inode->osd1 = 0;
        new_inode->i_block[0] = bnode; //change??
        new_inode->i_generation = 0;
        new_inode->i_file_acl = 0;
        new_inode->i_dir_acl = 0;
        new_inode->i_faddr = 0;
        new_inode->i_links_count = 2; // Itself and from parent.
        parent_node2->i_links_count++; // Parent gets one more link from parent dir in new directory. ???

//        read in src path into data block
        data_block = (char*)(disk + EXT2_BLOCK_SIZE *
                                          new_inode->i_block[0]);
        strcpy(data_block, src_path);

    }

    // Adding new inode/directory entry into the parent block.
    int i;
    int par_block_index;
    for (i = 0; parent_node2->i_block[i] != 0; i++) {
        par_block_index = parent_node2->i_block[i];
    }
    int total_rec_len;
    struct ext2_dir_entry *curdir = (struct ext2_dir_entry *) (disk + (1024 * par_block_index));
    // When this for loop exits, curdir should be the last directory
    for (total_rec_len = 0; total_rec_len + curdir->rec_len < 1024;) {
        total_rec_len += curdir->rec_len;
        curdir = (struct ext2_dir_entry *) (disk + (1024 * par_block_index) + total_rec_len);
    }
    // Check there's enough space to place the new dir entry in the current block
    // Reuse total_rec_len to find remaining bytes if curdir was reduced to proper size
    struct ext2_dir_entry *newdir;
    int remaining_rec_len = sizeof(curdir) + curdir->name_len; // Actual size of curdir
    remaining_rec_len += 4 - (remaining_rec_len % 4); // Add padding
    remaining_rec_len = 1024 - remaining_rec_len - total_rec_len; // Remaining space
    if (remaining_rec_len < (8 + strlen(file_name2))) { // Not enough space
        // Allocate new block
        int newblock;
        for (newblock = 22; newblock < sb->s_blocks_count; newblock++) {
            if (check_node(newblock, bmap) == 0) {
                break;
            }
        }
        if (newblock == sb->s_blocks_count) {
            fprintf(stderr, "No more blocks available.");
            exit(1);
        }
        set_node(newblock, bmap);
        sb->s_free_blocks_count--;
        parent_node2->i_block[i] = newblock; // i should still hold the first block space unused by parent
        parent_node2->i_blocks += 2; // One more block being added
        newdir = (struct ext2_dir_entry *) (disk + (1024 * newblock));
        newdir->rec_len = 1024; // Takes up the whole of the new block.
    } else { // Enough space
        // Change curdir, add new directory
        curdir->rec_len = sizeof(curdir) + curdir->name_len;
        curdir->rec_len += 4 - (curdir->rec_len % 4);
        total_rec_len += curdir->rec_len;
        newdir = (struct ext2_dir_entry *) (disk + (1024 *
                par_block_index) + total_rec_len);
        newdir->rec_len = 1024 - total_rec_len; // Takes up the rest of the block.
    }
    if(s_link_flag){
        newdir->inode = inode + 1;
        newdir->name_len = strlen(file_name2);
        newdir->file_type = EXT2_FT_SYMLINK;
        strncpy(newdir->name, file_name2, newdir->name_len);
        //no increase in the link count
    } else {
        //for the hard link
        newdir->inode = inode_indx1 + 1; // set the index to the linking index
        newdir->name_len = strlen(file_name2); //set the new name length
        newdir->file_type = EXT2_FT_REG_FILE; //set file type
        strncpy(newdir->name, file_name2,
                newdir->name_len); //set the new name
        inode1->i_links_count++; //increment the link count
    }
    return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x100, %rsp            # imm = 0x100
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
cmpl $0x4, -0x8(%rbp)
jge 0x18d8
movq 0x3742(%rip), %rax      # 0x4ff8
movq (%rax), %rdi
movq -0x10(%rbp), %rax
movq (%rax), %rdx
leaq 0x1769(%rip), %rsi      # 0x3030
movb $0x0, %al
callq 0x10a0
movl $0x1, %edi
callq 0x1110
movq $0x0, -0x18(%rbp)
movq $0x0, -0x20(%rbp)
movq $0x0, -0x28(%rbp)
movl $0x0, -0x2c(%rbp)
movl -0x8(%rbp), %edi
movq -0x10(%rbp), %rsi
leaq 0x184f(%rip), %rdx      # 0x3154
callq 0x1100
movl %eax, -0x30(%rbp)
cmpl $-0x1, %eax
je 0x19a8
cmpl $0x73, -0x30(%rbp)
jne 0x1923
movl $0x1, -0x2c(%rbp)
movq 0x36ae(%rip), %rax      # 0x4fd8
movl (%rax), %eax
movl %eax, -0x34(%rbp)
movl -0x34(%rbp), %eax
cmpl -0x8(%rbp), %eax
jge 0x19a6
movl -0x34(%rbp), %eax
movl %eax, -0xec(%rbp)
subl $0x2, %eax
je 0x1961
jmp 0x1947
movl -0xec(%rbp), %eax
subl $0x3, %eax
je 0x1973
jmp 0x1954
movl -0xec(%rbp), %eax
subl $0x4, %eax
je 0x1985
jmp 0x1997
movq -0x10(%rbp), %rax
movslq -0x34(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0x18(%rbp)
jmp 0x1999
movq -0x10(%rbp), %rax
movslq -0x34(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0x20(%rbp)
jmp 0x1999
movq -0x10(%rbp), %rax
movslq -0x34(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0x28(%rbp)
jmp 0x1999
jmp 0x1999
jmp 0x199b
movl -0x34(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x34(%rbp)
jmp 0x192f
jmp 0x19cc
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x18(%rbp)
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x20(%rbp)
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rax
movq %rax, -0x28(%rbp)
movq -0x18(%rbp), %rdi
movl $0x2, %esi
movb $0x0, %al
callq 0x10e0
movl %eax, -0x38(%rbp)
cmpl $0x0, -0x38(%rbp)
jne 0x1a0f
movq 0x360c(%rip), %rax      # 0x4ff8
movq (%rax), %rdi
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rdx
leaq 0x1667(%rip), %rsi      # 0x3065
movb $0x0, %al
callq 0x10a0
movl $0x1, %edi
callq 0x1110
movq -0x20(%rbp), %rdi
callq 0x1860
movl %eax, -0x3c(%rbp)
cmpl $0x1, -0x3c(%rbp)
jne 0x1a43
movq 0x35d0(%rip), %rax      # 0x4ff8
movq (%rax), %rdi
leaq 0x164e(%rip), %rsi      # 0x3080
movb $0x0, %al
callq 0x10a0
movl $0x1, %edi
callq 0x1110
movq -0x28(%rbp), %rdi
callq 0x1860
movl %eax, -0x40(%rbp)
cmpl $0x1, -0x40(%rbp)
jne 0x1a77
movq 0x359c(%rip), %rax      # 0x4ff8
movq (%rax), %rdi
leaq 0x164a(%rip), %rsi      # 0x30b0
movb $0x0, %al
callq 0x10a0
movl $0x1, %edi
callq 0x1110
movl -0x38(%rbp), %r8d
xorl %eax, %eax
movl %eax, %r9d
movl $0x20000, %esi          # imm = 0x20000
movl $0x3, %edx
movl $0x1, %ecx
movq %r9, %rdi
callq 0x1070
movq %rax, 0x3612(%rip)      # 0x50b0
movq $-0x1, %rax
cmpq %rax, 0x3604(%rip)      # 0x50b0
jne 0x1ac4
leaq 0x1629(%rip), %rdi      # 0x30de
callq 0x10f0
movl $0x1, %edi
callq 0x1110
movq 0x35e5(%rip), %rax      # 0x50b0
addq $0x400, %rax            # imm = 0x400
movq %rax, 0x35e0(%rip)      # 0x50b8
movq 0x35d1(%rip), %rax      # 0x50b0
addq $0x800, %rax            # imm = 0x800
movq %rax, 0x35d4(%rip)      # 0x50c0
movq 0x35bd(%rip), %rax      # 0x50b0
movq 0x35c6(%rip), %rcx      # 0x50c0
movl (%rcx), %ecx
shll $0xa, %ecx
movl %ecx, %ecx
addq %rcx, %rax
movq %rax, -0x48(%rbp)
movq 0x35a1(%rip), %rdi      # 0x50b0
movq -0x20(%rbp), %rsi
callq 0x1530
movl %eax, -0x4c(%rbp)
cmpl $-0x1, -0x4c(%rbp)
jne 0x1b47
movq 0x34d0(%rip), %rax      # 0x4ff8
movq (%rax), %rdi
movq -0x20(%rbp), %rdx
leaq 0x15ad(%rip), %rsi      # 0x30e3
movb $0x0, %al
callq 0x10a0
movl $0x2, %edi
callq 0x1110
movq 0x3562(%rip), %rax      # 0x50b0
movq 0x356b(%rip), %rcx      # 0x50c0
movl 0x8(%rcx), %ecx
shll $0xa, %ecx
movl %ecx, %ecx
addq %rcx, %rax
movq 0x3551(%rip), %rcx      # 0x50b8
movzwl 0x58(%rcx), %ecx
imull -0x4c(%rbp), %ecx
movslq %ecx, %rcx
addq %rcx, %rax
movq %rax, -0x58(%rbp)
movq 0x3530(%rip), %rdi      # 0x50b0
movq -0x28(%rbp), %rsi
callq 0x1530
movl %eax, -0x5c(%rbp)
cmpl $-0x1, -0x5c(%rbp)
jne 0x1bb4
movq 0x345f(%rip), %rax      # 0x4ff8
movq (%rax), %rdi
leaq 0x1560(%rip), %rsi      # 0x3103
movb $0x0, %al
callq 0x10a0
movl $0x2, %edi
callq 0x1110
movq -0x20(%rbp), %rdi
callq 0x1770
movq %rax, -0x68(%rbp)
movq -0x28(%rbp), %rdi
callq 0x1770
movq %rax, -0x70(%rbp)
movq 0x34db(%rip), %rdi      # 0x50b0
movq -0x58(%rbp), %rsi
movq -0x68(%rbp), %rdx
movl $0x1, %ecx
callq 0x13e0
movl %eax, -0x74(%rbp)
cmpl $-0x1, -0x74(%rbp)
je 0x1c16
movq 0x3401(%rip), %rax      # 0x4ff8
movq (%rax), %rdi
movq -0x68(%rbp), %rdx
leaq 0x1518(%rip), %rsi      # 0x311d
movb $0x0, %al
callq 0x10a0
movl $0x15, %edi
callq 0x1110
movq 0x3493(%rip), %rax      # 0x50b0
movq 0x349c(%rip), %rcx      # 0x50c0
movl 0x8(%rcx), %ecx
shll $0xa, %ecx
movl %ecx, %ecx
addq %rcx, %rax
movq 0x3482(%rip), %rcx      # 0x50b8
movzwl 0x58(%rcx), %ecx
imull -0x5c(%rbp), %ecx
movslq %ecx, %rcx
addq %rcx, %rax
movq %rax, -0x80(%rbp)
movq 0x3461(%rip), %rdi      # 0x50b0
movq -0x80(%rbp), %rsi
movq -0x70(%rbp), %rdx
movl $0x1, %ecx
callq 0x13e0
movl %eax, -0x84(%rbp)
cmpl $-0x1, -0x84(%rbp)
je 0x1c96
movq 0x3381(%rip), %rax      # 0x4ff8
movq (%rax), %rdi
movq -0x70(%rbp), %rdx
leaq 0x14b7(%rip), %rsi      # 0x313c
movb $0x0, %al
callq 0x10a0
movl $0x11, %edi
callq 0x1110
movq 0x3413(%rip), %rdi      # 0x50b0
movq -0x80(%rbp), %rsi
movq -0x70(%rbp), %rdx
xorl %ecx, %ecx
callq 0x13e0
movl %eax, -0x88(%rbp)
cmpl $-0x1, -0x88(%rbp)
je 0x1ce1
movq 0x3336(%rip), %rax      # 0x4ff8
movq (%rax), %rdi
movq -0x70(%rbp), %rdx
leaq 0x146c(%rip), %rsi      # 0x313c
movb $0x0, %al
callq 0x10a0
movl $0x11, %edi
callq 0x1110
movq 0x33c8(%rip), %rdi      # 0x50b0
movq -0x58(%rbp), %rsi
movq -0x68(%rbp), %rdx
xorl %ecx, %ecx
callq 0x13e0
movl %eax, -0x8c(%rbp)
movq 0x33ac(%rip), %rax      # 0x50b0
movq 0x33b5(%rip), %rcx      # 0x50c0
movl 0x4(%rcx), %ecx
shll $0xa, %ecx
movl %ecx, %ecx
addq %rcx, %rax
movq 0x339b(%rip), %rcx      # 0x50b8
movzwl 0x58(%rcx), %ecx
imull -0x8c(%rbp), %ecx
movl %ecx, %ecx
addq %rcx, %rax
movq %rax, -0x98(%rbp)
cmpl $0x0, -0x2c(%rbp)
je 0x1fe9
movq 0x336b(%rip), %rax      # 0x50b0
movq 0x3374(%rip), %rcx      # 0x50c0
movl 0x4(%rcx), %ecx
shll $0xa, %ecx
movl %ecx, %ecx
addq %rcx, %rax
movq %rax, -0xb0(%rbp)
movl $0xb, -0x9c(%rbp)
movl -0x9c(%rbp), %eax
movq 0x3343(%rip), %rcx      # 0x50b8
cmpl (%rcx), %eax
jae 0x1da5
movl -0x9c(%rbp), %edi
movq -0xb0(%rbp), %rsi
callq 0x1230
cmpl $0x0, %eax
jne 0x1d92
jmp 0x1da5
jmp 0x1d94
movl -0x9c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x9c(%rbp)
jmp 0x1d68
movl -0x9c(%rbp), %eax
movq 0x3306(%rip), %rcx      # 0x50b8
cmpl (%rcx), %eax
jne 0x1dd8
movq 0x323b(%rip), %rax      # 0x4ff8
movq (%rax), %rdi
leaq 0x138f(%rip), %rsi      # 0x3156
movb $0x0, %al
callq 0x10a0
movl $0x1, %edi
callq 0x1110
movl $0x16, -0xb4(%rbp)
movl -0xb4(%rbp), %eax
movq 0x32c9(%rip), %rcx      # 0x50b8
cmpl 0x4(%rcx), %eax
jae 0x1e1d
movl -0xb4(%rbp), %edi
movq -0x48(%rbp), %rsi
callq 0x1230
cmpl $0x0, %eax
jne 0x1e0a
jmp 0x1e1d
jmp 0x1e0c
movl -0xb4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xb4(%rbp)
jmp 0x1de2
movl -0xb4(%rbp), %eax
movq 0x328e(%rip), %rcx      # 0x50b8
cmpl 0x4(%rcx), %eax
jne 0x1e51
movq 0x31c2(%rip), %rax      # 0x4ff8
movq (%rax), %rdi
leaq 0x1330(%rip), %rsi      # 0x3170
movb $0x0, %al
callq 0x10a0
movl $0x1, %edi
callq 0x1110
movl -0x9c(%rbp), %edi
movq -0xb0(%rbp), %rsi
callq 0x1280
movl -0xb4(%rbp), %edi
movq -0x48(%rbp), %rsi
callq 0x1280
movq 0x323f(%rip), %rsi      # 0x50b8
movq 0x3240(%rip), %rdx      # 0x50c0
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x1710
movq 0x3227(%rip), %rsi      # 0x50b8
movq 0x3228(%rip), %rdx      # 0x50c0
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x1740
movq 0x3207(%rip), %rax      # 0x50b0
movq 0x3210(%rip), %rcx      # 0x50c0
movl 0x8(%rcx), %ecx
shll $0xa, %ecx
movl %ecx, %ecx
addq %rcx, %rax
movq 0x31f6(%rip), %rcx      # 0x50b8
movzwl 0x58(%rcx), %ecx
imull -0x9c(%rbp), %ecx
movslq %ecx, %rcx
addq %rcx, %rax
movq %rax, -0xa8(%rbp)
movq -0xa8(%rbp), %rax
movw $0xa000, (%rax)         # imm = 0xA000
movq -0xa8(%rbp), %rax
movw $0x0, 0x2(%rax)
movq -0x20(%rbp), %rdi
callq 0x1060
movl %eax, %ecx
movq -0xa8(%rbp), %rax
movl %ecx, 0x4(%rax)
xorl %eax, %eax
movl %eax, %edi
callq 0x10b0
movl %eax, %ecx
movq -0xa8(%rbp), %rax
movl %ecx, 0xc(%rax)
movq -0xa8(%rbp), %rax
movl $0x0, 0x14(%rax)
movq -0xa8(%rbp), %rax
movw $0x0, 0x18(%rax)
movq -0xa8(%rbp), %rax
movl $0x2, 0x1c(%rax)
movq -0xa8(%rbp), %rax
movl $0x0, 0x24(%rax)
movl -0xb4(%rbp), %ecx
movq -0xa8(%rbp), %rax
movl %ecx, 0x28(%rax)
movq -0xa8(%rbp), %rax
movl $0x0, 0x64(%rax)
movq -0xa8(%rbp), %rax
movl $0x0, 0x68(%rax)
movq -0xa8(%rbp), %rax
movl $0x0, 0x6c(%rax)
movq -0xa8(%rbp), %rax
movl $0x0, 0x70(%rax)
movq -0xa8(%rbp), %rax
movw $0x2, 0x1a(%rax)
movq -0x80(%rbp), %rax
movw 0x1a(%rax), %cx
addw $0x1, %cx
movw %cx, 0x1a(%rax)
movq 0x30f0(%rip), %rax      # 0x50b0
movq -0xa8(%rbp), %rcx
movl 0x28(%rcx), %ecx
shll $0xa, %ecx
movl %ecx, %ecx
addq %rcx, %rax
movq %rax, -0xc0(%rbp)
movq -0xc0(%rbp), %rdi
movq -0x20(%rbp), %rsi
callq 0x1050
movl $0x0, -0xc4(%rbp)
movq -0x80(%rbp), %rax
movslq -0xc4(%rbp), %rcx
cmpl $0x0, 0x28(%rax,%rcx,4)
je 0x202b
movq -0x80(%rbp), %rax
movslq -0xc4(%rbp), %rcx
movl 0x28(%rax,%rcx,4), %eax
movl %eax, -0xc8(%rbp)
movl -0xc4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xc4(%rbp)
jmp 0x1ff3
movq 0x307e(%rip), %rax      # 0x50b0
movl -0xc8(%rbp), %ecx
shll $0xa, %ecx
movslq %ecx, %rcx
addq %rcx, %rax
movq %rax, -0xd8(%rbp)
movl $0x0, -0xcc(%rbp)
movl -0xcc(%rbp), %eax
movq -0xd8(%rbp), %rcx
movzwl 0x4(%rcx), %ecx
addl %ecx, %eax
cmpl $0x400, %eax            # imm = 0x400
jge 0x20ac
movq -0xd8(%rbp), %rax
movzwl 0x4(%rax), %eax
addl -0xcc(%rbp), %eax
movl %eax, -0xcc(%rbp)
movq 0x3026(%rip), %rax      # 0x50b0
movl -0xc8(%rbp), %ecx
shll $0xa, %ecx
movslq %ecx, %rcx
addq %rcx, %rax
movslq -0xcc(%rbp), %rcx
addq %rcx, %rax
movq %rax, -0xd8(%rbp)
jmp 0x2052
movq -0xd8(%rbp), %rax
movzbl 0x6(%rax), %eax
addq $0x8, %rax
movl %eax, -0xe4(%rbp)
movl -0xe4(%rbp), %eax
movl $0x4, %ecx
cltd
idivl %ecx
movl $0x4, %eax
subl %edx, %eax
addl -0xe4(%rbp), %eax
movl %eax, -0xe4(%rbp)
movl $0x400, %eax            # imm = 0x400
subl -0xe4(%rbp), %eax
subl -0xcc(%rbp), %eax
movl %eax, -0xe4(%rbp)
movslq -0xe4(%rbp), %rax
movq %rax, -0xf8(%rbp)
movq -0x70(%rbp), %rdi
callq 0x1060
movq %rax, %rcx
movq -0xf8(%rbp), %rax
addq $0x8, %rcx
cmpq %rcx, %rax
jae 0x2210
movl $0x16, -0xe8(%rbp)
movl -0xe8(%rbp), %eax
movq 0x2f7a(%rip), %rcx      # 0x50b8
cmpl 0x4(%rcx), %eax
jae 0x216c
movl -0xe8(%rbp), %edi
movq -0x48(%rbp), %rsi
callq 0x1230
cmpl $0x0, %eax
jne 0x2159
jmp 0x216c
jmp 0x215b
movl -0xe8(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xe8(%rbp)
jmp 0x2131
movl -0xe8(%rbp), %eax
movq 0x2f3f(%rip), %rcx      # 0x50b8
cmpl 0x4(%rcx), %eax
jne 0x21a0
movq 0x2e73(%rip), %rax      # 0x4ff8
movq (%rax), %rdi
leaq 0xfe1(%rip), %rsi       # 0x3170
movb $0x0, %al
callq 0x10a0
movl $0x1, %edi
callq 0x1110
movl -0xe8(%rbp), %edi
movq -0x48(%rbp), %rsi
callq 0x1280
movq 0x2f02(%rip), %rax      # 0x50b8
movl 0xc(%rax), %ecx
addl $-0x1, %ecx
movl %ecx, 0xc(%rax)
movl -0xe8(%rbp), %edx
movq -0x80(%rbp), %rax
movslq -0xc4(%rbp), %rcx
movl %edx, 0x28(%rax,%rcx,4)
movq -0x80(%rbp), %rax
movl 0x1c(%rax), %ecx
addl $0x2, %ecx
movl %ecx, 0x1c(%rax)
movq 0x2ec8(%rip), %rax      # 0x50b0
movl -0xe8(%rbp), %ecx
shll $0xa, %ecx
movslq %ecx, %rcx
addq %rcx, %rax
movq %rax, -0xe0(%rbp)
movq -0xe0(%rbp), %rax
movw $0x400, 0x4(%rax)       # imm = 0x400
jmp 0x22b1
movq -0xd8(%rbp), %rax
movzbl 0x6(%rax), %eax
addq $0x8, %rax
movw %ax, %cx
movq -0xd8(%rbp), %rax
movw %cx, 0x4(%rax)
movq -0xd8(%rbp), %rax
movzwl 0x4(%rax), %eax
movl $0x4, %ecx
cltd
idivl %ecx
movl %edx, %eax
movl $0x4, %edx
subl %eax, %edx
movq -0xd8(%rbp), %rax
movzwl 0x4(%rax), %ecx
addl %edx, %ecx
movw %cx, 0x4(%rax)
movq -0xd8(%rbp), %rax
movzwl 0x4(%rax), %eax
addl -0xcc(%rbp), %eax
movl %eax, -0xcc(%rbp)
movq 0x2e38(%rip), %rax      # 0x50b0
movl -0xc8(%rbp), %ecx
shll $0xa, %ecx
movslq %ecx, %rcx
addq %rcx, %rax
movslq -0xcc(%rbp), %rcx
addq %rcx, %rax
movq %rax, -0xe0(%rbp)
movl $0x400, %eax            # imm = 0x400
subl -0xcc(%rbp), %eax
movw %ax, %cx
movq -0xe0(%rbp), %rax
movw %cx, 0x4(%rax)
cmpl $0x0, -0x2c(%rbp)
je 0x230c
movl -0x9c(%rbp), %ecx
addl $0x1, %ecx
movq -0xe0(%rbp), %rax
movl %ecx, (%rax)
movq -0x70(%rbp), %rdi
callq 0x1060
movb %al, %cl
movq -0xe0(%rbp), %rax
movb %cl, 0x6(%rax)
movq -0xe0(%rbp), %rax
movb $0x7, 0x7(%rax)
movq -0xe0(%rbp), %rdi
addq $0x8, %rdi
movq -0x70(%rbp), %rsi
movq -0xe0(%rbp), %rax
movzbl 0x6(%rax), %eax
movl %eax, %edx
callq 0x1040
jmp 0x2372
movl -0x8c(%rbp), %ecx
addl $0x1, %ecx
movq -0xe0(%rbp), %rax
movl %ecx, (%rax)
movq -0x70(%rbp), %rdi
callq 0x1060
movb %al, %cl
movq -0xe0(%rbp), %rax
movb %cl, 0x6(%rax)
movq -0xe0(%rbp), %rax
movb $0x1, 0x7(%rax)
movq -0xe0(%rbp), %rdi
addq $0x8, %rdi
movq -0x70(%rbp), %rsi
movq -0xe0(%rbp), %rax
movzbl 0x6(%rax), %eax
movl %eax, %edx
callq 0x1040
movq -0x98(%rbp), %rax
movw 0x1a(%rax), %cx
addw $0x1, %cx
movw %cx, 0x1a(%rax)
xorl %eax, %eax
addq $0x100, %rsp            # imm = 0x100
popq %rbp
retq