user: 请将以下的汇编代码转换成C语言代码：

```asm
<fnmatch>:
  endbr64
  push   %r15
  mov    %edx,%r15d
  push   %r14
  push   %r13
  mov    %edx,%r13d
  push   %r12
  and    $0x4,%r13d
  mov    %rsi,%r12
  push   %rbp
  mov    %rsi,%rbp
  push   %rbx
  mov    %rdi,%rbx
  sub    $0x8,%rsp
L208:
  movzbl (%rbx),%edi
  movzbl 0x0(%rbp),%r14d
  lea    0x1(%rbx),%r8
  cmp    $0x3f,%dil
  je     L259
  jg     L274
  test   %dil,%dil
  je     L358
  cmp    $0x2a,%dil
  jne    L417
  movzbl 0x1(%rbx),%eax
  mov    %r8,%rbx
  cmp    $0x2a,%al
  jne    L177
  nop
L7:
  movzbl 0x1(%rbx),%eax
  add    $0x1,%rbx
  cmp    $0x2a,%al
  je     L7
L177:
  cmp    $0x2e,%r14b
  je     L67
L348:
  test   %al,%al
  je     L217
  cmp    $0x2f,%al
  jne    L382
  test   $0x2,%r15b
  je     L382
  mov    %rbp,%rdi
  mov    $0x2f,%esi
  call   <strchr@plt>
  mov    %rax,%rbp
  test   %rax,%rax
  jne    L208
L436:
  add    $0x8,%rsp
  mov    $0x1,%eax
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  pop    %r15
  ret
  nopl   0x0(%rax)
L274:
  cmp    $0x5b,%dil
  je     L110
  cmp    $0x5c,%dil
  jne    L417
  test   $0x1,%r15b
  je     L34
L417:
  mov    %r8,%rbx
L55:
  cmp    %dil,%r14b
  je     L414
  test   $0x10,%r15b
  je     L436
  call   <tolower@plt>
  movzbl 0x0(%rbp),%edi
  mov    %eax,%r14d
  call   <tolower@plt>
  cmp    %eax,%r14d
  jne    L436
L414:
  add    $0x1,%rbp
  jmp    L208
  nopl   0x0(%rax,%rax,1)
L110:
  test   %r14b,%r14b
  je     L436
  cmp    $0x2f,%r14b
  jne    L408
  test   $0x2,%r15b
  jne    L436
L408:
  movsbl %r14b,%esi
  mov    %r15d,%edx
  mov    %r8,%rdi
  call   <rangematch@plt>
  mov    %rax,%rbx
  test   %rax,%rax
  jne    L414
  jmp    L436
  nopl   (%rax)
L358:
  and    $0x8,%r15d
  jne    L499
L178:
  xor    %eax,%eax
  test   %r14b,%r14b
  setne  %al
L299:
  add    $0x8,%rsp
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  pop    %r15
  ret
  nopl   0x0(%rax)
L259:
  test   %r14b,%r14b
  je     L436
  cmp    $0x2f,%r14b
  je     L314
  cmp    $0x2e,%r14b
  jne    L4
  test   %r13d,%r13d
  je     L4
  cmp    %r12,%rbp
  je     L436
  test   $0x2,%r15b
  je     L4
  cmpb   $0x2f,-0x1(%rbp)
  je     L436
  nopw   0x0(%rax,%rax,1)
L4:
  add    $0x1,%rbp
  mov    %r8,%rbx
  jmp    L208
  nopl   0x0(%rax)
L34:
  movzbl 0x1(%rbx),%eax
  test   %al,%al
  je     L417
  add    $0x2,%rbx
  movzbl %al,%edi
  jmp    L55
  nopl   0x0(%rax,%rax,1)
L499:
  cmp    $0x2f,%r14b
  jne    L178
L223:
  add    $0x8,%rsp
  xor    %eax,%eax
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  pop    %r15
  ret
  nopl   0x0(%rax,%rax,1)
L67:
  test   %r13d,%r13d
  je     L348
  cmp    %r12,%rbp
  je     L436
  test   $0x2,%r15b
  je     L348
  cmpb   $0x2f,-0x1(%rbp)
  jne    L348
  jmp    L436
  nopl   0x0(%rax,%rax,1)
L314:
  test   $0x2,%r15b
  jne    L436
  add    $0x1,%rbp
  mov    %r8,%rbx
  jmp    L208
L382:
  mov    %r15d,%r12d
  and    $0x2,%r15d
  and    $0xfffffffb,%r12d
  test   %r14b,%r14b
  jne    L24
  jmp    L436
  nopl   0x0(%rax,%rax,1)
L323:
  movzbl 0x1(%rbp),%r14d
  add    $0x1,%rbp
  test   %r14b,%r14b
  je     L436
L24:
  mov    %r12d,%edx
  mov    %rbp,%rsi
  mov    %rbx,%rdi
  call   <fnmatch>
  test   %eax,%eax
  je     L223
  cmp    $0x2f,%r14b
  jne    L323
  test   %r15d,%r15d
  je     L323
  jmp    L436
L217:
  test   $0x2,%r15b
  je     L223
  and    $0x8,%r15d
  jne    L223
  mov    $0x2f,%esi
  mov    %rbp,%rdi
  call   <strchr@plt>
  test   %rax,%rax
  setne  %al
  movzbl %al,%eax
  jmp    L299
```

assistant: ```c
int fnmatch(const char *pattern, const char *string, int flags) {
  const char *stringstart;
  char c;
  char test;
  for (stringstart = string;;)
    switch (c = *pattern++) {
    case '\0':
      if ((flags & 0x08) && *string == '/')
        return (0);
      return (*string == '\0' ? 0 : 1);
    case '?':
      if (*string == '\0')
        return (1);
      if (*string == '/' && (flags & 0x02))
        return (1);
      if (*string == '.' && (flags & 0x04) && (string == stringstart || ((flags & 0x02) && *(string - 1) == '/')))
        return (1);
      ++string;
      break;
    case '*':
      c = *pattern;
      while (c == '*')
        c = *++pattern;
      if (*string == '.' && (flags & 0x04) && (string == stringstart || ((flags & 0x02) && *(string - 1) == '/')))
        return (1);
      if (c == '\0')
        if (flags & 0x02)
          return ((flags & 0x08) || strchr(string, '/') == NULL ? 0 : 1);
        else
          return (0);
      else if (c == '/' && flags & 0x02) {
        if ((string = strchr(string, '/')) == NULL)
          return (1);
        break;
      }
      while ((test = *string) != '\0') {
        if (!fnmatch(pattern, string, flags & ~0x04))
          return (0);
        if (test == '/' && flags & 0x02)
          break;
        ++string;
      }
      return (1);
    case '[':
      if (*string == '\0')
        return (1);
      if (*string == '/' && flags & 0x02)
        return (1);
      if ((pattern = rangematch(pattern, *string, flags)) == NULL)
        return (1);
      ++string;
      break;
    case '\\':
      if (!(flags & 0x01)) {
        if ((c = *pattern++) == '\0') {
          c = '\\';
          --pattern;
        }
      }
    default:
      if (c == *string)
        ;
      else if ((flags & 0x10) && (tolower((unsigned char)c) == tolower((unsigned char)*string)))
        ;
      else
        return (1);
      string++;
      break;
    }
}
```