Change ScheduleDAG's SUnitMap from DenseMap<SDNode*, vector<SUnit*> >
[oota-llvm.git] / lib / System / 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/System/Path.h"
15 #include "llvm/Config/config.h"
16 #include <cassert>
17 #include <cstring>
18 #include <ostream>
19 using namespace llvm;
20 using namespace sys;
21
22 //===----------------------------------------------------------------------===//
23 //=== WARNING: Implementation here must contain only TRULY operating system
24 //===          independent code.
25 //===----------------------------------------------------------------------===//
26
27 bool Path::operator==(const Path &that) const {
28   return path == that.path;
29 }
30
31 bool Path::operator!=(const Path &that) const {
32   return path != that.path;
33 }
34
35 bool Path::operator<(const Path& that) const {
36   return path < that.path;
37 }
38
39 std::ostream& llvm::operator<<(std::ostream &strm, const sys::Path &aPath) {
40   strm << aPath.toString();
41   return strm;
42 }
43
44 Path
45 Path::GetLLVMConfigDir() {
46   Path result;
47 #ifdef LLVM_ETCDIR
48   if (result.set(LLVM_ETCDIR))
49     return result;
50 #endif
51   return GetLLVMDefaultConfigDir();
52 }
53
54 LLVMFileType
55 sys::IdentifyFileType(const char*magic, unsigned length) {
56   assert(magic && "Invalid magic number string");
57   assert(length >=4 && "Invalid magic number length");
58   switch (magic[0]) {
59     case 'B':
60       if (magic[1] == 'C' && magic[2] == (char)0xC0 && magic[3] == (char)0xDE)
61         return Bitcode_FileType;
62       break;
63     case '!':
64       if (length >= 8)
65         if (memcmp(magic,"!<arch>\n",8) == 0)
66           return Archive_FileType;
67       break;
68       
69     case '\177':
70       if (magic[1] == 'E' && magic[2] == 'L' && magic[3] == 'F') {
71         if (length >= 18 && magic[17] == 0)
72           switch (magic[16]) {
73             default: break;
74             case 1: return ELF_Relocatable_FileType;
75             case 2: return ELF_Executable_FileType;
76             case 3: return ELF_SharedObject_FileType;
77             case 4: return ELF_Core_FileType;
78           }
79       }
80       break;
81
82     case 0xCA:
83       // This is complicated by an overlap with Java class files. 
84       // See the Mach-O section in /usr/share/file/magic for details.
85       if (magic[1] == char(0xFE) && magic[2] == char(0xBA) && 
86           magic[3] == char(0xBE)) {
87         return Mach_O_DynamicallyLinkedSharedLib_FileType;
88         
89         // FIXME: How does this work?
90         if (length >= 14 && magic[13] == 0)
91           switch (magic[12]) {
92             default: break;
93             case 1: return Mach_O_Object_FileType;
94             case 2: return Mach_O_Executable_FileType;
95             case 3: return Mach_O_FixedVirtualMemorySharedLib_FileType;
96             case 4: return Mach_O_Core_FileType;
97             case 5: return Mach_O_PreloadExectuable_FileType;
98             case 6: return Mach_O_DynamicallyLinkedSharedLib_FileType;
99             case 7: return Mach_O_DynamicLinker_FileType;
100             case 8: return Mach_O_Bundle_FileType;
101             case 9: return Mach_O_DynamicallyLinkedSharedLibStub_FileType;
102           }
103       }
104       break;
105
106     case 0xF0: // PowerPC Windows
107     case 0x83: // Alpha 32-bit
108     case 0x84: // Alpha 64-bit
109     case 0x66: // MPS R4000 Windows
110     case 0x50: // mc68K
111     case 0x4c: // 80386 Windows
112       if (magic[1] == 0x01)
113         return COFF_FileType;
114
115     case 0x90: // PA-RISC Windows
116     case 0x68: // mc68K Windows
117       if (magic[1] == 0x02)
118         return COFF_FileType;
119       break;
120
121     default:
122       break;
123   }
124   return Unknown_FileType;
125 }
126
127 bool
128 Path::isArchive() const {
129   if (canRead())
130     return hasMagicNumber("!<arch>\012");
131   return false;
132 }
133
134 bool
135 Path::isDynamicLibrary() const {
136   if (canRead()) {
137     std::string Magic;
138     if (getMagicNumber(Magic, 64))
139       switch (IdentifyFileType(Magic.c_str(),
140                                static_cast<unsigned>(Magic.length()))) {
141         default: return false;
142         case Mach_O_FixedVirtualMemorySharedLib_FileType:
143         case Mach_O_DynamicallyLinkedSharedLib_FileType:
144         case Mach_O_DynamicallyLinkedSharedLibStub_FileType:
145         case ELF_SharedObject_FileType:
146         case COFF_FileType:  return true;
147       }
148   }
149   return false;
150 }
151
152 Path
153 Path::FindLibrary(std::string& name) {
154   std::vector<sys::Path> LibPaths;
155   GetSystemLibraryPaths(LibPaths);
156   for (unsigned i = 0; i < LibPaths.size(); ++i) {
157     sys::Path FullPath(LibPaths[i]);
158     FullPath.appendComponent("lib" + name + LTDL_SHLIB_EXT);
159     if (FullPath.isDynamicLibrary())
160       return FullPath;
161     FullPath.eraseSuffix();
162     FullPath.appendSuffix("a");
163     if (FullPath.isArchive())
164       return FullPath;
165   }
166   return sys::Path();
167 }
168
169 std::string Path::GetDLLSuffix() {
170   return LTDL_SHLIB_EXT;
171 }
172
173 bool
174 Path::isBitcodeFile() const {
175   std::string actualMagic;
176   if (!getMagicNumber(actualMagic, 4))
177     return false;
178   return actualMagic == "BC\xC0\xDE";
179 }
180
181 bool Path::hasMagicNumber(const std::string &Magic) const {
182   std::string actualMagic;
183   if (getMagicNumber(actualMagic, static_cast<unsigned>(Magic.size())))
184     return Magic == actualMagic;
185   return false;
186 }
187
188 static void getPathList(const char*path, std::vector<Path>& Paths) {
189   const char* at = path;
190   const char* delim = strchr(at, PathSeparator);
191   Path tmpPath;
192   while (delim != 0) {
193     std::string tmp(at, size_t(delim-at));
194     if (tmpPath.set(tmp))
195       if (tmpPath.canRead())
196         Paths.push_back(tmpPath);
197     at = delim + 1;
198     delim = strchr(at, PathSeparator);
199   }
200
201   if (*at != 0)
202     if (tmpPath.set(std::string(at)))
203       if (tmpPath.canRead())
204         Paths.push_back(tmpPath);
205 }
206
207 static std::string getDirnameCharSep(const std::string& path, char Sep) {
208   
209   if (path.empty())
210     return ".";
211   
212   // If the path is all slashes, return a single slash.
213   // Otherwise, remove all trailing slashes.
214   
215   signed pos = static_cast<signed>(path.size()) - 1;
216   
217   while (pos >= 0 && path[pos] == Sep)
218     --pos;
219   
220   if (pos < 0)
221     return path[0] == Sep ? std::string(1, Sep) : std::string(".");
222   
223   // Any slashes left?
224   signed i = 0;
225   
226   while (i < pos && path[i] != Sep)
227     ++i;
228   
229   if (i == pos) // No slashes?  Return "."
230     return ".";
231   
232   // There is at least one slash left.  Remove all trailing non-slashes.  
233   while (pos >= 0 && path[pos] != Sep)
234     --pos;
235   
236   // Remove any trailing slashes.
237   while (pos >= 0 && path[pos] == Sep)
238     --pos;
239   
240   if (pos < 0)
241     return path[0] == Sep ? std::string(1, Sep) : std::string(".");
242   
243   return path.substr(0, pos+1);
244 }
245
246 // Include the truly platform-specific parts of this class.
247 #if defined(LLVM_ON_UNIX)
248 #include "Unix/Path.inc"
249 #endif
250 #if defined(LLVM_ON_WIN32)
251 #include "Win32/Path.inc"
252 #endif
253