e53abe8f592a9de705748df257e2eb86f5430aa8
[oota-llvm.git] / lib / Support / Path.cpp
1 //===-- Path.cpp - Implement OS Path Concept --------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 //  This header file implements the operating system Path concept.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "llvm/Support/Path.h"
15 #include "llvm/Config/config.h"
16 #include "llvm/Support/Endian.h"
17 #include "llvm/Support/FileSystem.h"
18 #include <cassert>
19 #include <cstring>
20 #include <ostream>
21 using namespace llvm;
22 using namespace sys;
23 namespace {
24 using support::ulittle32_t;
25 }
26
27 //===----------------------------------------------------------------------===//
28 //=== WARNING: Implementation here must contain only TRULY operating system
29 //===          independent code.
30 //===----------------------------------------------------------------------===//
31
32 bool Path::operator==(const Path &that) const {
33   return path == that.path;
34 }
35
36 bool Path::operator<(const Path& that) const {
37   return path < that.path;
38 }
39
40 bool
41 Path::isArchive() const {
42   fs::file_magic type;
43   if (fs::identify_magic(str(), type))
44     return false;
45   return type == fs::file_magic::archive;
46 }
47
48 bool
49 Path::isDynamicLibrary() const {
50   fs::file_magic type;
51   if (fs::identify_magic(str(), type))
52     return false;
53   switch (type) {
54     default: return false;
55     case fs::file_magic::macho_fixed_virtual_memory_shared_lib:
56     case fs::file_magic::macho_dynamically_linked_shared_lib:
57     case fs::file_magic::macho_dynamically_linked_shared_lib_stub:
58     case fs::file_magic::elf_shared_object:
59     case fs::file_magic::pecoff_executable:  return true;
60   }
61 }
62
63 bool
64 Path::isObjectFile() const {
65   fs::file_magic type;
66   if (fs::identify_magic(str(), type) || type == fs::file_magic::unknown)
67     return false;
68   return true;
69 }
70
71 Path
72 Path::FindLibrary(std::string& name) {
73   std::vector<sys::Path> LibPaths;
74   GetSystemLibraryPaths(LibPaths);
75   for (unsigned i = 0; i < LibPaths.size(); ++i) {
76     sys::Path FullPath(LibPaths[i]);
77     FullPath.appendComponent("lib" + name + LTDL_SHLIB_EXT);
78     if (FullPath.isDynamicLibrary())
79       return FullPath;
80     FullPath.eraseSuffix();
81     FullPath.appendSuffix("a");
82     if (FullPath.isArchive())
83       return FullPath;
84   }
85   return sys::Path();
86 }
87
88 StringRef Path::GetDLLSuffix() {
89   return &(LTDL_SHLIB_EXT[1]);
90 }
91
92 void
93 Path::appendSuffix(StringRef suffix) {
94   if (!suffix.empty()) {
95     path.append(".");
96     path.append(suffix);
97   }
98 }
99
100 bool
101 Path::isBitcodeFile() const {
102   fs::file_magic type;
103   if (fs::identify_magic(str(), type))
104     return false;
105   return type == fs::file_magic::bitcode;
106 }
107
108 bool Path::hasMagicNumber(StringRef Magic) const {
109   std::string actualMagic;
110   if (getMagicNumber(actualMagic, static_cast<unsigned>(Magic.size())))
111     return Magic == actualMagic;
112   return false;
113 }
114
115 static void getPathList(const char*path, std::vector<Path>& Paths) {
116   const char* at = path;
117   const char* delim = strchr(at, PathSeparator);
118   Path tmpPath;
119   while (delim != 0) {
120     std::string tmp(at, size_t(delim-at));
121     if (tmpPath.set(tmp))
122       if (tmpPath.canRead())
123         Paths.push_back(tmpPath);
124     at = delim + 1;
125     delim = strchr(at, PathSeparator);
126   }
127
128   if (*at != 0)
129     if (tmpPath.set(std::string(at)))
130       if (tmpPath.canRead())
131         Paths.push_back(tmpPath);
132 }
133
134 static StringRef getDirnameCharSep(StringRef path, const char *Sep) {
135   assert(Sep[0] != '\0' && Sep[1] == '\0' &&
136          "Sep must be a 1-character string literal.");
137   if (path.empty())
138     return ".";
139
140   // If the path is all slashes, return a single slash.
141   // Otherwise, remove all trailing slashes.
142
143   signed pos = static_cast<signed>(path.size()) - 1;
144
145   while (pos >= 0 && path[pos] == Sep[0])
146     --pos;
147
148   if (pos < 0)
149     return path[0] == Sep[0] ? Sep : ".";
150
151   // Any slashes left?
152   signed i = 0;
153
154   while (i < pos && path[i] != Sep[0])
155     ++i;
156
157   if (i == pos) // No slashes?  Return "."
158     return ".";
159
160   // There is at least one slash left.  Remove all trailing non-slashes.
161   while (pos >= 0 && path[pos] != Sep[0])
162     --pos;
163
164   // Remove any trailing slashes.
165   while (pos >= 0 && path[pos] == Sep[0])
166     --pos;
167
168   if (pos < 0)
169     return path[0] == Sep[0] ? Sep : ".";
170
171   return path.substr(0, pos+1);
172 }
173
174 // Include the truly platform-specific parts of this class.
175 #if defined(LLVM_ON_UNIX)
176 #include "Unix/Path.inc"
177 #endif
178 #if defined(LLVM_ON_WIN32)
179 #include "Windows/Path.inc"
180 #endif