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

```asm
<purify_special_char>:
  endbr64
  push   %r14
  mov    %rdi,%r14
  xor    %edi,%edi
  push   %r13
  mov    %rdx,%r13
  push   %r12
  mov    %rsi,%r12
  push   %rbp
  push   %rbx
  movslq (%rsi),%rax
  cmpb   $0x7b,(%r14,%rax,1)
  jne    L20
  xor    %edi,%edi
  cmpb   $0x5c,0x1(%r14,%rax,1)
  sete   %dil
L20:
  call   <assert@plt>
  mov    (%r12),%eax
  lea    0x2(%rax),%ebp
  mov    %ebp,(%r12)
  movslq %ebp,%rbp
L114:
  movsbl (%r14,%rbp,1),%edi
  mov    %ebp,%ebx
  add    $0x1,%rbp
  call   <isalpha@plt>
  test   %rax,%rax
  jne    L114
  mov    (%r12),%esi
  mov    %r14,%rdi
  cmp    %ebx,%esi
  lea    0x1(%rsi),%eax
  cmove  %eax,%ebx
  xor    %ecx,%ecx
  mov    %ebx,%edx
  call   <foreign_letter@plt>
  test   %rax,%rax
  jne    L126
  mov    %ebx,(%r12)
L108:
  movslq %ebx,%rax
  mov    $0x1,%ebp
  movsbl (%r14,%rax,1),%edi
  test   %dil,%dil
  jne    L60
  jmp    L75
  xchg   %ax,%ax
L10:
  call   <isalpha@plt>
  test   %rax,%rax
  je     L158
  movslq (%r12),%rdx
  lea    0x1(%rdx),%eax
  mov    %eax,(%r12)
  movslq 0x0(%r13),%rax
  lea    0x1(%rax),%ecx
  mov    %ecx,0x0(%r13)
  movzbl (%r14,%rdx,1),%edx
  mov    %dl,(%r14,%rax,1)
  mov    (%r12),%ebx
L15:
  movslq %ebx,%rax
  movsbl (%r14,%rax,1),%edi
  test   %dil,%dil
  je     L75
L60:
  cmp    $0x7b,%dil
  je     L50
  cmp    $0x7d,%dil
  jne    L10
  sub    $0x1,%ebp
  je     L75
  add    $0x1,%ebx
  movslq %ebx,%rax
  mov    %ebx,(%r12)
  movsbl (%r14,%rax,1),%edi
  test   %dil,%dil
  jne    L60
L75:
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  ret
  nopl   0x0(%rax,%rax,1)
L50:
  add    $0x1,%ebx
  add    $0x1,%ebp
  mov    %ebx,(%r12)
  jmp    L15
  nopl   0x0(%rax)
L158:
  mov    (%r12),%eax
  lea    0x1(%rax),%ebx
  mov    %ebx,(%r12)
  jmp    L15
  nopl   (%rax)
L126:
  mov    %ebx,%eax
  sub    (%r12),%eax
  xor    %edi,%edi
  sub    $0x1,%eax
  cmp    $0x1,%eax
  setbe  %dil
  call   <assert@plt>
  movslq (%r12),%rdx
  lea    0x1(%rdx),%eax
  mov    %eax,(%r12)
  movslq 0x0(%r13),%rax
  lea    0x1(%rax),%ecx
  mov    %ecx,0x0(%r13)
  movzbl (%r14,%rdx,1),%edx
  mov    %dl,(%r14,%rax,1)
  movslq (%r12),%rax
  cmp    %ebx,%eax
  jl     L138
  mov    %eax,%ebx
  jmp    L108
L138:
  lea    0x1(%rax),%edx
  mov    %edx,(%r12)
  movsbl (%r14,%rax,1),%edi
  movslq 0x0(%r13),%rax
  lea    0x1(%rax),%edx
  lea    (%r14,%rax,1),%rbx
  mov    %edx,0x0(%r13)
  call   <tolower@plt>
  mov    %al,(%rbx)
  mov    (%r12),%ebx
  jmp    L108
```

assistant: ```c
void purify_special_char(char *str, int *src, int *dst) {
  int depth;
  int peek;
  assert(str[*src] == '{' && str[*src + 1] == '\\');
  depth = 1;
  *src += 2;
  peek = *src;
  while (isalpha(str[peek]))
    peek++;
  if (peek == *src)
    peek++;
  if (foreign_letter(str, *src, peek, NULL)) {
    assert(peek - *src == 1 || peek - *src == 2);
    str[(*dst)++] = str[(*src)++];
    if (*src < peek)
      str[(*dst)++] = tolower(str[(*src)++]);
  } else {
    *src = peek;
  }
  while (str[*src]) {
    switch (str[*src]) {
    case '{':
      depth++;
      (*src)++;
      break;
    case '}':
      depth--;
      if (depth == 0)
        return;
      (*src)++;
      break;
    default:
      if (isalpha(str[*src]))
        str[(*dst)++] = str[(*src)++];
      else
        (*src)++;
    }
  }
}
```