#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 */
scalar_t__ label_equals(unsigned char const *, unsigned int, char *);
unsigned get_service(const unsigned char *px, unsigned length, unsigned offset,
                     const unsigned char **r_service,
                     unsigned *r_service_length) {
  unsigned recurse_count = 0;
  unsigned offset_of_serv = 0;
  while (offset < length) {
    unsigned len;
    if (px[offset] == 0x00)
      break;
    if (px[offset] & 0xC0) {
      if (recurse_count > 100)
        return 0;
      else
        recurse_count++;
      if (offset + 2 > length)
        return 0;
      offset = (*((unsigned char *)(px + offset) + 0) << 8 |
                *((unsigned char *)(px + offset) + 1) << 0) &
               0x3FFF;
      continue;
    }
    len = px[offset++];
    if (offset + len > length)
      return 0;
    if (px[offset] == '_') {
      if (label_equals(px + offset, len, "_udp") ||
          label_equals(px + offset, len, "_tcp")) {
        if (offset_of_serv) {
          *r_service = px + offset_of_serv + 1;
          *r_service_length = px[offset_of_serv];
          return 0;
        }
      }
      offset_of_serv = offset - 1;
    } else
      offset_of_serv = 0;
    offset += len;
  }
  return 0;
}


x86 assembly (clang, -O0):
<get_service>:
push   %rbp
mov    %rsp,%rbp
sub    $0x40,%rsp
mov    %rdi,-0x10(%rbp)
mov    %esi,-0x14(%rbp)
mov    %edx,-0x18(%rbp)
mov    %rcx,-0x20(%rbp)
mov    %r8,-0x28(%rbp)
movl   $0x0,-0x2c(%rbp)
movl   $0x0,-0x30(%rbp)
mov    -0x18(%rbp),%eax
cmp    -0x14(%rbp),%eax
jae    12cd <get_service+0x1bd>
mov    -0x10(%rbp),%rax
mov    -0x18(%rbp),%ecx
movzbl (%rax,%rcx,1),%eax
cmp    $0x0,%eax
jne    115d <get_service+0x4d>
jmp    12cd <get_service+0x1bd>
mov    -0x10(%rbp),%rax
mov    -0x18(%rbp),%ecx
movzbl (%rax,%rcx,1),%eax
and    $0xc0,%eax
cmp    $0x0,%eax
je     11dc <get_service+0xcc>
cmpl   $0x64,-0x2c(%rbp)
jbe    118c <get_service+0x7c>
movl   $0x0,-0x4(%rbp)
jmp    12d4 <get_service+0x1c4>
mov    -0x2c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x2c(%rbp)
mov    -0x18(%rbp),%eax
add    $0x2,%eax
cmp    -0x14(%rbp),%eax
jbe    11b0 <get_service+0xa0>
movl   $0x0,-0x4(%rbp)
jmp    12d4 <get_service+0x1c4>
mov    -0x10(%rbp),%rax
mov    -0x18(%rbp),%ecx
movzbl (%rax,%rcx,1),%eax
shl    $0x8,%eax
mov    -0x10(%rbp),%rcx
mov    -0x18(%rbp),%edx
movzbl 0x1(%rcx,%rdx,1),%ecx
shl    $0x0,%ecx
or     %ecx,%eax
and    $0x3fff,%eax
mov    %eax,-0x18(%rbp)
jmp    1138 <get_service+0x28>
mov    -0x10(%rbp),%rax
mov    -0x18(%rbp),%ecx
mov    %ecx,%edx
add    $0x1,%edx
mov    %edx,-0x18(%rbp)
mov    %ecx,%ecx
movzbl (%rax,%rcx,1),%eax
mov    %eax,-0x34(%rbp)
mov    -0x18(%rbp),%eax
add    -0x34(%rbp),%eax
cmp    -0x14(%rbp),%eax
jbe    120f <get_service+0xff>
movl   $0x0,-0x4(%rbp)
jmp    12d4 <get_service+0x1c4>
mov    -0x10(%rbp),%rax
mov    -0x18(%rbp),%ecx
movzbl (%rax,%rcx,1),%eax
cmp    $0x5f,%eax
jne    12b8 <get_service+0x1a8>
mov    -0x10(%rbp),%rdi
mov    -0x18(%rbp),%eax
add    %rax,%rdi
mov    -0x34(%rbp),%esi
lea    0xdc9(%rip),%rdx
call   1030 <label_equals@plt>
cmp    $0x0,%rax
jne    1269 <get_service+0x159>
mov    -0x10(%rbp),%rdi
mov    -0x18(%rbp),%eax
add    %rax,%rdi
mov    -0x34(%rbp),%esi
lea    0xdab(%rip),%rdx
call   1030 <label_equals@plt>
cmp    $0x0,%rax
je     12aa <get_service+0x19a>
cmpl   $0x0,-0x30(%rbp)
je     12a5 <get_service+0x195>
mov    -0x10(%rbp),%rcx
mov    -0x30(%rbp),%eax
add    %rax,%rcx
add    $0x1,%rcx
mov    -0x20(%rbp),%rax
mov    %rcx,(%rax)
mov    -0x10(%rbp),%rax
mov    -0x30(%rbp),%ecx
movzbl (%rax,%rcx,1),%ecx
mov    -0x28(%rbp),%rax
mov    %ecx,(%rax)
movl   $0x0,-0x4(%rbp)
jmp    12d4 <get_service+0x1c4>
jmp    12aa <get_service+0x19a>
mov    -0x18(%rbp),%eax
sub    $0x1,%eax
mov    %eax,-0x30(%rbp)
jmp    12bf <get_service+0x1af>
movl   $0x0,-0x30(%rbp)
mov    -0x34(%rbp),%eax
add    -0x18(%rbp),%eax
mov    %eax,-0x18(%rbp)
jmp    1138 <get_service+0x28>
movl   $0x0,-0x4(%rbp)
mov    -0x4(%rbp),%eax
add    $0x40,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<get_service>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
sub    $0x28,%rsp
mov    %r8,0x20(%rsp)
mov    %rcx,0x18(%rsp)
cmp    %esi,%edx
jae    1240 <get_service+0x130>
mov    %edx,%r13d
mov    %esi,%ebp
xor    %r15d,%r15d
xor    %ecx,%ecx
mov    %rdi,0x10(%rsp)
jmp    115e <get_service+0x4e>
xor    %r13d,%r13d
cs nopw 0x0(%rax,%rax,1)
xchg   %ax,%ax
mov    %r13d,%r15d
mov    %ebx,%r13d
cmp    %ebp,%ebx
jae    1240 <get_service+0x130>
mov    %r13d,%r14d
movzbl (%rdi,%r14,1),%r12d
test   %r12d,%r12d
je     1240 <get_service+0x130>
test   $0xc0,%r12b
je     11b0 <get_service+0xa0>
cmp    $0x64,%ecx
ja     1240 <get_service+0x130>
add    $0x2,%r13d
cmp    %ebp,%r13d
ja     1240 <get_service+0x130>
add    $0x1,%ecx
movzbl 0x1(%rdi,%r14,1),%eax
and    $0x3f,%r12d
shl    $0x8,%r12d
or     %eax,%r12d
mov    %r12d,%ebx
mov    %r15d,%r13d
jmp    1150 <get_service+0x40>
nopw   0x0(%rax,%rax,1)
add    $0x1,%r14
lea    (%r14,%r12,1),%ebx
cmp    %ebp,%ebx
ja     1240 <get_service+0x130>
cmpb   $0x5f,(%rdi,%r14,1)
jne    1141 <get_service+0x31>
mov    %ecx,0xc(%rsp)
add    %rdi,%r14
mov    %r14,%rdi
mov    %r12d,%esi
lea    0xe21(%rip),%rdx
call   1030 <label_equals@plt>
test   %rax,%rax
jne    1200 <get_service+0xf0>
mov    %r14,%rdi
mov    %r12d,%esi
lea    0xe0f(%rip),%rdx
call   1030 <label_equals@plt>
test   %rax,%rax
je     1214 <get_service+0x104>
test   %r15d,%r15d
mov    0x10(%rsp),%rdi
mov    0xc(%rsp),%ecx
je     1150 <get_service+0x40>
jmp    1222 <get_service+0x112>
mov    0x10(%rsp),%rdi
mov    0xc(%rsp),%ecx
jmp    1150 <get_service+0x40>
mov    %r15d,%eax
lea    (%rdi,%rax,1),%rcx
add    $0x1,%rcx
mov    0x18(%rsp),%rdx
mov    %rcx,(%rdx)
movzbl (%rdi,%rax,1),%eax
mov    0x20(%rsp),%rcx
mov    %eax,(%rcx)
xor    %eax,%eax
add    $0x28,%rsp
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
@.str = [5 x i8] c"_udp\00"
@.str.1 = [5 x i8] c"_tcp\00"
define i32 @get_service(i8* %0, i32 %1, i32 %2, i8** %3, i32* %4) {
%6 = alloca i32
%7 = alloca i8*
%8 = alloca i32
%9 = alloca i32
%10 = alloca i8**
%11 = alloca i32*
%12 = alloca i32
%13 = alloca i32
%14 = alloca i32
store i8* %0, i8** %7
store i32 %1, i32* %8
store i32 %2, i32* %9
store i8** %3, i8*** %10
store i32* %4, i32** %11
store i32 0, i32* %12
store i32 0, i32* %13
br label %15
15: ; preds = %129, %50, %5
%16 = load i32, i32* %9
%17 = load i32, i32* %8
%18 = icmp ult i32 %16, %17
br i1 %18, label %19, label %133
19: ; preds = %15
%20 = load i8*, i8** %7
%21 = load i32, i32* %9
%22 = zext i32 %21 to i64
%23 = getelementptr inbounds i8, i8* %20, i64 %22
%24 = load i8, i8* %23
%25 = zext i8 %24 to i32
%26 = icmp eq i32 %25, 0
br i1 %26, label %27, label %28
27: ; preds = %19
br label %133
28: ; preds = %19
%29 = load i8*, i8** %7
%30 = load i32, i32* %9
%31 = zext i32 %30 to i64
%32 = getelementptr inbounds i8, i8* %29, i64 %31
%33 = load i8, i8* %32
%34 = zext i8 %33 to i32
%35 = and i32 %34, 192
%36 = icmp ne i32 %35, 0
br i1 %36, label %37, label %69
37: ; preds = %28
%38 = load i32, i32* %12
%39 = icmp ugt i32 %38, 100
br i1 %39, label %40, label %41
40: ; preds = %37
store i32 0, i32* %6
br label %134
41: ; preds = %37
%42 = load i32, i32* %12
%43 = add i32 %42, 1
store i32 %43, i32* %12
br label %44
44: ; preds = %41
%45 = load i32, i32* %9
%46 = add i32 %45, 2
%47 = load i32, i32* %8
%48 = icmp ugt i32 %46, %47
br i1 %48, label %49, label %50
49: ; preds = %44
store i32 0, i32* %6
br label %134
50: ; preds = %44
%51 = load i8*, i8** %7
%52 = load i32, i32* %9
%53 = zext i32 %52 to i64
%54 = getelementptr inbounds i8, i8* %51, i64 %53
%55 = getelementptr inbounds i8, i8* %54, i64 0
%56 = load i8, i8* %55
%57 = zext i8 %56 to i32
%58 = shl i32 %57, 8
%59 = load i8*, i8** %7
%60 = load i32, i32* %9
%61 = zext i32 %60 to i64
%62 = getelementptr inbounds i8, i8* %59, i64 %61
%63 = getelementptr inbounds i8, i8* %62, i64 1
%64 = load i8, i8* %63
%65 = zext i8 %64 to i32
%66 = shl i32 %65, 0
%67 = or i32 %58, %66
%68 = and i32 %67, 16383
store i32 %68, i32* %9
br label %15
69: ; preds = %28
%70 = load i8*, i8** %7
%71 = load i32, i32* %9
%72 = add i32 %71, 1
store i32 %72, i32* %9
%73 = zext i32 %71 to i64
%74 = getelementptr inbounds i8, i8* %70, i64 %73
%75 = load i8, i8* %74
%76 = zext i8 %75 to i32
store i32 %76, i32* %14
%77 = load i32, i32* %9
%78 = load i32, i32* %14
%79 = add i32 %77, %78
%80 = load i32, i32* %8
%81 = icmp ugt i32 %79, %80
br i1 %81, label %82, label %83
82: ; preds = %69
store i32 0, i32* %6
br label %134
83: ; preds = %69
%84 = load i8*, i8** %7
%85 = load i32, i32* %9
%86 = zext i32 %85 to i64
%87 = getelementptr inbounds i8, i8* %84, i64 %86
%88 = load i8, i8* %87
%89 = zext i8 %88 to i32
%90 = icmp eq i32 %89, 95
br i1 %90, label %91, label %128
91: ; preds = %83
%92 = load i8*, i8** %7
%93 = load i32, i32* %9
%94 = zext i32 %93 to i64
%95 = getelementptr inbounds i8, i8* %92, i64 %94
%96 = load i32, i32* %14
%97 = call i64 @label_equals(i8* %95, i32 %96, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0))
%98 = icmp ne i64 %97, 0
br i1 %98, label %107, label %99
99: ; preds = %91
%100 = load i8*, i8** %7
%101 = load i32, i32* %9
%102 = zext i32 %101 to i64
%103 = getelementptr inbounds i8, i8* %100, i64 %102
%104 = load i32, i32* %14
%105 = call i64 @label_equals(i8* %103, i32 %104, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.1, i64 0, i64 0))
%106 = icmp ne i64 %105, 0
br i1 %106, label %107, label %125
107: ; preds = %99, %91
%108 = load i32, i32* %13
%109 = icmp ne i32 %108, 0
br i1 %109, label %110, label %124
110: ; preds = %107
%111 = load i8*, i8** %7
%112 = load i32, i32* %13
%113 = zext i32 %112 to i64
%114 = getelementptr inbounds i8, i8* %111, i64 %113
%115 = getelementptr inbounds i8, i8* %114, i64 1
%116 = load i8**, i8*** %10
store i8* %115, i8** %116
%117 = load i8*, i8** %7
%118 = load i32, i32* %13
%119 = zext i32 %118 to i64
%120 = getelementptr inbounds i8, i8* %117, i64 %119
%121 = load i8, i8* %120
%122 = zext i8 %121 to i32
%123 = load i32*, i32** %11
store i32 %122, i32* %123
store i32 0, i32* %6
br label %134
124: ; preds = %107
br label %125
125: ; preds = %124, %99
%126 = load i32, i32* %9
%127 = sub i32 %126, 1
store i32 %127, i32* %13
br label %129
128: ; preds = %83
store i32 0, i32* %13
br label %129
129: ; preds = %128, %125
%130 = load i32, i32* %14
%131 = load i32, i32* %9
%132 = add i32 %131, %130
store i32 %132, i32* %9
br label %15
133: ; preds = %27, %15
store i32 0, i32* %6
br label %134
134: ; preds = %133, %110, %82, %49, %40
%135 = load i32, i32* %6
ret i32 %135
}

LLVM IR (-O2):
@.str = [5 x i8] c"_udp\00"
@.str.1 = [5 x i8] c"_tcp\00"
define i32 @get_service(i8* %0, i32 %1, i32 %2, i8** nocapture writeonly %3, i32* nocapture writeonly %4) {
%6 = icmp ult i32 %2, %1
br i1 %6, label %7, label %62
7: ; preds = %5, %57
%8 = phi i32 [ %60, %57 ], [ 0, %5 ]
%9 = phi i32 [ %59, %57 ], [ 0, %5 ]
%10 = phi i32 [ %58, %57 ], [ %2, %5 ]
%11 = zext i32 %10 to i64
%12 = getelementptr inbounds i8, i8* %0, i64 %11
%13 = load i8, i8* %12
%14 = zext i8 %13 to i32
%15 = icmp eq i8 %13, 0
br i1 %15, label %62, label %16
16: ; preds = %7
%17 = and i32 %14, 192
%18 = icmp eq i32 %17, 0
br i1 %18, label %32, label %19
19: ; preds = %16
%20 = icmp ugt i32 %9, 100
%21 = add i32 %10, 2
%22 = icmp ugt i32 %21, %1
%23 = select i1 %20, i1 true, i1 %22
br i1 %23, label %62, label %24
24: ; preds = %19
%25 = add nuw nsw i32 %9, 1
%26 = shl nuw nsw i32 %14, 8
%27 = getelementptr inbounds i8, i8* %12, i64 1
%28 = load i8, i8* %27
%29 = zext i8 %28 to i32
%30 = and i32 %26, 16128
%31 = or i32 %30, %29
br label %57
32: ; preds = %16
%33 = add nuw i32 %10, 1
%34 = add i32 %33, %14
%35 = icmp ugt i32 %34, %1
br i1 %35, label %62, label %36
36: ; preds = %32
%37 = zext i32 %33 to i64
%38 = getelementptr inbounds i8, i8* %0, i64 %37
%39 = load i8, i8* %38
%40 = icmp eq i8 %39, 95
br i1 %40, label %41, label %57
41: ; preds = %36
%42 = tail call i64 @label_equals(i8* %38, i32 %14, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0))
%43 = icmp eq i64 %42, 0
br i1 %43, label %44, label %49
44: ; preds = %41
%45 = tail call i64 @label_equals(i8* %38, i32 %14, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.1, i64 0, i64 0))
%46 = icmp ne i64 %45, 0
%47 = icmp ne i32 %8, 0
%48 = select i1 %46, i1 %47, i1 false
br i1 %48, label %51, label %57
49: ; preds = %41
%50 = icmp eq i32 %8, 0
br i1 %50, label %57, label %51
51: ; preds = %44, %49
%52 = zext i32 %8 to i64
%53 = getelementptr inbounds i8, i8* %0, i64 %52
%54 = getelementptr inbounds i8, i8* %53, i64 1
store i8* %54, i8** %3
%55 = load i8, i8* %53
%56 = zext i8 %55 to i32
store i32 %56, i32* %4
br label %62
57: ; preds = %49, %44, %36, %24
%58 = phi i32 [ %31, %24 ], [ %34, %36 ], [ %34, %44 ], [ %34, %49 ]
%59 = phi i32 [ %25, %24 ], [ %9, %36 ], [ %9, %44 ], [ %9, %49 ]
%60 = phi i32 [ %8, %24 ], [ 0, %36 ], [ %10, %44 ], [ %10, %49 ]
%61 = icmp ult i32 %58, %1
br i1 %61, label %7, label %62
62: ; preds = %57, %7, %19, %32, %5, %51
ret i32 0
}