#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 */
struct template_buffer {
  int dummy;
};
typedef int /*<<< orphan*/ esq;

/* Variables and functions */
int /*<<< orphan*/ buf_append(struct template_buffer *, char *, int);
char *buf_destroy(struct template_buffer *);
struct template_buffer *buf_init(unsigned int);
int /*<<< orphan*/ buf_putchar(struct template_buffer *, unsigned char);
scalar_t__ isalpha(unsigned char);
scalar_t__ isspace(unsigned char);
int snprintf(char *, int, char *, unsigned char);
char *striptags(const char *s, unsigned int l) {
  struct template_buffer *buf = buf_init(l);
  unsigned char *ptr = (unsigned char *)s;
  unsigned char *end = ptr + l;
  unsigned char *tag;
  unsigned char prev;
  char esq[8];
  int esl;
  for (prev = ' '; ptr < end; ptr++) {
    if ((*ptr == '<') && ((ptr + 2) < end) &&
        ((*(ptr + 1) == '/') || isalpha(*(ptr + 1)))) {
      for (tag = ptr; tag < end; tag++) {
        if (*tag == '>') {
          if (!isspace(prev))
            buf_putchar(buf, ' ');
          ptr = tag;
          prev = ' ';
          break;
        }
      }
    } else if (isspace(*ptr)) {
      if (!isspace(prev))
        buf_putchar(buf, *ptr);
      prev = *ptr;
    } else {
      switch (*ptr) {
      case '"':
      case '\'':
      case '<':
      case '>':
      case '&':
        esl = snprintf(esq, sizeof(esq), "&#%i;", *ptr);
        buf_append(buf, esq, esl);
        break;
      default:
        buf_putchar(buf, *ptr);
        break;
      }
      prev = *ptr;
    }
  }
  return buf_destroy(buf);
}


x86 assembly (clang, -O0):
<striptags>:
push   %rbp
mov    %rsp,%rbp
sub    $0x50,%rsp
mov    %rdi,-0x8(%rbp)
mov    %esi,-0xc(%rbp)
mov    -0xc(%rbp),%edi
call   1070 <buf_init@plt>
mov    %rax,-0x18(%rbp)
mov    -0x8(%rbp),%rax
mov    %rax,-0x20(%rbp)
mov    -0x20(%rbp),%rax
mov    -0xc(%rbp),%ecx
add    %rcx,%rax
mov    %rax,-0x28(%rbp)
movb   $0x20,-0x31(%rbp)
mov    -0x20(%rbp),%rax
cmp    -0x28(%rbp),%rax
jae    136d <striptags+0x1fd>
mov    -0x20(%rbp),%rax
movzbl (%rax),%eax
cmp    $0x3c,%eax
jne    1270 <striptags+0x100>
mov    -0x20(%rbp),%rax
add    $0x2,%rax
cmp    -0x28(%rbp),%rax
jae    1270 <striptags+0x100>
mov    -0x20(%rbp),%rax
movzbl 0x1(%rax),%eax
cmp    $0x2f,%eax
je     11fd <striptags+0x8d>
mov    -0x20(%rbp),%rax
movzbl 0x1(%rax),%edi
call   1060 <isalpha@plt>
cmp    $0x0,%rax
je     1270 <striptags+0x100>
mov    -0x20(%rbp),%rax
mov    %rax,-0x30(%rbp)
mov    -0x30(%rbp),%rax
cmp    -0x28(%rbp),%rax
jae    126b <striptags+0xfb>
mov    -0x30(%rbp),%rax
movzbl (%rax),%eax
cmp    $0x3e,%eax
jne    1255 <striptags+0xe5>
movzbl -0x31(%rbp),%edi
call   1040 <isspace@plt>
cmp    $0x0,%rax
jne    1244 <striptags+0xd4>
mov    -0x18(%rbp),%rdi
mov    $0x20,%esi
call   1090 <buf_putchar@plt>
mov    -0x30(%rbp),%rax
mov    %rax,-0x20(%rbp)
movb   $0x20,-0x31(%rbp)
jmp    126b <striptags+0xfb>
jmp    125a <striptags+0xea>
mov    -0x30(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x30(%rbp)
jmp    1205 <striptags+0x95>
jmp    1357 <striptags+0x1e7>
mov    -0x20(%rbp),%rax
movzbl (%rax),%edi
call   1040 <isspace@plt>
cmp    $0x0,%rax
je     12b7 <striptags+0x147>
movzbl -0x31(%rbp),%edi
call   1040 <isspace@plt>
cmp    $0x0,%rax
jne    12a9 <striptags+0x139>
mov    -0x18(%rbp),%rdi
mov    -0x20(%rbp),%rax
movzbl (%rax),%esi
call   1090 <buf_putchar@plt>
mov    -0x20(%rbp),%rax
mov    (%rax),%al
mov    %al,-0x31(%rbp)
jmp    1352 <striptags+0x1e2>
mov    -0x20(%rbp),%rax
movzbl (%rax),%eax
mov    %eax,-0x44(%rbp)
sub    $0x22,%eax
je     1305 <striptags+0x195>
jmp    12cf <striptags+0x15f>
mov    -0x44(%rbp),%eax
add    $0xffffffda,%eax
sub    $0x2,%eax
jb     1305 <striptags+0x195>
jmp    12e3 <striptags+0x173>
mov    -0x44(%rbp),%eax
sub    $0x3c,%eax
je     1305 <striptags+0x195>
jmp    12f4 <striptags+0x184>
mov    -0x44(%rbp),%eax
sub    $0x3e,%eax
jne    1339 <striptags+0x1c9>
jmp    1305 <striptags+0x195>
lea    -0x39(%rbp),%rdi
mov    -0x20(%rbp),%rax
mov    $0x8,%esi
lea    0xce7(%rip),%rdx
movzbl (%rax),%ecx
call   1030 <snprintf@plt>
mov    %eax,-0x40(%rbp)
mov    -0x18(%rbp),%rdi
lea    -0x39(%rbp),%rsi
mov    -0x40(%rbp),%edx
call   1050 <buf_append@plt>
jmp    1349 <striptags+0x1d9>
mov    -0x18(%rbp),%rdi
mov    -0x20(%rbp),%rax
movzbl (%rax),%esi
call   1090 <buf_putchar@plt>
mov    -0x20(%rbp),%rax
mov    (%rax),%al
mov    %al,-0x31(%rbp)
jmp    1357 <striptags+0x1e7>
jmp    135c <striptags+0x1ec>
mov    -0x20(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x20(%rbp)
jmp    11a5 <striptags+0x35>
mov    -0x18(%rbp),%rdi
call   1080 <buf_destroy@plt>
add    $0x50,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<striptags>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
push   %rax
mov    %esi,%ebp
mov    %rdi,%r13
mov    %esi,%edi
call   1070 <buf_init@plt>
mov    %rax,%r12
test   %ebp,%ebp
je     12b1 <striptags+0x141>
mov    %ebp,%ebp
add    %r13,%rbp
mov    $0x20,%r14b
mov    %rsp,%r15
jmp    11bb <striptags+0x4b>
movzbl %al,%esi
mov    %r12,%rdi
call   1090 <buf_putchar@plt>
mov    0x0(%r13),%r14b
add    $0x1,%r13
cmp    %rbp,%r13
jae    12b1 <striptags+0x141>
mov    0x0(%r13),%al
cmp    $0x3c,%al
jne    1220 <striptags+0xb0>
lea    0x2(%r13),%rcx
cmp    %rbp,%rcx
jae    1220 <striptags+0xb0>
mov    0x1(%r13),%al
cmp    $0x2f,%al
je     11e1 <striptags+0x71>
movzbl %al,%edi
call   1060 <isalpha@plt>
test   %rax,%rax
je     121a <striptags+0xaa>
cmp    %rbp,%r13
jae    11ae <striptags+0x3e>
mov    %r13,%rbx
nopl   0x0(%rax)
cmpb   $0x3e,(%rbx)
je     1200 <striptags+0x90>
add    $0x1,%rbx
cmp    %rbp,%rbx
jb     11f0 <striptags+0x80>
jmp    11ae <striptags+0x3e>
movzbl %r14b,%edi
call   1040 <isspace@plt>
mov    $0x20,%r14b
test   %rax,%rax
je     129c <striptags+0x12c>
mov    %rbx,%r13
jmp    11ae <striptags+0x3e>
mov    0x0(%r13),%al
xchg   %ax,%ax
movzbl %al,%edi
call   1040 <isspace@plt>
test   %rax,%rax
je     1250 <striptags+0xe0>
movzbl %r14b,%edi
call   1040 <isspace@plt>
test   %rax,%rax
jne    11aa <striptags+0x3a>
movzbl 0x0(%r13),%esi
jmp    11a2 <striptags+0x32>
nopl   0x0(%rax)
movzbl 0x0(%r13),%eax
cmp    $0x3e,%rax
ja     119f <striptags+0x2f>
movabs $0x500000c400000000,%rcx
bt     %rax,%rcx
jae    119f <striptags+0x2f>
movzbl %al,%ecx
mov    %r15,%rdi
mov    $0x8,%esi
lea    0xd7b(%rip),%rdx
call   1030 <snprintf@plt>
mov    %r12,%rdi
mov    %r15,%rsi
mov    %eax,%edx
call   1050 <buf_append@plt>
jmp    11aa <striptags+0x3a>
mov    %r12,%rdi
mov    $0x20,%esi
call   1090 <buf_putchar@plt>
mov    %rbx,%r13
jmp    11ae <striptags+0x3e>
mov    %r12,%rdi
call   1080 <buf_destroy@plt>
add    $0x8,%rsp
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
%struct.template_buffer = type { i32 }
@.str = [6 x i8] c"&#%i;\00"
define i8* @striptags(i8* %0, i32 %1) {
%3 = alloca i8*
%4 = alloca i32
%5 = alloca %struct.template_buffer*
%6 = alloca i8*
%7 = alloca i8*
%8 = alloca i8*
%9 = alloca i8
%10 = alloca [8 x i8]
%11 = alloca i32
store i8* %0, i8** %3
store i32 %1, i32* %4
%12 = load i32, i32* %4
%13 = call %struct.template_buffer* @buf_init(i32 %12)
store %struct.template_buffer* %13, %struct.template_buffer** %5
%14 = load i8*, i8** %3
store i8* %14, i8** %6
%15 = load i8*, i8** %6
%16 = load i32, i32* %4
%17 = zext i32 %16 to i64
%18 = getelementptr inbounds i8, i8* %15, i64 %17
store i8* %18, i8** %7
store i8 32, i8* %9
br label %19
19: ; preds = %110, %2
%20 = load i8*, i8** %6
%21 = load i8*, i8** %7
%22 = icmp ult i8* %20, %21
br i1 %22, label %23, label %113
23: ; preds = %19
%24 = load i8*, i8** %6
%25 = load i8, i8* %24
%26 = zext i8 %25 to i32
%27 = icmp eq i32 %26, 60
br i1 %27, label %28, label %70
28: ; preds = %23
%29 = load i8*, i8** %6
%30 = getelementptr inbounds i8, i8* %29, i64 2
%31 = load i8*, i8** %7
%32 = icmp ult i8* %30, %31
br i1 %32, label %33, label %70
33: ; preds = %28
%34 = load i8*, i8** %6
%35 = getelementptr inbounds i8, i8* %34, i64 1
%36 = load i8, i8* %35
%37 = zext i8 %36 to i32
%38 = icmp eq i32 %37, 47
br i1 %38, label %45, label %39
39: ; preds = %33
%40 = load i8*, i8** %6
%41 = getelementptr inbounds i8, i8* %40, i64 1
%42 = load i8, i8* %41
%43 = call i64 @isalpha(i8 zeroext %42)
%44 = icmp ne i64 %43, 0
br i1 %44, label %45, label %70
45: ; preds = %39, %33
%46 = load i8*, i8** %6
store i8* %46, i8** %8
br label %47
47: ; preds = %66, %45
%48 = load i8*, i8** %8
%49 = load i8*, i8** %7
%50 = icmp ult i8* %48, %49
br i1 %50, label %51, label %69
51: ; preds = %47
%52 = load i8*, i8** %8
%53 = load i8, i8* %52
%54 = zext i8 %53 to i32
%55 = icmp eq i32 %54, 62
br i1 %55, label %56, label %65
56: ; preds = %51
%57 = load i8, i8* %9
%58 = call i64 @isspace(i8 zeroext %57)
%59 = icmp ne i64 %58, 0
br i1 %59, label %63, label %60
60: ; preds = %56
%61 = load %struct.template_buffer*, %struct.template_buffer** %5
%62 = call i32 @buf_putchar(%struct.template_buffer* %61, i8 zeroext 32)
br label %63
63: ; preds = %60, %56
%64 = load i8*, i8** %8
store i8* %64, i8** %6
store i8 32, i8* %9
br label %69
65: ; preds = %51
br label %66
66: ; preds = %65
%67 = load i8*, i8** %8
%68 = getelementptr inbounds i8, i8* %67, i32 1
store i8* %68, i8** %8
br label %47
69: ; preds = %63, %47
br label %109
70: ; preds = %39, %28, %23
%71 = load i8*, i8** %6
%72 = load i8, i8* %71
%73 = call i64 @isspace(i8 zeroext %72)
%74 = icmp ne i64 %73, 0
br i1 %74, label %75, label %87
75: ; preds = %70
%76 = load i8, i8* %9
%77 = call i64 @isspace(i8 zeroext %76)
%78 = icmp ne i64 %77, 0
br i1 %78, label %84, label %79
79: ; preds = %75
%80 = load %struct.template_buffer*, %struct.template_buffer** %5
%81 = load i8*, i8** %6
%82 = load i8, i8* %81
%83 = call i32 @buf_putchar(%struct.template_buffer* %80, i8 zeroext %82)
br label %84
84: ; preds = %79, %75
%85 = load i8*, i8** %6
%86 = load i8, i8* %85
store i8 %86, i8* %9
br label %108
87: ; preds = %70
%88 = load i8*, i8** %6
%89 = load i8, i8* %88
%90 = zext i8 %89 to i32
switch i32 %90, label %100 [
i32 34, label %91
i32 39, label %91
i32 60, label %91
i32 62, label %91
i32 38, label %91
]
91: ; preds = %87, %87, %87, %87, %87
%92 = getelementptr inbounds [8 x i8], [8 x i8]* %10, i64 0, i64 0
%93 = load i8*, i8** %6
%94 = load i8, i8* %93
%95 = call i32 @snprintf(i8* %92, i32 8, i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str, i64 0, i64 0), i8 zeroext %94)
store i32 %95, i32* %11
%96 = load %struct.template_buffer*, %struct.template_buffer** %5
%97 = getelementptr inbounds [8 x i8], [8 x i8]* %10, i64 0, i64 0
%98 = load i32, i32* %11
%99 = call i32 @buf_append(%struct.template_buffer* %96, i8* %97, i32 %98)
br label %105
100: ; preds = %87
%101 = load %struct.template_buffer*, %struct.template_buffer** %5
%102 = load i8*, i8** %6
%103 = load i8, i8* %102
%104 = call i32 @buf_putchar(%struct.template_buffer* %101, i8 zeroext %103)
br label %105
105: ; preds = %100, %91
%106 = load i8*, i8** %6
%107 = load i8, i8* %106
store i8 %107, i8* %9
br label %108
108: ; preds = %105, %84
br label %109
109: ; preds = %108, %69
br label %110
110: ; preds = %109
%111 = load i8*, i8** %6
%112 = getelementptr inbounds i8, i8* %111, i32 1
store i8* %112, i8** %6
br label %19
113: ; preds = %19
%114 = load %struct.template_buffer*, %struct.template_buffer** %5
%115 = call i8* @buf_destroy(%struct.template_buffer* %114)
ret i8* %115
}

LLVM IR (-O2):
%struct.template_buffer = type { i32 }
@.str = [6 x i8] c"&#%i;\00"
define i8* @striptags(i8* %0, i32 %1) {
%3 = alloca [8 x i8]
%4 = tail call %struct.template_buffer* @buf_init(i32 %1)
%5 = zext i32 %1 to i64
%6 = getelementptr inbounds i8, i8* %0, i64 %5
%7 = getelementptr inbounds [8 x i8], [8 x i8]* %3, i64 0, i64 0
%8 = icmp eq i32 %1, 0
br i1 %8, label %66, label %9
9: ; preds = %2, %61
%10 = phi i8* [ %64, %61 ], [ %0, %2 ]
%11 = phi i8 [ %62, %61 ], [ 32, %2 ]
%12 = load i8, i8* %10
%13 = icmp eq i8 %12, 60
%14 = getelementptr inbounds i8, i8* %10, i64 2
%15 = icmp ult i8* %14, %6
%16 = select i1 %13, i1 %15, i1 false
br i1 %16, label %17, label %40
17: ; preds = %9
%18 = getelementptr inbounds i8, i8* %10, i64 1
%19 = load i8, i8* %18
%20 = icmp eq i8 %19, 47
br i1 %20, label %26, label %21
21: ; preds = %17
%22 = call i64 @isalpha(i8 zeroext %19)
%23 = icmp eq i64 %22, 0
br i1 %23, label %24, label %26
24: ; preds = %21
%25 = load i8, i8* %10
br label %40
26: ; preds = %21, %17
%27 = icmp ult i8* %10, %6
br i1 %27, label %28, label %61
28: ; preds = %26, %37
%29 = phi i8* [ %38, %37 ], [ %10, %26 ]
%30 = load i8, i8* %29
%31 = icmp eq i8 %30, 62
br i1 %31, label %32, label %37
32: ; preds = %28
%33 = call i64 @isspace(i8 zeroext %11)
%34 = icmp eq i64 %33, 0
br i1 %34, label %35, label %61
35: ; preds = %32
%36 = call i32 @buf_putchar(%struct.template_buffer* %4, i8 zeroext 32)
br label %61
37: ; preds = %28
%38 = getelementptr inbounds i8, i8* %29, i64 1
%39 = icmp ult i8* %38, %6
br i1 %39, label %28, label %61
40: ; preds = %24, %9
%41 = phi i8 [ %25, %24 ], [ %12, %9 ]
%42 = call i64 @isspace(i8 zeroext %41)
%43 = icmp eq i64 %42, 0
br i1 %43, label %52, label %44
44: ; preds = %40
%45 = call i64 @isspace(i8 zeroext %11)
%46 = icmp eq i64 %45, 0
br i1 %46, label %47, label %50
47: ; preds = %44
%48 = load i8, i8* %10
%49 = call i32 @buf_putchar(%struct.template_buffer* %4, i8 zeroext %48)
br label %50
50: ; preds = %47, %44
%51 = load i8, i8* %10
br label %61
52: ; preds = %40
%53 = load i8, i8* %10
switch i8 %53, label %57 [
i8 34, label %54
i8 39, label %54
i8 60, label %54
i8 62, label %54
i8 38, label %54
]
54: ; preds = %52, %52, %52, %52, %52
%55 = call i32 @snprintf(i8* %7, i32 8, i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str, i64 0, i64 0), i8 zeroext %53)
%56 = call i32 @buf_append(%struct.template_buffer* %4, i8* %7, i32 %55)
br label %59
57: ; preds = %52
%58 = call i32 @buf_putchar(%struct.template_buffer* %4, i8 zeroext %53)
br label %59
59: ; preds = %57, %54
%60 = load i8, i8* %10
br label %61
61: ; preds = %37, %26, %32, %35, %59, %50
%62 = phi i8 [ %51, %50 ], [ %60, %59 ], [ 32, %35 ], [ 32, %32 ], [ %11, %26 ], [ %11, %37 ]
%63 = phi i8* [ %10, %50 ], [ %10, %59 ], [ %29, %35 ], [ %29, %32 ], [ %10, %26 ], [ %10, %37 ]
%64 = getelementptr inbounds i8, i8* %63, i64 1
%65 = icmp ult i8* %64, %6
br i1 %65, label %9, label %66
66: ; preds = %61, %2
%67 = call i8* @buf_destroy(%struct.template_buffer* %4)
ret i8* %67
}