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

```asm
<getconfstring>:
  endbr64
  push   %r15
  push   %r14
  push   %r13
  push   %r12
  push   %rbp
  push   %rbx
  sub    $0x18,%rsp
  mov    %rsi,%r13
  mov    %rdx,%r14
  mov    %ecx,%r12d
  mov    %r8,%r15
  mov    %r9,0x8(%rsp)
  mov    0x58(%rsp),%ebp
  mov    $0x0,%ecx
  call   <get_key_value@plt>
  mov    %rax,%rbx
  test   %rax,%rax
  sete   %al
  test   %r12d,%r12d
  jne    L48
  test   %al,%al
  jne    L41
L48:
  test   %r12d,%r12d
  je     L141
  test   %al,%al
  je     L141
  mov    %r15,%rax
  test   %r15,%r15
  je     L161
  mov    %r15,%rbx
L141:
  test   %ebp,%ebp
  je     L158
  mov    0x8(%rsp),%r15
  mov    $0x0,%r12d
  jle    L199
L21:
  mov    (%r15),%rsi
  mov    %rbx,%rdi
  call   <strcasecmp@plt>
  test   %rax,%rax
  je     L32
  add    $0x1,%r12d
  add    $0x8,%r15
  cmp    %r12d,%ebp
  jne    L21
L163:
  mov    %r14,%rdx
  mov    %r13,%rsi
  lea    D21(%rip),%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  mov    $0x1,%edi
  call   <exit@plt>
  mov    %ebp,%r12d
  jmp    L199
L41:
  mov    %r14,%rdx
  mov    %r13,%rsi
  lea    D29(%rip),%rdi
  mov    $0x0,%eax
  call   <printf@plt>
  mov    $0x1,%edi
  call   <exit@plt>
L161:
  add    $0x18,%rsp
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  pop    %r15
  ret
L158:
  mov    %rbx,%rdi
  call   <xstrdup@plt>
  jmp    L161
L32:
  cmp    %r12d,%ebp
  je     L86
L199:
  cmpq   $0x0,0x50(%rsp)
  setne  %al
  cmpq   $0x0,0x60(%rsp)
  je     L126
  test   %al,%al
  je     L126
  movslq %r12d,%r12
  mov    0x50(%rsp),%rax
  mov    (%rax,%r12,4),%eax
  mov    0x60(%rsp),%rcx
  mov    %eax,(%rcx)
  mov    $0x0,%eax
  jmp    L161
L86:
  mov    %r12d,%ebp
  jmp    L163
L126:
  cmpq   $0x0,0x60(%rsp)
  jne    L106
  test   %al,%al
  je     L106
  lea    D13(%rip),%rdi
  call   <puts@plt>
  mov    $0x1,%edi
  call   <exit@plt>
  jmp    L161
L106:
  mov    %rbx,%rdi
  call   <xstrdup@plt>
  jmp    L161
```

tool_calls: name: retrieve_data
arguments: tag: D21
data_type: string
name: retrieve_data
arguments: tag: D29
data_type: string
name: retrieve_data
arguments: tag: D13
data_type: string

tool: D21: Config Item: [%s] %s: set error


tool: D29: Config Item: [%s] %s: not set


tool: D13: return value variable pointer isn't set.

assistant: ```c
char *getconfstring(void *cfgdata, const char *section, const char *key, int isnull, char *notfound, char **values, int *ivalues, int valnum, int *retival) {
  const char *cp;
  int i;
  cp = get_key_value(cfgdata, section, key, NULL);
  if (!cp && !isnull) {
    printf("Config Item: [%s] %s: not set\n", section, key);
    exit(1);
  } else if (!cp && isnull) {
    if (notfound) {
      cp = notfound;
      goto process;
    } else
      return notfound;
  } else {
  process:
    if (valnum == 0)
      return xstrdup(cp);
    for (i = 0; i < valnum; ++i) {
      if (strcasecmp(cp, values[i]) == 0)
        break;
    }
    if (i == valnum) {
      printf("Config Item: [%s] %s: set error\n", section, key);
      exit(1);
    }
    if (ivalues && retival) {
      *retival = ivalues[i];
      return NULL;
    } else if (ivalues && !retival) {
      printf("return value variable pointer isn't set.\n");
      exit(1);
    } else
      return xstrdup(cp);
  }
}
```