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    L81
  test   %al,%al
  jne    L8
  test   %r15d,%r15d
  jne    L81
L107:
  test   %ebx,%ebx
  je     L60
L87:
  mov    0x10(%rsp),%r13
  mov    $0x0,%r15d
  jg     L90
  jmp    L162
  nopl   0x0(%rax,%rax,1)
L42:
  add    $0x1,%r15d
  add    $0x8,%r13
  cmp    %r15d,%ebx
  je     L19
L90:
  mov    0x0(%r13),%rsi
  mov    %r14,%rdi
  call   <strcasecmp@plt>
  test   %rax,%rax
  jne    L42
L162:
  mov    0x18(%rsp),%rdx
  mov    0x8(%rsp),%rbx
  test   %rdx,%rdx
  setne  %al
  test   %rbx,%rbx
  je     L109
  test   %al,%al
  je     L22
  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)
L81:
  test   %al,%al
  je     L107
  test   %r13,%r13
  je     L100
  mov    %r13,%r14
  test   %ebx,%ebx
  jne    L87
  jmp    L60
  xchg   %ax,%ax
L8:
  mov    %r12,%rdx
  mov    %rbp,%rsi
  lea    D25(%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)
L22:
  cmpq   $0x0,0x8(%rsp)
  je     L109
L60:
  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
L109:
  test   %al,%al
  je     L60
  lea    D6(%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)
L100:
  add    $0x28,%rsp
  xor    %eax,%eax
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  pop    %r15
  ret
  nopl   0x0(%rax)
L19:
  mov    %r12,%rdx
  mov    %rbp,%rsi
  lea    D19(%rip),%rdi
  xor    %eax,%eax
  call   <printf@plt>
  mov    $0x1,%edi
  call   <exit@plt>
  jmp    L162
```

tool_calls: name: retrieve_data
arguments: tag: D25
type_infered: string
name: retrieve_data
arguments: tag: D6
type_infered: string
name: retrieve_data
arguments: tag: D19
type_infered: string

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


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

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