user: Converte this assembly snippet into its equivalent C code:

```asm
<parse_relax>:
  endbr64
  push   %rbp
  mov    %rsp,%rbp
  sub    $0x30,%rsp
  mov    %rdi,-0x28(%rbp)
  mov    -0x28(%rbp),%rax
  mov    %rax,%rdi
  call   <xstrdup@plt>
  mov    %rax,-0x8(%rbp)
  mov    -0x8(%rbp),%rax
  mov    %rax,%rdi
  call   <assert@plt>
  movl   $0x0,-0x14(%rbp)
  mov    -0x8(%rbp),%rax
  lea    D78(%rip),%rdx
  mov    %rdx,%rsi
  mov    %rax,%rdi
  call   <strtok@plt>
  mov    %rax,-0x10(%rbp)
  jmp    L20
L137:
  mov    -0x10(%rbp),%rax
  lea    D96(%rip),%rdx
  mov    %rdx,%rsi
  mov    %rax,%rdi
  call   <strcmp@plt>
  test   %rax,%rax
  jne    L48
  orl    $0x1,-0x14(%rbp)
  jmp    L55
L48:
  mov    -0x10(%rbp),%rax
  lea    D71(%rip),%rdx
  mov    %rdx,%rsi
  mov    %rax,%rdi
  call   <strcmp@plt>
  test   %rax,%rax
  jne    L14
  orl    $0x2,-0x14(%rbp)
  jmp    L55
L14:
  mov    -0x10(%rbp),%rax
  lea    D41(%rip),%rdx
  mov    %rdx,%rsi
  mov    %rax,%rdi
  call   <strcmp@plt>
  test   %rax,%rax
  jne    L77
  lea    D95(%rip),%rax
  mov    %rax,%rdi
  call   <warnf@plt>
  orl    $0x2,-0x14(%rbp)
  jmp    L55
L77:
  mov    -0x10(%rbp),%rax
  lea    D76(%rip),%rdx
  mov    %rdx,%rsi
  mov    %rax,%rdi
  call   <strcmp@plt>
  test   %rax,%rax
  jne    L69
  orl    $0x4,-0x14(%rbp)
  jmp    L55
L69:
  mov    -0x10(%rbp),%rax
  lea    D40(%rip),%rdx
  mov    %rdx,%rsi
  mov    %rax,%rdi
  call   <strcmp@plt>
  test   %rax,%rax
  jne    L10
  orl    $0x8,-0x14(%rbp)
  jmp    L55
L10:
  mov    -0x10(%rbp),%rax
  lea    D31(%rip),%rdx
  mov    %rdx,%rsi
  mov    %rax,%rdi
  call   <strcmp@plt>
  test   %rax,%rax
  jne    L0
  orl    $0x10,-0x14(%rbp)
  jmp    L55
L0:
  mov    -0x10(%rbp),%rax
  mov    %rax,%rsi
  lea    D24(%rip),%rax
  mov    %rax,%rdi
  call   <fatal@plt>
L55:
  lea    D78(%rip),%rax
  mov    %rax,%rsi
  mov    $0x0,%edi
  call   <strtok@plt>
  mov    %rax,-0x10(%rbp)
L20:
  cmpq   $0x0,-0x10(%rbp)
  jne    L137
  mov    -0x8(%rbp),%rax
  mov    %rax,%rdi
  call   <free@plt>
  mov    -0x14(%rbp),%eax
  leave
  ret
```

tool_calls: name: retrieve_data
arguments: tag: D78
type_guessed: string
name: retrieve_data
arguments: tag: D96
type_guessed: string
name: retrieve_data
arguments: tag: D71
type_guessed: string
name: retrieve_data
arguments: tag: D41
type_guessed: string
name: retrieve_data
arguments: tag: D95
type_guessed: string
name: retrieve_data
arguments: tag: D76
type_guessed: string
name: retrieve_data
arguments: tag: D40
type_guessed: string
name: retrieve_data
arguments: tag: D31
type_guessed: string
name: retrieve_data
arguments: tag: D24
type_guessed: string

tool: D78: ,

tool: D96: prefer-explicit

tool: D71: locally-static

tool: D41: generic-static

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

tool: D76: universal-bound

tool: D40: pure-files

tool: D31: impure

tool: D24: 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;
}
```