#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 */
typedef int /*<<< orphan*/ to;
struct termios {
  int /*<<< orphan*/ c_lflag;
};

/* Variables and functions */
int /*<<< orphan*/ ECHO;
int /*<<< orphan*/ ICANON;
int /*<<< orphan*/ ISIG;
int /*<<< orphan*/ STDIN_FILENO;
int /*<<< orphan*/ TCSADRAIN;
int /*<<< orphan*/ abort();
int asprintf(char **, char *, int /*<<< orphan*/);
struct termios *calloc(int, int);
int /*<<< orphan*/ errno;
int /*<<< orphan*/ fprintf(int /*<<< orphan*/, char *);
int /*<<< orphan*/ free(struct termios *);
int /*<<< orphan*/ memcpy(struct termios *, struct termios *, int);
int /*<<< orphan*/ stderr;
scalar_t__ strerror_r(int /*<<< orphan*/, char *, int);
int tcgetattr(int /*<<< orphan*/, struct termios *);
int tcsetattr(int /*<<< orphan*/, int /*<<< orphan*/, struct termios *);
struct termios *set_character_mode(char **errmsg) {
  struct termios to;
  struct termios *old = calloc(sizeof(to), 1);
  if (!old) {
    fprintf(stderr, "Out of memory.\n");
    abort();
  }
  if (tcgetattr(STDIN_FILENO, &to) == -1) {
    if (asprintf(errmsg, "tcgetattr() failed: %d", errno) == -1) {
      fprintf(stderr, "Out of memory.\n");
      abort();
    }
    free(old);
    return NULL;
  }
  memcpy(old, &to, sizeof(to));
  to.c_lflag &= ~ECHO;
  to.c_lflag &= ~ISIG;
  to.c_lflag &= ~ICANON;
  if (tcsetattr(STDIN_FILENO, TCSADRAIN, &to) == -1) {
    char buf[1000];
    if (strerror_r(errno, buf, 1000)) {
      fprintf(stderr, "strerror_r() failed.\n");
      abort();
    }
    if (asprintf(errmsg, "tcgetattr() failed: %d", errno) == -1) {
      fprintf(stderr, "Out of memory.\n");
      abort();
    }
    free(old);
    return NULL;
  }
  return old;
}


x86 assembly (clang, -O0):
<set_character_mode>:
push   %rbp
mov    %rsp,%rbp
sub    $0x410,%rsp
mov    %rdi,-0x10(%rbp)
mov    $0x4,%edi
mov    $0x1,%esi
call   1050 <calloc@plt>
mov    %rax,-0x20(%rbp)
cmpq   $0x0,-0x20(%rbp)
jne    11d9 <set_character_mode+0x49>
mov    0x2e0c(%rip),%rax
mov    (%rax),%edi
lea    0xe33(%rip),%rsi
call   1060 <fprintf@plt>
mov    $0x0,%al
call   1040 <abort@plt>
mov    0x2dd8(%rip),%rax
mov    (%rax),%edi
lea    -0x18(%rbp),%rsi
call   10a0 <tcgetattr@plt>
cmp    $0xffffffff,%eax
jne    1248 <set_character_mode+0xb8>
mov    -0x10(%rbp),%rdi
mov    0x2dc1(%rip),%rax
mov    (%rax),%edx
lea    0xe08(%rip),%rsi
call   1090 <asprintf@plt>
cmp    $0xffffffff,%eax
jne    1232 <set_character_mode+0xa2>
mov    0x2db3(%rip),%rax
mov    (%rax),%edi
lea    0xdda(%rip),%rsi
call   1060 <fprintf@plt>
mov    $0x0,%al
call   1040 <abort@plt>
mov    -0x20(%rbp),%rdi
call   1030 <free@plt>
movq   $0x0,-0x8(%rbp)
jmp    1350 <set_character_mode+0x1c0>
mov    -0x20(%rbp),%rdi
lea    -0x18(%rbp),%rsi
mov    $0x4,%edx
call   1070 <memcpy@plt>
mov    0x2d87(%rip),%rax
mov    (%rax),%eax
xor    $0xffffffff,%eax
and    -0x18(%rbp),%eax
mov    %eax,-0x18(%rbp)
mov    0x2d6d(%rip),%rax
mov    (%rax),%eax
xor    $0xffffffff,%eax
and    -0x18(%rbp),%eax
mov    %eax,-0x18(%rbp)
mov    0x2d2b(%rip),%rax
mov    (%rax),%eax
xor    $0xffffffff,%eax
and    -0x18(%rbp),%eax
mov    %eax,-0x18(%rbp)
mov    0x2d21(%rip),%rax
mov    (%rax),%edi
mov    0x2d28(%rip),%rax
mov    (%rax),%esi
lea    -0x18(%rbp),%rdx
call   10b0 <tcsetattr@plt>
cmp    $0xffffffff,%eax
jne    1348 <set_character_mode+0x1b8>
mov    0x2d05(%rip),%rax
mov    (%rax),%edi
lea    -0x410(%rbp),%rsi
mov    $0x3e8,%edx
call   1080 <strerror_r@plt>
cmp    $0x0,%rax
je     12f4 <set_character_mode+0x164>
mov    0x2cf1(%rip),%rax
mov    (%rax),%edi
lea    0xd3f(%rip),%rsi
call   1060 <fprintf@plt>
mov    $0x0,%al
call   1040 <abort@plt>
mov    -0x10(%rbp),%rdi
mov    0x2cc1(%rip),%rax
mov    (%rax),%edx
lea    0xd08(%rip),%rsi
call   1090 <asprintf@plt>
cmp    $0xffffffff,%eax
jne    1332 <set_character_mode+0x1a2>
mov    0x2cb3(%rip),%rax
mov    (%rax),%edi
lea    0xcda(%rip),%rsi
call   1060 <fprintf@plt>
mov    $0x0,%al
call   1040 <abort@plt>
mov    -0x20(%rbp),%rdi
call   1030 <free@plt>
movq   $0x0,-0x8(%rbp)
jmp    1350 <set_character_mode+0x1c0>
mov    -0x20(%rbp),%rax
mov    %rax,-0x8(%rbp)
mov    -0x8(%rbp),%rax
add    $0x410,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<set_character_mode>:
push   %r15
push   %r14
push   %r12
push   %rbx
sub    $0x3f8,%rsp
mov    %rdi,%r14
mov    $0x4,%edi
mov    $0x1,%esi
call   1050 <calloc@plt>
test   %rax,%rax
je     1282 <set_character_mode+0xf2>
mov    %rax,%rbx
mov    0x2df5(%rip),%r12
mov    (%r12),%edi
lea    0x8(%rsp),%rsi
call   10a0 <tcgetattr@plt>
cmp    $0xffffffff,%eax
je     1249 <set_character_mode+0xb9>
lea    0x8(%rsp),%r15
mov    %rbx,%rdi
mov    %r15,%rsi
mov    $0x4,%edx
call   1070 <memcpy@plt>
mov    0x2df6(%rip),%rax
mov    (%rax),%eax
mov    0x2de5(%rip),%rcx
or     (%rcx),%eax
mov    0x2dac(%rip),%rcx
or     (%rcx),%eax
not    %eax
and    %eax,0x8(%rsp)
mov    (%r12),%edi
mov    0x2db1(%rip),%rax
mov    (%rax),%esi
mov    %r15,%rdx
call   10b0 <tcsetattr@plt>
cmp    $0xffffffff,%eax
jne    1270 <set_character_mode+0xe0>
mov    0x2d93(%rip),%r15
mov    (%r15),%edi
lea    0x10(%rsp),%rsi
mov    $0x3e8,%edx
call   1080 <strerror_r@plt>
test   %rax,%rax
jne    129e <set_character_mode+0x10e>
mov    (%r15),%edx
jmp    1252 <set_character_mode+0xc2>
mov    0x2d70(%rip),%rax
mov    (%rax),%edx
lea    0xdb7(%rip),%rsi
mov    %r14,%rdi
call   1090 <asprintf@plt>
cmp    $0xffffffff,%eax
je     1282 <set_character_mode+0xf2>
mov    %rbx,%rdi
call   1030 <free@plt>
xor    %ebx,%ebx
mov    %rbx,%rax
add    $0x3f8,%rsp
pop    %rbx
pop    %r12
pop    %r14
pop    %r15
ret
mov    0x2d47(%rip),%rax
mov    (%rax),%edi
lea    0xd6e(%rip),%rsi
call   1060 <fprintf@plt>
xor    %eax,%eax
call   1040 <abort@plt>
mov    0x2d2b(%rip),%rax
mov    (%rax),%edi
lea    0xd79(%rip),%rsi
jmp    1292 <set_character_mode+0x102>

LLVM IR (-O0):
%struct.termios = type { i32 }
@stderr = global i32 0
@.str = [16 x i8] c"Out of memory.\0A\00"
@STDIN_FILENO = global i32 0
@.str.1 = [23 x i8] c"tcgetattr() failed: %d\00"
@errno = global i32 0
@ECHO = global i32 0
@ISIG = global i32 0
@ICANON = global i32 0
@TCSADRAIN = global i32 0
@.str.2 = [22 x i8] c"strerror_r() failed.\0A\00"
define %struct.termios* @set_character_mode(i8** %0) {
%2 = alloca %struct.termios*
%3 = alloca i8**
%4 = alloca %struct.termios
%5 = alloca %struct.termios*
%6 = alloca [1000 x i8]
store i8** %0, i8*** %3
%7 = call %struct.termios* @calloc(i32 4, i32 1)
store %struct.termios* %7, %struct.termios** %5
%8 = load %struct.termios*, %struct.termios** %5
%9 = icmp ne %struct.termios* %8, null
br i1 %9, label %14, label %10
10: ; preds = %1
%11 = load i32, i32* @stderr
%12 = call i32 @fprintf(i32 %11, i8* getelementptr inbounds ([16 x i8], [16 x i8]* @.str, i64 0, i64 0))
%13 = call i32 (...) @abort()
unreachable
14: ; preds = %1
%15 = load i32, i32* @STDIN_FILENO
%16 = call i32 @tcgetattr(i32 %15, %struct.termios* %4)
%17 = icmp eq i32 %16, -1
br i1 %17, label %18, label %30
18: ; preds = %14
%19 = load i8**, i8*** %3
%20 = load i32, i32* @errno
%21 = call i32 @asprintf(i8** %19, i8* getelementptr inbounds ([23 x i8], [23 x i8]* @.str.1, i64 0, i64 0), i32 %20)
%22 = icmp eq i32 %21, -1
br i1 %22, label %23, label %27
23: ; preds = %18
%24 = load i32, i32* @stderr
%25 = call i32 @fprintf(i32 %24, i8* getelementptr inbounds ([16 x i8], [16 x i8]* @.str, i64 0, i64 0))
%26 = call i32 (...) @abort()
unreachable
27: ; preds = %18
%28 = load %struct.termios*, %struct.termios** %5
%29 = call i32 @free(%struct.termios* %28)
store %struct.termios* null, %struct.termios** %2
br label %75
30: ; preds = %14
%31 = load %struct.termios*, %struct.termios** %5
%32 = call i32 @memcpy(%struct.termios* %31, %struct.termios* %4, i32 4)
%33 = load i32, i32* @ECHO
%34 = xor i32 %33, -1
%35 = getelementptr inbounds %struct.termios, %struct.termios* %4, i32 0, i32 0
%36 = load i32, i32* %35
%37 = and i32 %36, %34
store i32 %37, i32* %35
%38 = load i32, i32* @ISIG
%39 = xor i32 %38, -1
%40 = getelementptr inbounds %struct.termios, %struct.termios* %4, i32 0, i32 0
%41 = load i32, i32* %40
%42 = and i32 %41, %39
store i32 %42, i32* %40
%43 = load i32, i32* @ICANON
%44 = xor i32 %43, -1
%45 = getelementptr inbounds %struct.termios, %struct.termios* %4, i32 0, i32 0
%46 = load i32, i32* %45
%47 = and i32 %46, %44
store i32 %47, i32* %45
%48 = load i32, i32* @STDIN_FILENO
%49 = load i32, i32* @TCSADRAIN
%50 = call i32 @tcsetattr(i32 %48, i32 %49, %struct.termios* %4)
%51 = icmp eq i32 %50, -1
br i1 %51, label %52, label %73
52: ; preds = %30
%53 = load i32, i32* @errno
%54 = getelementptr inbounds [1000 x i8], [1000 x i8]* %6, i64 0, i64 0
%55 = call i64 @strerror_r(i32 %53, i8* %54, i32 1000)
%56 = icmp ne i64 %55, 0
br i1 %56, label %57, label %61
57: ; preds = %52
%58 = load i32, i32* @stderr
%59 = call i32 @fprintf(i32 %58, i8* getelementptr inbounds ([22 x i8], [22 x i8]* @.str.2, i64 0, i64 0))
%60 = call i32 (...) @abort()
unreachable
61: ; preds = %52
%62 = load i8**, i8*** %3
%63 = load i32, i32* @errno
%64 = call i32 @asprintf(i8** %62, i8* getelementptr inbounds ([23 x i8], [23 x i8]* @.str.1, i64 0, i64 0), i32 %63)
%65 = icmp eq i32 %64, -1
br i1 %65, label %66, label %70
66: ; preds = %61
%67 = load i32, i32* @stderr
%68 = call i32 @fprintf(i32 %67, i8* getelementptr inbounds ([16 x i8], [16 x i8]* @.str, i64 0, i64 0))
%69 = call i32 (...) @abort()
unreachable
70: ; preds = %61
%71 = load %struct.termios*, %struct.termios** %5
%72 = call i32 @free(%struct.termios* %71)
store %struct.termios* null, %struct.termios** %2
br label %75
73: ; preds = %30
%74 = load %struct.termios*, %struct.termios** %5
store %struct.termios* %74, %struct.termios** %2
br label %75
75: ; preds = %73, %70, %27
%76 = load %struct.termios*, %struct.termios** %2
ret %struct.termios* %76
}

LLVM IR (-O2):
%struct.termios = type { i32 }
@stderr = global i32 0
@.str = [16 x i8] c"Out of memory.\0A\00"
@STDIN_FILENO = global i32 0
@.str.1 = [23 x i8] c"tcgetattr() failed: %d\00"
@errno = global i32 0
@ECHO = global i32 0
@ISIG = global i32 0
@ICANON = global i32 0
@TCSADRAIN = global i32 0
@.str.2 = [22 x i8] c"strerror_r() failed.\0A\00"
define %struct.termios* @set_character_mode(i8** %0) {
%2 = alloca %struct.termios
%3 = alloca [1000 x i8]
%4 = bitcast %struct.termios* %2 to i8*
%5 = tail call %struct.termios* @calloc(i32 4, i32 1)
%6 = icmp eq %struct.termios* %5, null
br i1 %6, label %7, label %11
7: ; preds = %1
%8 = load i32, i32* @stderr
%9 = tail call i32 @fprintf(i32 %8, i8* getelementptr inbounds ([16 x i8], [16 x i8]* @.str, i64 0, i64 0))
%10 = tail call i32 (...) @abort()
unreachable
11: ; preds = %1
%12 = load i32, i32* @STDIN_FILENO
%13 = call i32 @tcgetattr(i32 %12, %struct.termios* %2)
%14 = icmp eq i32 %13, -1
br i1 %14, label %15, label %25
15: ; preds = %11
%16 = load i32, i32* @errno
%17 = call i32 @asprintf(i8** %0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* @.str.1, i64 0, i64 0), i32 %16)
%18 = icmp eq i32 %17, -1
br i1 %18, label %19, label %23
19: ; preds = %15
%20 = load i32, i32* @stderr
%21 = call i32 @fprintf(i32 %20, i8* getelementptr inbounds ([16 x i8], [16 x i8]* @.str, i64 0, i64 0))
%22 = call i32 (...) @abort()
unreachable
23: ; preds = %15
%24 = call i32 @free(%struct.termios* %5)
br label %59
25: ; preds = %11
%26 = call i32 @memcpy(%struct.termios* %5, %struct.termios* %2, i32 4)
%27 = load i32, i32* @ECHO
%28 = getelementptr inbounds %struct.termios, %struct.termios* %2, i64 0, i32 0
%29 = load i32, i32* %28
%30 = load i32, i32* @ISIG
%31 = or i32 %27, %30
%32 = load i32, i32* @ICANON
%33 = or i32 %31, %32
%34 = xor i32 %33, -1
%35 = and i32 %29, %34
store i32 %35, i32* %28
%36 = load i32, i32* @STDIN_FILENO
%37 = load i32, i32* @TCSADRAIN
%38 = call i32 @tcsetattr(i32 %36, i32 %37, %struct.termios* %2)
%39 = icmp eq i32 %38, -1
br i1 %39, label %40, label %59
40: ; preds = %25
%41 = getelementptr inbounds [1000 x i8], [1000 x i8]* %3, i64 0, i64 0
%42 = load i32, i32* @errno
%43 = call i64 @strerror_r(i32 %42, i8* %41, i32 1000)
%44 = icmp eq i64 %43, 0
br i1 %44, label %49, label %45
45: ; preds = %40
%46 = load i32, i32* @stderr
%47 = call i32 @fprintf(i32 %46, i8* getelementptr inbounds ([22 x i8], [22 x i8]* @.str.2, i64 0, i64 0))
%48 = call i32 (...) @abort()
unreachable
49: ; preds = %40
%50 = load i32, i32* @errno
%51 = call i32 @asprintf(i8** %0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* @.str.1, i64 0, i64 0), i32 %50)
%52 = icmp eq i32 %51, -1
br i1 %52, label %53, label %57
53: ; preds = %49
%54 = load i32, i32* @stderr
%55 = call i32 @fprintf(i32 %54, i8* getelementptr inbounds ([16 x i8], [16 x i8]* @.str, i64 0, i64 0))
%56 = call i32 (...) @abort()
unreachable
57: ; preds = %49
%58 = call i32 @free(%struct.termios* %5)
br label %59
59: ; preds = %25, %57, %23
%60 = phi %struct.termios* [ null, %23 ], [ null, %57 ], [ %5, %25 ]
ret %struct.termios* %60
}