#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__ isdigit(unsigned char const);
int strverscmp(const char *s1, const char *s2) {
  const unsigned char *p1 = (const unsigned char *)s1;
  const unsigned char *p2 = (const unsigned char *)s2;
  unsigned char c1, c2;
  int state;
  int diff;
  static const unsigned int next_state[] = {0x0, 0x4, 0xC, 0x0, 0x0, 0x4,
                                            0x4, 0x4, 0x0, 0x8, 0x8, 0x8,
                                            0x0, 0x8, 0xC, 0xC};
  static const int result_type[] = {
      2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2,  2, 2, 2, 2,  -1, -1, 2,
      1, 3, 3, 2, 1, 3, 3, 2, 2, 2, 2, 2, 2,  2, 2, 2, 2,  3,  2,  2,
      2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 2, -1, 2, 2, 2, -1, 2,  2,  2};
  if (p1 == p2)
    return 0;
  c1 = *p1++;
  c2 = *p2++;
  state = 0x0 | ((c1 == '0') + (isdigit(c1) != 0));
  while ((diff = c1 - c2) == 0 && c1 != '\0') {
    state = next_state[state];
    c1 = *p1++;
    c2 = *p2++;
    state |= (c1 == '0') + (isdigit(c1) != 0);
  }
  state = result_type[state << 2 | ((c2 == '0') + (isdigit(c2) != 0))];
  switch (state) {
  case 2:
    return diff;
  case 3:
    while (isdigit(*p1++))
      if (!isdigit(*p2++))
        return 1;
    return isdigit(*p2) ? -1 : diff;
  default:
    return state;
  }
}


x86 assembly (clang, -O0):
<strverscmp>:
push   %rbp
mov    %rsp,%rbp
sub    $0x50,%rsp
mov    %rdi,-0x10(%rbp)
mov    %rsi,-0x18(%rbp)
mov    -0x10(%rbp),%rax
mov    %rax,-0x20(%rbp)
mov    -0x18(%rbp),%rax
mov    %rax,-0x28(%rbp)
mov    -0x20(%rbp),%rax
cmp    -0x28(%rbp),%rax
jne    114a <strverscmp+0x3a>
movl   $0x0,-0x4(%rbp)
jmp    1358 <strverscmp+0x248>
mov    -0x20(%rbp),%rax
mov    %rax,%rcx
add    $0x1,%rcx
mov    %rcx,-0x20(%rbp)
mov    (%rax),%al
mov    %al,-0x29(%rbp)
mov    -0x28(%rbp),%rax
mov    %rax,%rcx
add    $0x1,%rcx
mov    %rcx,-0x28(%rbp)
mov    (%rax),%al
mov    %al,-0x2a(%rbp)
movzbl -0x29(%rbp),%eax
cmp    $0x30,%eax
sete   %al
and    $0x1,%al
movzbl %al,%eax
mov    %eax,-0x38(%rbp)
movzbl -0x29(%rbp),%edi
call   1030 <isdigit@plt>
mov    %rax,%rcx
mov    -0x38(%rbp),%eax
cmp    $0x0,%rcx
setne  %cl
and    $0x1,%cl
movzbl %cl,%ecx
add    %ecx,%eax
or     $0x0,%eax
mov    %eax,-0x30(%rbp)
movzbl -0x29(%rbp),%ecx
movzbl -0x2a(%rbp),%eax
sub    %eax,%ecx
mov    %ecx,-0x34(%rbp)
xor    %eax,%eax
cmp    $0x0,%ecx
mov    %al,-0x39(%rbp)
jne    11d0 <strverscmp+0xc0>
movzbl -0x29(%rbp),%eax
cmp    $0x0,%eax
setne  %al
mov    %al,-0x39(%rbp)
mov    -0x39(%rbp),%al
test   $0x1,%al
jne    11e0 <strverscmp+0xd0>
jmp    1254 <strverscmp+0x144>
movslq -0x30(%rbp),%rcx
lea    0xe15(%rip),%rax
mov    (%rax,%rcx,4),%eax
mov    %eax,-0x30(%rbp)
mov    -0x20(%rbp),%rax
mov    %rax,%rcx
add    $0x1,%rcx
mov    %rcx,-0x20(%rbp)
mov    (%rax),%al
mov    %al,-0x29(%rbp)
mov    -0x28(%rbp),%rax
mov    %rax,%rcx
add    $0x1,%rcx
mov    %rcx,-0x28(%rbp)
mov    (%rax),%al
mov    %al,-0x2a(%rbp)
movzbl -0x29(%rbp),%eax
cmp    $0x30,%eax
sete   %al
and    $0x1,%al
movzbl %al,%eax
mov    %eax,-0x40(%rbp)
movzbl -0x29(%rbp),%edi
call   1030 <isdigit@plt>
mov    %rax,%rcx
mov    -0x40(%rbp),%eax
cmp    $0x0,%rcx
setne  %cl
and    $0x1,%cl
movzbl %cl,%ecx
add    %ecx,%eax
or     -0x30(%rbp),%eax
mov    %eax,-0x30(%rbp)
jmp    11a8 <strverscmp+0x98>
mov    -0x30(%rbp),%eax
shl    $0x2,%eax
mov    %eax,-0x48(%rbp)
movzbl -0x2a(%rbp),%edi
mov    %edi,%eax
sub    $0x30,%eax
sete   %al
movzbl %al,%eax
mov    %eax,-0x4c(%rbp)
call   1030 <isdigit@plt>
mov    -0x4c(%rbp),%ecx
mov    %rax,%rdx
mov    -0x48(%rbp),%eax
sub    $0x1,%rdx
sbb    $0xffffffff,%ecx
or     %ecx,%eax
movslq %eax,%rcx
lea    0xdb0(%rip),%rax
mov    (%rax,%rcx,4),%eax
mov    %eax,-0x30(%rbp)
mov    -0x30(%rbp),%eax
mov    %eax,-0x44(%rbp)
sub    $0x2,%eax
je     12bb <strverscmp+0x1ab>
jmp    12aa <strverscmp+0x19a>
mov    -0x44(%rbp),%eax
sub    $0x3,%eax
je     12c6 <strverscmp+0x1b6>
jmp    1352 <strverscmp+0x242>
mov    -0x34(%rbp),%eax
mov    %eax,-0x4(%rbp)
jmp    1358 <strverscmp+0x248>
jmp    12cb <strverscmp+0x1bb>
mov    -0x20(%rbp),%rax
mov    %rax,%rcx
add    $0x1,%rcx
mov    %rcx,-0x20(%rbp)
movzbl (%rax),%edi
call   1030 <isdigit@plt>
cmp    $0x0,%rax
je     131e <strverscmp+0x20e>
mov    -0x28(%rbp),%rax
mov    %rax,%rcx
add    $0x1,%rcx
mov    %rcx,-0x28(%rbp)
movzbl (%rax),%edi
call   1030 <isdigit@plt>
cmp    $0x0,%rax
jne    1319 <strverscmp+0x209>
movl   $0x1,-0x4(%rbp)
jmp    1358 <strverscmp+0x248>
jmp    12cb <strverscmp+0x1bb>
mov    -0x28(%rbp),%rax
movzbl (%rax),%edi
call   1030 <isdigit@plt>
cmp    $0x0,%rax
je     1341 <strverscmp+0x231>
mov    $0xffffffff,%eax
mov    %eax,-0x50(%rbp)
jmp    1347 <strverscmp+0x237>
mov    -0x34(%rbp),%eax
mov    %eax,-0x50(%rbp)
mov    -0x50(%rbp),%eax
mov    %eax,-0x4(%rbp)
jmp    1358 <strverscmp+0x248>
mov    -0x30(%rbp),%eax
mov    %eax,-0x4(%rbp)
mov    -0x4(%rbp),%eax
add    $0x50,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<strverscmp>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
push   %rax
cmp    %rsi,%rdi
je     1219 <strverscmp+0x109>
mov    %rsi,%r14
mov    %rdi,%r15
movzbl (%rdi),%ebp
xor    %r12d,%r12d
cmp    $0x30,%ebp
sete   %r12b
movzbl (%rsi),%r13d
mov    %ebp,%edi
call   1030 <isdigit@plt>
xor    %ebx,%ebx
test   %rax,%rax
setne  %bl
add    %r12d,%ebx
nopl   (%rax)
add    $0x1,%r14
add    $0x1,%r15
mov    %ebp,%r12d
sub    %r13d,%r12d
test   %ebp,%ebp
je     11ab <strverscmp+0x9b>
test   %r12d,%r12d
jne    11ab <strverscmp+0x9b>
movslq %ebx,%rax
mov    %rax,(%rsp)
movzbl (%r15),%ebp
xor    %r13d,%r13d
cmp    $0x30,%ebp
sete   %r13b
mov    %r15,%r12
movzbl (%r14),%r15d
mov    %ebp,%edi
call   1030 <isdigit@plt>
xor    %ebx,%ebx
test   %rax,%rax
setne  %bl
add    %r13d,%ebx
mov    %r15d,%r13d
mov    %r12,%r15
lea    0xe5e(%rip),%rax
mov    (%rsp),%rcx
or     (%rax,%rcx,4),%ebx
jmp    1150 <strverscmp+0x40>
xor    %ebp,%ebp
cmp    $0x30,%r13b
sete   %bpl
movzbl %r13b,%edi
call   1030 <isdigit@plt>
xor    %ecx,%ecx
test   %rax,%rax
setne  %cl
add    %ebp,%ecx
lea    (%rcx,%rbx,4),%eax
cltq
lea    0xe6c(%rip),%rcx
mov    (%rcx,%rax,4),%eax
cmp    $0x2,%eax
je     121d <strverscmp+0x10d>
cmp    $0x3,%eax
jne    1234 <strverscmp+0x124>
xor    %ebx,%ebx
cs nopw 0x0(%rax,%rax,1)
nopl   (%rax)
movzbl (%r15,%rbx,1),%edi
call   1030 <isdigit@plt>
test   %rax,%rax
je     1222 <strverscmp+0x112>
movzbl (%r14,%rbx,1),%edi
call   1030 <isdigit@plt>
add    $0x1,%rbx
test   %rax,%rax
jne    11f0 <strverscmp+0xe0>
mov    $0x1,%eax
jmp    1234 <strverscmp+0x124>
xor    %eax,%eax
jmp    1234 <strverscmp+0x124>
mov    %r12d,%eax
jmp    1234 <strverscmp+0x124>
movzbl (%r14,%rbx,1),%edi
call   1030 <isdigit@plt>
neg    %rax
sbb    %eax,%eax
or     %r12d,%eax
add    $0x8,%rsp
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret

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

LLVM IR (-O2):
@strverscmp.next_state = internal unnamed_addr constant [16 x i32] [i32 0, i32 4, i32 12, i32 0, i32 0, i32 4, i32 4, i32 4, i32 0, i32 8, i32 8, i32 8, i32 0, i32 8, i32 12, i32 12]
@strverscmp.result_type = internal unnamed_addr constant [60 x i32] [i32 2, i32 2, i32 2, i32 2, i32 2, i32 3, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 -1, i32 -1, i32 2, i32 1, i32 3, i32 3, i32 2, i32 1, i32 3, i32 3, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 3, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 1, i32 1, i32 2, i32 -1, i32 2, i32 2, i32 2, i32 -1, i32 2, i32 2, i32 2]
define i32 @strverscmp(i8* %0, i8* %1) {
%3 = icmp eq i8* %0, %1
br i1 %3, label %80, label %4
4: ; preds = %2
%5 = load i8, i8* %0
%6 = load i8, i8* %1
%7 = icmp eq i8 %5, 48
%8 = zext i1 %7 to i32
%9 = tail call i64 @isdigit(i8 zeroext %5)
%10 = icmp ne i64 %9, 0
%11 = zext i1 %10 to i32
%12 = add nuw nsw i32 %11, %8
%13 = getelementptr inbounds i8, i8* %1, i64 1
%14 = getelementptr inbounds i8, i8* %0, i64 1
%15 = zext i8 %5 to i32
%16 = zext i8 %6 to i32
%17 = sub nsw i32 %15, %16
%18 = icmp eq i32 %17, 0
%19 = icmp ne i8 %5, 0
%20 = and i1 %19, %18
br i1 %20, label %21, label %45
21: ; preds = %4, %21
%22 = phi i8* [ %38, %21 ], [ %14, %4 ]
%23 = phi i8* [ %37, %21 ], [ %13, %4 ]
%24 = phi i32 [ %36, %21 ], [ %12, %4 ]
%25 = sext i32 %24 to i64
%26 = getelementptr inbounds [16 x i32], [16 x i32]* @strverscmp.next_state, i64 0, i64 %25
%27 = load i32, i32* %26
%28 = load i8, i8* %22
%29 = load i8, i8* %23
%30 = icmp eq i8 %28, 48
%31 = zext i1 %30 to i32
%32 = tail call i64 @isdigit(i8 zeroext %28)
%33 = icmp ne i64 %32, 0
%34 = zext i1 %33 to i32
%35 = add nuw nsw i32 %34, %31
%36 = or i32 %35, %27
%37 = getelementptr inbounds i8, i8* %23, i64 1
%38 = getelementptr inbounds i8, i8* %22, i64 1
%39 = zext i8 %28 to i32
%40 = zext i8 %29 to i32
%41 = sub nsw i32 %39, %40
%42 = icmp eq i32 %41, 0
%43 = icmp ne i8 %28, 0
%44 = and i1 %43, %42
br i1 %44, label %21, label %45
45: ; preds = %21, %4
%46 = phi i8 [ %6, %4 ], [ %29, %21 ]
%47 = phi i32 [ %12, %4 ], [ %36, %21 ]
%48 = phi i8* [ %13, %4 ], [ %37, %21 ]
%49 = phi i8* [ %14, %4 ], [ %38, %21 ]
%50 = phi i32 [ %17, %4 ], [ %41, %21 ]
%51 = shl i32 %47, 2
%52 = icmp eq i8 %46, 48
%53 = zext i1 %52 to i32
%54 = tail call i64 @isdigit(i8 zeroext %46)
%55 = icmp ne i64 %54, 0
%56 = zext i1 %55 to i32
%57 = add nuw nsw i32 %56, %53
%58 = or i32 %57, %51
%59 = sext i32 %58 to i64
%60 = getelementptr inbounds [60 x i32], [60 x i32]* @strverscmp.result_type, i64 0, i64 %59
%61 = load i32, i32* %60
switch i32 %61, label %79 [
i32 2, label %80
i32 3, label %62
]
62: ; preds = %45, %68
%63 = phi i8* [ %69, %68 ], [ %49, %45 ]
%64 = phi i8* [ %70, %68 ], [ %48, %45 ]
%65 = load i8, i8* %63
%66 = tail call i64 @isdigit(i8 zeroext %65)
%67 = icmp eq i64 %66, 0
br i1 %67, label %74, label %68
68: ; preds = %62
%69 = getelementptr inbounds i8, i8* %63, i64 1
%70 = getelementptr inbounds i8, i8* %64, i64 1
%71 = load i8, i8* %64
%72 = tail call i64 @isdigit(i8 zeroext %71)
%73 = icmp eq i64 %72, 0
br i1 %73, label %80, label %62
74: ; preds = %62
%75 = load i8, i8* %64
%76 = tail call i64 @isdigit(i8 zeroext %75)
%77 = icmp eq i64 %76, 0
%78 = select i1 %77, i32 %50, i32 -1
br label %80
79: ; preds = %45
br label %80
80: ; preds = %68, %45, %2, %79, %74
%81 = phi i32 [ %61, %79 ], [ %78, %74 ], [ 0, %2 ], [ %50, %45 ], [ 1, %68 ]
ret i32 %81
}