// File: /workspace/github_c_makefile_star2_O1/ryvnf[P]czc/main.c
// Function: main
int main(int argc, char **argv)
{
    char *out = NULL;

    struct arg_list *gcc_args = arg_list_new("gcc");
    struct arg_list **gcc_args_tailp = &gcc_args->next;
    struct arg_list *src_files = NULL;
    struct arg_list **src_files_tailp = &src_files;

    // Colors are disabled to make messages from 'gcc' consistent with other
    // messages which doesn't have color.
    *gcc_args_tailp = arg_list_new("-fno-diagnostics-color");
    gcc_args_tailp = &(*gcc_args_tailp)->next;

    // We don't want warnings from GCC to leak through.  Will still output
    // errors if the generated code does not compile.
    *gcc_args_tailp = arg_list_new("-w");
    gcc_args_tailp = &(*gcc_args_tailp)->next;

    // Tell GCC that the source has been preprocessed.  This is to avoid having
    // to escape trigraphs in the generated C code.
    *gcc_args_tailp = arg_list_new("-fpreprocessed");
    gcc_args_tailp = &(*gcc_args_tailp)->next;

    int input_file_count = 0;

    enum {
        TO_EXE,
        TO_C,
        TO_ASM,
        TO_OBJ,
        AST_PRINT
    } mode = TO_EXE;

    for (int i = 1; i < argc; ++i) {
        if (argv[i][0] == '-') {
            if (strcmp(argv[i], "--print-ast") == 0) {
                mode = AST_PRINT;
                continue;
            }
            if (strcmp(argv[i], "--to-c") == 0) {
                mode = TO_C;
                *gcc_args_tailp = arg_list_new(argv[i]);
                gcc_args_tailp = &(*gcc_args_tailp)->next;
                continue;
            }

            switch (argv[i][1]) {
                // These options require thir arguments to be in the option
                // flag.  Their arguments can be anything.  They are copied
                // directly to the GCC command-line.
                case 'O':
                case 'f':
                    *gcc_args_tailp = arg_list_new(argv[i]);
                    gcc_args_tailp = &(*gcc_args_tailp)->next;
                    break;

                // The '-o' option doesn't require its arguments to be in the
                // option flag.  So if the flag doesn't have an argument, parse
                // the next argv element as argument for the option.  The
                // option gets added to the GCC command-line, but it also sets
                // the variable 'out'.
                case 'o':
                    *gcc_args_tailp = arg_list_new(argv[i]);
                    gcc_args_tailp = &(*gcc_args_tailp)->next;

                    if (argv[i][2] != '\0') {
                        out = argv[i] + 1;
                    } else {
                        if ((out = argv[++i]) == NULL)
                            missing_arg_for_opt(argv[i - 1]);
                        *gcc_args_tailp = arg_list_new(argv[i]);
                        gcc_args_tailp = &(*gcc_args_tailp)->next;
                    }

                    break;

                // These options doesn't require their arguments to be in the
                // option flag.  So if the flag doesn't have an argument, parse
                // the next argv element as argument for the option.  The
                // options are copied directly to the GCC command-line.
                case 'l':
                case 'L':
                    *gcc_args_tailp = arg_list_new(argv[i]);
                    gcc_args_tailp = &(*gcc_args_tailp)->next;

                    if (argv[i][2] == '\0') {
                        if (argv[++i] == NULL)
                            missing_arg_for_opt(argv[i - 1]);
                        *gcc_args_tailp = arg_list_new(argv[i]);
                        gcc_args_tailp = &(*gcc_args_tailp)->next;
                    }
                    break;

                case 'c':
                    mode = TO_OBJ;
                    if (argv[i][2] != '\0')
                        unrecognized_opt(argv[i]);

                    *gcc_args_tailp = arg_list_new(argv[i]);
                    gcc_args_tailp = &(*gcc_args_tailp)->next;
                    break;

                case 'S':
                    mode = TO_ASM;
                    if (argv[i][2] != '\0')
                        unrecognized_opt(argv[i]);

                    *gcc_args_tailp = arg_list_new(argv[i]);
                    gcc_args_tailp = &(*gcc_args_tailp)->next;
                    break;

                default:
                    unrecognized_opt(argv[i]);
            }
            continue;
        }

        // Arguments left are input files.  These are interpreted differently
        // depending on their extension, like .o for object files passed to the
        // linker or .s for assembly files passed to the assembler.  Only .z
        // and .zc files are recognized as source files for the language, all
        // other file types are passed directly to the GCC command-line.
        const char *ext = get_file_ext(argv[i]);
        input_file_count++;

        if (ext == NULL || (strcmp(ext, "z") != 0 &&
                    strcmp(ext, "zc") != 0 && strcmp(ext, "Z") != 0 &&
                    strcmp(ext, "ZC") != 0)) {
            *gcc_args_tailp = arg_list_new(argv[i]);
            gcc_args_tailp = &(*gcc_args_tailp)->next;
            continue;
        }

        *src_files_tailp = arg_list_new(argv[i]);
        src_files_tailp = &(*src_files_tailp)->next;
    }

    if (input_file_count == 0) {
        fatal(NULL, "no input files");
        exit(1);
    }


    if (out != NULL && input_file_count != 1 && mode != TO_EXE) {
        fatal(NULL, "cannot specify '-o' with '-c', '-S', or '-C' with "
                "multiple files\n");
        exit(1);
    }

    if (src_files != NULL) {
        if (mode == TO_C) {
            gen_c(src_files, out);
        } else if (mode == AST_PRINT) {
            print_ast_files(src_files);
        } else {
            invoke_gcc(src_files, gcc_args, gcc_args_tailp);
        }
    } else {
        invoke_gcc(src_files, gcc_args, gcc_args_tailp);
    }

    arg_list_del(src_files);
    arg_list_del(gcc_args);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
movq %rsi, 0x10(%rsp)
movl %edi, %ebp
movl $0x10, %edi
callq 0x2160
movq %rax, %r14
leaq 0x53b9(%rip), %rdi      # 0xe59f
callq 0x2220
movq %rax, (%r14)
xorl %ebx, %ebx
movq %rbx, 0x8(%r14)
movq %rbx, 0x28(%rsp)
movl $0x10, %edi
callq 0x2160
movq %rax, %r15
leaq 0x539d(%rip), %rdi      # 0xe5aa
callq 0x2220
movq %rax, (%r15)
movq %rbx, 0x8(%r15)
movq %r14, 0x40(%rsp)
movq %r15, 0x8(%r14)
movl $0x10, %edi
callq 0x2160
movq %rax, %r12
leaq 0x538b(%rip), %rdi      # 0xe5c1
callq 0x2220
movq %rax, (%r12)
movq %rbx, 0x8(%r12)
movq %r12, 0x8(%r15)
movl $0x10, %edi
callq 0x2160
movq %rax, %r15
leaq 0x5368(%rip), %rdi      # 0xe5c4
callq 0x2220
movq %rax, (%r15)
leaq 0x8(%r15), %r13
movq %rbx, 0x8(%r15)
movq %r15, 0x8(%r12)
movl %ebp, 0x34(%rsp)
cmpl $0x2, %ebp
jl 0x960b
leaq 0x28(%rsp), %rax
movq %rax, 0x38(%rsp)
movq $0x0, 0x18(%rsp)
movl $0x1, %ebp
movl $0x0, 0xc(%rsp)
xorl %ebx, %ebx
movq 0x10(%rsp), %r12
movslq %ebp, %r14
movq (%r12,%r14,8), %r15
cmpb $0x2d, (%r15)
jne 0x930e
movq %r15, %rdi
leaq 0x5317(%rip), %rsi      # 0xe5d3
callq 0x2100
testl %eax, %eax
je 0x93b7
movq %r15, %rdi
leaq 0x530c(%rip), %rsi      # 0xe5df
callq 0x2100
testl %eax, %eax
je 0x93c4
movzbl 0x1(%r15), %eax
cmpl $0x62, %eax
jle 0x9401
cmpl $0x6b, %eax
jg 0x9499
cmpl $0x63, %eax
je 0x9534
cmpl $0x66, %eax
je 0x9458
jmp 0x969d
movq %r15, %rdi
movl $0x2e, %esi
callq 0x20d0
leaq 0x1(%rax), %r12
incl %ebx
testq %rax, %rax
cmoveq %rax, %r12
je 0x9458
movq %r12, %rdi
leaq 0x52ae(%rip), %rsi      # 0xe5e6
callq 0x2100
testl %eax, %eax
je 0x937e
movq %r12, %rdi
leaq 0x529d(%rip), %rsi      # 0xe5e8
callq 0x2100
testl %eax, %eax
je 0x937e
movq %r12, %rdi
leaq 0x528d(%rip), %rsi      # 0xe5eb
callq 0x2100
testl %eax, %eax
je 0x937e
movq %r12, %rdi
leaq 0x527c(%rip), %rsi      # 0xe5ed
callq 0x2100
testl %eax, %eax
jne 0x9458
movl $0x10, %edi
callq 0x2160
movq %rax, %r12
movq %r15, %rdi
callq 0x2220
movq %rax, (%r12)
movq $0x0, 0x8(%r12)
movq 0x38(%rsp), %rax
movq %r12, (%rax)
leaq 0x8(%r12), %rax
movq %rax, 0x38(%rsp)
jmp 0x9483
movl $0x4, 0xc(%rsp)
jmp 0x9488
movl $0x10, %edi
callq 0x2160
movq %rax, %r12
movq %r15, %rdi
callq 0x2220
movq %rax, (%r12)
movq $0x0, 0x8(%r12)
movq %r12, (%r13)
leaq 0x8(%r12), %r13
movq 0x10(%rsp), %r12
movl $0x1, 0xc(%rsp)
jmp 0x9488
cmpl $0x4c, %eax
je 0x94f2
cmpl $0x4f, %eax
je 0x9458
cmpl $0x53, %eax
jne 0x969d
cmpb $0x0, 0x2(%r15)
jne 0x969d
movl $0x10, %edi
callq 0x2160
movq %rax, %r12
movq %r15, %rdi
callq 0x2220
movq %rax, (%r12)
movq $0x0, 0x8(%r12)
movq %r12, (%r13)
leaq 0x8(%r12), %r13
movl $0x2, 0xc(%rsp)
jmp 0x9483
movl $0x10, %edi
callq 0x2160
movq %rax, %r12
movq %r15, %rdi
callq 0x2220
movq %rax, (%r12)
movq $0x0, 0x8(%r12)
movq %r12, (%r13)
leaq 0x8(%r12), %r13
movq 0x10(%rsp), %r12
incl %ebp
cmpl 0x34(%rsp), %ebp
jl 0x92a5
jmp 0x961c
cmpl $0x6c, %eax
je 0x94f2
cmpl $0x6f, %eax
jne 0x969d
movl $0x10, %edi
callq 0x2160
movq %rax, %r12
movq %r15, %rdi
callq 0x2220
movq %rax, (%r12)
leaq 0x8(%r12), %rax
movq $0x0, 0x8(%r12)
movq %r12, (%r13)
movq 0x10(%rsp), %r12
movq (%r12,%r14,8), %rdx
cmpb $0x0, 0x2(%rdx)
je 0x95c0
incq %rdx
movq %rax, %r13
movq %rdx, 0x18(%rsp)
jmp 0x9488
movl $0x10, %edi
callq 0x2160
movq %rax, %r12
movq %r15, %rdi
callq 0x2220
movq %rax, (%r12)
leaq 0x8(%r12), %rax
movq $0x0, 0x8(%r12)
movq %r12, (%r13)
movq 0x10(%rsp), %r12
movq (%r12,%r14,8), %rdx
cmpb $0x0, 0x2(%rdx)
je 0x9577
movq %rax, %r13
jmp 0x9488
cmpb $0x0, 0x2(%r15)
jne 0x969d
movl $0x10, %edi
callq 0x2160
movq %rax, %r12
movq %r15, %rdi
callq 0x2220
movq %rax, (%r12)
movq $0x0, 0x8(%r12)
movq %r12, (%r13)
leaq 0x8(%r12), %r13
movl $0x3, 0xc(%rsp)
jmp 0x9483
movq %rax, 0x20(%rsp)
movq 0x8(%r12,%r14,8), %r15
testq %r15, %r15
je 0x96c4
incl %ebp
movl $0x10, %edi
callq 0x2160
movq %rax, %r12
movq %r15, %rdi
callq 0x2220
movq %rax, (%r12)
leaq 0x8(%r12), %r13
movq $0x0, 0x8(%r12)
movq 0x20(%rsp), %rax
movq %r12, (%rax)
jmp 0x9483
movq %rax, 0x20(%rsp)
movq 0x8(%r12,%r14,8), %r14
testq %r14, %r14
je 0x96c4
incl %ebp
movl $0x10, %edi
callq 0x2160
movq %rax, %r15
movq %r14, 0x18(%rsp)
movq %r14, %rdi
callq 0x2220
movq %rax, (%r15)
leaq 0x8(%r15), %r13
movq $0x0, 0x8(%r15)
movq 0x20(%rsp), %rax
movq %r15, (%rax)
jmp 0x9488
movl $0x0, 0xc(%rsp)
movq $0x0, 0x18(%rsp)
testl %ebx, %ebx
je 0x96ab
movq 0x18(%rsp), %rsi
testq %rsi, %rsi
setne %al
cmpl $0x1, %ebx
setne %cl
andb %al, %cl
movl 0xc(%rsp), %edx
testl %edx, %edx
setne %al
andb %cl, %al
cmpb $0x1, %al
je 0x96b4
movq 0x28(%rsp), %rdi
testq %rdi, %rdi
movq 0x40(%rsp), %rbx
je 0x9666
cmpl $0x4, %edx
je 0x9675
cmpl $0x1, %edx
jne 0x9668
callq 0x8eb3
jmp 0x967a
xorl %edi, %edi
movq %rbx, %rsi
movq %r13, %rdx
callq 0x8fc8
jmp 0x967a
callq 0x8f85
movq 0x28(%rsp), %rdi
callq 0x8e48
movq %rbx, %rdi
callq 0x8e48
xorl %eax, %eax
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x4e86(%rip), %rsi      # 0xe52a
xorl %edi, %edi
movq %r15, %rdx
jmp 0x96cd
leaq 0x4f3e(%rip), %rsi      # 0xe5f0
jmp 0x96bb
leaq 0x4f44(%rip), %rsi      # 0xe5ff
xorl %edi, %edi
xorl %eax, %eax
callq 0x5011
leaq 0x4e86(%rip), %rsi      # 0xe551
xorl %edi, %edi
xorl %eax, %eax
callq 0x5011