user: What is the c source code of the assembly code below:

```asm
<wcsunits>:
  endbr64
  push   %r15
  mov    %rsi,%r15
  push   %r14
  push   %r13
  mov    %rcx,%r13
  push   %r12
  push   %rbp
  mov    %rdx,%rbp
  push   %rbx
  sub    $0x158,%rsp
  mov    %r8,0x8(%rsp)
  lea    0x30(%rsp),%r14
  lea    0x20(%rsp),%rdx
  lea    0x18(%rsp),%rsi
  mov    %r14,%rcx
  mov    %fs:0x28,%rax
  mov    %rax,0x148(%rsp)
  xor    %eax,%eax
  call   <wcsulex@plt>
  mov    %eax,%r12d
  test   %eax,%eax
  je     L77
L5:
  mov    0x148(%rsp),%rax
  sub    %fs:0x28,%rax
  jne    L149
  add    $0x158,%rsp
  mov    %r12d,%eax
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  pop    %r15
  ret
L77:
  lea    0xc0(%rsp),%rbx
  lea    0x28(%rsp),%rdx
  mov    %r15,%rdi
  lea    0x1c(%rsp),%rsi
  mov    %rbx,%rcx
  call   <wcsulex@plt>
  mov    %eax,%r12d
  test   %eax,%eax
  jne    L5
  xor    %eax,%eax
  cs nopw 0x0(%rax,%rax,1)
L11:
  movsd  (%r14,%rax,1),%xmm0
  ucomisd (%rbx,%rax,1),%xmm0
  jp     L4
  jne    L4
  add    $0x8,%rax
  cmp    $0x88,%rax
  jne    L11
  mov    0x8(%rsp),%rax
  movsd  D5(%rip),%xmm0
  movq   $0x0,0x0(%rbp)
  movq   $0x0,0x0(%r13)
  movsd  %xmm0,(%rax)
  mov    0x18(%rsp),%eax
  cmp    $0x2,%eax
  je     L163
  jg     L172
  test   %eax,%eax
  je     L186
  cmp    $0x1,%eax
  jne    L120
  mov    0x1c(%rsp),%eax
  cmp    $0x1,%eax
  je     L131
  cmp    $0x2,%eax
  jne    L151
  mov    D29(%rip),%rax
L252:
  mov    %rax,0x0(%rbp)
  movsd  0x20(%rsp),%xmm0
  divsd  0x28(%rsp),%xmm0
  call   <log@plt>
  movsd  %xmm0,0x0(%r13)
  jmp    L5
  nopl   (%rax)
L172:
  cmp    $0x3,%eax
  jne    L120
  cmpl   $0x3,0x1c(%rsp)
  jne    L151
  mov    0x8(%rsp),%rax
  movsd  %xmm0,0x0(%rbp)
  movsd  0x20(%rsp),%xmm0
  divsd  0x28(%rsp),%xmm0
  movsd  %xmm0,(%rax)
  jmp    L5
  nopl   0x0(%rax,%rax,1)
L4:
  mov    $0xa,%r12d
  jmp    L5
  nopl   0x0(%rax,%rax,1)
L120:
  mov    $0x9,%r12d
  jmp    L5
  nopl   0x0(%rax,%rax,1)
L151:
  mov    $0xb,%r12d
  jmp    L5
L131:
  movsd  %xmm0,0x0(%rbp)
  movsd  0x20(%rsp),%xmm0
  divsd  0x28(%rsp),%xmm0
  call   <log10@plt>
  movsd  %xmm0,0x0(%r13)
  jmp    L5
  nopl   0x0(%rax)
L163:
  mov    0x1c(%rsp),%eax
  cmp    $0x1,%eax
  je     L100
  cmp    $0x2,%eax
  jne    L151
  movsd  %xmm0,0x0(%rbp)
  movsd  0x20(%rsp),%xmm0
  divsd  0x28(%rsp),%xmm0
  call   <log@plt>
  movsd  %xmm0,0x0(%r13)
  jmp    L5
  nop
L186:
  mov    0x1c(%rsp),%r12d
  test   %r12d,%r12d
  jne    L151
  movsd  0x20(%rsp),%xmm0
  divsd  0x28(%rsp),%xmm0
  movsd  %xmm0,0x0(%rbp)
  jmp    L5
L100:
  mov    D17(%rip),%rax
  jmp    L252
L149:
  call   <__stack_chk_fail@plt>
```

tool_calls: name: unpack_data
arguments: tag: D5
type_guessed: f64
name: unpack_data
arguments: tag: D29
type_guessed: byte[8]
name: unpack_data
arguments: tag: D17
type_guessed: byte[8]

tool: D5: 1

tool: {"D29": [0x16,0x55,0xb5,0xbb,0xb1,0x6b,0x02,0x40]}

tool: {"D17": [0x0d,0xe5,0x26,0x15,0x7b,0xcb,0xdb,0x3f]}

assistant: ```c
int wcsunits(const char have[], const char want[], double *scale, double *offset, double *power) {
  int func1, func2, i, status;
  double scale1, scale2, units1[17], units2[17];
  if ((status = wcsulex(have, &func1, &scale1, units1))) {
    return status;
  }
  if ((status = wcsulex(want, &func2, &scale2, units2))) {
    return status;
  }
  for (i = 0; i < 17; i++) {
    if (units1[i] != units2[i]) {
      return 10;
    }
  }
  *scale = 0.0;
  *offset = 0.0;
  *power = 1.0;
  switch (func1) {
  case 0:
    if (func2) {
      return 11;
    }
    *scale = scale1 / scale2;
    break;
  case 1:
    if (func2 == 1) {
      *scale = 1.0;
      *offset = log10(scale1 / scale2);
    } else if (func2 == 2) {
      *scale = log(10.0);
      *offset = log(scale1 / scale2);
    } else {
      return 11;
    }
    break;
  case 2:
    if (func2 == 1) {
      *scale = 1.0 / log(10.0);
      *offset = log(scale1 / scale2);
    } else if (func2 == 2) {
      *scale = 1.0;
      *offset = log(scale1 / scale2);
    } else {
      return 11;
    }
    break;
  case 3:
    if (func2 != 3) {
      return 11;
    }
    *scale = 1.0;
    *power = scale1 / scale2;
    break;
  default:
    return 9;
  }
  return 0;
}
```