// File: /workspace/github_c_makefile_star2_O3/tditlu[P]shadetabler/src/cwalk/cwalk.c
// Function: cwk_path_change_extension
size_t cwk_path_change_extension(const char *path, const char *new_extension,
  char *buffer, size_t buffer_size)
{
  struct cwk_segment segment;
  const char *c, *old_extension;
  size_t pos, root_size, trail_size, new_extension_size;

  // First we try to get the last segment. We may only have a root without any
  // segments, in which case we will create one.
  if (!cwk_path_get_last_segment(path, &segment)) {

    // So there is no segment in this path. First we grab the root and output
    // that. We are not going to modify the root in any way. If there is no
    // root, this will end up with a root size 0, and nothing will be written.
    cwk_path_get_root(path, &root_size);
    pos = cwk_path_output_sized(buffer, buffer_size, 0, path, root_size);

    // Add a dot if the submitted value doesn't have any.
    if (*new_extension != '.') {
      pos += cwk_path_output_dot(buffer, buffer_size, pos);
    }

    // And finally terminate the output and return the total size of the path.
    pos += cwk_path_output(buffer, buffer_size, pos, new_extension);
    cwk_path_terminate_output(buffer, buffer_size, pos);
    return pos;
  }

  // Now we seek the old extension in the last segment, which we will replace
  // with the new one. If there is no old extension, it will point to the end of
  // the segment.
  old_extension = segment.end;
  for (c = segment.begin; c < segment.end; ++c) {
    if (*c == '.') {
      old_extension = c;
    }
  }

  pos = cwk_path_output_sized(buffer, buffer_size, 0, segment.path,
    (size_t)(old_extension - segment.path));

  // If the new extension starts with a dot, we will skip that dot. We always
  // output exactly one dot before the extension. If the extension contains
  // multiple dots, we will output those as part of the extension.
  if (*new_extension == '.') {
    ++new_extension;
  }

  // We calculate the size of the new extension, including the dot, in order to
  // output the trail - which is any part of the path coming after the
  // extension. We must output this first, since the buffer may overlap with the
  // submitted path - and it would be overridden by longer extensions.
  new_extension_size = strlen(new_extension) + 1;
  trail_size = cwk_path_output(buffer, buffer_size, pos + new_extension_size,
    segment.end);

  // Finally we output the dot and the new extension. The new extension itself
  // doesn't contain the dot anymore, so we must output that first.
  pos += cwk_path_output_dot(buffer, buffer_size, pos);
  pos += cwk_path_output(buffer, buffer_size, pos, new_extension);

  // Now we terminate the output with a null-terminating character, but before
  // we do that we must add the size of the trail to the position which we
  // output before.
  pos += trail_size;
  cwk_path_terminate_output(buffer, buffer_size, pos);

  // And the position is our output size now.
  return pos;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
movq %rcx, %r14
movq %rdx, %rbp
movq %rsi, %r15
movq %rdi, %r13
leaq 0x20(%rsp), %rsi
callq 0xf30f
testb %al, %al
je 0xf845
movq %rbp, 0x8(%rsp)
movq 0x30(%rsp), %rax
movq 0x38(%rsp), %rbp
movq %rbp, %r12
cmpq %rbp, %rax
jae 0xf74a
movq %rbp, %r12
cmpb $0x2e, (%rax)
cmoveq %rax, %r12
incq %rax
cmpq %rbp, %rax
jne 0xf73b
movq 0x20(%rsp), %rsi
subq %rsi, %r12
cmpq %r14, %r12
movq %r14, %rdx
cmovbq %r12, %rdx
testq %rdx, %rdx
je 0xf76b
movq 0x8(%rsp), %rdi
callq 0x1180
xorl %r13d, %r13d
cmpb $0x2e, (%r15)
sete %r13b
addq %r15, %r13
movq %r13, %rdi
callq 0x10a0
leaq 0x1(%r12), %r15
leaq (%r12,%rax), %rbx
incq %rbx
movq %rbp, %rdi
callq 0x10a0
leaq (%rbx,%rax), %rsi
xorl %edx, %edx
movq %r14, %rcx
subq %rbx, %rcx
cmovaeq %rcx, %rdx
cmpq %r14, %rsi
movq %rax, 0x10(%rsp)
cmovbq %rax, %rdx
testq %rdx, %rdx
je 0xf7c6
addq 0x8(%rsp), %rbx
movq %rbx, %rdi
movq %rbp, %rsi
callq 0x1180
xorl %eax, %eax
movq %r14, %rcx
subq %r12, %rcx
cmovaeq %rcx, %rax
cmpq %r14, %r15
movl $0x1, %edx
cmovaeq %rax, %rdx
testq %rdx, %rdx
movq 0x8(%rsp), %rbp
je 0xf7fa
addq %rbp, %r12
leaq 0x4a2a(%rip), %rsi      # 0x1421c
movq %r12, %rdi
callq 0x1130
movq %r13, %rdi
callq 0x10a0
leaq (%rax,%r15), %r12
xorl %edx, %edx
movq %r14, %rcx
subq %r15, %rcx
cmovaeq %rcx, %rdx
cmpq %r14, %r12
cmovbq %rax, %rdx
testq %rdx, %rdx
je 0xf82c
addq %rbp, %r15
movq %r15, %rdi
movq %r13, %rsi
callq 0x1180
addq 0x10(%rsp), %r12
testq %r14, %r14
je 0xf8ff
cmpq %r14, %r12
setb %bl
jmp 0xf8eb
leaq 0x18(%rsp), %rbx
movq %r13, %rdi
movq %rbx, %rsi
callq 0xeee6
movq (%rbx), %r12
cmpq %r14, %r12
movq %r14, %rdx
cmovbq %r12, %rdx
testq %rdx, %rdx
je 0xf872
movq %rbp, %rdi
movq %r13, %rsi
callq 0x1180
cmpb $0x2e, (%r15)
jne 0xf87d
movq %r12, %r13
jmp 0xf8b1
leaq 0x1(%r12), %r13
xorl %eax, %eax
movq %r14, %rcx
subq %r12, %rcx
cmovaeq %rcx, %rax
cmpq %r14, %r13
movl $0x1, %edx
cmovaeq %rax, %rdx
testq %rdx, %rdx
je 0xf8b1
addq %rbp, %r12
leaq 0x4973(%rip), %rsi      # 0x1421c
movq %r12, %rdi
callq 0x1130
movq %r15, %rdi
callq 0x10a0
leaq (%rax,%r13), %r12
xorl %edx, %edx
movq %r14, %rcx
subq %r13, %rcx
cmovaeq %rcx, %rdx
cmpq %r14, %r12
setb %bl
cmovbq %rax, %rdx
testq %rdx, %rdx
je 0xf8e6
addq %rbp, %r13
movq %r13, %rdi
movq %r15, %rsi
callq 0x1180
testq %r14, %r14
je 0xf8ff
leaq (%r14,%rbp), %rax
decq %rax
addq %r12, %rbp
testb %bl, %bl
cmoveq %rax, %rbp
movb $0x0, (%rbp)
movq %r12, %rax
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq