119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman//===-- PathV2.cpp - Implement OS Path Concept ------------------*- C++ -*-===//
219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman//
319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman//                     The LLVM Compiler Infrastructure
419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman//
519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// This file is distributed under the University of Illinois Open Source
619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// License. See LICENSE.TXT for details.
719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman//
819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman//===----------------------------------------------------------------------===//
919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman//
1019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman//  This file implements the operating system PathV2 API.
1119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman//
1219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman//===----------------------------------------------------------------------===//
1319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
1419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/Support/PathV2.h"
1519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/Support/FileSystem.h"
1619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "llvm/Support/ErrorHandling.h"
1719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include <cctype>
1819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include <cstdio>
1919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include <cstring>
2019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
2119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumannamespace {
2219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  using llvm::StringRef;
2319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  using llvm::sys::path::is_separator;
2419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
2519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#ifdef LLVM_ON_WIN32
2619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  const StringRef separators = "\\/";
2719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  const char      prefered_separator = '\\';
2819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#else
2919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  const StringRef separators = "/";
3019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  const char      prefered_separator = '/';
3119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#endif
3219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
3319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  const llvm::error_code success;
3419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
3519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  StringRef find_first_component(StringRef path) {
3619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // Look for this first component in the following order.
3719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // * empty (in this case we return an empty string)
3819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // * either C: or {//,\\}net.
3919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // * {/,\}
4019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // * {.,..}
4119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // * {file,directory}name
4219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
4319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if (path.empty())
4419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      return path;
4519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
4619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#ifdef LLVM_ON_WIN32
4719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // C:
4819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if (path.size() >= 2 && std::isalpha(path[0]) && path[1] == ':')
4919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      return path.substr(0, 2);
5019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#endif
5119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
5219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // //net
5319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if ((path.size() > 2) &&
5419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        is_separator(path[0]) &&
5519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        path[0] == path[1] &&
5619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        !is_separator(path[2])) {
5719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      // Find the next directory separator.
5819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      size_t end = path.find_first_of(separators, 2);
5919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      return path.substr(0, end);
6019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    }
6119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
6219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // {/,\}
6319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if (is_separator(path[0]))
6419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      return path.substr(0, 1);
6519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
6619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if (path.startswith(".."))
6719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      return path.substr(0, 2);
6819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
6919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if (path[0] == '.')
7019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      return path.substr(0, 1);
7119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
7219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // * {file,directory}name
7319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    size_t end = path.find_first_of(separators, 2);
7419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    return path.substr(0, end);
7519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  }
7619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
7719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  size_t filename_pos(StringRef str) {
7819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if (str.size() == 2 &&
7919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        is_separator(str[0]) &&
8019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        str[0] == str[1])
8119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      return 0;
8219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
8319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if (str.size() > 0 && is_separator(str[str.size() - 1]))
8419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      return str.size() - 1;
8519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
8619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    size_t pos = str.find_last_of(separators, str.size() - 1);
8719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
8819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#ifdef LLVM_ON_WIN32
8919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if (pos == StringRef::npos)
9019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      pos = str.find_last_of(':', str.size() - 2);
9119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#endif
9219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
9319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if (pos == StringRef::npos ||
9419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        (pos == 1 && is_separator(str[0])))
9519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      return 0;
9619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
9719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    return pos + 1;
9819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  }
9919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
10019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  size_t root_dir_start(StringRef str) {
10119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // case "c:/"
10219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#ifdef LLVM_ON_WIN32
10319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if (str.size() > 2 &&
10419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        str[1] == ':' &&
10519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        is_separator(str[2]))
10619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      return 2;
10719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#endif
10819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
10919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // case "//"
11019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if (str.size() == 2 &&
11119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        is_separator(str[0]) &&
11219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        str[0] == str[1])
11319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      return StringRef::npos;
11419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
11519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // case "//net"
11619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if (str.size() > 3 &&
11719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        is_separator(str[0]) &&
11819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        str[0] == str[1] &&
11919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        !is_separator(str[2])) {
12019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      return str.find_first_of(separators, 2);
12119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    }
12219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
12319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // case "/"
12419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if (str.size() > 0 && is_separator(str[0]))
12519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      return 0;
12619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
12719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    return StringRef::npos;
12819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  }
12919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
13019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  size_t parent_path_end(StringRef path) {
13119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    size_t end_pos = filename_pos(path);
13219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
13319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    bool filename_was_sep = path.size() > 0 && is_separator(path[end_pos]);
13419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
13519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // Skip separators except for root dir.
13619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    size_t root_dir_pos = root_dir_start(path.substr(0, end_pos));
13719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
13819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    while(end_pos > 0 &&
13919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman          (end_pos - 1) != root_dir_pos &&
14019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman          is_separator(path[end_pos - 1]))
14119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      --end_pos;
14219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
14319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if (end_pos == 1 && root_dir_pos == 0 && filename_was_sep)
14419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      return StringRef::npos;
14519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
14619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    return end_pos;
14719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  }
14819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman} // end unnamed namespace
14919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
15019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumannamespace llvm {
15119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumannamespace sys  {
15219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumannamespace path {
15319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
15419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanconst_iterator begin(StringRef path) {
15519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  const_iterator i;
15619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  i.Path      = path;
15719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  i.Component = find_first_component(path);
15819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  i.Position  = 0;
15919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  return i;
16019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
16119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
16219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanconst_iterator end(StringRef path) {
16319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  const_iterator i;
16419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  i.Path      = path;
16519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  i.Position  = path.size();
16619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  return i;
16719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
16819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
16919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanconst_iterator &const_iterator::operator++() {
17019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  assert(Position < Path.size() && "Tried to increment past end!");
17119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
17219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // Increment Position to past the current component
17319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  Position += Component.size();
17419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
17519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // Check for end.
17619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  if (Position == Path.size()) {
17719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    Component = StringRef();
17819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    return *this;
17919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  }
18019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
18119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // Both POSIX and Windows treat paths that begin with exactly two separators
18219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // specially.
18319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  bool was_net = Component.size() > 2 &&
18419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    is_separator(Component[0]) &&
18519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    Component[1] == Component[0] &&
18619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    !is_separator(Component[2]);
18719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
18819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // Handle separators.
18919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  if (is_separator(Path[Position])) {
19019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // Root dir.
19119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if (was_net
19219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#ifdef LLVM_ON_WIN32
19319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        // c:/
19419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        || Component.endswith(":")
19519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#endif
19619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        ) {
19719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      Component = Path.substr(Position, 1);
19819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      return *this;
19919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    }
20019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
20119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // Skip extra separators.
20219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    while (Position != Path.size() &&
20319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman           is_separator(Path[Position])) {
20419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      ++Position;
20519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    }
20619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
20719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // Treat trailing '/' as a '.'.
20819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if (Position == Path.size()) {
20919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      --Position;
21019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      Component = ".";
21119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      return *this;
21219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    }
21319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  }
21419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
21519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // Find next component.
21619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  size_t end_pos = Path.find_first_of(separators, Position);
21719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  Component = Path.slice(Position, end_pos);
21819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
21919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  return *this;
22019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
22119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
22219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanconst_iterator &const_iterator::operator--() {
22319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // If we're at the end and the previous char was a '/', return '.'.
22419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  if (Position == Path.size() &&
22519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      Path.size() > 1 &&
22619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      is_separator(Path[Position - 1])
22719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#ifdef LLVM_ON_WIN32
22819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      && Path[Position - 2] != ':'
22919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#endif
23019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      ) {
23119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    --Position;
23219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    Component = ".";
23319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    return *this;
23419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  }
23519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
23619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // Skip separators unless it's the root directory.
23719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  size_t root_dir_pos = root_dir_start(Path);
23819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  size_t end_pos = Position;
23919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
24019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  while(end_pos > 0 &&
24119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        (end_pos - 1) != root_dir_pos &&
24219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        is_separator(Path[end_pos - 1]))
24319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    --end_pos;
24419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
24519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // Find next separator.
24619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  size_t start_pos = filename_pos(Path.substr(0, end_pos));
24719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  Component = Path.slice(start_pos, end_pos);
24819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  Position = start_pos;
24919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  return *this;
25019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
25119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
25219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanbool const_iterator::operator==(const const_iterator &RHS) const {
25319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  return Path.begin() == RHS.Path.begin() &&
25419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman         Position == RHS.Position;
25519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
25619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
25719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanbool const_iterator::operator!=(const const_iterator &RHS) const {
25819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  return !(*this == RHS);
25919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
26019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
26119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanptrdiff_t const_iterator::operator-(const const_iterator &RHS) const {
26219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  return Position - RHS.Position;
26319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
26419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
26519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanconst StringRef root_path(StringRef path) {
26619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  const_iterator b = begin(path),
26719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                 pos = b,
26819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                 e = end(path);
26919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  if (b != e) {
27019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    bool has_net = b->size() > 2 && is_separator((*b)[0]) && (*b)[1] == (*b)[0];
27119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    bool has_drive =
27219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#ifdef LLVM_ON_WIN32
27319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      b->endswith(":");
27419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#else
27519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      false;
27619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#endif
27719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
27819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if (has_net || has_drive) {
27919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      if ((++pos != e) && is_separator((*pos)[0])) {
28019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        // {C:/,//net/}, so get the first two components.
28119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        return path.substr(0, b->size() + pos->size());
28219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      } else {
28319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        // just {C:,//net}, return the first component.
28419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        return *b;
28519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      }
28619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    }
28719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
28819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // POSIX style root directory.
28919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if (is_separator((*b)[0])) {
29019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      return *b;
29119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    }
29219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  }
29319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
29419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  return StringRef();
29519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
29619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
29719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanconst StringRef root_name(StringRef path) {
29819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  const_iterator b = begin(path),
29919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                 e = end(path);
30019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  if (b != e) {
30119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    bool has_net = b->size() > 2 && is_separator((*b)[0]) && (*b)[1] == (*b)[0];
30219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    bool has_drive =
30319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#ifdef LLVM_ON_WIN32
30419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      b->endswith(":");
30519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#else
30619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      false;
30719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#endif
30819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
30919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if (has_net || has_drive) {
31019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      // just {C:,//net}, return the first component.
31119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      return *b;
31219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    }
31319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  }
31419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
31519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // No path or no name.
31619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  return StringRef();
31719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
31819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
31919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanconst StringRef root_directory(StringRef path) {
32019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  const_iterator b = begin(path),
32119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                 pos = b,
32219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                 e = end(path);
32319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  if (b != e) {
32419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    bool has_net = b->size() > 2 && is_separator((*b)[0]) && (*b)[1] == (*b)[0];
32519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    bool has_drive =
32619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#ifdef LLVM_ON_WIN32
32719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      b->endswith(":");
32819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#else
32919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      false;
33019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#endif
33119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
33219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if ((has_net || has_drive) &&
33319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        // {C:,//net}, skip to the next component.
33419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        (++pos != e) && is_separator((*pos)[0])) {
33519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      return *pos;
33619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    }
33719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
33819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // POSIX style root directory.
33919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if (!has_net && is_separator((*b)[0])) {
34019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      return *b;
34119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    }
34219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  }
34319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
34419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // No path or no root.
34519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  return StringRef();
34619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
34719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
34819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanconst StringRef relative_path(StringRef path) {
34919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  StringRef root = root_path(path);
35019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  return root.substr(root.size());
35119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
35219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
35319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanvoid append(SmallVectorImpl<char> &path, const Twine &a,
35419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                         const Twine &b,
35519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                         const Twine &c,
35619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                         const Twine &d) {
35719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  SmallString<32> a_storage;
35819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  SmallString<32> b_storage;
35919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  SmallString<32> c_storage;
36019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  SmallString<32> d_storage;
36119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
36219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  SmallVector<StringRef, 4> components;
36319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  if (!a.isTriviallyEmpty()) components.push_back(a.toStringRef(a_storage));
36419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  if (!b.isTriviallyEmpty()) components.push_back(b.toStringRef(b_storage));
36519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  if (!c.isTriviallyEmpty()) components.push_back(c.toStringRef(c_storage));
36619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  if (!d.isTriviallyEmpty()) components.push_back(d.toStringRef(d_storage));
36719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
36819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  for (SmallVectorImpl<StringRef>::const_iterator i = components.begin(),
36919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                                  e = components.end();
37019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                                  i != e; ++i) {
37119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    bool path_has_sep = !path.empty() && is_separator(path[path.size() - 1]);
37219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    bool component_has_sep = !i->empty() && is_separator((*i)[0]);
37319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    bool is_root_name = has_root_name(*i);
37419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
37519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if (path_has_sep) {
37619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      // Strip separators from beginning of component.
37719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      size_t loc = i->find_first_not_of(separators);
37819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      StringRef c = i->substr(loc);
37919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
38019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      // Append it.
38119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      path.append(c.begin(), c.end());
38219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      continue;
38319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    }
38419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
38519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if (!component_has_sep && !(path.empty() || is_root_name)) {
38619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      // Add a separator.
38719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      path.push_back(prefered_separator);
38819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    }
38919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
39019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    path.append(i->begin(), i->end());
39119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  }
39219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
39319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
39419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanvoid append(SmallVectorImpl<char> &path,
39519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman            const_iterator begin, const_iterator end) {
39619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  for (; begin != end; ++begin)
39719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    path::append(path, *begin);
39819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
39919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
40019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanconst StringRef parent_path(StringRef path) {
40119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  size_t end_pos = parent_path_end(path);
40219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  if (end_pos == StringRef::npos)
40319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    return StringRef();
40419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  else
40519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    return path.substr(0, end_pos);
40619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
40719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
40819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanvoid remove_filename(SmallVectorImpl<char> &path) {
40919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  size_t end_pos = parent_path_end(StringRef(path.begin(), path.size()));
41019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  if (end_pos != StringRef::npos)
41119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    path.set_size(end_pos);
41219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
41319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
41419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanvoid replace_extension(SmallVectorImpl<char> &path, const Twine &extension) {
41519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  StringRef p(path.begin(), path.size());
41619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  SmallString<32> ext_storage;
41719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  StringRef ext = extension.toStringRef(ext_storage);
41819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
41919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // Erase existing extension.
42019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  size_t pos = p.find_last_of('.');
42119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  if (pos != StringRef::npos && pos >= filename_pos(p))
42219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    path.set_size(pos);
42319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
42419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // Append '.' if needed.
42519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  if (ext.size() > 0 && ext[0] != '.')
42619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    path.push_back('.');
42719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
42819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // Append extension.
42919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  path.append(ext.begin(), ext.end());
43019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
43119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
43219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanvoid native(const Twine &path, SmallVectorImpl<char> &result) {
43319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // Clear result.
43419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  result.clear();
43519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#ifdef LLVM_ON_WIN32
43619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  SmallString<128> path_storage;
43719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  StringRef p = path.toStringRef(path_storage);
43819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  result.reserve(p.size());
43919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  for (StringRef::const_iterator i = p.begin(),
44019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                 e = p.end();
44119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                 i != e;
44219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                                 ++i) {
44319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if (*i == '/')
44419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      result.push_back('\\');
44519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    else
44619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      result.push_back(*i);
44719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  }
44819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#else
44919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  path.toVector(result);
45019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#endif
45119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
45219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
45319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanconst StringRef filename(StringRef path) {
45419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  return *(--end(path));
45519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
45619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
45719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanconst StringRef stem(StringRef path) {
45819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  StringRef fname = filename(path);
45919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  size_t pos = fname.find_last_of('.');
46019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  if (pos == StringRef::npos)
46119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    return fname;
46219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  else
46319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if ((fname.size() == 1 && fname == ".") ||
46419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        (fname.size() == 2 && fname == ".."))
46519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      return fname;
46619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    else
46719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      return fname.substr(0, pos);
46819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
46919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
47019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanconst StringRef extension(StringRef path) {
47119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  StringRef fname = filename(path);
47219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  size_t pos = fname.find_last_of('.');
47319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  if (pos == StringRef::npos)
47419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    return StringRef();
47519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  else
47619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if ((fname.size() == 1 && fname == ".") ||
47719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman        (fname.size() == 2 && fname == ".."))
47819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      return StringRef();
47919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    else
48019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      return fname.substr(pos);
48119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
48219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
48319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanbool is_separator(char value) {
48419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  switch(value) {
48519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#ifdef LLVM_ON_WIN32
48619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    case '\\': // fall through
48719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#endif
48819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    case '/': return true;
48919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    default: return false;
49019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  }
49119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
49219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
49319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanvoid system_temp_directory(bool erasedOnReboot, SmallVectorImpl<char> &result) {
49419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  result.clear();
49519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
49619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // Check whether the temporary directory is specified by an environment
49719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // variable.
49819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  const char *EnvironmentVariable;
49919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#ifdef LLVM_ON_WIN32
50019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  EnvironmentVariable = "TEMP";
50119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#else
50219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  EnvironmentVariable = "TMPDIR";
50319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#endif
50419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  if (char *RequestedDir = getenv(EnvironmentVariable)) {
50519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    result.append(RequestedDir, RequestedDir + strlen(RequestedDir));
50619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    return;
50719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  }
50819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
50919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // Fall back to a system default.
51019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  const char *DefaultResult;
51119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#ifdef LLVM_ON_WIN32
51219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  (void)erasedOnReboot;
51319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  DefaultResult = "C:\\TEMP";
51419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#else
51519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  if (erasedOnReboot)
51619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    DefaultResult = "/tmp";
51719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  else
51819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    DefaultResult = "/var/tmp";
51919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#endif
52019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  result.append(DefaultResult, DefaultResult + strlen(DefaultResult));
52119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
52219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
52319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanbool has_root_name(const Twine &path) {
52419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  SmallString<128> path_storage;
52519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  StringRef p = path.toStringRef(path_storage);
52619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
52719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  return !root_name(p).empty();
52819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
52919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
53019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanbool has_root_directory(const Twine &path) {
53119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  SmallString<128> path_storage;
53219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  StringRef p = path.toStringRef(path_storage);
53319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
53419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  return !root_directory(p).empty();
53519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
53619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
53719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanbool has_root_path(const Twine &path) {
53819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  SmallString<128> path_storage;
53919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  StringRef p = path.toStringRef(path_storage);
54019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
54119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  return !root_path(p).empty();
54219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
54319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
54419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanbool has_relative_path(const Twine &path) {
54519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  SmallString<128> path_storage;
54619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  StringRef p = path.toStringRef(path_storage);
54719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
54819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  return !relative_path(p).empty();
54919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
55019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
55119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanbool has_filename(const Twine &path) {
55219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  SmallString<128> path_storage;
55319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  StringRef p = path.toStringRef(path_storage);
55419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
55519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  return !filename(p).empty();
55619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
55719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
55819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanbool has_parent_path(const Twine &path) {
55919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  SmallString<128> path_storage;
56019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  StringRef p = path.toStringRef(path_storage);
56119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
56219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  return !parent_path(p).empty();
56319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
56419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
56519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanbool has_stem(const Twine &path) {
56619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  SmallString<128> path_storage;
56719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  StringRef p = path.toStringRef(path_storage);
56819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
56919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  return !stem(p).empty();
57019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
57119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
57219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanbool has_extension(const Twine &path) {
57319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  SmallString<128> path_storage;
57419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  StringRef p = path.toStringRef(path_storage);
57519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
57619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  return !extension(p).empty();
57719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
57819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
57919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanbool is_absolute(const Twine &path) {
58019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  SmallString<128> path_storage;
58119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  StringRef p = path.toStringRef(path_storage);
58219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
58319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  bool rootDir = has_root_directory(p),
58419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#ifdef LLVM_ON_WIN32
58519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman       rootName = has_root_name(p);
58619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#else
58719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman       rootName = true;
58819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#endif
58919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
59019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  return rootDir && rootName;
59119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
59219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
59319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanbool is_relative(const Twine &path) {
59419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  return !is_absolute(path);
59519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
59619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
59719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman} // end namespace path
59819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
59919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumannamespace fs {
60019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
60119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanerror_code make_absolute(SmallVectorImpl<char> &path) {
60219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  StringRef p(path.data(), path.size());
60319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
60419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  bool rootName      = path::has_root_name(p),
60519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman       rootDirectory = path::has_root_directory(p);
60619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
60719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // Already absolute.
60819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  if (rootName && rootDirectory)
60919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    return success;
61019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
61119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // All of the following conditions will need the current directory.
61219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  SmallString<128> current_dir;
61319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  if (error_code ec = current_path(current_dir)) return ec;
61419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
61519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  // Relative path. Prepend the current directory.
61619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  if (!rootName && !rootDirectory) {
61719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // Append path to the current directory.
61819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    path::append(current_dir, p);
61919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // Set path to the result.
62019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    path.swap(current_dir);
62119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    return success;
62219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  }
62319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
62419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  if (!rootName && rootDirectory) {
62519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    StringRef cdrn = path::root_name(current_dir);
62619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    SmallString<128> curDirRootName(cdrn.begin(), cdrn.end());
62719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    path::append(curDirRootName, p);
62819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // Set path to the result.
62919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    path.swap(curDirRootName);
63019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    return success;
63119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  }
63219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
63319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  if (rootName && !rootDirectory) {
63419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    StringRef pRootName      = path::root_name(p);
63519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    StringRef bRootDirectory = path::root_directory(current_dir);
63619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    StringRef bRelativePath  = path::relative_path(current_dir);
63719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    StringRef pRelativePath  = path::relative_path(p);
63819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
63919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    SmallString<128> res;
64019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    path::append(res, pRootName, bRootDirectory, bRelativePath, pRelativePath);
64119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    path.swap(res);
64219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    return success;
64319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  }
64419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
64519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  llvm_unreachable("All rootName and rootDirectory combinations should have "
64619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman                   "occurred above!");
64719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
64819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
64919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanerror_code create_directories(const Twine &path, bool &existed) {
65019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  SmallString<128> path_storage;
65119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  StringRef p = path.toStringRef(path_storage);
65219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
65319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  StringRef parent = path::parent_path(p);
65419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  bool parent_exists;
65519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
65619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  if (error_code ec = fs::exists(parent, parent_exists)) return ec;
65719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
65819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  if (!parent_exists)
65919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if (error_code ec = create_directories(parent, existed)) return ec;
66019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
66119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  return create_directory(p, existed);
66219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
66319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
66419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanbool exists(file_status status) {
66519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  return status_known(status) && status.type() != file_type::file_not_found;
66619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
66719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
66819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanbool status_known(file_status s) {
66919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  return s.type() != file_type::status_error;
67019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
67119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
67219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanbool is_directory(file_status status) {
67319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  return status.type() == file_type::directory_file;
67419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
67519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
67619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanerror_code is_directory(const Twine &path, bool &result) {
67719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  file_status st;
67819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  if (error_code ec = status(path, st))
67919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    return ec;
68019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  result = is_directory(st);
68119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  return success;
68219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
68319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
68419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanbool is_regular_file(file_status status) {
68519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  return status.type() == file_type::regular_file;
68619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
68719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
68819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanerror_code is_regular_file(const Twine &path, bool &result) {
68919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  file_status st;
69019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  if (error_code ec = status(path, st))
69119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    return ec;
69219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  result = is_regular_file(st);
69319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  return success;
69419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
69519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
69619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanbool is_symlink(file_status status) {
69719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  return status.type() == file_type::symlink_file;
69819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
69919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
70019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanerror_code is_symlink(const Twine &path, bool &result) {
70119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  file_status st;
70219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  if (error_code ec = status(path, st))
70319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    return ec;
70419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  result = is_symlink(st);
70519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  return success;
70619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
70719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
70819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanbool is_other(file_status status) {
70919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  return exists(status) &&
71019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman         !is_regular_file(status) &&
71119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman         !is_directory(status) &&
71219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman         !is_symlink(status);
71319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
71419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
71519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanvoid directory_entry::replace_filename(const Twine &filename, file_status st) {
71619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  SmallString<128> path(Path.begin(), Path.end());
71719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  path::remove_filename(path);
71819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  path::append(path, filename);
71919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  Path = path.str();
72019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  Status = st;
72119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
72219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
72319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanerror_code has_magic(const Twine &path, const Twine &magic, bool &result) {
72419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  SmallString<32>  MagicStorage;
72519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  StringRef Magic = magic.toStringRef(MagicStorage);
72619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  SmallString<32> Buffer;
72719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
72819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  if (error_code ec = get_magic(path, Magic.size(), Buffer)) {
72919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if (ec == errc::value_too_large) {
73019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      // Magic.size() > file_size(Path).
73119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      result = false;
73219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      return success;
73319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    }
73419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    return ec;
73519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  }
73619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
73719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  result = Magic == Buffer;
73819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  return success;
73919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
74019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
74119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanerror_code identify_magic(const Twine &path, LLVMFileType &result) {
74219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  SmallString<32> Magic;
74319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  error_code ec = get_magic(path, Magic.capacity(), Magic);
74419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  if (ec && ec != errc::value_too_large)
74519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    return ec;
74619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
74719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  result = IdentifyFileType(Magic.data(), Magic.size());
74819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  return success;
74919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
75019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
75119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumannamespace {
75219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanerror_code remove_all_r(StringRef path, file_type ft, uint32_t &count) {
75319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  if (ft == file_type::directory_file) {
75419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    // This code would be a lot better with exceptions ;/.
75519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    error_code ec;
75619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    for (directory_iterator i(path, ec), e; i != e; i.increment(ec)) {
75719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      if (ec) return ec;
75819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      file_status st;
75919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      if (error_code ec = i->status(st)) return ec;
76019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman      if (error_code ec = remove_all_r(i->path(), st.type(), count)) return ec;
76119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    }
76219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    bool obviously_this_exists;
76319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if (error_code ec = remove(path, obviously_this_exists)) return ec;
76419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    assert(obviously_this_exists);
76519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    ++count; // Include the directory itself in the items removed.
76619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  } else {
76719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    bool obviously_this_exists;
76819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    if (error_code ec = remove(path, obviously_this_exists)) return ec;
76919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    assert(obviously_this_exists);
77019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    ++count;
77119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  }
77219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
77319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  return success;
77419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
77519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman} // end unnamed namespace
77619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
77719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanerror_code remove_all(const Twine &path, uint32_t &num_removed) {
77819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  SmallString<128> path_storage;
77919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  StringRef p = path.toStringRef(path_storage);
78019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
78119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  file_status fs;
78219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  if (error_code ec = status(path, fs))
78319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman    return ec;
78419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  num_removed = 0;
78519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  return remove_all_r(p, fs.type(), num_removed);
78619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
78719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
78819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Baumanerror_code directory_entry::status(file_status &result) const {
78919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman  return fs::status(Path, result);
79019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman}
79119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
79219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman} // end namespace fs
79319bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman} // end namespace sys
79419bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman} // end namespace llvm
79519bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman
79619bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman// Include the truly platform-specific parts.
79719bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#if defined(LLVM_ON_UNIX)
79819bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "Unix/PathV2.inc"
79919bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#endif
80019bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#if defined(LLVM_ON_WIN32)
80119bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#include "Windows/PathV2.inc"
80219bac1e08be200c31efd26f0f5fd144c9b3eefd3John Bauman#endif
803