Path.cpp revision 40db5d4539144aa086b60685a4dae324972fb23f
1b89a2237ea79e0576fdb426b124f1940f53da159Reid Spencer//===-- Path.cpp - Implement OS Path Concept --------------------*- C++ -*-===//
2f976c856fcc5055f3fc7d9f070d72c2d027c1d9dMisha Brukman//
3b89a2237ea79e0576fdb426b124f1940f53da159Reid Spencer//                     The LLVM Compiler Infrastructure
4b89a2237ea79e0576fdb426b124f1940f53da159Reid Spencer//
54ee451de366474b9c228b4e5fa573795a715216dChris Lattner// This file is distributed under the University of Illinois Open Source
64ee451de366474b9c228b4e5fa573795a715216dChris Lattner// License. See LICENSE.TXT for details.
7f976c856fcc5055f3fc7d9f070d72c2d027c1d9dMisha Brukman//
8b89a2237ea79e0576fdb426b124f1940f53da159Reid Spencer//===----------------------------------------------------------------------===//
9b89a2237ea79e0576fdb426b124f1940f53da159Reid Spencer//
10b89a2237ea79e0576fdb426b124f1940f53da159Reid Spencer//  This header file implements the operating system Path concept.
11b89a2237ea79e0576fdb426b124f1940f53da159Reid Spencer//
12b89a2237ea79e0576fdb426b124f1940f53da159Reid Spencer//===----------------------------------------------------------------------===//
138e66595512b065b69d595bae665b6ad665eca6d0Reid Spencer
14b89a2237ea79e0576fdb426b124f1940f53da159Reid Spencer#include "llvm/System/Path.h"
1579fc9249574cee0ec69d920e5a16497ba799020aReid Spencer#include "llvm/Config/config.h"
1698bc8ed49be09c282e2f0f679fcce382f62390dcAlkis Evlogimenos#include <cassert>
17f52e32aab0422407cc8def93348667c255bb5d80Duncan Sands#include <cstring>
18c67dc457ceb543f00d2d67e857c1d6f25371378aChris Lattner#include <ostream>
19c67dc457ceb543f00d2d67e857c1d6f25371378aChris Lattnerusing namespace llvm;
208e66595512b065b69d595bae665b6ad665eca6d0Reid Spencerusing namespace sys;
21b89a2237ea79e0576fdb426b124f1940f53da159Reid Spencer
22b89a2237ea79e0576fdb426b124f1940f53da159Reid Spencer//===----------------------------------------------------------------------===//
23b89a2237ea79e0576fdb426b124f1940f53da159Reid Spencer//=== WARNING: Implementation here must contain only TRULY operating system
24f976c856fcc5055f3fc7d9f070d72c2d027c1d9dMisha Brukman//===          independent code.
25b89a2237ea79e0576fdb426b124f1940f53da159Reid Spencer//===----------------------------------------------------------------------===//
26b89a2237ea79e0576fdb426b124f1940f53da159Reid Spencer
2740db5d4539144aa086b60685a4dae324972fb23fBill Wendlingbool Path::operator==(const Path &that) const {
2840db5d4539144aa086b60685a4dae324972fb23fBill Wendling  return path == that.path;
2940db5d4539144aa086b60685a4dae324972fb23fBill Wendling}
3040db5d4539144aa086b60685a4dae324972fb23fBill Wendling
3140db5d4539144aa086b60685a4dae324972fb23fBill Wendlingbool Path::operator!=(const Path &that) const {
3240db5d4539144aa086b60685a4dae324972fb23fBill Wendling  return path != that.path;
3340db5d4539144aa086b60685a4dae324972fb23fBill Wendling}
3440db5d4539144aa086b60685a4dae324972fb23fBill Wendling
3540db5d4539144aa086b60685a4dae324972fb23fBill Wendlingbool Path::operator<(const Path& that) const {
3640db5d4539144aa086b60685a4dae324972fb23fBill Wendling  return path < that.path;
3740db5d4539144aa086b60685a4dae324972fb23fBill Wendling}
3840db5d4539144aa086b60685a4dae324972fb23fBill Wendling
39c67dc457ceb543f00d2d67e857c1d6f25371378aChris Lattnerstd::ostream& llvm::operator<<(std::ostream &strm, const sys::Path &aPath) {
40c67dc457ceb543f00d2d67e857c1d6f25371378aChris Lattner  strm << aPath.toString();
41c67dc457ceb543f00d2d67e857c1d6f25371378aChris Lattner  return strm;
42c67dc457ceb543f00d2d67e857c1d6f25371378aChris Lattner}
43c67dc457ceb543f00d2d67e857c1d6f25371378aChris Lattner
44c29befb554c025da801737bc86a8215d1dc6038cReid SpencerPath
45c29befb554c025da801737bc86a8215d1dc6038cReid SpencerPath::GetLLVMConfigDir() {
46c29befb554c025da801737bc86a8215d1dc6038cReid Spencer  Path result;
47ab68df02bc29045b9f02783518fbc7d0f23f56b7Jeff Cohen#ifdef LLVM_ETCDIR
48dd04df0ec33a903ee7fc747701bafde622f77d8bReid Spencer  if (result.set(LLVM_ETCDIR))
49c29befb554c025da801737bc86a8215d1dc6038cReid Spencer    return result;
50ab68df02bc29045b9f02783518fbc7d0f23f56b7Jeff Cohen#endif
51c29befb554c025da801737bc86a8215d1dc6038cReid Spencer  return GetLLVMDefaultConfigDir();
52c29befb554c025da801737bc86a8215d1dc6038cReid Spencer}
53c29befb554c025da801737bc86a8215d1dc6038cReid Spencer
54f976c856fcc5055f3fc7d9f070d72c2d027c1d9dMisha BrukmanLLVMFileType
55a2a62210f2b5fb69364c62e65bb0b8baae6cc50eReid Spencersys::IdentifyFileType(const char*magic, unsigned length) {
56f37ce99c0af5921bb0cc132350ffdf8b73cf30a7Reid Spencer  assert(magic && "Invalid magic number string");
57f37ce99c0af5921bb0cc132350ffdf8b73cf30a7Reid Spencer  assert(length >=4 && "Invalid magic number length");
58f37ce99c0af5921bb0cc132350ffdf8b73cf30a7Reid Spencer  switch (magic[0]) {
59f283a5e53a99d13035a9e783acff80d4ea064a92Chris Lattner    case 'B':
60f283a5e53a99d13035a9e783acff80d4ea064a92Chris Lattner      if (magic[1] == 'C' && magic[2] == (char)0xC0 && magic[3] == (char)0xDE)
61f283a5e53a99d13035a9e783acff80d4ea064a92Chris Lattner        return Bitcode_FileType;
62f283a5e53a99d13035a9e783acff80d4ea064a92Chris Lattner      break;
63f37ce99c0af5921bb0cc132350ffdf8b73cf30a7Reid Spencer    case '!':
648bb5fd17f9a715ac9ce87619f3b6c1066a244859Reid Spencer      if (length >= 8)
65f37ce99c0af5921bb0cc132350ffdf8b73cf30a7Reid Spencer        if (memcmp(magic,"!<arch>\n",8) == 0)
668bb5fd17f9a715ac9ce87619f3b6c1066a244859Reid Spencer          return Archive_FileType;
678bb5fd17f9a715ac9ce87619f3b6c1066a244859Reid Spencer      break;
688bb5fd17f9a715ac9ce87619f3b6c1066a244859Reid Spencer
698bb5fd17f9a715ac9ce87619f3b6c1066a244859Reid Spencer    case '\177':
7024eac6cb00ab18afe7a175ea876bbde776c07532Chris Lattner      if (magic[1] == 'E' && magic[2] == 'L' && magic[3] == 'F') {
71947aa7de67c553a0bbf0ef60173f23a8747014bfReid Spencer        if (length >= 18 && magic[17] == 0)
72947aa7de67c553a0bbf0ef60173f23a8747014bfReid Spencer          switch (magic[16]) {
73947aa7de67c553a0bbf0ef60173f23a8747014bfReid Spencer            default: break;
74947aa7de67c553a0bbf0ef60173f23a8747014bfReid Spencer            case 1: return ELF_Relocatable_FileType;
75947aa7de67c553a0bbf0ef60173f23a8747014bfReid Spencer            case 2: return ELF_Executable_FileType;
76947aa7de67c553a0bbf0ef60173f23a8747014bfReid Spencer            case 3: return ELF_SharedObject_FileType;
77947aa7de67c553a0bbf0ef60173f23a8747014bfReid Spencer            case 4: return ELF_Core_FileType;
78947aa7de67c553a0bbf0ef60173f23a8747014bfReid Spencer          }
7924eac6cb00ab18afe7a175ea876bbde776c07532Chris Lattner      }
808bb5fd17f9a715ac9ce87619f3b6c1066a244859Reid Spencer      break;
818bb5fd17f9a715ac9ce87619f3b6c1066a244859Reid Spencer
82ade7592085cbb3d37a7cc9701c4c07c9c58a87c5Chris Lattner    case 0xCA:
838bb5fd17f9a715ac9ce87619f3b6c1066a244859Reid Spencer      // This is complicated by an overlap with Java class files.
848bb5fd17f9a715ac9ce87619f3b6c1066a244859Reid Spencer      // See the Mach-O section in /usr/share/file/magic for details.
85ade7592085cbb3d37a7cc9701c4c07c9c58a87c5Chris Lattner      if (magic[1] == char(0xFE) && magic[2] == char(0xBA) &&
86ade7592085cbb3d37a7cc9701c4c07c9c58a87c5Chris Lattner          magic[3] == char(0xBE)) {
87ade7592085cbb3d37a7cc9701c4c07c9c58a87c5Chris Lattner        return Mach_O_DynamicallyLinkedSharedLib_FileType;
88ade7592085cbb3d37a7cc9701c4c07c9c58a87c5Chris Lattner
89ade7592085cbb3d37a7cc9701c4c07c9c58a87c5Chris Lattner        // FIXME: How does this work?
90947aa7de67c553a0bbf0ef60173f23a8747014bfReid Spencer        if (length >= 14 && magic[13] == 0)
91947aa7de67c553a0bbf0ef60173f23a8747014bfReid Spencer          switch (magic[12]) {
92947aa7de67c553a0bbf0ef60173f23a8747014bfReid Spencer            default: break;
93947aa7de67c553a0bbf0ef60173f23a8747014bfReid Spencer            case 1: return Mach_O_Object_FileType;
94947aa7de67c553a0bbf0ef60173f23a8747014bfReid Spencer            case 2: return Mach_O_Executable_FileType;
95947aa7de67c553a0bbf0ef60173f23a8747014bfReid Spencer            case 3: return Mach_O_FixedVirtualMemorySharedLib_FileType;
96947aa7de67c553a0bbf0ef60173f23a8747014bfReid Spencer            case 4: return Mach_O_Core_FileType;
97947aa7de67c553a0bbf0ef60173f23a8747014bfReid Spencer            case 5: return Mach_O_PreloadExectuable_FileType;
98947aa7de67c553a0bbf0ef60173f23a8747014bfReid Spencer            case 6: return Mach_O_DynamicallyLinkedSharedLib_FileType;
99947aa7de67c553a0bbf0ef60173f23a8747014bfReid Spencer            case 7: return Mach_O_DynamicLinker_FileType;
100947aa7de67c553a0bbf0ef60173f23a8747014bfReid Spencer            case 8: return Mach_O_Bundle_FileType;
101947aa7de67c553a0bbf0ef60173f23a8747014bfReid Spencer            case 9: return Mach_O_DynamicallyLinkedSharedLibStub_FileType;
102947aa7de67c553a0bbf0ef60173f23a8747014bfReid Spencer          }
103ade7592085cbb3d37a7cc9701c4c07c9c58a87c5Chris Lattner      }
1048bb5fd17f9a715ac9ce87619f3b6c1066a244859Reid Spencer      break;
1058bb5fd17f9a715ac9ce87619f3b6c1066a244859Reid Spencer
1068bb5fd17f9a715ac9ce87619f3b6c1066a244859Reid Spencer    case 0xF0: // PowerPC Windows
1078bb5fd17f9a715ac9ce87619f3b6c1066a244859Reid Spencer    case 0x83: // Alpha 32-bit
1088bb5fd17f9a715ac9ce87619f3b6c1066a244859Reid Spencer    case 0x84: // Alpha 64-bit
1098bb5fd17f9a715ac9ce87619f3b6c1066a244859Reid Spencer    case 0x66: // MPS R4000 Windows
1108bb5fd17f9a715ac9ce87619f3b6c1066a244859Reid Spencer    case 0x50: // mc68K
1118bb5fd17f9a715ac9ce87619f3b6c1066a244859Reid Spencer    case 0x4c: // 80386 Windows
1128bb5fd17f9a715ac9ce87619f3b6c1066a244859Reid Spencer      if (magic[1] == 0x01)
1138bb5fd17f9a715ac9ce87619f3b6c1066a244859Reid Spencer        return COFF_FileType;
1148bb5fd17f9a715ac9ce87619f3b6c1066a244859Reid Spencer
1158bb5fd17f9a715ac9ce87619f3b6c1066a244859Reid Spencer    case 0x90: // PA-RISC Windows
1168bb5fd17f9a715ac9ce87619f3b6c1066a244859Reid Spencer    case 0x68: // mc68K Windows
1178bb5fd17f9a715ac9ce87619f3b6c1066a244859Reid Spencer      if (magic[1] == 0x02)
1188bb5fd17f9a715ac9ce87619f3b6c1066a244859Reid Spencer        return COFF_FileType;
119f37ce99c0af5921bb0cc132350ffdf8b73cf30a7Reid Spencer      break;
120f37ce99c0af5921bb0cc132350ffdf8b73cf30a7Reid Spencer
121f37ce99c0af5921bb0cc132350ffdf8b73cf30a7Reid Spencer    default:
122f37ce99c0af5921bb0cc132350ffdf8b73cf30a7Reid Spencer      break;
123f37ce99c0af5921bb0cc132350ffdf8b73cf30a7Reid Spencer  }
1248bb5fd17f9a715ac9ce87619f3b6c1066a244859Reid Spencer  return Unknown_FileType;
125f37ce99c0af5921bb0cc132350ffdf8b73cf30a7Reid Spencer}
126f37ce99c0af5921bb0cc132350ffdf8b73cf30a7Reid Spencer
127ccb23a13e90c20e555ede74f30ea2ecb90e24d18Reid Spencerbool
128ccb23a13e90c20e555ede74f30ea2ecb90e24d18Reid SpencerPath::isArchive() const {
129c7f083297cd796c2fadb534307e4ef406fd68945Reid Spencer  if (canRead())
130ccb23a13e90c20e555ede74f30ea2ecb90e24d18Reid Spencer    return hasMagicNumber("!<arch>\012");
131ccb23a13e90c20e555ede74f30ea2ecb90e24d18Reid Spencer  return false;
132ccb23a13e90c20e555ede74f30ea2ecb90e24d18Reid Spencer}
133ccb23a13e90c20e555ede74f30ea2ecb90e24d18Reid Spencer
134ccb23a13e90c20e555ede74f30ea2ecb90e24d18Reid Spencerbool
135ccb23a13e90c20e555ede74f30ea2ecb90e24d18Reid SpencerPath::isDynamicLibrary() const {
136410aa020a2c834a5029bb98ee44691c0ec6f2c53Reid Spencer  if (canRead()) {
137410aa020a2c834a5029bb98ee44691c0ec6f2c53Reid Spencer    std::string Magic;
138410aa020a2c834a5029bb98ee44691c0ec6f2c53Reid Spencer    if (getMagicNumber(Magic, 64))
13934cd4a484e532cc463fd5a4bf59b88d13c5467c1Evan Cheng      switch (IdentifyFileType(Magic.c_str(),
14034cd4a484e532cc463fd5a4bf59b88d13c5467c1Evan Cheng                               static_cast<unsigned>(Magic.length()))) {
141410aa020a2c834a5029bb98ee44691c0ec6f2c53Reid Spencer        default: return false;
142947aa7de67c553a0bbf0ef60173f23a8747014bfReid Spencer        case Mach_O_FixedVirtualMemorySharedLib_FileType:
143947aa7de67c553a0bbf0ef60173f23a8747014bfReid Spencer        case Mach_O_DynamicallyLinkedSharedLib_FileType:
144947aa7de67c553a0bbf0ef60173f23a8747014bfReid Spencer        case Mach_O_DynamicallyLinkedSharedLibStub_FileType:
145947aa7de67c553a0bbf0ef60173f23a8747014bfReid Spencer        case ELF_SharedObject_FileType:
146410aa020a2c834a5029bb98ee44691c0ec6f2c53Reid Spencer        case COFF_FileType:  return true;
147410aa020a2c834a5029bb98ee44691c0ec6f2c53Reid Spencer      }
148410aa020a2c834a5029bb98ee44691c0ec6f2c53Reid Spencer  }
149ccb23a13e90c20e555ede74f30ea2ecb90e24d18Reid Spencer  return false;
150ccb23a13e90c20e555ede74f30ea2ecb90e24d18Reid Spencer}
151ccb23a13e90c20e555ede74f30ea2ecb90e24d18Reid Spencer
152ccb23a13e90c20e555ede74f30ea2ecb90e24d18Reid SpencerPath
153ccb23a13e90c20e555ede74f30ea2ecb90e24d18Reid SpencerPath::FindLibrary(std::string& name) {
154ccb23a13e90c20e555ede74f30ea2ecb90e24d18Reid Spencer  std::vector<sys::Path> LibPaths;
155ccb23a13e90c20e555ede74f30ea2ecb90e24d18Reid Spencer  GetSystemLibraryPaths(LibPaths);
156ccb23a13e90c20e555ede74f30ea2ecb90e24d18Reid Spencer  for (unsigned i = 0; i < LibPaths.size(); ++i) {
157ccb23a13e90c20e555ede74f30ea2ecb90e24d18Reid Spencer    sys::Path FullPath(LibPaths[i]);
158dd04df0ec33a903ee7fc747701bafde622f77d8bReid Spencer    FullPath.appendComponent("lib" + name + LTDL_SHLIB_EXT);
159ccb23a13e90c20e555ede74f30ea2ecb90e24d18Reid Spencer    if (FullPath.isDynamicLibrary())
160ccb23a13e90c20e555ede74f30ea2ecb90e24d18Reid Spencer      return FullPath;
161dd04df0ec33a903ee7fc747701bafde622f77d8bReid Spencer    FullPath.eraseSuffix();
162ccb23a13e90c20e555ede74f30ea2ecb90e24d18Reid Spencer    FullPath.appendSuffix("a");
163ccb23a13e90c20e555ede74f30ea2ecb90e24d18Reid Spencer    if (FullPath.isArchive())
164ccb23a13e90c20e555ede74f30ea2ecb90e24d18Reid Spencer      return FullPath;
165ccb23a13e90c20e555ede74f30ea2ecb90e24d18Reid Spencer  }
166ccb23a13e90c20e555ede74f30ea2ecb90e24d18Reid Spencer  return sys::Path();
167ccb23a13e90c20e555ede74f30ea2ecb90e24d18Reid Spencer}
168ccb23a13e90c20e555ede74f30ea2ecb90e24d18Reid Spencer
169c67dc457ceb543f00d2d67e857c1d6f25371378aChris Lattnerstd::string Path::GetDLLSuffix() {
17079fc9249574cee0ec69d920e5a16497ba799020aReid Spencer  return LTDL_SHLIB_EXT;
17179fc9249574cee0ec69d920e5a16497ba799020aReid Spencer}
17279fc9249574cee0ec69d920e5a16497ba799020aReid Spencer
173f283a5e53a99d13035a9e783acff80d4ea064a92Chris Lattnerbool
174f283a5e53a99d13035a9e783acff80d4ea064a92Chris LattnerPath::isBitcodeFile() const {
175f283a5e53a99d13035a9e783acff80d4ea064a92Chris Lattner  std::string actualMagic;
176f283a5e53a99d13035a9e783acff80d4ea064a92Chris Lattner  if (!getMagicNumber(actualMagic, 4))
177f283a5e53a99d13035a9e783acff80d4ea064a92Chris Lattner    return false;
178f283a5e53a99d13035a9e783acff80d4ea064a92Chris Lattner  return actualMagic == "BC\xC0\xDE";
179f283a5e53a99d13035a9e783acff80d4ea064a92Chris Lattner}
180f283a5e53a99d13035a9e783acff80d4ea064a92Chris Lattner
181f283a5e53a99d13035a9e783acff80d4ea064a92Chris Lattnerbool Path::hasMagicNumber(const std::string &Magic) const {
182f283a5e53a99d13035a9e783acff80d4ea064a92Chris Lattner  std::string actualMagic;
18334cd4a484e532cc463fd5a4bf59b88d13c5467c1Evan Cheng  if (getMagicNumber(actualMagic, static_cast<unsigned>(Magic.size())))
184f283a5e53a99d13035a9e783acff80d4ea064a92Chris Lattner    return Magic == actualMagic;
185f283a5e53a99d13035a9e783acff80d4ea064a92Chris Lattner  return false;
186f283a5e53a99d13035a9e783acff80d4ea064a92Chris Lattner}
187f283a5e53a99d13035a9e783acff80d4ea064a92Chris Lattner
188e18bc08fbc674584fe3a3a0c6b866a5aea201a91Anton Korobeynikovstd::string
189e18bc08fbc674584fe3a3a0c6b866a5aea201a91Anton KorobeynikovPath::getSuffix() const {
190e18bc08fbc674584fe3a3a0c6b866a5aea201a91Anton Korobeynikov  return path.substr(path.rfind('.') + 1);
191e18bc08fbc674584fe3a3a0c6b866a5aea201a91Anton Korobeynikov}
192f283a5e53a99d13035a9e783acff80d4ea064a92Chris Lattner
193e1b332a30459a726e882a4f484a9a31f2cea9e29Chris Lattnerstatic void getPathList(const char*path, std::vector<Path>& Paths) {
194e1b332a30459a726e882a4f484a9a31f2cea9e29Chris Lattner  const char* at = path;
195e1b332a30459a726e882a4f484a9a31f2cea9e29Chris Lattner  const char* delim = strchr(at, PathSeparator);
196e1b332a30459a726e882a4f484a9a31f2cea9e29Chris Lattner  Path tmpPath;
197e1b332a30459a726e882a4f484a9a31f2cea9e29Chris Lattner  while (delim != 0) {
198e1b332a30459a726e882a4f484a9a31f2cea9e29Chris Lattner    std::string tmp(at, size_t(delim-at));
199e1b332a30459a726e882a4f484a9a31f2cea9e29Chris Lattner    if (tmpPath.set(tmp))
200e1b332a30459a726e882a4f484a9a31f2cea9e29Chris Lattner      if (tmpPath.canRead())
201e1b332a30459a726e882a4f484a9a31f2cea9e29Chris Lattner        Paths.push_back(tmpPath);
202e1b332a30459a726e882a4f484a9a31f2cea9e29Chris Lattner    at = delim + 1;
203e1b332a30459a726e882a4f484a9a31f2cea9e29Chris Lattner    delim = strchr(at, PathSeparator);
204e1b332a30459a726e882a4f484a9a31f2cea9e29Chris Lattner  }
205e1b332a30459a726e882a4f484a9a31f2cea9e29Chris Lattner
206e1b332a30459a726e882a4f484a9a31f2cea9e29Chris Lattner  if (*at != 0)
207e1b332a30459a726e882a4f484a9a31f2cea9e29Chris Lattner    if (tmpPath.set(std::string(at)))
208e1b332a30459a726e882a4f484a9a31f2cea9e29Chris Lattner      if (tmpPath.canRead())
209e1b332a30459a726e882a4f484a9a31f2cea9e29Chris Lattner        Paths.push_back(tmpPath);
210e1b332a30459a726e882a4f484a9a31f2cea9e29Chris Lattner}
211e1b332a30459a726e882a4f484a9a31f2cea9e29Chris Lattner
2129b01cc0ede3bfef32ce46159670dedc3e9769a64Ted Kremenekstatic std::string getDirnameCharSep(const std::string& path, char Sep) {
213cf55c8e221c1d31a361f99ee49078d261cdf431cTed Kremenek
214cf55c8e221c1d31a361f99ee49078d261cdf431cTed Kremenek  if (path.empty())
215cf55c8e221c1d31a361f99ee49078d261cdf431cTed Kremenek    return ".";
216cf55c8e221c1d31a361f99ee49078d261cdf431cTed Kremenek
217cf55c8e221c1d31a361f99ee49078d261cdf431cTed Kremenek  // If the path is all slashes, return a single slash.
218cf55c8e221c1d31a361f99ee49078d261cdf431cTed Kremenek  // Otherwise, remove all trailing slashes.
219cf55c8e221c1d31a361f99ee49078d261cdf431cTed Kremenek
22034cd4a484e532cc463fd5a4bf59b88d13c5467c1Evan Cheng  signed pos = static_cast<signed>(path.size()) - 1;
221cf55c8e221c1d31a361f99ee49078d261cdf431cTed Kremenek
222cf55c8e221c1d31a361f99ee49078d261cdf431cTed Kremenek  while (pos >= 0 && path[pos] == Sep)
223cf55c8e221c1d31a361f99ee49078d261cdf431cTed Kremenek    --pos;
224cf55c8e221c1d31a361f99ee49078d261cdf431cTed Kremenek
225cf55c8e221c1d31a361f99ee49078d261cdf431cTed Kremenek  if (pos < 0)
226cf55c8e221c1d31a361f99ee49078d261cdf431cTed Kremenek    return path[0] == Sep ? std::string(1, Sep) : std::string(".");
227cf55c8e221c1d31a361f99ee49078d261cdf431cTed Kremenek
228cf55c8e221c1d31a361f99ee49078d261cdf431cTed Kremenek  // Any slashes left?
229cf55c8e221c1d31a361f99ee49078d261cdf431cTed Kremenek  signed i = 0;
230cf55c8e221c1d31a361f99ee49078d261cdf431cTed Kremenek
231cf55c8e221c1d31a361f99ee49078d261cdf431cTed Kremenek  while (i < pos && path[i] != Sep)
232cf55c8e221c1d31a361f99ee49078d261cdf431cTed Kremenek    ++i;
233cf55c8e221c1d31a361f99ee49078d261cdf431cTed Kremenek
234cf55c8e221c1d31a361f99ee49078d261cdf431cTed Kremenek  if (i == pos) // No slashes?  Return "."
235cf55c8e221c1d31a361f99ee49078d261cdf431cTed Kremenek    return ".";
236cf55c8e221c1d31a361f99ee49078d261cdf431cTed Kremenek
237cf55c8e221c1d31a361f99ee49078d261cdf431cTed Kremenek  // There is at least one slash left.  Remove all trailing non-slashes.
238cf55c8e221c1d31a361f99ee49078d261cdf431cTed Kremenek  while (pos >= 0 && path[pos] != Sep)
239cf55c8e221c1d31a361f99ee49078d261cdf431cTed Kremenek    --pos;
240cf55c8e221c1d31a361f99ee49078d261cdf431cTed Kremenek
241cf55c8e221c1d31a361f99ee49078d261cdf431cTed Kremenek  // Remove any trailing slashes.
242cf55c8e221c1d31a361f99ee49078d261cdf431cTed Kremenek  while (pos >= 0 && path[pos] == Sep)
243cf55c8e221c1d31a361f99ee49078d261cdf431cTed Kremenek    --pos;
244cf55c8e221c1d31a361f99ee49078d261cdf431cTed Kremenek
245cf55c8e221c1d31a361f99ee49078d261cdf431cTed Kremenek  if (pos < 0)
246cf55c8e221c1d31a361f99ee49078d261cdf431cTed Kremenek    return path[0] == Sep ? std::string(1, Sep) : std::string(".");
247cf55c8e221c1d31a361f99ee49078d261cdf431cTed Kremenek
248cf55c8e221c1d31a361f99ee49078d261cdf431cTed Kremenek  return path.substr(0, pos+1);
249cf55c8e221c1d31a361f99ee49078d261cdf431cTed Kremenek}
250cf55c8e221c1d31a361f99ee49078d261cdf431cTed Kremenek
251b89a2237ea79e0576fdb426b124f1940f53da159Reid Spencer// Include the truly platform-specific parts of this class.
252dafe55f64b038445adce31fe884e453db859194cReid Spencer#if defined(LLVM_ON_UNIX)
253bccc8abc79338d1cfdd5ea20f7288452ddf75b84Reid Spencer#include "Unix/Path.inc"
254dafe55f64b038445adce31fe884e453db859194cReid Spencer#endif
255dafe55f64b038445adce31fe884e453db859194cReid Spencer#if defined(LLVM_ON_WIN32)
256bccc8abc79338d1cfdd5ea20f7288452ddf75b84Reid Spencer#include "Win32/Path.inc"
257dafe55f64b038445adce31fe884e453db859194cReid Spencer#endif
25823dd3327a03b9b64b428ea07dae580326159e47bReid Spencer
259