// File: /workspace/github_c_makefile_star2_O3/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, %r14
movl %edi, %ebx
movq (%rsi), %rax
movq %rax, 0x145b4(%rip)     # 0x18a00
leaq 0xdc09(%rip), %r12      # 0x1205c
leaq 0xdbaa(%rip), %r13      # 0x12004
movq 0x13b77(%rip), %rbp     # 0x17fd8
xorl %r15d, %r15d
movl %ebx, %edi
movq %r14, %rsi
movq %r12, %rdx
callq 0x3270
leal -0x63(%rax), %ecx
cmpl $0x15, %ecx
ja 0x4524
movslq (%r13,%rcx,4), %rax
addq %r13, %rax
jmpq *%rax
movb $0x1, 0x1457a(%rip)     # 0x18a08
jmp 0x4464
movb $0x1, 0x14589(%rip)     # 0x18a20
jmp 0x4464
movb $0x1, 0x14570(%rip)     # 0x18a10
jmp 0x4464
movb $0x1, 0x14563(%rip)     # 0x18a0c
jmp 0x4464
cmpq $0x0, 0x14575(%rip)     # 0x18a28
jne 0x44bc
xorl %eax, %eax
callq 0x80ed
movq (%rbp), %rax
movq %rax, 0x14561(%rip)     # 0x18a28
movq 0x14532(%rip), %rdi     # 0x18a00
callq 0x4c98
movq 0x1454e(%rip), %rdi     # 0x18a28
movzbl 0x14543(%rip), %esi     # 0x18a24
callq 0x70f1
jmp 0x4464
movb $0x1, 0x14532(%rip)     # 0x18a24
jmp 0x4464
movb $0x1, 0x1451a(%rip)     # 0x18a18
jmp 0x4464
movq (%rbp), %r15
jmp 0x4464
movb $0x1, 0x14501(%rip)     # 0x18a14
jmp 0x4464
movb $0x1, 0x144fd(%rip)     # 0x18a1c
jmp 0x4464
cmpl $-0x1, %eax
jne 0x4709
movb 0x144d9(%rip), %al      # 0x18a0c
movb 0x144cf(%rip), %dl      # 0x18a08
movl %eax, %ecx
andb %dl, %cl
testb $0x1, %cl
jne 0x4710
movb 0x144c3(%rip), %sil     # 0x18a10
movl %eax, %ecx
andb %sil, %cl
testb $0x1, %cl
jne 0x4717
movb 0x144b3(%rip), %cl      # 0x18a14
andb %cl, %dl
testb $0x1, %dl
jne 0x471e
andb %cl, %sil
testb $0x1, %sil
jne 0x4725
movl %eax, %edx
andb %cl, %dl
testb $0x1, %dl
jne 0x472c
orb %al, %cl
leaq 0x1de(%rip), %rdx       # 0x476d
leaq 0x21d(%rip), %rsi       # 0x47b3
testb $0x1, %al
cmovneq %rdx, %rsi
movq %rsi, (%rsp)
testb $0x1, %cl
jne 0x45be
cmpq $0x0, 0x1447b(%rip)     # 0x18a28
jne 0x4766
leaq 0x4ee(%rip), %rax       # 0x4aa8
movq %rax, (%rsp)
testq %r15, %r15
je 0x45ce
movq %r15, %rdi
callq *(%rsp)
jmp 0x4705
movq 0x139fb(%rip), %rax     # 0x17fd0
movslq (%rax), %rax
cmpl %eax, %ebx
jne 0x4667
movl $0x4, %r12d
movl $0x1, %edi
movl $0x4, %esi
callq 0x31b0
movq %rax, %rbx
movl $0x3, %r14d
movq %rax, %r15
movq %r14, %r13
movq %r12, %r14
xorl %edi, %edi
movq %r15, %rsi
movq %r13, %rdx
callq 0x3190
testq %rax, %rax
je 0x46f7
cmpq $-0x1, %rax
je 0x4748
subq %rax, %r13
je 0x4631
addq %rax, %r15
jmp 0x4607
leaq (%r14,%r14), %r12
movl $0x1, %edi
movq %r12, %rsi
callq 0x31b0
movq %rax, %r13
movq %rax, %rdi
movq %rbx, %rsi
movq %r14, %rdx
callq 0x31f0
leaq (%r14,%r13), %r15
decq %r15
movq %rbx, %rdi
callq 0x3040
movq %r13, %rbx
jmp 0x4601
cmpl %eax, %ebx
jle 0x4705
leaq (%r14,%rax,8), %r14
subl %eax, %ebx
leaq 0x8(%rsp), %r15
movq (%r14), %rdi
xorl %esi, %esi
xorl %eax, %eax
callq 0x3250
cmpl $-0x1, %eax
je 0x4756
movl %eax, %ebp
movl %eax, %edi
movq %r15, %rsi
callq 0x32a0
cmpl $-0x1, %eax
je 0x475e
movq 0x38(%rsp), %r12
xorl %edi, %edi
movq %r12, %rsi
movl $0x1, %edx
movl $0x2, %ecx
movl %ebp, %r8d
xorl %r9d, %r9d
callq 0x30d0
movq %rax, %r13
testq %rax, %rax
je 0x46ed
movq %r13, %rdi
callq *(%rsp)
movq %r13, %rdi
movq %r12, %rsi
callq 0x3230
movl %ebp, %edi
callq 0x3160
addq $0x8, %r14
decl %ebx
jne 0x467a
jmp 0x4705
movq (%r14), %rdi
callq 0x3260
jmp 0x46cb
movq %rbx, %rdi
callq *(%rsp)
movq %rbx, %rdi
callq 0x3040
xorl %eax, %eax
jmp 0x4736
callq 0x33c5
jmp 0x4731
callq 0x339e
jmp 0x4731
callq 0x3377
jmp 0x4731
callq 0x3350
jmp 0x4731
callq 0x3329
jmp 0x4731
callq 0x3302
movl $0x1, %eax
addq $0x98, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0xd9f4(%rip), %rdi      # 0x12143
callq 0x3260
jmp 0x4731
movq %r14, %rdi
callq 0x32f1
movq %r14, %rdi
callq 0x32e0
xorl %edi, %edi
callq 0x3080