user: Please show me the C implementation that matches the assembly code listed below:

```asm
<parse_relax>:
  endbr64
  push   %r15
  push   %r14
  push   %r13
  push   %r12
  push   %rbp
  push   %rbx
  sub    $0x8,%rsp
  call   <xstrdup@plt>
  mov    %rax,%r13
  mov    %rax,%rdi
  call   <assert@plt>
  lea    D50(%rip),%rsi
  mov    %r13,%rdi
  call   <strtok@plt>
  test   %rax,%rax
  je     L141
  mov    %rax,%rbx
  mov    $0x0,%ebp
  lea    D40(%rip),%r12
  lea    D53(%rip),%r14
  lea    D17(%rip),%r15
  jmp    L99
L146:
  or     $0x1,%ebp
L34:
  lea    D50(%rip),%rsi
  mov    $0x0,%edi
  call   <strtok@plt>
  mov    %rax,%rbx
  test   %rax,%rax
  je     L31
L99:
  mov    %r12,%rsi
  mov    %rbx,%rdi
  call   <strcmp@plt>
  test   %rax,%rax
  je     L146
  mov    %r14,%rsi
  mov    %rbx,%rdi
  call   <strcmp@plt>
  test   %rax,%rax
  jne    L38
  or     $0x2,%ebp
  jmp    L34
L38:
  mov    %r15,%rsi
  mov    %rbx,%rdi
  call   <strcmp@plt>
  test   %rax,%rax
  jne    L97
  lea    D22(%rip),%rdi
  call   <warnf@plt>
  or     $0x2,%ebp
  jmp    L34
L97:
  lea    D48(%rip),%rsi
  mov    %rbx,%rdi
  call   <strcmp@plt>
  test   %rax,%rax
  jne    L78
  or     $0x4,%ebp
  jmp    L34
L78:
  lea    D79(%rip),%rsi
  mov    %rbx,%rdi
  call   <strcmp@plt>
  test   %rax,%rax
  jne    L14
  or     $0x8,%ebp
  jmp    L34
L14:
  lea    D3(%rip),%rsi
  mov    %rbx,%rdi
  call   <strcmp@plt>
  test   %rax,%rax
  jne    L4
  or     $0x10,%ebp
  jmp    L34
L4:
  mov    %rbx,%rsi
  lea    D99(%rip),%rdi
  call   <fatal@plt>
  jmp    L34
L141:
  mov    $0x0,%ebp
L31:
  mov    %r13,%rdi
  call   <free@plt>
  mov    %ebp,%eax
  add    $0x8,%rsp
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  pop    %r15
  ret
```

tool_calls: name: parse_data
arguments: tag: D50
data_type: string
name: parse_data
arguments: tag: D40
data_type: string
name: parse_data
arguments: tag: D53
data_type: string
name: parse_data
arguments: tag: D17
data_type: string
name: parse_data
arguments: tag: D22
data_type: string
name: parse_data
arguments: tag: D48
data_type: string
name: parse_data
arguments: tag: D79
data_type: string
name: parse_data
arguments: tag: D3
data_type: string
name: parse_data
arguments: tag: D99
data_type: string

tool: D50: ,

tool: D40: prefer-explicit

tool: D53: locally-static

tool: D17: generic-static

tool: D22: relax option 'generic-static' is deprecated: use 'locally-static' instead

tool: D48: universal-bound

tool: D79: pure-files

tool: D3: impure

tool: D99: invalid relax option '%s'

assistant: ```c
unsigned parse_relax(const char *str) {
  char *copy = xstrdup(str);
  assert(copy);
  unsigned mask = 0;
  char *token = strtok(copy, ",");
  while (token != NULL) {
    if (strcmp(token, "prefer-explicit") == 0)
      mask |= (1 << 0);
    else if (strcmp(token, "locally-static") == 0)
      mask |= (1 << 1);
    else if (strcmp(token, "generic-static") == 0) {
      warnf("relax option 'generic-static' is deprecated: use "
            "'locally-static' instead");
      mask |= (1 << 1);
    } else if (strcmp(token, "universal-bound") == 0)
      mask |= (1 << 2);
    else if (strcmp(token, "pure-files") == 0)
      mask |= (1 << 3);
    else if (strcmp(token, "impure") == 0)
      mask |= (1 << 4);
    else
      fatal("invalid relax option '%s'", token);
    token = strtok(NULL, ",");
  }
  free(copy);
  return mask;
}
```