/*============================================================================
  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 "cmInstallCommand.h"

#include "cmInstallDirectoryGenerator.h"
#include "cmInstallFilesGenerator.h"
#include "cmInstallScriptGenerator.h"
#include "cmInstallTargetGenerator.h"
#include "cmInstallExportGenerator.h"
#include "cmInstallCommandArguments.h"
#include "cmTargetExport.h"
#include "cmExportSet.h"

#include <cmsys/Glob.hxx>

static cmInstallTargetGenerator* CreateInstallTargetGenerator(cmTarget& target,
     const cmInstallCommandArguments& args, bool impLib, bool forceOpt = false)
{
  cmInstallGenerator::MessageLevel message =
    cmInstallGenerator::SelectMessageLevel(target.GetMakefile());
  return new cmInstallTargetGenerator(target, args.GetDestination().c_str(),
                        impLib, args.GetPermissions().c_str(),
                        args.GetConfigurations(), args.GetComponent().c_str(),
                        message,
                        args.GetOptional() || forceOpt);
}

static cmInstallFilesGenerator* CreateInstallFilesGenerator(
  cmMakefile* mf,
    const std::vector<std::string>& absFiles,
    const cmInstallCommandArguments& args, bool programs)
{
  cmInstallGenerator::MessageLevel message =
    cmInstallGenerator::SelectMessageLevel(mf);
  return new cmInstallFilesGenerator(mf,
                        absFiles, args.GetDestination().c_str(),
                        programs, args.GetPermissions().c_str(),
                        args.GetConfigurations(), args.GetComponent().c_str(),
                        message,
                        args.GetRename().c_str(), args.GetOptional());
}


// cmInstallCommand
bool cmInstallCommand::InitialPass(std::vector<std::string> const& args,
                                   cmExecutionStatus &)
{
  // Allow calling with no arguments so that arguments may be built up
  // using a variable that may be left empty.
  if(args.empty())
    {
    return true;
    }

  // Enable the install target.
  this->Makefile->GetLocalGenerator()
    ->GetGlobalGenerator()->EnableInstallTarget();

  this->DefaultComponentName = this->Makefile->GetSafeDefinition(
                                       "CMAKE_INSTALL_DEFAULT_COMPONENT_NAME");
  if (this->DefaultComponentName.empty())
    {
    this->DefaultComponentName = "Unspecified";
    }

  // Switch among the command modes.
  if(args[0] == "SCRIPT")
    {
    return this->HandleScriptMode(args);
    }
  else if(args[0] == "CODE")
    {
    return this->HandleScriptMode(args);
    }
  else if(args[0] == "TARGETS")
    {
    return this->HandleTargetsMode(args);
    }
  else if(args[0] == "FILES")
    {
    return this->HandleFilesMode(args);
    }
  else if(args[0] == "PROGRAMS")
    {
    return this->HandleFilesMode(args);
    }
  else if(args[0] == "DIRECTORY")
    {
    return this->HandleDirectoryMode(args);
    }
  else if(args[0] == "EXPORT")
    {
    return this->HandleExportMode(args);
    }

  // Unknown mode.
  std::string e = "called with unknown mode ";
  e += args[0];
  this->SetError(e);
  return false;
}

//----------------------------------------------------------------------------
bool cmInstallCommand::HandleScriptMode(std::vector<std::string> const& args)
{
  std::string component = this->DefaultComponentName;
  int componentCount = 0;
  bool doing_script = false;
  bool doing_code = false;

  // Scan the args once for COMPONENT. Only allow one.
  //
  for(size_t i=0; i < args.size(); ++i)
    {
    if(args[i] == "COMPONENT" && i+1 < args.size())
        {
        ++componentCount;
        ++i;
        component = args[i];
        }
    }

  if(componentCount>1)
    {
    this->SetError("given more than one COMPONENT for the SCRIPT or CODE "
      "signature of the INSTALL command. "
      "Use multiple INSTALL commands with one COMPONENT each.");
    return false;
    }

  // Scan the args again, this time adding install generators each time we
  // encounter a SCRIPT or CODE arg:
  //
  for(size_t i=0; i < args.size(); ++i)
    {
    if(args[i] == "SCRIPT")
      {
      doing_script = true;
      doing_code = false;
      }
    else if(args[i] == "CODE")
      {
      doing_script = false;
      doing_code = true;
      }
    else if(args[i] == "COMPONENT")
      {
      doing_script = false;
      doing_code = false;
      }
    else if(doing_script)
      {
      doing_script = false;
      std::string script = args[i];
      if(!cmSystemTools::FileIsFullPath(script.c_str()))
        {
        script = this->Makefile->GetCurrentDirectory();
        script += "/";
        script += args[i];
        }
      if(cmSystemTools::FileIsDirectory(script))
        {
        this->SetError("given a directory as value of SCRIPT argument.");
        return false;
        }
      this->Makefile->AddInstallGenerator(
        new cmInstallScriptGenerator(script.c_str(), false,
                                     component.c_str()));
      }
    else if(doing_code)
      {
      doing_code = false;
      std::string code = args[i];
      this->Makefile->AddInstallGenerator(
        new cmInstallScriptGenerator(code.c_str(), true,
                                     component.c_str()));
      }
    }

  if(doing_script)
    {
    this->SetError("given no value for SCRIPT argument.");
    return false;
    }
  if(doing_code)
    {
    this->SetError("given no value for CODE argument.");
    return false;
    }

  //Tell the global generator about any installation component names specified.
  this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
                             ->AddInstallComponent(component.c_str());

  return true;
}


/*struct InstallPart
{
  InstallPart(cmCommandArgumentsHelper* helper, const char* key,
         cmCommandArgumentGroup* group);
  cmCAStringVector argVector;
  cmInstallCommandArguments args;
};*/

//----------------------------------------------------------------------------
bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
{
  // This is the TARGETS mode.
  std::vector<cmTarget*> targets;

  cmCommandArgumentsHelper argHelper;
  cmCommandArgumentGroup group;
  cmCAStringVector genericArgVector      (&argHelper,0);
  cmCAStringVector archiveArgVector      (&argHelper,"ARCHIVE",&group);
  cmCAStringVector libraryArgVector      (&argHelper,"LIBRARY",&group);
  cmCAStringVector runtimeArgVector      (&argHelper,"RUNTIME",&group);
  cmCAStringVector frameworkArgVector    (&argHelper,"FRAMEWORK",&group);
  cmCAStringVector bundleArgVector       (&argHelper,"BUNDLE",&group);
  cmCAStringVector includesArgVector     (&argHelper,"INCLUDES",&group);
  cmCAStringVector privateHeaderArgVector(&argHelper,"PRIVATE_HEADER",&group);
  cmCAStringVector publicHeaderArgVector (&argHelper,"PUBLIC_HEADER",&group);
  cmCAStringVector resourceArgVector     (&argHelper,"RESOURCE",&group);
  genericArgVector.Follows(0);
  group.Follows(&genericArgVector);

  argHelper.Parse(&args, 0);

  // now parse the generic args (i.e. the ones not specialized on LIBRARY/
  // ARCHIVE, RUNTIME etc. (see above)
  // These generic args also contain the targets and the export stuff
  std::vector<std::string> unknownArgs;
  cmInstallCommandArguments genericArgs(this->DefaultComponentName);
  cmCAStringVector targetList(&genericArgs.Parser, "TARGETS");
  cmCAString exports(&genericArgs.Parser,"EXPORT", &genericArgs.ArgumentGroup);
  targetList.Follows(0);
  genericArgs.ArgumentGroup.Follows(&targetList);
  genericArgs.Parse(&genericArgVector.GetVector(), &unknownArgs);
  bool success = genericArgs.Finalize();

  cmInstallCommandArguments archiveArgs(this->DefaultComponentName);
  cmInstallCommandArguments libraryArgs(this->DefaultComponentName);
  cmInstallCommandArguments runtimeArgs(this->DefaultComponentName);
  cmInstallCommandArguments frameworkArgs(this->DefaultComponentName);
  cmInstallCommandArguments bundleArgs(this->DefaultComponentName);
  cmInstallCommandArguments privateHeaderArgs(this->DefaultComponentName);
  cmInstallCommandArguments publicHeaderArgs(this->DefaultComponentName);
  cmInstallCommandArguments resourceArgs(this->DefaultComponentName);
  cmInstallCommandIncludesArgument includesArgs;

  // now parse the args for specific parts of the target (e.g. LIBRARY,
  // RUNTIME, ARCHIVE etc.
  archiveArgs.Parse      (&archiveArgVector.GetVector(),       &unknownArgs);
  libraryArgs.Parse      (&libraryArgVector.GetVector(),       &unknownArgs);
  runtimeArgs.Parse      (&runtimeArgVector.GetVector(),       &unknownArgs);
  frameworkArgs.Parse    (&frameworkArgVector.GetVector(),     &unknownArgs);
  bundleArgs.Parse       (&bundleArgVector.GetVector(),        &unknownArgs);
  privateHeaderArgs.Parse(&privateHeaderArgVector.GetVector(), &unknownArgs);
  publicHeaderArgs.Parse (&publicHeaderArgVector.GetVector(),  &unknownArgs);
  resourceArgs.Parse     (&resourceArgVector.GetVector(),      &unknownArgs);
  includesArgs.Parse     (&includesArgVector.GetVector(),      &unknownArgs);

  if(!unknownArgs.empty())
    {
    // Unknown argument.
    std::ostringstream e;
    e << "TARGETS given unknown argument \"" << unknownArgs[0] << "\".";
    this->SetError(e.str());
    return false;
    }

  // apply generic args
  archiveArgs.SetGenericArguments(&genericArgs);
  libraryArgs.SetGenericArguments(&genericArgs);
  runtimeArgs.SetGenericArguments(&genericArgs);
  frameworkArgs.SetGenericArguments(&genericArgs);
  bundleArgs.SetGenericArguments(&genericArgs);
  privateHeaderArgs.SetGenericArguments(&genericArgs);
  publicHeaderArgs.SetGenericArguments(&genericArgs);
  resourceArgs.SetGenericArguments(&genericArgs);

  success = success && archiveArgs.Finalize();
  success = success && libraryArgs.Finalize();
  success = success && runtimeArgs.Finalize();
  success = success && frameworkArgs.Finalize();
  success = success && bundleArgs.Finalize();
  success = success && privateHeaderArgs.Finalize();
  success = success && publicHeaderArgs.Finalize();
  success = success && resourceArgs.Finalize();

  if(!success)
    {
    return false;
    }

  // Enforce argument rules too complex to specify for the
  // general-purpose parser.
  if(archiveArgs.GetNamelinkOnly() ||
     runtimeArgs.GetNamelinkOnly() ||
     frameworkArgs.GetNamelinkOnly() ||
     bundleArgs.GetNamelinkOnly() ||
     privateHeaderArgs.GetNamelinkOnly() ||
     publicHeaderArgs.GetNamelinkOnly() ||
     resourceArgs.GetNamelinkOnly())
    {
    this->SetError(
      "TARGETS given NAMELINK_ONLY option not in LIBRARY group.  "
      "The NAMELINK_ONLY option may be specified only following LIBRARY."
      );
    return false;
    }
  if(archiveArgs.GetNamelinkSkip() ||
     runtimeArgs.GetNamelinkSkip() ||
     frameworkArgs.GetNamelinkSkip() ||
     bundleArgs.GetNamelinkSkip() ||
     privateHeaderArgs.GetNamelinkSkip() ||
     publicHeaderArgs.GetNamelinkSkip() ||
     resourceArgs.GetNamelinkSkip())
    {
    this->SetError(
      "TARGETS given NAMELINK_SKIP option not in LIBRARY group.  "
      "The NAMELINK_SKIP option may be specified only following LIBRARY."
      );
    return false;
    }
  if(libraryArgs.GetNamelinkOnly() && libraryArgs.GetNamelinkSkip())
    {
    this->SetError(
      "TARGETS given NAMELINK_ONLY and NAMELINK_SKIP.  "
      "At most one of these two options may be specified."
      );
    return false;
    }

  // Select the mode for installing symlinks to versioned shared libraries.
  cmInstallTargetGenerator::NamelinkModeType
    namelinkMode = cmInstallTargetGenerator::NamelinkModeNone;
  if(libraryArgs.GetNamelinkOnly())
    {
    namelinkMode = cmInstallTargetGenerator::NamelinkModeOnly;
    }
  else if(libraryArgs.GetNamelinkSkip())
    {
    namelinkMode = cmInstallTargetGenerator::NamelinkModeSkip;
    }

  // Check if there is something to do.
  if(targetList.GetVector().empty())
    {
    return true;
    }

  // Check whether this is a DLL platform.
  bool dll_platform = (this->Makefile->IsOn("WIN32") ||
                       this->Makefile->IsOn("CYGWIN") ||
                       this->Makefile->IsOn("MINGW"));

  for(std::vector<std::string>::const_iterator
      targetIt=targetList.GetVector().begin();
      targetIt!=targetList.GetVector().end();
      ++targetIt)
    {

    if (this->Makefile->IsAlias(*targetIt))
      {
      std::ostringstream e;
      e << "TARGETS given target \"" << (*targetIt)
        << "\" which is an alias.";
      this->SetError(e.str());
      return false;
      }
    // Lookup this target in the current directory.
    if(cmTarget* target=this->Makefile->FindTarget(*targetIt))
      {
      // Found the target.  Check its type.
      if(target->GetType() != cmTarget::EXECUTABLE &&
         target->GetType() != cmTarget::STATIC_LIBRARY &&
         target->GetType() != cmTarget::SHARED_LIBRARY &&
         target->GetType() != cmTarget::MODULE_LIBRARY &&
         target->GetType() != cmTarget::OBJECT_LIBRARY &&
         target->GetType() != cmTarget::INTERFACE_LIBRARY)
        {
        std::ostringstream e;
        e << "TARGETS given target \"" << (*targetIt)
          << "\" which is not an executable, library, or module.";
        this->SetError(e.str());
        return false;
        }
      else if(target->GetType() == cmTarget::OBJECT_LIBRARY)
        {
        std::ostringstream e;
        e << "TARGETS given OBJECT library \"" << (*targetIt)
          << "\" which may not be installed.";
        this->SetError(e.str());
        return false;
        }
      // Store the target in the list to be installed.
      targets.push_back(target);
      }
    else
      {
      // Did not find the target.
      std::ostringstream e;
      e << "TARGETS given target \"" << (*targetIt)
        << "\" which does not exist in this directory.";
      this->SetError(e.str());
      return false;
      }
    }

  // Keep track of whether we will be performing an installation of
  // any files of the given type.
  bool installsArchive = false;
  bool installsLibrary = false;
  bool installsRuntime = false;
  bool installsFramework = false;
  bool installsBundle = false;
  bool installsPrivateHeader = false;
  bool installsPublicHeader = false;
  bool installsResource = false;

  // Generate install script code to install the given targets.
  for(std::vector<cmTarget*>::iterator ti = targets.begin();
      ti != targets.end(); ++ti)
    {
    // Handle each target type.
    cmTarget& target = *(*ti);
    cmInstallTargetGenerator* archiveGenerator = 0;
    cmInstallTargetGenerator* libraryGenerator = 0;
    cmInstallTargetGenerator* runtimeGenerator = 0;
    cmInstallTargetGenerator* frameworkGenerator = 0;
    cmInstallTargetGenerator* bundleGenerator = 0;
    cmInstallFilesGenerator* privateHeaderGenerator = 0;
    cmInstallFilesGenerator* publicHeaderGenerator = 0;
    cmInstallFilesGenerator* resourceGenerator = 0;

    // Track whether this is a namelink-only rule.
    bool namelinkOnly = false;

    switch(target.GetType())
      {
      case cmTarget::SHARED_LIBRARY:
        {
        // Shared libraries are handled differently on DLL and non-DLL
        // platforms.  All windows platforms are DLL platforms including
        // cygwin.  Currently no other platform is a DLL platform.
        if(dll_platform)
          {
          // When in namelink only mode skip all libraries on Windows.
          if(namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly)
            {
            continue;
            }

          // This is a DLL platform.
          if(!archiveArgs.GetDestination().empty())
            {
            // The import library uses the ARCHIVE properties.
            archiveGenerator = CreateInstallTargetGenerator(target,
                                                            archiveArgs, true);
            }
          if(!runtimeArgs.GetDestination().empty())
            {
            // The DLL uses the RUNTIME properties.
            runtimeGenerator = CreateInstallTargetGenerator(target,
                                                           runtimeArgs, false);
            }
          if ((archiveGenerator==0) && (runtimeGenerator==0))
            {
            this->SetError("Library TARGETS given no DESTINATION!");
            return false;
            }
          }
        else
          {
          // This is a non-DLL platform.
          // If it is marked with FRAMEWORK property use the FRAMEWORK set of
          // INSTALL properties. Otherwise, use the LIBRARY properties.
          if(target.IsFrameworkOnApple())
            {
            // When in namelink only mode skip frameworks.
            if(namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly)
              {
              continue;
              }

            // Use the FRAMEWORK properties.
            if (!frameworkArgs.GetDestination().empty())
              {
              frameworkGenerator = CreateInstallTargetGenerator(target,
                                                         frameworkArgs, false);
              }
            else
              {
              std::ostringstream e;
              e << "TARGETS given no FRAMEWORK DESTINATION for shared library "
                "FRAMEWORK target \"" << target.GetName() << "\".";
              this->SetError(e.str());
              return false;
              }
            }
          else
            {
            // The shared library uses the LIBRARY properties.
            if (!libraryArgs.GetDestination().empty())
              {
              libraryGenerator = CreateInstallTargetGenerator(target,
                                                           libraryArgs, false);
              libraryGenerator->SetNamelinkMode(namelinkMode);
              namelinkOnly =
                (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly);
              }
            else
              {
              std::ostringstream e;
              e << "TARGETS given no LIBRARY DESTINATION for shared library "
                "target \"" << target.GetName() << "\".";
              this->SetError(e.str());
              return false;
              }
            }
          }
        }
        break;
      case cmTarget::STATIC_LIBRARY:
        {
        // Static libraries use ARCHIVE properties.
        if (!archiveArgs.GetDestination().empty())
          {
          archiveGenerator = CreateInstallTargetGenerator(target, archiveArgs,
                                                          false);
          }
        else
          {
          std::ostringstream e;
          e << "TARGETS given no ARCHIVE DESTINATION for static library "
            "target \"" << target.GetName() << "\".";
          this->SetError(e.str());
          return false;
          }
        }
        break;
      case cmTarget::MODULE_LIBRARY:
        {
        // Modules use LIBRARY properties.
        if (!libraryArgs.GetDestination().empty())
          {
          libraryGenerator = CreateInstallTargetGenerator(target, libraryArgs,
                                                          false);
          libraryGenerator->SetNamelinkMode(namelinkMode);
          namelinkOnly =
            (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly);
          }
        else
          {
          std::ostringstream e;
          e << "TARGETS given no LIBRARY DESTINATION for module target \""
            << target.GetName() << "\".";
          this->SetError(e.str());
          return false;
          }
        }
        break;
      case cmTarget::EXECUTABLE:
        {
        if(target.IsAppBundleOnApple())
          {
          // Application bundles use the BUNDLE properties.
          if (!bundleArgs.GetDestination().empty())
            {
            bundleGenerator = CreateInstallTargetGenerator(target, bundleArgs,
                                                           false);
            }
          else if(!runtimeArgs.GetDestination().empty())
            {
            bool failure = false;
            if(this->CheckCMP0006(failure))
              {
              // For CMake 2.4 compatibility fallback to the RUNTIME
              // properties.
              bundleGenerator =
                CreateInstallTargetGenerator(target, runtimeArgs, false);
              }
            else if(failure)
              {
              return false;
              }
            }
          if(!bundleGenerator)
            {
            std::ostringstream e;
            e << "TARGETS given no BUNDLE DESTINATION for MACOSX_BUNDLE "
                 "executable target \"" << target.GetName() << "\".";
            this->SetError(e.str());
            return false;
            }
          }
        else
          {
          // Executables use the RUNTIME properties.
          if (!runtimeArgs.GetDestination().empty())
            {
            runtimeGenerator = CreateInstallTargetGenerator(target,
                                                           runtimeArgs, false);
            }
          else
            {
            std::ostringstream e;
            e << "TARGETS given no RUNTIME DESTINATION for executable "
                 "target \"" << target.GetName() << "\".";
            this->SetError(e.str());
            return false;
            }
          }

        // On DLL platforms an executable may also have an import
        // library.  Install it to the archive destination if it
        // exists.
        if(dll_platform && !archiveArgs.GetDestination().empty() &&
           target.IsExecutableWithExports())
          {
          // The import library uses the ARCHIVE properties.
          archiveGenerator = CreateInstallTargetGenerator(target,
                                                      archiveArgs, true, true);
          }
        }
        break;
      case cmTarget::INTERFACE_LIBRARY:
          // Nothing to do. An INTERFACE_LIBRARY can be installed, but the
          // only effect of that is to make it exportable. It installs no
          // other files itself.
        break;
      default:
        // This should never happen due to the above type check.
        // Ignore the case.
        break;
      }

    // These well-known sets of files are installed *automatically* for
    // FRAMEWORK SHARED library targets on the Mac as part of installing the
    // FRAMEWORK.  For other target types or on other platforms, they are not
    // installed automatically and so we need to create install files
    // generators for them.
    bool createInstallGeneratorsForTargetFileSets = true;

    if(target.IsFrameworkOnApple()
        || target.GetType() == cmTarget::INTERFACE_LIBRARY)
      {
      createInstallGeneratorsForTargetFileSets = false;
      }

    if(createInstallGeneratorsForTargetFileSets && !namelinkOnly)
      {
      const char* files = target.GetProperty("PRIVATE_HEADER");
      if ((files) && (*files))
        {
        std::vector<std::string> relFiles;
        cmSystemTools::ExpandListArgument(files, relFiles);
        std::vector<std::string> absFiles;
        if (!this->MakeFilesFullPath("PRIVATE_HEADER", relFiles, absFiles))
          {
          return false;
          }

        // Create the files install generator.
        if (!privateHeaderArgs.GetDestination().empty())
          {
          privateHeaderGenerator =
            CreateInstallFilesGenerator(this->Makefile, absFiles,
                                        privateHeaderArgs, false);
          }
        else
          {
          std::ostringstream e;
          e << "INSTALL TARGETS - target " << target.GetName() << " has "
            << "PRIVATE_HEADER files but no PRIVATE_HEADER DESTINATION.";
          cmSystemTools::Message(e.str().c_str(), "Warning");
          }
        }

      files = target.GetProperty("PUBLIC_HEADER");
      if ((files) && (*files))
        {
        std::vector<std::string> relFiles;
        cmSystemTools::ExpandListArgument(files, relFiles);
        std::vector<std::string> absFiles;
        if (!this->MakeFilesFullPath("PUBLIC_HEADER", relFiles, absFiles))
          {
          return false;
          }

        // Create the files install generator.
        if (!publicHeaderArgs.GetDestination().empty())
          {
          publicHeaderGenerator =
            CreateInstallFilesGenerator(this->Makefile, absFiles,
                                        publicHeaderArgs, false);
          }
        else
          {
          std::ostringstream e;
          e << "INSTALL TARGETS - target " << target.GetName() << " has "
            << "PUBLIC_HEADER files but no PUBLIC_HEADER DESTINATION.";
          cmSystemTools::Message(e.str().c_str(), "Warning");
          }
        }

      files = target.GetProperty("RESOURCE");
      if ((files) && (*files))
        {
        std::vector<std::string> relFiles;
        cmSystemTools::ExpandListArgument(files, relFiles);
        std::vector<std::string> absFiles;
        if (!this->MakeFilesFullPath("RESOURCE", relFiles, absFiles))
          {
          return false;
          }

        // Create the files install generator.
        if (!resourceArgs.GetDestination().empty())
          {
          resourceGenerator = CreateInstallFilesGenerator(
            this->Makefile, absFiles, resourceArgs, false);
          }
        else
          {
          std::ostringstream e;
          e << "INSTALL TARGETS - target " << target.GetName() << " has "
            << "RESOURCE files but no RESOURCE DESTINATION.";
          cmSystemTools::Message(e.str().c_str(), "Warning");
          }
        }
      }

    // Keep track of whether we're installing anything in each category
    installsArchive = installsArchive || archiveGenerator != 0;
    installsLibrary = installsLibrary || libraryGenerator != 0;
    installsRuntime = installsRuntime || runtimeGenerator != 0;
    installsFramework = installsFramework || frameworkGenerator != 0;
    installsBundle = installsBundle || bundleGenerator != 0;
    installsPrivateHeader = installsPrivateHeader
      || privateHeaderGenerator != 0;
    installsPublicHeader = installsPublicHeader || publicHeaderGenerator != 0;
    installsResource = installsResource || resourceGenerator;

    this->Makefile->AddInstallGenerator(archiveGenerator);
    this->Makefile->AddInstallGenerator(libraryGenerator);
    this->Makefile->AddInstallGenerator(runtimeGenerator);
    this->Makefile->AddInstallGenerator(frameworkGenerator);
    this->Makefile->AddInstallGenerator(bundleGenerator);
    this->Makefile->AddInstallGenerator(privateHeaderGenerator);
    this->Makefile->AddInstallGenerator(publicHeaderGenerator);
    this->Makefile->AddInstallGenerator(resourceGenerator);

    // Add this install rule to an export if one was specified and
    // this is not a namelink-only rule.
    if(!exports.GetString().empty() && !namelinkOnly)
      {
      cmTargetExport *te = new cmTargetExport;
      te->Target = &target;
      te->ArchiveGenerator = archiveGenerator;
      te->BundleGenerator = bundleGenerator;
      te->FrameworkGenerator = frameworkGenerator;
      te->HeaderGenerator = publicHeaderGenerator;
      te->LibraryGenerator = libraryGenerator;
      te->RuntimeGenerator = runtimeGenerator;
      this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
        ->GetExportSets()[exports.GetString()]->AddTargetExport(te);

      te->InterfaceIncludeDirectories =
          cmJoin(includesArgs.GetIncludeDirs(), ";");
      }
    }

  // Tell the global generator about any installation component names
  // specified
  if (installsArchive)
    {
    this->Makefile->GetLocalGenerator()->
      GetGlobalGenerator()
      ->AddInstallComponent(archiveArgs.GetComponent().c_str());
    }
  if (installsLibrary)
    {
    this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
      ->AddInstallComponent(libraryArgs.GetComponent().c_str());
    }
  if (installsRuntime)
    {
    this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
      ->AddInstallComponent(runtimeArgs.GetComponent().c_str());
    }
  if (installsFramework)
    {
    this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
      ->AddInstallComponent(frameworkArgs.GetComponent().c_str());
    }
  if (installsBundle)
    {
    this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
      ->AddInstallComponent(bundleArgs.GetComponent().c_str());
    }
  if (installsPrivateHeader)
    {
    this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
      ->AddInstallComponent(privateHeaderArgs.GetComponent().c_str());
    }
  if (installsPublicHeader)
    {
    this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
      ->AddInstallComponent(publicHeaderArgs.GetComponent().c_str());
    }
  if (installsResource)
    {
    this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
      ->AddInstallComponent(resourceArgs.GetComponent().c_str());
    }

  return true;
}

//----------------------------------------------------------------------------
bool cmInstallCommand::HandleFilesMode(std::vector<std::string> const& args)
{
  // This is the FILES mode.
  bool programs = (args[0] == "PROGRAMS");
  cmInstallCommandArguments ica(this->DefaultComponentName);
  cmCAStringVector files(&ica.Parser, programs ? "PROGRAMS" : "FILES");
  files.Follows(0);
  ica.ArgumentGroup.Follows(&files);
  std::vector<std::string> unknownArgs;
  ica.Parse(&args, &unknownArgs);

  if(!unknownArgs.empty())
    {
    // Unknown argument.
    std::ostringstream e;
    e << args[0] << " given unknown argument \"" << unknownArgs[0] << "\".";
    this->SetError(e.str());
    return false;
    }

  // Check if there is something to do.
  if(files.GetVector().empty())
    {
    return true;
    }

  if(!ica.GetRename().empty() && files.GetVector().size() > 1)
    {
    // The rename option works only with one file.
    std::ostringstream e;
    e << args[0] << " given RENAME option with more than one file.";
    this->SetError(e.str());
    return false;
    }

  std::vector<std::string> absFiles;
  if (!this->MakeFilesFullPath(args[0].c_str(), files.GetVector(), absFiles))
    {
    return false;
    }

  if (!ica.Finalize())
    {
    return false;
    }

  if(ica.GetDestination().empty())
    {
    // A destination is required.
    std::ostringstream e;
    e << args[0] << " given no DESTINATION!";
    this->SetError(e.str());
    return false;
    }

  // Create the files install generator.
  this->Makefile->AddInstallGenerator(
    CreateInstallFilesGenerator(this->Makefile, absFiles, ica, programs));

  //Tell the global generator about any installation component names specified.
  this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
                             ->AddInstallComponent(ica.GetComponent().c_str());

  return true;
}

//----------------------------------------------------------------------------
bool
cmInstallCommand::HandleDirectoryMode(std::vector<std::string> const& args)
{
  enum Doing { DoingNone, DoingDirs, DoingDestination, DoingPattern,
               DoingRegex, DoingPermsFile, DoingPermsDir, DoingPermsMatch,
               DoingConfigurations, DoingComponent };
  Doing doing = DoingDirs;
  bool in_match_mode = false;
  bool optional = false;
  bool message_never = false;
  std::vector<std::string> dirs;
  const char* destination = 0;
  std::string permissions_file;
  std::string permissions_dir;
  std::vector<std::string> configurations;
  std::string component = this->DefaultComponentName;
  std::string literal_args;
  for(unsigned int i=1; i < args.size(); ++i)
    {
    if(args[i] == "DESTINATION")
      {
      if(in_match_mode)
        {
        std::ostringstream e;
        e << args[0] << " does not allow \""
          << args[i] << "\" after PATTERN or REGEX.";
        this->SetError(e.str());
        return false;
        }

      // Switch to setting the destination property.
      doing = DoingDestination;
      }
    else if(args[i] == "OPTIONAL")
      {
      if(in_match_mode)
        {
        std::ostringstream e;
        e << args[0] << " does not allow \""
          << args[i] << "\" after PATTERN or REGEX.";
        this->SetError(e.str());
        return false;
        }

      // Mark the rule as optional.
      optional = true;
      doing = DoingNone;
      }
    else if(args[i] == "MESSAGE_NEVER")
      {
      if(in_match_mode)
        {
        std::ostringstream e;
        e << args[0] << " does not allow \""
          << args[i] << "\" after PATTERN or REGEX.";
        this->SetError(e.str());
        return false;
        }

      // Mark the rule as quiet.
      message_never = true;
      doing = DoingNone;
      }
    else if(args[i] == "PATTERN")
      {
      // Switch to a new pattern match rule.
      doing = DoingPattern;
      in_match_mode = true;
      }
    else if(args[i] == "REGEX")
      {
      // Switch to a new regex match rule.
      doing = DoingRegex;
      in_match_mode = true;
      }
    else if(args[i] == "EXCLUDE")
      {
      // Add this property to the current match rule.
      if(!in_match_mode || doing == DoingPattern || doing == DoingRegex)
        {
        std::ostringstream e;
        e << args[0] << " does not allow \""
          << args[i] << "\" before a PATTERN or REGEX is given.";
        this->SetError(e.str());
        return false;
        }
      literal_args += " EXCLUDE";
      doing = DoingNone;
      }
    else if(args[i] == "PERMISSIONS")
      {
      if(!in_match_mode)
        {
        std::ostringstream e;
        e << args[0] << " does not allow \""
          << args[i] << "\" before a PATTERN or REGEX is given.";
        this->SetError(e.str());
        return false;
        }

      // Switch to setting the current match permissions property.
      literal_args += " PERMISSIONS";
      doing = DoingPermsMatch;
      }
    else if(args[i] == "FILE_PERMISSIONS")
      {
      if(in_match_mode)
        {
        std::ostringstream e;
        e << args[0] << " does not allow \""
          << args[i] << "\" after PATTERN or REGEX.";
        this->SetError(e.str());
        return false;
        }

      // Switch to setting the file permissions property.
      doing = DoingPermsFile;
      }
    else if(args[i] == "DIRECTORY_PERMISSIONS")
      {
      if(in_match_mode)
        {
        std::ostringstream e;
        e << args[0] << " does not allow \""
          << args[i] << "\" after PATTERN or REGEX.";
        this->SetError(e.str());
        return false;
        }

      // Switch to setting the directory permissions property.
      doing = DoingPermsDir;
      }
    else if(args[i] == "USE_SOURCE_PERMISSIONS")
      {
      if(in_match_mode)
        {
        std::ostringstream e;
        e << args[0] << " does not allow \""
          << args[i] << "\" after PATTERN or REGEX.";
        this->SetError(e.str());
        return false;
        }

      // Add this option literally.
      literal_args += " USE_SOURCE_PERMISSIONS";
      doing = DoingNone;
      }
    else if(args[i] == "FILES_MATCHING")
      {
      if(in_match_mode)
        {
        std::ostringstream e;
        e << args[0] << " does not allow \""
          << args[i] << "\" after PATTERN or REGEX.";
        this->SetError(e.str());
        return false;
        }

      // Add this option literally.
      literal_args += " FILES_MATCHING";
      doing = DoingNone;
      }
    else if(args[i] == "CONFIGURATIONS")
      {
      if(in_match_mode)
        {
        std::ostringstream e;
        e << args[0] << " does not allow \""
          << args[i] << "\" after PATTERN or REGEX.";
        this->SetError(e.str());
        return false;
        }

      // Switch to setting the configurations property.
      doing = DoingConfigurations;
      }
    else if(args[i] == "COMPONENT")
      {
      if(in_match_mode)
        {
        std::ostringstream e;
        e << args[0] << " does not allow \""
          << args[i] << "\" after PATTERN or REGEX.";
        this->SetError(e.str());
        return false;
        }

      // Switch to setting the component property.
      doing = DoingComponent;
      }
    else if(doing == DoingDirs)
      {
      // Convert this directory to a full path.
      std::string dir = args[i];
      if(!cmSystemTools::FileIsFullPath(dir.c_str()))
        {
        dir = this->Makefile->GetCurrentDirectory();
        dir += "/";
        dir += args[i];
        }

      // Make sure the name is a directory.
      if(cmSystemTools::FileExists(dir.c_str()) &&
         !cmSystemTools::FileIsDirectory(dir))
        {
        std::ostringstream e;
        e << args[0] << " given non-directory \""
          << args[i] << "\" to install.";
        this->SetError(e.str());
        return false;
        }

      // Store the directory for installation.
      dirs.push_back(dir);
      }
    else if(doing == DoingConfigurations)
      {
      configurations.push_back(args[i]);
      }
    else if(doing == DoingDestination)
      {
      destination = args[i].c_str();
      doing = DoingNone;
      }
    else if(doing == DoingPattern)
      {
      // Convert the pattern to a regular expression.  Require a
      // leading slash and trailing end-of-string in the matched
      // string to make sure the pattern matches only whole file
      // names.
      literal_args += " REGEX \"/";
      std::string regex = cmsys::Glob::PatternToRegex(args[i], false);
      cmSystemTools::ReplaceString(regex, "\\", "\\\\");
      literal_args += regex;
      literal_args += "$\"";
      doing = DoingNone;
      }
    else if(doing == DoingRegex)
      {
      literal_args += " REGEX \"";
    // Match rules are case-insensitive on some platforms.
#if defined(_WIN32) || defined(__APPLE__) || defined(__CYGWIN__)
      std::string regex = cmSystemTools::LowerCase(args[i]);
#else
      std::string regex = args[i];
#endif
      cmSystemTools::ReplaceString(regex, "\\", "\\\\");
      literal_args += regex;
      literal_args += "\"";
      doing = DoingNone;
      }
    else if(doing == DoingComponent)
      {
      component = args[i];
      doing = DoingNone;
      }
    else if(doing == DoingPermsFile)
     {
     // Check the requested permission.
     if(!cmInstallCommandArguments::CheckPermissions(args[i],permissions_file))
        {
        std::ostringstream e;
        e << args[0] << " given invalid file permission \""
          << args[i] << "\".";
        this->SetError(e.str());
        return false;
        }
      }
    else if(doing == DoingPermsDir)
      {
      // Check the requested permission.
      if(!cmInstallCommandArguments::CheckPermissions(args[i],permissions_dir))
        {
        std::ostringstream e;
        e << args[0] << " given invalid directory permission \""
          << args[i] << "\".";
        this->SetError(e.str());
        return false;
        }
      }
    else if(doing == DoingPermsMatch)
      {
      // Check the requested permission.
      if(!cmInstallCommandArguments::CheckPermissions(args[i], literal_args))
        {
        std::ostringstream e;
        e << args[0] << " given invalid permission \""
          << args[i] << "\".";
        this->SetError(e.str());
        return false;
        }
      }
    else
      {
      // Unknown argument.
      std::ostringstream e;
      e << args[0] << " given unknown argument \"" << args[i] << "\".";
      this->SetError(e.str());
      return false;
      }
    }

  // Support installing an empty directory.
  if(dirs.empty() && destination)
    {
    dirs.push_back("");
    }

  // Check if there is something to do.
  if(dirs.empty())
    {
    return true;
    }
  if(!destination)
    {
    // A destination is required.
    std::ostringstream e;
    e << args[0] << " given no DESTINATION!";
    this->SetError(e.str());
    return false;
    }

  cmInstallGenerator::MessageLevel message =
    cmInstallGenerator::SelectMessageLevel(this->Makefile, message_never);

  // Create the directory install generator.
  this->Makefile->AddInstallGenerator(
    new cmInstallDirectoryGenerator(dirs, destination,
                                    permissions_file.c_str(),
                                    permissions_dir.c_str(),
                                    configurations,
                                    component.c_str(),
                                    message,
                                    literal_args.c_str(),
                                    optional));

  // Tell the global generator about any installation component names
  // specified.
  this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
    ->AddInstallComponent(component.c_str());

  return true;
}

//----------------------------------------------------------------------------
bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args)
{
  // This is the EXPORT mode.
  cmInstallCommandArguments ica(this->DefaultComponentName);
  cmCAString exp(&ica.Parser, "EXPORT");
  cmCAString name_space(&ica.Parser, "NAMESPACE", &ica.ArgumentGroup);
  cmCAEnabler exportOld(&ica.Parser, "EXPORT_LINK_INTERFACE_LIBRARIES",
                        &ica.ArgumentGroup);
  cmCAString filename(&ica.Parser, "FILE", &ica.ArgumentGroup);
  exp.Follows(0);

  ica.ArgumentGroup.Follows(&exp);
  std::vector<std::string> unknownArgs;
  ica.Parse(&args, &unknownArgs);

  if (!unknownArgs.empty())
    {
    // Unknown argument.
    std::ostringstream e;
    e << args[0] << " given unknown argument \"" << unknownArgs[0] << "\".";
    this->SetError(e.str());
    return false;
    }

  if (!ica.Finalize())
    {
    return false;
    }

  // Make sure there is a destination.
  if(ica.GetDestination().empty())
    {
    // A destination is required.
    std::ostringstream e;
    e << args[0] << " given no DESTINATION!";
    this->SetError(e.str());
    return false;
    }

  // Check the file name.
  std::string fname = filename.GetString();
  if(fname.find_first_of(":/\\") != fname.npos)
    {
    std::ostringstream e;
    e << args[0] << " given invalid export file name \"" << fname << "\".  "
      << "The FILE argument may not contain a path.  "
      << "Specify the path in the DESTINATION argument.";
    this->SetError(e.str());
    return false;
    }

  // Check the file extension.
  if(!fname.empty() &&
     cmSystemTools::GetFilenameLastExtension(fname) != ".cmake")
    {
    std::ostringstream e;
    e << args[0] << " given invalid export file name \"" << fname << "\".  "
      << "The FILE argument must specify a name ending in \".cmake\".";
    this->SetError(e.str());
    return false;
    }

  // Construct the file name.
  if(fname.empty())
    {
    fname = exp.GetString();
    fname += ".cmake";

    if(fname.find_first_of(":/\\") != fname.npos)
      {
      std::ostringstream e;
      e << args[0] << " given export name \"" << exp.GetString() << "\".  "
        << "This name cannot be safely converted to a file name.  "
        << "Specify a different export name or use the FILE option to set "
        << "a file name explicitly.";
      this->SetError(e.str());
      return false;
      }
    }

  cmExportSet *exportSet = this->Makefile->GetLocalGenerator()
                    ->GetGlobalGenerator()->GetExportSets()[exp.GetString()];
  if (exportOld.IsEnabled())
    {
    for(std::vector<cmTargetExport*>::const_iterator
          tei = exportSet->GetTargetExports()->begin();
        tei != exportSet->GetTargetExports()->end(); ++tei)
      {
      cmTargetExport const* te = *tei;
      const bool newCMP0022Behavior =
                      te->Target->GetPolicyStatusCMP0022() != cmPolicies::WARN
                   && te->Target->GetPolicyStatusCMP0022() != cmPolicies::OLD;

      if(!newCMP0022Behavior)
        {
        std::ostringstream e;
        e << "INSTALL(EXPORT) given keyword \""
          << "EXPORT_LINK_INTERFACE_LIBRARIES" << "\", but target \""
          << te->Target->GetName()
          << "\" does not have policy CMP0022 set to NEW.";
        this->SetError(e.str());
        return false;
        }
      }
    }

  cmInstallGenerator::MessageLevel message =
    cmInstallGenerator::SelectMessageLevel(this->Makefile);

  // Create the export install generator.
  cmInstallExportGenerator* exportGenerator =
    new cmInstallExportGenerator(
      exportSet,
      ica.GetDestination().c_str(),
      ica.GetPermissions().c_str(), ica.GetConfigurations(),
      ica.GetComponent().c_str(), message, fname.c_str(),
      name_space.GetCString(), exportOld.IsEnabled(), this->Makefile);
  this->Makefile->AddInstallGenerator(exportGenerator);

  return true;
}

bool cmInstallCommand::MakeFilesFullPath(const char* modeName,
                                      const std::vector<std::string>& relFiles,
                                      std::vector<std::string>& absFiles)
{
  for(std::vector<std::string>::const_iterator fileIt = relFiles.begin();
      fileIt != relFiles.end();
      ++fileIt)
    {
    std::string file = (*fileIt);
    std::string::size_type gpos = cmGeneratorExpression::Find(file);
    if(gpos != 0 && !cmSystemTools::FileIsFullPath(file.c_str()))
      {
      file = this->Makefile->GetCurrentDirectory();
      file += "/";
      file += *fileIt;
      }

    // Make sure the file is not a directory.
    if(gpos == file.npos && cmSystemTools::FileIsDirectory(file))
      {
      std::ostringstream e;
      e << modeName << " given directory \"" << (*fileIt) << "\" to install.";
      this->SetError(e.str());
      return false;
      }
    // Store the file for installation.
    absFiles.push_back(file);
    }
  return true;
}

//----------------------------------------------------------------------------
bool cmInstallCommand::CheckCMP0006(bool& failure)
{
  switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0006))
    {
    case cmPolicies::WARN:
      {
      this->Makefile->IssueMessage(
        cmake::AUTHOR_WARNING,
        this->Makefile->GetPolicies()->GetPolicyWarning(cmPolicies::CMP0006)
        );
      }
    case cmPolicies::OLD:
      // OLD behavior is to allow compatibility
      return true;
    case cmPolicies::NEW:
      // NEW behavior is to disallow compatibility
      break;
    case cmPolicies::REQUIRED_IF_USED:
    case cmPolicies::REQUIRED_ALWAYS:
      failure = true;
      this->Makefile->IssueMessage(
        cmake::FATAL_ERROR,
        this->Makefile->GetPolicies()
        ->GetRequiredPolicyError(cmPolicies::CMP0006)
        );
      break;
    }
  return false;
}
