// File: /workspace/github_c_makefile_star2_O1/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 $0xa8, %rsp
movq %rsi, %r14
movl %edi, %ebx
movq (%rsi), %rax
movq %rax, 0x155b4(%rip)     # 0x19a00
leaq 0xdc09(%rip), %r12      # 0x1205c
leaq 0xdbaa(%rip), %r13      # 0x12004
movq 0x14b77(%rip), %rbp     # 0x18fd8
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, 0x1557a(%rip)     # 0x19a08
jmp 0x4464
movb $0x1, 0x15589(%rip)     # 0x19a20
jmp 0x4464
movb $0x1, 0x15570(%rip)     # 0x19a10
jmp 0x4464
movb $0x1, 0x15563(%rip)     # 0x19a0c
jmp 0x4464
cmpq $0x0, 0x15575(%rip)     # 0x19a28
jne 0x44bc
xorl %eax, %eax
callq 0x80ff
movq (%rbp), %rax
movq %rax, 0x15561(%rip)     # 0x19a28
movq 0x15532(%rip), %rdi     # 0x19a00
callq 0x4cd8
movq 0x1554e(%rip), %rdi     # 0x19a28
movzbl 0x15543(%rip), %esi     # 0x19a24
callq 0x70bf
jmp 0x4464
movb $0x1, 0x15532(%rip)     # 0x19a24
jmp 0x4464
movb $0x1, 0x1551a(%rip)     # 0x19a18
jmp 0x4464
movq (%rbp), %r15
jmp 0x4464
movb $0x1, 0x15501(%rip)     # 0x19a14
jmp 0x4464
movb $0x1, 0x154fd(%rip)     # 0x19a1c
jmp 0x4464
cmpl $-0x1, %eax
jne 0x4757
movb 0x154d9(%rip), %al      # 0x19a0c
movb 0x154cf(%rip), %dl      # 0x19a08
movl %eax, %ecx
andb %dl, %cl
testb $0x1, %cl
jne 0x476c
movb 0x154c3(%rip), %sil     # 0x19a10
movl %eax, %ecx
andb %sil, %cl
testb $0x1, %cl
jne 0x4773
movb 0x154b3(%rip), %cl      # 0x19a14
andb %cl, %dl
testb $0x1, %dl
jne 0x477a
andb %cl, %sil
testb $0x1, %sil
jne 0x4781
movl %eax, %edx
andb %cl, %dl
testb $0x1, %dl
jne 0x4788
orb %al, %cl
leaq 0x22c(%rip), %rdx       # 0x47bb
leaq 0x26b(%rip), %rsi       # 0x4801
testb $0x1, %al
cmovneq %rdx, %rsi
movq %rsi, 0x10(%rsp)
testb $0x1, %cl
jne 0x45c0
cmpq $0x0, 0x1547a(%rip)     # 0x19a28
jne 0x47b4
leaq 0x525(%rip), %rax       # 0x4ae0
movq %rax, 0x10(%rsp)
testq %r15, %r15
je 0x45d3
movq %r15, %rdi
callq *0x10(%rsp)
xorl %eax, %eax
jmp 0x4792
movq 0x149f6(%rip), %rax     # 0x18fd0
movslq (%rax), %rax
cmpl %eax, %ebx
jne 0x46aa
movl $0x4, %ebp
movl $0x1, %edi
movl $0x4, %esi
callq 0x31b0
movq %rax, %r14
movl $0x0, 0xc(%rsp)
movl $0x3, %r13d
movq %rax, %r12
xorl %ebx, %ebx
xorl %edi, %edi
movq %r12, %rsi
movq %r13, %rdx
callq 0x3190
testq %rax, %rax
je 0x4635
cmpq $-0x1, %rax
je 0x468a
subq %rax, %r13
je 0x4649
addq %rax, %r12
xorl %eax, %eax
movb $0x1, %bl
jmp 0x463a
movl $0x6, %eax
movq %rbp, %r15
movq %r15, %rbp
testl %eax, %eax
je 0x460d
jmp 0x473e
leaq (,%rbp,2), %r15
movl $0x1, %edi
movq %r15, %rsi
callq 0x31b0
movq %r14, %rbx
movq %rax, %r14
movq %rax, %rdi
movq %rbx, %rsi
movq %rbp, %rdx
callq 0x31f0
leaq (%r14,%rbp), %r12
decq %r12
movq %rbx, %rdi
callq 0x3040
xorl %eax, %eax
movb $0x1, %bl
movq %rbp, %r13
jmp 0x463d
leaq 0xdab2(%rip), %rdi      # 0x12143
callq 0x3260
movl $0x1, %eax
xorl %ebx, %ebx
movq %rbp, %r15
movl $0x1, 0xc(%rsp)
jmp 0x463d
cmpl %eax, %ebx
jle 0x45cc
leaq (%r14,%rax,8), %r14
subl %eax, %ebx
leaq 0x18(%rsp), %r15
movq (%r14), %rdi
xorl %esi, %esi
xorl %eax, %eax
callq 0x3250
cmpl $-0x1, %eax
je 0x47a4
movl %eax, %ebp
movl %eax, %edi
movq %r15, %rsi
callq 0x32a0
cmpl $-0x1, %eax
je 0x47ac
movq 0x48(%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 0x4734
movq %r13, %rdi
callq *0x10(%rsp)
movq %r13, %rdi
movq %r12, %rsi
callq 0x3230
movl %ebp, %edi
callq 0x3160
addq $0x8, %r14
decl %ebx
jne 0x46bd
jmp 0x45cc
movq (%r14), %rdi
callq 0x3260
jmp 0x470e
cmpl $0x6, %eax
jne 0x475e
movq %r14, %rdi
callq *0x10(%rsp)
movq %r14, %rdi
callq 0x3040
jmp 0x45cc
callq 0x33c5
jmp 0x478d
testb %bl, %bl
movl 0xc(%rsp), %eax
jne 0x45cc
jmp 0x4792
callq 0x339e
jmp 0x478d
callq 0x3377
jmp 0x478d
callq 0x3350
jmp 0x478d
callq 0x3329
jmp 0x478d
callq 0x3302
movl $0x1, %eax
addq $0xa8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %r14, %rdi
callq 0x32f1
movq %r14, %rdi
callq 0x32e0
xorl %edi, %edi
callq 0x3080