// File: /workspace/github_c_makefile_star2_O3/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 $0x38, %rsp
movq %rsi, %r12
movl %edi, %ebp
movl $0x10, %edi
callq 0x2160
movq %rax, %r14
leaq 0x5545(%rip), %rdi      # 0xe59f
callq 0x2220
movq %rax, (%r14)
xorl %r13d, %r13d
movq %r13, 0x28(%rsp)
movl $0x10, %edi
callq 0x2160
movq %rax, %rbx
leaq 0x552c(%rip), %rdi      # 0xe5aa
callq 0x2220
movq %rax, (%rbx)
movq %r14, 0x30(%rsp)
movq %rbx, 0x8(%r14)
movl $0x10, %edi
callq 0x2160
movq %rax, %r15
leaq 0x551e(%rip), %rdi      # 0xe5c1
callq 0x2220
movq %rax, (%r15)
movq %r15, 0x8(%rbx)
movl $0x10, %edi
callq 0x2160
movq %rax, %rbx
leaq 0x5501(%rip), %rdi      # 0xe5c4
callq 0x2220
movq %rax, (%rbx)
movq $0x0, 0x8(%rsp)
movq %r13, 0x8(%rbx)
movq %rbx, 0x8(%r15)
movl %ebp, 0x1c(%rsp)
cmpl $0x2, %ebp
jl 0x94ae
addq $0x8, %rbx
leaq 0x28(%rsp), %rax
movq %rax, 0x20(%rsp)
movl $0x1, %r15d
movq $0x0, 0x10(%rsp)
xorl %ebp, %ebp
movq %r12, (%rsp)
movslq %r15d, %r14
movq (%r12,%r14,8), %r13
cmpb $0x2d, (%r13)
jne 0x916e
movq %r13, %rdi
leaq 0x54af(%rip), %rsi      # 0xe5d3
callq 0x2100
testl %eax, %eax
je 0x91aa
movq %r13, %rdi
leaq 0x54a8(%rip), %rsi      # 0xe5df
callq 0x2100
testl %eax, %eax
je 0x91b1
movzbl 0x1(%r13), %eax
cmpl $0x62, %eax
jle 0x9245
cmpl $0x6b, %eax
jg 0x92dc
cmpl $0x63, %eax
je 0x9373
cmpl $0x66, %eax
je 0x929b
jmp 0x94a0
movq %r13, %rdi
movl $0x2e, %esi
callq 0x20d0
incl %ebp
testq %rax, %rax
je 0x929b
movzbl 0x1(%rax), %ecx
cmpl $0x5a, %ecx
je 0x91ee
cmpl $0x7a, %ecx
jne 0x929b
cmpb $0x0, 0x2(%rax)
je 0x9208
cmpb $0x63, 0x2(%rax)
jne 0x929b
jmp 0x91fe
movl $0x4, %eax
jmp 0x91e4
movl $0x10, %edi
callq 0x2160
movq %rax, %r12
movq %r13, %rdi
callq 0x2220
movq %rax, (%r12)
movq $0x0, 0x8(%r12)
movq %r12, (%rbx)
leaq 0x8(%r12), %rbx
movq (%rsp), %r12
movl $0x1, %eax
movq %rax, 0x8(%rsp)
jmp 0x92c9
cmpb $0x0, 0x2(%rax)
je 0x9208
cmpb $0x43, 0x2(%rax)
jne 0x929b
cmpb $0x0, 0x3(%rax)
jne 0x929b
movl $0x10, %edi
callq 0x2160
movq %rax, %r12
movq %r13, %rdi
callq 0x2220
movq %rax, (%r12)
movq $0x0, 0x8(%r12)
movq 0x20(%rsp), %rax
movq %r12, (%rax)
leaq 0x8(%r12), %rax
movq (%rsp), %r12
movq %rax, 0x20(%rsp)
jmp 0x92c9
cmpl $0x4c, %eax
je 0x9333
cmpl $0x4f, %eax
je 0x929b
cmpl $0x53, %eax
jne 0x94a0
cmpb $0x0, 0x2(%r13)
jne 0x94a0
movl $0x10, %edi
callq 0x2160
movq %rax, %r12
movq %r13, %rdi
callq 0x2220
movq %rax, (%r12)
movq $0x0, 0x8(%r12)
movq %r12, (%rbx)
leaq 0x8(%r12), %rbx
movl $0x2, %eax
jmp 0x93ad
movl $0x10, %edi
callq 0x2160
movq %rax, %r12
movq %r13, %rdi
callq 0x2220
movq %rax, (%r12)
movq $0x0, 0x8(%r12)
movq %r12, (%rbx)
leaq 0x8(%r12), %rbx
movq (%rsp), %r12
incl %r15d
cmpl 0x1c(%rsp), %r15d
jl 0x910c
jmp 0x941d
cmpl $0x6c, %eax
je 0x9333
cmpl $0x6f, %eax
jne 0x94a0
movl $0x10, %edi
callq 0x2160
movq %rax, %r12
movq %r13, %rdi
callq 0x2220
movq %rax, (%r12)
leaq 0x8(%r12), %r13
movq $0x0, 0x8(%r12)
movq %r12, (%rbx)
movq (%rsp), %r12
movq (%r12,%r14,8), %rdx
cmpb $0x0, 0x2(%rdx)
je 0x93d7
incq %rdx
movq %r13, %rbx
movq %rdx, 0x10(%rsp)
jmp 0x92c9
movl $0x10, %edi
callq 0x2160
movq %rax, %r12
movq %r13, %rdi
callq 0x2220
movq %rax, (%r12)
leaq 0x8(%r12), %r13
movq $0x0, 0x8(%r12)
movq %r12, (%rbx)
movq (%rsp), %r12
movq (%r12,%r14,8), %rdx
cmpb $0x0, 0x2(%rdx)
je 0x93b7
movq %r13, %rbx
jmp 0x92c9
cmpb $0x0, 0x2(%r13)
jne 0x94a0
movl $0x10, %edi
callq 0x2160
movq %rax, %r12
movq %r13, %rdi
callq 0x2220
movq %rax, (%r12)
movq $0x0, 0x8(%r12)
movq %r12, (%rbx)
leaq 0x8(%r12), %rbx
movl $0x3, %eax
movq %rax, 0x8(%rsp)
jmp 0x92c5
movq 0x8(%r12,%r14,8), %rbx
testq %rbx, %rbx
je 0x94b7
incl %r15d
movl $0x10, %edi
callq 0x2160
movq %rax, %r12
jmp 0x93fa
movq 0x8(%r12,%r14,8), %rbx
testq %rbx, %rbx
je 0x94b7
incl %r15d
movl $0x10, %edi
callq 0x2160
movq %rax, %r12
movq %rbx, 0x10(%rsp)
movq %rbx, %rdi
callq 0x2220
movq %rax, (%r12)
leaq 0x8(%r12), %rbx
movq $0x0, 0x8(%r12)
movq %r12, (%r13)
jmp 0x92c5
testl %ebp, %ebp
je 0x94ae
movq 0x10(%rsp), %rsi
testq %rsi, %rsi
setne %al
cmpl $0x1, %ebp
setne %cl
andb %al, %cl
movq 0x8(%rsp), %rdx
testl %edx, %edx
setne %al
andb %cl, %al
cmpb $0x1, %al
je 0x94c7
movq 0x28(%rsp), %r14
testq %r14, %r14
movq 0x30(%rsp), %r15
je 0x946b
movq %r14, %rdi
cmpl $0x4, %edx
je 0x947a
cmpl $0x1, %edx
jne 0x946d
callq 0x8d37
jmp 0x947f
xorl %edi, %edi
movq %r15, %rsi
movq %rbx, %rdx
callq 0x8e3b
jmp 0x947f
callq 0x8df8
movq %r14, %rdi
callq 0x8ccc
movq %r15, %rdi
callq 0x8ccc
xorl %eax, %eax
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x5083(%rip), %rsi      # 0xe52a
xorl %edi, %edi
movq %r13, %rdx
jmp 0x94c0
leaq 0x5131(%rip), %rsi      # 0xe5e6
jmp 0x94ce
leaq 0x5093(%rip), %rsi      # 0xe551
xorl %edi, %edi
xorl %eax, %eax
callq 0x4fa1
leaq 0x5127(%rip), %rsi      # 0xe5f5
xorl %edi, %edi
xorl %eax, %eax
callq 0x4fa1
nop