user: 请从给定的汇编指令推导出C源代码:

```asm
<fpattern_submatch>:
  endbr64
  push   %r15
  push   %r14
  push   %r13
  push   %r12
  push   %rbp
  push   %rbx
  sub    $0x28,%rsp
  mov    %rsi,0x10(%rsp)
  movzbl (%rdi),%r13d
  test   %r13b,%r13b
  je     L358
  mov    %rdi,%rbp
  add    $0x1,%rsi
  mov    %rsi,%r15
  jmp    L665
L628:
  cmp    $0x1a,%r13b
  jne    L390
  test   %dl,%dl
  je     L111
  mov    $0x1,%eax
  cmp    $0x2e,%dl
  je     L111
L451:
  mov    %eax,%ecx
  movzbl (%rsi,%rax,1),%edx
  add    $0x1,%rax
  test   %dl,%dl
  je     L40
  cmp    $0x2e,%dl
  jne    L451
L40:
  test   %ecx,%ecx
  js     L347
L493:
  movslq %ecx,%rax
  add    %rax,%rsi
  mov    %rsi,%r13
  sub    %esi,%ecx
  mov    %ecx,%ebp
  jmp    L613
L88:
  cmp    $0x5b,%r13b
  je     L346
  cmp    $0x5c,%r13b
  jne    L390
  movsbl 0x1(%rbp),%ebx
  mov    %r12d,%edi
  call   <tolower@plt>
  mov    %eax,%r12d
  mov    %ebx,%edi
  call   <tolower@plt>
  test   %ebx,%ebx
  je     L584
  cmp    %eax,%r12d
  jne    L584
  add    $0x2,%rbp
  jmp    L619
L562:
  mov    $0x0,%edx
  jmp    L547
L111:
  mov    $0x0,%ecx
  jmp    L493
L672:
  test   %r12d,%r12d
  je     L255
  mov    %rbx,%rbp
L619:
  movzbl 0x0(%rbp),%r13d
  add    $0x1,%r15
  test   %r13b,%r13b
  je     L358
L665:
  lea    -0x1(%r15),%rsi
  mov    %r15,0x10(%rsp)
  movzbl -0x1(%r15),%edx
  movsbl %dl,%r12d
  lea    0x1(%rbp),%rbx
  cmp    $0x3f,%r13b
  je     L672
  jg     L88
  cmp    $0x21,%r13b
  je     L158
  cmp    $0x2a,%r13b
  jne    L628
  mov    $0x1,%eax
  test   %dl,%dl
  je     L562
L450:
  mov    %eax,%edx
  add    $0x1,%rax
  cmpb   $0x0,-0x1(%rsi,%rax,1)
  jne    L450
  test   %edx,%edx
  js     L546
L547:
  movslq %edx,%rax
  add    %rax,%rsi
  mov    %rsi,%r13
  sub    %esi,%edx
  mov    %edx,%ebp
  jmp    L432
L143:
  sub    $0x1,%r13
  mov    %ebp,%eax
  add    %r13d,%eax
  js     L255
L432:
  mov    %r13,%rsi
  mov    %rbx,%rdi
  call   <fpattern_submatch>
  mov    %eax,%r12d
  test   %eax,%eax
  je     L143
  mov    $0x1,%r12d
  jmp    L255
L518:
  sub    $0x1,%r13
  mov    %ebp,%eax
  add    %r13d,%eax
  js     L255
L613:
  mov    %r13,%rsi
  mov    %rbx,%rdi
  call   <fpattern_submatch>
  mov    %eax,%r12d
  test   %eax,%eax
  je     L518
  mov    $0x1,%r12d
  jmp    L255
L346:
  movzbl 0x1(%rbp),%r13d
  cmp    $0x21,%r13b
  je     L389
  cmp    $0x5d,%r13b
  je     L150
  test   %r13b,%r13b
  je     L150
  movl   $0x0,0x18(%rsp)
  movl   $0x1,0x1c(%rsp)
  jmp    L152
L389:
  lea    0x2(%rbp),%rbx
  movzbl 0x2(%rbp),%r13d
  cmp    $0x5d,%r13b
  je     L436
  test   %r13b,%r13b
  je     L436
  movl   $0x1,0x18(%rsp)
  movl   $0x0,0x1c(%rsp)
  jmp    L152
L398:
  movzbl 0x2(%rbx),%eax
  lea    0x2(%rbx),%rdx
  cmp    $0x5c,%al
  je     L149
L12:
  test   %al,%al
  je     L669
  lea    0x1(%rdx),%rbx
  movsbl %al,%eax
  mov    %eax,0xc(%rsp)
  jmp    L603
L149:
  lea    0x3(%rbx),%rdx
  movzbl 0x3(%rbx),%eax
  jmp    L12
L172:
  cmp    $0x5d,%r13b
  je     L483
L152:
  cmp    $0x5c,%r13b
  sete   %al
  movzbl %al,%eax
  add    %rax,%rbx
  movzbl (%rbx),%ebp
  test   %bpl,%bpl
  je     L600
  movsbl %bpl,%ebp
  cmpb   $0x2d,0x1(%rbx)
  je     L398
  add    $0x1,%rbx
  mov    %ebp,0xc(%rsp)
L603:
  movzbl (%rbx),%r13d
  test   %r13b,%r13b
  je     L67
  mov    %r12d,%edi
  call   <tolower@plt>
  mov    %eax,%r14d
  mov    %ebp,%edi
  call   <tolower@plt>
  cmp    %eax,%r14d
  jl     L172
  mov    0xc(%rsp),%edi
  call   <tolower@plt>
  cmp    %eax,%r14d
  mov    0x18(%rsp),%eax
  cmovle 0x1c(%rsp),%eax
  mov    %eax,0x18(%rsp)
  jmp    L172
L669:
  cmpl   $0x0,0x18(%rsp)
  je     L470
  mov    %rdx,%rbx
L436:
  cmpb   $0x0,(%rbx)
  je     L1
L620:
  lea    0x1(%rbx),%rbp
  jmp    L619
L158:
  mov    $0x0,%r12d
  cmpb   $0x0,0x1(%rbp)
  jne    L213
L255:
  mov    %r12d,%eax
  add    $0x28,%rsp
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  pop    %r15
  ret
L213:
  mov    %rbx,%rdi
  call   <fpattern_submatch>
  test   %eax,%eax
  sete   %r12b
  movzbl %r12b,%r12d
  jmp    L255
L390:
  mov    %r12d,%edi
  call   <tolower@plt>
  mov    %eax,%ebp
  movsbl %r13b,%edi
  call   <tolower@plt>
  cmp    %eax,%ebp
  jne    L289
  mov    %rbx,%rbp
  jmp    L619
L358:
  mov    0x10(%rsp),%rax
  cmpb   $0x0,(%rax)
  sete   %r12b
  movzbl %r12b,%r12d
  jmp    L255
L546:
  mov    $0x0,%r12d
  jmp    L255
L347:
  mov    $0x0,%r12d
  jmp    L255
L584:
  mov    $0x0,%r12d
  jmp    L255
L600:
  mov    $0x0,%r12d
  jmp    L255
L67:
  mov    $0x0,%r12d
  jmp    L255
L470:
  mov    0x18(%rsp),%r12d
  jmp    L255
L1:
  mov    $0x0,%r12d
  jmp    L255
L289:
  mov    $0x0,%r12d
  jmp    L255
L483:
  cmpl   $0x0,0x18(%rsp)
  jne    L620
  mov    0x18(%rsp),%r12d
  jmp    L255
L150:
  mov    $0x0,%r12d
  jmp    L255
```

assistant: ```c
int fpattern_submatch(const char *pat, const char *fname) {
  int fch;
  int pch;
  int i;
  int yes, match;
  int lo, hi;
  while (*pat != '\0') {
    fch = *fname;
    pch = *pat;
    pat++;
    switch (pch) {
    case '?':
      if (fch == '\0')
        return (0);
      fname++;
      break;
    case '*':
      i = 0;
      while (fname[i] != '\0')
        i++;
      while (i >= 0) {
        if (fpattern_submatch(pat, fname + i))
          return (1);
        i--;
      }
      return (0);
    case '\x1A':
      i = 0;
      while (fname[i] != '\0' && fname[i] != '.')
        i++;
      while (i >= 0) {
        if (fpattern_submatch(pat, fname + i))
          return (1);
        i--;
      }
      return (0);
    case '\\':
      pch = *pat;
      if (tolower(fch) != tolower(pch) || pch == '\0')
        return (0);
      fname++;
      pat++;
      break;
    case '[':
      yes = 1;
      if (*pat == '!') {
        pat++;
        yes = 0;
      }
      match = !yes;
      while (*pat != ']' && *pat != '\0') {
        if (*pat == '\\')
          pat++;
        if (*pat == '\0')
          break;
        lo = *pat++;
        hi = lo;
        if (*pat == '-') {
          pat++;
          if (*pat == '\\')
            pat++;
          if (*pat == '\0')
            break;
          hi = *pat++;
        }
        if (*pat == '\0')
          break;
        if (tolower(fch) >= tolower(lo) && tolower(fch) <= tolower(hi))
          match = yes;
      }
      if (!match)
        return (0);
      if (*pat == '\0')
        return (0);
      fname++;
      pat++;
      break;
    case '!':
      if (*pat == '\0')
        return (0);
      i = fpattern_submatch(pat, fname);
      return !i;
    default:
      if (tolower(fch) != tolower(pch))
        return (0);
      fname++;
      break;
    }
  }
  if (*fname != '\0')
    return (0);
  return (1);
}
```