C++程序  |  201行  |  5.57 KB

//===- SearchDirs.cpp -----------------------------------------------------===//
//
//                     The MCLinker Project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "mcld/MC/SearchDirs.h"

#include "mcld/MC/MCLDDirectory.h"
#include "mcld/Support/FileSystem.h"

namespace mcld {

//===----------------------------------------------------------------------===//
// Non-member functions
//===----------------------------------------------------------------------===//
static inline void SpecToFilename(const std::string& pSpec,
                                  std::string& pFile) {
  pFile = "lib";
  pFile += pSpec;
}

//===----------------------------------------------------------------------===//
// SearchDirs
//===----------------------------------------------------------------------===//
SearchDirs::SearchDirs() {
  // a magic number 8, no why.
  // please prove it or change it
  m_DirList.reserve(8);
}

SearchDirs::SearchDirs(const sys::fs::Path& pSysRoot) : m_SysRoot(pSysRoot) {
  // a magic number 8, no why.
  // please prove it or change it
  m_DirList.reserve(8);
}

SearchDirs::~SearchDirs() {
  iterator dir, dirEnd = end();
  for (dir = begin(); dir != dirEnd; ++dir) {
    delete (*dir);
  }
}

bool SearchDirs::insert(const std::string& pPath) {
  MCLDDirectory* dir = new MCLDDirectory(pPath);
  if (dir->isInSysroot())
    dir->setSysroot(m_SysRoot);

  if (exists(dir->path()) && is_directory(dir->path())) {
    m_DirList.push_back(dir);
    return true;
  } else {
    delete dir;
    return false;
  }
  return true;
}

bool SearchDirs::insert(const char* pPath) {
  return insert(std::string(pPath));
}

bool SearchDirs::insert(const sys::fs::Path& pPath) {
  return insert(pPath.native());
}

mcld::sys::fs::Path* SearchDirs::find(const std::string& pNamespec,
                                      mcld::Input::Type pType) {
  assert(Input::DynObj == pType || Input::Archive == pType ||
         Input::Script == pType);

  std::string file;
  switch (pType) {
    case Input::Script:
      file.assign(pNamespec);
      break;
    case Input::DynObj:
    case Input::Archive:
      SpecToFilename(pNamespec, file);
      break;
    default:
      break;
  }  // end of switch

  // for all MCLDDirectorys
  DirList::iterator mcld_dir, mcld_dir_end = m_DirList.end();
  for (mcld_dir = m_DirList.begin(); mcld_dir != mcld_dir_end; ++mcld_dir) {
    // for all entries in MCLDDirectory
    MCLDDirectory::iterator entry = (*mcld_dir)->begin();
    MCLDDirectory::iterator enEnd = (*mcld_dir)->end();

    switch (pType) {
      case Input::Script: {
        while (entry != enEnd) {
          if (file == entry.path()->filename().native())
            return entry.path();
          ++entry;
        }
        break;
      }
      case Input::DynObj: {
        while (entry != enEnd) {
          if (file == entry.path()->stem().native()) {
            if (mcld::sys::fs::detail::shared_library_extension ==
                entry.path()->extension().native()) {
              return entry.path();
            }
          }
          ++entry;
        }
      }
      /** Fall through **/
      case Input::Archive: {
        entry = (*mcld_dir)->begin();
        enEnd = (*mcld_dir)->end();
        while (entry != enEnd) {
          if (file == entry.path()->stem().native() &&
              mcld::sys::fs::detail::static_library_extension ==
                  entry.path()->extension().native()) {
            return entry.path();
          }
          ++entry;
        }
      }
      default:
        break;
    }  // end of switch
  }    // end of for
  return NULL;
}

const mcld::sys::fs::Path* SearchDirs::find(const std::string& pNamespec,
                                            mcld::Input::Type pType) const {
  assert(Input::DynObj == pType || Input::Archive == pType ||
         Input::Script == pType);

  std::string file;
  switch (pType) {
    case Input::Script:
      file.assign(pNamespec);
      break;
    case Input::DynObj:
    case Input::Archive:
      SpecToFilename(pNamespec, file);
      break;
    default:
      break;
  }  // end of switch

  // for all MCLDDirectorys
  DirList::const_iterator mcld_dir, mcld_dir_end = m_DirList.end();
  for (mcld_dir = m_DirList.begin(); mcld_dir != mcld_dir_end; ++mcld_dir) {
    // for all entries in MCLDDirectory
    MCLDDirectory::iterator entry = (*mcld_dir)->begin();
    MCLDDirectory::iterator enEnd = (*mcld_dir)->end();

    switch (pType) {
      case Input::Script: {
        while (entry != enEnd) {
          if (file == entry.path()->filename().native())
            return entry.path();
          ++entry;
        }
        break;
      }
      case Input::DynObj: {
        while (entry != enEnd) {
          if (file == entry.path()->stem().native()) {
            if (mcld::sys::fs::detail::shared_library_extension ==
                entry.path()->extension().native()) {
              return entry.path();
            }
          }
          ++entry;
        }
      }
      /** Fall through **/
      case Input::Archive: {
        entry = (*mcld_dir)->begin();
        enEnd = (*mcld_dir)->end();
        while (entry != enEnd) {
          if (file == entry.path()->stem().native() &&
              mcld::sys::fs::detail::static_library_extension ==
                  entry.path()->extension().native()) {
            return entry.path();
          }
          ++entry;
        }
      }
      default:
        break;
    }  // end of switch
  }    // end of for
  return NULL;
}

}  // namespace mcld