// File: /workspace/github_c_makefile_star2_O2/tditlu[P]shadetabler/src/cwalk/cwalk.c
// Function: cwk_path_get_relative
size_t cwk_path_get_relative(const char *base_directory, const char *path,
  char *buffer, size_t buffer_size)
{
  size_t pos, base_root_length, path_root_length;
  bool absolute, base_available, other_available, has_output;
  const char *base_paths[2], *other_paths[2];
  struct cwk_segment_joined bsj, osj;

  pos = 0;

  // First we compare the roots of those two paths. If the roots are not equal
  // we can't continue, since there is no way to get a relative path from
  // different roots.
  cwk_path_get_root(base_directory, &base_root_length);
  cwk_path_get_root(path, &path_root_length);
  if (!cwk_path_is_string_equal(base_directory, path, base_root_length)) {
    return pos;
  }

  // Verify whether this is an absolute path. We need to know that since we can
  // remove all back-segments if it is.
  absolute = cwk_path_is_root_absolute(base_directory, base_root_length);

  // Initialize our joined segments. This will allow us to use the internal
  // functions to skip until diverge and invisible. We only have one path in
  // them though.
  base_paths[0] = base_directory;
  base_paths[1] = NULL;
  other_paths[0] = path;
  other_paths[1] = NULL;
  cwk_path_get_first_segment_joined(base_paths, &bsj);
  cwk_path_get_first_segment_joined(other_paths, &osj);

  // Okay, now we skip until the segments diverge. We don't have anything to do
  // with the segments which are equal.
  cwk_path_skip_segments_until_diverge(&bsj, &osj, absolute, &base_available,
    &other_available);

  // Assume there is no output until we have got some. We will need this
  // information later on to remove trailing slashes or alternatively output a
  // current-segment.
  has_output = false;

  // So if we still have some segments left in the base path we will now output
  // a back segment for all of them.
  if (base_available) {
    do {
      // Skip any invisible segment. We don't care about those and we don't need
      // to navigate back because of them.
      if (!cwk_path_segment_joined_skip_invisible(&bsj, absolute)) {
        break;
      }

      // Toggle the flag if we have output. We need to remember that, since we
      // want to remove the trailing slash.
      has_output = true;

      // Output the back segment and a separator. No need to worry about the
      // superfluous segment since it will be removed later on.
      pos += cwk_path_output_back(buffer, buffer_size, pos);
      pos += cwk_path_output_separator(buffer, buffer_size, pos);
    } while (cwk_path_get_next_segment_joined(&bsj));
  }

  // And if we have some segments available of the target path we will output
  // all of those.
  if (other_available) {
    do {
      // Again, skip any invisible segments since we don't need to navigate into
      // them.
      if (!cwk_path_segment_joined_skip_invisible(&osj, absolute)) {
        break;
      }

      // Toggle the flag if we have output. We need to remember that, since we
      // want to remove the trailing slash.
      has_output = true;

      // Output the current segment and a separator. No need to worry about the
      // superfluous segment since it will be removed later on.
      pos += cwk_path_output_sized(buffer, buffer_size, pos, osj.segment.begin,
        osj.segment.size);
      pos += cwk_path_output_separator(buffer, buffer_size, pos);
    } while (cwk_path_get_next_segment_joined(&osj));
  }

  // If we have some output by now we will have to remove the trailing slash. We
  // simply do that by moving back one character. The terminate output function
  // will then place the '\0' on this position. Otherwise, if there is no
  // output, we will have to output a "current directory", since the target path
  // points to the base path.
  if (has_output) {
    --pos;
  } else {
    pos += cwk_path_output_current(buffer, buffer_size, pos);
  }

  // Finally, we can terminate the output - which means we place a '\0' at the
  // current position or at the end of the buffer.
  cwk_path_terminate_output(buffer, buffer_size, pos);

  return pos;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xb8, %rsp
movq %rcx, %rbx
movq %rdx, %r13
movq %rsi, %r14
movq %rdi, %r15
leaq 0x18(%rsp), %r12
movq %r12, %rsi
callq 0xce34
leaq 0x10(%rsp), %rsi
movq %r14, %rdi
callq 0xce34
movq (%r12), %r12
movq %r15, %rdi
movq %r14, %rsi
movq %r12, %rdx
callq 0xce57
testb %al, %al
je 0xccbe
movq %r13, (%rsp)
movq %r15, %rdi
movq %r12, %rsi
callq 0xcedf
movl %eax, %ebp
leaq 0xa0(%rsp), %rdi
movq %r15, (%rdi)
andq $0x0, 0x8(%rdi)
leaq 0x90(%rsp), %r12
movq %r14, (%r12)
andq $0x0, 0x8(%r12)
leaq 0x58(%rsp), %r15
movq %r15, %rsi
callq 0xcef2
leaq 0x20(%rsp), %r13
movq %r12, %rdi
movq %r13, %rsi
callq 0xcef2
movzbl %bpl, %ebp
movq %r15, %rdi
movl %ebp, %esi
callq 0xcf39
movl %eax, %r14d
movq %r13, %rdi
movl %ebp, %esi
callq 0xcf39
movl %eax, %r12d
testb %r14b, %r14b
je 0xccae
testb %r12b, %r12b
je 0xccae
movq 0x30(%rsp), %rsi
movq 0x68(%rsp), %rdi
movq 0x78(%rsp), %rdx
callq 0xce57
testb %al, %al
je 0xccc6
movq %r15, %rdi
callq 0xcfb1
movl %eax, %r14d
movq %r13, %rdi
callq 0xcfb1
movl %eax, %r12d
testb %r14b, %r14b
je 0xccae
testb %r12b, %r12b
jne 0xcc52
testb %r14b, %r14b
jne 0xccc9
xorl %r15d, %r15d
xorl %r14d, %r14d
jmp 0xcd4b
xorl %r12d, %r12d
jmp 0xce1f
movb $0x1, %r12b
xorl %r15d, %r15d
leaq 0x58(%rsp), %r13
xorl %r14d, %r14d
movl %ebp, 0xc(%rsp)
movq %r13, %rdi
movl %ebp, %esi
callq 0xcf39
testb %al, %al
je 0xcd4b
movq %r13, %rbp
leaq 0x2(%r15), %r14
movq %rbx, %rax
subq %r15, %rax
movl $0x0, %edx
cmovaeq %rax, %rdx
cmpq %rbx, %r14
pushq $0x2
popq %rax
cmovbq %rax, %rdx
testq %rdx, %rdx
movq (%rsp), %r13
je 0xcd21
addq %r13, %r15
movq %r15, %rdi
leaq 0x4125(%rip), %rsi      # 0x10e41
callq 0x1120
movq %r13, %rdi
movq %rbx, %rsi
movq %r14, %rdx
callq 0xcf6d
movq %rax, %r15
addq %r14, %r15
movq %rbp, %r13
movq %rbp, %rdi
callq 0xcfb1
movb $0x1, %r14b
testb %al, %al
movl 0xc(%rsp), %ebp
jne 0xccd8
testb %r12b, %r12b
je 0xcdc0
leaq 0x20(%rsp), %r12
movq (%rsp), %r13
movq %r12, %rdi
movl %ebp, %esi
callq 0xcf39
testb %al, %al
je 0xcdc0
movq 0x40(%rsp), %rax
leaq (%rax,%r15), %r14
movq %rbx, %rdx
subq %r15, %rdx
movl $0x0, %ecx
cmovbq %rcx, %rdx
cmpq %rbx, %r14
cmovbq %rax, %rdx
testq %rdx, %rdx
je 0xcd9b
movq 0x30(%rsp), %rsi
addq %r13, %r15
movq %r15, %rdi
callq 0x1170
movq %r13, %rdi
movq %rbx, %rsi
movq %r14, %rdx
callq 0xcf6d
movq %rax, %r15
addq %r14, %r15
movq %r12, %rdi
callq 0xcfb1
movb $0x1, %r14b
testb %al, %al
jne 0xcd59
jmp 0xcdc6
testb $0x1, %r14b
je 0xcdd2
decq %r15
movq %r15, %r12
movq (%rsp), %r14
jmp 0xce07
leaq 0x1(%r15), %r12
xorl %eax, %eax
movq %rbx, %rcx
subq %r15, %rcx
cmovaeq %rcx, %rax
cmpq %rbx, %r12
pushq $0x1
popq %rdx
cmovaeq %rax, %rdx
testq %rdx, %rdx
movq (%rsp), %r14
je 0xce07
addq %r14, %r15
leaq 0x432d(%rip), %rsi      # 0x1112c
movq %r15, %rdi
callq 0x1120
testq %rbx, %rbx
je 0xce1f
leaq (%r14,%r12), %rax
cmpq %rbx, %r12
leaq -0x1(%r14,%rbx), %rcx
cmovbq %rax, %rcx
movb $0x0, (%rcx)
movq %r12, %rax
addq $0xb8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq