// File: /workspace/github_c_makefile_star2_O2/salextpuru[P]speccy-toochain/src/mhmt/mhmt-parsearg.c
// Function: parse_args
ULONG parse_args(int argc, char* argv[])
{
    struct argtbl argstore[ARG_STORE_SIZE+1]; // last element is always stop-value
    struct argtbl * arg;
    ULONG inarg_pos; // position in argv[] array
    ULONG storearg_pos; // position in argstore[] array
    ULONG files_num; // number of filenames specified
    char * temp_filename;
    ULONG last_arg_type;
    ULONG maxwin;
    ULONG i;

    for(i=0; i<ARG_STORE_SIZE+1; i++) {
        argstore[i].name = NULL;
        argstore[i].type = ARG_NOARG;
    }

    if( argc<2 ) {
        printf("No arguments! Use \"mhmt -h\" or \"mhmt -help\" for help!\n");
        return 0L;
    }

    // shortcut for help request
    if( !cmp_str_nocase( argv[1]+1, "h" ) || !cmp_str_nocase( argv[1]+1, "help" ) )
        return ARG_PARSER_SHOWHELP;

    inarg_pos = 1;
    storearg_pos = 0;
    files_num = 0;

    // first find all arguments beginning with "-"
    while( inarg_pos<(ULONG)argc && *(argv[inarg_pos])=='-' ) {
        arg=match_arg(argv[inarg_pos]+1); // search match...

        if( arg ) { // match!
            if( storearg_pos>=ARG_STORE_SIZE ) {
                printf("Too many arguments!\n");
                return ARG_PARSER_ERROR|ARG_PARSER_SHOWHELP;
            }

            argstore[storearg_pos++] = *arg;

        } else { // argument does not match predefined set
            printf("Wrong arguments!\n");
            return ARG_PARSER_ERROR|ARG_PARSER_SHOWHELP;
        }

        inarg_pos++;
    }

    // parse filenames then
    while( inarg_pos<(ULONG)argc ) {
        if( files_num>=2 ) { // there should be no more than two filenames
            printf("Too many filenames specified!\n");
            return ARG_PARSER_ERROR|ARG_PARSER_SHOWHELP;
        }

        temp_filename = (char *)malloc( 1+strlen(argv[inarg_pos]) );

        if( !temp_filename ) {
            printf("Cannot allocate memory for filename string!\n");
            return ARG_PARSER_ERROR;
        }

        strcpy( temp_filename, argv[inarg_pos] );

        if( files_num==0 )
            wrk.fname_in = temp_filename;

        else // only files_num==1, because of condition in the beginning of current "while" cycle
            wrk.fname_out = temp_filename;

        files_num++;
        inarg_pos++;
    }

    if( !files_num ) { // there must be at least 1 filename specified
        printf("No filenames specified!\n");
        return ARG_PARSER_ERROR|ARG_PARSER_SHOWHELP;
    }

    // now optional arguments (starting with "-") are stored in argstore[],
    // all needed filenames are also copied, go proceed configuring with
    // optional arguments
    // sort argument array (in increasing .type order) to ensure correct parsing
    sort_args( argstore, ARG_STORE_SIZE );
    storearg_pos = 0;
    last_arg_type = ARG_INIT; // there is no such value in argstore[].type

    while( argstore[storearg_pos].type != ARG_NOARG ) {
        if( last_arg_type == argstore[storearg_pos].type ) {
            printf("Redundant arguments!\n");
            return ARG_PARSER_ERROR|ARG_PARSER_SHOWHELP;
        }

        switch( argstore[storearg_pos].type ) {
        case ARG_MODE:
            wrk.mode = 1; // set depack mode
            break;

        case ARG_GREEDY:
            if( wrk.mode ) { // since sorted, argument list causes parsing go from up to down in this "case" list
                printf("No greedy mode specification for DEpacking!\n");
                return ARG_PARSER_ERROR;
            }

            wrk.greedy = 1; // set greedy packing mode
            break;

        case ARG_PTYPE:
            if( !cmp_str_nocase( argstore[storearg_pos].name, ARGSTR_MEGALZ ) ) {
                wrk.packtype = PK_MLZ;
                wrk.zxheader = 0;
                wrk.wordbit  = 0;
                wrk.bigend   = 0;
                wrk.fullbits = 0;
                wrk.maxwin   = 4352;

            } else if( !cmp_str_nocase( argstore[storearg_pos].name, ARGSTR_HRUM ) ) {
                wrk.packtype = PK_HRM;
                wrk.zxheader = 0; // by default, there is NO ZX-HEADER if only -hrm or -hst specified
                wrk.wordbit  = 1;
                wrk.bigend   = 0;
                wrk.fullbits = 1;
                wrk.maxwin   = 4096;

            } else if( !cmp_str_nocase( argstore[storearg_pos].name, ARGSTR_HRUST ) ) {
                wrk.packtype = PK_HST;
                wrk.zxheader = 0; // by default, there is NO ZX-HEADER if only -hrm or -hst specified
                wrk.wordbit  = 1;
                wrk.bigend   = 0;
                wrk.fullbits = 1;
                wrk.maxwin   = 65536;

            } else { // there shouldn't be this case, but nevertheless...
                printf("Impossible error #1! Press any key to continue or \"SPACE\" to exit... :-)\n");
                return ARG_PARSER_ERROR;
            }

            break;

        case ARG_ZXHEAD:

            // ZX-header is not applicable for PK_MLZ type...
            // also wrk.packtype has been already set before...
            if( PK_MLZ==wrk.packtype ) {
                printf("There couldn't be zx-header in megalz mode!\n");
                return ARG_PARSER_ERROR;
            }

            wrk.zxheader = 1;
            break;

        case ARG_WORD:

            // whether bits must be grouped in words or in bytes
            if( !cmp_str_nocase( argstore[storearg_pos].name, ARGSTR_8 ) ) {
                if( wrk.zxheader ) { // won't force byte-wise bits when there is a zx-header
                    printf("There can be only 16bit grouping of bits when ZX-header is active!\n");
                    return ARG_PARSER_ERROR;
                }

                wrk.wordbit = 0;

            } else if( !cmp_str_nocase( argstore[storearg_pos].name, ARGSTR_16 ) ) {
                wrk.wordbit = 1;

            } else { // there shouldn't be this case, but nevertheless...
                printf("Impossible error #2! Press any key to continue or \"SPACE\" to exit... :-)\n");
                return ARG_PARSER_ERROR;
            }

            break;

        case ARG_BIGEND:

            // whether word-grouped bits must be big- or little-endian arranged
            if( wrk.zxheader ) {
                printf("There can be only little-endian arrangement of bits when ZX-header is active!\n");
                return ARG_PARSER_ERROR;
            }

            wrk.bigend = 1;
            break;

        case ARG_MAXWIN:
            maxwin = get_maxwin( argstore[storearg_pos].name );

            if( !maxwin ) { // there shouldn't be this case, but nevertheless...
                printf("Impossible error #3! Press any key to continue or \"SPACE\" to exit... :-)\n");
                return ARG_PARSER_ERROR;
            }

            // wrk.maxwin is already initialized to the maximum value suitable for given packing type, so check new setting
            if( maxwin > wrk.maxwin ) {
                printf("Maximum window specified is too big for given packing type!\n");
                return ARG_PARSER_ERROR;
            }

            wrk.maxwin = maxwin;
            break;

        default:
            // once again impossible error: we shouldn't be here since "while" loop condition...
            printf("Impossible error #4! Press any key to continue or \"SPACE\" to exit... :-)\n");
            return ARG_PARSER_ERROR;
            break;
        }

        last_arg_type = argstore[storearg_pos++].type;
    }

    return ARG_PARSER_GO;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x128, %rsp            # imm = 0x128
movq %rsi, %r14
movl %edi, %r15d
pushq $0x8
popq %rax
cmpq $0x118, %rax            # imm = 0x118
je 0x31d6
andq $0x0, 0x8(%rsp,%rax)
movl $0xff, 0x10(%rsp,%rax)
addq $0x10, %rax
jmp 0x31ba
cmpl $0x2, %r15d
jge 0x31f5
xorl %ebp, %ebp
leaq 0x30de(%rip), %rbx      # 0x62c3
movq %rbx, %rdi
callq 0x1110
movl %ebp, %r12d
jmp 0x3591
movq 0x8(%r14), %rbx
incq %rbx
leaq 0x2d5d(%rip), %rsi      # 0x5f60
movq %rbx, %rdi
callq 0x362d
pushq $0x1
popq %r12
testl %eax, %eax
je 0x3591
leaq 0x2dbb(%rip), %rsi      # 0x5fd9
movq %rbx, %rdi
callq 0x362d
testl %eax, %eax
je 0x3591
leal -0x1(%r15), %r12d
shlq $0x3, %r12
pushq $0x1
popq %rbx
xorl %r13d, %r13d
movl $0x101, %ebp            # imm = 0x101
cmpq %r13, %r12
je 0x327f
movq 0x8(%r14,%r13), %rdi
cmpb $0x2d, (%rdi)
jne 0x3282
incq %rdi
callq 0x369e
testq %rax, %rax
je 0x32e7
cmpq $0x80, %r13
je 0x32f3
movups (%rax), %xmm0
movups %xmm0, 0x10(%rsp,%r13,2)
incl %ebx
addq $0x8, %r13
jmp 0x3241
movl %r15d, %ebx
movl %ebx, %r12d
movl %r15d, %ebp
leaq (%r14,%r12,8), %rbx
xorl %r13d, %r13d
leaq (%r12,%r13), %rax
cmpq %rbp, %rax
jae 0x32ff
cmpl $0x2, %r13d
je 0x35a6
movq (%rbx,%r13,8), %r14
movq %r14, %rdi
callq 0x1050
leaq 0x1(%rax), %rdi
callq 0x10d0
testq %rax, %rax
je 0x35b7
movq %rax, %r15
movq %rax, %rdi
movq %r14, %rsi
callq 0x1060
xorl %eax, %eax
testl %r13d, %r13d
setne %al
leaq 0x7043(%rip), %rcx      # 0xa320
movq %r15, 0x20(%rcx,%rax,8)
incq %r13
jmp 0x328f
leaq 0x2fb0(%rip), %rbx      # 0x629e
jmp 0x31e5
leaq 0x2fb5(%rip), %rbx      # 0x62af
jmp 0x31e5
movl $0x101, %ebp            # imm = 0x101
testl %r13d, %r13d
je 0x35c8
leaq 0x10(%rsp), %rdi
pushq $0x10
popq %rsi
callq 0x36d3
leaq 0x6fff(%rip), %rax      # 0xa320
movl 0x1c(%rax), %ecx
movl %ecx, (%rsp)
movl 0xc(%rax), %esi
movl (%rax), %ecx
movl %ecx, 0x4(%rsp)
movl 0x8(%rax), %eax
movl %eax, 0x8(%rsp)
xorl %r14d, %r14d
pushq $0x2
popq %r12
leaq 0x2efa(%rip), %rbx      # 0x623f
leaq 0x2bf4(%rip), %rdx      # 0x5f40
xorl %r15d, %r15d
movl %r15d, %ecx
movl %r14d, %eax
shlq $0x4, %rax
movl 0x18(%rsp,%rax), %r15d
cmpl $0xff, %r15d
je 0x3591
cmpl %r15d, %ecx
je 0x31e5
leal -0x1(%r15), %ecx
cmpl $0x6, %ecx
ja 0x35d4
addq %rsp, %rax
addq $0x10, %rax
movslq (%rdx,%rcx,4), %rcx
addq %rdx, %rcx
jmpq *%rcx
leaq 0x6f88(%rip), %rax      # 0xa320
movl $0x1, 0x8(%rax)
pushq $0x1
popq %rax
movl %eax, 0x8(%rsp)
jmp 0x3589
movl %esi, 0xc(%rsp)
movq (%rax), %rdi
movq %rdi, %r13
leaq 0x2bd6(%rip), %rsi      # 0x5f92
callq 0x362d
testl %eax, %eax
je 0x350e
movq %r13, %rdi
leaq 0x2b8f(%rip), %rsi      # 0x5f62
callq 0x362d
testl %eax, %eax
jne 0x360a
leaq 0x6f39(%rip), %rax      # 0xa320
movl $0x1, 0x10(%rax)
leaq 0x2b4b(%rip), %rdx      # 0x5f40
movl 0xc(%rsp), %esi
jmp 0x3589
movq (%rax), %r13
movq %r13, %rdi
leaq 0x2220(%rip), %rsi      # 0x562b
callq 0x362d
testl %eax, %eax
je 0x3528
movq %r13, %rdi
leaq 0x220e(%rip), %rsi      # 0x5630
callq 0x362d
testl %eax, %eax
je 0x3555
movq %r13, %rdi
leaq 0x21fc(%rip), %rsi      # 0x5635
callq 0x362d
testl %eax, %eax
jne 0x3613
leaq 0x6ed3(%rip), %rax      # 0xa320
movl $0x3, (%rax)
movaps 0x2ac6(%rip), %xmm0     # 0x5f20
movups %xmm0, 0xc(%rax)
movl $0x10000, 0x1c(%rax)    # imm = 0x10000
movl $0x10000, (%rsp)        # imm = 0x10000
xorl %esi, %esi
pushq $0x3
jmp 0x354e
cmpl $0x1, 0x4(%rsp)
je 0x35ef
leaq 0x6e99(%rip), %rax      # 0xa320
movl $0x1, 0xc(%rax)
pushq $0x1
popq %rsi
jmp 0x3589
cmpl $0x0, 0x8(%rsp)
jne 0x35f8
leaq 0x6e78(%rip), %rax      # 0xa320
movl $0x1, 0x4(%rax)
movl $0x0, 0x8(%rsp)
jmp 0x3589
testl %esi, %esi
jne 0x35dd
leaq 0x6e55(%rip), %rax      # 0xa320
movl $0x1, 0x14(%rax)
xorl %esi, %esi
jmp 0x3589
movl %esi, %r13d
movq (%rax), %rdi
callq 0x371a
testl %eax, %eax
je 0x35e6
cmpl (%rsp), %eax
ja 0x3601
leaq 0x6e24(%rip), %rcx      # 0xa320
movl %eax, 0x1c(%rcx)
movl %eax, (%rsp)
leaq 0x2a37(%rip), %rdx      # 0x5f40
movl %r13d, %esi
jmp 0x3589
cmpl $0x0, 0xc(%rsp)
jne 0x361c
leaq 0x6e00(%rip), %rax      # 0xa320
andl $0x0, 0x10(%rax)
xorl %esi, %esi
jmp 0x3582
leaq 0x6df1(%rip), %rax      # 0xa320
movl $0x1, (%rax)
xorps %xmm0, %xmm0
movups %xmm0, 0xc(%rax)
movl $0x1100, 0x1c(%rax)     # imm = 0x1100
movl $0x1100, (%rsp)         # imm = 0x1100
xorl %esi, %esi
pushq $0x1
popq %rax
movl %eax, 0x4(%rsp)
jmp 0x3582
leaq 0x6dc4(%rip), %rax      # 0xa320
movl $0x2, (%rax)
movaps 0x29b7(%rip), %xmm0     # 0x5f20
movups %xmm0, 0xc(%rax)
movl $0x1000, 0x1c(%rax)     # imm = 0x1000
movl $0x1000, (%rsp)         # imm = 0x1000
xorl %esi, %esi
movl %r12d, 0x4(%rsp)
leaq 0x29b7(%rip), %rdx      # 0x5f40
incl %r14d
jmp 0x334f
movl %r12d, %eax
addq $0x128, %rsp            # imm = 0x128
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl $0x101, %ebp            # imm = 0x101
leaq 0x2cce(%rip), %rbx      # 0x6280
jmp 0x31e5
movl $0x100, %ebp            # imm = 0x100
leaq 0x2c91(%rip), %rbx      # 0x6254
jmp 0x31e5
leaq 0x2a0f(%rip), %rbx      # 0x5fde
jmp 0x31e5
leaq 0x2c1b(%rip), %rbx      # 0x61f6
jmp 0x3623
leaq 0x2a97(%rip), %rbx      # 0x607b
jmp 0x3623
leaq 0x2a09(%rip), %rbx      # 0x5ff6
jmp 0x3623
leaq 0x2b5f(%rip), %rbx      # 0x6155
jmp 0x3623
leaq 0x2bcb(%rip), %rbx      # 0x61ca
jmp 0x3623
leaq 0x2a37(%rip), %rbx      # 0x603f
jmp 0x3623
leaq 0x2afb(%rip), %rbx      # 0x610c
jmp 0x3623
leaq 0x2b67(%rip), %rbx      # 0x6181
jmp 0x3623
leaq 0x2aa6(%rip), %rbx      # 0x60c9
movl $0x100, %ebp            # imm = 0x100
jmp 0x31e5