user: Translate the below assembly code into C programming language:

```asm
<read_chat>:
  endbr64
  push   %r15
  push   %r14
  push   %r13
  push   %r12
  push   %rbp
  push   %rbx
  sub    $0x28,%rsp
  mov    (%rdi),%r14
  mov    %rdi,0x8(%rsp)
  mov    %fs:0x28,%rax
  mov    %rax,0x18(%rsp)
  xor    %eax,%eax
  test   %r14,%r14
  je     L274
  mov    %r14,%rdi
  call   <strlen@plt>
  mov    %eax,%ebx
  test   %eax,%eax
  jle    L218
  lea    0x1(%rax),%edi
  call   <malloc@plt>
  mov    %rax,(%rsp)
  mov    %rax,%r15
  test   %rax,%rax
  je     L218
  sar    %ebx
  lea    0x8(,%rbx,8),%edi
  call   <malloc@plt>
  mov    %rax,%r12
  test   %rax,%rax
  je     L88
  mov    %r14,%rsi
  mov    %r15,%rdi
  lea    D16(%rip),%r14
  call   <strcpy@plt>
  mov    %r15,%rdi
  mov    %r14,%rsi
  call   <strtok@plt>
  mov    %rax,%r15
  test   %rax,%rax
  je     L268
  mov    $0x1,%r13d
  lea    D17(%rip),%rbp
  nopl   (%rax)
L312:
  mov    %r15,0x10(%rsp)
  movzbl (%r15),%edx
  test   %dl,%dl
  je     L23
  mov    %r15,%rax
  mov    %r15,%rbx
  jmp    L45
  nopl   0x0(%rax)
L68:
  mov    %dl,(%rbx)
  mov    0x10(%rsp),%rdx
  add    $0x1,%rbx
  lea    0x1(%rdx),%rax
L224:
  mov    %rax,0x10(%rsp)
  cmpb   $0x0,(%rbx)
  je     L23
L31:
  movzbl 0x1(%rdx),%edx
L45:
  cmp    $0x5c,%dl
  jne    L68
  lea    0x1(%rax),%rdi
  mov    %rdi,0x10(%rsp)
  movzbl 0x1(%rax),%esi
  test   %sil,%sil
  je     L104
  lea    -0x30(%rsi),%edx
  cmp    $0x48,%dl
  ja     L97
  movzbl %dl,%edx
  movslq 0x0(%rbp,%rdx,4),%rdx
  add    %rbp,%rdx
  notrack jmp *%rdx
  nopw   0x0(%rax,%rax,1)
L218:
  movq   $0x0,(%rsp)
L88:
  mov    (%rsp),%rdi
  xor    %r14d,%r14d
  call   <free@plt>
L274:
  mov    0x18(%rsp),%rax
  sub    %fs:0x28,%rax
  jne    L177
  add    $0x28,%rsp
  mov    %r14,%rax
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  pop    %r15
  ret
  nopw   0x0(%rax,%rax,1)
L97:
  mov    %sil,(%rbx)
  mov    0x10(%rsp),%rdx
  add    $0x1,%rbx
  lea    0x1(%rdx),%rax
  mov    %rax,0x10(%rsp)
  cmpb   $0x0,(%rbx)
  jne    L31
  cs nopw 0x0(%rax,%rax,1)
L23:
  movsbl (%r15),%esi
  cmp    $0x22,%sil
  je     L115
  cmp    $0x27,%sil
  je     L115
L5:
  mov    %r15,-0x8(%r12,%r13,8)
  mov    %r14,%rsi
  xor    %edi,%edi
  movslq %r13d,%rbx
  add    $0x1,%r13
  call   <strtok@plt>
  mov    %rax,%r15
  test   %rax,%rax
  jne    L312
  lea    (%r12,%rbx,8),%rax
L62:
  movq   $0x0,(%rax)
  mov    (%rsp),%rcx
  mov    %r12,%r14
  mov    0x8(%rsp),%rax
  mov    %rcx,(%rax)
  jmp    L274
  nopl   0x0(%rax)
  movb   $0x20,(%rbx)
  mov    0x10(%rsp),%rdx
  add    $0x1,%rbx
  lea    0x1(%rdx),%rax
  jmp    L224
  movb   $0x8,(%rbx)
  mov    0x10(%rsp),%rdx
  add    $0x1,%rbx
  lea    0x1(%rdx),%rax
  jmp    L224
  movb   $0x7,(%rbx)
  mov    0x10(%rsp),%rdx
  add    $0x1,%rbx
  lea    0x1(%rdx),%rax
  jmp    L224
  movb   $0xff,(%rbx)
  mov    0x10(%rsp),%rdx
  add    $0x1,%rbx
  lea    0x1(%rdx),%rax
  jmp    L224
  movb   $0xa,(%rbx)
  mov    0x10(%rsp),%rdx
  add    $0x1,%rbx
  lea    0x1(%rdx),%rax
  jmp    L224
  movb   $0xc,(%rbx)
  mov    0x10(%rsp),%rdx
  add    $0x1,%rbx
  lea    0x1(%rdx),%rax
  jmp    L224
  movb   $0x1b,(%rbx)
  mov    0x10(%rsp),%rdx
  add    $0x1,%rbx
  lea    0x1(%rdx),%rax
  jmp    L224
  add    $0x2,%rax
  lea    0x10(%rsp),%rdi
  mov    $0x3,%edx
  mov    $0x8,%esi
  mov    %rax,0x10(%rsp)
L168:
  call   <getdigit@plt>
  add    $0x1,%rbx
  mov    %al,-0x1(%rbx)
  mov    0x10(%rsp),%rax
  lea    -0x1(%rax),%rdx
  jmp    L224
  add    $0x2,%rax
  lea    0x10(%rsp),%rdi
  mov    $0x2,%edx
  mov    $0x10,%esi
  mov    %rax,0x10(%rsp)
  jmp    L168
  movb   $0x9,(%rbx)
  mov    0x10(%rsp),%rdx
  add    $0x1,%rbx
  lea    0x1(%rdx),%rax
  jmp    L224
  movb   $0xd,(%rbx)
  mov    0x10(%rsp),%rdx
  add    $0x1,%rbx
  lea    0x1(%rdx),%rax
  jmp    L224
  nopl   0x0(%rax)
L115:
  lea    0x1(%r15),%rbx
  mov    %rbx,%rdi
  call   <strrchr@plt>
  mov    %rax,0x10(%rsp)
  test   %rax,%rax
  je     L5
  movzbl (%rax),%esi
  movsbl (%r15),%edx
  cmp    %edx,%esi
  jne    L5
  cmpb   $0x0,0x1(%rax)
  jne    L5
  movb   $0x0,(%rax)
  mov    %rbx,%rsi
  mov    %r15,%rdi
  call   <strcpy@plt>
  jmp    L5
  cs nopw 0x0(%rax,%rax,1)
L104:
  mov    %rax,%rdx
  mov    %rdi,%rax
  jmp    L224
L268:
  mov    %r12,%rax
  jmp    L62
L177:
  call   <__stack_chk_fail@plt>
```

assistant: ```c
char **read_chat(char **chatstr) {
  char *str = *chatstr;
  char **res = NULL;
  if (str != NULL) {
    char *tmp = NULL;
    int l;
    if ((l = strlen(str)) > 0 && (tmp = malloc(l + 1)) != NULL && (res = malloc((l / 2 + 1) * sizeof(char *))) != NULL) {
      static char ws[] = " \t";
      char *p;
      for (l = 0, p = strtok(strcpy(tmp, str), ws); p != NULL; p = strtok(NULL, ws)) {
        unsigned char *q, *r;
        for (q = r = (unsigned char *)p; *r; ++q) {
          if (*q == '\\') {
            switch (*++q) {
            case 'a':
              *r++ = '\a';
              break;
            case 'r':
              *r++ = '\r';
              break;
            case 'n':
              *r++ = '\n';
              break;
            case 'f':
              *r++ = '\f';
              break;
            case 'b':
              *r++ = '\b';
              break;
            case 'e':
              *r++ = 27;
              break;
            case 't':
              *r++ = '\t';
              break;
            case 'p':
              *r++ = (unsigned char)'\xff';
              break;
            case 's':
            case 'S':
              *r++ = ' ';
              break;
            case 'x':
              ++q;
              *r++ = getdigit(&q, 16, 2);
              --q;
              break;
            case '0':
              ++q;
              *r++ = getdigit(&q, 8, 3);
              --q;
              break;
            default:
              *r++ = *q;
              break;
            case 0:
              --q;
              break;
            }
          } else {
            *r++ = *q;
          }
        }
        if (*p == '"' || *p == '\'') {
          q = strrchr(p + 1, *p);
          if (q != NULL && *q == *p && q[1] == '\0') {
            *q = '\0';
            strcpy(p, p + 1);
          }
        }
        res[l++] = p;
      }
      res[l] = NULL;
      *chatstr = tmp;
      return res;
    }
    free(tmp);
  }
  return res;
}
```