text: /*============================================================================
    CMake - Cross Platform Makefile Generator
    Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
  
    Distributed under the OSI-approved BSD License (the "License");
    see accompanying file Copyright.txt for details.
  
    This software is distributed WITHOUT ANY WARRANTY; without even the
    implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    See the License for more information.
  ============================================================================*/
  #include "cmFindPathCommand.h"
  
  #include <cmsys/Glob.hxx>
  
  cmFindPathCommand::cmFindPathCommand()
  {
    this->EnvironmentPath = "INCLUDE";
    this->IncludeFileInPath = false;
  }
  
  // cmFindPathCommand
  bool cmFindPathCommand::InitialPass(std::vector<std::string> const& argsIn,
                                      cmExecutionStatus&)
  {
    this->VariableDocumentation = "Path to a file.";
    this->CMakePathName = "INCLUDE";
    if (!this->ParseArguments(argsIn)) {
      return false;
    }
    if (this->AlreadyInCache) {
      // If the user specifies the entry on the command line without a
      // type we should add the type and docstring but keep the original
      // value.
      if (this->AlreadyInCacheWithoutMetaInfo) {
        this->Makefile->AddCacheDefinition(
          this->VariableName, "", this->VariableDocumentation.c_str(),
          (this->IncludeFileInPath ? cmState::FILEPATH : cmState::PATH));
      }
      return true;
    }
  
    std::string result = this->FindHeader();
    if (!result.empty()) {
      this->Makefile->AddCacheDefinition(
        this->VariableName, result.c_str(), this->VariableDocumentation.c_str(),
        (this->IncludeFileInPath) ? cmState::FILEPATH : cmState::PATH);
      return true;
    }
    this->Makefile->AddCacheDefinition(
      this->VariableName, (this->VariableName + "-NOTFOUND").c_str(),
      this->VariableDocumentation.c_str(),
      (this->IncludeFileInPath) ? cmState::FILEPATH : cmState::PATH);
    return true;
  }
  
  std::string cmFindPathCommand::FindHeader()
  {
    std::string header;
    if (this->SearchFrameworkFirst || this->SearchFrameworkOnly) {
      header = this->FindFrameworkHeader();
    }
    if (header.empty() && !this->SearchFrameworkOnly) {
      header = this->FindNormalHeader();
    }
    if (header.empty() && this->SearchFrameworkLast) {
      header = this->FindFrameworkHeader();
    }
    return header;
  }
  
  std::string cmFindPathCommand::FindHeaderInFramework(std::string const& file,
                                                       std::string const& dir)
  {
    std::string fileName = file;
    std::string frameWorkName;
    std::string::size_type pos = fileName.find("/");
    // if there is a / in the name try to find the header as a framework
    // For example bar/foo.h would look for:
    // bar.framework/Headers/foo.h
    if (pos != fileName.npos) {
      // remove the name from the slash;
      fileName = fileName.substr(pos + 1);
      frameWorkName = file;
      frameWorkName =
        frameWorkName.substr(0, frameWorkName.size() - fileName.size() - 1);
      // if the framework has a path in it then just use the filename
      if (frameWorkName.find("/") != frameWorkName.npos) {
        fileName = file;
        frameWorkName = "";
      }
      if (!frameWorkName.empty()) {
        std::string fpath = dir;
        fpath += frameWorkName;
        fpath += ".framework";
        std::string intPath = fpath;
        intPath += "/Headers/";
        intPath += fileName;
        if (cmSystemTools::FileExists(intPath.c_str())) {
          if (this->IncludeFileInPath) {
            return intPath;
          }
          return fpath;
        }
      }
    }
    // if it is not found yet or not a framework header, then do a glob search
    // for all frameworks in the directory: dir/*.framework/Headers/<file>
    std::string glob = dir;
    glob += "*.framework/Headers/";
    glob += file;
    cmsys::Glob globIt;
    globIt.FindFiles(glob);
    std::vector<std::string> files = globIt.GetFiles();
    if (!files.empty()) {
      std::string fheader = cmSystemTools::CollapseFullPath(files[0]);
      if (this->IncludeFileInPath) {
        return fheader;
      }
      fheader = cmSystemTools::GetFilenamePath(fheader);
      return fheader;
    }
    return "";
  }
  
  std::string cmFindPathCommand::FindNormalHeader()
  {
    std::string tryPath;
    for (std::vector<std::string>::const_iterator ni = this->Names.begin();
         ni != this->Names.end(); ++ni) {
      for (std::vector<std::string>::const_iterator p =
             this->SearchPaths.begin();
           p != this->SearchPaths.end(); ++p) {
        tryPath = *p;
        tryPath += *ni;
        if (cmSystemTools::FileExists(tryPath.c_str())) {
          if (this->IncludeFileInPath) {
            return tryPath;
          } else {
            return *p;
          }
        }
      }
    }
    return "";
  }
  
  std::string cmFindPathCommand::FindFrameworkHeader()
  {
    for (std::vector<std::string>::const_iterator ni = this->Names.begin();
         ni != this->Names.end(); ++ni) {
      for (std::vector<std::string>::const_iterator p =
             this->SearchPaths.begin();
           p != this->SearchPaths.end(); ++p) {
        std::string fwPath = this->FindHeaderInFramework(*ni, *p);
        if (!fwPath.empty()) {
          return fwPath;
        }
      }
    }
    return "";
  }
  