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

```asm
<base64_decode>:
  endbr64
  push   %r15
  push   %r14
  push   %r13
  mov    %rsi,%r13
  push   %r12
  push   %rbp
  mov    %rdi,%rbp
  push   %rbx
  sub    $0x28,%rsp
  test   %rdi,%rdi
  je     L23
  test   %rsi,%rsi
  je     L23
L69:
  mov    %rbp,%rdi
  call   <strlen@plt>
  mov    %rax,%rbx
  lea    (%rax,%rax,2),%eax
  test   %eax,%eax
  lea    0x3(%rax),%r12d
  cmovns %eax,%r12d
  sar    $0x2,%r12d
  mov    %r12d,0x1c(%rsp)
  test   $0x3,%bl
  jne    L87
  mov    0x0(%r13),%rdi
  movslq %r12d,%rdx
  test   %rdi,%rdi
  je     L7
L13:
  xor    %esi,%esi
  call   <memset@plt>
  movslq %ebx,%rax
  cmpb   $0x3d,-0x2(%rbp,%rax,1)
  jne    L67
  lea    -0x1(%r12),%esi
  mov    %esi,0x1c(%rsp)
L67:
  cmpb   $0x3d,-0x1(%rbp,%rax,1)
  jne    L86
  subl   $0x1,0x1c(%rsp)
L86:
  cmp    $0x3,%ebx
  jle    L81
  lea    -0x4(%rbx),%eax
  mov    %rbp,%r14
  xor    %r12d,%r12d
  xor    %r15d,%r15d
  shr    $0x2,%eax
  add    $0x1,%eax
  lea    (%rax,%rax,2),%rax
  mov    %rax,0x10(%rsp)
  xchg   %ax,%ax
L47:
  movzbl 0x2(%r14),%ebp
  movzbl 0x3(%r14),%ecx
  movzbl (%r14),%edi
  movzbl 0x1(%r14),%ebx
  cmp    $0x3d,%bpl
  cmove  %r15d,%ebp
  cmp    $0x3d,%cl
  cmove  %r15d,%ecx
  xor    %eax,%eax
  add    $0x4,%r14
  mov    %cl,0x1b(%rsp)
  call   <b64toi@plt>
  mov    %ebx,%edi
  mov    %eax,0x8(%rsp)
  xor    %eax,%eax
  call   <b64toi@plt>
  mov    0x8(%rsp),%r8d
  mov    0x0(%r13),%rdi
  sar    $0x4,%eax
  lea    (%rax,%r8,4),%r8d
  xor    %eax,%eax
  mov    %r8b,(%rdi,%r12,1)
  mov    %ebx,%edi
  call   <b64toi@plt>
  mov    %ebp,%edi
  mov    %eax,%ebx
  xor    %eax,%eax
  call   <b64toi@plt>
  shl    $0x4,%ebx
  mov    0x0(%r13),%rdi
  sar    $0x2,%eax
  add    %eax,%ebx
  xor    %eax,%eax
  mov    %bl,0x1(%rdi,%r12,1)
  mov    %ebp,%edi
  call   <b64toi@plt>
  movzbl 0x1b(%rsp),%edi
  mov    %eax,%ebx
  xor    %eax,%eax
  call   <b64toi@plt>
  shl    $0x6,%ebx
  mov    0x0(%r13),%rdx
  add    %eax,%ebx
  mov    %bl,0x2(%rdx,%r12,1)
  add    $0x3,%r12
  cmp    %r12,0x10(%rsp)
  jne    L47
L81:
  mov    0x1c(%rsp),%eax
  add    $0x28,%rsp
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  pop    %r15
  ret
  xchg   %ax,%ax
L87:
  mov    $0x41,%edx
  lea    D34(%rip),%rdi
  mov    $0xfffffcff,%ecx
  xor    %eax,%eax
  lea    D23(%rip),%rsi
  call   <exit_on_error_m@plt>
  mov    0x0(%r13),%rdi
  movslq %r12d,%rdx
  test   %rdi,%rdi
  jne    L13
L7:
  mov    %rdx,%rdi
  mov    %rdx,0x8(%rsp)
  call   <malloc@plt>
  mov    0x8(%rsp),%rdx
  mov    %rax,0x0(%r13)
  mov    %rax,%rdi
  jmp    L13
  nopl   (%rax)
L23:
  mov    $0xfffffcff,%ecx
  mov    $0x39,%edx
  lea    D23(%rip),%rsi
  xor    %eax,%eax
  lea    D34(%rip),%rdi
  call   <exit_on_error_m@plt>
  jmp    L69
```

tool_calls: name: read_data
arguments: data_tag: D34
type: string
name: read_data
arguments: data_tag: D23
type: string

tool: D34: /scratch/repos/new/home/jordi_armengol_estape/c-scraper/outputs/2022-01-22/02-19-57/repos/aozkesek/c_cplusplus/refs/heads/master/liblicense/base64.c

tool: D23: base64_decode

assistant: ```c
int base64_decode(const unsigned char *source, unsigned char **target) {
  if (!source || !target)
    exit_on_error_m("/scratch/repos/new/home/jordi_armengol_estape/c-scraper/outputs/2022-01-22/02-19-57/repos/aozkesek/c_cplusplus/refs/heads/master/liblicense/base64.c", __FUNCTION__, 57, -0x0301);
  int i = 0, j = 0, slen = strlen((const char *)source), tlen = (slen * 3 / 4);
  if (slen % 4)
    exit_on_error_m("/scratch/repos/new/home/jordi_armengol_estape/c-scraper/outputs/2022-01-22/02-19-57/repos/aozkesek/c_cplusplus/refs/heads/master/liblicense/base64.c", __FUNCTION__, 65, -0x0301);
  if (!(*target))
    *target = malloc(tlen);
  memset(*target, 0, tlen);
  if (source[slen - 2] == '=')
    tlen--;
  if (source[slen - 1] == '=')
    tlen--;
  while (i <= slen - 4) {
    unsigned char b0 = source[i], b1 = source[i + 1], b2 = source[i + 2] == '=' ? 0 : source[i + 2], b3 = source[i + 3] == '=' ? 0 : source[i + 3];
    (*target)[j] = (b64toi(b0) << 2) + (b64toi(b1) >> 4);
    (*target)[j + 1] = ((b64toi(b1) & 0xf) << 4) + (b64toi(b2) >> 2);
    (*target)[j + 2] = ((b64toi(b2) & 0x3) << 6) + b64toi(b3);
    i += 4;
    j += 3;
  }
  return tlen;
}
```