// File: jvanns[P]verbatim/sub/lmdb/libraries/liblmdb/mdb.c
// Function: mdb_cursor_get
int
mdb_cursor_get(MDB_cursor *mc, MDB_val *key, MDB_val *data,
    MDB_cursor_op op)
{
	int		 rc;
	int		 exact = 0;
	int		 (*mfunc)(MDB_cursor *mc, MDB_val *key, MDB_val *data);

	if (mc == NULL)
		return EINVAL;

	if (mc->mc_txn->mt_flags & MDB_TXN_BLOCKED)
		return MDB_BAD_TXN;

	switch (op) {
	case MDB_GET_CURRENT:
		if (!(mc->mc_flags & C_INITIALIZED)) {
			rc = EINVAL;
		} else {
			MDB_page *mp = mc->mc_pg[mc->mc_top];
			int nkeys = NUMKEYS(mp);
			if (!nkeys || mc->mc_ki[mc->mc_top] >= nkeys) {
				mc->mc_ki[mc->mc_top] = nkeys;
				rc = MDB_NOTFOUND;
				break;
			}
			rc = MDB_SUCCESS;
			if (IS_LEAF2(mp)) {
				key->mv_size = mc->mc_db->md_pad;
				key->mv_data = LEAF2KEY(mp, mc->mc_ki[mc->mc_top], key->mv_size);
			} else {
				MDB_node *leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]);
				MDB_GET_KEY(leaf, key);
				if (data) {
					if (F_ISSET(leaf->mn_flags, F_DUPDATA)) {
						if (mc->mc_flags & C_DEL)
							mdb_xcursor_init1(mc, leaf);
						rc = mdb_cursor_get(&mc->mc_xcursor->mx_cursor, data, NULL, MDB_GET_CURRENT);
					} else {
						rc = mdb_node_read(mc->mc_txn, leaf, data);
					}
				}
			}
		}
		break;
	case MDB_GET_BOTH:
	case MDB_GET_BOTH_RANGE:
		if (data == NULL) {
			rc = EINVAL;
			break;
		}
		if (mc->mc_xcursor == NULL) {
			rc = MDB_INCOMPATIBLE;
			break;
		}
		/* FALLTHRU */
	case MDB_SET:
	case MDB_SET_KEY:
	case MDB_SET_RANGE:
		if (key == NULL) {
			rc = EINVAL;
		} else {
			rc = mdb_cursor_set(mc, key, data, op,
				op == MDB_SET_RANGE ? NULL : &exact);
		}
		break;
	case MDB_GET_MULTIPLE:
		if (data == NULL || !(mc->mc_flags & C_INITIALIZED)) {
			rc = EINVAL;
			break;
		}
		if (!(mc->mc_db->md_flags & MDB_DUPFIXED)) {
			rc = MDB_INCOMPATIBLE;
			break;
		}
		rc = MDB_SUCCESS;
		if (!(mc->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED) ||
			(mc->mc_xcursor->mx_cursor.mc_flags & C_EOF))
			break;
		goto fetchm;
	case MDB_NEXT_MULTIPLE:
		if (data == NULL) {
			rc = EINVAL;
			break;
		}
		if (!(mc->mc_db->md_flags & MDB_DUPFIXED)) {
			rc = MDB_INCOMPATIBLE;
			break;
		}
		if (!(mc->mc_flags & C_INITIALIZED))
			rc = mdb_cursor_first(mc, key, data);
		else
			rc = mdb_cursor_next(mc, key, data, MDB_NEXT_DUP);
		if (rc == MDB_SUCCESS) {
			if (mc->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED) {
				MDB_cursor *mx;
fetchm:
				mx = &mc->mc_xcursor->mx_cursor;
				data->mv_size = NUMKEYS(mx->mc_pg[mx->mc_top]) *
					mx->mc_db->md_pad;
				data->mv_data = METADATA(mx->mc_pg[mx->mc_top]);
				mx->mc_ki[mx->mc_top] = NUMKEYS(mx->mc_pg[mx->mc_top])-1;
			} else {
				rc = MDB_NOTFOUND;
			}
		}
		break;
	case MDB_NEXT:
	case MDB_NEXT_DUP:
	case MDB_NEXT_NODUP:
		if (!(mc->mc_flags & C_INITIALIZED))
			rc = mdb_cursor_first(mc, key, data);
		else
			rc = mdb_cursor_next(mc, key, data, op);
		break;
	case MDB_PREV:
	case MDB_PREV_DUP:
	case MDB_PREV_NODUP:
		if (!(mc->mc_flags & C_INITIALIZED)) {
			rc = mdb_cursor_last(mc, key, data);
			if (rc)
				break;
			mc->mc_flags |= C_INITIALIZED;
			mc->mc_ki[mc->mc_top]++;
		}
		rc = mdb_cursor_prev(mc, key, data, op);
		break;
	case MDB_FIRST:
		rc = mdb_cursor_first(mc, key, data);
		break;
	case MDB_FIRST_DUP:
		mfunc = mdb_cursor_first;
	mmove:
		if (data == NULL || !(mc->mc_flags & C_INITIALIZED)) {
			rc = EINVAL;
			break;
		}
		if (mc->mc_xcursor == NULL) {
			rc = MDB_INCOMPATIBLE;
			break;
		}
		{
			MDB_node *leaf = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]);
			if (!F_ISSET(leaf->mn_flags, F_DUPDATA)) {
				MDB_GET_KEY(leaf, key);
				rc = mdb_node_read(mc->mc_txn, leaf, data);
				break;
			}
		}
		if (!(mc->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED)) {
			rc = EINVAL;
			break;
		}
		rc = mfunc(&mc->mc_xcursor->mx_cursor, data, NULL);
		break;
	case MDB_LAST:
		rc = mdb_cursor_last(mc, key, data);
		break;
	case MDB_LAST_DUP:
		mfunc = mdb_cursor_last;
		goto mmove;
	default:
		DPRINTF(("unhandled/unimplemented cursor operation %u", op));
		rc = EINVAL;
		break;
	}

	if (mc->mc_flags & C_DEL)
		mc->mc_flags ^= C_DEL;

	return rc;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x90, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movl %ecx, -0x24(%rbp)
movl $0x0, -0x2c(%rbp)
cmpq $0x0, -0x10(%rbp)
jne 0x8184
movl $0x16, -0x4(%rbp)
jmp 0x87f0
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rax
movl 0x7c(%rax), %eax
andl $0x13, %eax
cmpl $0x0, %eax
je 0x81a3
movl $0xffff87c2, -0x4(%rbp) # imm = 0xFFFF87C2
jmp 0x87f0
movl -0x24(%rbp), %eax
movq %rax, -0x68(%rbp)
subq $0x11, %rax
ja 0x87c7
movq -0x68(%rbp), %rax
leaq 0xf1dd(%rip), %rcx      # 0x1739c
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x10(%rbp), %rax
movl 0x44(%rax), %eax
andl $0x1, %eax
cmpl $0x0, %eax
jne 0x81e3
movl $0x16, -0x28(%rbp)
jmp 0x836e
movq -0x10(%rbp), %rax
movq -0x10(%rbp), %rcx
movzwl 0x42(%rcx), %ecx
movq 0x48(%rax,%rcx,8), %rax
movq %rax, -0x40(%rbp)
movq -0x40(%rbp), %rax
movzwl 0xc(%rax), %eax
subl $0x10, %eax
shrl %eax
movl %eax, -0x44(%rbp)
cmpl $0x0, -0x44(%rbp)
je 0x8227
movq -0x10(%rbp), %rax
movq -0x10(%rbp), %rcx
movzwl 0x42(%rcx), %ecx
movzwl 0x148(%rax,%rcx,2), %eax
cmpl -0x44(%rbp), %eax
jl 0x824d
movl -0x44(%rbp), %eax
movw %ax, %dx
movq -0x10(%rbp), %rax
movq -0x10(%rbp), %rcx
movzwl 0x42(%rcx), %ecx
movw %dx, 0x148(%rax,%rcx,2)
movl $0xffff87b2, -0x28(%rbp) # imm = 0xFFFF87B2
jmp 0x87ce
movl $0x0, -0x28(%rbp)
movq -0x40(%rbp), %rax
movzwl 0xa(%rax), %eax
andl $0x20, %eax
cmpl $0x20, %eax
jne 0x82ab
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movl (%rax), %eax
movl %eax, %ecx
movq -0x18(%rbp), %rax
movq %rcx, (%rax)
movq -0x40(%rbp), %rcx
addq $0x10, %rcx
movq -0x10(%rbp), %rax
movq -0x10(%rbp), %rdx
movzwl 0x42(%rdx), %edx
movzwl 0x148(%rax,%rdx,2), %eax
movq -0x18(%rbp), %rdx
imulq (%rdx), %rax
addq %rax, %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x8(%rax)
jmp 0x836c
movq -0x40(%rbp), %rax
movq -0x40(%rbp), %rcx
movq -0x10(%rbp), %rdx
movq -0x10(%rbp), %rsi
movzwl 0x42(%rsi), %esi
movzwl 0x148(%rdx,%rsi,2), %edx
movzwl 0x10(%rcx,%rdx,2), %ecx
movslq %ecx, %rcx
addq %rcx, %rax
movq %rax, -0x50(%rbp)
cmpq $0x0, -0x18(%rbp)
je 0x82fe
movq -0x50(%rbp), %rax
movzwl 0x6(%rax), %eax
movl %eax, %ecx
movq -0x18(%rbp), %rax
movq %rcx, (%rax)
movq -0x50(%rbp), %rcx
addq $0x8, %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x8(%rax)
cmpq $0x0, -0x20(%rbp)
je 0x836a
movq -0x50(%rbp), %rax
movzwl 0x4(%rax), %eax
andl $0x4, %eax
cmpl $0x4, %eax
jne 0x8350
movq -0x10(%rbp), %rax
movl 0x44(%rax), %eax
andl $0x8, %eax
cmpl $0x0, %eax
je 0x8331
movq -0x10(%rbp), %rdi
movq -0x50(%rbp), %rsi
callq 0x8800
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rdi
movq -0x20(%rbp), %rsi
xorl %eax, %eax
movl %eax, %edx
movl $0x4, %ecx
callq 0x8150
movl %eax, -0x28(%rbp)
jmp 0x8368
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rdi
movq -0x50(%rbp), %rsi
movq -0x20(%rbp), %rdx
callq 0x8a10
movl %eax, -0x28(%rbp)
jmp 0x836a
jmp 0x836c
jmp 0x836e
jmp 0x87ce
cmpq $0x0, -0x20(%rbp)
jne 0x8386
movl $0x16, -0x28(%rbp)
jmp 0x87ce
movq -0x10(%rbp), %rax
cmpq $0x0, 0x10(%rax)
jne 0x839d
movl $0xffff87c0, -0x28(%rbp) # imm = 0xFFFF87C0
jmp 0x87ce
jmp 0x839f
cmpq $0x0, -0x18(%rbp)
jne 0x83af
movl $0x16, -0x28(%rbp)
jmp 0x840f
movq -0x10(%rbp), %rax
movq %rax, -0x88(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0x80(%rbp)
movq -0x20(%rbp), %rax
movq %rax, -0x78(%rbp)
movl -0x24(%rbp), %eax
movl %eax, -0x6c(%rbp)
cmpl $0x11, -0x24(%rbp)
jne 0x83e1
xorl %eax, %eax
movq %rax, -0x90(%rbp)
jmp 0x83ee
leaq -0x2c(%rbp), %rax
movq %rax, -0x90(%rbp)
jmp 0x83ee
movl -0x6c(%rbp), %ecx
movq -0x78(%rbp), %rdx
movq -0x80(%rbp), %rsi
movq -0x88(%rbp), %rdi
movq -0x90(%rbp), %r8
callq 0x7970
movl %eax, -0x28(%rbp)
jmp 0x87ce
cmpq $0x0, -0x20(%rbp)
je 0x842a
movq -0x10(%rbp), %rax
movl 0x44(%rax), %eax
andl $0x1, %eax
cmpl $0x0, %eax
jne 0x8436
movl $0x16, -0x28(%rbp)
jmp 0x87ce
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movzwl 0x4(%rax), %eax
andl $0x10, %eax
cmpl $0x0, %eax
jne 0x8456
movl $0xffff87c0, -0x28(%rbp) # imm = 0xFFFF87C0
jmp 0x87ce
movl $0x0, -0x28(%rbp)
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rax
movl 0x44(%rax), %eax
andl $0x1, %eax
cmpl $0x0, %eax
je 0x8483
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rax
movl 0x44(%rax), %eax
andl $0x2, %eax
cmpl $0x0, %eax
je 0x8488
jmp 0x87ce
jmp 0x8521
cmpq $0x0, -0x20(%rbp)
jne 0x84a0
movl $0x16, -0x28(%rbp)
jmp 0x87ce
movq -0x10(%rbp), %rax
movq 0x28(%rax), %rax
movzwl 0x4(%rax), %eax
andl $0x10, %eax
cmpl $0x0, %eax
jne 0x84c0
movl $0xffff87c0, -0x28(%rbp) # imm = 0xFFFF87C0
jmp 0x87ce
movq -0x10(%rbp), %rax
movl 0x44(%rax), %eax
andl $0x1, %eax
cmpl $0x0, %eax
jne 0x84e5
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0x20(%rbp), %rdx
callq 0x8b00
movl %eax, -0x28(%rbp)
jmp 0x84fe
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0x20(%rbp), %rdx
movl $0x9, %ecx
callq 0x8d30
movl %eax, -0x28(%rbp)
cmpl $0x0, -0x28(%rbp)
jne 0x85b9
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rax
movl 0x44(%rax), %eax
andl $0x1, %eax
cmpl $0x0, %eax
je 0x85b0
jmp 0x8521
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x58(%rbp)
movq -0x58(%rbp), %rax
movq -0x58(%rbp), %rcx
movzwl 0x42(%rcx), %ecx
movq 0x48(%rax,%rcx,8), %rax
movzwl 0xc(%rax), %eax
subl $0x10, %eax
shrl %eax
movq -0x58(%rbp), %rcx
movq 0x28(%rcx), %rcx
imull (%rcx), %eax
movl %eax, %eax
movl %eax, %ecx
movq -0x20(%rbp), %rax
movq %rcx, (%rax)
movq -0x58(%rbp), %rax
movq -0x58(%rbp), %rcx
movzwl 0x42(%rcx), %ecx
movq 0x48(%rax,%rcx,8), %rcx
addq $0x10, %rcx
movq -0x20(%rbp), %rax
movq %rcx, 0x8(%rax)
movq -0x58(%rbp), %rax
movq -0x58(%rbp), %rcx
movzwl 0x42(%rcx), %ecx
movq 0x48(%rax,%rcx,8), %rax
movzwl 0xc(%rax), %eax
subl $0x10, %eax
shrl %eax
subl $0x1, %eax
movw %ax, %dx
movq -0x58(%rbp), %rax
movq -0x58(%rbp), %rcx
movzwl 0x42(%rcx), %ecx
movw %dx, 0x148(%rax,%rcx,2)
jmp 0x85b7
movl $0xffff87b2, -0x28(%rbp) # imm = 0xFFFF87B2
jmp 0x85b9
jmp 0x87ce
movq -0x10(%rbp), %rax
movl 0x44(%rax), %eax
andl $0x1, %eax
cmpl $0x0, %eax
jne 0x85e3
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0x20(%rbp), %rdx
callq 0x8b00
movl %eax, -0x28(%rbp)
jmp 0x85fa
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0x20(%rbp), %rdx
movl -0x24(%rbp), %ecx
callq 0x8d30
movl %eax, -0x28(%rbp)
jmp 0x87ce
movq -0x10(%rbp), %rax
movl 0x44(%rax), %eax
andl $0x1, %eax
cmpl $0x0, %eax
jne 0x865a
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0x20(%rbp), %rdx
callq 0x90d0
movl %eax, -0x28(%rbp)
cmpl $0x0, -0x28(%rbp)
je 0x862d
jmp 0x87ce
movq -0x10(%rbp), %rax
movl 0x44(%rax), %ecx
orl $0x1, %ecx
movl %ecx, 0x44(%rax)
movq -0x10(%rbp), %rax
movq -0x10(%rbp), %rcx
movzwl 0x42(%rcx), %ecx
movw 0x148(%rax,%rcx,2), %dx
addw $0x1, %dx
movw %dx, 0x148(%rax,%rcx,2)
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0x20(%rbp), %rdx
movl -0x24(%rbp), %ecx
callq 0x9350
movl %eax, -0x28(%rbp)
jmp 0x87ce
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0x20(%rbp), %rdx
callq 0x8b00
movl %eax, -0x28(%rbp)
jmp 0x87ce
leaq 0x46a(%rip), %rax       # 0x8b00
movq %rax, -0x38(%rbp)
cmpq $0x0, -0x20(%rbp)
je 0x86b0
movq -0x10(%rbp), %rax
movl 0x44(%rax), %eax
andl $0x1, %eax
cmpl $0x0, %eax
jne 0x86bc
movl $0x16, -0x28(%rbp)
jmp 0x87ce
movq -0x10(%rbp), %rax
cmpq $0x0, 0x10(%rax)
jne 0x86d3
movl $0xffff87c0, -0x28(%rbp) # imm = 0xFFFF87C0
jmp 0x87ce
movq -0x10(%rbp), %rax
movq -0x10(%rbp), %rcx
movzwl 0x42(%rcx), %ecx
movq 0x48(%rax,%rcx,8), %rax
movq -0x10(%rbp), %rcx
movq -0x10(%rbp), %rdx
movzwl 0x42(%rdx), %edx
movq 0x48(%rcx,%rdx,8), %rcx
movq -0x10(%rbp), %rdx
movq -0x10(%rbp), %rsi
movzwl 0x42(%rsi), %esi
movzwl 0x148(%rdx,%rsi,2), %edx
movzwl 0x10(%rcx,%rdx,2), %ecx
movslq %ecx, %rcx
addq %rcx, %rax
movq %rax, -0x60(%rbp)
movq -0x60(%rbp), %rax
movzwl 0x4(%rax), %eax
andl $0x4, %eax
cmpl $0x4, %eax
je 0x876a
cmpq $0x0, -0x18(%rbp)
je 0x8750
movq -0x60(%rbp), %rax
movzwl 0x6(%rax), %eax
movl %eax, %ecx
movq -0x18(%rbp), %rax
movq %rcx, (%rax)
movq -0x60(%rbp), %rcx
addq $0x8, %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x8(%rax)
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rdi
movq -0x60(%rbp), %rsi
movq -0x20(%rbp), %rdx
callq 0x8a10
movl %eax, -0x28(%rbp)
jmp 0x87ce
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rax
movl 0x44(%rax), %eax
andl $0x1, %eax
cmpl $0x0, %eax
jne 0x8786
movl $0x16, -0x28(%rbp)
jmp 0x87ce
movq -0x38(%rbp), %rax
movq -0x10(%rbp), %rcx
movq 0x10(%rcx), %rdi
movq -0x20(%rbp), %rsi
xorl %ecx, %ecx
movl %ecx, %edx
callq *%rax
movl %eax, -0x28(%rbp)
jmp 0x87ce
movq -0x10(%rbp), %rdi
movq -0x18(%rbp), %rsi
movq -0x20(%rbp), %rdx
callq 0x90d0
movl %eax, -0x28(%rbp)
jmp 0x87ce
leaq 0x912(%rip), %rax       # 0x90d0
movq %rax, -0x38(%rbp)
jmp 0x869a
movl $0x16, -0x28(%rbp)
movq -0x10(%rbp), %rax
movl 0x44(%rax), %eax
andl $0x8, %eax
cmpl $0x0, %eax
je 0x87ea
movq -0x10(%rbp), %rax
movl 0x44(%rax), %ecx
xorl $0x8, %ecx
movl %ecx, 0x44(%rax)
movl -0x28(%rbp), %eax
movl %eax, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x90, %rsp
popq %rbp
retq
nopl (%rax)