1 //===- SearchDirs.cpp -----------------------------------------------------===//
2 //
3 //                     The MCLinker Project
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 #include "mcld/MC/SearchDirs.h"
10 
11 #include "mcld/MC/MCLDDirectory.h"
12 #include "mcld/Support/FileSystem.h"
13 
14 namespace mcld {
15 
16 //===----------------------------------------------------------------------===//
17 // Non-member functions
18 //===----------------------------------------------------------------------===//
SpecToFilename(const std::string & pSpec,std::string & pFile)19 static inline void SpecToFilename(const std::string& pSpec,
20                                   std::string& pFile) {
21   pFile = "lib";
22   pFile += pSpec;
23 }
24 
25 //===----------------------------------------------------------------------===//
26 // SearchDirs
27 //===----------------------------------------------------------------------===//
SearchDirs()28 SearchDirs::SearchDirs() {
29   // a magic number 8, no why.
30   // please prove it or change it
31   m_DirList.reserve(8);
32 }
33 
SearchDirs(const sys::fs::Path & pSysRoot)34 SearchDirs::SearchDirs(const sys::fs::Path& pSysRoot) : m_SysRoot(pSysRoot) {
35   // a magic number 8, no why.
36   // please prove it or change it
37   m_DirList.reserve(8);
38 }
39 
~SearchDirs()40 SearchDirs::~SearchDirs() {
41   iterator dir, dirEnd = end();
42   for (dir = begin(); dir != dirEnd; ++dir) {
43     delete (*dir);
44   }
45 }
46 
insert(const std::string & pPath)47 bool SearchDirs::insert(const std::string& pPath) {
48   MCLDDirectory* dir = new MCLDDirectory(pPath);
49   if (dir->isInSysroot())
50     dir->setSysroot(m_SysRoot);
51 
52   if (exists(dir->path()) && is_directory(dir->path())) {
53     m_DirList.push_back(dir);
54     return true;
55   } else {
56     delete dir;
57     return false;
58   }
59   return true;
60 }
61 
insert(const char * pPath)62 bool SearchDirs::insert(const char* pPath) {
63   return insert(std::string(pPath));
64 }
65 
insert(const sys::fs::Path & pPath)66 bool SearchDirs::insert(const sys::fs::Path& pPath) {
67   return insert(pPath.native());
68 }
69 
find(const std::string & pNamespec,mcld::Input::Type pType)70 mcld::sys::fs::Path* SearchDirs::find(const std::string& pNamespec,
71                                       mcld::Input::Type pType) {
72   assert(Input::DynObj == pType || Input::Archive == pType ||
73          Input::Script == pType);
74 
75   std::string file;
76   switch (pType) {
77     case Input::Script:
78       file.assign(pNamespec);
79       break;
80     case Input::DynObj:
81     case Input::Archive:
82       SpecToFilename(pNamespec, file);
83       break;
84     default:
85       break;
86   }  // end of switch
87 
88   // for all MCLDDirectorys
89   DirList::iterator mcld_dir, mcld_dir_end = m_DirList.end();
90   for (mcld_dir = m_DirList.begin(); mcld_dir != mcld_dir_end; ++mcld_dir) {
91     // for all entries in MCLDDirectory
92     MCLDDirectory::iterator entry = (*mcld_dir)->begin();
93     MCLDDirectory::iterator enEnd = (*mcld_dir)->end();
94 
95     switch (pType) {
96       case Input::Script: {
97         while (entry != enEnd) {
98           if (file == entry.path()->filename().native())
99             return entry.path();
100           ++entry;
101         }
102         break;
103       }
104       case Input::DynObj: {
105         while (entry != enEnd) {
106           if (file == entry.path()->stem().native()) {
107             if (mcld::sys::fs::detail::shared_library_extension ==
108                 entry.path()->extension().native()) {
109               return entry.path();
110             }
111           }
112           ++entry;
113         }
114       }
115       /** Fall through **/
116       case Input::Archive: {
117         entry = (*mcld_dir)->begin();
118         enEnd = (*mcld_dir)->end();
119         while (entry != enEnd) {
120           if (file == entry.path()->stem().native() &&
121               mcld::sys::fs::detail::static_library_extension ==
122                   entry.path()->extension().native()) {
123             return entry.path();
124           }
125           ++entry;
126         }
127       }
128       default:
129         break;
130     }  // end of switch
131   }    // end of for
132   return NULL;
133 }
134 
find(const std::string & pNamespec,mcld::Input::Type pType) const135 const mcld::sys::fs::Path* SearchDirs::find(const std::string& pNamespec,
136                                             mcld::Input::Type pType) const {
137   assert(Input::DynObj == pType || Input::Archive == pType ||
138          Input::Script == pType);
139 
140   std::string file;
141   switch (pType) {
142     case Input::Script:
143       file.assign(pNamespec);
144       break;
145     case Input::DynObj:
146     case Input::Archive:
147       SpecToFilename(pNamespec, file);
148       break;
149     default:
150       break;
151   }  // end of switch
152 
153   // for all MCLDDirectorys
154   DirList::const_iterator mcld_dir, mcld_dir_end = m_DirList.end();
155   for (mcld_dir = m_DirList.begin(); mcld_dir != mcld_dir_end; ++mcld_dir) {
156     // for all entries in MCLDDirectory
157     MCLDDirectory::iterator entry = (*mcld_dir)->begin();
158     MCLDDirectory::iterator enEnd = (*mcld_dir)->end();
159 
160     switch (pType) {
161       case Input::Script: {
162         while (entry != enEnd) {
163           if (file == entry.path()->filename().native())
164             return entry.path();
165           ++entry;
166         }
167         break;
168       }
169       case Input::DynObj: {
170         while (entry != enEnd) {
171           if (file == entry.path()->stem().native()) {
172             if (mcld::sys::fs::detail::shared_library_extension ==
173                 entry.path()->extension().native()) {
174               return entry.path();
175             }
176           }
177           ++entry;
178         }
179       }
180       /** Fall through **/
181       case Input::Archive: {
182         entry = (*mcld_dir)->begin();
183         enEnd = (*mcld_dir)->end();
184         while (entry != enEnd) {
185           if (file == entry.path()->stem().native() &&
186               mcld::sys::fs::detail::static_library_extension ==
187                   entry.path()->extension().native()) {
188             return entry.path();
189           }
190           ++entry;
191         }
192       }
193       default:
194         break;
195     }  // end of switch
196   }    // end of for
197   return NULL;
198 }
199 
200 }  // namespace mcld
201