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