Browse Source

Merge topic 'extract-cmOutputConverter'

59e21ffa Port static calls from cmLocalGenerator to cmOutputConverter.
242dcc2c cmListFileBacktrace: Replace local generator with cmState::Snapshot.
1cff330b cmTarget: Port to cmOutputConverter.
2f1bd62b cmCustomCommandGenerator: Port to cmOutputConverter.
0f2a1324 cmCommandArgumentParserHelper: Port to cmOutputConverter.
4d8b79ad cmComputeLinkInformation: Port to cmOutputConverter.
8680520f cmMakefile: Make the cmState::Snapshot accessible.
6d7abb63 cmOutputConverter: Extract from cmLocalGenerator.
a8244157 cmState::Snapshot: Provide accessor for the cmState.
1f4ef396 cmLocalGenerator: Remove some commented lines of code.
Brad King 10 years ago
parent
commit
d18852d596

+ 2 - 0
Source/CMakeLists.txt

@@ -300,6 +300,8 @@ set(SRCS
   cmMakefileUtilityTargetGenerator.cxx
   cmOSXBundleGenerator.cxx
   cmOSXBundleGenerator.h
+  cmOutputConverter.cxx
+  cmOutputConverter.h
   cmNewLineStyle.h
   cmNewLineStyle.cxx
   cmOrderDirectories.cxx

+ 4 - 4
Source/cmCPackPropertiesGenerator.cxx

@@ -1,6 +1,6 @@
 #include "cmCPackPropertiesGenerator.h"
 
-#include "cmLocalGenerator.h"
+#include "cmOutputConverter.h"
 
 cmCPackPropertiesGenerator::cmCPackPropertiesGenerator(
   cmMakefile* mf,
@@ -29,15 +29,15 @@ void cmCPackPropertiesGenerator::GenerateScriptForConfig(std::ostream& os,
     cmInstalledFile::Property const& property = i->second;
 
     os << indent << "set_property(INSTALL " <<
-      cmLocalGenerator::EscapeForCMake(expandedFileName) << " PROPERTY " <<
-      cmLocalGenerator::EscapeForCMake(name);
+      cmOutputConverter::EscapeForCMake(expandedFileName) << " PROPERTY " <<
+      cmOutputConverter::EscapeForCMake(name);
 
     for(cmInstalledFile::ExpressionVectorType::const_iterator
       j = property.ValueExpressions.begin();
       j != property.ValueExpressions.end(); ++j)
       {
       std::string value = (*j)->Evaluate(this->Makefile, config);
-      os << " " << cmLocalGenerator::EscapeForCMake(value);
+      os << " " << cmOutputConverter::EscapeForCMake(value);
       }
 
     os << ")\n";

+ 4 - 3
Source/cmCommandArgumentParserHelper.cxx

@@ -14,7 +14,7 @@
 #include "cmSystemTools.h"
 #include "cmMakefile.h"
 #include "cmState.h"
-#include "cmLocalGenerator.h"
+#include "cmOutputConverter.h"
 
 #include "cmCommandArgumentLexer.h"
 
@@ -141,8 +141,9 @@ char* cmCommandArgumentParserHelper::ExpandVariable(const char* var)
         {
         std::ostringstream msg;
         cmListFileContext lfc;
-        lfc.FilePath = this->Makefile->GetLocalGenerator()
-            ->Convert(this->FileName, cmLocalGenerator::HOME);
+        cmOutputConverter converter(this->Makefile->GetStateSnapshot());
+        lfc.FilePath = converter.Convert(this->FileName,
+                                         cmOutputConverter::HOME);
 
         lfc.Line = this->FileLine;
         msg << "uninitialized variable \'" << var << "\'";

+ 3 - 3
Source/cmComputeLinkInformation.cxx

@@ -16,7 +16,7 @@
 
 #include "cmGlobalGenerator.h"
 #include "cmState.h"
-#include "cmLocalGenerator.h"
+#include "cmOutputConverter.h"
 #include "cmMakefile.h"
 #include "cmTarget.h"
 #include "cmake.h"
@@ -246,7 +246,6 @@ cmComputeLinkInformation
   // Store context information.
   this->Target = target;
   this->Makefile = this->Target->GetMakefile();
-  this->LocalGenerator = this->Makefile->GetLocalGenerator();
   this->GlobalGenerator = this->Makefile->GetGlobalGenerator();
   this->CMakeInstance = this->GlobalGenerator->GetCMakeInstance();
 
@@ -1395,7 +1394,8 @@ void cmComputeLinkInformation::AddFrameworkItem(std::string const& item)
 
   // Add the item using the -framework option.
   this->Items.push_back(Item("-framework", false));
-  fw = this->LocalGenerator->EscapeForShell(fw);
+  cmOutputConverter converter(this->Makefile->GetStateSnapshot());
+  fw = converter.EscapeForShell(fw);
   this->Items.push_back(Item(fw, false));
 }
 

+ 0 - 2
Source/cmComputeLinkInformation.h

@@ -18,7 +18,6 @@
 
 class cmake;
 class cmGlobalGenerator;
-class cmLocalGenerator;
 class cmMakefile;
 class cmTarget;
 class cmOrderDirectories;
@@ -75,7 +74,6 @@ private:
   // Context information.
   cmTarget const* Target;
   cmMakefile* Makefile;
-  cmLocalGenerator* LocalGenerator;
   cmGlobalGenerator* GlobalGenerator;
   cmake* CMakeInstance;
 

+ 3 - 3
Source/cmCoreTryCompile.cxx

@@ -11,7 +11,7 @@
 ============================================================================*/
 #include "cmCoreTryCompile.h"
 #include "cmake.h"
-#include "cmLocalGenerator.h"
+#include "cmOutputConverter.h"
 #include "cmGlobalGenerator.h"
 #include "cmAlgorithms.h"
 #include "cmExportTryCompileFileGenerator.h"
@@ -322,7 +322,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv)
       std::string langFlags = "CMAKE_" + *li + "_FLAGS";
       const char* flags = this->Makefile->GetDefinition(langFlags);
       fprintf(fout, "set(CMAKE_%s_FLAGS %s)\n", li->c_str(),
-              cmLocalGenerator::EscapeForCMake(flags?flags:"").c_str());
+              cmOutputConverter::EscapeForCMake(flags?flags:"").c_str());
       fprintf(fout, "set(CMAKE_%s_FLAGS \"${CMAKE_%s_FLAGS}"
               " ${COMPILE_DEFINITIONS}\")\n", li->c_str(), li->c_str());
       }
@@ -355,7 +355,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv)
         const char* exeLinkFlags =
           this->Makefile->GetDefinition("CMAKE_EXE_LINKER_FLAGS");
         fprintf(fout, "set(CMAKE_EXE_LINKER_FLAGS %s)\n",
-                cmLocalGenerator::EscapeForCMake(
+                cmOutputConverter::EscapeForCMake(
                     exeLinkFlags ? exeLinkFlags : "").c_str());
         } break;
       }

+ 4 - 3
Source/cmCustomCommandGenerator.cxx

@@ -13,13 +13,13 @@
 
 #include "cmMakefile.h"
 #include "cmCustomCommand.h"
-#include "cmLocalGenerator.h"
+#include "cmOutputConverter.h"
 #include "cmGeneratorExpression.h"
 
 //----------------------------------------------------------------------------
 cmCustomCommandGenerator::cmCustomCommandGenerator(
   cmCustomCommand const& cc, const std::string& config, cmMakefile* mf):
-  CC(cc), Config(config), Makefile(mf), LG(mf->GetLocalGenerator()),
+  CC(cc), Config(config), Makefile(mf),
   OldStyle(cc.GetEscapeOldStyle()), MakeVars(cc.GetEscapeAllowMakeVars()),
   GE(new cmGeneratorExpression(&cc.GetBacktrace())), DependsDone(false)
 {
@@ -96,7 +96,8 @@ cmCustomCommandGenerator
       }
     else
       {
-      cmd += this->LG->EscapeForShell(arg, this->MakeVars);
+      cmOutputConverter converter(this->Makefile->GetStateSnapshot());
+      cmd += converter.EscapeForShell(arg, this->MakeVars);
       }
     }
 }

+ 0 - 2
Source/cmCustomCommandGenerator.h

@@ -16,7 +16,6 @@
 
 class cmCustomCommand;
 class cmMakefile;
-class cmLocalGenerator;
 class cmGeneratorExpression;
 
 class cmCustomCommandGenerator
@@ -24,7 +23,6 @@ class cmCustomCommandGenerator
   cmCustomCommand const& CC;
   std::string Config;
   cmMakefile* Makefile;
-  cmLocalGenerator* LG;
   bool OldStyle;
   bool MakeVars;
   cmGeneratorExpression* GE;

+ 1 - 1
Source/cmIfCommand.cxx

@@ -27,7 +27,7 @@ static std::string cmIfCommandError(
       i != args.end(); ++i)
     {
     err += " ";
-    err += cmLocalGenerator::EscapeForCMake(i->GetValue());
+    err += cmOutputConverter::EscapeForCMake(i->GetValue());
     }
   err += "\n";
   return err;

+ 4 - 4
Source/cmListFileCache.cxx

@@ -412,9 +412,9 @@ void cmListFileBacktrace::PrintTitle(std::ostream& out)
     return;
     }
 
+  cmOutputConverter converter(this->Snapshot);
   cmListFileContext lfc = this->front();
-  lfc.FilePath = this->LocalGenerator->Convert(lfc.FilePath,
-                                               cmLocalGenerator::HOME);
+  lfc.FilePath = converter.Convert(lfc.FilePath, cmOutputConverter::HOME);
   out << (lfc.Line ? " at " : " in ") << lfc;
 }
 
@@ -425,13 +425,13 @@ void cmListFileBacktrace::PrintCallStack(std::ostream& out)
     return;
     }
 
+  cmOutputConverter converter(this->Snapshot);
   const_iterator i = this->begin() + 1;
   out << "Call Stack (most recent call first):\n";
   while(i != this->end())
     {
     cmListFileContext lfc = *i;
-    lfc.FilePath = this->LocalGenerator->Convert(lfc.FilePath,
-                                                 cmLocalGenerator::HOME);
+    lfc.FilePath = converter.Convert(lfc.FilePath, cmOutputConverter::HOME);
     out << "  " << lfc << "\n";
     ++i;
     }

+ 4 - 4
Source/cmListFileCache.h

@@ -14,7 +14,7 @@
 
 #include "cmStandardIncludes.h"
 
-class cmLocalGenerator;
+#include "cmState.h"
 
 /** \class cmListFileCache
  * \brief A class to cache list file contents.
@@ -74,8 +74,8 @@ struct cmListFileFunction: public cmListFileContext
 class cmListFileBacktrace: private std::vector<cmListFileContext>
 {
   public:
-    cmListFileBacktrace(cmLocalGenerator* localGen = 0)
-      : LocalGenerator(localGen)
+    cmListFileBacktrace(cmState::Snapshot snapshot = cmState::Snapshot())
+      : Snapshot(snapshot)
     {
     }
 
@@ -84,7 +84,7 @@ class cmListFileBacktrace: private std::vector<cmListFileContext>
     void PrintTitle(std::ostream& out);
     void PrintCallStack(std::ostream& out);
   private:
-    cmLocalGenerator* LocalGenerator;
+    cmState::Snapshot Snapshot;
 };
 
 struct cmListFile

+ 1 - 422
Source/cmLocalGenerator.cxx

@@ -46,7 +46,7 @@
 cmLocalGenerator::cmLocalGenerator(cmGlobalGenerator* gg,
                                    cmLocalGenerator* parent,
                                    cmState::Snapshot snapshot)
-  : StateSnapshot(snapshot)
+  : cmOutputConverter(snapshot), StateSnapshot(snapshot)
 {
   assert(snapshot.IsValid());
   this->GlobalGenerator = gg;
@@ -58,7 +58,6 @@ cmLocalGenerator::cmLocalGenerator(cmGlobalGenerator* gg,
 
   this->Makefile = new cmMakefile(this);
 
-  this->LinkScriptShell = false;
   this->EmitUniversalBinaryFlags = true;
   this->BackwardsCompatibility = 0;
   this->BackwardsCompatibilityFinal = false;
@@ -1095,58 +1094,6 @@ void cmLocalGenerator::InsertRuleLauncher(std::string& s, cmTarget* target,
     }
 }
 
-//----------------------------------------------------------------------------
-std::string
-cmLocalGenerator::ConvertToOutputForExistingCommon(const std::string& remote,
-                                                   std::string const& result,
-                                                   OutputFormat format)
-{
-  // If this is a windows shell, the result has a space, and the path
-  // already exists, we can use a short-path to reference it without a
-  // space.
-  if(this->GetState()->UseWindowsShell() && result.find(' ') != result.npos &&
-     cmSystemTools::FileExists(remote.c_str()))
-    {
-    std::string tmp;
-    if(cmSystemTools::GetShortPath(remote, tmp))
-      {
-      return this->ConvertToOutputFormat(tmp, format);
-      }
-    }
-
-  // Otherwise, leave it unchanged.
-  return result;
-}
-
-//----------------------------------------------------------------------------
-std::string
-cmLocalGenerator::ConvertToOutputForExisting(const std::string& remote,
-                                             RelativeRoot local,
-                                             OutputFormat format)
-{
-  static_cast<void>(local);
-
-  // Perform standard conversion.
-  std::string result = this->ConvertToOutputFormat(remote, format);
-
-  // Consider short-path.
-  return this->ConvertToOutputForExistingCommon(remote, result, format);
-}
-
-//----------------------------------------------------------------------------
-std::string
-cmLocalGenerator::ConvertToOutputForExisting(RelativeRoot remote,
-                                             const std::string& local,
-                                             OutputFormat format)
-{
-  // Perform standard conversion.
-  std::string result = this->Convert(remote, local, format, true);
-
-  // Consider short-path.
-  const char* remotePath = this->GetRelativeRootPath(remote);
-  return this->ConvertToOutputForExistingCommon(remotePath, result, format);
-}
-
 //----------------------------------------------------------------------------
 std::string
 cmLocalGenerator::ConvertToIncludeReference(std::string const& path,
@@ -2603,230 +2550,6 @@ cmLocalGenerator::ConstructComment(cmCustomCommandGenerator const& ccg,
   return default_comment;
 }
 
-//----------------------------------------------------------------------------
-const char* cmLocalGenerator::GetRelativeRootPath(RelativeRoot relroot)
-{
-  switch (relroot)
-    {
-    case HOME:         return this->GetState()->GetSourceDirectory();
-    case START:        return this->StateSnapshot.GetCurrentSourceDirectory();
-    case HOME_OUTPUT:  return this->GetState()->GetBinaryDirectory();
-    case START_OUTPUT: return this->StateSnapshot.GetCurrentBinaryDirectory();
-    default: break;
-    }
-  return 0;
-}
-
-//----------------------------------------------------------------------------
-std::string cmLocalGenerator::Convert(const std::string& source,
-                                      RelativeRoot relative,
-                                      OutputFormat output)
-{
-  // Convert the path to a relative path.
-  std::string result = source;
-
-  switch (relative)
-    {
-    case HOME:
-      //result = cmSystemTools::CollapseFullPath(result.c_str());
-      result = this->ConvertToRelativePath(
-          this->GetState()->GetSourceDirectoryComponents(), result);
-      break;
-    case START:
-      //result = cmSystemTools::CollapseFullPath(result.c_str());
-      result = this->ConvertToRelativePath(
-          this->StateSnapshot.GetCurrentSourceDirectoryComponents(), result);
-      break;
-    case HOME_OUTPUT:
-      //result = cmSystemTools::CollapseFullPath(result.c_str());
-      result = this->ConvertToRelativePath(
-          this->GetState()->GetBinaryDirectoryComponents(), result);
-      break;
-    case START_OUTPUT:
-      //result = cmSystemTools::CollapseFullPath(result.c_str());
-      result = this->ConvertToRelativePath(
-          this->StateSnapshot.GetCurrentBinaryDirectoryComponents(), result);
-      break;
-    case FULL:
-      result = cmSystemTools::CollapseFullPath(result);
-      break;
-    case NONE:
-      break;
-
-    }
-  return this->ConvertToOutputFormat(result, output);
-}
-
-//----------------------------------------------------------------------------
-std::string cmLocalGenerator::ConvertToOutputFormat(const std::string& source,
-                                                    OutputFormat output)
-{
-  std::string result = source;
-  // Convert it to an output path.
-  if (output == MAKERULE)
-    {
-    result = cmSystemTools::ConvertToOutputPath(result.c_str());
-    }
-  else if(output == SHELL || output == WATCOMQUOTE)
-    {
-        // For the MSYS shell convert drive letters to posix paths, so
-    // that c:/some/path becomes /c/some/path.  This is needed to
-    // avoid problems with the shell path translation.
-    if(this->GetState()->UseMSYSShell() && !this->LinkScriptShell)
-      {
-      if(result.size() > 2 && result[1] == ':')
-        {
-        result[1] = result[0];
-        result[0] = '/';
-        }
-      }
-    if(this->GetState()->UseWindowsShell())
-      {
-      std::replace(result.begin(), result.end(), '/', '\\');
-      }
-    result = this->EscapeForShell(result, true, false, output == WATCOMQUOTE);
-    }
-  else if(output == RESPONSE)
-    {
-    result = this->EscapeForShell(result, false, false, false);
-    }
-  return result;
-}
-
-//----------------------------------------------------------------------------
-std::string cmLocalGenerator::Convert(RelativeRoot remote,
-                                      const std::string& local,
-                                      OutputFormat output, bool optional)
-{
-  const char* remotePath = this->GetRelativeRootPath(remote);
-
-  // The relative root must have a path (i.e. not FULL or NONE)
-  assert(remotePath != 0);
-
-  if(!local.empty() && !optional)
-    {
-    std::vector<std::string> components;
-    cmSystemTools::SplitPath(local, components);
-    std::string result = this->ConvertToRelativePath(components, remotePath);
-    return this->ConvertToOutputFormat(result, output);
-    }
-  else
-    {
-    return this->ConvertToOutputFormat(remotePath, output);
-    }
-}
-
-//----------------------------------------------------------------------------
-static bool cmLocalGeneratorNotAbove(const char* a, const char* b)
-{
-  return (cmSystemTools::ComparePath(a, b) ||
-          cmSystemTools::IsSubDirectory(a, b));
-}
-
-//----------------------------------------------------------------------------
-std::string
-cmLocalGenerator::ConvertToRelativePath(const std::vector<std::string>& local,
-                                        const std::string& in_remote,
-                                        bool force)
-{
-  // The path should never be quoted.
-  assert(in_remote[0] != '\"');
-
-  // The local path should never have a trailing slash.
-  assert(!local.empty() && !(local[local.size()-1] == ""));
-
-  // If the path is already relative then just return the path.
-  if(!cmSystemTools::FileIsFullPath(in_remote.c_str()))
-    {
-    return in_remote;
-    }
-
-  if(!force)
-    {
-    // Skip conversion if the path and local are not both in the source
-    // or both in the binary tree.
-    std::string local_path = cmSystemTools::JoinPath(local);
-    if(!((cmLocalGeneratorNotAbove(local_path.c_str(),
-              this->StateSnapshot.GetRelativePathTopBinary()) &&
-          cmLocalGeneratorNotAbove(in_remote.c_str(),
-              this->StateSnapshot.GetRelativePathTopBinary())) ||
-         (cmLocalGeneratorNotAbove(local_path.c_str(),
-              this->StateSnapshot.GetRelativePathTopSource()) &&
-          cmLocalGeneratorNotAbove(in_remote.c_str(),
-              this->StateSnapshot.GetRelativePathTopSource()))))
-      {
-      return in_remote;
-      }
-    }
-
-  // Identify the longest shared path component between the remote
-  // path and the local path.
-  std::vector<std::string> remote;
-  cmSystemTools::SplitPath(in_remote, remote);
-  unsigned int common=0;
-  while(common < remote.size() &&
-        common < local.size() &&
-        cmSystemTools::ComparePath(remote[common],
-                                   local[common]))
-    {
-    ++common;
-    }
-
-  // If no part of the path is in common then return the full path.
-  if(common == 0)
-    {
-    return in_remote;
-    }
-
-  // If the entire path is in common then just return a ".".
-  if(common == remote.size() &&
-     common == local.size())
-    {
-    return ".";
-    }
-
-  // If the entire path is in common except for a trailing slash then
-  // just return a "./".
-  if(common+1 == remote.size() &&
-     remote[common].empty() &&
-     common == local.size())
-    {
-    return "./";
-    }
-
-  // Construct the relative path.
-  std::string relative;
-
-  // First add enough ../ to get up to the level of the shared portion
-  // of the path.  Leave off the trailing slash.  Note that the last
-  // component of local will never be empty because local should never
-  // have a trailing slash.
-  for(unsigned int i=common; i < local.size(); ++i)
-    {
-    relative += "..";
-    if(i < local.size()-1)
-      {
-      relative += "/";
-      }
-    }
-
-  // Now add the portion of the destination path that is not included
-  // in the shared portion of the path.  Add a slash the first time
-  // only if there was already something in the path.  If there was a
-  // trailing slash in the input then the last iteration of the loop
-  // will add a slash followed by an empty string which will preserve
-  // the trailing slash in the output.
-
-  if(!relative.empty() && !remote.empty())
-    {
-    relative += "/";
-    }
-  relative += cmJoin(cmRange(remote).advance(common), "/");
-
-  // Finally return the path.
-  return relative;
-}
-
 //----------------------------------------------------------------------------
 class cmInstallTargetGeneratorLocal: public cmInstallTargetGenerator
 {
@@ -3219,150 +2942,6 @@ cmLocalGenerator
   return source.GetLanguage();
 }
 
-//----------------------------------------------------------------------------
-static bool cmLocalGeneratorIsShellOperator(const std::string& str)
-{
-  static std::set<std::string> shellOperators;
-  if(shellOperators.empty())
-    {
-    shellOperators.insert("<");
-    shellOperators.insert(">");
-    shellOperators.insert("<<");
-    shellOperators.insert(">>");
-    shellOperators.insert("|");
-    shellOperators.insert("||");
-    shellOperators.insert("&&");
-    shellOperators.insert("&>");
-    shellOperators.insert("1>");
-    shellOperators.insert("2>");
-    shellOperators.insert("2>&1");
-    shellOperators.insert("1>&2");
-    }
-  return shellOperators.count(str) > 0;
-}
-
-//----------------------------------------------------------------------------
-std::string cmLocalGenerator::EscapeForShell(const std::string& str,
-                                             bool makeVars,
-                                             bool forEcho,
-                                             bool useWatcomQuote)
-{
-  // Do not escape shell operators.
-  if(cmLocalGeneratorIsShellOperator(str))
-    {
-    return str;
-    }
-
-  // Compute the flags for the target shell environment.
-  int flags = 0;
-  if(this->GetState()->UseWindowsVSIDE())
-    {
-    flags |= cmsysSystem_Shell_Flag_VSIDE;
-    }
-  else if(!this->LinkScriptShell)
-    {
-    flags |= cmsysSystem_Shell_Flag_Make;
-    }
-  if(makeVars)
-    {
-    flags |= cmsysSystem_Shell_Flag_AllowMakeVariables;
-    }
-  if(forEcho)
-    {
-    flags |= cmsysSystem_Shell_Flag_EchoWindows;
-    }
-  if(useWatcomQuote)
-    {
-    flags |= cmsysSystem_Shell_Flag_WatcomQuote;
-    }
-  if(this->GetState()->UseWatcomWMake())
-    {
-    flags |= cmsysSystem_Shell_Flag_WatcomWMake;
-    }
-  if(this->GetState()->UseMinGWMake())
-    {
-    flags |= cmsysSystem_Shell_Flag_MinGWMake;
-    }
-  if(this->GetState()->UseNMake())
-    {
-    flags |= cmsysSystem_Shell_Flag_NMake;
-    }
-
-  // Compute the buffer size needed.
-  int size = (this->GetState()->UseWindowsShell() ?
-              cmsysSystem_Shell_GetArgumentSizeForWindows(str.c_str(), flags) :
-              cmsysSystem_Shell_GetArgumentSizeForUnix(str.c_str(), flags));
-
-  // Compute the shell argument itself.
-  std::vector<char> arg(size);
-  if(this->GetState()->UseWindowsShell())
-    {
-    cmsysSystem_Shell_GetArgumentForWindows(str.c_str(), &arg[0], flags);
-    }
-  else
-    {
-    cmsysSystem_Shell_GetArgumentForUnix(str.c_str(), &arg[0], flags);
-    }
-  return std::string(&arg[0]);
-}
-
-//----------------------------------------------------------------------------
-std::string cmLocalGenerator::EscapeForCMake(const std::string& str)
-{
-  // Always double-quote the argument to take care of most escapes.
-  std::string result = "\"";
-  for(const char* c = str.c_str(); *c; ++c)
-    {
-    if(*c == '"')
-      {
-      // Escape the double quote to avoid ending the argument.
-      result += "\\\"";
-      }
-    else if(*c == '$')
-      {
-      // Escape the dollar to avoid expanding variables.
-      result += "\\$";
-      }
-    else if(*c == '\\')
-      {
-      // Escape the backslash to avoid other escapes.
-      result += "\\\\";
-      }
-    else
-      {
-      // Other characters will be parsed correctly.
-      result += *c;
-      }
-    }
-  result += "\"";
-  return result;
-}
-
-//----------------------------------------------------------------------------
-cmLocalGenerator::FortranFormat
-cmLocalGenerator::GetFortranFormat(const char* value)
-{
-  FortranFormat format = FortranFormatNone;
-  if(value && *value)
-    {
-    std::vector<std::string> fmt;
-    cmSystemTools::ExpandListArgument(value, fmt);
-    for(std::vector<std::string>::iterator fi = fmt.begin();
-        fi != fmt.end(); ++fi)
-      {
-      if(*fi == "FIXED")
-        {
-        format = FortranFormatFixed;
-        }
-      if(*fi == "FREE")
-        {
-        format = FortranFormatFree;
-        }
-      }
-    }
-  return format;
-}
-
 //----------------------------------------------------------------------------
 std::string
 cmLocalGenerator::GetTargetDirectory(cmTarget const&) const

+ 2 - 80
Source/cmLocalGenerator.h

@@ -14,6 +14,7 @@
 
 #include "cmStandardIncludes.h"
 #include "cmState.h"
+#include "cmOutputConverter.h"
 
 class cmMakefile;
 class cmGlobalGenerator;
@@ -31,7 +32,7 @@ class cmCustomCommandGenerator;
  * platforms. This class should never be constructed directly. A
  * GlobalGenerator will create it and invoke the appropriate commands on it.
  */
-class cmLocalGenerator
+class cmLocalGenerator : public cmOutputConverter
 {
 public:
   cmLocalGenerator(cmGlobalGenerator* gg, cmLocalGenerator* parent,
@@ -90,35 +91,6 @@ public:
   cmState* GetState() const;
   cmState::Snapshot GetStateSnapshot() const;
 
-  /**
-   * Convert something to something else. This is a centralized conversion
-   * routine used by the generators to handle relative paths and the like.
-   * The flags determine what is actually done.
-   *
-   * relative: treat the argument as a directory and convert it to make it
-   * relative or full or unchanged. If relative (HOME, START etc) then that
-   * specifies what it should be relative to.
-   *
-   * output: make the result suitable for output to a...
-   *
-   * optional: should any relative path operation be controlled by the rel
-   * path setting
-   */
-  enum RelativeRoot { NONE, FULL, HOME, START, HOME_OUTPUT, START_OUTPUT };
-  enum OutputFormat { UNCHANGED, MAKERULE, SHELL, WATCOMQUOTE, RESPONSE };
-  std::string ConvertToOutputFormat(const std::string& source,
-                                    OutputFormat output);
-  std::string Convert(const std::string& remote, RelativeRoot local,
-                      OutputFormat output = UNCHANGED);
-  std::string Convert(RelativeRoot remote, const std::string& local,
-                      OutputFormat output = UNCHANGED,
-                      bool optional = false);
-
-  /**
-    * Get path for the specified relative root.
-    */
-  const char* GetRelativeRootPath(RelativeRoot relroot);
-
   ///! set/get the parent generator
   cmLocalGenerator* GetParent() const {return this->Parent;}
 
@@ -194,17 +166,6 @@ public:
   bool GetRealDependency(const std::string& name, const std::string& config,
                          std::string& dep);
 
-  ///! for existing files convert to output path and short path if spaces
-  std::string ConvertToOutputForExisting(const std::string& remote,
-                                         RelativeRoot local = START_OUTPUT,
-                                         OutputFormat format = SHELL);
-
-  /** For existing path identified by RelativeRoot convert to output
-      path and short path if spaces.  */
-  std::string ConvertToOutputForExisting(RelativeRoot remote,
-                                         const std::string& local = "",
-                                         OutputFormat format = SHELL);
-
   virtual std::string ConvertToIncludeReference(std::string const& path,
                                                 OutputFormat format = SHELL,
                                                 bool forceFullPaths = false);
@@ -276,40 +237,6 @@ public:
     const char* FilterPrefix;
   };
 
-  /** Set whether to treat conversions to SHELL as a link script shell.  */
-  void SetLinkScriptShell(bool b) { this->LinkScriptShell = b; }
-
-  /** Escape the given string to be used as a command line argument in
-      the native build system shell.  Optionally allow the build
-      system to replace make variable references.  Optionally adjust
-      escapes for the special case of passing to the native echo
-      command.  */
-  std::string EscapeForShell(const std::string& str, bool makeVars = false,
-                             bool forEcho = false,
-                             bool useWatcomQuote = false);
-
-  /** Escape the given string as an argument in a CMake script.  */
-  static std::string EscapeForCMake(const std::string& str);
-
-  enum FortranFormat
-    {
-    FortranFormatNone,
-    FortranFormatFixed,
-    FortranFormatFree
-    };
-  FortranFormat GetFortranFormat(const char* value);
-
-  /**
-   * Convert the given remote path to a relative path with respect to
-   * the given local path.  The local path must be given in component
-   * form (see SystemTools::SplitPath) without a trailing slash.  The
-   * remote path must use forward slashes and not already be escaped
-   * or quoted.
-   */
-  std::string ConvertToRelativePath(const std::vector<std::string>& local,
-                                    const std::string& remote,
-                                    bool force=false);
-
   /**
    * Get the relative path from the generator output directory to a
    * per-target support directory.
@@ -442,7 +369,6 @@ protected:
 
   std::set<cmTarget const*> WarnCMP0063;
 
-  bool LinkScriptShell;
   bool EmitUniversalBinaryFlags;
 
   // Hack for ExpandRuleVariable until object-oriented version is
@@ -452,10 +378,6 @@ protected:
   cmIML_INT_uint64_t BackwardsCompatibility;
   bool BackwardsCompatibilityFinal;
 private:
-  std::string ConvertToOutputForExistingCommon(const std::string& remote,
-                                               std::string const& result,
-                                               OutputFormat format);
-
   void AddSharedFlags(std::string& flags, const std::string& lang,
                       bool shared);
   bool GetShouldUseOldFlags(bool shared, const std::string &lang) const;

+ 3 - 3
Source/cmLocalUnixMakefileGenerator3.cxx

@@ -1254,7 +1254,7 @@ cmLocalUnixMakefileGenerator3
         f != files.end(); ++f)
       {
       std::string fc = this->Convert(*f,START_OUTPUT,UNCHANGED);
-      fout << "  " << cmLocalGenerator::EscapeForCMake(fc) << "\n";
+      fout << "  " << cmOutputConverter::EscapeForCMake(fc) << "\n";
       }
     fout << ")\n";
     }
@@ -2052,7 +2052,7 @@ void cmLocalUnixMakefileGenerator3
           di != defines.end(); ++di)
         {
         cmakefileStream
-          << "  " << cmLocalGenerator::EscapeForCMake(*di) << "\n";
+          << "  " << cmOutputConverter::EscapeForCMake(*di) << "\n";
         }
       cmakefileStream
         << "  )\n";
@@ -2106,7 +2106,7 @@ void cmLocalUnixMakefileGenerator3
         tri != transformRules.end(); ++tri)
       {
       cmakefileStream << "  "
-          << cmLocalGenerator::EscapeForCMake(*tri) << "\n";
+          << cmOutputConverter::EscapeForCMake(*tri) << "\n";
       }
     cmakefileStream
       << "  )\n";

+ 7 - 2
Source/cmMakefile.cxx

@@ -277,7 +277,7 @@ void cmMakefile::IssueMessage(cmake::MessageType t,
 //----------------------------------------------------------------------------
 cmListFileBacktrace cmMakefile::GetBacktrace() const
 {
-  cmListFileBacktrace backtrace(this->GetLocalGenerator());
+  cmListFileBacktrace backtrace(this->StateSnapshot);
   for(CallStackType::const_reverse_iterator i = this->CallStack.rbegin();
       i != this->CallStack.rend(); ++i)
     {
@@ -290,7 +290,7 @@ cmListFileBacktrace cmMakefile::GetBacktrace() const
 cmListFileBacktrace
 cmMakefile::GetBacktrace(cmListFileContext const& lfc) const
 {
-  cmListFileBacktrace backtrace(this->GetLocalGenerator());
+  cmListFileBacktrace backtrace(this->StateSnapshot);
   backtrace.Append(lfc);
   for(CallStackType::const_reverse_iterator i = this->CallStack.rbegin();
       i != this->CallStack.rend(); ++i)
@@ -4657,6 +4657,11 @@ void cmMakefile::StoreMatches(cmsys::RegularExpression& re)
   this->MarkVariableAsUsed(nMatchesVariable);
 }
 
+cmState::Snapshot cmMakefile::GetStateSnapshot() const
+{
+  return this->StateSnapshot;
+}
+
 //----------------------------------------------------------------------------
 cmPolicies::PolicyStatus
 cmMakefile::GetPolicyStatus(cmPolicies::PolicyID id) const

+ 2 - 0
Source/cmMakefile.h

@@ -819,6 +819,8 @@ public:
   void ClearMatches();
   void StoreMatches(cmsys::RegularExpression& re);
 
+  cmState::Snapshot GetStateSnapshot() const;
+
 protected:
   // add link libraries and directories to the target
   void AddGlobalLinkInformation(const std::string& name, cmTarget& target);

+ 2 - 2
Source/cmMakefileTargetGenerator.cxx

@@ -1126,8 +1126,8 @@ void cmMakefileTargetGenerator::WriteTargetDependRules()
         pi != this->MultipleOutputPairs.end(); ++pi)
       {
       *this->InfoFileStream
-        << "  " << cmLocalGenerator::EscapeForCMake(pi->first)
-        << " "  << cmLocalGenerator::EscapeForCMake(pi->second)
+        << "  " << cmOutputConverter::EscapeForCMake(pi->first)
+        << " "  << cmOutputConverter::EscapeForCMake(pi->second)
         << "\n";
       }
     *this->InfoFileStream << "  )\n\n";

+ 447 - 0
Source/cmOutputConverter.cxx

@@ -0,0 +1,447 @@
+/*============================================================================
+  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 "cmOutputConverter.h"
+
+#include "cmAlgorithms.h"
+#include "cmake.h"
+
+#include <cmsys/System.h>
+
+#include <assert.h>
+
+cmOutputConverter::cmOutputConverter(cmState::Snapshot snapshot)
+  : StateSnapshot(snapshot), LinkScriptShell(false)
+{
+}
+
+//----------------------------------------------------------------------------
+std::string
+cmOutputConverter::ConvertToOutputForExistingCommon(const std::string& remote,
+                                                    std::string const& result,
+                                                    OutputFormat format)
+{
+  // If this is a windows shell, the result has a space, and the path
+  // already exists, we can use a short-path to reference it without a
+  // space.
+  if(this->GetState()->UseWindowsShell() && result.find(' ') != result.npos &&
+     cmSystemTools::FileExists(remote.c_str()))
+    {
+    std::string tmp;
+    if(cmSystemTools::GetShortPath(remote, tmp))
+      {
+      return this->ConvertToOutputFormat(tmp, format);
+      }
+    }
+
+  // Otherwise, leave it unchanged.
+  return result;
+}
+
+//----------------------------------------------------------------------------
+std::string
+cmOutputConverter::ConvertToOutputForExisting(const std::string& remote,
+                                              RelativeRoot local,
+                                              OutputFormat format)
+{
+  static_cast<void>(local);
+
+  // Perform standard conversion.
+  std::string result = this->ConvertToOutputFormat(remote, format);
+
+  // Consider short-path.
+  return this->ConvertToOutputForExistingCommon(remote, result, format);
+}
+
+//----------------------------------------------------------------------------
+std::string
+cmOutputConverter::ConvertToOutputForExisting(RelativeRoot remote,
+                                              const std::string& local,
+                                              OutputFormat format)
+{
+  // Perform standard conversion.
+  std::string result = this->Convert(remote, local, format, true);
+
+  // Consider short-path.
+  const char* remotePath = this->GetRelativeRootPath(remote);
+  return this->ConvertToOutputForExistingCommon(remotePath, result, format);
+}
+
+//----------------------------------------------------------------------------
+const char* cmOutputConverter::GetRelativeRootPath(RelativeRoot relroot)
+{
+  switch (relroot)
+    {
+    case HOME:         return this->GetState()->GetSourceDirectory();
+    case START:        return this->StateSnapshot.GetCurrentSourceDirectory();
+    case HOME_OUTPUT:  return this->GetState()->GetBinaryDirectory();
+    case START_OUTPUT: return this->StateSnapshot.GetCurrentBinaryDirectory();
+    default: break;
+    }
+  return 0;
+}
+
+std::string cmOutputConverter::Convert(const std::string& source,
+                                       RelativeRoot relative,
+                                       OutputFormat output)
+{
+  // Convert the path to a relative path.
+  std::string result = source;
+
+  switch (relative)
+    {
+  case HOME:
+    result = this->ConvertToRelativePath(
+          this->GetState()->GetSourceDirectoryComponents(), result);
+    break;
+  case START:
+    result = this->ConvertToRelativePath(
+          this->StateSnapshot.GetCurrentSourceDirectoryComponents(), result);
+    break;
+  case HOME_OUTPUT:
+    result = this->ConvertToRelativePath(
+          this->GetState()->GetBinaryDirectoryComponents(), result);
+    break;
+  case START_OUTPUT:
+    result = this->ConvertToRelativePath(
+          this->StateSnapshot.GetCurrentBinaryDirectoryComponents(), result);
+    break;
+  case FULL:
+    result = cmSystemTools::CollapseFullPath(result);
+    break;
+  case NONE:
+    break;
+    }
+  return this->ConvertToOutputFormat(result, output);
+}
+
+//----------------------------------------------------------------------------
+std::string cmOutputConverter::ConvertToOutputFormat(const std::string& source,
+                                                     OutputFormat output)
+{
+  std::string result = source;
+  // Convert it to an output path.
+  if (output == MAKERULE)
+    {
+    result = cmSystemTools::ConvertToOutputPath(result.c_str());
+    }
+  else if(output == SHELL || output == WATCOMQUOTE)
+    {
+        // For the MSYS shell convert drive letters to posix paths, so
+    // that c:/some/path becomes /c/some/path.  This is needed to
+    // avoid problems with the shell path translation.
+    if(this->GetState()->UseMSYSShell() && !this->LinkScriptShell)
+      {
+      if(result.size() > 2 && result[1] == ':')
+        {
+        result[1] = result[0];
+        result[0] = '/';
+        }
+      }
+    if(this->GetState()->UseWindowsShell())
+      {
+      std::replace(result.begin(), result.end(), '/', '\\');
+      }
+    result = this->EscapeForShell(result, true, false, output == WATCOMQUOTE);
+    }
+  else if(output == RESPONSE)
+    {
+    result = this->EscapeForShell(result, false, false, false);
+    }
+  return result;
+}
+
+//----------------------------------------------------------------------------
+std::string cmOutputConverter::Convert(RelativeRoot remote,
+                                      const std::string& local,
+                                      OutputFormat output,
+                                      bool optional)
+{
+  const char* remotePath = this->GetRelativeRootPath(remote);
+
+  // The relative root must have a path (i.e. not FULL or NONE)
+  assert(remotePath != 0);
+
+  if(!local.empty() && !optional)
+    {
+    std::vector<std::string> components;
+    cmSystemTools::SplitPath(local, components);
+    std::string result = this->ConvertToRelativePath(components, remotePath);
+    return this->ConvertToOutputFormat(result, output);
+    }
+
+  return this->ConvertToOutputFormat(remotePath, output);
+}
+
+//----------------------------------------------------------------------------
+static bool cmOutputConverterNotAbove(const char* a, const char* b)
+{
+  return (cmSystemTools::ComparePath(a, b) ||
+          cmSystemTools::IsSubDirectory(a, b));
+}
+
+//----------------------------------------------------------------------------
+std::string
+cmOutputConverter::ConvertToRelativePath(const std::vector<std::string>& local,
+                                        const std::string& in_remote,
+                                        bool force)
+{
+  // The path should never be quoted.
+  assert(in_remote[0] != '\"');
+
+  // The local path should never have a trailing slash.
+  assert(!local.empty() && !(local[local.size()-1] == ""));
+
+  // If the path is already relative then just return the path.
+  if(!cmSystemTools::FileIsFullPath(in_remote.c_str()))
+    {
+    return in_remote;
+    }
+
+  if(!force)
+    {
+    // Skip conversion if the path and local are not both in the source
+    // or both in the binary tree.
+    std::string local_path = cmSystemTools::JoinPath(local);
+    if(!((cmOutputConverterNotAbove(local_path.c_str(),
+              this->StateSnapshot.GetRelativePathTopBinary()) &&
+          cmOutputConverterNotAbove(in_remote.c_str(),
+              this->StateSnapshot.GetRelativePathTopBinary())) ||
+         (cmOutputConverterNotAbove(local_path.c_str(),
+              this->StateSnapshot.GetRelativePathTopSource()) &&
+          cmOutputConverterNotAbove(in_remote.c_str(),
+              this->StateSnapshot.GetRelativePathTopSource()))))
+      {
+      return in_remote;
+      }
+    }
+
+  // Identify the longest shared path component between the remote
+  // path and the local path.
+  std::vector<std::string> remote;
+  cmSystemTools::SplitPath(in_remote, remote);
+  unsigned int common=0;
+  while(common < remote.size() &&
+        common < local.size() &&
+        cmSystemTools::ComparePath(remote[common],
+                                   local[common]))
+    {
+    ++common;
+    }
+
+  // If no part of the path is in common then return the full path.
+  if(common == 0)
+    {
+    return in_remote;
+    }
+
+  // If the entire path is in common then just return a ".".
+  if(common == remote.size() &&
+     common == local.size())
+    {
+    return ".";
+    }
+
+  // If the entire path is in common except for a trailing slash then
+  // just return a "./".
+  if(common+1 == remote.size() &&
+     remote[common].empty() &&
+     common == local.size())
+    {
+    return "./";
+    }
+
+  // Construct the relative path.
+  std::string relative;
+
+  // First add enough ../ to get up to the level of the shared portion
+  // of the path.  Leave off the trailing slash.  Note that the last
+  // component of local will never be empty because local should never
+  // have a trailing slash.
+  for(unsigned int i=common; i < local.size(); ++i)
+    {
+    relative += "..";
+    if(i < local.size()-1)
+      {
+      relative += "/";
+      }
+    }
+
+  // Now add the portion of the destination path that is not included
+  // in the shared portion of the path.  Add a slash the first time
+  // only if there was already something in the path.  If there was a
+  // trailing slash in the input then the last iteration of the loop
+  // will add a slash followed by an empty string which will preserve
+  // the trailing slash in the output.
+
+  if(!relative.empty() && !remote.empty())
+    {
+    relative += "/";
+    }
+  relative += cmJoin(cmRange(remote).advance(common), "/");
+
+  // Finally return the path.
+  return relative;
+}
+
+//----------------------------------------------------------------------------
+static bool cmOutputConverterIsShellOperator(const std::string& str)
+{
+  static std::set<std::string> shellOperators;
+  if(shellOperators.empty())
+    {
+    shellOperators.insert("<");
+    shellOperators.insert(">");
+    shellOperators.insert("<<");
+    shellOperators.insert(">>");
+    shellOperators.insert("|");
+    shellOperators.insert("||");
+    shellOperators.insert("&&");
+    shellOperators.insert("&>");
+    shellOperators.insert("1>");
+    shellOperators.insert("2>");
+    shellOperators.insert("2>&1");
+    shellOperators.insert("1>&2");
+    }
+  return shellOperators.count(str) > 0;
+}
+
+//----------------------------------------------------------------------------
+std::string cmOutputConverter::EscapeForShell(const std::string& str,
+                                             bool makeVars,
+                                             bool forEcho,
+                                             bool useWatcomQuote)
+{
+  // Do not escape shell operators.
+  if(cmOutputConverterIsShellOperator(str))
+    {
+    return str;
+    }
+
+  // Compute the flags for the target shell environment.
+  int flags = 0;
+  if(this->GetState()->UseWindowsVSIDE())
+    {
+    flags |= cmsysSystem_Shell_Flag_VSIDE;
+    }
+  else if(!this->LinkScriptShell)
+    {
+    flags |= cmsysSystem_Shell_Flag_Make;
+    }
+  if(makeVars)
+    {
+    flags |= cmsysSystem_Shell_Flag_AllowMakeVariables;
+    }
+  if(forEcho)
+    {
+    flags |= cmsysSystem_Shell_Flag_EchoWindows;
+    }
+  if(useWatcomQuote)
+    {
+    flags |= cmsysSystem_Shell_Flag_WatcomQuote;
+    }
+  if(this->GetState()->UseWatcomWMake())
+    {
+    flags |= cmsysSystem_Shell_Flag_WatcomWMake;
+    }
+  if(this->GetState()->UseMinGWMake())
+    {
+    flags |= cmsysSystem_Shell_Flag_MinGWMake;
+    }
+  if(this->GetState()->UseNMake())
+    {
+    flags |= cmsysSystem_Shell_Flag_NMake;
+    }
+
+  // Compute the buffer size needed.
+  int size = (this->GetState()->UseWindowsShell() ?
+              cmsysSystem_Shell_GetArgumentSizeForWindows(str.c_str(), flags) :
+              cmsysSystem_Shell_GetArgumentSizeForUnix(str.c_str(), flags));
+
+  // Compute the shell argument itself.
+  std::vector<char> arg(size);
+  if(this->GetState()->UseWindowsShell())
+    {
+    cmsysSystem_Shell_GetArgumentForWindows(str.c_str(), &arg[0], flags);
+    }
+  else
+    {
+    cmsysSystem_Shell_GetArgumentForUnix(str.c_str(), &arg[0], flags);
+    }
+  return std::string(&arg[0]);
+}
+
+//----------------------------------------------------------------------------
+std::string cmOutputConverter::EscapeForCMake(const std::string& str)
+{
+  // Always double-quote the argument to take care of most escapes.
+  std::string result = "\"";
+  for(const char* c = str.c_str(); *c; ++c)
+    {
+    if(*c == '"')
+      {
+      // Escape the double quote to avoid ending the argument.
+      result += "\\\"";
+      }
+    else if(*c == '$')
+      {
+      // Escape the dollar to avoid expanding variables.
+      result += "\\$";
+      }
+    else if(*c == '\\')
+      {
+      // Escape the backslash to avoid other escapes.
+      result += "\\\\";
+      }
+    else
+      {
+      // Other characters will be parsed correctly.
+      result += *c;
+      }
+    }
+  result += "\"";
+  return result;
+}
+
+//----------------------------------------------------------------------------
+cmOutputConverter::FortranFormat
+cmOutputConverter::GetFortranFormat(const char* value)
+{
+  FortranFormat format = FortranFormatNone;
+  if(value && *value)
+    {
+    std::vector<std::string> fmt;
+    cmSystemTools::ExpandListArgument(value, fmt);
+    for(std::vector<std::string>::iterator fi = fmt.begin();
+        fi != fmt.end(); ++fi)
+      {
+      if(*fi == "FIXED")
+        {
+        format = FortranFormatFixed;
+        }
+      if(*fi == "FREE")
+        {
+        format = FortranFormatFree;
+        }
+      }
+    }
+  return format;
+}
+
+void cmOutputConverter::SetLinkScriptShell(bool linkScriptShell)
+{
+  this->LinkScriptShell = linkScriptShell;
+}
+
+cmState* cmOutputConverter::GetState() const
+{
+  return this->StateSnapshot.GetState();
+}

+ 106 - 0
Source/cmOutputConverter.h

@@ -0,0 +1,106 @@
+/*============================================================================
+  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.
+============================================================================*/
+#ifndef cmOutputConverter_h
+#define cmOutputConverter_h
+
+#include "cmStandardIncludes.h"
+
+#include "cmGlobalGenerator.h"
+#include "cmState.h"
+
+class cmOutputConverter
+{
+public:
+  cmOutputConverter(cmState::Snapshot snapshot);
+
+  /**
+   * Convert something to something else. This is a centralized conversion
+   * routine used by the generators to handle relative paths and the like.
+   * The flags determine what is actually done.
+   *
+   * relative: treat the argument as a directory and convert it to make it
+   * relative or full or unchanged. If relative (HOME, START etc) then that
+   * specifies what it should be relative to.
+   *
+   * output: make the result suitable for output to a...
+   *
+   * optional: should any relative path operation be controlled by the rel
+   * path setting
+   */
+  enum RelativeRoot { NONE, FULL, HOME, START, HOME_OUTPUT, START_OUTPUT };
+  enum OutputFormat { UNCHANGED, MAKERULE, SHELL, WATCOMQUOTE, RESPONSE };
+  std::string ConvertToOutputFormat(const std::string& source,
+                                    OutputFormat output);
+  std::string Convert(const std::string& remote, RelativeRoot local,
+                      OutputFormat output = UNCHANGED);
+  std::string Convert(RelativeRoot remote, const std::string& local,
+                      OutputFormat output = UNCHANGED,
+                      bool optional = false);
+
+  /**
+    * Get path for the specified relative root.
+    */
+  const char* GetRelativeRootPath(RelativeRoot relroot);
+
+  ///! for existing files convert to output path and short path if spaces
+  std::string ConvertToOutputForExisting(const std::string& remote,
+                                         RelativeRoot local = START_OUTPUT,
+                                         OutputFormat format = SHELL);
+
+  /** For existing path identified by RelativeRoot convert to output
+      path and short path if spaces.  */
+  std::string ConvertToOutputForExisting(RelativeRoot remote,
+                                         const std::string& local = "",
+                                         OutputFormat format = SHELL);
+
+  void SetLinkScriptShell(bool linkScriptShell);
+
+  std::string EscapeForShell(const std::string& str,
+                                    bool makeVars = false,
+                                    bool forEcho = false,
+                                    bool useWatcomQuote = false);
+
+  static std::string EscapeForCMake(const std::string& str);
+
+  enum FortranFormat
+    {
+    FortranFormatNone,
+    FortranFormatFixed,
+    FortranFormatFree
+    };
+  static FortranFormat GetFortranFormat(const char* value);
+
+  /**
+   * Convert the given remote path to a relative path with respect to
+   * the given local path.  The local path must be given in component
+   * form (see SystemTools::SplitPath) without a trailing slash.  The
+   * remote path must use forward slashes and not already be escaped
+   * or quoted.
+   */
+  std::string ConvertToRelativePath(const std::vector<std::string>& local,
+                                    const std::string& in_remote,
+                                    bool force = false);
+
+private:
+  cmState* GetState() const;
+
+  std::string ConvertToOutputForExistingCommon(const std::string& remote,
+                                               std::string const& result,
+                                               OutputFormat format);
+
+private:
+  cmState::Snapshot StateSnapshot;
+
+  bool LinkScriptShell;
+};
+
+#endif

+ 20 - 20
Source/cmQtAutoGenerators.cxx

@@ -550,9 +550,9 @@ void cmQtAutoGenerators::SetupAutoGenerateTarget(cmTarget const* target)
   std::string autogenTargetName = getAutogenTargetName(target);
 
   makefile->AddDefinition("_moc_target_name",
-          cmLocalGenerator::EscapeForCMake(autogenTargetName).c_str());
+          cmOutputConverter::EscapeForCMake(autogenTargetName).c_str());
   makefile->AddDefinition("_origin_target_name",
-          cmLocalGenerator::EscapeForCMake(target->GetName()).c_str());
+          cmOutputConverter::EscapeForCMake(target->GetName()).c_str());
 
   std::string targetDir = getAutogenTargetDir(target);
 
@@ -582,7 +582,7 @@ void cmQtAutoGenerators::SetupAutoGenerateTarget(cmTarget const* target)
     this->SetupSourceFiles(target);
     }
   makefile->AddDefinition("_cpp_files",
-          cmLocalGenerator::EscapeForCMake(this->Sources).c_str());
+          cmOutputConverter::EscapeForCMake(this->Sources).c_str());
   if (target->GetPropertyAsBool("AUTOMOC"))
     {
     this->SetupAutoMocTarget(target, autogenTargetName,
@@ -764,11 +764,11 @@ void cmQtAutoGenerators::SetupAutoMocTarget(cmTarget const* target,
   const char* tmp = target->GetProperty("AUTOMOC_MOC_OPTIONS");
   std::string _moc_options = (tmp!=0 ? tmp : "");
   makefile->AddDefinition("_moc_options",
-          cmLocalGenerator::EscapeForCMake(_moc_options).c_str());
+          cmOutputConverter::EscapeForCMake(_moc_options).c_str());
   makefile->AddDefinition("_skip_moc",
-          cmLocalGenerator::EscapeForCMake(this->SkipMoc).c_str());
+          cmOutputConverter::EscapeForCMake(this->SkipMoc).c_str());
   makefile->AddDefinition("_moc_headers",
-          cmLocalGenerator::EscapeForCMake(this->Headers).c_str());
+          cmOutputConverter::EscapeForCMake(this->Headers).c_str());
   bool relaxedMode = makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE");
   makefile->AddDefinition("_moc_relaxed_mode", relaxedMode ? "TRUE" : "FALSE");
 
@@ -780,9 +780,9 @@ void cmQtAutoGenerators::SetupAutoMocTarget(cmTarget const* target,
                                       _moc_incs, _moc_compile_defs);
 
   makefile->AddDefinition("_moc_incs",
-          cmLocalGenerator::EscapeForCMake(_moc_incs).c_str());
+          cmOutputConverter::EscapeForCMake(_moc_incs).c_str());
   makefile->AddDefinition("_moc_compile_defs",
-          cmLocalGenerator::EscapeForCMake(_moc_compile_defs).c_str());
+          cmOutputConverter::EscapeForCMake(_moc_compile_defs).c_str());
 
   for (std::vector<std::string>::const_iterator li = configs.begin();
        li != configs.end(); ++li)
@@ -795,7 +795,7 @@ void cmQtAutoGenerators::SetupAutoMocTarget(cmTarget const* target,
     if (config_moc_incs != _moc_incs)
       {
       configIncludes[*li] =
-                    cmLocalGenerator::EscapeForCMake(config_moc_incs);
+                    cmOutputConverter::EscapeForCMake(config_moc_incs);
       if(_moc_incs.empty())
         {
         _moc_incs = config_moc_incs;
@@ -804,7 +804,7 @@ void cmQtAutoGenerators::SetupAutoMocTarget(cmTarget const* target,
     if (config_moc_compile_defs != _moc_compile_defs)
       {
       configDefines[*li] =
-            cmLocalGenerator::EscapeForCMake(config_moc_compile_defs);
+            cmOutputConverter::EscapeForCMake(config_moc_compile_defs);
       if(_moc_compile_defs.empty())
         {
         _moc_compile_defs = config_moc_compile_defs;
@@ -906,7 +906,7 @@ void cmQtAutoGenerators::SetupAutoUicTarget(cmTarget const* target,
   skipped.insert(skipVec.begin(), skipVec.end());
 
   makefile->AddDefinition("_skip_uic",
-          cmLocalGenerator::EscapeForCMake(this->SkipUic).c_str());
+          cmOutputConverter::EscapeForCMake(this->SkipUic).c_str());
 
   std::vector<cmSourceFile*> uiFilesWithOptions
                                         = makefile->GetQtUiFilesWithOptions();
@@ -920,7 +920,7 @@ void cmQtAutoGenerators::SetupAutoUicTarget(cmTarget const* target,
 
   if (!_uic_opts.empty())
     {
-    _uic_opts = cmLocalGenerator::EscapeForCMake(_uic_opts);
+    _uic_opts = cmOutputConverter::EscapeForCMake(_uic_opts);
     makefile->AddDefinition("_uic_target_options", _uic_opts.c_str());
     }
   for (std::vector<std::string>::const_iterator li = configs.begin();
@@ -931,7 +931,7 @@ void cmQtAutoGenerators::SetupAutoUicTarget(cmTarget const* target,
     if (config_uic_opts != _uic_opts)
       {
       configUicOptions[*li] =
-                    cmLocalGenerator::EscapeForCMake(config_uic_opts);
+                    cmOutputConverter::EscapeForCMake(config_uic_opts);
       if(_uic_opts.empty())
         {
         _uic_opts = config_uic_opts;
@@ -966,9 +966,9 @@ void cmQtAutoGenerators::SetupAutoUicTarget(cmTarget const* target,
     }
 
   makefile->AddDefinition("_qt_uic_options_files",
-              cmLocalGenerator::EscapeForCMake(uiFileFiles).c_str());
+              cmOutputConverter::EscapeForCMake(uiFileFiles).c_str());
   makefile->AddDefinition("_qt_uic_options_options",
-            cmLocalGenerator::EscapeForCMake(uiFileOptions).c_str());
+            cmOutputConverter::EscapeForCMake(uiFileOptions).c_str());
 
   std::string targetName = target->GetName();
   if (strcmp(qtVersion, "5") == 0)
@@ -1141,15 +1141,15 @@ void cmQtAutoGenerators::SetupAutoRccTarget(cmTarget const* target)
       }
     }
   makefile->AddDefinition("_qt_rcc_inputs_" + target->GetName(),
-                      cmLocalGenerator::EscapeForCMake(qrcInputs).c_str());
+                      cmOutputConverter::EscapeForCMake(qrcInputs).c_str());
 
   makefile->AddDefinition("_rcc_files",
-          cmLocalGenerator::EscapeForCMake(_rcc_files).c_str());
+          cmOutputConverter::EscapeForCMake(_rcc_files).c_str());
 
   makefile->AddDefinition("_qt_rcc_options_files",
-              cmLocalGenerator::EscapeForCMake(rccFileFiles).c_str());
+              cmOutputConverter::EscapeForCMake(rccFileFiles).c_str());
   makefile->AddDefinition("_qt_rcc_options_options",
-            cmLocalGenerator::EscapeForCMake(rccFileOptions).c_str());
+            cmOutputConverter::EscapeForCMake(rccFileOptions).c_str());
 
   makefile->AddDefinition("_qt_rcc_executable",
                           this->GetRccExecutable(target).c_str());
@@ -1434,7 +1434,7 @@ cmQtAutoGenerators::WriteOldMocDefinitionsFile(
   outfile.open(filename.c_str(),
                std::ios::trunc);
   outfile << "set(AM_OLD_COMPILE_SETTINGS "
-              << cmLocalGenerator::EscapeForCMake(
+              << cmOutputConverter::EscapeForCMake(
                  this->CurrentCompileSettingsStr) << ")\n";
 
   outfile.close();

+ 5 - 0
Source/cmState.cxx

@@ -785,3 +785,8 @@ cmState::Snapshot cmState::Snapshot::GetBuildsystemDirectoryParent() const
 
   return snapshot;
 }
+
+cmState* cmState::Snapshot::GetState() const
+{
+  return this->State;
+}

+ 2 - 0
Source/cmState.h

@@ -54,6 +54,8 @@ public:
     bool IsValid() const;
     Snapshot GetBuildsystemDirectoryParent() const;
 
+    cmState* GetState() const;
+
   private:
     void ComputeRelativePathTopSource();
     void ComputeRelativePathTopBinary();

+ 3 - 3
Source/cmTarget.cxx

@@ -13,7 +13,7 @@
 #include "cmake.h"
 #include "cmMakefile.h"
 #include "cmSourceFile.h"
-#include "cmLocalGenerator.h"
+#include "cmOutputConverter.h"
 #include "cmGlobalGenerator.h"
 #include "cmComputeLinkInformation.h"
 #include "cmListFileCache.h"
@@ -1257,14 +1257,14 @@ void cmTarget::GetTllSignatureTraces(std::ostringstream &s,
                                                                 : "plain");
   s << "The uses of the " << sigString << " signature are here:\n";
   typedef std::vector<std::pair<TLLSignature, cmListFileContext> > Container;
-  cmLocalGenerator* lg = this->GetMakefile()->GetLocalGenerator();
+  cmOutputConverter converter(this->GetMakefile()->GetStateSnapshot());
   for(Container::const_iterator it = this->TLLCommands.begin();
       it != this->TLLCommands.end(); ++it)
     {
     if (it->first == sig)
       {
       cmListFileContext lfc = it->second;
-      lfc.FilePath = lg->Convert(lfc.FilePath, cmLocalGenerator::HOME);
+      lfc.FilePath = converter.Convert(lfc.FilePath, cmOutputConverter::HOME);
       s << " * " << lfc << std::endl;
       }
     }

+ 7 - 7
Source/cmTestGenerator.cxx

@@ -12,7 +12,7 @@
 #include "cmTestGenerator.h"
 
 #include "cmGeneratorExpression.h"
-#include "cmLocalGenerator.h"
+#include "cmOutputConverter.h"
 #include "cmMakefile.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
@@ -97,13 +97,13 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os,
       cmSystemTools::ExpandListArgument(emulator, emulatorWithArgs);
       std::string emulatorExe(emulatorWithArgs[0]);
       cmSystemTools::ConvertToUnixSlashes(emulatorExe);
-      os << cmLocalGenerator::EscapeForCMake(emulatorExe) << " ";
+      os << cmOutputConverter::EscapeForCMake(emulatorExe) << " ";
       for(std::vector<std::string>::const_iterator ei =
           emulatorWithArgs.begin()+1;
           ei != emulatorWithArgs.end();
           ++ei)
         {
-        os << cmLocalGenerator::EscapeForCMake(*ei) << " ";
+        os << cmOutputConverter::EscapeForCMake(*ei) << " ";
         }
       }
     }
@@ -115,11 +115,11 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os,
     }
 
   // Generate the command line with full escapes.
-  os << cmLocalGenerator::EscapeForCMake(exe);
+  os << cmOutputConverter::EscapeForCMake(exe);
   for(std::vector<std::string>::const_iterator ci = command.begin()+1;
       ci != command.end(); ++ci)
     {
-    os << " " << cmLocalGenerator::EscapeForCMake(
+    os << " " << cmOutputConverter::EscapeForCMake(
                                          ge.Parse(*ci)->Evaluate(mf, config));
     }
 
@@ -136,7 +136,7 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os,
         i != pm.end(); ++i)
       {
       os << " " << i->first
-         << " " << cmLocalGenerator::EscapeForCMake(
+         << " " << cmOutputConverter::EscapeForCMake(
            ge.Parse(i->second.GetValue())->Evaluate(mf, config));
       }
     os << ")" << std::endl;
@@ -206,7 +206,7 @@ void cmTestGenerator::GenerateOldStyle(std::ostream& fout,
         i != pm.end(); ++i)
       {
       fout << " " << i->first
-           << " " << cmLocalGenerator::EscapeForCMake(i->second.GetValue());
+           << " " << cmOutputConverter::EscapeForCMake(i->second.GetValue());
       }
     fout << ")" << std::endl;
     }

+ 1 - 0
bootstrap

@@ -299,6 +299,7 @@ CMAKE_CXX_SOURCES="\
   cmMakefileLibraryTargetGenerator \
   cmMakefileTargetGenerator \
   cmMakefileUtilityTargetGenerator \
+  cmOutputConverter \
   cmOSXBundleGenerator \
   cmNewLineStyle \
   cmBootstrapCommands1 \