// File: /workspace/github_c_makefile_star2_O0/jtuu[P]quesler/src/vm.c
// Function: process_string_tags
static uint16_t* process_string_tags(uint16_t* str) {
    typedef enum {
        TAG_UNKNOWN,
        TAG_REGISTER
    } TagType;

    uint16_t* cur_pos = str;

    uint16_t* tag_start = NULL;
    uint16_t* tag_value_start = NULL;
    TagType tag_type = TAG_UNKNOWN;

    struct {
        uint16_t* str;
        size_t len;
        size_t capacity;
    } result = {.str = NULL, .len = 0, .capacity = 0};

    while (true) {
        uint16_t chr = *cur_pos;

        if (chr == 0) {
            break;
        }

        switch ((char) *cur_pos) {
            case '<':
                tag_start = cur_pos;
                break;
            case '>':
                switch (tag_type) {
                    case TAG_REGISTER: {
                        uint8_t reg = 0;
                        do {
                            reg = (uint8_t) (reg * 10 + (*tag_value_start - '0'));
                        } while (++tag_value_start < cur_pos);

                        int32_t val = AS_DWORD(vm.registers[reg]);
                        uint16_t val_str[10];
                        size_t val_str_len = 0;

                        do {
                            val_str[10 - val_str_len - 1] = (uint16_t) ('0' + val % 10);
                            val_str_len++;
                            val /= 10;
                        } while (val > 0);

                        while (result.capacity < result.len + val_str_len + 1) {
                            size_t old_capacity = result.capacity;
                            result.capacity = GROW_CAPACITY(old_capacity);
                            result.str = GROW_ARRAY(uint16_t, result.str,
                                old_capacity, result.capacity);
                        }

                        memcpy((char*) &result.str[result.len], (char*) &val_str[10 - val_str_len],
                            val_str_len * 2);
                        result.len += val_str_len;
                        
                        break;
                    }
                    default:
                        fprintf(stderr, "VM: Unknown string tag\n");
                        break;
                }

                tag_start = NULL;
                tag_value_start = NULL;
                tag_type = TAG_UNKNOWN;
                break;
            default:
                if (tag_start == NULL) {
                    if (result.capacity < result.len + 2) {
                        size_t old_capacity = result.capacity;
                        result.capacity = GROW_CAPACITY(old_capacity);
                        result.str = GROW_ARRAY(uint16_t, result.str,
                            old_capacity, result.capacity);
                    }

                    result.str[result.len] = *cur_pos;
                    result.len++;
                } else if (cur_pos - tag_start == 1) {

                    switch ((char) *cur_pos) {
                        case 'R': __attribute__((fallthrough));
                        case 'r':
                            tag_type = TAG_REGISTER;
                            tag_value_start = cur_pos + 1;
                            break;
                        default:
                            fprintf(stderr, "VM: Unknown string tag\n");
                            break;
                    }
                }
                break;
        }

        cur_pos++;
    }

    result.str[result.len] = 0;

    return result.str;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xa0, %rsp
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x10(%rbp)
movq $0x0, -0x18(%rbp)
movq $0x0, -0x20(%rbp)
movl $0x0, -0x24(%rbp)
leaq -0x40(%rbp), %rdi
xorl %esi, %esi
movl $0x18, %edx
callq 0x40b0
movq -0x10(%rbp), %rax
movw (%rax), %ax
movw %ax, -0x42(%rbp)
movzwl -0x42(%rbp), %eax
cmpl $0x0, %eax
jne 0xb337
jmp 0xb5e7
movq -0x10(%rbp), %rax
movsbl (%rax), %eax
movl %eax, -0x7c(%rbp)
subl $0x3c, %eax
je 0xb355
jmp 0xb348
movl -0x7c(%rbp), %eax
subl $0x3e, %eax
je 0xb362
jmp 0xb4de
movq -0x10(%rbp), %rax
movq %rax, -0x18(%rbp)
jmp 0xb5d6
movl -0x24(%rbp), %eax
subl $0x1, %eax
jne 0xb4aa
jmp 0xb370
movb $0x0, -0x43(%rbp)
movzbl -0x43(%rbp), %eax
imull $0xa, %eax, %eax
movq -0x20(%rbp), %rcx
movzwl (%rcx), %ecx
subl $0x30, %ecx
addl %ecx, %eax
movb %al, -0x43(%rbp)
movq -0x20(%rbp), %rax
addq $0x2, %rax
movq %rax, -0x20(%rbp)
cmpq -0x10(%rbp), %rax
jb 0xb374
movzbl -0x43(%rbp), %eax
movl %eax, %ecx
leaq 0xe3cf(%rip), %rax      # 0x19778
addq $0x10, %rax
shlq $0x4, %rcx
addq %rcx, %rax
movl 0x8(%rax), %eax
movl %eax, -0x48(%rbp)
movq $0x0, -0x68(%rbp)
movl -0x48(%rbp), %eax
movl $0xa, %ecx
cltd
idivl %ecx
addl $0x30, %edx
movw %dx, %cx
movl $0xa, %eax
subq -0x68(%rbp), %rax
subq $0x1, %rax
movw %cx, -0x60(%rbp,%rax,2)
movq -0x68(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x68(%rbp)
movl -0x48(%rbp), %eax
movl $0xa, %ecx
cltd
idivl %ecx
movl %eax, -0x48(%rbp)
cmpl $0x0, -0x48(%rbp)
jg 0xb3c2
jmp 0xb407
movq -0x30(%rbp), %rax
movq -0x38(%rbp), %rcx
addq -0x68(%rbp), %rcx
addq $0x1, %rcx
cmpq %rcx, %rax
jae 0xb46f
movq -0x30(%rbp), %rax
movq %rax, -0x70(%rbp)
cmpq $0x8, -0x70(%rbp)
jae 0xb439
movl $0x8, %eax
movq %rax, -0x88(%rbp)
jmp 0xb447
movq -0x70(%rbp), %rax
shlq %rax
movq %rax, -0x88(%rbp)
movq -0x88(%rbp), %rax
movq %rax, -0x30(%rbp)
movq -0x40(%rbp), %rdi
movq -0x70(%rbp), %rsi
shlq %rsi
movq -0x30(%rbp), %rdx
shlq %rdx
callq 0x79e0
movq %rax, -0x40(%rbp)
jmp 0xb407
movq -0x40(%rbp), %rdi
movq -0x38(%rbp), %rax
shlq %rax
addq %rax, %rdi
movl $0xa, %eax
subq -0x68(%rbp), %rax
leaq -0x60(%rbp), %rsi
shlq %rax
addq %rax, %rsi
movq -0x68(%rbp), %rdx
shlq %rdx
callq 0x4110
movq -0x68(%rbp), %rax
addq -0x38(%rbp), %rax
movq %rax, -0x38(%rbp)
jmp 0xb4c2
movq 0xdb3f(%rip), %rax      # 0x18ff0
movq (%rax), %rdi
leaq 0x2e8f(%rip), %rsi      # 0xe34a
movb $0x0, %al
callq 0x40f0
movq $0x0, -0x18(%rbp)
movq $0x0, -0x20(%rbp)
movl $0x0, -0x24(%rbp)
jmp 0xb5d6
cmpq $0x0, -0x18(%rbp)
jne 0xb56c
movq -0x30(%rbp), %rax
movq -0x38(%rbp), %rcx
addq $0x2, %rcx
cmpq %rcx, %rax
jae 0xb54b
movq -0x30(%rbp), %rax
movq %rax, -0x78(%rbp)
cmpq $0x8, -0x78(%rbp)
jae 0xb517
movl $0x8, %eax
movq %rax, -0x90(%rbp)
jmp 0xb525
movq -0x78(%rbp), %rax
shlq %rax
movq %rax, -0x90(%rbp)
movq -0x90(%rbp), %rax
movq %rax, -0x30(%rbp)
movq -0x40(%rbp), %rdi
movq -0x78(%rbp), %rsi
shlq %rsi
movq -0x30(%rbp), %rdx
shlq %rdx
callq 0x79e0
movq %rax, -0x40(%rbp)
movq -0x10(%rbp), %rax
movw (%rax), %dx
movq -0x40(%rbp), %rax
movq -0x38(%rbp), %rcx
movw %dx, (%rax,%rcx,2)
movq -0x38(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x38(%rbp)
jmp 0xb5d4
movq -0x10(%rbp), %rax
movq -0x18(%rbp), %rcx
subq %rcx, %rax
sarq %rax
cmpq $0x1, %rax
jne 0xb5d2
movq -0x10(%rbp), %rax
movsbl (%rax), %eax
movl %eax, -0x94(%rbp)
subl $0x52, %eax
je 0xb5a1
jmp 0xb594
movl -0x94(%rbp), %eax
subl $0x72, %eax
je 0xb5a3
jmp 0xb5b8
jmp 0xb5a3
movl $0x1, -0x24(%rbp)
movq -0x10(%rbp), %rax
addq $0x2, %rax
movq %rax, -0x20(%rbp)
jmp 0xb5d0
movq 0xda31(%rip), %rax      # 0x18ff0
movq (%rax), %rdi
leaq 0x2d81(%rip), %rsi      # 0xe34a
movb $0x0, %al
callq 0x40f0
jmp 0xb5d2
jmp 0xb5d4
jmp 0xb5d6
movq -0x10(%rbp), %rax
addq $0x2, %rax
movq %rax, -0x10(%rbp)
jmp 0xb31e
movq -0x40(%rbp), %rax
movq -0x38(%rbp), %rcx
movw $0x0, (%rax,%rcx,2)
movq -0x40(%rbp), %rax
addq $0xa0, %rsp
popq %rbp
retq