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

```asm
<nip_count_tokens>:
  endbr64
  push   %r15
  push   %r14
  push   %r13
  push   %r12
  push   %rbp
  push   %rbx
  sub    $0x28,%rsp
  mov    %rdi,%rbp
  mov    %rsi,%r12
  mov    %edx,0x18(%rsp)
  mov    %rcx,%r14
  mov    %r8d,0x14(%rsp)
  mov    %r9d,0x10(%rsp)
  test   %rsi,%rsi
  je     L246
  movl   $0x0,(%rsi)
L246:
  movzbl 0x0(%rbp),%edi
  test   %dil,%dil
  je     L320
  mov    $0x0,%r15d
  mov    $0x0,%r13d
  movl   $0x0,0x1c(%rsp)
  mov    0x14(%rsp),%eax
  lea    -0x1(%rax),%eax
  lea    0x1(%r14,%rax,1),%rbx
  jmp    L98
L5:
  cmpl   $0x0,0x14(%rsp)
  jle    L327
  mov    %r14,%rax
L104:
  cmp    %dil,(%rax)
  je     L157
  add    $0x1,%rax
  cmp    %rbx,%rax
  jne    L104
  jmp    L327
L157:
  mov    $0x1,%r15d
  jmp    L327
L183:
  cmpl   $0x0,0x18(%rsp)
  setne  0xf(%rsp)
  movzbl 0xf(%rsp),%ecx
  cmp    $0x22,%dil
  sete   %dl
  test   %al,%dl
  je     L319
  test   %cl,%cl
  jne    L290
L319:
  test   %r13d,%r13d
  jne    L314
  cmpl   $0x0,0x60(%rsp)
  jne    L270
  mov    0x60(%rsp),%r13d
  cmpb   $0xa,0x0(%rbp)
  je     L333
L176:
  addl   $0x1,0x1c(%rsp)
  mov    $0x1,%r13d
  jmp    L333
L290:
  lea    0x1(%rbp),%rax
L237:
  movzbl (%rax),%edx
  test   %dl,%dl
  je     L333
  add    $0x1,%rax
  cmp    $0x22,%dl
  jne    L237
  addl   $0x1,0x1c(%rsp)
  mov    $0x2,%r13d
  jmp    L333
L270:
  movsbl %dil,%edi
  call   <isspace@plt>
  test   %rax,%rax
  jne    L333
  jmp    L176
L314:
  cmpl   $0x0,0x60(%rsp)
  je     L297
  cmp    $0x1,%r13d
  je     L233
L297:
  movzbl 0x0(%rbp),%eax
  cmp    $0xa,%al
  je     L211
  cmp    $0x2,%r13d
  sete   %dl
  test   %dl,0xf(%rsp)
  je     L333
  cmp    $0x22,%al
  mov    $0x0,%eax
  cmove  %eax,%r13d
  jmp    L333
L233:
  movsbl %dil,%edi
  call   <isspace@plt>
  test   %rax,%rax
  je     L297
  mov    $0x0,%r13d
  jmp    L333
L204:
  mov    0x10(%rsp),%r13d
  mov    %r13d,%r15d
L333:
  add    $0x1,%rbp
  test   %r12,%r12
  je     L168
  addl   $0x1,(%r12)
L168:
  movzbl 0x0(%rbp),%edi
  test   %dil,%dil
  je     L110
L98:
  test   %r14,%r14
  jne    L5
L327:
  cmp    $0x2,%r13d
  setne  %al
  test   %r15d,%r15d
  je     L183
  test   %al,%al
  je     L183
  cmpl   $0x0,0x10(%rsp)
  je     L204
  addl   $0x1,0x1c(%rsp)
  mov    $0x0,%r15d
  mov    $0x0,%r13d
  jmp    L333
L211:
  mov    $0x0,%r13d
  jmp    L333
L320:
  movl   $0x0,0x1c(%rsp)
L110:
  mov    0x1c(%rsp),%eax
  add    $0x28,%rsp
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  pop    %r15
  ret
```

assistant: ```c
int nip_count_tokens(const char *s, int *chars, int q_strings, char *separators, int n_separators, int sep_tokens, int wspace_sep) {
  int i;
  int tokens = 0, state = 0;
  int separator_found = 0;
  char ch;
  if (chars)
    *chars = 0;
  while (*s != '\0') {
    if (separators)
      for (i = 0; i < n_separators; i++)
        if (*s == separators[i]) {
          separator_found = 1;
          break;
        }
    if (state != 2 && separator_found) {
      if (sep_tokens)
        tokens++;
      state = 0;
      separator_found = 0;
    } else if (q_strings && state != 2 && (*s == '"')) {
      i = 1;
      while ((ch = s[i++]) != '\0')
        if (ch == '"') {
          state = 2;
          tokens++;
          break;
        }
    } else if (state == 0) {
      if ((wspace_sep && !isspace((int)*s)) || (!wspace_sep && *s != '\n')) {
        tokens++;
        state = 1;
      }
    } else if ((wspace_sep && state == 1 && isspace((int)*s)) || *s == '\n')
      state = 0;
    else if (q_strings && state == 2 && (*s == '"'))
      state = 0;
    s++;
    if (chars)
      (*chars)++;
  }
  return tokens;
}
```