#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 */
char EOF;
int /*<<< orphan*/ printf(char *, char, unsigned short, ...);
int /*<<< orphan*/ ungetch(char);
void ungets(char string[100]) {
  char c1 = 0;
  char c2 = 0;
  char c3 = 0;
  unsigned short int exit = 0;
  unsigned short int i = 0;
  for (i = 0; exit == 0 || string[i] != EOF; i++) {
    if (string[i] == 'r' && string[i + 1] == 'e' && string[i + 2] == 'v') {
      exit = 1;
      printf("exit = 0; s [ %d ] = %c; s [ %d ] = %c; s [ %d ] = %c.\n", i,
             string[i], i + 1, string[i + 1], i + 2, string[i + 2]);
    } else {
      ungetch(string[i]);
      printf("ungetching symbol %c, i = %d.\n", string[i], i);
    };
    if (i > 15) {
      exit = 1;
    };
  }
}


x86 assembly (clang, -O0):
<ungets>:
push   %rbp
mov    %rsp,%rbp
sub    $0x20,%rsp
mov    %rdi,-0x8(%rbp)
movb   $0x0,-0x9(%rbp)
movb   $0x0,-0xa(%rbp)
movb   $0x0,-0xb(%rbp)
movw   $0x0,-0xe(%rbp)
movw   $0x0,-0x10(%rbp)
movw   $0x0,-0x10(%rbp)
movzwl -0xe(%rbp),%ecx
mov    $0x1,%al
cmp    $0x0,%ecx
mov    %al,-0x11(%rbp)
je     117a <ungets+0x5a>
mov    -0x8(%rbp),%rax
movzwl -0x10(%rbp),%ecx
movsbl (%rax,%rcx,1),%eax
mov    0x2e79(%rip),%rcx
movsbl (%rcx),%ecx
cmp    %ecx,%eax
setne  %al
mov    %al,-0x11(%rbp)
mov    -0x11(%rbp),%al
test   $0x1,%al
jne    118a <ungets+0x6a>
jmp    129d <ungets+0x17d>
mov    -0x8(%rbp),%rax
movzwl -0x10(%rbp),%ecx
movsbl (%rax,%rcx,1),%eax
cmp    $0x72,%eax
jne    1243 <ungets+0x123>
mov    -0x8(%rbp),%rax
movzwl -0x10(%rbp),%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
movsbl (%rax,%rcx,1),%eax
cmp    $0x65,%eax
jne    1243 <ungets+0x123>
mov    -0x8(%rbp),%rax
movzwl -0x10(%rbp),%ecx
add    $0x2,%ecx
movslq %ecx,%rcx
movsbl (%rax,%rcx,1),%eax
cmp    $0x76,%eax
jne    1243 <ungets+0x123>
movw   $0x1,-0xe(%rbp)
mov    -0x10(%rbp),%ax
mov    %al,%sil
mov    -0x8(%rbp),%rax
movzwl -0x10(%rbp),%ecx
movsbl (%rax,%rcx,1),%eax
mov    %ax,%dx
movzwl -0x10(%rbp),%ecx
add    $0x1,%ecx
mov    -0x8(%rbp),%rax
movzwl -0x10(%rbp),%edi
add    $0x1,%edi
movslq %edi,%rdi
movsbl (%rax,%rdi,1),%r8d
movzwl -0x10(%rbp),%r9d
add    $0x2,%r9d
mov    -0x8(%rbp),%rax
movzwl -0x10(%rbp),%edi
add    $0x2,%edi
movslq %edi,%rdi
movsbl (%rax,%rdi,1),%eax
lea    0xdd3(%rip),%rdi
movsbl %sil,%esi
movzwl %dx,%edx
mov    %eax,(%rsp)
mov    $0x0,%al
call   1030 <printf@plt>
jmp    1274 <ungets+0x154>
mov    -0x8(%rbp),%rax
movzwl -0x10(%rbp),%ecx
movsbl (%rax,%rcx,1),%edi
call   1040 <ungetch@plt>
mov    -0x8(%rbp),%rax
movzwl -0x10(%rbp),%ecx
mov    (%rax,%rcx,1),%al
lea    0xdd2(%rip),%rdi
movsbl %al,%esi
movzwl -0x10(%rbp),%edx
mov    $0x0,%al
call   1030 <printf@plt>
movzwl -0x10(%rbp),%eax
cmp    $0xf,%eax
jle    1287 <ungets+0x167>
movw   $0x1,-0xe(%rbp)
jmp    128c <ungets+0x16c>
mov    -0x10(%rbp),%ax
add    $0x1,%ax
mov    %ax,-0x10(%rbp)
jmp    114a <ungets+0x2a>
add    $0x20,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<ungets>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
push   %rax
mov    %rdi,%r12
mov    (%rdi),%al
mov    $0x1,%ebp
xor    %r15d,%r15d
xor    %r14d,%r14d
xor    %r13d,%r13d
xchg   %ax,%ax
movzwl %r14w,%ebx
cmp    $0x72,%al
jne    1190 <ungets+0x70>
cmpb   $0x65,0x1(%r12,%rbx,1)
jne    1190 <ungets+0x70>
cmpb   $0x76,0x2(%r12,%rbx,1)
jne    1190 <ungets+0x70>
lea    0x1(%rbx),%rcx
lea    0x2(%rbx),%r9
movl   $0x76,(%rsp)
movsbl %r14b,%esi
lea    0xe8e(%rip),%rdi
mov    $0x72,%edx
mov    $0x65,%r8d
xor    %eax,%eax
call   1030 <printf@plt>
mov    $0x1,%r13w
jmp    11ad <ungets+0x8d>
nopl   0x0(%rax,%rax,1)
movsbl %al,%edi
call   1040 <ungetch@plt>
movsbl (%r12,%r15,1),%esi
lea    0xe94(%rip),%rdi
mov    %ebx,%edx
xor    %eax,%eax
call   1030 <printf@plt>
cmp    $0x10,%r14w
lea    0x1(%r14),%r14d
movzwl %r14w,%r15d
cmovae %ebp,%r13d
movzbl (%r12,%r15,1),%eax
test   %r13w,%r13w
je     1140 <ungets+0x20>
mov    0x2e14(%rip),%rcx
cmp    (%rcx),%al
jne    1140 <ungets+0x20>
add    $0x8,%rsp
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
@EOF = global i8 0
@.str = [56 x i8] c"exit = 0; s [ %d ] = %c; s [ %d ] = %c; s [ %d ] = %c.\0A\00"
@.str.1 = [31 x i8] c"ungetching symbol %c, i = %d.\0A\00"
define void @ungets(i8* %0) {
%2 = alloca i8*
%3 = alloca i8
%4 = alloca i8
%5 = alloca i8
%6 = alloca i16
%7 = alloca i16
store i8* %0, i8** %2
store i8 0, i8* %3
store i8 0, i8* %4
store i8 0, i8* %5
store i16 0, i16* %6
store i16 0, i16* %7
store i16 0, i16* %7
br label %8
8: ; preds = %104, %1
%9 = load i16, i16* %6
%10 = zext i16 %9 to i32
%11 = icmp eq i32 %10, 0
br i1 %11, label %22, label %12
12: ; preds = %8
%13 = load i8*, i8** %2
%14 = load i16, i16* %7
%15 = zext i16 %14 to i64
%16 = getelementptr inbounds i8, i8* %13, i64 %15
%17 = load i8, i8* %16
%18 = sext i8 %17 to i32
%19 = load i8, i8* @EOF
%20 = sext i8 %19 to i32
%21 = icmp ne i32 %18, %20
br label %22
22: ; preds = %12, %8
%23 = phi i1 [ true, %8 ], [ %21, %12 ]
br i1 %23, label %24, label %107
24: ; preds = %22
%25 = load i8*, i8** %2
%26 = load i16, i16* %7
%27 = zext i16 %26 to i64
%28 = getelementptr inbounds i8, i8* %25, i64 %27
%29 = load i8, i8* %28
%30 = sext i8 %29 to i32
%31 = icmp eq i32 %30, 114
br i1 %31, label %32, label %84
32: ; preds = %24
%33 = load i8*, i8** %2
%34 = load i16, i16* %7
%35 = zext i16 %34 to i32
%36 = add nsw i32 %35, 1
%37 = sext i32 %36 to i64
%38 = getelementptr inbounds i8, i8* %33, i64 %37
%39 = load i8, i8* %38
%40 = sext i8 %39 to i32
%41 = icmp eq i32 %40, 101
br i1 %41, label %42, label %84
42: ; preds = %32
%43 = load i8*, i8** %2
%44 = load i16, i16* %7
%45 = zext i16 %44 to i32
%46 = add nsw i32 %45, 2
%47 = sext i32 %46 to i64
%48 = getelementptr inbounds i8, i8* %43, i64 %47
%49 = load i8, i8* %48
%50 = sext i8 %49 to i32
%51 = icmp eq i32 %50, 118
br i1 %51, label %52, label %84
52: ; preds = %42
store i16 1, i16* %6
%53 = load i16, i16* %7
%54 = trunc i16 %53 to i8
%55 = load i8*, i8** %2
%56 = load i16, i16* %7
%57 = zext i16 %56 to i64
%58 = getelementptr inbounds i8, i8* %55, i64 %57
%59 = load i8, i8* %58
%60 = sext i8 %59 to i16
%61 = load i16, i16* %7
%62 = zext i16 %61 to i32
%63 = add nsw i32 %62, 1
%64 = load i8*, i8** %2
%65 = load i16, i16* %7
%66 = zext i16 %65 to i32
%67 = add nsw i32 %66, 1
%68 = sext i32 %67 to i64
%69 = getelementptr inbounds i8, i8* %64, i64 %68
%70 = load i8, i8* %69
%71 = sext i8 %70 to i32
%72 = load i16, i16* %7
%73 = zext i16 %72 to i32
%74 = add nsw i32 %73, 2
%75 = load i8*, i8** %2
%76 = load i16, i16* %7
%77 = zext i16 %76 to i32
%78 = add nsw i32 %77, 2
%79 = sext i32 %78 to i64
%80 = getelementptr inbounds i8, i8* %75, i64 %79
%81 = load i8, i8* %80
%82 = sext i8 %81 to i32
%83 = call i32 (i8*, i8, i16, ...) @printf(i8* getelementptr inbounds ([56 x i8], [56 x i8]* @.str, i64 0, i64 0), i8 signext %54, i16 zeroext %60, i32 %63, i32 %71, i32 %74, i32 %82)
br label %98
84: ; preds = %42, %32, %24
%85 = load i8*, i8** %2
%86 = load i16, i16* %7
%87 = zext i16 %86 to i64
%88 = getelementptr inbounds i8, i8* %85, i64 %87
%89 = load i8, i8* %88
%90 = call i32 @ungetch(i8 signext %89)
%91 = load i8*, i8** %2
%92 = load i16, i16* %7
%93 = zext i16 %92 to i64
%94 = getelementptr inbounds i8, i8* %91, i64 %93
%95 = load i8, i8* %94
%96 = load i16, i16* %7
%97 = call i32 (i8*, i8, i16, ...) @printf(i8* getelementptr inbounds ([31 x i8], [31 x i8]* @.str.1, i64 0, i64 0), i8 signext %95, i16 zeroext %96)
br label %98
98: ; preds = %84, %52
%99 = load i16, i16* %7
%100 = zext i16 %99 to i32
%101 = icmp sgt i32 %100, 15
br i1 %101, label %102, label %103
102: ; preds = %98
store i16 1, i16* %6
br label %103
103: ; preds = %102, %98
br label %104
104: ; preds = %103
%105 = load i16, i16* %7
%106 = add i16 %105, 1
store i16 %106, i16* %7
br label %8
107: ; preds = %22
ret void
}

LLVM IR (-O2):
@EOF = global i8 0
@.str = [56 x i8] c"exit = 0; s [ %d ] = %c; s [ %d ] = %c; s [ %d ] = %c.\0A\00"
@.str.1 = [31 x i8] c"ungetching symbol %c, i = %d.\0A\00"
define void @ungets(i8* nocapture %0) {
%2 = load i8, i8* %0
br label %3
3: ; preds = %1, %30
%4 = phi i8 [ %2, %1 ], [ %38, %30 ]
%5 = phi i64 [ 0, %1 ], [ %36, %30 ]
%6 = phi i16 [ 0, %1 ], [ %33, %30 ]
%7 = phi i16 [ 0, %1 ], [ %34, %30 ]
%8 = getelementptr inbounds i8, i8* %0, i64 %5
%9 = icmp eq i8 %4, 114
br i1 %9, label %10, label %26
10: ; preds = %3
%11 = zext i16 %6 to i32
%12 = add nuw nsw i32 %11, 1
%13 = zext i32 %12 to i64
%14 = getelementptr inbounds i8, i8* %0, i64 %13
%15 = load i8, i8* %14
%16 = icmp eq i8 %15, 101
br i1 %16, label %17, label %26
17: ; preds = %10
%18 = add nuw nsw i32 %11, 2
%19 = zext i32 %18 to i64
%20 = getelementptr inbounds i8, i8* %0, i64 %19
%21 = load i8, i8* %20
%22 = icmp eq i8 %21, 118
br i1 %22, label %23, label %26
23: ; preds = %17
%24 = trunc i16 %6 to i8
%25 = tail call i32 (i8*, i8, i16, ...) @printf(i8* getelementptr inbounds ([56 x i8], [56 x i8]* @.str, i64 0, i64 0), i8 signext %24, i16 zeroext 114, i32 %12, i32 101, i32 %18, i32 118)
br label %30
26: ; preds = %17, %10, %3
%27 = tail call i32 @ungetch(i8 signext %4)
%28 = load i8, i8* %8
%29 = tail call i32 (i8*, i8, i16, ...) @printf(i8* getelementptr inbounds ([31 x i8], [31 x i8]* @.str.1, i64 0, i64 0), i8 signext %28, i16 zeroext %6)
br label %30
30: ; preds = %26, %23
%31 = phi i16 [ 1, %23 ], [ %7, %26 ]
%32 = icmp ugt i16 %6, 15
%33 = add i16 %6, 1
%34 = select i1 %32, i16 1, i16 %31
%35 = icmp ne i16 %34, 0
%36 = zext i16 %33 to i64
%37 = getelementptr inbounds i8, i8* %0, i64 %36
%38 = load i8, i8* %37
%39 = load i8, i8* @EOF
%40 = icmp eq i8 %38, %39
%41 = select i1 %35, i1 %40, i1 false
br i1 %41, label %42, label %3
42: ; preds = %30
ret void
}