#define NULL ((void *)0)
typedef unsigned long size_t; // Customize by platform.
typedef long intptr_t;
typedef unsigned long uintptr_t;
typedef long scalar_t__; // Either arithmetic or pointer type.
/* By default, we understand bool (as a convenience). */
typedef int bool;
#define false 0
#define true 1

/* Forward declarations */

/* Type definitions */

/* Variables and functions */
int ERR;
short const KEY_BACKSPACE;
short const KEY_DC;
short const KEY_DOWN;
short const KEY_ENTER;
short const KEY_LEFT;
short const KEY_RIGHT;
short const KEY_UP;
int getch();
int kb_readkey(unsigned char *dest) {
  const short funckeys[7] = {KEY_LEFT,  KEY_RIGHT,     KEY_UP, KEY_DOWN,
                             KEY_ENTER, KEY_BACKSPACE, KEY_DC};
  const unsigned char keys[7] = {1, 2, 3, 4, '\n', '\b', 0x7F};
  int c = getch();
  int i;
  if (c == ERR)
    return 0;
  for (i = 0; i < 7; i++)
    if (c == funckeys[i]) {
      dest[0] = keys[i];
      return 1;
    }
  if (c >= 0x100) {
    dest[0] = c & 0xFF;
    dest[1] = c >> 8;
    return 2;
  }
  dest[0] = c;
  return 1;
}


x86 assembly (clang, -O0):
<kb_readkey>:
push   %rbp
mov    %rsp,%rbp
sub    $0x30,%rsp
mov    %rdi,-0x10(%rbp)
mov    0x2e8d(%rip),%rax
mov    (%rax),%ax
mov    %ax,-0x1e(%rbp)
mov    0x2e87(%rip),%rax
mov    (%rax),%ax
mov    %ax,-0x1c(%rbp)
mov    0x2e89(%rip),%rax
mov    (%rax),%ax
mov    %ax,-0x1a(%rbp)
mov    0x2e83(%rip),%rax
mov    (%rax),%ax
mov    %ax,-0x18(%rbp)
mov    0x2e45(%rip),%rax
mov    (%rax),%ax
mov    %ax,-0x16(%rbp)
mov    0x2e6f(%rip),%rax
mov    (%rax),%ax
mov    %ax,-0x14(%rbp)
mov    0x2e71(%rip),%rax
mov    (%rax),%ax
mov    %ax,-0x12(%rbp)
mov    0xe8a(%rip),%eax
mov    %eax,-0x25(%rbp)
mov    0xe84(%rip),%ax
mov    %ax,-0x21(%rbp)
mov    0xe7c(%rip),%al
mov    %al,-0x1f(%rbp)
mov    $0x0,%al
call   1030 <getch@plt>
mov    %eax,-0x2c(%rbp)
mov    -0x2c(%rbp),%eax
mov    0x2e31(%rip),%rcx
cmp    (%rcx),%eax
jne    11c3 <kb_readkey+0xb3>
movl   $0x0,-0x4(%rbp)
jmp    125f <kb_readkey+0x14f>
movl   $0x0,-0x30(%rbp)
cmpl   $0x7,-0x30(%rbp)
jge    1215 <kb_readkey+0x105>
mov    -0x2c(%rbp),%eax
movslq -0x30(%rbp),%rcx
movswl -0x1e(%rbp,%rcx,2),%ecx
cmp    %ecx,%eax
jne    1202 <kb_readkey+0xf2>
movslq -0x30(%rbp),%rax
mov    -0x25(%rbp,%rax,1),%cl
mov    -0x10(%rbp),%rax
mov    %cl,(%rax)
movl   $0x1,-0x4(%rbp)
jmp    125f <kb_readkey+0x14f>
jmp    1207 <kb_readkey+0xf7>
mov    -0x30(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x30(%rbp)
jmp    11ca <kb_readkey+0xba>
cmpl   $0x100,-0x2c(%rbp)
jl     124d <kb_readkey+0x13d>
mov    -0x2c(%rbp),%eax
and    $0xff,%eax
mov    %al,%cl
mov    -0x10(%rbp),%rax
mov    %cl,(%rax)
mov    -0x2c(%rbp),%eax
sar    $0x8,%eax
mov    %al,%cl
mov    -0x10(%rbp),%rax
mov    %cl,0x1(%rax)
movl   $0x2,-0x4(%rbp)
jmp    125f <kb_readkey+0x14f>
mov    -0x2c(%rbp),%eax
mov    %al,%cl
mov    -0x10(%rbp),%rax
mov    %cl,(%rax)
movl   $0x1,-0x4(%rbp)
mov    -0x4(%rbp),%eax
add    $0x30,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<kb_readkey>:
push   %rbp
push   %rbx
push   %rax
mov    %rdi,%rbx
xor    %ebp,%ebp
xor    %eax,%eax
call   1030 <getch@plt>
mov    0x2ec2(%rip),%rcx
cmp    (%rcx),%eax
je     114e <kb_readkey+0x3e>
test   %eax,%eax
je     1146 <kb_readkey+0x36>
mov    %al,(%rbx)
mov    $0x1,%ebp
cmp    $0x100,%eax
jl     114e <kb_readkey+0x3e>
mov    %ah,0x1(%rbx)
mov    $0x2,%ebp
jmp    114e <kb_readkey+0x3e>
movb   $0x1,(%rbx)
mov    $0x1,%ebp
mov    %ebp,%eax
add    $0x8,%rsp
pop    %rbx
pop    %rbp
ret

LLVM IR (-O0):
@KEY_LEFT = constant i16 0
@KEY_RIGHT = constant i16 0
@KEY_UP = constant i16 0
@KEY_DOWN = constant i16 0
@KEY_ENTER = constant i16 0
@KEY_BACKSPACE = constant i16 0
@KEY_DC = constant i16 0
@__const.kb_readkey.keys = [7 x i8] c"\01\02\03\04\0A\08\7F"
@ERR = global i32 0
define i32 @kb_readkey(i8* %0) {
%2 = alloca i32
%3 = alloca i8*
%4 = alloca [7 x i16]
%5 = alloca [7 x i8]
%6 = alloca i32
%7 = alloca i32
store i8* %0, i8** %3
%8 = getelementptr inbounds [7 x i16], [7 x i16]* %4, i64 0, i64 0
%9 = load i16, i16* @KEY_LEFT
store i16 %9, i16* %8
%10 = getelementptr inbounds i16, i16* %8, i64 1
%11 = load i16, i16* @KEY_RIGHT
store i16 %11, i16* %10
%12 = getelementptr inbounds i16, i16* %10, i64 1
%13 = load i16, i16* @KEY_UP
store i16 %13, i16* %12
%14 = getelementptr inbounds i16, i16* %12, i64 1
%15 = load i16, i16* @KEY_DOWN
store i16 %15, i16* %14
%16 = getelementptr inbounds i16, i16* %14, i64 1
%17 = load i16, i16* @KEY_ENTER
store i16 %17, i16* %16
%18 = getelementptr inbounds i16, i16* %16, i64 1
%19 = load i16, i16* @KEY_BACKSPACE
store i16 %19, i16* %18
%20 = getelementptr inbounds i16, i16* %18, i64 1
%21 = load i16, i16* @KEY_DC
store i16 %21, i16* %20
%22 = bitcast [7 x i8]* %5 to i8*
%23 = call i32 (...) @getch()
store i32 %23, i32* %6
%24 = load i32, i32* %6
%25 = load i32, i32* @ERR
%26 = icmp eq i32 %24, %25
br i1 %26, label %27, label %28
27: ; preds = %1
store i32 0, i32* %2
br label %70
28: ; preds = %1
store i32 0, i32* %7
br label %29
29: ; preds = %48, %28
%30 = load i32, i32* %7
%31 = icmp slt i32 %30, 7
br i1 %31, label %32, label %51
32: ; preds = %29
%33 = load i32, i32* %6
%34 = load i32, i32* %7
%35 = sext i32 %34 to i64
%36 = getelementptr inbounds [7 x i16], [7 x i16]* %4, i64 0, i64 %35
%37 = load i16, i16* %36
%38 = sext i16 %37 to i32
%39 = icmp eq i32 %33, %38
br i1 %39, label %40, label %47
40: ; preds = %32
%41 = load i32, i32* %7
%42 = sext i32 %41 to i64
%43 = getelementptr inbounds [7 x i8], [7 x i8]* %5, i64 0, i64 %42
%44 = load i8, i8* %43
%45 = load i8*, i8** %3
%46 = getelementptr inbounds i8, i8* %45, i64 0
store i8 %44, i8* %46
store i32 1, i32* %2
br label %70
47: ; preds = %32
br label %48
48: ; preds = %47
%49 = load i32, i32* %7
%50 = add nsw i32 %49, 1
store i32 %50, i32* %7
br label %29
51: ; preds = %29
%52 = load i32, i32* %6
%53 = icmp sge i32 %52, 256
br i1 %53, label %54, label %65
54: ; preds = %51
%55 = load i32, i32* %6
%56 = and i32 %55, 255
%57 = trunc i32 %56 to i8
%58 = load i8*, i8** %3
%59 = getelementptr inbounds i8, i8* %58, i64 0
store i8 %57, i8* %59
%60 = load i32, i32* %6
%61 = ashr i32 %60, 8
%62 = trunc i32 %61 to i8
%63 = load i8*, i8** %3
%64 = getelementptr inbounds i8, i8* %63, i64 1
store i8 %62, i8* %64
store i32 2, i32* %2
br label %70
65: ; preds = %51
%66 = load i32, i32* %6
%67 = trunc i32 %66 to i8
%68 = load i8*, i8** %3
%69 = getelementptr inbounds i8, i8* %68, i64 0
store i8 %67, i8* %69
store i32 1, i32* %2
br label %70
70: ; preds = %65, %54, %40, %27
%71 = load i32, i32* %2
ret i32 %71
}

LLVM IR (-O2):
@KEY_LEFT = constant i16 0
@KEY_RIGHT = constant i16 0
@KEY_UP = constant i16 0
@KEY_DOWN = constant i16 0
@KEY_ENTER = constant i16 0
@KEY_BACKSPACE = constant i16 0
@KEY_DC = constant i16 0
@ERR = global i32 0
define i32 @kb_readkey(i8* nocapture writeonly %0) {
%2 = tail call i32 (...) @getch()
%3 = load i32, i32* @ERR
%4 = icmp eq i32 %2, %3
br i1 %4, label %15, label %5
5: ; preds = %1
%6 = icmp eq i32 %2, 0
br i1 %6, label %7, label %8
7: ; preds = %5
store i8 1, i8* %0
br label %15
8: ; preds = %5
%9 = icmp sgt i32 %2, 255
%10 = trunc i32 %2 to i8
store i8 %10, i8* %0
br i1 %9, label %11, label %15
11: ; preds = %8
%12 = lshr i32 %2, 8
%13 = trunc i32 %12 to i8
%14 = getelementptr inbounds i8, i8* %0, i64 1
store i8 %13, i8* %14
br label %15
15: ; preds = %8, %1, %11, %7
%16 = phi i32 [ 1, %7 ], [ 2, %11 ], [ 0, %1 ], [ 1, %8 ]
ret i32 %16
}