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') + (((unsigned int)(c1) - '0' <= 9) != 0));
  while ((diff = c1 - c2) == 0 && c1 != '\0') {
    state = next_state[state];
    c1 = *p1++;
    c2 = *p2++;
    state |= (c1 == '0') + (((unsigned int)(c1) - '0' <= 9) != 0);
  }
  state = result_type[state << 2 |
                      ((c2 == '0') + (((unsigned int)(c2) - '0' <= 9) != 0))];
  switch (state) {
  case 2:
    return diff;
  case 3:
    while (((unsigned int)(*p1++) - '0' <= 9))
      if (!((unsigned int)(*p2++) - '0' <= 9))
        return 1;
    return ((unsigned int)(*p2) - '0' <= 9) ? -1 : diff;
  default:
    return state;
  }
}


x86 assembly (clang, -O0):
<strverscmp>:
push   %rbp
mov    %rsp,%rbp
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    1136 <strverscmp+0x36>
movl   $0x0,-0x4(%rbp)
jmp    1329 <strverscmp+0x229>
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
movzbl -0x29(%rbp),%ecx
sub    $0x30,%ecx
cmp    $0x9,%ecx
setbe  %cl
and    $0x1,%cl
movzbl %cl,%ecx
cmp    $0x0,%ecx
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,-0x35(%rbp)
jne    11bc <strverscmp+0xbc>
movzbl -0x29(%rbp),%eax
cmp    $0x0,%eax
setne  %al
mov    %al,-0x35(%rbp)
mov    -0x35(%rbp),%al
test   $0x1,%al
jne    11cc <strverscmp+0xcc>
jmp    1240 <strverscmp+0x140>
movslq -0x30(%rbp),%rcx
lea    0xe29(%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
movzbl -0x29(%rbp),%ecx
sub    $0x30,%ecx
cmp    $0x9,%ecx
setbe  %cl
and    $0x1,%cl
movzbl %cl,%ecx
cmp    $0x0,%ecx
setne  %cl
and    $0x1,%cl
movzbl %cl,%ecx
add    %ecx,%eax
or     -0x30(%rbp),%eax
mov    %eax,-0x30(%rbp)
jmp    1194 <strverscmp+0x94>
mov    -0x30(%rbp),%eax
shl    $0x2,%eax
movzbl -0x2a(%rbp),%edx
mov    %edx,%ecx
sub    $0x30,%ecx
sete   %cl
movzbl %cl,%ecx
add    $0xffffffd0,%edx
sub    $0xa,%edx
adc    $0x0,%ecx
or     %ecx,%eax
movslq %eax,%rcx
lea    0xdd6(%rip),%rax
mov    (%rax,%rcx,4),%eax
mov    %eax,-0x30(%rbp)
mov    -0x30(%rbp),%eax
mov    %eax,-0x3c(%rbp)
sub    $0x2,%eax
je     1295 <strverscmp+0x195>
jmp    1284 <strverscmp+0x184>
mov    -0x3c(%rbp),%eax
sub    $0x3,%eax
je     12a0 <strverscmp+0x1a0>
jmp    1323 <strverscmp+0x223>
mov    -0x34(%rbp),%eax
mov    %eax,-0x4(%rbp)
jmp    1329 <strverscmp+0x229>
jmp    12a5 <strverscmp+0x1a5>
mov    -0x20(%rbp),%rax
mov    %rax,%rcx
add    $0x1,%rcx
mov    %rcx,-0x20(%rbp)
movzbl (%rax),%eax
sub    $0x30,%eax
cmp    $0x9,%eax
ja     12f2 <strverscmp+0x1f2>
mov    -0x28(%rbp),%rax
mov    %rax,%rcx
add    $0x1,%rcx
mov    %rcx,-0x28(%rbp)
movzbl (%rax),%eax
sub    $0x30,%eax
cmp    $0x9,%eax
jbe    12ed <strverscmp+0x1ed>
movl   $0x1,-0x4(%rbp)
jmp    1329 <strverscmp+0x229>
jmp    12a5 <strverscmp+0x1a5>
mov    -0x28(%rbp),%rax
movzbl (%rax),%eax
sub    $0x30,%eax
cmp    $0x9,%eax
ja     1312 <strverscmp+0x212>
mov    $0xffffffff,%eax
mov    %eax,-0x40(%rbp)
jmp    1318 <strverscmp+0x218>
mov    -0x34(%rbp),%eax
mov    %eax,-0x40(%rbp)
mov    -0x40(%rbp),%eax
mov    %eax,-0x4(%rbp)
jmp    1329 <strverscmp+0x229>
mov    -0x30(%rbp),%eax
mov    %eax,-0x4(%rbp)
mov    -0x4(%rbp),%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<strverscmp>:
cmp    %rsi,%rdi
je     11f2 <strverscmp+0xf2>
movzbl (%rdi),%edx
xor    %ecx,%ecx
cmp    $0x30,%edx
sete   %cl
lea    -0x30(%rdx),%r8d
xor    %eax,%eax
cmp    $0xa,%r8d
setb   %al
add    %ecx,%eax
add    $0x1,%rdi
mov    (%rsi),%r8b
add    $0x1,%rsi
movzbl %r8b,%r10d
mov    %edx,%ecx
sub    %r10d,%ecx
jne    118c <strverscmp+0x8c>
test   %dl,%dl
je     118c <strverscmp+0x8c>
lea    0xebc(%rip),%r9
cs nopw 0x0(%rax,%rax,1)
xchg   %ax,%ax
movslq %eax,%r8
movzbl (%rdi),%edx
xor    %ecx,%ecx
cmp    $0x30,%edx
sete   %cl
lea    -0x30(%rdx),%r10d
xor    %eax,%eax
cmp    $0xa,%r10d
setb   %al
add    %ecx,%eax
or     (%r9,%r8,4),%eax
add    $0x1,%rdi
movzbl (%rsi),%r8d
add    $0x1,%rsi
movzbl %r8b,%r10d
mov    %edx,%ecx
sub    %r10d,%ecx
jne    118c <strverscmp+0x8c>
test   %dl,%dl
jne    1150 <strverscmp+0x50>
xor    %r9d,%r9d
cmp    $0x30,%r8b
sete   %r9b
add    $0xffffffd0,%r10d
xor    %edx,%edx
cmp    $0xa,%r10d
setb   %dl
add    %r9d,%edx
lea    (%rdx,%rax,4),%eax
cltq
lea    0xe8d(%rip),%rdx
mov    (%rdx,%rax,4),%eax
cmp    $0x2,%eax
je     1207 <strverscmp+0x107>
cmp    $0x3,%eax
jne    1209 <strverscmp+0x109>
xor    %eax,%eax
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax)
movzbl (%rdi,%rax,1),%edx
add    $0xffffffd0,%edx
cmp    $0x9,%edx
ja     11f5 <strverscmp+0xf5>
movzbl (%rsi,%rax,1),%edx
add    $0xffffffd0,%edx
add    $0x1,%rax
cmp    $0xa,%edx
jb     11d0 <strverscmp+0xd0>
mov    $0x1,%eax
ret
xor    %eax,%eax
ret
movzbl (%rsi,%rax,1),%eax
add    $0xffffffd0,%eax
cmp    $0xa,%eax
mov    $0xffffffff,%eax
cmovb  %eax,%ecx
mov    %ecx,%eax
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 %128
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 = zext i8 %29 to i32
%31 = sub i32 %30, 48
%32 = icmp ule i32 %31, 9
%33 = zext i1 %32 to i32
%34 = icmp ne i32 %33, 0
%35 = zext i1 %34 to i32
%36 = add nsw i32 %28, %35
%37 = or i32 0, %36
store i32 %37, i32* %10
br label %38
38: ; preds = %51, %18
%39 = load i8, i8* %8
%40 = zext i8 %39 to i32
%41 = load i8, i8* %9
%42 = zext i8 %41 to i32
%43 = sub nsw i32 %40, %42
store i32 %43, i32* %11
%44 = icmp eq i32 %43, 0
br i1 %44, label %45, label %49
45: ; preds = %38
%46 = load i8, i8* %8
%47 = zext i8 %46 to i32
%48 = icmp ne i32 %47, 0
br label %49
49: ; preds = %45, %38
%50 = phi i1 [ false, %38 ], [ %48, %45 ]
br i1 %50, label %51, label %76
51: ; preds = %49
%52 = load i32, i32* %10
%53 = sext i32 %52 to i64
%54 = getelementptr inbounds [16 x i32], [16 x i32]* @strverscmp.next_state, i64 0, i64 %53
%55 = load i32, i32* %54
store i32 %55, i32* %10
%56 = load i8*, i8** %6
%57 = getelementptr inbounds i8, i8* %56, i32 1
store i8* %57, i8** %6
%58 = load i8, i8* %56
store i8 %58, i8* %8
%59 = load i8*, i8** %7
%60 = getelementptr inbounds i8, i8* %59, i32 1
store i8* %60, i8** %7
%61 = load i8, i8* %59
store i8 %61, i8* %9
%62 = load i8, i8* %8
%63 = zext i8 %62 to i32
%64 = icmp eq i32 %63, 48
%65 = zext i1 %64 to i32
%66 = load i8, i8* %8
%67 = zext i8 %66 to i32
%68 = sub i32 %67, 48
%69 = icmp ule i32 %68, 9
%70 = zext i1 %69 to i32
%71 = icmp ne i32 %70, 0
%72 = zext i1 %71 to i32
%73 = add nsw i32 %65, %72
%74 = load i32, i32* %10
%75 = or i32 %74, %73
store i32 %75, i32* %10
br label %38
76: ; preds = %49
%77 = load i32, i32* %10
%78 = shl i32 %77, 2
%79 = load i8, i8* %9
%80 = zext i8 %79 to i32
%81 = icmp eq i32 %80, 48
%82 = zext i1 %81 to i32
%83 = load i8, i8* %9
%84 = zext i8 %83 to i32
%85 = sub i32 %84, 48
%86 = icmp ule i32 %85, 9
%87 = zext i1 %86 to i32
%88 = icmp ne i32 %87, 0
%89 = zext i1 %88 to i32
%90 = add nsw i32 %82, %89
%91 = or i32 %78, %90
%92 = sext i32 %91 to i64
%93 = getelementptr inbounds [60 x i32], [60 x i32]* @strverscmp.result_type, i64 0, i64 %92
%94 = load i32, i32* %93
store i32 %94, i32* %10
%95 = load i32, i32* %10
switch i32 %95, label %126 [
i32 2, label %96
i32 3, label %98
]
96: ; preds = %76
%97 = load i32, i32* %11
store i32 %97, i32* %3
br label %128
98: ; preds = %76
br label %99
99: ; preds = %114, %98
%100 = load i8*, i8** %6
%101 = getelementptr inbounds i8, i8* %100, i32 1
store i8* %101, i8** %6
%102 = load i8, i8* %100
%103 = zext i8 %102 to i32
%104 = sub i32 %103, 48
%105 = icmp ule i32 %104, 9
br i1 %105, label %106, label %115
106: ; preds = %99
%107 = load i8*, i8** %7
%108 = getelementptr inbounds i8, i8* %107, i32 1
store i8* %108, i8** %7
%109 = load i8, i8* %107
%110 = zext i8 %109 to i32
%111 = sub i32 %110, 48
%112 = icmp ule i32 %111, 9
br i1 %112, label %114, label %113
113: ; preds = %106
store i32 1, i32* %3
br label %128
114: ; preds = %106
br label %99
115: ; preds = %99
%116 = load i8*, i8** %7
%117 = load i8, i8* %116
%118 = zext i8 %117 to i32
%119 = sub i32 %118, 48
%120 = icmp ule i32 %119, 9
br i1 %120, label %121, label %122
121: ; preds = %115
br label %124
122: ; preds = %115
%123 = load i32, i32* %11
br label %124
124: ; preds = %122, %121
%125 = phi i32 [ -1, %121 ], [ %123, %122 ]
store i32 %125, i32* %3
br label %128
126: ; preds = %76
%127 = load i32, i32* %10
store i32 %127, i32* %3
br label %128
128: ; preds = %126, %124, %113, %96, %17
%129 = load i32, i32* %3
ret i32 %129
}

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 %86, label %4
4: ; preds = %2
%5 = load i8, i8* %0
%6 = zext i8 %5 to i32
%7 = icmp eq i8 %5, 48
%8 = zext i1 %7 to i32
%9 = add nsw i32 %6, -48
%10 = icmp ult i32 %9, 10
%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 = load i8, i8* %1
%16 = zext i8 %15 to i32
%17 = sub nsw i32 %6, %16
%18 = icmp eq i32 %17, 0
%19 = icmp ne i8 %5, 0
%20 = select i1 %18, i1 %19, i1 false
br i1 %20, label %21, label %47
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 = zext i8 %28 to i32
%30 = icmp eq i8 %28, 48
%31 = zext i1 %30 to i32
%32 = add nsw i32 %29, -48
%33 = icmp ult i32 %32, 10
%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 = load i8, i8* %23
%40 = zext i8 %39 to i32
%41 = sub nsw i32 %29, %40
%42 = icmp eq i32 %41, 0
%43 = icmp ne i8 %28, 0
%44 = select i1 %42, i1 %43, i1 false
br i1 %44, label %21, label %45
45: ; preds = %21
%46 = zext i8 %39 to i32
br label %47
47: ; preds = %45, %4
%48 = phi i32 [ %16, %4 ], [ %46, %45 ]
%49 = phi i8 [ %15, %4 ], [ %39, %45 ]
%50 = phi i32 [ %12, %4 ], [ %36, %45 ]
%51 = phi i8* [ %13, %4 ], [ %37, %45 ]
%52 = phi i8* [ %14, %4 ], [ %38, %45 ]
%53 = phi i32 [ %17, %4 ], [ %41, %45 ]
%54 = shl i32 %50, 2
%55 = icmp eq i8 %49, 48
%56 = zext i1 %55 to i32
%57 = add nsw i32 %48, -48
%58 = icmp ult i32 %57, 10
%59 = zext i1 %58 to i32
%60 = add nuw nsw i32 %59, %56
%61 = or i32 %60, %54
%62 = sext i32 %61 to i64
%63 = getelementptr inbounds [60 x i32], [60 x i32]* @strverscmp.result_type, i64 0, i64 %62
%64 = load i32, i32* %63
switch i32 %64, label %85 [
i32 2, label %86
i32 3, label %65
]
65: ; preds = %47, %72
%66 = phi i8* [ %73, %72 ], [ %52, %47 ]
%67 = phi i8* [ %74, %72 ], [ %51, %47 ]
%68 = load i8, i8* %66
%69 = zext i8 %68 to i32
%70 = add nsw i32 %69, -48
%71 = icmp ult i32 %70, 10
br i1 %71, label %72, label %79
72: ; preds = %65
%73 = getelementptr inbounds i8, i8* %66, i64 1
%74 = getelementptr inbounds i8, i8* %67, i64 1
%75 = load i8, i8* %67
%76 = zext i8 %75 to i32
%77 = add nsw i32 %76, -48
%78 = icmp ult i32 %77, 10
br i1 %78, label %65, label %86
79: ; preds = %65
%80 = load i8, i8* %67
%81 = zext i8 %80 to i32
%82 = add nsw i32 %81, -48
%83 = icmp ult i32 %82, 10
%84 = select i1 %83, i32 -1, i32 %53
br label %86
85: ; preds = %47
br label %86
86: ; preds = %72, %47, %2, %85, %79
%87 = phi i32 [ %64, %85 ], [ %84, %79 ], [ 0, %2 ], [ %53, %47 ], [ 1, %72 ]
ret i32 %87
}