// File: ridiculousfish[P]docopt_fish/docopt_fish.cpp
// Function: docopt_fish::argv_classifier_t::parse_unseparated_short_options(std::vector<docopt_fish::error_t, std::allocator<docopt_fish::error_t>>*)
bool argv_classifier_t::parse_unseparated_short_options(error_list_t *out_errors) {
    const string_t &arg = this->arg();
    assert(this->arg_has_prefix("-"));
    assert(arg.length() > 1);  // must not be just a single dash
    bool errored = false;
    bool last_option_has_argument = false;

    // Construct the list of options in-order, corresponding to this argument
    std::vector<option_t> options_for_argument;

    // walk over the characters in the argument, skipping the leading dash
    for (size_t idx_in_arg = 1; idx_in_arg < arg.length() && !errored; idx_in_arg++) {
        // Get list of short options matching this resolved option.
        const rstring_t::char_t short_char = arg.at(idx_in_arg);
        const option_list_t matches = this->filter_options([&](const option_t &opt) {
            // This is a short option (-D) so we check the second character (idx 1)
            const rstring_t &name = opt.names[option_t::single_short];
            return name.length() > 1 && name[1] == short_char;
        });
        
        size_t match_count = matches.size();
        // We should catch all duplicates during the preflight phase
        assert(match_count <= 1);
        if (match_count < 1) {
            this->error(out_errors, error_unknown_option, "Unknown short option",
                              idx_in_arg);
            errored = true;
        } else {
            // Just one match, add it to the global array
            options_for_argument.push_back(matches.at(0));
        }
    }

    if (!errored) {
        // Now we have all of the short options that this argument represents. No
        // option is allowed to have a value, except possibly the last one.
        for (size_t i = 0; i < options_for_argument.size(); i++) {
            const option_t &opt = options_for_argument.at(i);
            if (opt.has_value()) {
                if (i + 1 == options_for_argument.size()) {
                    // This is the last option
                    last_option_has_argument = true;
                } else {
                    // This is not the last option
                    // This i+1 is the position in the argument and needs some
                    // explanation. We have a leading dash and then an argument,
                    // which is parsed into short options - one per character, including
                    // the dash. Hence we can map from index-in-option to index-in-argument,
                    // unless there was an unknown option error above. In that case this
                    // will be wrong (but we typically only show the first error anyways)
                    this->error(out_errors, error_option_unexpected_argument,
                                      "Option may not have a value unless it is the last option",
                                      i + 1);
                    errored = true;
                }
            }
        }
    }

    // If we have an argument, determine the index of its name and its value
    rstring_t value_for_last_option;
    const size_t name_idx = this->idx;
    size_t val_idx_for_last_option = npos;
    if (!errored && last_option_has_argument) {
        // We don't support -f=bar style for short options.
        // TODO: support delimiter-free style (gcc -Dmacro=something)
        if (this->idx + 1 < this->argv.size()) {
            val_idx_for_last_option = this->idx + 1;
            value_for_last_option = rstring_t(this->argv.at(this->idx + 1));
        } else {
            // We are at the last argument, and we expect a value. Return the value as
            // a suggestion.
            this->suggest(options_for_argument.back().value);
            this->error(out_errors, error_option_has_missing_argument,
                              "Option expects an argument");
            errored = true;
        }
    }

    if (!errored) {
        // Construct resolved options
        for (size_t i = 0; i < options_for_argument.size(); i++) {
            // Most options have no value.
            size_t val_idx = npos;
            rstring_t value;
            if (i + 1 == options_for_argument.size() && last_option_has_argument) {
                // This is the last option
                value = value_for_last_option;
                val_idx = val_idx_for_last_option;
            }
            const option_t &opt = options_for_argument.at(i);
            this->classification.resolved_options.emplace_back(opt, name_idx, val_idx, value);
        }

        // Update the index
        this->idx += (last_option_has_argument ? 2 : 1);
    }
    return !errored;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x180, %rsp            # imm = 0x180
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x8(%rbp), %rdi
movq %rdi, -0x108(%rbp)
callq 0xc6f0
movq -0x108(%rbp), %rdi
movq %rax, -0x18(%rbp)
leaq 0x44dbf(%rip), %rsi     # 0x4e734
callq 0xc720
testb $0x1, %al
jne 0x9980
jmp 0x9982
jmp 0x99a1
leaq 0x41a0f(%rip), %rdi     # 0x4b398
leaq 0x416f8(%rip), %rsi     # 0x4b088
movl $0x256, %edx            # imm = 0x256
leaq 0x41a16(%rip), %rcx     # 0x4b3b2
callq 0x81e0
movq -0x18(%rbp), %rdi
callq 0x85a0
cmpq $0x1, %rax
jbe 0x99b2
jmp 0x99d1
leaq 0x41a4e(%rip), %rdi     # 0x4b407
leaq 0x416c8(%rip), %rsi     # 0x4b088
movl $0x257, %edx            # imm = 0x257
leaq 0x419e6(%rip), %rcx     # 0x4b3b2
callq 0x81e0
movb $0x0, -0x19(%rbp)
movb $0x0, -0x1a(%rbp)
leaq -0x38(%rbp), %rdi
callq 0xca90
movq $0x1, -0x40(%rbp)
movq -0x40(%rbp), %rax
movq %rax, -0x118(%rbp)
movq -0x18(%rbp), %rdi
callq 0x85a0
movq -0x118(%rbp), %rcx
movq %rax, %rdx
xorl %eax, %eax
cmpq %rdx, %rcx
movb %al, -0x109(%rbp)
jae 0x9a20
movb -0x19(%rbp), %al
xorb $-0x1, %al
movb %al, -0x109(%rbp)
movb -0x109(%rbp), %al
testb $0x1, %al
jne 0x9a2f
jmp 0x9b42
movq -0x18(%rbp), %rdi
movq -0x40(%rbp), %rsi
callq 0x8630
movq %rax, -0x120(%rbp)
jmp 0x9a45
movq -0x108(%rbp), %rsi
movq -0x120(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x44(%rbp)
leaq -0x44(%rbp), %rax
movq %rax, -0x78(%rbp)
leaq -0x70(%rbp), %rdi
leaq -0x78(%rbp), %rdx
callq 0x9f00
jmp 0x9a6f
leaq -0x70(%rbp), %rdi
callq 0xcab0
movq %rax, -0x80(%rbp)
cmpq $0x1, -0x80(%rbp)
ja 0x9a85
jmp 0x9ab5
leaq 0x4198c(%rip), %rdi     # 0x4b418
leaq 0x415f5(%rip), %rsi     # 0x4b088
movl $0x26a, %edx            # imm = 0x26A
leaq 0x41913(%rip), %rcx     # 0x4b3b2
callq 0x81e0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
jmp 0x9ee7
cmpq $0x1, -0x80(%rbp)
jae 0x9afe
movq -0x108(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x40(%rbp), %r8
leaq 0x41957(%rip), %rcx     # 0x4b429
movl $0x67, %edx
callq 0xc880
jmp 0x9ade
movb $0x1, -0x19(%rbp)
jmp 0x9b28
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x50(%rbp)
movl %eax, -0x54(%rbp)
leaq -0x70(%rbp), %rdi
callq 0xcb80
jmp 0x9ee7
xorl %eax, %eax
movl %eax, %esi
leaq -0x70(%rbp), %rdi
callq 0xcb40
movq %rax, -0x128(%rbp)
jmp 0x9b14
movq -0x128(%rbp), %rsi
leaq -0x38(%rbp), %rdi
callq 0xcad0
jmp 0x9b26
jmp 0x9b28
leaq -0x70(%rbp), %rdi
callq 0xcb80
movq -0x40(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x40(%rbp)
jmp 0x99ea
testb $0x1, -0x19(%rbp)
jne 0x9c41
movq $0x0, -0x88(%rbp)
movq -0x88(%rbp), %rax
movq %rax, -0x130(%rbp)
leaq -0x38(%rbp), %rdi
callq 0xcab0
movq %rax, %rcx
movq -0x130(%rbp), %rax
cmpq %rcx, %rax
jae 0x9c3f
movq -0x88(%rbp), %rsi
leaq -0x38(%rbp), %rdi
callq 0xcbe0
movq %rax, -0x138(%rbp)
jmp 0x9b9a
movq -0x138(%rbp), %rax
movq %rax, -0x90(%rbp)
movq -0x90(%rbp), %rdi
callq 0xc8e0
movb %al, -0x139(%rbp)
jmp 0x9bbc
movb -0x139(%rbp), %al
testb $0x1, %al
jne 0x9bc8
jmp 0x9c26
movq -0x88(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x148(%rbp)
leaq -0x38(%rbp), %rdi
callq 0xcab0
movq %rax, %rcx
movq -0x148(%rbp), %rax
cmpq %rcx, %rax
jne 0x9bf8
movb $0x1, -0x1a(%rbp)
jmp 0x9c24
movq -0x108(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq -0x88(%rbp), %r8
incq %r8
leaq 0x4182a(%rip), %rcx     # 0x4b43e
movl $0x65, %edx
callq 0xc880
jmp 0x9c20
movb $0x1, -0x19(%rbp)
jmp 0x9c26
jmp 0x9c28
movq -0x88(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x88(%rbp)
jmp 0x9b57
jmp 0x9c41
leaq -0xa8(%rbp), %rdi
callq 0xbe70
jmp 0x9c4f
movq -0x108(%rbp), %rax
movq 0x20(%rax), %rax
movq %rax, -0xb0(%rbp)
movq $-0x1, -0xb8(%rbp)
testb $0x1, -0x19(%rbp)
jne 0x9d6d
testb $0x1, -0x1a(%rbp)
je 0x9d6d
movq -0x108(%rbp), %rax
movq 0x20(%rax), %rcx
addq $0x1, %rcx
movq %rcx, -0x150(%rbp)
movq (%rax), %rdi
callq 0xc910
movq %rax, %rcx
movq -0x150(%rbp), %rax
cmpq %rcx, %rax
jae 0x9d26
movq -0x108(%rbp), %rax
movq 0x20(%rax), %rcx
incq %rcx
movq %rcx, -0xb8(%rbp)
movq (%rax), %rdi
movq 0x20(%rax), %rsi
incq %rsi
callq 0xc930
movq %rax, -0x158(%rbp)
jmp 0x9cda
movq -0x158(%rbp), %rsi
xorl %eax, %eax
movl %eax, %edx
leaq -0xd0(%rbp), %rdi
movq $-0x1, %rcx
callq 0xc430
jmp 0x9cfa
movq -0xd0(%rbp), %rax
movq %rax, -0xa8(%rbp)
movq -0xc8(%rbp), %rax
movq %rax, -0xa0(%rbp)
movq -0xc0(%rbp), %rax
movq %rax, -0x98(%rbp)
jmp 0x9d6b
leaq -0x38(%rbp), %rdi
callq 0xcc20
movq -0x108(%rbp), %rdi
movq %rax, %rsi
addq $0x48, %rsi
callq 0xc970
jmp 0x9d44
movq -0x108(%rbp), %rdi
movq -0x10(%rbp), %rsi
leaq 0x41586(%rip), %rcx     # 0x4b2dc
xorl %eax, %eax
movl %eax, %r8d
movl $0x64, %edx
callq 0xc880
jmp 0x9d67
movb $0x1, -0x19(%rbp)
jmp 0x9d6d
testb $0x1, -0x19(%rbp)
jne 0x9ec2
movq $0x0, -0xd8(%rbp)
movq -0xd8(%rbp), %rax
movq %rax, -0x160(%rbp)
leaq -0x38(%rbp), %rdi
callq 0xcab0
movq %rax, %rcx
movq -0x160(%rbp), %rax
cmpq %rcx, %rax
jae 0x9e9b
movq $-0x1, -0xe0(%rbp)
leaq -0xf8(%rbp), %rdi
callq 0xbe70
jmp 0x9dc5
movq -0xd8(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x168(%rbp)
leaq -0x38(%rbp), %rdi
callq 0xcab0
movq %rax, %rcx
movq -0x168(%rbp), %rax
cmpq %rcx, %rax
jne 0x9e2d
testb $0x1, -0x1a(%rbp)
je 0x9e2d
movq -0xa8(%rbp), %rax
movq %rax, -0xf8(%rbp)
movq -0xa0(%rbp), %rax
movq %rax, -0xf0(%rbp)
movq -0x98(%rbp), %rax
movq %rax, -0xe8(%rbp)
movq -0xb8(%rbp), %rax
movq %rax, -0xe0(%rbp)
movq -0xd8(%rbp), %rsi
leaq -0x38(%rbp), %rdi
callq 0xcbe0
movq %rax, -0x170(%rbp)
jmp 0x9e46
movq -0x108(%rbp), %rdi
movq -0x170(%rbp), %rax
movq %rax, -0x100(%rbp)
addq $0x40, %rdi
movq -0x100(%rbp), %rsi
leaq -0xb0(%rbp), %rdx
leaq -0xe0(%rbp), %rcx
leaq -0xf8(%rbp), %r8
callq 0xc9f0
jmp 0x9e82
jmp 0x9e84
movq -0xd8(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xd8(%rbp)
jmp 0x9d82
movq -0x108(%rbp), %rax
movb -0x1a(%rbp), %sil
movl $0x1, %ecx
movl $0x2, %edx
testb $0x1, %sil
cmovnel %edx, %ecx
movslq %ecx, %rcx
addq 0x20(%rax), %rcx
movq %rcx, 0x20(%rax)
movb -0x19(%rbp), %al
xorb $-0x1, %al
movb %al, -0x171(%rbp)
leaq -0x38(%rbp), %rdi
callq 0xcb80
movb -0x171(%rbp), %al
andb $0x1, %al
addq $0x180, %rsp            # imm = 0x180
popq %rbp
retq
leaq -0x38(%rbp), %rdi
callq 0xcb80
movq -0x50(%rbp), %rdi
callq 0x85d0
nopl (%rax)