// File: /workspace/github_c_makefile_star2_O2/wjmelements[P]evm/evm.c
// Function: main
int main(int argc, char *const argv[]) {
    selfPath = argv[0];
    int option;
    char *contents = NULL;
    while ((option = getopt (argc, argv, "cdgjlo:suw:x")) != -1)
        switch (option) {
            case 'c':
                wrapConstructor = 1;
                break;
            case 'd':
                inverse = 1;
                break;
            case 'j':
                labelJumpdests = 1;
                break;
            case 'o':
                contents = optarg;
                break;
            case 'x':
                runtime = 1;
                break;
            case 'g':
                includeGas = 1;
                break;
            case 's':
                includeStatus = 1;
                break;
            case 'l':
                includeLogs = 1;
                break;
            case 'u':
                updateConfigFile = 1;
                break;
            case 'w':
                if (configFile == NULL) {
                    evmInit();
                }
                configFile = optarg;
                dioInit(selfPath);
                loadConfig(configFile, updateConfigFile);
                break;
            case '?':
            default:
                USAGE;
                return 1;
        }
    if (inverse && wrapConstructor) {
        fputs("-c cannot be used with -d\n", stderr);
        USAGE;
        return 1;
    }
    if (inverse && labelJumpdests) {
        fputs("-j cannot be used with -d\n", stderr);
        USAGE;
        return 1;
    }
    if (runtime && wrapConstructor) {
        fputs("-c cannot be used with -x\n", stderr);
        USAGE;
        return 1;
    }
    if (runtime && labelJumpdests) {
        fputs("-j cannot be used with -x\n", stderr);
        USAGE;
        return 1;
    }
    if (inverse && runtime) {
        fputs("-d cannot be used with -x\n", stderr);
        USAGE;
        return 1;
    }
    void (*subprogram)(const char*);
    if (inverse) {
        subprogram = disassemble;
    } else if (runtime) {
        subprogram = execute;
    } else if (configFile) {
        // tests should _exit(1) if they fail
        _exit(0);
    } else {
        subprogram = assemble;
    }
    if (contents != NULL) {
        // input is from the command line
        subprogram(contents);
    } else if (optind == argc) {
        // read from stdin
        size_t bufferSize = 4;
        size_t capacity = bufferSize - 1;
        char *input = calloc(1, bufferSize);
        char *pos = input;
        while (1) {
            ssize_t red = read(0, pos, capacity);
            if (red == -1) {
                perror("stdin");
                return 1;
            }
            if (red == 0) {
                // EOF
                break;
            }
            capacity -= red;
            if (capacity) {
                pos += red;
            } else {
                char *next = calloc(1, bufferSize << 1);
                memcpy(next, input, bufferSize);
                pos = next + bufferSize - 1;
                capacity = bufferSize;
                bufferSize <<= 1;
                free(input);
                input = next;
            }
        }
        subprogram(input);
        // free is redundant with program termination but makes valgrind happy
        free(input);
    } else for (int i = optind; i < argc; i++) {
        int fd = open(argv[i], O_RDONLY);
        if (fd == -1) {
            perror(argv[i]);
            _exit(1);
        }

        struct stat fstatus;
        int fstatSuccess = fstat(fd, &fstatus);
        if (fstatSuccess == -1) {
            perror(argv[i]);
            _exit(1);
        }
        
        contents = mmap(NULL, fstatus.st_size, PROT_READ, MAP_PRIVATE | MAP_FILE, fd, 0);
        if (contents == NULL) {
            perror(argv[i]);
        }
        subprogram(contents);
        munmap(contents, fstatus.st_size);
        close(fd);
    }
    return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x98, %rsp
movq %rsi, %rbx
movl %edi, %ebp
movq (%rsi), %rax
movq %rax, 0x13614(%rip)     # 0x16a00
leaq 0xbc69(%rip), %r15      # 0xf05c
leaq 0xbc0a(%rip), %r12      # 0xf004
movq 0x12bd7(%rip), %r13     # 0x15fd8
xorl %r14d, %r14d
movl %ebp, %edi
movq %rbx, %rsi
movq %r15, %rdx
callq 0x3270
leal -0x63(%rax), %ecx
cmpl $0x15, %ecx
ja 0x34c3
movslq (%r12,%rcx,4), %rax
addq %r12, %rax
jmpq *%rax
movb $0x1, 0x135db(%rip)     # 0x16a08
jmp 0x3404
movb $0x1, 0x135ea(%rip)     # 0x16a20
jmp 0x3404
movb $0x1, 0x135d1(%rip)     # 0x16a10
jmp 0x3404
movb $0x1, 0x135c4(%rip)     # 0x16a0c
jmp 0x3404
cmpq $0x0, 0x135d6(%rip)     # 0x16a28
jne 0x345b
xorl %eax, %eax
callq 0x6955
movq (%r13), %rax
movq %rax, 0x135c2(%rip)     # 0x16a28
movq 0x13593(%rip), %rdi     # 0x16a00
callq 0x3c00
movq 0x135af(%rip), %rdi     # 0x16a28
movzbl 0x135a4(%rip), %esi     # 0x16a24
callq 0x568c
jmp 0x3404
movb $0x1, 0x13593(%rip)     # 0x16a24
jmp 0x3404
movb $0x1, 0x1357b(%rip)     # 0x16a18
jmp 0x3404
movq (%r13), %r14
jmp 0x3404
movb $0x1, 0x13562(%rip)     # 0x16a14
jmp 0x3404
movb $0x1, 0x1355e(%rip)     # 0x16a1c
jmp 0x3404
cmpl $-0x1, %eax
jne 0x369b
movb 0x1353a(%rip), %al      # 0x16a0c
movb 0x13530(%rip), %dl      # 0x16a08
movl %eax, %ecx
andb %dl, %cl
testb $0x1, %cl
jne 0x36a7
movb 0x13524(%rip), %sil     # 0x16a10
movl %eax, %ecx
andb %sil, %cl
testb $0x1, %cl
jne 0x36ba
movb 0x13514(%rip), %cl      # 0x16a14
andb %cl, %dl
testb $0x1, %dl
jne 0x36cd
andb %cl, %sil
testb $0x1, %sil
jne 0x36e0
movl %eax, %edx
andb %cl, %dl
testb $0x1, %dl
jne 0x36f3
orb %al, %cl
leaq 0x225(%rip), %rdx       # 0x3753
leaq 0x255(%rip), %rsi       # 0x378a
testb $0x1, %al
cmovneq %rdx, %rsi
movq %rsi, (%rsp)
testb $0x1, %cl
jne 0x355d
cmpq $0x0, 0x134dc(%rip)     # 0x16a28
jne 0x374c
leaq 0x48a(%rip), %rax       # 0x39e3
movq %rax, (%rsp)
testq %r14, %r14
je 0x356d
movq %r14, %rdi
callq *(%rsp)
jmp 0x3694
movq 0x12a5c(%rip), %rax     # 0x15fd0
movslq (%rax), %r12
cmpl %ebp, %r12d
jne 0x3600
pushq $0x1
popq %rbx
pushq $0x4
popq %r13
movq %rbx, %rdi
movq %r13, %rsi
callq 0x31b0
movq %rax, %r14
pushq $0x3
popq %r15
movq %rax, %r12
movq %r15, %rbp
movq %r13, %r15
xorl %edi, %edi
movq %r12, %rsi
movq %rbp, %rdx
callq 0x3190
testq %rax, %rax
je 0x3686
cmpq $-0x1, %rax
je 0x372d
subq %rax, %rbp
je 0x35cc
addq %rax, %r12
jmp 0x35a2
leaq (%r15,%r15), %r13
movq %rbx, %rdi
movq %r13, %rsi
callq 0x31b0
movq %rax, %rbp
movq %rax, %rdi
movq %r14, %rsi
movq %r15, %rdx
callq 0x31f0
leaq (%r15,%rbp), %r12
decq %r12
movq %r14, %rdi
callq 0x3040
movq %rbp, %r14
jmp 0x359c
movslq %ebp, %rbp
cmpq %rbp, %r12
jge 0x3694
movq (%rbx,%r12,8), %rdi
xorl %esi, %esi
xorl %eax, %eax
callq 0x3250
cmpl $-0x1, %eax
je 0x373b
movl %eax, %r13d
movl %eax, %edi
leaq 0x8(%rsp), %rsi
callq 0x32a0
cmpl $-0x1, %eax
je 0x373b
movq 0x38(%rsp), %r14
xorl %edi, %edi
movq %r14, %rsi
pushq $0x1
popq %rdx
pushq $0x2
popq %rcx
movl %r13d, %r8d
xorl %r9d, %r9d
callq 0x30d0
movq %rax, %r15
testq %rax, %rax
je 0x367b
movq %r15, %rdi
callq *(%rsp)
movq %r15, %rdi
movq %r14, %rsi
callq 0x3230
movl %r13d, %edi
callq 0x3160
incq %r12
jmp 0x3603
movq (%rbx,%r12,8), %rdi
callq 0x3260
jmp 0x365d
movq %r14, %rdi
callq *(%rsp)
movq %r14, %rdi
callq 0x3040
xorl %eax, %eax
jmp 0x371b
movq 0x12956(%rip), %rax     # 0x15ff8
movq (%rax), %rsi
jmp 0x370c
movq 0x1294a(%rip), %rbx     # 0x15ff8
movq (%rbx), %rsi
leaq 0xba04(%rip), %rdi      # 0xf0bc
jmp 0x3704
movq 0x12937(%rip), %rbx     # 0x15ff8
movq (%rbx), %rsi
leaq 0xba0c(%rip), %rdi      # 0xf0d7
jmp 0x3704
movq 0x12924(%rip), %rbx     # 0x15ff8
movq (%rbx), %rsi
leaq 0xba14(%rip), %rdi      # 0xf0f2
jmp 0x3704
movq 0x12911(%rip), %rbx     # 0x15ff8
movq (%rbx), %rsi
leaq 0xba1c(%rip), %rdi      # 0xf10d
jmp 0x3704
movq 0x128fe(%rip), %rbx     # 0x15ff8
movq (%rbx), %rsi
leaq 0xba24(%rip), %rdi      # 0xf128
callq 0x3130
movq (%rbx), %rsi
leaq 0xb956(%rip), %rdi      # 0xf069
callq 0x3130
pushq $0x1
popq %rax
addq $0x98, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0xba0f(%rip), %rdi      # 0xf143
callq 0x3260
jmp 0x3718
movq (%rbx,%r12,8), %rdi
callq 0x3260
pushq $0x1
popq %rdi
callq 0x3080
xorl %edi, %edi
callq 0x3080