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
14namespace mcld {
15
16//===----------------------------------------------------------------------===//
17// Non-member functions
18//===----------------------------------------------------------------------===//
19static inline void SpecToFilename(const std::string& pSpec,
20                                  std::string& pFile) {
21  pFile = "lib";
22  pFile += pSpec;
23}
24
25//===----------------------------------------------------------------------===//
26// SearchDirs
27//===----------------------------------------------------------------------===//
28SearchDirs::SearchDirs() {
29  // a magic number 8, no why.
30  // please prove it or change it
31  m_DirList.reserve(8);
32}
33
34SearchDirs::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
40SearchDirs::~SearchDirs() {
41  iterator dir, dirEnd = end();
42  for (dir = begin(); dir != dirEnd; ++dir) {
43    delete (*dir);
44  }
45}
46
47bool 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
62bool SearchDirs::insert(const char* pPath) {
63  return insert(std::string(pPath));
64}
65
66bool SearchDirs::insert(const sys::fs::Path& pPath) {
67  return insert(pPath.native());
68}
69
70mcld::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
135const 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