// File: fgheng[P]keysound/./include/args.hpp
// Function: process_command_line_arguments(int, char**)
static void process_command_line_arguments(int argc, char** argv) {
    if (argc <= 1) {
        usage();
        exit(EXIT_FAILURE);
    }

    int flag;
    struct option long_options[] = {
        // struct option
        // {
            // const char *name;
            // int         has_arg;
            // int        *flag;
            // int         val;
        // };
        // name: 选项名称
        // has_arg: 是否携带参数
        //     0: no_argument  无参数 --version --help
        //     1: required_argument 一个参数 --json piano.json or --json=piano.json
        //     2: optional_argument 只能按照指定格式输入 --json=piano.json
        // flag:
        //     空:
        //        当获得某个选项的时候，getopt_long返回val
        //        {"help", no_argument, 0, 'h'}, --help, getopt_long将会返回'h'
        //     非空:
        //        当获得某个长选项的时候，getopt_long将返回0，并将flag指向val。
        //        {"json", required_argument, &lopt, 'j'}，--json ./piano.json
        //        getopt_long将会返回0，同时lopt的值为j
        //
        // getopt_long返回值：
        // 1. 短选项找到，返回找到的字母
        // 2. 长选项找到：
        //    1. 如果flag为NULL，那么返回val
        //    2. 如果flag不为NULL，那么返回0，同时flag指向val
        // 3. 如果查询到的字符没有在短长中，返回?
        // 4. 结束，返回-1
        // {"file", required_argument, &flag, 'f'},
        // {"dir", required_argument, &flag, 'd'},
        // {"json", required_argument, &flag, 'j'},
        // {"log", required_argument, &flag, 'l'},


	/*English*/

	// struct option
        // {
            // const char *name;
            // int         has_arg;
            // int        *flag;
            // int         val;
        // };
	// name: option name
        // has_arg: whether to carry parameters
        // 0: no_argument no parameters --version --help
        // 1: required_argument one parameter --json piano.json or --json=piano.json
        // 2: optional_argument can only be entered in the specified format --json=piano.json
        // flag:
        // empty:
        // When an option is obtained, getopt_long returns val
        // {"help", no_argument, 0,'h'}, --help, getopt_long will return'h'
        //     non empty:
        // When a long option is obtained, getopt_long will return 0 and point the flag to val.
        // {"json", required_argument, &lopt,'j'}, --json ./piano.json
        // getopt_long will return 0, and the value of lopt will be j
        //
        // getopt_long return value:
        // 1. Short option found, return the found letter
        // 2. Long option found:
        // 1. If flag is NULL, return val
        // 2. If flag is not NULL, then return 0, and flag points to val
        // 3. If the queried character is not in the short length, return?
        // 4. End, return -1
	// {"file", required_argument, &flag, 'f'},
        // {"dir", required_argument, &flag, 'd'},
        // {"json", required_argument, &flag, 'j'},
        // {"log", required_argument, &flag, 'l'},


        {"file", required_argument, 0, 'f'},
        {"dir", required_argument, 0, 'd'},
        {"json", required_argument, 0, 'j'},
        {"log", required_argument, 0, 'l'},
        {"daemon", no_argument, 0, 'D'},
        {"kill", no_argument, 0, 'k'},
        {"help", no_argument, 0, '?'},
        {0, 0, 0, 0}
    };

    int c;
    while ((c = getopt_long(argc, argv, "kh?d:f:j:l:D", long_options, 0)) != -1) {
        switch (c) {
            case 'd':
                args.dir = std::string(optarg);
                if (args.flag != 0) {
                    usage();
                    exit(EXIT_FAILURE);
                }
                else args.flag = 'd';
                break;
            case 'f':
                args.wav_file = std::string(optarg);
                if (args.flag != 0) {
                    usage();
                    exit(EXIT_FAILURE);
                } else args.flag = 'f';
                break;
            case 'j':
                args.json = std::string(optarg);
                if (args.flag != 0) {
                    usage();
                    exit(EXIT_FAILURE);
                }
                else args.flag = 'j';
                break;
            case 'l':
                args.log = std::string(optarg);
                break;
            case 'D':
                args.daemon = true;
                break;
            case 'k':
                args.kill = true;
                break;
            case 'h':
            case '?':
            default:
                usage();
                exit(EXIT_FAILURE);
                break;
        }
    }

    if (args.flag == 0 && !args.kill) {
        usage();
        exit(EXIT_FAILURE);
    }

    while (optind < argc)
        std::cout <<  "Non-option argument " << argv[optind++] << std::endl;

}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x220, %rsp            # imm = 0x220
movl %edi, -0x4(%rbp)
movq %rsi, -0x10(%rbp)
cmpl $0x1, -0x4(%rbp)
jg 0x127e7
callq 0x12fb0
movl $0x1, %edi
callq 0x4480
leaq -0x120(%rbp), %rdi
leaq 0xc3db(%rip), %rsi      # 0x1ebd0
movl $0x100, %edx            # imm = 0x100
callq 0x42e0
movl -0x4(%rbp), %edi
movq -0x10(%rbp), %rsi
leaq -0x120(%rbp), %rcx
leaq 0x42bc(%rip), %rdx      # 0x16ad0
xorl %eax, %eax
movl %eax, %r8d
callq 0x4610
movl %eax, -0x124(%rbp)
cmpl $-0x1, %eax
je 0x12b46
movl -0x124(%rbp), %eax
addl $-0x3f, %eax
movl %eax, %ecx
movq %rcx, -0x1e0(%rbp)
subl $0x2d, %eax
ja 0x12b32
movq -0x1e0(%rbp), %rax
leaq 0x419e(%rip), %rcx      # 0x169f4
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq 0xc72a(%rip), %rax      # 0x1ef90
movq (%rax), %rax
movq %rax, -0x1f0(%rbp)
leaq -0x149(%rbp), %rdi
movq %rdi, -0x1e8(%rbp)
callq 0x4680
movq -0x1f0(%rbp), %rsi
movq -0x1e8(%rbp), %rdx
leaq -0x148(%rbp), %rdi
callq 0x93e0
jmp 0x1289f
leaq 0xf3d2(%rip), %rdi      # 0x21c78
addq $0x48, %rdi
leaq -0x148(%rbp), %rsi
callq 0x4490
leaq -0x148(%rbp), %rdi
callq 0x4728
leaq -0x149(%rbp), %rdi
callq 0x4420
cmpl $0x0, 0xf3a3(%rip)      # 0x21c78
je 0x12909
callq 0x12fb0
movl $0x1, %edi
callq 0x4480
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x158(%rbp)
movl %eax, -0x15c(%rbp)
leaq -0x149(%rbp), %rdi
callq 0x4420
jmp 0x12bce
movl $0x64, 0xf365(%rip)     # 0x21c78
jmp 0x12b41
movq 0xc671(%rip), %rax      # 0x1ef90
movq (%rax), %rax
movq %rax, -0x200(%rbp)
leaq -0x181(%rbp), %rdi
movq %rdi, -0x1f8(%rbp)
callq 0x4680
movq -0x200(%rbp), %rsi
movq -0x1f8(%rbp), %rdx
leaq -0x180(%rbp), %rdi
callq 0x93e0
jmp 0x12958
leaq 0xf319(%rip), %rdi      # 0x21c78
addq $0x28, %rdi
leaq -0x180(%rbp), %rsi
callq 0x4490
leaq -0x180(%rbp), %rdi
callq 0x4728
leaq -0x181(%rbp), %rdi
callq 0x4420
cmpl $0x0, 0xf2ea(%rip)      # 0x21c78
je 0x129c2
callq 0x12fb0
movl $0x1, %edi
callq 0x4480
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x158(%rbp)
movl %eax, -0x15c(%rbp)
leaq -0x181(%rbp), %rdi
callq 0x4420
jmp 0x12bce
movl $0x66, 0xf2ac(%rip)     # 0x21c78
jmp 0x12b41
movq 0xc5b8(%rip), %rax      # 0x1ef90
movq (%rax), %rax
movq %rax, -0x210(%rbp)
leaq -0x1a9(%rbp), %rdi
movq %rdi, -0x208(%rbp)
callq 0x4680
movq -0x210(%rbp), %rsi
movq -0x208(%rbp), %rdx
leaq -0x1a8(%rbp), %rdi
callq 0x93e0
jmp 0x12a11
leaq 0xf260(%rip), %rdi      # 0x21c78
addq $0x8, %rdi
leaq -0x1a8(%rbp), %rsi
callq 0x4490
leaq -0x1a8(%rbp), %rdi
callq 0x4728
leaq -0x1a9(%rbp), %rdi
callq 0x4420
cmpl $0x0, 0xf231(%rip)      # 0x21c78
je 0x12a7b
callq 0x12fb0
movl $0x1, %edi
callq 0x4480
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x158(%rbp)
movl %eax, -0x15c(%rbp)
leaq -0x1a9(%rbp), %rdi
callq 0x4420
jmp 0x12bce
movl $0x6a, 0xf1f3(%rip)     # 0x21c78
jmp 0x12b41
movq 0xc4ff(%rip), %rax      # 0x1ef90
movq (%rax), %rax
movq %rax, -0x220(%rbp)
leaq -0x1d1(%rbp), %rdi
movq %rdi, -0x218(%rbp)
callq 0x4680
movq -0x220(%rbp), %rsi
movq -0x218(%rbp), %rdx
leaq -0x1d0(%rbp), %rdi
callq 0x93e0
jmp 0x12aca
leaq 0xf1a7(%rip), %rdi      # 0x21c78
addq $0x68, %rdi
leaq -0x1d0(%rbp), %rsi
callq 0x4490
leaq -0x1d0(%rbp), %rdi
callq 0x4728
leaq -0x1d1(%rbp), %rdi
callq 0x4420
jmp 0x12b41
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x158(%rbp)
movl %eax, -0x15c(%rbp)
leaq -0x1d1(%rbp), %rdi
callq 0x4420
jmp 0x12bce
movb $0x1, 0xf157(%rip)      # 0x21c7c
jmp 0x12b41
movb $0x1, 0xf14f(%rip)      # 0x21c7d
jmp 0x12b41
jmp 0x12b32
callq 0x12fb0
movl $0x1, %edi
callq 0x4480
jmp 0x127ff
cmpl $0x0, 0xf12b(%rip)      # 0x21c78
jne 0x12b67
testb $0x1, 0xf127(%rip)      # 0x21c7d
jne 0x12b67
callq 0x12fb0
movl $0x1, %edi
callq 0x4480
jmp 0x12b69
movq 0xc458(%rip), %rax      # 0x1efc8
movl (%rax), %eax
cmpl -0x4(%rbp), %eax
jge 0x12bc5
movq 0xc43a(%rip), %rdi      # 0x1efb8
leaq 0x3f58(%rip), %rsi      # 0x16add
callq 0x43a0
movq %rax, %rdi
movq -0x10(%rbp), %rax
movq 0xc430(%rip), %rcx      # 0x1efc8
movl (%rcx), %ecx
movl %ecx, %esi
addl $0x1, %esi
movq 0xc422(%rip), %rdx      # 0x1efc8
movl %esi, (%rdx)
movslq %ecx, %rcx
movq (%rax,%rcx,8), %rsi
callq 0x43a0
movq %rax, %rdi
movq 0xc3ca(%rip), %rsi      # 0x1ef88
callq 0x4400
jmp 0x12b69
addq $0x220, %rsp            # imm = 0x220
popq %rbp
retq
movq -0x158(%rbp), %rdi
callq 0x4670
nopw (%rax,%rax)