// File: /workspace/github_c_makefile_star2_O3/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, 0x8(%rsp)
movq %rsi, %r15
movq %rdi, %r12
leaq 0x18(%rsp), %r14
movq %r14, %rsi
callq 0xeee6
leaq 0x10(%rsp), %rsi
movq %r15, %rdi
callq 0xeee6
movq (%r14), %r14
movq %r12, %rdi
movq %r15, %rsi
movq %r14, %rdx
callq 0xef2b
testb %al, %al
je 0xec37
testq %r14, %r14
je 0xec3f
movl 0xa515(%rip), %eax      # 0x19120
leaq 0xa02e(%rip), %rcx      # 0x18c40
movq (%rcx,%rax,8), %rax
movb (%rax), %dl
testb %dl, %dl
je 0xec3f
movb -0x1(%r12,%r14), %cl
incq %rax
cmpb %cl, %dl
sete %bpl
je 0xec41
movb (%rax), %dl
incq %rax
testb %dl, %dl
jne 0xec24
jmp 0xec41
xorl %r12d, %r12d
jmp 0xeed1
xorl %ebp, %ebp
leaq 0xa0(%rsp), %rdi
movq %r12, (%rdi)
xorl %eax, %eax
movq %rax, 0x8(%rdi)
leaq 0x90(%rsp), %r14
movq %r15, (%r14)
movq %rax, 0x8(%r14)
leaq 0x58(%rsp), %r15
movq %r15, %rsi
callq 0xefc4
leaq 0x20(%rsp), %r13
movq %r14, %rdi
movq %r13, %rsi
callq 0xefc4
movzbl %bpl, %ebp
movq %r15, %rdi
movl %ebp, %esi
callq 0xf030
movl %eax, %r14d
movq %r13, %rdi
movl %ebp, %esi
callq 0xf030
movl %eax, %r12d
testb %r14b, %r14b
je 0xecde
testb %r12b, %r12b
je 0xecde
movq 0x30(%rsp), %rsi
movq 0x68(%rsp), %rdi
movq 0x78(%rsp), %rdx
callq 0xef2b
testb %al, %al
je 0xece8
movq %r15, %rdi
callq 0xf064
movl %eax, %r14d
movq %r13, %rdi
callq 0xf064
movl %eax, %r12d
testb %r14b, %r14b
je 0xecde
testb %r12b, %r12b
jne 0xec82
testb %r14b, %r14b
jne 0xeceb
jmp 0xedb1
movb $0x1, %r12b
leaq 0x58(%rsp), %rdi
movl %ebp, %esi
callq 0xf030
testb %al, %al
je 0xedb1
leaq 0x58(%rsp), %r13
movl $0x2, %r14d
leaq -0x2(%r14), %rax
movq %rbx, %rdx
subq %rax, %rdx
movl $0x0, %eax
cmovbq %rax, %rdx
cmpq %rbx, %r14
movl $0x2, %eax
cmovbq %rax, %rdx
testq %rdx, %rdx
je 0xed47
movq 0x8(%rsp), %rax
leaq (%rax,%r14), %rdi
addq $-0x2, %rdi
leaq 0x51ef(%rip), %rsi      # 0x13f31
callq 0x1130
leaq 0x1(%r14), %r15
movq %rbx, %rax
subq %r14, %rax
movl $0x0, %edx
cmovaeq %rax, %rdx
cmpq %rbx, %r15
movl $0x1, %eax
cmovbq %rax, %rdx
testq %rdx, %rdx
je 0xed8a
movl 0xa3af(%rip), %eax      # 0x19120
leaq 0x9ec8(%rip), %rcx      # 0x18c40
movq (%rcx,%rax,8), %rsi
movq 0x8(%rsp), %rax
leaq (%rax,%r14), %rdi
callq 0x1180
movq %r13, %rdi
callq 0xf064
testb %al, %al
je 0xedac
movq %r13, %rdi
movl %ebp, %esi
callq 0xf030
addq $0x3, %r14
testb %al, %al
jne 0xed0a
movb $0x1, %r14b
jmp 0xedb7
xorl %r15d, %r15d
xorl %r14d, %r14d
testb %r12b, %r12b
je 0xee72
leaq 0x20(%rsp), %rdi
movl %ebp, %esi
callq 0xf030
testb %al, %al
je 0xee72
movl $0x1, %r13d
leaq 0x20(%rsp), %r12
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 0xee15
movq 0x30(%rsp), %rsi
addq 0x8(%rsp), %r15
movq %r15, %rdi
callq 0x1180
leaq 0x1(%r14), %r15
movq %rbx, %rax
subq %r14, %rax
movl $0x0, %edx
cmovaeq %rax, %rdx
cmpq %rbx, %r15
cmovbq %r13, %rdx
testq %rdx, %rdx
je 0xee52
movl 0xa2e6(%rip), %eax      # 0x19120
leaq 0x9dff(%rip), %rcx      # 0x18c40
movq (%rcx,%rax,8), %rsi
addq 0x8(%rsp), %r14
movq %r14, %rdi
callq 0x1180
movq %r12, %rdi
callq 0xf064
testb %al, %al
je 0xee77
movq %r12, %rdi
movl %ebp, %esi
callq 0xf030
testb %al, %al
jne 0xeddf
jmp 0xee77
testb %r14b, %r14b
je 0xee7f
decq %r15
movq %r15, %r12
jmp 0xeeb4
leaq 0x1(%r15), %r12
xorl %eax, %eax
movq %rbx, %rcx
subq %r15, %rcx
cmovaeq %rcx, %rax
cmpq %rbx, %r12
movl $0x1, %edx
cmovaeq %rax, %rdx
testq %rdx, %rdx
je 0xeeb4
addq 0x8(%rsp), %r15
leaq 0x5370(%rip), %rsi      # 0x1421c
movq %r15, %rdi
callq 0x1130
testq %rbx, %rbx
je 0xeed1
movq 0x8(%rsp), %rcx
leaq (%rcx,%r12), %rax
cmpq %rbx, %r12
leaq -0x1(%rcx,%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