#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 is_a_backspace(unsigned char);
int is_a_left(unsigned char);
scalar_t__ is_a_return(unsigned char);
int is_a_right(unsigned char);
int /*<<< orphan*/ strcpy(unsigned char *, char *);
char *strdup(unsigned char *);
unsigned char strlen(char *);
unsigned char terminal_get_and_echo(unsigned char, unsigned char, unsigned char,
                                    unsigned char);
char *input_line_and_echo(unsigned char rubout, unsigned char size,
                          char *existing_text) {
  unsigned char c = 0;
  unsigned char i = 0;
  unsigned char j = 0;
  unsigned char buf[64];
  buf[0] = '\0';
  if (existing_text != NULL) {
    strcpy(buf, existing_text);
    i = strlen(existing_text);
    j = strlen(existing_text);
  }
  while (is_a_return(c) == 0) {
    c = terminal_get_and_echo(i, j, size, rubout);
    if (is_a_backspace(c) == 1) {
      if (i > 0) {
        --i;
        j = i;
        buf[i] = '\0';
      }
    } else if (is_a_left(c) == 1) {
      if (i > 0) {
        --i;
      }
    } else if (is_a_right(c) == 1) {
      if (i < j) {
        ++i;
      }
    } else if (is_a_return(c) == 0) {
      if (i < size) {
        buf[i] = c;
        ++i;
        j = i;
        buf[i] = '\0';
      } else {
        buf[i - 1] = c;
        buf[i] = '\0';
      }
    }
  }
  return strdup(buf);
}


x86 assembly (clang, -O0):
<input_line_and_echo>:
push   %rbp
mov    %rsp,%rbp
sub    $0x60,%rsp
mov    %sil,%al
mov    %dil,%cl
mov    %cl,-0x1(%rbp)
mov    %al,-0x2(%rbp)
mov    %rdx,-0x10(%rbp)
movb   $0x0,-0x11(%rbp)
movb   $0x0,-0x12(%rbp)
movb   $0x0,-0x13(%rbp)
movb   $0x0,-0x60(%rbp)
cmpq   $0x0,-0x10(%rbp)
je     11d8 <input_line_and_echo+0x58>
lea    -0x60(%rbp),%rdi
mov    -0x10(%rbp),%rsi
call   1030 <strcpy@plt>
mov    -0x10(%rbp),%rdi
call   1040 <strlen@plt>
mov    %al,-0x12(%rbp)
mov    -0x10(%rbp),%rdi
call   1040 <strlen@plt>
mov    %al,-0x13(%rbp)
jmp    11dd <input_line_and_echo+0x5d>
movzbl -0x11(%rbp),%edi
call   1090 <is_a_return@plt>
cmp    $0x0,%rax
jne    1320 <input_line_and_echo+0x1a0>
mov    -0x12(%rbp),%dl
mov    -0x13(%rbp),%cl
mov    -0x2(%rbp),%al
movzbl %dl,%edi
movzbl %cl,%esi
movzbl %al,%edx
movzbl -0x1(%rbp),%ecx
call   1080 <terminal_get_and_echo@plt>
mov    %al,-0x11(%rbp)
movzbl -0x11(%rbp),%edi
call   1050 <is_a_backspace@plt>
cmp    $0x1,%eax
jne    1249 <input_line_and_echo+0xc9>
movzbl -0x12(%rbp),%eax
cmp    $0x0,%eax
jle    1244 <input_line_and_echo+0xc4>
mov    -0x12(%rbp),%al
add    $0xff,%al
mov    %al,-0x12(%rbp)
mov    -0x12(%rbp),%al
mov    %al,-0x13(%rbp)
movzbl -0x12(%rbp),%eax
movb   $0x0,-0x60(%rbp,%rax,1)
jmp    131b <input_line_and_echo+0x19b>
movzbl -0x11(%rbp),%edi
call   1070 <is_a_left@plt>
cmp    $0x1,%eax
jne    1275 <input_line_and_echo+0xf5>
movzbl -0x12(%rbp),%eax
cmp    $0x0,%eax
jle    1270 <input_line_and_echo+0xf0>
mov    -0x12(%rbp),%al
add    $0xff,%al
mov    %al,-0x12(%rbp)
jmp    1316 <input_line_and_echo+0x196>
movzbl -0x11(%rbp),%edi
call   1060 <is_a_right@plt>
cmp    $0x1,%eax
jne    12a4 <input_line_and_echo+0x124>
movzbl -0x12(%rbp),%eax
movzbl -0x13(%rbp),%ecx
cmp    %ecx,%eax
jge    129f <input_line_and_echo+0x11f>
mov    -0x12(%rbp),%al
add    $0x1,%al
mov    %al,-0x12(%rbp)
jmp    1311 <input_line_and_echo+0x191>
movzbl -0x11(%rbp),%edi
call   1090 <is_a_return@plt>
cmp    $0x0,%rax
jne    130c <input_line_and_echo+0x18c>
movzbl -0x12(%rbp),%eax
movzbl -0x2(%rbp),%ecx
cmp    %ecx,%eax
jge    12ee <input_line_and_echo+0x16e>
mov    -0x11(%rbp),%cl
movzbl -0x12(%rbp),%eax
mov    %cl,-0x60(%rbp,%rax,1)
mov    -0x12(%rbp),%al
add    $0x1,%al
mov    %al,-0x12(%rbp)
mov    -0x12(%rbp),%al
mov    %al,-0x13(%rbp)
movzbl -0x12(%rbp),%eax
movb   $0x0,-0x60(%rbp,%rax,1)
jmp    1307 <input_line_and_echo+0x187>
mov    -0x11(%rbp),%cl
movzbl -0x12(%rbp),%eax
sub    $0x1,%eax
cltq
mov    %cl,-0x60(%rbp,%rax,1)
movzbl -0x12(%rbp),%eax
movb   $0x0,-0x60(%rbp,%rax,1)
jmp    130c <input_line_and_echo+0x18c>
jmp    1311 <input_line_and_echo+0x191>
jmp    1316 <input_line_and_echo+0x196>
jmp    131b <input_line_and_echo+0x19b>
jmp    11dd <input_line_and_echo+0x5d>
lea    -0x60(%rbp),%rdi
call   10a0 <strdup@plt>
add    $0x60,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<input_line_and_echo>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
sub    $0x58,%rsp
mov    %esi,0x8(%rsp)
mov    %edi,%r15d
movb   $0x0,0x10(%rsp)
test   %rdx,%rdx
je     11c6 <input_line_and_echo+0x46>
mov    %rdx,%rbp
lea    0x10(%rsp),%rdi
mov    %rdx,%rsi
call   1030 <strcpy@plt>
mov    %rbp,%rdi
call   1040 <strlen@plt>
mov    %eax,%ebx
mov    %rbp,%rdi
call   1040 <strlen@plt>
mov    %eax,%r14d
jmp    11cb <input_line_and_echo+0x4b>
xor    %ebx,%ebx
xor    %r14d,%r14d
xor    %edi,%edi
call   1090 <is_a_return@plt>
test   %rax,%rax
je     11f0 <input_line_and_echo+0x70>
lea    0x10(%rsp),%rdi
call   10a0 <strdup@plt>
add    $0x58,%rsp
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret
movzbl 0x8(%rsp),%eax
mov    %eax,0xc(%rsp)
movzbl %r15b,%r12d
jmp    121c <input_line_and_echo+0x9c>
nop
lea    -0x1(%rbx),%eax
test   %bl,%bl
movzbl %al,%ebx
mov    $0x0,%eax
cmove  %eax,%ebx
mov    %ebp,%edi
call   1090 <is_a_return@plt>
test   %rax,%rax
jne    11d7 <input_line_and_echo+0x57>
movzbl %bl,%r13d
movzbl %r14b,%esi
mov    %r13d,%edi
mov    0xc(%rsp),%edx
mov    %r12d,%ecx
call   1080 <terminal_get_and_echo@plt>
mov    %eax,%r15d
movzbl %al,%ebp
mov    %ebp,%edi
call   1050 <is_a_backspace@plt>
cmp    $0x1,%eax
jne    1260 <input_line_and_echo+0xe0>
test   %bl,%bl
je     1280 <input_line_and_echo+0x100>
add    $0xff,%bl
movzbl %bl,%eax
movb   $0x0,0x10(%rsp,%rax,1)
mov    %ebx,%r14d
jmp    1210 <input_line_and_echo+0x90>
nopl   0x0(%rax)
mov    %ebp,%edi
call   1070 <is_a_left@plt>
cmp    $0x1,%eax
je     1200 <input_line_and_echo+0x80>
mov    %ebp,%edi
call   1060 <is_a_right@plt>
cmp    $0x1,%eax
jne    1284 <input_line_and_echo+0x104>
cmp    %r14b,%bl
adc    $0x0,%bl
jmp    1210 <input_line_and_echo+0x90>
xor    %ebx,%ebx
jmp    1210 <input_line_and_echo+0x90>
mov    %ebp,%edi
call   1090 <is_a_return@plt>
test   %rax,%rax
jne    1210 <input_line_and_echo+0x90>
cmp    0x8(%rsp),%r13b
jae    12b1 <input_line_and_echo+0x131>
mov    %r15b,0x10(%rsp,%r13,1)
movb   $0x0,0x11(%rsp,%r13,1)
add    $0x1,%r13
mov    %r13d,%ebx
mov    %r13d,%r14d
jmp    1210 <input_line_and_echo+0x90>
mov    %r15b,0xf(%rsp,%r13,1)
movb   $0x0,0x10(%rsp,%r13,1)
jmp    1210 <input_line_and_echo+0x90>

LLVM IR (-O0):
define i8* @input_line_and_echo(i8 zeroext %0, i8 zeroext %1, i8* %2) {
%4 = alloca i8
%5 = alloca i8
%6 = alloca i8*
%7 = alloca i8
%8 = alloca i8
%9 = alloca i8
%10 = alloca [64 x i8]
store i8 %0, i8* %4
store i8 %1, i8* %5
store i8* %2, i8** %6
store i8 0, i8* %7
store i8 0, i8* %8
store i8 0, i8* %9
%11 = getelementptr inbounds [64 x i8], [64 x i8]* %10, i64 0, i64 0
store i8 0, i8* %11
%12 = load i8*, i8** %6
%13 = icmp ne i8* %12, null
br i1 %13, label %14, label %22
14: ; preds = %3
%15 = getelementptr inbounds [64 x i8], [64 x i8]* %10, i64 0, i64 0
%16 = load i8*, i8** %6
%17 = call i32 @strcpy(i8* %15, i8* %16)
%18 = load i8*, i8** %6
%19 = call zeroext i8 @strlen(i8* %18)
store i8 %19, i8* %8
%20 = load i8*, i8** %6
%21 = call zeroext i8 @strlen(i8* %20)
store i8 %21, i8* %9
br label %22
22: ; preds = %14, %3
br label %23
23: ; preds = %109, %22
%24 = load i8, i8* %7
%25 = call i64 @is_a_return(i8 zeroext %24)
%26 = icmp eq i64 %25, 0
br i1 %26, label %27, label %110
27: ; preds = %23
%28 = load i8, i8* %8
%29 = load i8, i8* %9
%30 = load i8, i8* %5
%31 = load i8, i8* %4
%32 = call zeroext i8 @terminal_get_and_echo(i8 zeroext %28, i8 zeroext %29, i8 zeroext %30, i8 zeroext %31)
store i8 %32, i8* %7
%33 = load i8, i8* %7
%34 = call i32 @is_a_backspace(i8 zeroext %33)
%35 = icmp eq i32 %34, 1
br i1 %35, label %36, label %48
36: ; preds = %27
%37 = load i8, i8* %8
%38 = zext i8 %37 to i32
%39 = icmp sgt i32 %38, 0
br i1 %39, label %40, label %47
40: ; preds = %36
%41 = load i8, i8* %8
%42 = add i8 %41, -1
store i8 %42, i8* %8
%43 = load i8, i8* %8
store i8 %43, i8* %9
%44 = load i8, i8* %8
%45 = zext i8 %44 to i64
%46 = getelementptr inbounds [64 x i8], [64 x i8]* %10, i64 0, i64 %45
store i8 0, i8* %46
br label %47
47: ; preds = %40, %36
br label %109
48: ; preds = %27
%49 = load i8, i8* %7
%50 = call i32 @is_a_left(i8 zeroext %49)
%51 = icmp eq i32 %50, 1
br i1 %51, label %52, label %60
52: ; preds = %48
%53 = load i8, i8* %8
%54 = zext i8 %53 to i32
%55 = icmp sgt i32 %54, 0
br i1 %55, label %56, label %59
56: ; preds = %52
%57 = load i8, i8* %8
%58 = add i8 %57, -1
store i8 %58, i8* %8
br label %59
59: ; preds = %56, %52
br label %108
60: ; preds = %48
%61 = load i8, i8* %7
%62 = call i32 @is_a_right(i8 zeroext %61)
%63 = icmp eq i32 %62, 1
br i1 %63, label %64, label %74
64: ; preds = %60
%65 = load i8, i8* %8
%66 = zext i8 %65 to i32
%67 = load i8, i8* %9
%68 = zext i8 %67 to i32
%69 = icmp slt i32 %66, %68
br i1 %69, label %70, label %73
70: ; preds = %64
%71 = load i8, i8* %8
%72 = add i8 %71, 1
store i8 %72, i8* %8
br label %73
73: ; preds = %70, %64
br label %107
74: ; preds = %60
%75 = load i8, i8* %7
%76 = call i64 @is_a_return(i8 zeroext %75)
%77 = icmp eq i64 %76, 0
br i1 %77, label %78, label %106
78: ; preds = %74
%79 = load i8, i8* %8
%80 = zext i8 %79 to i32
%81 = load i8, i8* %5
%82 = zext i8 %81 to i32
%83 = icmp slt i32 %80, %82
br i1 %83, label %84, label %95
84: ; preds = %78
%85 = load i8, i8* %7
%86 = load i8, i8* %8
%87 = zext i8 %86 to i64
%88 = getelementptr inbounds [64 x i8], [64 x i8]* %10, i64 0, i64 %87
store i8 %85, i8* %88
%89 = load i8, i8* %8
%90 = add i8 %89, 1
store i8 %90, i8* %8
%91 = load i8, i8* %8
store i8 %91, i8* %9
%92 = load i8, i8* %8
%93 = zext i8 %92 to i64
%94 = getelementptr inbounds [64 x i8], [64 x i8]* %10, i64 0, i64 %93
store i8 0, i8* %94
br label %105
95: ; preds = %78
%96 = load i8, i8* %7
%97 = load i8, i8* %8
%98 = zext i8 %97 to i32
%99 = sub nsw i32 %98, 1
%100 = sext i32 %99 to i64
%101 = getelementptr inbounds [64 x i8], [64 x i8]* %10, i64 0, i64 %100
store i8 %96, i8* %101
%102 = load i8, i8* %8
%103 = zext i8 %102 to i64
%104 = getelementptr inbounds [64 x i8], [64 x i8]* %10, i64 0, i64 %103
store i8 0, i8* %104
br label %105
105: ; preds = %95, %84
br label %106
106: ; preds = %105, %74
br label %107
107: ; preds = %106, %73
br label %108
108: ; preds = %107, %59
br label %109
109: ; preds = %108, %47
br label %23
110: ; preds = %23
%111 = getelementptr inbounds [64 x i8], [64 x i8]* %10, i64 0, i64 0
%112 = call i8* @strdup(i8* %111)
ret i8* %112
}

LLVM IR (-O2):
define noalias i8* @input_line_and_echo(i8 zeroext %0, i8 zeroext %1, i8* %2) {
%4 = alloca [64 x i8]
%5 = getelementptr inbounds [64 x i8], [64 x i8]* %4, i64 0, i64 0
store i8 0, i8* %5
%6 = icmp eq i8* %2, null
br i1 %6, label %11, label %7
7: ; preds = %3
%8 = call i32 @strcpy(i8* %5, i8* %2)
%9 = call zeroext i8 @strlen(i8* %2)
%10 = call zeroext i8 @strlen(i8* %2)
br label %11
11: ; preds = %7, %3
%12 = phi i8 [ %9, %7 ], [ 0, %3 ]
%13 = phi i8 [ %10, %7 ], [ 0, %3 ]
%14 = call i64 @is_a_return(i8 zeroext 0)
%15 = icmp eq i64 %14, 0
br i1 %15, label %16, label %62
16: ; preds = %11, %57
%17 = phi i8 [ %59, %57 ], [ %13, %11 ]
%18 = phi i8 [ %58, %57 ], [ %12, %11 ]
%19 = call zeroext i8 @terminal_get_and_echo(i8 zeroext %18, i8 zeroext %17, i8 zeroext %1, i8 zeroext %0)
%20 = call i32 @is_a_backspace(i8 zeroext %19)
%21 = icmp eq i32 %20, 1
br i1 %21, label %22, label %28
22: ; preds = %16
%23 = icmp eq i8 %18, 0
br i1 %23, label %57, label %24
24: ; preds = %22
%25 = add i8 %18, -1
%26 = zext i8 %25 to i64
%27 = getelementptr inbounds [64 x i8], [64 x i8]* %4, i64 0, i64 %26
store i8 0, i8* %27
br label %57
28: ; preds = %16
%29 = call i32 @is_a_left(i8 zeroext %19)
%30 = icmp eq i32 %29, 1
br i1 %30, label %31, label %35
31: ; preds = %28
%32 = icmp eq i8 %18, 0
%33 = add i8 %18, -1
%34 = select i1 %32, i8 0, i8 %33
br label %57
35: ; preds = %28
%36 = call i32 @is_a_right(i8 zeroext %19)
%37 = icmp eq i32 %36, 1
br i1 %37, label %38, label %42
38: ; preds = %35
%39 = icmp ult i8 %18, %17
%40 = zext i1 %39 to i8
%41 = add i8 %18, %40
br label %57
42: ; preds = %35
%43 = call i64 @is_a_return(i8 zeroext %19)
%44 = icmp eq i64 %43, 0
br i1 %44, label %45, label %57
45: ; preds = %42
%46 = icmp ult i8 %18, %1
%47 = zext i8 %18 to i64
br i1 %46, label %48, label %53
48: ; preds = %45
%49 = getelementptr inbounds [64 x i8], [64 x i8]* %4, i64 0, i64 %47
store i8 %19, i8* %49
%50 = add nuw i8 %18, 1
%51 = zext i8 %50 to i64
%52 = getelementptr inbounds [64 x i8], [64 x i8]* %4, i64 0, i64 %51
store i8 0, i8* %52
br label %57
53: ; preds = %45
%54 = add nsw i64 %47, -1
%55 = getelementptr inbounds [64 x i8], [64 x i8]* %4, i64 0, i64 %54
store i8 %19, i8* %55
%56 = getelementptr inbounds [64 x i8], [64 x i8]* %4, i64 0, i64 %47
store i8 0, i8* %56
br label %57
57: ; preds = %38, %31, %42, %53, %48, %22, %24
%58 = phi i8 [ %25, %24 ], [ 0, %22 ], [ %50, %48 ], [ %18, %53 ], [ %18, %42 ], [ %34, %31 ], [ %41, %38 ]
%59 = phi i8 [ %25, %24 ], [ %17, %22 ], [ %50, %48 ], [ %17, %53 ], [ %17, %42 ], [ %17, %31 ], [ %17, %38 ]
%60 = call i64 @is_a_return(i8 zeroext %19)
%61 = icmp eq i64 %60, 0
br i1 %61, label %16, label %62
62: ; preds = %57, %11
%63 = call i8* @strdup(i8* %5)
ret i8* %63
}