// File: skeeto[P]elisp-ffi/ffi-glue.cc
// Function: main
int main() {
    Machine vm{std::cout};
    Reader reader{vm, std::cin};

    while (!std::cin.eof()) {
        int command = std::cin.get();
        switch (command) {
        /* push signed integer */
        case 'i' + 0: /* i */
            reader.read_sint8();
            break;
        case 'i' + 1: /* j */
            reader.read_sint16();
            break;
        case 'i' + 2: /* k */
            reader.read_sint32();
            break;
        case 'i' + 3: /* l */
            reader.read_sint64();
            break;

        /* push unsigned integer */
        case 'u' + 0: /* u */
            reader.read_uint8();
            break;
        case 'u' + 1: /* v */
            reader.read_uint16();
            break;
        case 'u' + 2: /* w */
            reader.read_uint32();
            break;
        case 'u' + 3: /* x */
            reader.read_uint64();
            break;

        /* push float */
        case 'f':
            reader.read_float();
            break;
        case 'd':
            reader.read_double();
            break;

        /* push pointer */
        case 'p':
            reader.read_pointer();
            break;

        /* push void */
        case 'V':
            vm.stack.push();
            break;

        /* peek */
        case 'e':
            vm.peek();
            break;

        /* pop */
        case 'o':
            vm.pop();
            break;

        /* call */
        case 'c':
            vm.call(false);
            break;

        /* call with errno */
        case 'E':
            vm.call(true);
            break;

        /* call */
        case 'C':
            vm.cif();
            break;

        /* "malloc" */
        case 'M':
            reader.read(vm.stack.pop().value.u32);
            break;

        /* free */
        case 'F':
            vm.free();
            break;

        /* dl calls */
        case 'O':
            vm.dlopen();
            break;
        case 'S':
            vm.dlsym();
            break;

        /* strlen */
        case 'L':
            vm.strlen();
            break;

        /* dump */
        case 'D':
            vm.dump();
            break;

        /* read from memory */
        case 'r':
            vm.read_mem();
            break;

        /* array read from memory */
        case 'A':
            vm.read_array();
            break;

        /* duplicate top value */
        case '!':
            vm.stack.dup();
            break;

        /* get stack size */
        case '?':
            vm.size();
            break;

        /* no-op */
        case ' ':
        case '\n':
        case '\r':
        case -1:
            break;

        default:
            std::cerr << "invalid op: " << static_cast<char>(command) << std::endl;
            break;
        }
        std::cout.flush();
    }

    std::cout << std::endl;
    return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xc0, %rsp
movl $0x0, -0x4(%rbp)
movq 0x8857(%rip), %rsi      # 0xafa0
leaq -0x58(%rbp), %rdi
movq %rdi, -0x90(%rbp)
callq 0x2b40
movq -0x90(%rbp), %rsi
movq 0x8861(%rip), %rdx      # 0xafc8
leaq -0x68(%rbp), %rdi
callq 0x2be0
jmp 0x2772
jmp 0x2774
movq 0x884d(%rip), %rdi      # 0xafc8
movq (%rdi), %rax
movq -0x18(%rax), %rax
addq %rax, %rdi
callq 0x22e0
movb %al, -0x91(%rbp)
jmp 0x2792
movb -0x91(%rbp), %al
xorb $-0x1, %al
testb $0x1, %al
jne 0x27a3
jmp 0x2a49
movq 0x881e(%rip), %rdi      # 0xafc8
callq 0x2210
movl %eax, -0x98(%rbp)
jmp 0x27b7
movl -0x98(%rbp), %eax
movl %eax, -0x78(%rbp)
movl -0x78(%rbp), %eax
incl %eax
movl %eax, %ecx
movq %rcx, -0xa0(%rbp)
subl $0x79, %eax
ja 0x29ea
movq -0xa0(%rbp), %rax
leaq 0x481f(%rip), %rcx      # 0x7004
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
leaq -0x58(%rbp), %rdi
callq 0x3d30
jmp 0x2a7a
leaq -0x68(%rbp), %rdi
callq 0x2c10
jmp 0x2813
jmp 0x2a36
leaq -0x68(%rbp), %rdi
callq 0x2c50
jmp 0x2823
jmp 0x2a36
leaq -0x68(%rbp), %rdi
callq 0x2c90
jmp 0x2833
jmp 0x2a36
leaq -0x68(%rbp), %rdi
callq 0x2cd0
jmp 0x2843
jmp 0x2a36
leaq -0x68(%rbp), %rdi
callq 0x2d10
jmp 0x2853
jmp 0x2a36
leaq -0x68(%rbp), %rdi
callq 0x2d50
jmp 0x2863
jmp 0x2a36
leaq -0x68(%rbp), %rdi
callq 0x2d90
jmp 0x2873
jmp 0x2a36
leaq -0x68(%rbp), %rdi
callq 0x2dd0
jmp 0x2883
jmp 0x2a36
leaq -0x68(%rbp), %rdi
callq 0x2e10
jmp 0x2893
jmp 0x2a36
leaq -0x68(%rbp), %rdi
callq 0x2e50
jmp 0x28a3
jmp 0x2a36
leaq -0x68(%rbp), %rdi
callq 0x2e90
jmp 0x28b3
jmp 0x2a36
leaq -0x58(%rbp), %rdi
callq 0x2ed0
jmp 0x28c3
jmp 0x2a36
leaq -0x58(%rbp), %rdi
callq 0x2f00
jmp 0x28d3
jmp 0x2a36
leaq -0x58(%rbp), %rdi
callq 0x2f40
jmp 0x28e3
jmp 0x2a36
leaq -0x58(%rbp), %rdi
xorl %esi, %esi
callq 0x2f80
jmp 0x28f5
jmp 0x2a36
leaq -0x58(%rbp), %rdi
movl $0x1, %esi
callq 0x2f80
jmp 0x290a
jmp 0x2a36
leaq -0x58(%rbp), %rdi
callq 0x30f0
jmp 0x291a
jmp 0x2a36
leaq -0x58(%rbp), %rdi
callq 0x3260
movq %rdx, -0xb0(%rbp)
movq %rax, -0xa8(%rbp)
jmp 0x2938
movq -0xb0(%rbp), %rax
movq -0xa8(%rbp), %rcx
movq %rcx, -0x88(%rbp)
movq %rax, -0x80(%rbp)
movl -0x80(%rbp), %esi
leaq -0x68(%rbp), %rdi
callq 0x31f0
jmp 0x295f
jmp 0x2a36
leaq -0x58(%rbp), %rdi
callq 0x32a0
jmp 0x296f
jmp 0x2a36
leaq -0x58(%rbp), %rdi
callq 0x32e0
jmp 0x297f
jmp 0x2a36
leaq -0x58(%rbp), %rdi
callq 0x3340
jmp 0x298f
jmp 0x2a36
leaq -0x58(%rbp), %rdi
callq 0x33b0
jmp 0x299f
jmp 0x2a36
leaq -0x58(%rbp), %rdi
callq 0x3400
jmp 0x29af
jmp 0x2a36
leaq -0x58(%rbp), %rdi
callq 0x3460
jmp 0x29bf
jmp 0x2a36
leaq -0x58(%rbp), %rdi
callq 0x3650
jmp 0x29cc
jmp 0x2a36
leaq -0x58(%rbp), %rdi
callq 0x3cd0
jmp 0x29d9
jmp 0x2a36
leaq -0x58(%rbp), %rdi
callq 0x3d00
jmp 0x29e6
jmp 0x2a36
jmp 0x2a36
movq 0x85ff(%rip), %rdi      # 0xaff0
leaq 0x48b7(%rip), %rsi      # 0x72af
callq 0x21b0
movq %rax, -0xb8(%rbp)
jmp 0x2a06
movq -0xb8(%rbp), %rdi
movsbl -0x78(%rbp), %esi
callq 0x2200
movq %rax, -0xc0(%rbp)
jmp 0x2a1f
movq -0xc0(%rbp), %rdi
movq 0x8543(%rip), %rsi      # 0xaf70
callq 0x21e0
jmp 0x2a34
jmp 0x2a36
movq 0x8563(%rip), %rdi      # 0xafa0
callq 0x2120
jmp 0x2a44
jmp 0x2774
movq 0x8550(%rip), %rdi      # 0xafa0
movq 0x8519(%rip), %rsi      # 0xaf70
callq 0x21e0
jmp 0x2a5e
movl $0x0, -0x4(%rbp)
leaq -0x58(%rbp), %rdi
callq 0x3d30
movl -0x4(%rbp), %eax
addq $0xc0, %rsp
popq %rbp
retq
movq -0x70(%rbp), %rdi
callq 0x22c0
nopw %cs:(%rax,%rax)
nopl (%rax)