user: Please show me the C implementation that matches the assembly code listed below:

```asm
<str_stats>:
  endbr64
  push   %r13
  pxor   %xmm0,%xmm0
  mov    %rdi,%rcx
  push   %r12
  push   %rbp
  push   %rbx
  sub    $0xc8,%rsp
  mov    %fs:0x28,%rax
  mov    %rax,0xb8(%rsp)
  xor    %eax,%eax
  movl   $0x45,0x34(%rsp)
  movabs $0x4f00000049,%rax
  mov    %rax,0x38(%rsp)
  movabs $0x5900000055,%rax
  mov    %rax,0x40(%rsp)
  movabs $0x4400000043,%rax
  mov    %rax,0x64(%rsp)
  movabs $0x4700000046,%rax
  mov    %rax,0x6c(%rsp)
  movabs $0x4a00000048,%rax
  mov    %rax,0x74(%rsp)
  movabs $0x4c0000004b,%rax
  mov    %rax,0x7c(%rsp)
  movabs $0x4e0000004d,%rax
  mov    %rax,0x84(%rsp)
  movabs $0x5100000050,%rax
  mov    %rax,0x8c(%rsp)
  movabs $0x5300000052,%rax
  mov    %rax,0x94(%rsp)
  movabs $0x5600000054,%rax
  mov    %rax,0x9c(%rsp)
  movabs $0x5800000057,%rax
  mov    %rax,0xa4(%rsp)
  movabs $0x5a00000059,%rax
  mov    %rax,0xac(%rsp)
  movabs $0x300000002,%rax
  mov    %rax,0x8(%rsp)
  movabs $0x500000004,%rax
  mov    %rax,0x10(%rsp)
  movabs $0x700000006,%rax
  movq   $0x0,0x58(%rsp)
  movl   $0x1,0x4(%rsp)
  mov    %rax,0x18(%rsp)
  movabs $0x900000008,%rax
  mov    %rax,0x20(%rsp)
  xor    %eax,%eax
  movups %xmm0,0x48(%rsp)
  nopl   (%rax)
L108:
  mov    %rax,%rdx
  add    $0x1,%rax
  cmpb   $0x0,(%rcx,%rax,1)
  jne    L108
  lea    0x1(%rdx,%rcx,1),%r8
  xor    %r13d,%r13d
  xor    %ebp,%ebp
  xor    %r12d,%r12d
  xor    %r11d,%r11d
  lea    0x60(%rsp),%r9
  lea    0x28(%rsp),%r10
  xor    %esi,%esi
  lea    0xb4(%rsp),%rdi
  jmp    L38
  nopl   0x0(%rax,%rax,1)
L0:
  lea    -0x7b(%rax),%edx
  cmp    $0x4,%edx
  jbe    L89
  lea    -0x5b(%rax),%edx
  cmp    $0x5,%edx
  jbe    L89
  lea    -0x30(%rax),%edx
  cmp    $0x2a,%edx
  jbe    L159
  lea    -0x61(%rax),%edx
  cmp    $0x19,%edx
  jbe    L159
L64:
  add    $0x1,%rcx
  cmp    %r8,%rcx
  je     L24
L38:
  movsbl (%rcx),%eax
  lea    -0x20(%rax),%edx
  cmp    $0xf,%edx
  ja     L0
L89:
  add    $0x1,%rcx
  xor    %esi,%esi
  cmp    %r8,%rcx
  jne    L38
L24:
  mov    %r11d,%esi
  lea    D11(%rip),%rdi
  call   <printf@plt>
  mov    %ebp,%esi
  lea    D31(%rip),%rdi
  call   <printf@plt>
  mov    %r12d,%esi
  lea    D24(%rip),%rdi
  call   <printf@plt>
  mov    0xb8(%rsp),%rax
  sub    %fs:0x28,%rax
  jne    L103
  add    $0xc8,%rsp
  mov    %r13d,%esi
  lea    D29(%rip),%rdi
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  jmp    1070 <printf@plt>
  xchg   %ax,%ax
L159:
  cmp    $0x1,%esi
  mov    $0x41,%edx
  lea    0x34(%rsp),%rsi
  adc    $0x0,%r11d
  jmp    L152
  nopl   0x0(%rax,%rax,1)
L21:
  mov    (%rsi),%edx
  add    $0x4,%rsi
L152:
  xor    %ebx,%ebx
  cmp    %edx,%eax
  sete   %bl
  add    $0x20,%edx
  add    %ebx,%r12d
  cmp    %eax,%edx
  sete   %dl
  movzbl %dl,%edx
  add    %edx,%r12d
  cmp    %r9,%rsi
  jne    L21
  lea    0x64(%rsp),%rsi
  mov    $0x42,%edx
  jmp    L25
  nopw   0x0(%rax,%rax,1)
L17:
  mov    (%rsi),%edx
  add    $0x4,%rsi
L25:
  xor    %ebx,%ebx
  cmp    %edx,%eax
  sete   %bl
  add    $0x20,%edx
  add    %ebx,%ebp
  cmp    %eax,%edx
  sete   %dl
  movzbl %dl,%edx
  add    %edx,%ebp
  cmp    %rdi,%rsi
  jne    L17
  lea    0x4(%rsp),%rsi
  xor    %edx,%edx
  jmp    L122
  nopw   0x0(%rax,%rax,1)
L43:
  mov    (%rsi),%edx
  add    $0x4,%rsi
L122:
  add    $0x30,%edx
  cmp    %eax,%edx
  sete   %dl
  movzbl %dl,%edx
  add    %edx,%r13d
  cmp    %rsi,%r10
  jne    L43
  mov    $0x1,%esi
  jmp    L64
L103:
  call   <__stack_chk_fail@plt>
```

tool_calls: name: unpack_data
arguments: data_tag: D11
data_type: string
name: unpack_data
arguments: data_tag: D31
data_type: string
name: unpack_data
arguments: data_tag: D24
data_type: string
name: unpack_data
arguments: data_tag: D29
data_type: string

tool: D11: %d mot(s)


tool: D31: %d consonnes(s)


tool: D24: %d voyelle(s)


tool: D29: %d chiffre(s)

assistant: ```c
void str_stats(char *arg) {
  const DEHORS = 0;
  const DEDANS = 1;
  enum voyellesMaj { A = 65, E = 69, I = 73, O = 79, U = 85, Y = 89 };
  enum chiffres { ZERO, UN, DEUX, TROIS, QUATRE, CINQ, SIX, SEPT, HUIT, NEUF };
  enum consonnes { B = 66, C = 67, D = 68, F = 70, G = 71, H = 72, J = 74, K = 75, L = 76, M = 77, N = 78, P = 80, Q = 81, R = 82, S = 83, T = 84, V = 86, W = 87, X = 88, Z = 90 };
  int i, j, g, taille, tailleV, tailleCo, tailleCh, etat, mots, voyelles, consonnes, chiffres;
  etat = mots = voyelles = consonnes = chiffres = 0;
  taille = tailleCo = tailleCh = 0;
  int tabv[12] = {A, E, I, O, U, Y};
  int tabco[21] = {B, C, D, F, G, H, J, K, L, M, N, P, Q, R, S, T, V, W, X, Y, Z};
  int tabch[10] = {ZERO, UN, DEUX, TROIS, QUATRE, CINQ, SIX, SEPT, HUIT, NEUF};
  do {
    taille++;
  } while (arg[taille] != '\0');
  for (i = 0; i < taille; i++) {
    int c = arg[i];
    if ((c >= ' ' && c <= '/') || (c >= '{' && c < 128 || c >= '[' && c <= 96)) {
      etat = DEHORS;
    } else if (c >= '0' && c <= 'Z' || c >= 'a' && c <= 'z') {
      if (etat == DEHORS)
        mots++;
      etat = DEDANS;
      for (j = 0; j < 12; j++) {
        (c == tabv[j]) ? voyelles++ : 0;
        (c == (tabv[j] + 32)) ? voyelles++ : 0;
      }
      for (j = 0; j < 21; j++) {
        (c == tabco[j]) ? consonnes++ : 0;
        (c == (tabco[j] + 32)) ? consonnes++ : 0;
      }
      for (j = 0; j < 10; j++) {
        (c == (tabch[j] + 48)) ? chiffres++ : 0;
      }
    }
  }
  printf("%d mot(s)\n", mots);
  printf("%d consonnes(s)\n", consonnes);
  printf("%d voyelle(s)\n", voyelles);
  printf("%d chiffre(s)", chiffres);
}
```