user: 请从给定的汇编指令推导出C源代码:

```asm
<parseTime>:
  endbr64
  push   %r15
  push   %r14
  push   %r13
  push   %r12
  push   %rbp
  push   %rbx
  sub    $0x28,%rsp
  mov    %rdi,%r12
  mov    %rsi,%r14
  mov    %fs:0x28,%rax
  mov    %rax,0x18(%rsp)
  xor    %eax,%eax
  call   <strlen@plt>
  mov    %rax,%rbp
  mov    %rax,%r13
  lea    -0x8(%rax),%rax
  cmp    $0x7,%rax
  ja     L190
  cmp    $0x9,%rbp
  je     L190
  mov    $0x0,%eax
  cmp    $0xe,%rbp
  je     L48
  mov    $0x0,%ebx
  mov    %rbp,%r15
  and    $0x1,%r15d
  jmp    L65
L261:
  movsbl (%r12,%rbx,1),%edi
  call   <isdigit@plt>
  test   %eax,%eax
  je     L48
L186:
  add    $0x1,%rbx
  cmp    %rbx,%r13
  jbe    L242
L65:
  test   %r15,%r15
  je     L261
  lea    -0x3(%r13),%rax
  cmp    %rbx,%rax
  jne    L261
  cmpb   $0x2e,(%r12,%rbx,1)
  je     L186
  mov    $0x0,%eax
  jmp    L48
L242:
  movb   $0x0,0xc(%rsp)
  test   %r15,%r15
  je     L175
  lea    -0x3(%rbp),%r13
  mov    $0x0,%eax
  cmpb   $0x2e,-0x3(%r12,%rbp,1)
  jne    L48
  movsbl -0x2(%r12,%rbp,1),%edx
  lea    0x10(%rdx,%rdx,4),%edx
  movzbl -0x1(%r12,%rbp,1),%eax
  lea    -0x30(%rax,%rdx,2),%edx
  mov    %dl,0xc(%rsp)
  mov    $0x0,%eax
  cmp    $0x3c,%dl
  jg     L48
L175:
  movsbl -0x2(%r12,%r13,1),%edx
  lea    0x10(%rdx,%rdx,4),%edx
  movzbl -0x1(%r12,%r13,1),%eax
  lea    -0x30(%rax,%rdx,2),%edx
  mov    %dl,0xd(%rsp)
  mov    $0x0,%eax
  cmp    $0x3b,%dl
  jg     L48
  movsbl -0x4(%r12,%r13,1),%edx
  lea    0x10(%rdx,%rdx,4),%edx
  movzbl -0x3(%r12,%r13,1),%eax
  lea    -0x30(%rax,%rdx,2),%edx
  mov    %dl,0xe(%rsp)
  mov    $0x0,%eax
  cmp    $0x17,%dl
  jg     L48
  movsbl -0x6(%r12,%r13,1),%eax
  lea    0x10(%rax,%rax,4),%eax
  movzbl -0x5(%r12,%r13,1),%edx
  lea    -0x30(%rdx,%rax,2),%eax
  mov    %al,0xf(%rsp)
  test   %al,%al
  je     L204
  cmp    $0x1f,%al
  jg     L204
  movsbl -0x8(%r12,%r13,1),%edx
  lea    0x10(%rdx,%rdx,4),%edx
  movzbl -0x7(%r12,%r13,1),%eax
  lea    -0x31(%rax,%rdx,2),%edx
  mov    %dl,0x10(%rsp)
  mov    $0x0,%eax
  cmp    $0xb,%dl
  ja     L48
  cmp    $0x9,%r13
  jbe    L233
  movsbl -0xa(%r12,%r13,1),%eax
  lea    -0xf0(%rax,%rax,4),%edx
  movsbl -0x9(%r12,%r13,1),%eax
  lea    (%rax,%rdx,2),%eax
  lea    -0x30(%rax),%edx
  cmp    $0xc,%r13
  je     L57
  lea    0x73c(%rax),%ecx
  add    $0x7a0,%eax
  cmp    $0x45,%edx
  cmovge %ecx,%eax
L225:
  sub    $0x76c,%eax
  mov    %eax,0x14(%rsp)
  lea    0xc(%rsp),%rdi
  call   <mktime@plt>
  mov    %eax,0x8(%r14)
  movq   $0x0,(%r14)
  mov    $0x1,%eax
  jmp    L48
L57:
  movsbl (%r12),%eax
  sub    $0x30,%eax
  imul   $0x3e8,%eax,%eax
  movsbl 0x1(%r12),%ecx
  sub    $0x30,%ecx
  imul   $0x64,%ecx,%ecx
  add    %ecx,%eax
  add    %edx,%eax
  jmp    L225
L233:
  mov    $0x0,%edi
  call   <time@plt>
  mov    %eax,0x8(%rsp)
  lea    0x8(%rsp),%rdi
  call   <localtime@plt>
  mov    %rax,%rbx
  test   %rax,%rax
  je     L208
L139:
  mov    0x8(%rbx),%eax
  jmp    L225
L208:
  lea    D8(%rip),%rsi
  mov    $0x1,%edi
  call   <err@plt>
  jmp    L139
L190:
  mov    $0x0,%eax
L48:
  mov    0x18(%rsp),%rdx
  sub    %fs:0x28,%rdx
  jne    L140
  add    $0x28,%rsp
  pop    %rbx
  pop    %rbp
  pop    %r12
  pop    %r13
  pop    %r14
  pop    %r15
  ret
L204:
  mov    $0x0,%eax
  jmp    L48
L140:
  call   <__stack_chk_fail@plt>
```

tool_calls: name: extract_symbolic_data
arguments: label: D8
datatype: string

tool: D8: localtime

assistant: ```c
bool parseTime(const char *str, struct timespec *ts) {
  size_t length = strlen(str);
  if (length < 8 || length == 9 || length == 14 || length > 15)
    return false;
  for (size_t i = 0; i < length; i++) {
    if (length % 2 && i == length - 3) {
      if (str[i] != '.')
        return false;
      continue;
    }
    if (!isdigit(str[i]))
      return false;
  }
  struct tm tm;
  tm.tm_sec = 0;
  if (length % 2) {
    if (str[length - 3] != '.')
      return false;
    tm.tm_sec = (str[length - 2] - '0') * 10 + str[length - 1] - '0';
    if (tm.tm_sec > 60)
      return false;
    length -= 3;
  }
  tm.tm_min = (str[length - 2] - '0') * 10 + str[length - 1] - '0';
  if (tm.tm_min > 59)
    return false;
  tm.tm_hour = (str[length - 4] - '0') * 10 + str[length - 3] - '0';
  if (tm.tm_hour > 23)
    return false;
  tm.tm_mday = (str[length - 6] - '0') * 10 + str[length - 5] - '0';
  if (tm.tm_mday == 0 || tm.tm_mday > 31)
    return false;
  tm.tm_mon = (str[length - 8] - '0') * 10 + str[length - 7] - '0' - 1;
  if (tm.tm_mon < 0 || tm.tm_mon >= 12)
    return false;
  int year;
  if (length >= 10) {
    year = (str[length - 10] - '0') * 10 + str[length - 9] - '0';
    if (length == 12) {
      year += (str[0] - '0') * 1000 + (str[1] - '0') * 100;
    } else if (year >= 69) {
      year += 1900;
    } else {
      year += 2000;
    }
  } else {
    time_t t = time(NULL);
    struct tm *now = localtime(&t);
    if (!now)
      err(1, "localtime");
    year = now->tm_year;
  }
  tm.tm_year = year - 1900;
  ts->tv_sec = mktime(&tm);
  ts->tv_nsec = 0;
  return true;
}
```