user: 请将这段汇编代码片段转换成等效的C代码：

```asm
<getconfstring>:
  endbr64
  push   %r15
  mov    %ecx,%r15d
  xor    %ecx,%ecx
  push   %r14
  push   %r13
  mov    %r8,%r13
  push   %r12
  mov    %rdx,%r12
  push   %rbp
  mov    %rsi,%rbp
  push   %rbx
  sub    $0x28,%rsp
  mov    0x60(%rsp),%rax
  mov    0x68(%rsp),%ebx
  mov    %r9,0x10(%rsp)
  mov    %rax,0x18(%rsp)
  mov    0x70(%rsp),%rax
  mov    %rax,0x8(%rsp)
  call   <get_key_value@plt>
  test   %rax,%rax
  mov    %rax,%r14
  sete   %al
  test   %r15d,%r15d
  jne    L70
  test   %al,%al
  jne    L13
  test   %r15d,%r15d
  jne    L70
L60:
  test   %ebx,%ebx
  je     L6
L106:
  mov    0x10(%rsp),%r13
  mov    $0x0,%r15d
  jg     L71
  jmp    L26
  nopl   0x0(%rax,%rax,1)
L164:
  add    $0x1,%r15d
  add    $0x8,%r13
  cmp    %r15d,%ebx
  je     L15
L71:
  mov    0x0(%r13),%rsi
  mov    %r14,%rdi
  call   <strcasecmp@plt>
  test   %rax,%rax
  jne    L164
L26:
  mov    0x18(%rsp),%rdx
  mov    0x8(%rsp),%rbx
  test   %rdx,%rdx
  setne  %al
  test   %rbx,%rbx
  je     L119
  test   %al,%al
  je     L82
  movslq %r15d,%rcx
  mov    (%rdx,%rcx,4),%eax
  mov    %eax,(%rbx)
  add    $0x28,%rsp
  xor    %eax,%eax
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  pop    %r15
  ret
  nopl   0x0(%rax,%rax,1)
L70:
  test   %al,%al
  je     L60
  test   %r13,%r13
  je     L27
  mov    %r13,%r14
  test   %ebx,%ebx
  jne    L106
  jmp    L6
  xchg   %ax,%ax
L13:
  mov    %r12,%rdx
  mov    %rbp,%rsi
  lea    D2(%rip),%rdi
  xor    %eax,%eax
  call   <printf@plt>
  mov    $0x1,%edi
  call   <exit@plt>
  add    $0x28,%rsp
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  pop    %r15
  ret
  nopl   (%rax)
L82:
  cmpq   $0x0,0x8(%rsp)
  je     L119
L6:
  add    $0x28,%rsp
  mov    %r14,%rdi
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  pop    %r15
  jmp    10e0 <xstrdup@plt>
  xchg   %ax,%ax
L119:
  test   %al,%al
  je     L6
  lea    D11(%rip),%rdi
  call   <puts@plt>
  mov    $0x1,%edi
  call   <exit@plt>
  add    $0x28,%rsp
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  pop    %r15
  ret
  nopl   0x0(%rax)
L27:
  add    $0x28,%rsp
  xor    %eax,%eax
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  pop    %r15
  ret
  nopl   0x0(%rax)
L15:
  mov    %r12,%rdx
  mov    %rbp,%rsi
  lea    D7(%rip),%rdi
  xor    %eax,%eax
  call   <printf@plt>
  mov    $0x1,%edi
  call   <exit@plt>
  jmp    L26
```

tool_calls: name: extract_symbolic_data
arguments: data_tag: D2
type: string
name: extract_symbolic_data
arguments: data_tag: D11
type: string
name: extract_symbolic_data
arguments: data_tag: D7
type: string

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


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

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


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);
  }
}
```